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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'soc_fsl-6.20-1' of https://git.kernel.org/pub/scm/linux/kernel/git/chleroy/linux into soc/drivers

FSL SOC Changes for 6.20

Freescale Management Complex:
- Convert fsl-mc bus to bus callbacks
- Fix a use-after-free
- Drop redundant error messages
- Fix ressources release on some error path

Freescale QUICC Engine:
- Add an interrupt controller for IO Ports
- Use scoped for-each OF child loop

* tag 'soc_fsl-6.20-1' of https://git.kernel.org/pub/scm/linux/kernel/git/chleroy/linux:
bus: fsl-mc: fix an error handling in fsl_mc_device_add()
soc: fsl: qe: qe_ports_ic: Consolidate chained IRQ handler install/remove
dt-bindings: soc: fsl: qe: Add an interrupt controller for QUICC Engine Ports
soc: fsl: qe: Add an interrupt controller for QUICC Engine Ports
soc: fsl: qe: Simplify with scoped for each OF child loop
bus: fsl-mc: fix use-after-free in driver_override_show()
bus: fsl-mc: Convert to bus callbacks
bus: fsl-mc: Drop error message in probe function

Signed-off-by: Arnd Bergmann <arnd@arndb.de>

+233 -63
+51
Documentation/devicetree/bindings/interrupt-controller/fsl,qe-ports-ic.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/interrupt-controller/fsl,qe-ports-ic.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Freescale QUICC Engine I/O Ports Interrupt Controller 8 + 9 + maintainers: 10 + - Christophe Leroy (CS GROUP) <chleroy@kernel.org> 11 + 12 + properties: 13 + compatible: 14 + enum: 15 + - fsl,mpc8323-qe-ports-ic 16 + 17 + reg: 18 + maxItems: 1 19 + 20 + interrupt-controller: true 21 + 22 + '#address-cells': 23 + const: 0 24 + 25 + '#interrupt-cells': 26 + const: 1 27 + 28 + interrupts: 29 + maxItems: 1 30 + 31 + required: 32 + - compatible 33 + - reg 34 + - interrupt-controller 35 + - '#address-cells' 36 + - '#interrupt-cells' 37 + - interrupts 38 + 39 + additionalProperties: false 40 + 41 + examples: 42 + - | 43 + interrupt-controller@c00 { 44 + compatible = "fsl,mpc8323-qe-ports-ic"; 45 + reg = <0xc00 0x18>; 46 + interrupt-controller; 47 + #address-cells = <0>; 48 + #interrupt-cells = <1>; 49 + interrupts = <74 0x8>; 50 + interrupt-parent = <&ipic>; 51 + };
+38 -51
drivers/bus/fsl-mc/fsl-mc-bus.c
··· 137 137 return 0; 138 138 } 139 139 140 + static int fsl_mc_probe(struct device *dev) 141 + { 142 + struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); 143 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); 144 + 145 + if (mc_drv->probe) 146 + return mc_drv->probe(mc_dev); 147 + 148 + return 0; 149 + } 150 + 151 + static void fsl_mc_remove(struct device *dev) 152 + { 153 + struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); 154 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); 155 + 156 + if (mc_drv->remove) 157 + mc_drv->remove(mc_dev); 158 + } 159 + 160 + static void fsl_mc_shutdown(struct device *dev) 161 + { 162 + struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); 163 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); 164 + 165 + if (dev->driver && mc_drv->shutdown) 166 + mc_drv->shutdown(mc_dev); 167 + } 168 + 140 169 static int fsl_mc_dma_configure(struct device *dev) 141 170 { 142 171 const struct device_driver *drv = READ_ONCE(dev->driver); ··· 231 202 struct device_attribute *attr, char *buf) 232 203 { 233 204 struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); 205 + ssize_t len; 234 206 235 - return sysfs_emit(buf, "%s\n", mc_dev->driver_override); 207 + device_lock(dev); 208 + len = sysfs_emit(buf, "%s\n", mc_dev->driver_override); 209 + device_unlock(dev); 210 + return len; 236 211 } 237 212 static DEVICE_ATTR_RW(driver_override); 238 213 ··· 347 314 .name = "fsl-mc", 348 315 .match = fsl_mc_bus_match, 349 316 .uevent = fsl_mc_bus_uevent, 317 + .probe = fsl_mc_probe, 318 + .remove = fsl_mc_remove, 319 + .shutdown = fsl_mc_shutdown, 350 320 .dma_configure = fsl_mc_dma_configure, 351 321 .dma_cleanup = fsl_mc_dma_cleanup, 352 322 .dev_groups = fsl_mc_dev_groups, ··· 470 434 return NULL; 471 435 } 472 436 473 - static int fsl_mc_driver_probe(struct device *dev) 474 - { 475 - struct fsl_mc_driver *mc_drv; 476 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); 477 - int error; 478 - 479 - mc_drv = to_fsl_mc_driver(dev->driver); 480 - 481 - error = mc_drv->probe(mc_dev); 482 - if (error < 0) { 483 - if (error != -EPROBE_DEFER) 484 - dev_err(dev, "%s failed: %d\n", __func__, error); 485 - return error; 486 - } 487 - 488 - return 0; 489 - } 490 - 491 - static int fsl_mc_driver_remove(struct device *dev) 492 - { 493 - struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); 494 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); 495 - 496 - mc_drv->remove(mc_dev); 497 - 498 - return 0; 499 - } 500 - 501 - static void fsl_mc_driver_shutdown(struct device *dev) 502 - { 503 - struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); 504 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); 505 - 506 - mc_drv->shutdown(mc_dev); 507 - } 508 - 509 437 /* 510 438 * __fsl_mc_driver_register - registers a child device driver with the 511 439 * MC bus ··· 485 485 486 486 mc_driver->driver.owner = owner; 487 487 mc_driver->driver.bus = &fsl_mc_bus_type; 488 - 489 - if (mc_driver->probe) 490 - mc_driver->driver.probe = fsl_mc_driver_probe; 491 - 492 - if (mc_driver->remove) 493 - mc_driver->driver.remove = fsl_mc_driver_remove; 494 - 495 - if (mc_driver->shutdown) 496 - mc_driver->driver.shutdown = fsl_mc_driver_shutdown; 497 488 498 489 error = driver_register(&mc_driver->driver); 499 490 if (error < 0) { ··· 896 905 return 0; 897 906 898 907 error_cleanup_dev: 899 - kfree(mc_dev->regions); 900 - if (mc_bus) 901 - kfree(mc_bus); 902 - else 903 - kfree(mc_dev); 908 + put_device(&mc_dev->dev); 904 909 905 910 return error; 906 911 }
+1 -1
drivers/soc/fsl/qe/Makefile
··· 11 11 obj-$(CONFIG_UCC_FAST) += ucc_fast.o 12 12 obj-$(CONFIG_QE_TDM) += qe_tdm.o 13 13 obj-$(CONFIG_QE_USB) += usb.o 14 - obj-$(CONFIG_QE_GPIO) += gpio.o 14 + obj-$(CONFIG_QE_GPIO) += gpio.o qe_ports_ic.o
+141
drivers/soc/fsl/qe/qe_ports_ic.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * QUICC ENGINE I/O Ports Interrupt Controller 4 + * 5 + * Copyright (c) 2025 Christophe Leroy CS GROUP France (christophe.leroy@csgroup.eu) 6 + */ 7 + 8 + #include <linux/irq.h> 9 + #include <linux/irqdomain.h> 10 + #include <linux/platform_device.h> 11 + 12 + /* QE IC registers offset */ 13 + #define CEPIER 0x0c 14 + #define CEPIMR 0x10 15 + #define CEPICR 0x14 16 + 17 + struct qepic_data { 18 + void __iomem *reg; 19 + struct irq_domain *host; 20 + }; 21 + 22 + static void qepic_mask(struct irq_data *d) 23 + { 24 + struct qepic_data *data = irq_data_get_irq_chip_data(d); 25 + 26 + clrbits32(data->reg + CEPIMR, 1 << (31 - irqd_to_hwirq(d))); 27 + } 28 + 29 + static void qepic_unmask(struct irq_data *d) 30 + { 31 + struct qepic_data *data = irq_data_get_irq_chip_data(d); 32 + 33 + setbits32(data->reg + CEPIMR, 1 << (31 - irqd_to_hwirq(d))); 34 + } 35 + 36 + static void qepic_end(struct irq_data *d) 37 + { 38 + struct qepic_data *data = irq_data_get_irq_chip_data(d); 39 + 40 + out_be32(data->reg + CEPIER, 1 << (31 - irqd_to_hwirq(d))); 41 + } 42 + 43 + static int qepic_set_type(struct irq_data *d, unsigned int flow_type) 44 + { 45 + struct qepic_data *data = irq_data_get_irq_chip_data(d); 46 + unsigned int vec = (unsigned int)irqd_to_hwirq(d); 47 + 48 + switch (flow_type & IRQ_TYPE_SENSE_MASK) { 49 + case IRQ_TYPE_EDGE_FALLING: 50 + setbits32(data->reg + CEPICR, 1 << (31 - vec)); 51 + return 0; 52 + case IRQ_TYPE_EDGE_BOTH: 53 + case IRQ_TYPE_NONE: 54 + clrbits32(data->reg + CEPICR, 1 << (31 - vec)); 55 + return 0; 56 + } 57 + return -EINVAL; 58 + } 59 + 60 + static struct irq_chip qepic = { 61 + .name = "QEPIC", 62 + .irq_mask = qepic_mask, 63 + .irq_unmask = qepic_unmask, 64 + .irq_eoi = qepic_end, 65 + .irq_set_type = qepic_set_type, 66 + }; 67 + 68 + static int qepic_get_irq(struct irq_desc *desc) 69 + { 70 + struct qepic_data *data = irq_desc_get_handler_data(desc); 71 + u32 event = in_be32(data->reg + CEPIER); 72 + 73 + if (!event) 74 + return -1; 75 + 76 + return irq_find_mapping(data->host, 32 - ffs(event)); 77 + } 78 + 79 + static void qepic_cascade(struct irq_desc *desc) 80 + { 81 + generic_handle_irq(qepic_get_irq(desc)); 82 + } 83 + 84 + static int qepic_host_map(struct irq_domain *h, unsigned int virq, irq_hw_number_t hw) 85 + { 86 + irq_set_chip_data(virq, h->host_data); 87 + irq_set_chip_and_handler(virq, &qepic, handle_fasteoi_irq); 88 + return 0; 89 + } 90 + 91 + static const struct irq_domain_ops qepic_host_ops = { 92 + .map = qepic_host_map, 93 + }; 94 + 95 + static int qepic_probe(struct platform_device *pdev) 96 + { 97 + struct device *dev = &pdev->dev; 98 + struct qepic_data *data; 99 + int irq; 100 + 101 + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 102 + if (!data) 103 + return -ENOMEM; 104 + 105 + data->reg = devm_platform_ioremap_resource(pdev, 0); 106 + if (IS_ERR(data->reg)) 107 + return PTR_ERR(data->reg); 108 + 109 + irq = platform_get_irq(pdev, 0); 110 + if (irq < 0) 111 + return irq; 112 + 113 + data->host = irq_domain_add_linear(dev->of_node, 32, &qepic_host_ops, data); 114 + if (!data->host) 115 + return -ENODEV; 116 + 117 + irq_set_chained_handler_and_data(irq, qepic_cascade, data); 118 + 119 + return 0; 120 + } 121 + 122 + static const struct of_device_id qepic_match[] = { 123 + { 124 + .compatible = "fsl,mpc8323-qe-ports-ic", 125 + }, 126 + {}, 127 + }; 128 + 129 + static struct platform_driver qepic_driver = { 130 + .driver = { 131 + .name = "qe_ports_ic", 132 + .of_match_table = qepic_match, 133 + }, 134 + .probe = qepic_probe, 135 + }; 136 + 137 + static int __init qepic_init(void) 138 + { 139 + return platform_driver_register(&qepic_driver); 140 + } 141 + arch_initcall(qepic_init);
+2 -11
drivers/soc/fsl/qe/qmc.c
··· 1284 1284 1285 1285 static int qmc_of_parse_chans(struct qmc *qmc, struct device_node *np) 1286 1286 { 1287 - struct device_node *chan_np; 1288 1287 struct qmc_chan *chan; 1289 1288 const char *mode; 1290 1289 u32 chan_id; 1291 1290 u64 ts_mask; 1292 1291 int ret; 1293 1292 1294 - for_each_available_child_of_node(np, chan_np) { 1293 + for_each_available_child_of_node_scoped(np, chan_np) { 1295 1294 ret = of_property_read_u32(chan_np, "reg", &chan_id); 1296 1295 if (ret) { 1297 1296 dev_err(qmc->dev, "%pOF: failed to read reg\n", chan_np); 1298 - of_node_put(chan_np); 1299 1297 return ret; 1300 1298 } 1301 1299 if (chan_id > 63) { 1302 1300 dev_err(qmc->dev, "%pOF: Invalid chan_id\n", chan_np); 1303 - of_node_put(chan_np); 1304 1301 return -EINVAL; 1305 1302 } 1306 1303 1307 1304 chan = devm_kzalloc(qmc->dev, sizeof(*chan), GFP_KERNEL); 1308 - if (!chan) { 1309 - of_node_put(chan_np); 1305 + if (!chan) 1310 1306 return -ENOMEM; 1311 - } 1312 1307 1313 1308 chan->id = chan_id; 1314 1309 spin_lock_init(&chan->ts_lock); ··· 1314 1319 if (ret) { 1315 1320 dev_err(qmc->dev, "%pOF: failed to read fsl,tx-ts-mask\n", 1316 1321 chan_np); 1317 - of_node_put(chan_np); 1318 1322 return ret; 1319 1323 } 1320 1324 chan->tx_ts_mask_avail = ts_mask; ··· 1323 1329 if (ret) { 1324 1330 dev_err(qmc->dev, "%pOF: failed to read fsl,rx-ts-mask\n", 1325 1331 chan_np); 1326 - of_node_put(chan_np); 1327 1332 return ret; 1328 1333 } 1329 1334 chan->rx_ts_mask_avail = ts_mask; ··· 1333 1340 if (ret && ret != -EINVAL) { 1334 1341 dev_err(qmc->dev, "%pOF: failed to read fsl,operational-mode\n", 1335 1342 chan_np); 1336 - of_node_put(chan_np); 1337 1343 return ret; 1338 1344 } 1339 1345 if (!strcmp(mode, "transparent")) { ··· 1342 1350 } else { 1343 1351 dev_err(qmc->dev, "%pOF: Invalid fsl,operational-mode (%s)\n", 1344 1352 chan_np, mode); 1345 - of_node_put(chan_np); 1346 1353 return -EINVAL; 1347 1354 } 1348 1355