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.

misc: keba: Add UART devices

Add support for the UART auxiliary devices. This enables access to up to
3 different UARTs, which are implemented in the FPGA.

Signed-off-by: Gerhard Engleder <eg@keba.com>
Link: https://lore.kernel.org/r/20241011191257.19702-9-gerhard@engleder-embedded.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Gerhard Engleder and committed by
Greg Kroah-Hartman
a27b406a ca7b844b

+116
+104
drivers/misc/keba/cp500.c
··· 46 46 47 47 /* MSIX */ 48 48 #define CP500_AXI_MSIX 3 49 + #define CP500_RFB_UART_MSIX 4 50 + #define CP500_DEBUG_UART_MSIX 5 51 + #define CP500_SI1_UART_MSIX 6 49 52 #define CP500_NUM_MSIX 8 50 53 #define CP500_NUM_MSIX_NO_MMI 2 51 54 #define CP500_NUM_MSIX_NO_AXI 3 ··· 78 75 struct cp500_dev_info { 79 76 off_t offset; 80 77 size_t size; 78 + unsigned int msix; 81 79 }; 82 80 83 81 struct cp500_devs { ··· 87 83 struct cp500_dev_info i2c; 88 84 struct cp500_dev_info fan; 89 85 struct cp500_dev_info batt; 86 + struct cp500_dev_info uart0_rfb; 87 + struct cp500_dev_info uart1_dbg; 88 + struct cp500_dev_info uart2_si1; 90 89 }; 91 90 92 91 /* list of devices within FPGA of CP035 family (CP035, CP056, CP057) */ ··· 99 92 .i2c = { 0x4000, SZ_4K }, 100 93 .fan = { 0x9000, SZ_4K }, 101 94 .batt = { 0xA000, SZ_4K }, 95 + .uart0_rfb = { 0xB000, SZ_4K, CP500_RFB_UART_MSIX }, 96 + .uart2_si1 = { 0xD000, SZ_4K, CP500_SI1_UART_MSIX }, 102 97 }; 103 98 104 99 /* list of devices within FPGA of CP505 family (CP503, CP505, CP507) */ ··· 110 101 .i2c = { 0x5000, SZ_4K }, 111 102 .fan = { 0x9000, SZ_4K }, 112 103 .batt = { 0xA000, SZ_4K }, 104 + .uart0_rfb = { 0xB000, SZ_4K, CP500_RFB_UART_MSIX }, 105 + .uart2_si1 = { 0xD000, SZ_4K, CP500_SI1_UART_MSIX }, 113 106 }; 114 107 115 108 /* list of devices within FPGA of CP520 family (CP520, CP530) */ ··· 121 110 .i2c = { 0x5000, SZ_4K }, 122 111 .fan = { 0x8000, SZ_4K }, 123 112 .batt = { 0x9000, SZ_4K }, 113 + .uart0_rfb = { 0xC000, SZ_4K, CP500_RFB_UART_MSIX }, 114 + .uart1_dbg = { 0xD000, SZ_4K, CP500_DEBUG_UART_MSIX }, 124 115 }; 125 116 126 117 struct cp500_nvmem { ··· 148 135 struct keba_i2c_auxdev *i2c; 149 136 struct keba_fan_auxdev *fan; 150 137 struct keba_batt_auxdev *batt; 138 + struct keba_uart_auxdev *uart0_rfb; 139 + struct keba_uart_auxdev *uart1_dbg; 140 + struct keba_uart_auxdev *uart2_si1; 151 141 152 142 /* ECM EtherCAT BAR */ 153 143 resource_size_t ecm_hwbase; ··· 526 510 return 0; 527 511 } 528 512 513 + static void cp500_uart_release(struct device *dev) 514 + { 515 + struct keba_uart_auxdev *uart = 516 + container_of(dev, struct keba_uart_auxdev, auxdev.dev); 517 + 518 + kfree(uart); 519 + } 520 + 521 + static int cp500_register_uart(struct cp500 *cp500, 522 + struct keba_uart_auxdev **uart, const char *name, 523 + struct cp500_dev_info *info, unsigned int irq) 524 + { 525 + int ret; 526 + 527 + *uart = kzalloc(sizeof(**uart), GFP_KERNEL); 528 + if (!*uart) 529 + return -ENOMEM; 530 + 531 + (*uart)->auxdev.name = name; 532 + (*uart)->auxdev.id = 0; 533 + (*uart)->auxdev.dev.release = cp500_uart_release; 534 + (*uart)->auxdev.dev.parent = &cp500->pci_dev->dev; 535 + (*uart)->io = (struct resource) { 536 + /* UART register area */ 537 + .start = (resource_size_t) cp500->sys_hwbase + info->offset, 538 + .end = (resource_size_t) cp500->sys_hwbase + info->offset + 539 + info->size - 1, 540 + .flags = IORESOURCE_MEM, 541 + }; 542 + (*uart)->irq = irq; 543 + 544 + ret = auxiliary_device_init(&(*uart)->auxdev); 545 + if (ret) { 546 + kfree(*uart); 547 + *uart = NULL; 548 + 549 + return ret; 550 + } 551 + ret = __auxiliary_device_add(&(*uart)->auxdev, "keba"); 552 + if (ret) { 553 + auxiliary_device_uninit(&(*uart)->auxdev); 554 + *uart = NULL; 555 + 556 + return ret; 557 + } 558 + 559 + return 0; 560 + } 561 + 529 562 static int cp500_nvmem_read(void *priv, unsigned int offset, void *val, 530 563 size_t bytes) 531 564 { ··· 733 668 dev_warn(dev, "Failed to register fan!\n"); 734 669 if (cp500_register_batt(cp500)) 735 670 dev_warn(dev, "Failed to register battery!\n"); 671 + if (cp500->devs->uart0_rfb.size && 672 + cp500->devs->uart0_rfb.msix < cp500->msix_num) { 673 + int irq = pci_irq_vector(cp500->pci_dev, 674 + cp500->devs->uart0_rfb.msix); 675 + 676 + if (cp500_register_uart(cp500, &cp500->uart0_rfb, "rs485-uart", 677 + &cp500->devs->uart0_rfb, irq)) 678 + dev_warn(dev, "Failed to register RFB UART!\n"); 679 + } 680 + if (cp500->devs->uart1_dbg.size && 681 + cp500->devs->uart1_dbg.msix < cp500->msix_num) { 682 + int irq = pci_irq_vector(cp500->pci_dev, 683 + cp500->devs->uart1_dbg.msix); 684 + 685 + if (cp500_register_uart(cp500, &cp500->uart1_dbg, "rs232-uart", 686 + &cp500->devs->uart1_dbg, irq)) 687 + dev_warn(dev, "Failed to register debug UART!\n"); 688 + } 689 + if (cp500->devs->uart2_si1.size && 690 + cp500->devs->uart2_si1.msix < cp500->msix_num) { 691 + int irq = pci_irq_vector(cp500->pci_dev, 692 + cp500->devs->uart2_si1.msix); 693 + 694 + if (cp500_register_uart(cp500, &cp500->uart2_si1, "uart", 695 + &cp500->devs->uart2_si1, irq)) 696 + dev_warn(dev, "Failed to register SI1 UART!\n"); 697 + } 736 698 } 737 699 738 700 static void cp500_unregister_dev(struct auxiliary_device *auxdev) ··· 785 693 if (cp500->batt) { 786 694 cp500_unregister_dev(&cp500->batt->auxdev); 787 695 cp500->batt = NULL; 696 + } 697 + if (cp500->uart0_rfb) { 698 + cp500_unregister_dev(&cp500->uart0_rfb->auxdev); 699 + cp500->uart0_rfb = NULL; 700 + } 701 + if (cp500->uart1_dbg) { 702 + cp500_unregister_dev(&cp500->uart1_dbg->auxdev); 703 + cp500->uart1_dbg = NULL; 704 + } 705 + if (cp500->uart2_si1) { 706 + cp500_unregister_dev(&cp500->uart2_si1->auxdev); 707 + cp500->uart2_si1 = NULL; 788 708 } 789 709 } 790 710
+12
include/linux/misc/keba.h
··· 57 57 struct resource io; 58 58 }; 59 59 60 + /** 61 + * struct keba_uart_auxdev - KEBA UART auxiliary device 62 + * @auxdev: auxiliary device object 63 + * @io: address range of UART controller IO memory 64 + * @irq: number of UART controller interrupt 65 + */ 66 + struct keba_uart_auxdev { 67 + struct auxiliary_device auxdev; 68 + struct resource io; 69 + unsigned int irq; 70 + }; 71 + 60 72 #endif /* _LINUX_MISC_KEBA_H */