diff options
Diffstat (limited to 'drivers/staging/kpc2000/kpc2000')
-rw-r--r-- | drivers/staging/kpc2000/kpc2000/Makefile | 2 | ||||
-rw-r--r-- | drivers/staging/kpc2000/kpc2000/cell_probe.c | 750 | ||||
-rw-r--r-- | drivers/staging/kpc2000/kpc2000/core.c | 892 | ||||
-rw-r--r-- | drivers/staging/kpc2000/kpc2000/dma_common_defs.h | 19 | ||||
-rw-r--r-- | drivers/staging/kpc2000/kpc2000/fileops.c | 131 | ||||
-rw-r--r-- | drivers/staging/kpc2000/kpc2000/kp2000_module.c | 54 | ||||
-rw-r--r-- | drivers/staging/kpc2000/kpc2000/pcie.h | 119 | ||||
-rw-r--r-- | drivers/staging/kpc2000/kpc2000/uapi.h | 22 |
8 files changed, 965 insertions, 1024 deletions
diff --git a/drivers/staging/kpc2000/kpc2000/Makefile b/drivers/staging/kpc2000/kpc2000/Makefile index 28ab1e185f9f..c274ad083db6 100644 --- a/drivers/staging/kpc2000/kpc2000/Makefile +++ b/drivers/staging/kpc2000/kpc2000/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-m := kpc2000.o -kpc2000-objs += kp2000_module.o core.o cell_probe.o fileops.o +kpc2000-objs += core.o cell_probe.o diff --git a/drivers/staging/kpc2000/kpc2000/cell_probe.c b/drivers/staging/kpc2000/kpc2000/cell_probe.c index e0dba91e7fa8..c124a836db27 100644 --- a/drivers/staging/kpc2000/kpc2000/cell_probe.c +++ b/drivers/staging/kpc2000/kpc2000/cell_probe.c @@ -4,7 +4,6 @@ #include <linux/types.h> #include <linux/export.h> #include <linux/slab.h> -#include <asm/io.h> #include <linux/io.h> #include <linux/io-64-nonatomic-lo-hi.h> #include <linux/mfd/core.h> @@ -25,7 +24,7 @@ * D C2S DMA Present * DDD C2S DMA Channel Number [up to 8 channels] * II IRQ Count [0 to 3 IRQs per core] - 1111111000 + * 1111111000 * IIIIIII IRQ Base Number [up to 128 IRQs per card] * ___ Spare * @@ -40,166 +39,192 @@ #define KP_CORE_ID_SPI 5 struct core_table_entry { - u16 type; - u32 offset; - u32 length; - bool s2c_dma_present; - u8 s2c_dma_channel_num; - bool c2s_dma_present; - u8 c2s_dma_channel_num; - u8 irq_count; - u8 irq_base_num; + u16 type; + u32 offset; + u32 length; + bool s2c_dma_present; + u8 s2c_dma_channel_num; + bool c2s_dma_present; + u8 c2s_dma_channel_num; + u8 irq_count; + u8 irq_base_num; }; static void parse_core_table_entry_v0(struct core_table_entry *cte, const u64 read_val) { - cte->type = ((read_val & 0xFFF0000000000000) >> 52); - cte->offset = ((read_val & 0x00000000FFFF0000) >> 16) * 4096; - cte->length = ((read_val & 0x0000FFFF00000000) >> 32) * 8; - cte->s2c_dma_present = ((read_val & 0x0008000000000000) >> 51); - cte->s2c_dma_channel_num = ((read_val & 0x0007000000000000) >> 48); - cte->c2s_dma_present = ((read_val & 0x0000000000008000) >> 15); - cte->c2s_dma_channel_num = ((read_val & 0x0000000000007000) >> 12); - cte->irq_count = ((read_val & 0x0000000000000C00) >> 10); - cte->irq_base_num = ((read_val & 0x00000000000003F8) >> 3); + cte->type = ((read_val & 0xFFF0000000000000) >> 52); + cte->offset = ((read_val & 0x00000000FFFF0000) >> 16) * 4096; + cte->length = ((read_val & 0x0000FFFF00000000) >> 32) * 8; + cte->s2c_dma_present = ((read_val & 0x0008000000000000) >> 51); + cte->s2c_dma_channel_num = ((read_val & 0x0007000000000000) >> 48); + cte->c2s_dma_present = ((read_val & 0x0000000000008000) >> 15); + cte->c2s_dma_channel_num = ((read_val & 0x0000000000007000) >> 12); + cte->irq_count = ((read_val & 0x0000000000000C00) >> 10); + cte->irq_base_num = ((read_val & 0x00000000000003F8) >> 3); } static void dbg_cte(struct kp2000_device *pcard, struct core_table_entry *cte) { - dev_dbg(&pcard->pdev->dev, "CTE: type:%3d offset:%3d (%3d) length:%3d (%3d) s2c:%d c2s:%d irq_count:%d base_irq:%d\n", - cte->type, - cte->offset, - cte->offset / 4096, - cte->length, - cte->length / 8, - (cte->s2c_dma_present ? cte->s2c_dma_channel_num : -1), - (cte->c2s_dma_present ? cte->c2s_dma_channel_num : -1), - cte->irq_count, - cte->irq_base_num - ); + dev_dbg(&pcard->pdev->dev, "CTE: type:%3d offset:%3d (%3d) length:%3d (%3d) s2c:%d c2s:%d irq_count:%d base_irq:%d\n", + cte->type, + cte->offset, + cte->offset / 4096, + cte->length, + cte->length / 8, + (cte->s2c_dma_present ? cte->s2c_dma_channel_num : -1), + (cte->c2s_dma_present ? cte->c2s_dma_channel_num : -1), + cte->irq_count, + cte->irq_base_num + ); } static void parse_core_table_entry(struct core_table_entry *cte, const u64 read_val, const u8 entry_rev) { switch (entry_rev) { - case 0: parse_core_table_entry_v0(cte, read_val); break; - default: cte->type = 0; break; + case 0: + parse_core_table_entry_v0(cte, read_val); + break; + default: + cte->type = 0; + break; } } - -int probe_core_basic(unsigned int core_num, struct kp2000_device *pcard, char *name, const struct core_table_entry cte) +static int probe_core_basic(unsigned int core_num, struct kp2000_device *pcard, + char *name, const struct core_table_entry cte) { - struct mfd_cell cell = {0}; - struct resource resources[2]; - - struct kpc_core_device_platdata core_pdata = { - .card_id = pcard->card_id, - .build_version = pcard->build_version, - .hardware_revision = pcard->hardware_revision, - .ssid = pcard->ssid, - .ddna = pcard->ddna, - }; - - dev_dbg(&pcard->pdev->dev, "Found Basic core: type = %02d dma = %02x / %02x offset = 0x%x length = 0x%x (%d regs)\n", cte.type, KPC_OLD_S2C_DMA_CH_NUM(cte), KPC_OLD_C2S_DMA_CH_NUM(cte), cte.offset, cte.length, cte.length / 8); - - - cell.platform_data = &core_pdata; - cell.pdata_size = sizeof(struct kpc_core_device_platdata); - cell.name = name; - cell.id = core_num; - cell.num_resources = 2; - - memset(&resources, 0, sizeof(resources)); - - resources[0].start = cte.offset; - resources[0].end = cte.offset + (cte.length - 1); - resources[0].flags = IORESOURCE_MEM; - - resources[1].start = pcard->pdev->irq; - resources[1].end = pcard->pdev->irq; - resources[1].flags = IORESOURCE_IRQ; - - cell.resources = resources; - - return mfd_add_devices( - PCARD_TO_DEV(pcard), // parent - pcard->card_num * 100, // id - &cell, // struct mfd_cell * - 1, // ndevs - &pcard->regs_base_resource, - 0, // irq_base - NULL // struct irq_domain * - ); + struct mfd_cell cell = { .id = core_num, .name = name }; + struct resource resources[2]; + + struct kpc_core_device_platdata core_pdata = { + .card_id = pcard->card_id, + .build_version = pcard->build_version, + .hardware_revision = pcard->hardware_revision, + .ssid = pcard->ssid, + .ddna = pcard->ddna, + }; + + dev_dbg(&pcard->pdev->dev, "Found Basic core: type = %02d dma = %02x / %02x offset = 0x%x length = 0x%x (%d regs)\n", cte.type, KPC_OLD_S2C_DMA_CH_NUM(cte), KPC_OLD_C2S_DMA_CH_NUM(cte), cte.offset, cte.length, cte.length / 8); + + cell.platform_data = &core_pdata; + cell.pdata_size = sizeof(struct kpc_core_device_platdata); + cell.num_resources = 2; + + memset(&resources, 0, sizeof(resources)); + + resources[0].start = cte.offset; + resources[0].end = cte.offset + (cte.length - 1); + resources[0].flags = IORESOURCE_MEM; + + resources[1].start = pcard->pdev->irq; + resources[1].end = pcard->pdev->irq; + resources[1].flags = IORESOURCE_IRQ; + + cell.resources = resources; + + return mfd_add_devices(PCARD_TO_DEV(pcard), // parent + pcard->card_num * 100, // id + &cell, // struct mfd_cell * + 1, // ndevs + &pcard->regs_base_resource, + 0, // irq_base + NULL); // struct irq_domain * } - struct kpc_uio_device { - struct list_head list; - struct kp2000_device *pcard; - struct device *dev; - struct uio_info uioinfo; - struct core_table_entry cte; - u16 core_num; + struct list_head list; + struct kp2000_device *pcard; + struct device *dev; + struct uio_info uioinfo; + struct core_table_entry cte; + u16 core_num; }; -static ssize_t show_attr(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t offset_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct kpc_uio_device *kudev = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", kudev->cte.offset); +} +static DEVICE_ATTR_RO(offset); + +static ssize_t size_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct kpc_uio_device *kudev = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", kudev->cte.length); +} +static DEVICE_ATTR_RO(size); + +static ssize_t type_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct kpc_uio_device *kudev = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", kudev->cte.type); +} +static DEVICE_ATTR_RO(type); + +static ssize_t s2c_dma_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct kpc_uio_device *kudev = dev_get_drvdata(dev); + + if (!kudev->cte.s2c_dma_present) + return sprintf(buf, "%s", "not present\n"); + + return sprintf(buf, "%u\n", kudev->cte.s2c_dma_channel_num); +} +static DEVICE_ATTR_RO(s2c_dma); + +static ssize_t c2s_dma_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct kpc_uio_device *kudev = dev_get_drvdata(dev); + + if (!kudev->cte.c2s_dma_present) + return sprintf(buf, "%s", "not present\n"); + + return sprintf(buf, "%u\n", kudev->cte.c2s_dma_channel_num); +} +static DEVICE_ATTR_RO(c2s_dma); + +static ssize_t irq_count_show(struct device *dev, struct device_attribute *attr, + char *buf) { - struct kpc_uio_device *kudev = dev_get_drvdata(dev); - - #define ATTR_NAME_CMP(v) (strcmp(v, attr->attr.name) == 0) - if ATTR_NAME_CMP("offset"){ - return scnprintf(buf, PAGE_SIZE, "%u\n", kudev->cte.offset); - } else if ATTR_NAME_CMP("size"){ - return scnprintf(buf, PAGE_SIZE, "%u\n", kudev->cte.length); - } else if ATTR_NAME_CMP("type"){ - return scnprintf(buf, PAGE_SIZE, "%u\n", kudev->cte.type); - } - else if ATTR_NAME_CMP("s2c_dma"){ - if (kudev->cte.s2c_dma_present){ - return scnprintf(buf, PAGE_SIZE, "%u\n", kudev->cte.s2c_dma_channel_num); - } else { - return scnprintf(buf, PAGE_SIZE, "not present\n"); - } - } else if ATTR_NAME_CMP("c2s_dma"){ - if (kudev->cte.c2s_dma_present){ - return scnprintf(buf, PAGE_SIZE, "%u\n", kudev->cte.c2s_dma_channel_num); - } else { - return scnprintf(buf, PAGE_SIZE, "not present\n"); - } - } - else if ATTR_NAME_CMP("irq_count"){ - return scnprintf(buf, PAGE_SIZE, "%u\n", kudev->cte.irq_count); - } else if ATTR_NAME_CMP("irq_base_num"){ - return scnprintf(buf, PAGE_SIZE, "%u\n", kudev->cte.irq_base_num); - } else if ATTR_NAME_CMP("core_num"){ - return scnprintf(buf, PAGE_SIZE, "%u\n", kudev->core_num); - } else { - return 0; - } - #undef ATTR_NAME_CMP + struct kpc_uio_device *kudev = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", kudev->cte.irq_count); +} +static DEVICE_ATTR_RO(irq_count); + +static ssize_t irq_base_num_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kpc_uio_device *kudev = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", kudev->cte.irq_base_num); } +static DEVICE_ATTR_RO(irq_base_num); + +static ssize_t core_num_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct kpc_uio_device *kudev = dev_get_drvdata(dev); + return sprintf(buf, "%u\n", kudev->core_num); +} +static DEVICE_ATTR_RO(core_num); -DEVICE_ATTR(offset, 0444, show_attr, NULL); -DEVICE_ATTR(size, 0444, show_attr, NULL); -DEVICE_ATTR(type, 0444, show_attr, NULL); -DEVICE_ATTR(s2c_dma_ch, 0444, show_attr, NULL); -DEVICE_ATTR(c2s_dma_ch, 0444, show_attr, NULL); -DEVICE_ATTR(s2c_dma, 0444, show_attr, NULL); -DEVICE_ATTR(c2s_dma, 0444, show_attr, NULL); -DEVICE_ATTR(irq_count, 0444, show_attr, NULL); -DEVICE_ATTR(irq_base_num, 0444, show_attr, NULL); -DEVICE_ATTR(core_num, 0444, show_attr, NULL); -struct attribute * kpc_uio_class_attrs[] = { +struct attribute *kpc_uio_class_attrs[] = { &dev_attr_offset.attr, &dev_attr_size.attr, &dev_attr_type.attr, - &dev_attr_s2c_dma_ch.attr, - &dev_attr_c2s_dma_ch.attr, &dev_attr_s2c_dma.attr, &dev_attr_c2s_dma.attr, &dev_attr_irq_count.attr, @@ -208,264 +233,277 @@ struct attribute * kpc_uio_class_attrs[] = { NULL, }; - static int kp2000_check_uio_irq(struct kp2000_device *pcard, u32 irq_num) { - u64 interrupt_active = readq(pcard->sysinfo_regs_base + REG_INTERRUPT_ACTIVE); - u64 interrupt_mask_inv = ~readq(pcard->sysinfo_regs_base + REG_INTERRUPT_MASK); - u64 irq_check_mask = (1 << irq_num); - if (interrupt_active & irq_check_mask){ // if it's active (interrupt pending) - if (interrupt_mask_inv & irq_check_mask){ // and if it's not masked off - return 1; - } - } - return 0; + u64 interrupt_active = readq(pcard->sysinfo_regs_base + REG_INTERRUPT_ACTIVE); + u64 interrupt_mask_inv = ~readq(pcard->sysinfo_regs_base + REG_INTERRUPT_MASK); + u64 irq_check_mask = BIT_ULL(irq_num); + + if (interrupt_active & irq_check_mask) { // if it's active (interrupt pending) + if (interrupt_mask_inv & irq_check_mask) { // and if it's not masked off + return 1; + } + } + return 0; } static irqreturn_t kuio_handler(int irq, struct uio_info *uioinfo) { - struct kpc_uio_device *kudev = uioinfo->priv; - if (irq != kudev->pcard->pdev->irq) - return IRQ_NONE; - - if (kp2000_check_uio_irq(kudev->pcard, kudev->cte.irq_base_num)){ - writeq((1 << kudev->cte.irq_base_num), kudev->pcard->sysinfo_regs_base + REG_INTERRUPT_ACTIVE); // Clear the active flag - return IRQ_HANDLED; - } - return IRQ_NONE; + struct kpc_uio_device *kudev = uioinfo->priv; + + if (irq != kudev->pcard->pdev->irq) + return IRQ_NONE; + + if (kp2000_check_uio_irq(kudev->pcard, kudev->cte.irq_base_num)) { + /* Clear the active flag */ + writeq(BIT_ULL(kudev->cte.irq_base_num), + kudev->pcard->sysinfo_regs_base + REG_INTERRUPT_ACTIVE); + return IRQ_HANDLED; + } + return IRQ_NONE; } static int kuio_irqcontrol(struct uio_info *uioinfo, s32 irq_on) { - struct kpc_uio_device *kudev = uioinfo->priv; - struct kp2000_device *pcard = kudev->pcard; - u64 mask; - - lock_card(pcard); - mask = readq(pcard->sysinfo_regs_base + REG_INTERRUPT_MASK); - if (irq_on){ - mask &= ~(1 << (kudev->cte.irq_base_num)); - } else { - mask |= (1 << (kudev->cte.irq_base_num)); - } - writeq(mask, pcard->sysinfo_regs_base + REG_INTERRUPT_MASK); - unlock_card(pcard); - - return 0; + struct kpc_uio_device *kudev = uioinfo->priv; + struct kp2000_device *pcard = kudev->pcard; + u64 mask; + + mutex_lock(&pcard->sem); + mask = readq(pcard->sysinfo_regs_base + REG_INTERRUPT_MASK); + if (irq_on) + mask &= ~(BIT_ULL(kudev->cte.irq_base_num)); + else + mask |= BIT_ULL(kudev->cte.irq_base_num); + writeq(mask, pcard->sysinfo_regs_base + REG_INTERRUPT_MASK); + mutex_unlock(&pcard->sem); + + return 0; } -int probe_core_uio(unsigned int core_num, struct kp2000_device *pcard, char *name, const struct core_table_entry cte) +static int probe_core_uio(unsigned int core_num, struct kp2000_device *pcard, + char *name, const struct core_table_entry cte) { - struct kpc_uio_device *kudev; - int rv; - - dev_dbg(&pcard->pdev->dev, "Found UIO core: type = %02d dma = %02x / %02x offset = 0x%x length = 0x%x (%d regs)\n", cte.type, KPC_OLD_S2C_DMA_CH_NUM(cte), KPC_OLD_C2S_DMA_CH_NUM(cte), cte.offset, cte.length, cte.length / 8); - - kudev = kzalloc(sizeof(struct kpc_uio_device), GFP_KERNEL); - if (!kudev){ - dev_err(&pcard->pdev->dev, "probe_core_uio: failed to kzalloc kpc_uio_device\n"); - return -ENOMEM; - } - - INIT_LIST_HEAD(&kudev->list); - kudev->pcard = pcard; - kudev->cte = cte; - kudev->core_num = core_num; - - kudev->uioinfo.priv = kudev; - kudev->uioinfo.name = name; - kudev->uioinfo.version = "0.0"; - if (cte.irq_count > 0){ - kudev->uioinfo.irq_flags = IRQF_SHARED; - kudev->uioinfo.irq = pcard->pdev->irq; - kudev->uioinfo.handler = kuio_handler; - kudev->uioinfo.irqcontrol = kuio_irqcontrol; - } else { - kudev->uioinfo.irq = 0; - } - - kudev->uioinfo.mem[0].name = "uiomap"; - kudev->uioinfo.mem[0].addr = pci_resource_start(pcard->pdev, REG_BAR) + cte.offset; - kudev->uioinfo.mem[0].size = (cte.length + PAGE_SIZE-1) & ~(PAGE_SIZE-1); // Round up to nearest PAGE_SIZE boundary - kudev->uioinfo.mem[0].memtype = UIO_MEM_PHYS; - - kudev->dev = device_create(kpc_uio_class, &pcard->pdev->dev, MKDEV(0,0), kudev, "%s.%d.%d.%d", kudev->uioinfo.name, pcard->card_num, cte.type, kudev->core_num); - if (IS_ERR(kudev->dev)) { - dev_err(&pcard->pdev->dev, "probe_core_uio device_create failed!\n"); - return -ENODEV; - } - dev_set_drvdata(kudev->dev, kudev); - - rv = uio_register_device(kudev->dev, &kudev->uioinfo); - if (rv){ - dev_err(&pcard->pdev->dev, "probe_core_uio failed uio_register_device: %d\n", rv); - return rv; - } - - list_add_tail(&kudev->list, &pcard->uio_devices_list); - - return 0; -} + struct kpc_uio_device *kudev; + int rv; + + dev_dbg(&pcard->pdev->dev, "Found UIO core: type = %02d dma = %02x / %02x offset = 0x%x length = 0x%x (%d regs)\n", cte.type, KPC_OLD_S2C_DMA_CH_NUM(cte), KPC_OLD_C2S_DMA_CH_NUM(cte), cte.offset, cte.length, cte.length / 8); + + kudev = kzalloc(sizeof(*kudev), GFP_KERNEL); + if (!kudev) + return -ENOMEM; + + INIT_LIST_HEAD(&kudev->list); + kudev->pcard = pcard; + kudev->cte = cte; + kudev->core_num = core_num; + + kudev->uioinfo.priv = kudev; + kudev->uioinfo.name = name; + kudev->uioinfo.version = "0.0"; + if (cte.irq_count > 0) { + kudev->uioinfo.irq_flags = IRQF_SHARED; + kudev->uioinfo.irq = pcard->pdev->irq; + kudev->uioinfo.handler = kuio_handler; + kudev->uioinfo.irqcontrol = kuio_irqcontrol; + } else { + kudev->uioinfo.irq = 0; + } + + kudev->uioinfo.mem[0].name = "uiomap"; + kudev->uioinfo.mem[0].addr = pci_resource_start(pcard->pdev, REG_BAR) + cte.offset; + kudev->uioinfo.mem[0].size = (cte.length + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); // Round up to nearest PAGE_SIZE boundary + kudev->uioinfo.mem[0].memtype = UIO_MEM_PHYS; + + kudev->dev = device_create(kpc_uio_class, &pcard->pdev->dev, MKDEV(0, 0), kudev, "%s.%d.%d.%d", kudev->uioinfo.name, pcard->card_num, cte.type, kudev->core_num); + if (IS_ERR(kudev->dev)) { + dev_err(&pcard->pdev->dev, "%s: device_create failed!\n", + __func__); + kfree(kudev); + return -ENODEV; + } + dev_set_drvdata(kudev->dev, kudev); + + rv = uio_register_device(kudev->dev, &kudev->uioinfo); + if (rv) { + dev_err(&pcard->pdev->dev, "%s: failed uio_register_device: %d\n", + __func__, rv); + put_device(kudev->dev); + kfree(kudev); + return rv; + } + list_add_tail(&kudev->list, &pcard->uio_devices_list); + + return 0; +} static int create_dma_engine_core(struct kp2000_device *pcard, size_t engine_regs_offset, int engine_num, int irq_num) { - struct mfd_cell cell = {0}; - struct resource resources[2]; - - dev_dbg(&pcard->pdev->dev, "create_dma_core(pcard = [%p], engine_regs_offset = %zx, engine_num = %d)\n", pcard, engine_regs_offset, engine_num); - - cell.platform_data = NULL; - cell.pdata_size = 0; - cell.id = engine_num; - cell.name = KP_DRIVER_NAME_DMA_CONTROLLER; - cell.num_resources = 2; - - memset(&resources, 0, sizeof(resources)); - - resources[0].start = engine_regs_offset; - resources[0].end = engine_regs_offset + (KPC_DMA_ENGINE_SIZE - 1); - resources[0].flags = IORESOURCE_MEM; - - resources[1].start = irq_num; - resources[1].end = irq_num; - resources[1].flags = IORESOURCE_IRQ; - - cell.resources = resources; - - return mfd_add_devices( - PCARD_TO_DEV(pcard), // parent - pcard->card_num * 100, // id - &cell, // struct mfd_cell * - 1, // ndevs - &pcard->dma_base_resource, - 0, // irq_base - NULL // struct irq_domain * - ); + struct mfd_cell cell = { .id = engine_num }; + struct resource resources[2]; + + cell.platform_data = NULL; + cell.pdata_size = 0; + cell.name = KP_DRIVER_NAME_DMA_CONTROLLER; + cell.num_resources = 2; + + memset(&resources, 0, sizeof(resources)); + + resources[0].start = engine_regs_offset; + resources[0].end = engine_regs_offset + (KPC_DMA_ENGINE_SIZE - 1); + resources[0].flags = IORESOURCE_MEM; + + resources[1].start = irq_num; + resources[1].end = irq_num; + resources[1].flags = IORESOURCE_IRQ; + + cell.resources = resources; + + return mfd_add_devices(PCARD_TO_DEV(pcard), // parent + pcard->card_num * 100, // id + &cell, // struct mfd_cell * + 1, // ndevs + &pcard->dma_base_resource, + 0, // irq_base + NULL); // struct irq_domain * } static int kp2000_setup_dma_controller(struct kp2000_device *pcard) { - int err; - unsigned int i; - u64 capabilities_reg; - - // S2C Engines - for (i = 0 ; i < 32 ; i++){ - capabilities_reg = readq( pcard->dma_bar_base + KPC_DMA_S2C_BASE_OFFSET + (KPC_DMA_ENGINE_SIZE * i) ); - if (capabilities_reg & ENGINE_CAP_PRESENT_MASK){ - err = create_dma_engine_core(pcard, (KPC_DMA_S2C_BASE_OFFSET + (KPC_DMA_ENGINE_SIZE * i)), i, pcard->pdev->irq); - if (err) goto err_out; - } - } - // C2S Engines - for (i = 0 ; i < 32 ; i++){ - capabilities_reg = readq( pcard->dma_bar_base + KPC_DMA_C2S_BASE_OFFSET + (KPC_DMA_ENGINE_SIZE * i) ); - if (capabilities_reg & ENGINE_CAP_PRESENT_MASK){ - err = create_dma_engine_core(pcard, (KPC_DMA_C2S_BASE_OFFSET + (KPC_DMA_ENGINE_SIZE * i)), 32+i, pcard->pdev->irq); - if (err) goto err_out; - } - } - - return 0; - + int err; + unsigned int i; + u64 capabilities_reg; + + // S2C Engines + for (i = 0 ; i < 32 ; i++) { + capabilities_reg = readq(pcard->dma_bar_base + KPC_DMA_S2C_BASE_OFFSET + (KPC_DMA_ENGINE_SIZE * i)); + if (capabilities_reg & ENGINE_CAP_PRESENT_MASK) { + err = create_dma_engine_core(pcard, (KPC_DMA_S2C_BASE_OFFSET + (KPC_DMA_ENGINE_SIZE * i)), i, pcard->pdev->irq); + if (err) + goto err_out; + } + } + // C2S Engines + for (i = 0 ; i < 32 ; i++) { + capabilities_reg = readq(pcard->dma_bar_base + KPC_DMA_C2S_BASE_OFFSET + (KPC_DMA_ENGINE_SIZE * i)); + if (capabilities_reg & ENGINE_CAP_PRESENT_MASK) { + err = create_dma_engine_core(pcard, (KPC_DMA_C2S_BASE_OFFSET + (KPC_DMA_ENGINE_SIZE * i)), 32 + i, pcard->pdev->irq); + if (err) + goto err_out; + } + } + + return 0; + err_out: - dev_err(&pcard->pdev->dev, "kp2000_setup_dma_controller: failed to add a DMA Engine: %d\n", err); - return err; + dev_err(&pcard->pdev->dev, "%s: failed to add a DMA Engine: %d\n", + __func__, err); + return err; } int kp2000_probe_cores(struct kp2000_device *pcard) { - int err = 0; - int i; - int current_type_id; - u64 read_val; - unsigned int highest_core_id = 0; - struct core_table_entry cte; - - dev_dbg(&pcard->pdev->dev, "kp2000_probe_cores(pcard = %p / %d)\n", pcard, pcard->card_num); - - err = kp2000_setup_dma_controller(pcard); - if (err) return err; - - INIT_LIST_HEAD(&pcard->uio_devices_list); - - // First, iterate the core table looking for the highest CORE_ID - for (i = 0 ; i < pcard->core_table_length ; i++){ - read_val = readq(pcard->sysinfo_regs_base + ((pcard->core_table_offset + i) * 8)); - parse_core_table_entry(&cte, read_val, pcard->core_table_rev); - dbg_cte(pcard, &cte); - if (cte.type > highest_core_id){ - highest_core_id = cte.type; - } - if (cte.type == KP_CORE_ID_INVALID){ - dev_info(&pcard->pdev->dev, "Found Invalid core: %016llx\n", read_val); - } - } - // Then, iterate over the possible core types. - for (current_type_id = 1 ; current_type_id <= highest_core_id ; current_type_id++){ - unsigned int core_num = 0; - // Foreach core type, iterate the whole table and instantiate subdevices for each core. - // Yes, this is O(n*m) but the actual runtime is small enough that it's an acceptable tradeoff. - for (i = 0 ; i < pcard->core_table_length ; i++){ - read_val = readq(pcard->sysinfo_regs_base + ((pcard->core_table_offset + i) * 8)); - parse_core_table_entry(&cte, read_val, pcard->core_table_rev); - - if (cte.type == current_type_id){ - switch (cte.type){ - case KP_CORE_ID_I2C: - err = probe_core_basic(core_num, pcard, KP_DRIVER_NAME_I2C, cte); - break; - - case KP_CORE_ID_SPI: - err = probe_core_basic(core_num, pcard, KP_DRIVER_NAME_SPI, cte); - break; - - default: - err = probe_core_uio(core_num, pcard, "kpc_uio", cte); - break; - } - if (err){ - dev_err(&pcard->pdev->dev, "kp2000_probe_cores: failed to add core %d: %d\n", i, err); - return err; - } - core_num++; - } - } - } - - // Finally, instantiate a UIO device for the core_table. - cte.type = 0; // CORE_ID_BOARD_INFO - cte.offset = 0; // board info is always at the beginning - cte.length = 512*8; - cte.s2c_dma_present = false; - cte.s2c_dma_channel_num = 0; - cte.c2s_dma_present = false; - cte.c2s_dma_channel_num = 0; - cte.irq_count = 0; - cte.irq_base_num = 0; - err = probe_core_uio(0, pcard, "kpc_uio", cte); - if (err){ - dev_err(&pcard->pdev->dev, "kp2000_probe_cores: failed to add board_info core: %d\n", err); - return err; - } - - return 0; + int err = 0; + int i; + int current_type_id; + u64 read_val; + unsigned int highest_core_id = 0; + struct core_table_entry cte; + + err = kp2000_setup_dma_controller(pcard); + if (err) + return err; + + INIT_LIST_HEAD(&pcard->uio_devices_list); + + // First, iterate the core table looking for the highest CORE_ID + for (i = 0 ; i < pcard->core_table_length ; i++) { + read_val = readq(pcard->sysinfo_regs_base + ((pcard->core_table_offset + i) * 8)); + parse_core_table_entry(&cte, read_val, pcard->core_table_rev); + dbg_cte(pcard, &cte); + if (cte.type > highest_core_id) + highest_core_id = cte.type; + if (cte.type == KP_CORE_ID_INVALID) + dev_info(&pcard->pdev->dev, "Found Invalid core: %016llx\n", read_val); + } + // Then, iterate over the possible core types. + for (current_type_id = 1 ; current_type_id <= highest_core_id ; current_type_id++) { + unsigned int core_num = 0; + // Foreach core type, iterate the whole table and instantiate subdevices for each core. + // Yes, this is O(n*m) but the actual runtime is small enough that it's an acceptable tradeoff. + for (i = 0 ; i < pcard->core_table_length ; i++) { + read_val = readq(pcard->sysinfo_regs_base + ((pcard->core_table_offset + i) * 8)); + parse_core_table_entry(&cte, read_val, pcard->core_table_rev); + + if (cte.type != current_type_id) + continue; + + switch (cte.type) { + case KP_CORE_ID_I2C: + err = probe_core_basic(core_num, pcard, + KP_DRIVER_NAME_I2C, cte); + break; + + case KP_CORE_ID_SPI: + err = probe_core_basic(core_num, pcard, + KP_DRIVER_NAME_SPI, cte); + break; + + default: + err = probe_core_uio(core_num, pcard, "kpc_uio", cte); + break; + } + if (err) { + dev_err(&pcard->pdev->dev, + "%s: failed to add core %d: %d\n", + __func__, i, err); + goto error; + } + core_num++; + } + } + + // Finally, instantiate a UIO device for the core_table. + cte.type = 0; // CORE_ID_BOARD_INFO + cte.offset = 0; // board info is always at the beginning + cte.length = 512 * 8; + cte.s2c_dma_present = false; + cte.s2c_dma_channel_num = 0; + cte.c2s_dma_present = false; + cte.c2s_dma_channel_num = 0; + cte.irq_count = 0; + cte.irq_base_num = 0; + err = probe_core_uio(0, pcard, "kpc_uio", cte); + if (err) { + dev_err(&pcard->pdev->dev, "%s: failed to add board_info core: %d\n", + __func__, err); + goto error; + } + + return 0; + +error: + kp2000_remove_cores(pcard); + mfd_remove_devices(PCARD_TO_DEV(pcard)); + return err; } void kp2000_remove_cores(struct kp2000_device *pcard) { - struct list_head *ptr; - struct list_head *next; - list_for_each_safe(ptr, next, &pcard->uio_devices_list){ - struct kpc_uio_device *kudev = list_entry(ptr, struct kpc_uio_device, list); - uio_unregister_device(&kudev->uioinfo); - device_unregister(kudev->dev); - list_del(&kudev->list); - kfree(kudev); - } + struct list_head *ptr; + struct list_head *next; + + list_for_each_safe(ptr, next, &pcard->uio_devices_list) { + struct kpc_uio_device *kudev = list_entry(ptr, struct kpc_uio_device, list); + + uio_unregister_device(&kudev->uioinfo); + device_unregister(kudev->dev); + list_del(&kudev->list); + kfree(kudev); + } } diff --git a/drivers/staging/kpc2000/kpc2000/core.c b/drivers/staging/kpc2000/kpc2000/core.c index 40390cdd3c8d..cb05cca687e1 100644 --- a/drivers/staging/kpc2000/kpc2000/core.c +++ b/drivers/staging/kpc2000/kpc2000/core.c @@ -1,11 +1,17 @@ // SPDX-License-Identifier: GPL-2.0+ +#include <linux/kernel.h> +#include <linux/idr.h> #include <linux/init.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/types.h> #include <linux/export.h> #include <linux/slab.h> -#include <asm/io.h> +#include <linux/fs.h> +#include <linux/errno.h> +#include <linux/cdev.h> +#include <linux/rwsem.h> +#include <linux/uaccess.h> #include <linux/io.h> #include <linux/mfd/core.h> #include <linux/platform_device.h> @@ -17,421 +23,543 @@ #include <linux/sched.h> #include <linux/jiffies.h> #include "pcie.h" +#include "uapi.h" +static DEFINE_IDA(card_num_ida); /******************************************************* - * SysFS Attributes - ******************************************************/ -static ssize_t show_attr(struct device *dev, struct device_attribute *attr, char *buf) + * SysFS Attributes + ******************************************************/ + +static ssize_t ssid_show(struct device *dev, struct device_attribute *attr, + char *buf) { - struct pci_dev *pdev = to_pci_dev(dev); - struct kp2000_device *pcard; - - if (!pdev) return -ENXIO; - pcard = pci_get_drvdata(pdev); - if (!pcard) return -ENXIO; - - if (strcmp("ssid", attr->attr.name) == 0){ return scnprintf(buf, PAGE_SIZE, "%016llx\n", pcard->ssid); } else - if (strcmp("ddna", attr->attr.name) == 0){ return scnprintf(buf, PAGE_SIZE, "%016llx\n", pcard->ddna); } else - if (strcmp("card_id", attr->attr.name) == 0){ return scnprintf(buf, PAGE_SIZE, "%08x\n", pcard->card_id); } else - if (strcmp("hw_rev", attr->attr.name) == 0){ return scnprintf(buf, PAGE_SIZE, "%08x\n", pcard->hardware_revision); } else - if (strcmp("build", attr->attr.name) == 0){ return scnprintf(buf, PAGE_SIZE, "%08x\n", pcard->build_version); } else - if (strcmp("build_date", attr->attr.name) == 0){ return scnprintf(buf, PAGE_SIZE, "%08x\n", pcard->build_datestamp); } else - if (strcmp("build_time", attr->attr.name) == 0){ return scnprintf(buf, PAGE_SIZE, "%08x\n", pcard->build_timestamp); } else - { return -ENXIO; } + struct kp2000_device *pcard = dev_get_drvdata(dev); + + return sprintf(buf, "%016llx\n", pcard->ssid); } +static DEVICE_ATTR_RO(ssid); -static ssize_t show_cpld_config_reg(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t ddna_show(struct device *dev, struct device_attribute *attr, + char *buf) { - struct pci_dev *pdev = to_pci_dev(dev); - struct kp2000_device *pcard; - u64 val; + struct kp2000_device *pcard = dev_get_drvdata(dev); - if (!pdev) - return -ENXIO; + return sprintf(buf, "%016llx\n", pcard->ddna); +} +static DEVICE_ATTR_RO(ddna); - pcard = pci_get_drvdata(pdev); - if (!pcard) - return -ENXIO; +static ssize_t card_id_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct kp2000_device *pcard = dev_get_drvdata(dev); + + return sprintf(buf, "%08x\n", pcard->card_id); +} +static DEVICE_ATTR_RO(card_id); + +static ssize_t hw_rev_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct kp2000_device *pcard = dev_get_drvdata(dev); + + return sprintf(buf, "%08x\n", pcard->hardware_revision); +} +static DEVICE_ATTR_RO(hw_rev); + +static ssize_t build_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct kp2000_device *pcard = dev_get_drvdata(dev); + + return sprintf(buf, "%08x\n", pcard->build_version); +} +static DEVICE_ATTR_RO(build); + +static ssize_t build_date_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kp2000_device *pcard = dev_get_drvdata(dev); + + return sprintf(buf, "%08x\n", pcard->build_datestamp); +} +static DEVICE_ATTR_RO(build_date); + +static ssize_t build_time_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kp2000_device *pcard = dev_get_drvdata(dev); + + return sprintf(buf, "%08x\n", pcard->build_timestamp); +} +static DEVICE_ATTR_RO(build_time); + +static ssize_t cpld_reg_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct kp2000_device *pcard = dev_get_drvdata(dev); + u64 val; val = readq(pcard->sysinfo_regs_base + REG_CPLD_CONFIG); - return scnprintf(buf, PAGE_SIZE, "%016llx\n", val); + return sprintf(buf, "%016llx\n", val); +} +static DEVICE_ATTR_RO(cpld_reg); + +static ssize_t cpld_reconfigure(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct kp2000_device *pcard = dev_get_drvdata(dev); + long wr_val; + int rv; + + rv = kstrtol(buf, 0, &wr_val); + if (rv < 0) + return rv; + if (wr_val > 7) + return -EINVAL; + + wr_val = wr_val << 8; + wr_val |= 0x1; // Set the "Configure Go" bit + writeq(wr_val, pcard->sysinfo_regs_base + REG_CPLD_CONFIG); + return count; } -static ssize_t cpld_reconfigure(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +static DEVICE_ATTR(cpld_reconfigure, 0220, NULL, cpld_reconfigure); + +static ssize_t irq_mask_reg_show(struct device *dev, + struct device_attribute *attr, char *buf) { - struct pci_dev *pdev = to_pci_dev(dev); - long wr_val; - struct kp2000_device *pcard; - int rv; - - if (!pdev) return -ENXIO; - pcard = pci_get_drvdata(pdev); - if (!pcard) return -ENXIO; - - rv = kstrtol(buf, 0, &wr_val); - if (rv < 0) return rv; - if (wr_val > 7) return -EINVAL; - - wr_val = wr_val << 8; - wr_val |= 0x1; // Set the "Configure Go" bit - writeq(wr_val, pcard->sysinfo_regs_base + REG_CPLD_CONFIG); - return count; + struct kp2000_device *pcard = dev_get_drvdata(dev); + u64 val; + + val = readq(pcard->sysinfo_regs_base + REG_INTERRUPT_MASK); + return sprintf(buf, "%016llx\n", val); } +static DEVICE_ATTR_RO(irq_mask_reg); +static ssize_t irq_active_reg_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kp2000_device *pcard = dev_get_drvdata(dev); + u64 val; -DEVICE_ATTR(ssid, 0444, show_attr, NULL); -DEVICE_ATTR(ddna, 0444, show_attr, NULL); -DEVICE_ATTR(card_id, 0444, show_attr, NULL); -DEVICE_ATTR(hw_rev, 0444, show_attr, NULL); -DEVICE_ATTR(build, 0444, show_attr, NULL); -DEVICE_ATTR(build_date, 0444, show_attr, NULL); -DEVICE_ATTR(build_time, 0444, show_attr, NULL); -DEVICE_ATTR(cpld_reg, 0444, show_cpld_config_reg, NULL); -DEVICE_ATTR(cpld_reconfigure, 0220, NULL, cpld_reconfigure); - -static const struct attribute * kp_attr_list[] = { - &dev_attr_ssid.attr, - &dev_attr_ddna.attr, - &dev_attr_card_id.attr, - &dev_attr_hw_rev.attr, - &dev_attr_build.attr, - &dev_attr_build_date.attr, - &dev_attr_build_time.attr, - &dev_attr_cpld_reg.attr, - &dev_attr_cpld_reconfigure.attr, - NULL, -}; + val = readq(pcard->sysinfo_regs_base + REG_INTERRUPT_ACTIVE); + return sprintf(buf, "%016llx\n", val); +} +static DEVICE_ATTR_RO(irq_active_reg); +static ssize_t pcie_error_count_reg_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct kp2000_device *pcard = dev_get_drvdata(dev); + u64 val; + + val = readq(pcard->sysinfo_regs_base + REG_PCIE_ERROR_COUNT); + return sprintf(buf, "%016llx\n", val); +} +static DEVICE_ATTR_RO(pcie_error_count_reg); + +static ssize_t core_table_offset_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kp2000_device *pcard = dev_get_drvdata(dev); + + return sprintf(buf, "%08x\n", pcard->core_table_offset); +} +static DEVICE_ATTR_RO(core_table_offset); + +static ssize_t core_table_length_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kp2000_device *pcard = dev_get_drvdata(dev); + + return sprintf(buf, "%08x\n", pcard->core_table_length); +} +static DEVICE_ATTR_RO(core_table_length); + +static const struct attribute *kp_attr_list[] = { + &dev_attr_ssid.attr, + &dev_attr_ddna.attr, + &dev_attr_card_id.attr, + &dev_attr_hw_rev.attr, + &dev_attr_build.attr, + &dev_attr_build_date.attr, + &dev_attr_build_time.attr, + &dev_attr_cpld_reg.attr, + &dev_attr_cpld_reconfigure.attr, + &dev_attr_irq_mask_reg.attr, + &dev_attr_irq_active_reg.attr, + &dev_attr_pcie_error_count_reg.attr, + &dev_attr_core_table_offset.attr, + &dev_attr_core_table_length.attr, + NULL, +}; /******************************************************* - * Functions - ******************************************************/ + * Functions + ******************************************************/ static void wait_and_read_ssid(struct kp2000_device *pcard) { - u64 read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_SSID); - unsigned long timeout; - - if (read_val & 0x8000000000000000){ - pcard->ssid = read_val; - return; - } - - timeout = jiffies + (HZ * 2); - do { - read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_SSID); - if (read_val & 0x8000000000000000){ - pcard->ssid = read_val; - return; - } - cpu_relax(); - //schedule(); - } while (time_before(jiffies, timeout)); - - dev_notice(&pcard->pdev->dev, "SSID didn't show up!\n"); - - #if 0 - // Timed out waiting for the SSID to show up, just use the DDNA instead? - read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_DDNA); - pcard->ssid = read_val; - #else - // Timed out waiting for the SSID to show up, stick all zeros in the value - pcard->ssid = 0; - #endif + u64 read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_SSID); + unsigned long timeout; + + if (read_val & 0x8000000000000000) { + pcard->ssid = read_val; + return; + } + + timeout = jiffies + (HZ * 2); + do { + read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_SSID); + if (read_val & 0x8000000000000000) { + pcard->ssid = read_val; + return; + } + cpu_relax(); + //schedule(); + } while (time_before(jiffies, timeout)); + + dev_notice(&pcard->pdev->dev, "SSID didn't show up!\n"); + + // Timed out waiting for the SSID to show up, stick all zeros in the + // value + pcard->ssid = 0; } static int read_system_regs(struct kp2000_device *pcard) { - u64 read_val; - - read_val = readq(pcard->sysinfo_regs_base + REG_MAGIC_NUMBER); - if (read_val != KP2000_MAGIC_VALUE){ - dev_err(&pcard->pdev->dev, "Invalid magic! Got: 0x%016llx Want: 0x%016lx\n", read_val, KP2000_MAGIC_VALUE); - return -EILSEQ; - } - - read_val = readq(pcard->sysinfo_regs_base + REG_CARD_ID_AND_BUILD); - pcard->card_id = (read_val & 0xFFFFFFFF00000000) >> 32; - pcard->build_version = (read_val & 0x00000000FFFFFFFF) >> 0; - - read_val = readq(pcard->sysinfo_regs_base + REG_DATE_AND_TIME_STAMPS); - pcard->build_datestamp = (read_val & 0xFFFFFFFF00000000) >> 32; - pcard->build_timestamp = (read_val & 0x00000000FFFFFFFF) >> 0; - - read_val = readq(pcard->sysinfo_regs_base + REG_CORE_TABLE_OFFSET); - pcard->core_table_length = (read_val & 0xFFFFFFFF00000000) >> 32; - pcard->core_table_offset = (read_val & 0x00000000FFFFFFFF) >> 0; - - wait_and_read_ssid(pcard); - - read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_HW_ID); - pcard->core_table_rev = (read_val & 0x0000000000000F00) >> 8; - pcard->hardware_revision = (read_val & 0x000000000000001F); - - read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_DDNA); - pcard->ddna = read_val; - - dev_info(&pcard->pdev->dev, "system_regs: %08x %08x %08x %08x %02x %d %d %016llx %016llx\n", - pcard->card_id, - pcard->build_version, - pcard->build_datestamp, - pcard->build_timestamp, - pcard->hardware_revision, - pcard->core_table_rev, - pcard->core_table_length, - pcard->ssid, - pcard->ddna - ); - - if (pcard->core_table_rev > 1){ - dev_err(&pcard->pdev->dev, "core table entry revision is higher than we can deal with, cannot continue with this card!\n"); - return 1; - } - - return 0; + u64 read_val; + + read_val = readq(pcard->sysinfo_regs_base + REG_MAGIC_NUMBER); + if (read_val != KP2000_MAGIC_VALUE) { + dev_err(&pcard->pdev->dev, + "Invalid magic! Got: 0x%016llx Want: 0x%016llx\n", + read_val, KP2000_MAGIC_VALUE); + return -EILSEQ; + } + + read_val = readq(pcard->sysinfo_regs_base + REG_CARD_ID_AND_BUILD); + pcard->card_id = (read_val & 0xFFFFFFFF00000000) >> 32; + pcard->build_version = (read_val & 0x00000000FFFFFFFF) >> 0; + + read_val = readq(pcard->sysinfo_regs_base + REG_DATE_AND_TIME_STAMPS); + pcard->build_datestamp = (read_val & 0xFFFFFFFF00000000) >> 32; + pcard->build_timestamp = (read_val & 0x00000000FFFFFFFF) >> 0; + + read_val = readq(pcard->sysinfo_regs_base + REG_CORE_TABLE_OFFSET); + pcard->core_table_length = (read_val & 0xFFFFFFFF00000000) >> 32; + pcard->core_table_offset = (read_val & 0x00000000FFFFFFFF) >> 0; + + wait_and_read_ssid(pcard); + + read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_HW_ID); + pcard->core_table_rev = (read_val & 0x0000000000000F00) >> 8; + pcard->hardware_revision = (read_val & 0x000000000000001F); + + read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_DDNA); + pcard->ddna = read_val; + + dev_info(&pcard->pdev->dev, + "system_regs: %08x %08x %08x %08x %02x %d %d %016llx %016llx\n", + pcard->card_id, + pcard->build_version, + pcard->build_datestamp, + pcard->build_timestamp, + pcard->hardware_revision, + pcard->core_table_rev, + pcard->core_table_length, + pcard->ssid, + pcard->ddna); + + if (pcard->core_table_rev > 1) { + dev_err(&pcard->pdev->dev, + "core table entry revision is higher than we can deal with, cannot continue with this card!\n"); + return 1; + } + + return 0; } -irqreturn_t kp2000_irq_handler(int irq, void *dev_id) +static irqreturn_t kp2000_irq_handler(int irq, void *dev_id) { - struct kp2000_device *pcard = (struct kp2000_device*)dev_id; - SetBackEndControl(pcard->dma_common_regs, KPC_DMA_CARD_IRQ_ENABLE | KPC_DMA_CARD_USER_INTERRUPT_MODE | KPC_DMA_CARD_USER_INTERRUPT_ACTIVE); - return IRQ_HANDLED; + struct kp2000_device *pcard = dev_id; + + writel(KPC_DMA_CARD_IRQ_ENABLE | + KPC_DMA_CARD_USER_INTERRUPT_MODE | + KPC_DMA_CARD_USER_INTERRUPT_ACTIVE, + pcard->dma_common_regs); + return IRQ_HANDLED; } -int kp2000_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) +static int kp2000_pcie_probe(struct pci_dev *pdev, + const struct pci_device_id *id) { - int err = 0; - struct kp2000_device *pcard; - static int card_count = 1; - int rv; - unsigned long reg_bar_phys_addr; - unsigned long reg_bar_phys_len; - unsigned long dma_bar_phys_addr; - unsigned long dma_bar_phys_len; - u16 regval; - - dev_dbg(&pdev->dev, "kp2000_pcie_probe(pdev = [%p], id = [%p])\n", pdev, id); - - //{ Step 1: Allocate a struct for the pcard - pcard = kzalloc(sizeof(struct kp2000_device), GFP_KERNEL); - if (NULL == pcard){ - dev_err(&pdev->dev, "probe: failed to allocate private card data\n"); - return -ENOMEM; - } - dev_dbg(&pdev->dev, "probe: allocated struct kp2000_device @ %p\n", pcard); - //} - - //{ Step 2: Initialize trivial pcard elements - pcard->card_num = card_count; - card_count++; - scnprintf(pcard->name, 16, "kpcard%d", pcard->card_num); - - mutex_init(&pcard->sem); - lock_card(pcard); - - pcard->pdev = pdev; - pci_set_drvdata(pdev, pcard); - //} - - //{ Step 3: Enable PCI device - err = pci_enable_device(pcard->pdev); - if (err){ - dev_err(&pcard->pdev->dev, "probe: failed to enable PCIE2000 PCIe device (%d)\n", err); - goto out3; - } - //} - - //{ Step 4: Setup the Register BAR - reg_bar_phys_addr = pci_resource_start(pcard->pdev, REG_BAR); - reg_bar_phys_len = pci_resource_len(pcard->pdev, REG_BAR); - - pcard->regs_bar_base = ioremap_nocache(reg_bar_phys_addr, PAGE_SIZE); - if (NULL == pcard->regs_bar_base){ - dev_err(&pcard->pdev->dev, "probe: REG_BAR could not remap memory to virtual space\n"); - err = -ENODEV; - goto out4; - } - dev_dbg(&pcard->pdev->dev, "probe: REG_BAR virt hardware address start [%p]\n", pcard->regs_bar_base); - - err = pci_request_region(pcard->pdev, REG_BAR, KP_DRIVER_NAME_KP2000); - if (err){ - iounmap(pcard->regs_bar_base); - dev_err(&pcard->pdev->dev, "probe: failed to acquire PCI region (%d)\n", err); - err = -ENODEV; - goto out4; - } - - pcard->regs_base_resource.start = reg_bar_phys_addr; - pcard->regs_base_resource.end = reg_bar_phys_addr + reg_bar_phys_len - 1; - pcard->regs_base_resource.flags = IORESOURCE_MEM; - //} - - //{ Step 5: Setup the DMA BAR - dma_bar_phys_addr = pci_resource_start(pcard->pdev, DMA_BAR); - dma_bar_phys_len = pci_resource_len(pcard->pdev, DMA_BAR); - - pcard->dma_bar_base = ioremap_nocache(dma_bar_phys_addr, dma_bar_phys_len); - if (NULL == pcard->dma_bar_base){ - dev_err(&pcard->pdev->dev, "probe: DMA_BAR could not remap memory to virtual space\n"); - err = -ENODEV; - goto out5; - } - dev_dbg(&pcard->pdev->dev, "probe: DMA_BAR virt hardware address start [%p]\n", pcard->dma_bar_base); - - pcard->dma_common_regs = pcard->dma_bar_base + KPC_DMA_COMMON_OFFSET; - - err = pci_request_region(pcard->pdev, DMA_BAR, "kp2000_pcie"); - if (err){ - iounmap(pcard->dma_bar_base); - dev_err(&pcard->pdev->dev, "probe: failed to acquire PCI region (%d)\n", err); - err = -ENODEV; - goto out5; - } - - pcard->dma_base_resource.start = dma_bar_phys_addr; - pcard->dma_base_resource.end = dma_bar_phys_addr + dma_bar_phys_len - 1; - pcard->dma_base_resource.flags = IORESOURCE_MEM; - //} - - //{ Step 6: System Regs - pcard->sysinfo_regs_base = pcard->regs_bar_base; - err = read_system_regs(pcard); - if (err) - goto out6; - - // Disable all "user" interrupts because they're not used yet. - writeq(0xFFFFFFFFFFFFFFFF, pcard->sysinfo_regs_base + REG_INTERRUPT_MASK); - //} - - //{ Step 7: Configure PCI thingies - // let the card master PCIe - pci_set_master(pcard->pdev); - // enable IO and mem if not already done - pci_read_config_word(pcard->pdev, PCI_COMMAND, ®val); - regval |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY); - pci_write_config_word(pcard->pdev, PCI_COMMAND, regval); - - // Clear relaxed ordering bit - pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_RELAX_EN, 0); - - // Set Max_Payload_Size and Max_Read_Request_Size - regval = (0x0) << 5; // Max_Payload_Size = 128 B - pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_PAYLOAD, regval); - regval = (0x0) << 12; // Max_Read_Request_Size = 128 B - pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_READRQ, regval); - - // Enable error reporting for: Correctable Errors, Non-Fatal Errors, Fatal Errors, Unsupported Requests - pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, 0, PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE); - - err = dma_set_mask(PCARD_TO_DEV(pcard), DMA_BIT_MASK(64)); - if (err){ - dev_err(&pcard->pdev->dev, "CANNOT use DMA mask %0llx\n", DMA_BIT_MASK(64)); - goto out7; - } - dev_dbg(&pcard->pdev->dev, "Using DMA mask %0llx\n", dma_get_mask(PCARD_TO_DEV(pcard))); - //} - - //{ Step 8: Configure IRQs - err = pci_enable_msi(pcard->pdev); - if (err < 0) - goto out8a; - - rv = request_irq(pcard->pdev->irq, kp2000_irq_handler, IRQF_SHARED, pcard->name, pcard); - if (rv){ - dev_err(&pcard->pdev->dev, "kp2000_pcie_probe: failed to request_irq: %d\n", rv); - goto out8b; - } - //} - - //{ Step 9: Setup sysfs attributes - err = sysfs_create_files(&(pdev->dev.kobj), kp_attr_list); - if (err){ - dev_err(&pdev->dev, "Failed to add sysfs files: %d\n", err); - goto out9; - } - //} - - //{ Step 10: Setup misc device - pcard->miscdev.minor = MISC_DYNAMIC_MINOR; - pcard->miscdev.fops = &kp2000_fops; - pcard->miscdev.parent = &pcard->pdev->dev; - pcard->miscdev.name = pcard->name; - - err = misc_register(&pcard->miscdev); - if (err){ - dev_err(&pcard->pdev->dev, "kp2000_pcie_probe: misc_register failed: %d\n", err); - goto out10; - } - //} - - //{ Step 11: Probe cores - err = kp2000_probe_cores(pcard); - if (err) - goto out11; - //} - - //{ Step 12: Enable IRQs in HW - SetBackEndControl(pcard->dma_common_regs, KPC_DMA_CARD_IRQ_ENABLE | KPC_DMA_CARD_USER_INTERRUPT_MODE); - //} - - dev_dbg(&pcard->pdev->dev, "kp2000_pcie_probe() complete!\n"); - unlock_card(pcard); - return 0; - - out11: - misc_deregister(&pcard->miscdev); - out10: - sysfs_remove_files(&(pdev->dev.kobj), kp_attr_list); - out9: - free_irq(pcard->pdev->irq, pcard); - out8b: - pci_disable_msi(pcard->pdev); - out8a: - out7: - out6: - iounmap(pcard->dma_bar_base); - pci_release_region(pdev, DMA_BAR); - pcard->dma_bar_base = NULL; - out5: - iounmap(pcard->regs_bar_base); - pci_release_region(pdev, REG_BAR); - pcard->regs_bar_base = NULL; - out4: - pci_disable_device(pcard->pdev); - out3: - unlock_card(pcard); - kfree(pcard); - return err; + int err = 0; + struct kp2000_device *pcard; + int rv; + unsigned long reg_bar_phys_addr; + unsigned long reg_bar_phys_len; + unsigned long dma_bar_phys_addr; + unsigned long dma_bar_phys_len; + u16 regval; + + pcard = kzalloc(sizeof(*pcard), GFP_KERNEL); + if (!pcard) + return -ENOMEM; + dev_dbg(&pdev->dev, "probe: allocated struct kp2000_device @ %p\n", + pcard); + + err = ida_simple_get(&card_num_ida, 1, INT_MAX, GFP_KERNEL); + if (err < 0) { + dev_err(&pdev->dev, "probe: failed to get card number (%d)\n", + err); + goto err_free_pcard; + } + pcard->card_num = err; + scnprintf(pcard->name, 16, "kpcard%u", pcard->card_num); + + mutex_init(&pcard->sem); + mutex_lock(&pcard->sem); + + pcard->pdev = pdev; + pci_set_drvdata(pdev, pcard); + + err = pci_enable_device(pcard->pdev); + if (err) { + dev_err(&pcard->pdev->dev, + "probe: failed to enable PCIE2000 PCIe device (%d)\n", + err); + goto err_remove_ida; + } + + /* Setup the Register BAR */ + reg_bar_phys_addr = pci_resource_start(pcard->pdev, REG_BAR); + reg_bar_phys_len = pci_resource_len(pcard->pdev, REG_BAR); + + pcard->regs_bar_base = ioremap_nocache(reg_bar_phys_addr, PAGE_SIZE); + if (!pcard->regs_bar_base) { + dev_err(&pcard->pdev->dev, + "probe: REG_BAR could not remap memory to virtual space\n"); + err = -ENODEV; + goto err_disable_device; + } + dev_dbg(&pcard->pdev->dev, + "probe: REG_BAR virt hardware address start [%p]\n", + pcard->regs_bar_base); + + err = pci_request_region(pcard->pdev, REG_BAR, KP_DRIVER_NAME_KP2000); + if (err) { + dev_err(&pcard->pdev->dev, + "probe: failed to acquire PCI region (%d)\n", + err); + err = -ENODEV; + goto err_unmap_regs; + } + + pcard->regs_base_resource.start = reg_bar_phys_addr; + pcard->regs_base_resource.end = reg_bar_phys_addr + + reg_bar_phys_len - 1; + pcard->regs_base_resource.flags = IORESOURCE_MEM; + + /* Setup the DMA BAR */ + dma_bar_phys_addr = pci_resource_start(pcard->pdev, DMA_BAR); + dma_bar_phys_len = pci_resource_len(pcard->pdev, DMA_BAR); + + pcard->dma_bar_base = ioremap_nocache(dma_bar_phys_addr, + dma_bar_phys_len); + if (!pcard->dma_bar_base) { + dev_err(&pcard->pdev->dev, + "probe: DMA_BAR could not remap memory to virtual space\n"); + err = -ENODEV; + goto err_release_regs; + } + dev_dbg(&pcard->pdev->dev, + "probe: DMA_BAR virt hardware address start [%p]\n", + pcard->dma_bar_base); + + pcard->dma_common_regs = pcard->dma_bar_base + KPC_DMA_COMMON_OFFSET; + + err = pci_request_region(pcard->pdev, DMA_BAR, "kp2000_pcie"); + if (err) { + dev_err(&pcard->pdev->dev, + "probe: failed to acquire PCI region (%d)\n", err); + err = -ENODEV; + goto err_unmap_dma; + } + + pcard->dma_base_resource.start = dma_bar_phys_addr; + pcard->dma_base_resource.end = dma_bar_phys_addr + + dma_bar_phys_len - 1; + pcard->dma_base_resource.flags = IORESOURCE_MEM; + + /* Read System Regs */ + pcard->sysinfo_regs_base = pcard->regs_bar_base; + err = read_system_regs(pcard); + if (err) + goto err_release_dma; + + // Disable all "user" interrupts because they're not used yet. + writeq(0xFFFFFFFFFFFFFFFF, + pcard->sysinfo_regs_base + REG_INTERRUPT_MASK); + + // let the card master PCIe + pci_set_master(pcard->pdev); + + // enable IO and mem if not already done + pci_read_config_word(pcard->pdev, PCI_COMMAND, ®val); + regval |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY); + pci_write_config_word(pcard->pdev, PCI_COMMAND, regval); + + // Clear relaxed ordering bit + pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, + PCI_EXP_DEVCTL_RELAX_EN, 0); + + // Set Max_Payload_Size and Max_Read_Request_Size + regval = (0x0) << 5; // Max_Payload_Size = 128 B + pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, + PCI_EXP_DEVCTL_PAYLOAD, regval); + regval = (0x0) << 12; // Max_Read_Request_Size = 128 B + pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, + PCI_EXP_DEVCTL_READRQ, regval); + + // Enable error reporting for: Correctable Errors, Non-Fatal Errors, + // Fatal Errors, Unsupported Requests + pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, 0, + PCI_EXP_DEVCTL_CERE | + PCI_EXP_DEVCTL_NFERE | + PCI_EXP_DEVCTL_FERE | + PCI_EXP_DEVCTL_URRE); + + err = dma_set_mask(PCARD_TO_DEV(pcard), DMA_BIT_MASK(64)); + if (err) { + dev_err(&pcard->pdev->dev, + "CANNOT use DMA mask %0llx\n", DMA_BIT_MASK(64)); + goto err_release_dma; + } + dev_dbg(&pcard->pdev->dev, + "Using DMA mask %0llx\n", dma_get_mask(PCARD_TO_DEV(pcard))); + + err = pci_enable_msi(pcard->pdev); + if (err < 0) + goto err_release_dma; + + rv = request_irq(pcard->pdev->irq, kp2000_irq_handler, IRQF_SHARED, + pcard->name, pcard); + if (rv) { + dev_err(&pcard->pdev->dev, + "%s: failed to request_irq: %d\n", __func__, rv); + goto err_disable_msi; + } + + err = sysfs_create_files(&pdev->dev.kobj, kp_attr_list); + if (err) { + dev_err(&pdev->dev, "Failed to add sysfs files: %d\n", err); + goto err_free_irq; + } + + err = kp2000_probe_cores(pcard); + if (err) + goto err_remove_sysfs; + + /* Enable IRQs in HW */ + writel(KPC_DMA_CARD_IRQ_ENABLE | KPC_DMA_CARD_USER_INTERRUPT_MODE, + pcard->dma_common_regs); + + mutex_unlock(&pcard->sem); + return 0; + +err_remove_sysfs: + sysfs_remove_files(&pdev->dev.kobj, kp_attr_list); +err_free_irq: + free_irq(pcard->pdev->irq, pcard); +err_disable_msi: + pci_disable_msi(pcard->pdev); +err_release_dma: + pci_release_region(pdev, DMA_BAR); +err_unmap_dma: + iounmap(pcard->dma_bar_base); +err_release_regs: + pci_release_region(pdev, REG_BAR); +err_unmap_regs: + iounmap(pcard->regs_bar_base); +err_disable_device: + pci_disable_device(pcard->pdev); +err_remove_ida: + mutex_unlock(&pcard->sem); + ida_simple_remove(&card_num_ida, pcard->card_num); +err_free_pcard: + kfree(pcard); + return err; +} + +static void kp2000_pcie_remove(struct pci_dev *pdev) +{ + struct kp2000_device *pcard = pci_get_drvdata(pdev); + + if (!pcard) + return; + + mutex_lock(&pcard->sem); + kp2000_remove_cores(pcard); + mfd_remove_devices(PCARD_TO_DEV(pcard)); + sysfs_remove_files(&pdev->dev.kobj, kp_attr_list); + free_irq(pcard->pdev->irq, pcard); + pci_disable_msi(pcard->pdev); + if (pcard->dma_bar_base) { + iounmap(pcard->dma_bar_base); + pci_release_region(pdev, DMA_BAR); + pcard->dma_bar_base = NULL; + } + if (pcard->regs_bar_base) { + iounmap(pcard->regs_bar_base); + pci_release_region(pdev, REG_BAR); + pcard->regs_bar_base = NULL; + } + pci_disable_device(pcard->pdev); + pci_set_drvdata(pdev, NULL); + mutex_unlock(&pcard->sem); + ida_simple_remove(&card_num_ida, pcard->card_num); + kfree(pcard); } +struct class *kpc_uio_class; +ATTRIBUTE_GROUPS(kpc_uio_class); + +static const struct pci_device_id kp2000_pci_device_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_DAKTRONICS, PCI_DEVICE_ID_DAKTRONICS) }, + { PCI_DEVICE(PCI_VENDOR_ID_DAKTRONICS, PCI_DEVICE_ID_DAKTRONICS_KADOKA_P2KR0) }, + { 0, } +}; +MODULE_DEVICE_TABLE(pci, kp2000_pci_device_ids); + +static struct pci_driver kp2000_driver_inst = { + .name = "kp2000_pcie", + .id_table = kp2000_pci_device_ids, + .probe = kp2000_pcie_probe, + .remove = kp2000_pcie_remove, +}; -void kp2000_pcie_remove(struct pci_dev *pdev) +static int __init kp2000_pcie_init(void) { - struct kp2000_device *pcard = pci_get_drvdata(pdev); - - dev_dbg(&pdev->dev, "kp2000_pcie_remove(pdev=%p)\n", pdev); - - if (pcard == NULL) return; - - lock_card(pcard); - kp2000_remove_cores(pcard); - mfd_remove_devices(PCARD_TO_DEV(pcard)); - misc_deregister(&pcard->miscdev); - sysfs_remove_files(&(pdev->dev.kobj), kp_attr_list); - free_irq(pcard->pdev->irq, pcard); - pci_disable_msi(pcard->pdev); - if (pcard->dma_bar_base != NULL){ - iounmap(pcard->dma_bar_base); - pci_release_region(pdev, DMA_BAR); - pcard->dma_bar_base = NULL; - } - if (pcard->regs_bar_base != NULL){ - iounmap(pcard->regs_bar_base); - pci_release_region(pdev, REG_BAR); - pcard->regs_bar_base = NULL; - } - pci_disable_device(pcard->pdev); - pci_set_drvdata(pdev, NULL); - unlock_card(pcard); - kfree(pcard); + kpc_uio_class = class_create(THIS_MODULE, "kpc_uio"); + if (IS_ERR(kpc_uio_class)) + return PTR_ERR(kpc_uio_class); + + kpc_uio_class->dev_groups = kpc_uio_class_groups; + return pci_register_driver(&kp2000_driver_inst); } +module_init(kp2000_pcie_init); + +static void __exit kp2000_pcie_exit(void) +{ + pci_unregister_driver(&kp2000_driver_inst); + class_destroy(kpc_uio_class); + ida_destroy(&card_num_ida); +} +module_exit(kp2000_pcie_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Lee.Brooke@Daktronics.com, Matt.Sickler@Daktronics.com"); +MODULE_SOFTDEP("pre: uio post: kpc_nwl_dma kpc_i2c kpc_spi"); diff --git a/drivers/staging/kpc2000/kpc2000/dma_common_defs.h b/drivers/staging/kpc2000/kpc2000/dma_common_defs.h index f35e636b1fb7..21450e3d408f 100644 --- a/drivers/staging/kpc2000/kpc2000/dma_common_defs.h +++ b/drivers/staging/kpc2000/kpc2000/dma_common_defs.h @@ -21,23 +21,4 @@ #define KPC_DMA_CARD_S2C_INTERRUPT_STATUS_MASK 0x00FF0000 #define KPC_DMA_CARD_C2S_INTERRUPT_STATUS_MASK 0xFF000000 -static inline void SetBackEndControl(void __iomem *regs, u32 value) -{ - writel(value, regs + 0); -} -static inline u32 GetBackEndStatus(void __iomem *regs) -{ - return readl(regs + 0); -} - -static inline u32 BackEndControlSetClear(void __iomem *regs, u32 set_bits, u32 clear_bits) -{ - u32 start_val = GetBackEndStatus(regs); - u32 new_val = start_val; - new_val &= ~clear_bits; - new_val |= set_bits; - SetBackEndControl(regs, new_val); - return start_val; -} - #endif /* KPC_DMA_COMMON_DEFS_H_ */ diff --git a/drivers/staging/kpc2000/kpc2000/fileops.c b/drivers/staging/kpc2000/kpc2000/fileops.c deleted file mode 100644 index b3b0b763fa1e..000000000000 --- a/drivers/staging/kpc2000/kpc2000/fileops.c +++ /dev/null @@ -1,131 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -#include <linux/module.h> -#include <linux/init.h> -#include <linux/kernel.h> /* printk() */ -#include <linux/slab.h> /* kmalloc() */ -#include <linux/fs.h> /* everything... */ -#include <linux/errno.h> /* error codes */ -#include <linux/types.h> /* size_t */ -#include <linux/cdev.h> -#include <linux/uaccess.h> /* copy_*_user */ -#include <linux/rwsem.h> -#include <linux/idr.h> -#include <linux/io-64-nonatomic-lo-hi.h> -#include <linux/device.h> -#include <linux/sched.h> -#include "pcie.h" -#include "uapi.h" - -int kp2000_cdev_open(struct inode *inode, struct file *filp) -{ - struct kp2000_device *pcard = container_of(filp->private_data, struct kp2000_device, miscdev); - - dev_dbg(&pcard->pdev->dev, "kp2000_cdev_open(filp = [%p], pcard = [%p])\n", filp, pcard); - - filp->private_data = pcard; /* so other methods can access it */ - - return 0; -} - -int kp2000_cdev_close(struct inode *inode, struct file *filp) -{ - struct kp2000_device *pcard = filp->private_data; - - dev_dbg(&pcard->pdev->dev, "kp2000_cdev_close(filp = [%p], pcard = [%p])\n", filp, pcard); - return 0; -} - - -ssize_t kp2000_cdev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) -{ - struct kp2000_device *pcard = filp->private_data; - int cnt = 0; - int ret; -#define BUFF_CNT 1024 - char buff[BUFF_CNT] = {0}; //NOTE: Increase this so it is at least as large as all the scnprintfs. And don't use unbounded strings. "%s" - //NOTE: also, this is a really shitty way to implement the read() call, but it will work for any size 'count'. - - if (WARN(NULL == buf, "kp2000_cdev_read: buf is a NULL pointer!\n")) - return -EINVAL; - - cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "Card ID : 0x%08x\n", pcard->card_id); - cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "Build Version : 0x%08x\n", pcard->build_version); - cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "Build Date : 0x%08x\n", pcard->build_datestamp); - cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "Build Time : 0x%08x\n", pcard->build_timestamp); - cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "Core Table Offset : 0x%08x\n", pcard->core_table_offset); - cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "Core Table Length : 0x%08x\n", pcard->core_table_length); - cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "Hardware Revision : 0x%08x\n", pcard->hardware_revision); - cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "SSID : 0x%016llx\n", pcard->ssid); - cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "DDNA : 0x%016llx\n", pcard->ddna); - cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "IRQ Mask : 0x%016llx\n", readq(pcard->sysinfo_regs_base + REG_INTERRUPT_MASK)); - cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "IRQ Active : 0x%016llx\n", readq(pcard->sysinfo_regs_base + REG_INTERRUPT_ACTIVE)); - cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "CPLD : 0x%016llx\n", readq(pcard->sysinfo_regs_base + REG_CPLD_CONFIG)); - - if (*f_pos >= cnt) - return 0; - - if (count > cnt) - count = cnt; - - ret = copy_to_user(buf, buff + *f_pos, count); - if (ret) - return -EFAULT; - *f_pos += count; - return count; -} - -ssize_t kp2000_cdev_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) -{ - return -EINVAL; -} - -long kp2000_cdev_ioctl(struct file *filp, unsigned int ioctl_num, unsigned long ioctl_param) -{ - struct kp2000_device *pcard = filp->private_data; - - dev_dbg(&pcard->pdev->dev, "kp2000_cdev_ioctl(filp = [%p], ioctl_num = 0x%08x, ioctl_param = 0x%016lx) pcard = [%p]\n", filp, ioctl_num, ioctl_param, pcard); - - switch (ioctl_num){ - case KP2000_IOCTL_GET_CPLD_REG: return readq(pcard->sysinfo_regs_base + REG_CPLD_CONFIG); - case KP2000_IOCTL_GET_PCIE_ERROR_REG: return readq(pcard->sysinfo_regs_base + REG_PCIE_ERROR_COUNT); - - case KP2000_IOCTL_GET_EVERYTHING: { - struct kp2000_regs temp; - int ret; - - memset(&temp, 0, sizeof(temp)); - temp.card_id = pcard->card_id; - temp.build_version = pcard->build_version; - temp.build_datestamp = pcard->build_datestamp; - temp.build_timestamp = pcard->build_timestamp; - temp.hw_rev = pcard->hardware_revision; - temp.ssid = pcard->ssid; - temp.ddna = pcard->ddna; - temp.cpld_reg = readq(pcard->sysinfo_regs_base + REG_CPLD_CONFIG); - - ret = copy_to_user((void*)ioctl_param, (void*)&temp, sizeof(temp)); - if (ret) - return -EFAULT; - - return sizeof(temp); - } - - default: - return -ENOTTY; - } - return -ENOTTY; -} - - -struct file_operations kp2000_fops = { - .owner = THIS_MODULE, - .open = kp2000_cdev_open, - .release = kp2000_cdev_close, - .read = kp2000_cdev_read, - //.write = kp2000_cdev_write, - //.poll = kp2000_cdev_poll, - //.fasync = kp2000_cdev_fasync, - .llseek = noop_llseek, - .unlocked_ioctl = kp2000_cdev_ioctl, -}; - diff --git a/drivers/staging/kpc2000/kpc2000/kp2000_module.c b/drivers/staging/kpc2000/kpc2000/kp2000_module.c deleted file mode 100644 index fa3bd266ba54..000000000000 --- a/drivers/staging/kpc2000/kpc2000/kp2000_module.c +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -#include <linux/init.h> -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/types.h> -#include <linux/export.h> -#include <linux/slab.h> -#include <asm/io.h> -#include <linux/io.h> -#include <linux/mfd/core.h> -#include <linux/platform_device.h> -#include <linux/ioport.h> -#include "pcie.h" - - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Lee.Brooke@Daktronics.com, Matt.Sickler@Daktronics.com"); -MODULE_SOFTDEP("pre: uio post: kpc_nwl_dma kpc_i2c kpc_spi"); - -struct class *kpc_uio_class; -ATTRIBUTE_GROUPS(kpc_uio_class); - -static const struct pci_device_id kp2000_pci_device_ids[] = { - { PCI_DEVICE(PCI_VENDOR_ID_DAKTRONICS, PCI_DEVICE_ID_DAKTRONICS) }, - { PCI_DEVICE(PCI_VENDOR_ID_DAKTRONICS, PCI_DEVICE_ID_DAKTRONICS_KADOKA_P2KR0) }, - { 0, } -}; -MODULE_DEVICE_TABLE(pci, kp2000_pci_device_ids); - -static struct pci_driver kp2000_driver_inst = { - .name = "kp2000_pcie", - .id_table = kp2000_pci_device_ids, - .probe = kp2000_pcie_probe, - .remove = kp2000_pcie_remove -}; - - -static int __init kp2000_pcie_init(void) -{ - kpc_uio_class = class_create(THIS_MODULE, "kpc_uio"); - if (IS_ERR(kpc_uio_class)) - return PTR_ERR(kpc_uio_class); - - kpc_uio_class->dev_groups = kpc_uio_class_groups; - return pci_register_driver(&kp2000_driver_inst); -} -module_init(kp2000_pcie_init); - -static void __exit kp2000_pcie_exit(void) -{ - pci_unregister_driver(&kp2000_driver_inst); - class_destroy(kpc_uio_class); -} -module_exit(kp2000_pcie_exit); diff --git a/drivers/staging/kpc2000/kpc2000/pcie.h b/drivers/staging/kpc2000/kpc2000/pcie.h index 893aebfd1449..cb815c30faa4 100644 --- a/drivers/staging/kpc2000/kpc2000/pcie.h +++ b/drivers/staging/kpc2000/kpc2000/pcie.h @@ -2,7 +2,6 @@ #ifndef KP2000_PCIE_H #define KP2000_PCIE_H #include <linux/types.h> -#include <linux/miscdevice.h> #include <linux/pci.h> #include "../kpc.h" #include "dma_common_defs.h" @@ -27,86 +26,66 @@ * 9 <---------------------- IRQ Active Flags ----------------------> */ -#define REG_WIDTH 8 -#define REG_MAGIC_NUMBER (0 * REG_WIDTH) -#define REG_CARD_ID_AND_BUILD (1 * REG_WIDTH) -#define REG_DATE_AND_TIME_STAMPS (2 * REG_WIDTH) -#define REG_CORE_TABLE_OFFSET (3 * REG_WIDTH) -#define REG_FPGA_SSID (4 * REG_WIDTH) -#define REG_FPGA_HW_ID (5 * REG_WIDTH) -#define REG_FPGA_DDNA (6 * REG_WIDTH) -#define REG_CPLD_CONFIG (7 * REG_WIDTH) -#define REG_INTERRUPT_MASK (8 * REG_WIDTH) -#define REG_INTERRUPT_ACTIVE (9 * REG_WIDTH) -#define REG_PCIE_ERROR_COUNT (10 * REG_WIDTH) +#define REG_WIDTH 8 +#define REG_MAGIC_NUMBER (0 * REG_WIDTH) +#define REG_CARD_ID_AND_BUILD (1 * REG_WIDTH) +#define REG_DATE_AND_TIME_STAMPS (2 * REG_WIDTH) +#define REG_CORE_TABLE_OFFSET (3 * REG_WIDTH) +#define REG_FPGA_SSID (4 * REG_WIDTH) +#define REG_FPGA_HW_ID (5 * REG_WIDTH) +#define REG_FPGA_DDNA (6 * REG_WIDTH) +#define REG_CPLD_CONFIG (7 * REG_WIDTH) +#define REG_INTERRUPT_MASK (8 * REG_WIDTH) +#define REG_INTERRUPT_ACTIVE (9 * REG_WIDTH) +#define REG_PCIE_ERROR_COUNT (10 * REG_WIDTH) -#define KP2000_MAGIC_VALUE 0x196C61482231894D +#define KP2000_MAGIC_VALUE 0x196C61482231894DULL -#define PCI_VENDOR_ID_DAKTRONICS 0x1c33 -#define PCI_DEVICE_ID_DAKTRONICS 0x6021 +#define PCI_VENDOR_ID_DAKTRONICS 0x1c33 +#define PCI_DEVICE_ID_DAKTRONICS 0x6021 -#define DMA_BAR 0 -#define REG_BAR 1 +#define DMA_BAR 0 +#define REG_BAR 1 struct kp2000_device { - struct pci_dev *pdev; - struct miscdevice miscdev; - char name[16]; - - unsigned int card_num; - struct mutex sem; - - void __iomem *sysinfo_regs_base; - void __iomem *regs_bar_base; - struct resource regs_base_resource; - void __iomem *dma_bar_base; - void __iomem *dma_common_regs; - struct resource dma_base_resource; - - // "System Registers" - u32 card_id; - u32 build_version; - u32 build_datestamp; - u32 build_timestamp; - u32 core_table_offset; - u32 core_table_length; - u8 core_table_rev; - u8 hardware_revision; - u64 ssid; - u64 ddna; - - // IRQ stuff - unsigned int irq; - - struct list_head uio_devices_list; + struct pci_dev *pdev; + char name[16]; + + unsigned int card_num; + struct mutex sem; + + void __iomem *sysinfo_regs_base; + void __iomem *regs_bar_base; + struct resource regs_base_resource; + void __iomem *dma_bar_base; + void __iomem *dma_common_regs; + struct resource dma_base_resource; + + // "System Registers" + u32 card_id; + u32 build_version; + u32 build_datestamp; + u32 build_timestamp; + u32 core_table_offset; + u32 core_table_length; + u8 core_table_rev; + u8 hardware_revision; + u64 ssid; + u64 ddna; + + // IRQ stuff + unsigned int irq; + + struct list_head uio_devices_list; }; extern struct class *kpc_uio_class; extern struct attribute *kpc_uio_class_attrs[]; -int kp2000_pcie_probe(struct pci_dev *dev, const struct pci_device_id *id); -void kp2000_pcie_remove(struct pci_dev *pdev); -int kp2000_probe_cores(struct kp2000_device *pcard); -void kp2000_remove_cores(struct kp2000_device *pcard); - -extern struct file_operations kp2000_fops; - +int kp2000_probe_cores(struct kp2000_device *pcard); +void kp2000_remove_cores(struct kp2000_device *pcard); // Define this quick little macro because the expression is used frequently -#define PCARD_TO_DEV(pcard) (&(pcard->pdev->dev)) - -static inline void -lock_card(struct kp2000_device *pcard) -{ - BUG_ON(pcard == NULL); - mutex_lock(&pcard->sem); -} -static inline void -unlock_card(struct kp2000_device *pcard) -{ - BUG_ON(pcard == NULL); - mutex_unlock(&pcard->sem); -} - +#define PCARD_TO_DEV(pcard) (&(pcard->pdev->dev)) #endif /* KP2000_PCIE_H */ diff --git a/drivers/staging/kpc2000/kpc2000/uapi.h b/drivers/staging/kpc2000/kpc2000/uapi.h index ef8008bcd33d..16f37f002dc6 100644 --- a/drivers/staging/kpc2000/kpc2000/uapi.h +++ b/drivers/staging/kpc2000/kpc2000/uapi.h @@ -5,18 +5,18 @@ #include <linux/ioctl.h> struct kp2000_regs { - __u32 card_id; - __u32 build_version; - __u32 build_datestamp; - __u32 build_timestamp; - __u32 hw_rev; - __u64 ssid; - __u64 ddna; - __u64 cpld_reg; + __u32 card_id; + __u32 build_version; + __u32 build_datestamp; + __u32 build_timestamp; + __u32 hw_rev; + __u64 ssid; + __u64 ddna; + __u64 cpld_reg; }; -#define KP2000_IOCTL_GET_CPLD_REG _IOR('k', 9, __u32) -#define KP2000_IOCTL_GET_PCIE_ERROR_REG _IOR('k', 11, __u32) -#define KP2000_IOCTL_GET_EVERYTHING _IOR('k', 8, struct kp2000_regs*) +#define KP2000_IOCTL_GET_CPLD_REG _IOR('k', 9, __u32) +#define KP2000_IOCTL_GET_PCIE_ERROR_REG _IOR('k', 11, __u32) +#define KP2000_IOCTL_GET_EVERYTHING _IOR('k', 8, struct kp2000_regs*) #endif /* KP2000_CDEV_UAPI_H_ */ |