diff options
Diffstat (limited to 'drivers/staging/kpc2000')
-rw-r--r-- | drivers/staging/kpc2000/Kconfig | 59 | ||||
-rw-r--r-- | drivers/staging/kpc2000/Makefile | 6 | ||||
-rw-r--r-- | drivers/staging/kpc2000/TODO | 2 | ||||
-rw-r--r-- | drivers/staging/kpc2000/kpc.h | 23 | ||||
-rw-r--r-- | drivers/staging/kpc2000/kpc2000/Makefile | 4 | ||||
-rw-r--r-- | drivers/staging/kpc2000/kpc2000/cell_probe.c | 548 | ||||
-rw-r--r-- | drivers/staging/kpc2000/kpc2000/core.c | 565 | ||||
-rw-r--r-- | drivers/staging/kpc2000/kpc2000/dma_common_defs.h | 23 | ||||
-rw-r--r-- | drivers/staging/kpc2000/kpc2000/pcie.h | 90 | ||||
-rw-r--r-- | drivers/staging/kpc2000/kpc2000/uapi.h | 22 | ||||
-rw-r--r-- | drivers/staging/kpc2000/kpc2000_i2c.c | 731 | ||||
-rw-r--r-- | drivers/staging/kpc2000/kpc2000_spi.c | 517 | ||||
-rw-r--r-- | drivers/staging/kpc2000/kpc_dma/Makefile | 6 | ||||
-rw-r--r-- | drivers/staging/kpc2000/kpc_dma/dma.c | 270 | ||||
-rw-r--r-- | drivers/staging/kpc2000/kpc_dma/fileops.c | 363 | ||||
-rw-r--r-- | drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.c | 249 | ||||
-rw-r--r-- | drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.h | 222 | ||||
-rw-r--r-- | drivers/staging/kpc2000/kpc_dma/uapi.h | 11 |
18 files changed, 0 insertions, 3711 deletions
diff --git a/drivers/staging/kpc2000/Kconfig b/drivers/staging/kpc2000/Kconfig deleted file mode 100644 index 897965359fcb..000000000000 --- a/drivers/staging/kpc2000/Kconfig +++ /dev/null @@ -1,59 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 - -config KPC2000 - bool "Daktronics KPC Device support" - select MFD_CORE - depends on PCI - depends on UIO - help - Select this if you wish to use the Daktronics KPC PCI devices - - If unsure, say N. - -config KPC2000_CORE - tristate "Daktronics KPC PCI UIO device" - depends on KPC2000 - help - Say Y here if you wish to support the Daktronics KPC PCI - device in UIO mode. - - To compile this driver as a module, choose M here: the module - will be called kpc2000 - - If unsure, say N. - -config KPC2000_SPI - tristate "Daktronics KPC SPI device" - depends on KPC2000 && SPI - help - Say Y here if you wish to support the Daktronics KPC PCI - device in SPI mode. - - To compile this driver as a module, choose M here: the module - will be called kpc2000_spi - - If unsure, say N. - -config KPC2000_I2C - tristate "Daktronics KPC I2C device" - depends on KPC2000 && I2C - help - Say Y here if you wish to support the Daktronics KPC PCI - device in I2C mode. - - To compile this driver as a module, choose M here: the module - will be called kpc2000_i2c - - If unsure, say N. - -config KPC2000_DMA - tristate "Daktronics KPC DMA controller" - depends on KPC2000 - help - Say Y here if you wish to support the Daktronics DMA controller. - - To compile this driver as a module, choose M here: the module - will be called kpc2000_dma - - If unsure, say N. - diff --git a/drivers/staging/kpc2000/Makefile b/drivers/staging/kpc2000/Makefile deleted file mode 100644 index d15ed49807d5..000000000000 --- a/drivers/staging/kpc2000/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 - -obj-$(CONFIG_KPC2000) += kpc2000/ -obj-$(CONFIG_KPC2000_I2C) += kpc2000_i2c.o -obj-$(CONFIG_KPC2000_SPI) += kpc2000_spi.o -obj-$(CONFIG_KPC2000_DMA) += kpc_dma/ diff --git a/drivers/staging/kpc2000/TODO b/drivers/staging/kpc2000/TODO deleted file mode 100644 index 9b5ab37fb3a0..000000000000 --- a/drivers/staging/kpc2000/TODO +++ /dev/null @@ -1,2 +0,0 @@ -- the kpc_spi driver doesn't seem to let multiple transactions (to different instances of the core) happen in parallel... -- The kpc_i2c driver is a hot mess, it should probably be cleaned up a ton. It functions against current hardware though. diff --git a/drivers/staging/kpc2000/kpc.h b/drivers/staging/kpc2000/kpc.h deleted file mode 100644 index a3fc9c9221aa..000000000000 --- a/drivers/staging/kpc2000/kpc.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -#ifndef KPC_H_ -#define KPC_H_ - -/* ***** Driver Names ***** */ -#define KP_DRIVER_NAME_KP2000 "kp2000" -#define KP_DRIVER_NAME_INVALID "kpc_invalid" -#define KP_DRIVER_NAME_DMA_CONTROLLER "kpc_nwl_dma" -#define KP_DRIVER_NAME_UIO "uio_pdrv_genirq" -#define KP_DRIVER_NAME_I2C "kpc_i2c" -#define KP_DRIVER_NAME_SPI "kpc_spi" - -struct kpc_core_device_platdata { - u32 card_id; - u32 build_version; - u32 hardware_revision; - u64 ssid; - u64 ddna; -}; - -#define PCI_DEVICE_ID_DAKTRONICS_KADOKA_P2KR0 0x4b03 - -#endif /* KPC_H_ */ diff --git a/drivers/staging/kpc2000/kpc2000/Makefile b/drivers/staging/kpc2000/kpc2000/Makefile deleted file mode 100644 index c274ad083db6..000000000000 --- a/drivers/staging/kpc2000/kpc2000/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 - -obj-m := kpc2000.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 deleted file mode 100644 index e7e963d62699..000000000000 --- a/drivers/staging/kpc2000/kpc2000/cell_probe.c +++ /dev/null @@ -1,548 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/types.h> -#include <linux/export.h> -#include <linux/slab.h> -#include <linux/io.h> -#include <linux/io-64-nonatomic-lo-hi.h> -#include <linux/mfd/core.h> -#include <linux/platform_device.h> -#include <linux/ioport.h> -#include <linux/uio_driver.h> -#include "pcie.h" - -/* Core (Resource) Table Layout: - * one Resource per record (8 bytes) - * 6 5 4 3 2 1 0 - * 3210987654321098765432109876543210987654321098765432109876543210 - * IIIIIIIIIIII Core Type [up to 4095 types] - * D S2C DMA Present - * DDD S2C DMA Channel Number [up to 8 channels] - * LLLLLLLLLLLLLLLL Register Count (64-bit registers) [up to 65535 registers] - * OOOOOOOOOOOOOOOO Core Offset (in 4kB blocks) [up to 65535 cores] - * D C2S DMA Present - * DDD C2S DMA Channel Number [up to 8 channels] - * II IRQ Count [0 to 3 IRQs per core] - * 1111111000 - * IIIIIII IRQ Base Number [up to 128 IRQs per card] - * ___ Spare - * - */ - -#define KPC_OLD_DMA_CH_NUM(present, channel) \ - ((present) ? (0x8 | ((channel) & 0x7)) : 0) -#define KPC_OLD_S2C_DMA_CH_NUM(cte) \ - KPC_OLD_DMA_CH_NUM(cte.s2c_dma_present, cte.s2c_dma_channel_num) -#define KPC_OLD_C2S_DMA_CH_NUM(cte) \ - KPC_OLD_DMA_CH_NUM(cte.c2s_dma_present, cte.c2s_dma_channel_num) - -#define KP_CORE_ID_INVALID 0 -#define KP_CORE_ID_I2C 3 -#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; -}; - -static -void parse_core_table_entry_v0(struct core_table_entry *cte, const u64 read_val) -{ - cte->type = ((read_val & 0xFFF0000000000000UL) >> 52); - cte->offset = ((read_val & 0x00000000FFFF0000UL) >> 16) * 4096; - cte->length = ((read_val & 0x0000FFFF00000000UL) >> 32) * 8; - cte->s2c_dma_present = ((read_val & 0x0008000000000000UL) >> 51); - cte->s2c_dma_channel_num = ((read_val & 0x0007000000000000UL) >> 48); - cte->c2s_dma_present = ((read_val & 0x0000000000008000UL) >> 15); - cte->c2s_dma_channel_num = ((read_val & 0x0000000000007000UL) >> 12); - cte->irq_count = ((read_val & 0x0000000000000C00UL) >> 10); - cte->irq_base_num = ((read_val & 0x00000000000003F8UL) >> 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 - ); -} - -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; - } -} - -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 = { .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; -}; - -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); - - 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); - -struct attribute *kpc_uio_class_attrs[] = { - &dev_attr_offset.attr, - &dev_attr_size.attr, - &dev_attr_type.attr, - &dev_attr_s2c_dma.attr, - &dev_attr_c2s_dma.attr, - &dev_attr_irq_count.attr, - &dev_attr_irq_base_num.attr, - &dev_attr_core_num.attr, - 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 = 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)) { - /* 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; - - 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; -} - -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(*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; - - // Round up to nearest PAGE_SIZE boundary - kudev->uioinfo.mem[0].size = (cte.length + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); - 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 = { .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; - -err_out: - 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; - - 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); - } -} - diff --git a/drivers/staging/kpc2000/kpc2000/core.c b/drivers/staging/kpc2000/kpc2000/core.c deleted file mode 100644 index 6462a3059fb0..000000000000 --- a/drivers/staging/kpc2000/kpc2000/core.c +++ /dev/null @@ -1,565 +0,0 @@ -// 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 <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> -#include <linux/ioport.h> -#include <linux/io-64-nonatomic-lo-hi.h> -#include <linux/interrupt.h> -#include <linux/workqueue.h> -#include <linux/device.h> -#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 ssid_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - - return sprintf(buf, "%016llx\n", pcard->ssid); -} -static DEVICE_ATTR_RO(ssid); - -static ssize_t ddna_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - - return sprintf(buf, "%016llx\n", pcard->ddna); -} -static DEVICE_ATTR_RO(ddna); - -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 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); - unsigned long wr_val; - int rv; - - rv = kstrtoul(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 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 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; - - 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 - ******************************************************/ - -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 & 0x8000000000000000UL) { - pcard->ssid = read_val; - return; - } - - timeout = jiffies + (HZ * 2); - do { - read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_SSID); - if (read_val & 0x8000000000000000UL) { - 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%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 & 0xFFFFFFFF00000000UL) >> 32; - pcard->build_version = (read_val & 0x00000000FFFFFFFFUL) >> 0; - - read_val = readq(pcard->sysinfo_regs_base + REG_DATE_AND_TIME_STAMPS); - pcard->build_datestamp = (read_val & 0xFFFFFFFF00000000UL) >> 32; - pcard->build_timestamp = (read_val & 0x00000000FFFFFFFFUL) >> 0; - - read_val = readq(pcard->sysinfo_regs_base + REG_CORE_TABLE_OFFSET); - pcard->core_table_length = (read_val & 0xFFFFFFFF00000000UL) >> 32; - pcard->core_table_offset = (read_val & 0x00000000FFFFFFFFUL) >> 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; -} - -static irqreturn_t kp2000_irq_handler(int irq, void *dev_id) -{ - 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; -} - -static int kp2000_pcie_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - int err = 0; - struct kp2000_device *pcard; - 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(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(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(0xFFFFFFFFFFFFFFFFUL, - 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; - - err = request_irq(pcard->pdev->irq, kp2000_irq_handler, IRQF_SHARED, - pcard->name, pcard); - if (err) { - dev_err(&pcard->pdev->dev, - "%s: failed to request_irq: %d\n", __func__, err); - 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, -}; - -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); - 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 deleted file mode 100644 index 613c4898f65e..000000000000 --- a/drivers/staging/kpc2000/kpc2000/dma_common_defs.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -#ifndef KPC_DMA_COMMON_DEFS_H_ -#define KPC_DMA_COMMON_DEFS_H_ - -#define KPC_DMA_COMMON_OFFSET 0x4000 -#define KPC_DMA_S2C_BASE_OFFSET 0x0000 -#define KPC_DMA_C2S_BASE_OFFSET 0x2000 -#define KPC_DMA_ENGINE_SIZE 0x0100 -#define ENGINE_CAP_PRESENT_MASK 0x1 - -#define KPC_DMA_CARD_IRQ_ENABLE BIT(0) -#define KPC_DMA_CARD_IRQ_ACTIVE BIT(1) -#define KPC_DMA_CARD_IRQ_PENDING BIT(2) -#define KPC_DMA_CARD_IRQ_MSI BIT(3) -#define KPC_DMA_CARD_USER_INTERRUPT_MODE BIT(4) -#define KPC_DMA_CARD_USER_INTERRUPT_ACTIVE BIT(5) -#define KPC_DMA_CARD_IRQ_MSIX_MODE BIT(6) -#define KPC_DMA_CARD_MAX_PAYLOAD_SIZE_MASK 0x0700 -#define KPC_DMA_CARD_MAX_READ_REQUEST_SIZE_MASK 0x7000 -#define KPC_DMA_CARD_S2C_INTERRUPT_STATUS_MASK 0x00FF0000 -#define KPC_DMA_CARD_C2S_INTERRUPT_STATUS_MASK 0xFF000000 - -#endif /* KPC_DMA_COMMON_DEFS_H_ */ diff --git a/drivers/staging/kpc2000/kpc2000/pcie.h b/drivers/staging/kpc2000/kpc2000/pcie.h deleted file mode 100644 index f1fc91b4c704..000000000000 --- a/drivers/staging/kpc2000/kpc2000/pcie.h +++ /dev/null @@ -1,90 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -#ifndef KP2000_PCIE_H -#define KP2000_PCIE_H -#include <linux/types.h> -#include <linux/pci.h> -#include "../kpc.h" -#include "dma_common_defs.h" - -/* System Register Map (BAR 1, Start Addr 0) - * - * BAR Size: - * 1048576 (0x100000) bytes = 131072 (0x20000) registers = 256 pages (4K) - * - * 6 5 4 3 2 1 0 - * 3210987654321098765432109876543210987654321098765432109876543210 - * 0 <--------------------------- MAGIC ----------------------------> - * 1 <----------- Card ID ---------><----------- Revision ----------> - * 2 <--------- Date Stamp --------><--------- Time Stamp ----------> - * 3 <-------- Core Tbl Len -------><-------- Core Tbl Offset ------> - * 4 <---------------------------- SSID ----------------------------> - * 5 < HWID > - * 6 <------------------------- FPGA DDNA --------------------------> - * 7 <------------------------ CPLD Config -------------------------> - * 8 <----------------------- IRQ Mask Flags -----------------------> - * 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 KP2000_MAGIC_VALUE 0x196C61482231894DULL - -#define PCI_VENDOR_ID_DAKTRONICS 0x1c33 -#define PCI_DEVICE_ID_DAKTRONICS 0x6021 - -#define DMA_BAR 0 -#define REG_BAR 1 - -struct kp2000_device { - 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_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)) - -#endif /* KP2000_PCIE_H */ diff --git a/drivers/staging/kpc2000/kpc2000/uapi.h b/drivers/staging/kpc2000/kpc2000/uapi.h deleted file mode 100644 index 16f37f002dc6..000000000000 --- a/drivers/staging/kpc2000/kpc2000/uapi.h +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -#ifndef KP2000_CDEV_UAPI_H_ -#define KP2000_CDEV_UAPI_H_ -#include <linux/types.h> -#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; -}; - -#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_ */ diff --git a/drivers/staging/kpc2000/kpc2000_i2c.c b/drivers/staging/kpc2000/kpc2000_i2c.c deleted file mode 100644 index 14f7940fa4fb..000000000000 --- a/drivers/staging/kpc2000/kpc2000_i2c.c +++ /dev/null @@ -1,731 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * KPC2000 i2c driver - * - * Adapted i2c-i801.c for use with Kadoka hardware. - * - * Copyright (C) 1998 - 2002 - * Frodo Looijaard <frodol@dds.nl>, - * Philip Edelbrock <phil@netroedge.com>, - * Mark D. Studebaker <mdsxyz123@yahoo.com> - * Copyright (C) 2007 - 2012 - * Jean Delvare <khali@linux-fr.org> - * Copyright (C) 2010 Intel Corporation - * David Woodhouse <dwmw2@infradead.org> - * Copyright (C) 2014-2018 Daktronics - * Matt Sickler <matt.sickler@daktronics.com>, - * Jordon Hofer <jordon.hofer@daktronics.com> - */ -#include <linux/init.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/io.h> -#include <linux/io-64-nonatomic-lo-hi.h> -#include <linux/export.h> -#include <linux/slab.h> -#include <linux/platform_device.h> -#include <linux/fs.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include "kpc.h" - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Matt.Sickler@Daktronics.com"); - -struct kpc_i2c { - unsigned long smba; - struct i2c_adapter adapter; - unsigned int features; -}; - -/***************************** - *** Part 1 - i2c Handlers *** - *****************************/ - -#define REG_SIZE 8 - -/* I801 SMBus address offsets */ -#define SMBHSTSTS(p) ((0 * REG_SIZE) + (p)->smba) -#define SMBHSTCNT(p) ((2 * REG_SIZE) + (p)->smba) -#define SMBHSTCMD(p) ((3 * REG_SIZE) + (p)->smba) -#define SMBHSTADD(p) ((4 * REG_SIZE) + (p)->smba) -#define SMBHSTDAT0(p) ((5 * REG_SIZE) + (p)->smba) -#define SMBHSTDAT1(p) ((6 * REG_SIZE) + (p)->smba) -#define SMBBLKDAT(p) ((7 * REG_SIZE) + (p)->smba) -#define SMBPEC(p) ((8 * REG_SIZE) + (p)->smba) /* ICH3 and later */ -#define SMBAUXSTS(p) ((12 * REG_SIZE) + (p)->smba) /* ICH4 and later */ -#define SMBAUXCTL(p) ((13 * REG_SIZE) + (p)->smba) /* ICH4 and later */ - -/* PCI Address Constants */ -#define SMBBAR 4 -#define SMBHSTCFG 0x040 - -/* Host configuration bits for SMBHSTCFG */ -#define SMBHSTCFG_HST_EN 1 -#define SMBHSTCFG_SMB_SMI_EN 2 -#define SMBHSTCFG_I2C_EN 4 - -/* Auxiliary control register bits, ICH4+ only */ -#define SMBAUXCTL_CRC 1 -#define SMBAUXCTL_E32B 2 - -/* kill bit for SMBHSTCNT */ -#define SMBHSTCNT_KILL 2 - -/* Other settings */ -#define MAX_RETRIES 400 -#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */ - -/* I801 command constants */ -#define I801_QUICK 0x00 -#define I801_BYTE 0x04 -#define I801_BYTE_DATA 0x08 -#define I801_WORD_DATA 0x0C -#define I801_PROC_CALL 0x10 /* unimplemented */ -#define I801_BLOCK_DATA 0x14 -#define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */ -#define I801_BLOCK_LAST 0x34 -#define I801_I2C_BLOCK_LAST 0x38 /* ICH5 and later */ -#define I801_START 0x40 -#define I801_PEC_EN 0x80 /* ICH3 and later */ - -/* I801 Hosts Status register bits */ -#define SMBHSTSTS_BYTE_DONE 0x80 -#define SMBHSTSTS_INUSE_STS 0x40 -#define SMBHSTSTS_SMBALERT_STS 0x20 -#define SMBHSTSTS_FAILED 0x10 -#define SMBHSTSTS_BUS_ERR 0x08 -#define SMBHSTSTS_DEV_ERR 0x04 -#define SMBHSTSTS_INTR 0x02 -#define SMBHSTSTS_HOST_BUSY 0x01 - -#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_FAILED | \ - SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | SMBHSTSTS_INTR) - -/* Older devices have their ID defined in <linux/pci_ids.h> */ -#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22 -#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22 -/* Patsburg also has three 'Integrated Device Function' SMBus controllers */ -#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0 0x1d70 -#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1 0x1d71 -#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2 0x1d72 -#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS 0x1e22 -#define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330 -#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30 -#define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22 -#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22 - -#define FEATURE_SMBUS_PEC BIT(0) -#define FEATURE_BLOCK_BUFFER BIT(1) -#define FEATURE_BLOCK_PROC BIT(2) -#define FEATURE_I2C_BLOCK_READ BIT(3) -/* Not really a feature, but it's convenient to handle it as such */ -#define FEATURE_IDF BIT(15) - -// FIXME! -#undef inb_p -#define inb_p(a) readq((void __iomem *)a) -#undef outb_p -#define outb_p(d, a) writeq(d, (void __iomem *)a) - -/* Make sure the SMBus host is ready to start transmitting. - * Return 0 if it is, -EBUSY if it is not. - */ -static int i801_check_pre(struct kpc_i2c *priv) -{ - int status; - - status = inb_p(SMBHSTSTS(priv)); - if (status & SMBHSTSTS_HOST_BUSY) { - dev_err(&priv->adapter.dev, - "SMBus is busy, can't use it! (status=%x)\n", status); - return -EBUSY; - } - - status &= STATUS_FLAGS; - if (status) { - outb_p(status, SMBHSTSTS(priv)); - status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS; - if (status) { - dev_err(&priv->adapter.dev, - "Failed clearing status flags (%02x)\n", status); - return -EBUSY; - } - } - return 0; -} - -/* Convert the status register to an error code, and clear it. */ -static int i801_check_post(struct kpc_i2c *priv, int status, int timeout) -{ - int result = 0; - - /* If the SMBus is still busy, we give up */ - if (timeout) { - dev_err(&priv->adapter.dev, "Transaction timeout\n"); - /* try to stop the current command */ - dev_dbg(&priv->adapter.dev, - "Terminating the current operation\n"); - outb_p(inb_p(SMBHSTCNT(priv)) | SMBHSTCNT_KILL, - SMBHSTCNT(priv)); - usleep_range(1000, 2000); - outb_p(inb_p(SMBHSTCNT(priv)) & (~SMBHSTCNT_KILL), - SMBHSTCNT(priv)); - - /* Check if it worked */ - status = inb_p(SMBHSTSTS(priv)); - if ((status & SMBHSTSTS_HOST_BUSY) || - !(status & SMBHSTSTS_FAILED)) - dev_err(&priv->adapter.dev, - "Failed terminating the transaction\n"); - outb_p(STATUS_FLAGS, SMBHSTSTS(priv)); - return -ETIMEDOUT; - } - - if (status & SMBHSTSTS_FAILED) { - result = -EIO; - dev_err(&priv->adapter.dev, "Transaction failed\n"); - } - if (status & SMBHSTSTS_DEV_ERR) { - result = -ENXIO; - dev_dbg(&priv->adapter.dev, "No response\n"); - } - if (status & SMBHSTSTS_BUS_ERR) { - result = -EAGAIN; - dev_dbg(&priv->adapter.dev, "Lost arbitration\n"); - } - - if (result) { - /* Clear error flags */ - outb_p(status & STATUS_FLAGS, SMBHSTSTS(priv)); - status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS; - if (status) - dev_warn(&priv->adapter.dev, - "Failed clearing status flags at end of transaction (%02x)\n", - status); - } - - return result; -} - -static int i801_transaction(struct kpc_i2c *priv, int xact) -{ - int status; - int result; - int timeout = 0; - - result = i801_check_pre(priv); - if (result < 0) - return result; - /* the current contents of SMBHSTCNT can be overwritten, since PEC, - * INTREN, SMBSCMD are passed in xact - */ - outb_p(xact | I801_START, SMBHSTCNT(priv)); - - /* We will always wait for a fraction of a second! */ - do { - usleep_range(250, 500); - status = inb_p(SMBHSTSTS(priv)); - } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_RETRIES)); - - result = i801_check_post(priv, status, timeout > MAX_RETRIES); - if (result < 0) - return result; - - outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv)); - return 0; -} - -/* wait for INTR bit as advised by Intel */ -static void i801_wait_hwpec(struct kpc_i2c *priv) -{ - int timeout = 0; - int status; - - do { - usleep_range(250, 500); - status = inb_p(SMBHSTSTS(priv)); - } while ((!(status & SMBHSTSTS_INTR)) && (timeout++ < MAX_RETRIES)); - - if (timeout > MAX_RETRIES) - dev_dbg(&priv->adapter.dev, "PEC Timeout!\n"); - - outb_p(status, SMBHSTSTS(priv)); -} - -static int i801_block_transaction_by_block(struct kpc_i2c *priv, - union i2c_smbus_data *data, - char read_write, int hwpec) -{ - int i, len; - int status; - - inb_p(SMBHSTCNT(priv)); /* reset the data buffer index */ - - /* Use 32-byte buffer to process this transaction */ - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - outb_p(len, SMBHSTDAT0(priv)); - for (i = 0; i < len; i++) - outb_p(data->block[i + 1], SMBBLKDAT(priv)); - } - - status = i801_transaction(priv, - I801_BLOCK_DATA | ENABLE_INT9 | I801_PEC_EN * hwpec); - if (status) - return status; - - if (read_write == I2C_SMBUS_READ) { - len = inb_p(SMBHSTDAT0(priv)); - if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) - return -EPROTO; - - data->block[0] = len; - for (i = 0; i < len; i++) - data->block[i + 1] = inb_p(SMBBLKDAT(priv)); - } - return 0; -} - -static int i801_block_transaction_byte_by_byte(struct kpc_i2c *priv, - union i2c_smbus_data *data, - char read_write, int command, - int hwpec) -{ - int i, len; - int smbcmd; - int status; - int result; - int timeout; - - result = i801_check_pre(priv); - if (result < 0) - return result; - - len = data->block[0]; - - if (read_write == I2C_SMBUS_WRITE) { - outb_p(len, SMBHSTDAT0(priv)); - outb_p(data->block[1], SMBBLKDAT(priv)); - } - - for (i = 1; i <= len; i++) { - if (i == len && read_write == I2C_SMBUS_READ) { - if (command == I2C_SMBUS_I2C_BLOCK_DATA) - smbcmd = I801_I2C_BLOCK_LAST; - else - smbcmd = I801_BLOCK_LAST; - } else { - if (command == I2C_SMBUS_I2C_BLOCK_DATA && - read_write == I2C_SMBUS_READ) - smbcmd = I801_I2C_BLOCK_DATA; - else - smbcmd = I801_BLOCK_DATA; - } - outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT(priv)); - - if (i == 1) - outb_p(inb(SMBHSTCNT(priv)) | I801_START, - SMBHSTCNT(priv)); - /* We will always wait for a fraction of a second! */ - timeout = 0; - do { - usleep_range(250, 500); - status = inb_p(SMBHSTSTS(priv)); - } while (!(status & SMBHSTSTS_BYTE_DONE) && - (timeout++ < MAX_RETRIES)); - - result = i801_check_post(priv, status, timeout > MAX_RETRIES); - if (result < 0) - return result; - if (i == 1 && read_write == I2C_SMBUS_READ && - command != I2C_SMBUS_I2C_BLOCK_DATA) { - len = inb_p(SMBHSTDAT0(priv)); - if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) { - dev_err(&priv->adapter.dev, - "Illegal SMBus block read size %d\n", - len); - /* Recover */ - while (inb_p(SMBHSTSTS(priv)) & - SMBHSTSTS_HOST_BUSY) - outb_p(SMBHSTSTS_BYTE_DONE, - SMBHSTSTS(priv)); - outb_p(SMBHSTSTS_INTR, - SMBHSTSTS(priv)); - return -EPROTO; - } - data->block[0] = len; - } - - /* Retrieve/store value in SMBBLKDAT */ - if (read_write == I2C_SMBUS_READ) - data->block[i] = inb_p(SMBBLKDAT(priv)); - if (read_write == I2C_SMBUS_WRITE && i + 1 <= len) - outb_p(data->block[i + 1], SMBBLKDAT(priv)); - /* signals SMBBLKDAT ready */ - outb_p(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR, SMBHSTSTS(priv)); - } - - return 0; -} - -static int i801_set_block_buffer_mode(struct kpc_i2c *priv) -{ - outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_E32B, SMBAUXCTL(priv)); - if ((inb_p(SMBAUXCTL(priv)) & SMBAUXCTL_E32B) == 0) - return -EIO; - return 0; -} - -/* Block transaction function */ -static int i801_block_transaction(struct kpc_i2c *priv, - union i2c_smbus_data *data, char read_write, - int command, int hwpec) -{ - int result = 0; - //unsigned char hostc; - - if (command == I2C_SMBUS_I2C_BLOCK_DATA) { - if (read_write == I2C_SMBUS_WRITE) { - /* set I2C_EN bit in configuration register */ - //TODO: Figure out the right thing to do here... - //pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &hostc); - //pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc | SMBHSTCFG_I2C_EN); - } else if (!(priv->features & FEATURE_I2C_BLOCK_READ)) { - dev_err(&priv->adapter.dev, - "I2C block read is unsupported!\n"); - return -EOPNOTSUPP; - } - } - - if (read_write == I2C_SMBUS_WRITE || - command == I2C_SMBUS_I2C_BLOCK_DATA) { - if (data->block[0] < 1) - data->block[0] = 1; - if (data->block[0] > I2C_SMBUS_BLOCK_MAX) - data->block[0] = I2C_SMBUS_BLOCK_MAX; - } else { - data->block[0] = 32; /* max for SMBus block reads */ - } - - /* Experience has shown that the block buffer can only be used for - * SMBus (not I2C) block transactions, even though the datasheet - * doesn't mention this limitation. - */ - if ((priv->features & FEATURE_BLOCK_BUFFER) && - command != I2C_SMBUS_I2C_BLOCK_DATA && - i801_set_block_buffer_mode(priv) == 0) { - result = i801_block_transaction_by_block(priv, data, - read_write, hwpec); - } else { - result = i801_block_transaction_byte_by_byte(priv, data, - read_write, - command, hwpec); - } - - if (result == 0 && hwpec) - i801_wait_hwpec(priv); - if (command == I2C_SMBUS_I2C_BLOCK_DATA && - read_write == I2C_SMBUS_WRITE) { - /* restore saved configuration register value */ - //TODO: Figure out the right thing to do here... - //pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc); - } - return result; -} - -/* Return negative errno on error. */ -static s32 i801_access(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, u8 command, - int size, union i2c_smbus_data *data) -{ - int hwpec; - int block = 0; - int ret, xact = 0; - struct kpc_i2c *priv = i2c_get_adapdata(adap); - - hwpec = (priv->features & FEATURE_SMBUS_PEC) && - (flags & I2C_CLIENT_PEC) && - size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA; - - switch (size) { - case I2C_SMBUS_QUICK: - dev_dbg(&priv->adapter.dev, " [acc] SMBUS_QUICK\n"); - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD(priv)); - - xact = I801_QUICK; - break; - case I2C_SMBUS_BYTE: - dev_dbg(&priv->adapter.dev, " [acc] SMBUS_BYTE\n"); - - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD(priv)); - if (read_write == I2C_SMBUS_WRITE) - outb_p(command, SMBHSTCMD(priv)); - xact = I801_BYTE; - break; - case I2C_SMBUS_BYTE_DATA: - dev_dbg(&priv->adapter.dev, " [acc] SMBUS_BYTE_DATA\n"); - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD(priv)); - - outb_p(command, SMBHSTCMD(priv)); - if (read_write == I2C_SMBUS_WRITE) - outb_p(data->byte, SMBHSTDAT0(priv)); - xact = I801_BYTE_DATA; - break; - case I2C_SMBUS_WORD_DATA: - dev_dbg(&priv->adapter.dev, " [acc] SMBUS_WORD_DATA\n"); - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD(priv)); - - outb_p(command, SMBHSTCMD(priv)); - if (read_write == I2C_SMBUS_WRITE) { - outb_p(data->word & 0xff, SMBHSTDAT0(priv)); - outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv)); - } - xact = I801_WORD_DATA; - break; - case I2C_SMBUS_BLOCK_DATA: - dev_dbg(&priv->adapter.dev, " [acc] SMBUS_BLOCK_DATA\n"); - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD(priv)); - - outb_p(command, SMBHSTCMD(priv)); - block = 1; - break; - case I2C_SMBUS_I2C_BLOCK_DATA: - dev_dbg(&priv->adapter.dev, " [acc] SMBUS_I2C_BLOCK_DATA\n"); - /* NB: page 240 of ICH5 datasheet shows that the R/#W - * bit should be cleared here, even when reading - */ - outb_p((addr & 0x7f) << 1, SMBHSTADD(priv)); - if (read_write == I2C_SMBUS_READ) { - /* NB: page 240 of ICH5 datasheet also shows - * that DATA1 is the cmd field when reading - */ - outb_p(command, SMBHSTDAT1(priv)); - } else { - outb_p(command, SMBHSTCMD(priv)); - } - block = 1; - break; - default: - dev_dbg(&priv->adapter.dev, - " [acc] Unsupported transaction %d\n", size); - return -EOPNOTSUPP; - } - - if (hwpec) { /* enable/disable hardware PEC */ - dev_dbg(&priv->adapter.dev, " [acc] hwpec: yes\n"); - outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_CRC, SMBAUXCTL(priv)); - } else { - dev_dbg(&priv->adapter.dev, " [acc] hwpec: no\n"); - outb_p(inb_p(SMBAUXCTL(priv)) & - (~SMBAUXCTL_CRC), SMBAUXCTL(priv)); - } - - if (block) { - dev_dbg(&priv->adapter.dev, " [acc] block: yes\n"); - ret = i801_block_transaction(priv, data, read_write, size, - hwpec); - } else { - dev_dbg(&priv->adapter.dev, " [acc] block: no\n"); - ret = i801_transaction(priv, xact | ENABLE_INT9); - } - - /* Some BIOSes don't like it when PEC is enabled at reboot or resume - * time, so we forcibly disable it after every transaction. Turn off - * E32B for the same reason. - */ - if (hwpec || block) { - dev_dbg(&priv->adapter.dev, " [acc] hwpec || block\n"); - outb_p(inb_p(SMBAUXCTL(priv)) & ~(SMBAUXCTL_CRC | - SMBAUXCTL_E32B), SMBAUXCTL(priv)); - } - if (block) { - dev_dbg(&priv->adapter.dev, " [acc] block\n"); - return ret; - } - if (ret) { - dev_dbg(&priv->adapter.dev, " [acc] ret %d\n", ret); - return ret; - } - if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK)) { - dev_dbg(&priv->adapter.dev, - " [acc] I2C_SMBUS_WRITE || I801_QUICK -> ret 0\n"); - return 0; - } - - switch (xact & 0x7f) { - case I801_BYTE: /* Result put in SMBHSTDAT0 */ - case I801_BYTE_DATA: - dev_dbg(&priv->adapter.dev, - " [acc] I801_BYTE or I801_BYTE_DATA\n"); - data->byte = inb_p(SMBHSTDAT0(priv)); - break; - case I801_WORD_DATA: - dev_dbg(&priv->adapter.dev, " [acc] I801_WORD_DATA\n"); - data->word = inb_p(SMBHSTDAT0(priv)) + - (inb_p(SMBHSTDAT1(priv)) << 8); - break; - } - return 0; -} - -#define enable_flag(x) (x) -#define disable_flag(x) 0 -#define enable_flag_if(x, cond) ((cond) ? (x) : 0) - -static u32 i801_func(struct i2c_adapter *adapter) -{ - struct kpc_i2c *priv = i2c_get_adapdata(adapter); - - /* original settings - * u32 f = I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - * I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - * I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK | - * ((priv->features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) | - * ((priv->features & FEATURE_I2C_BLOCK_READ) ? - * I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0); - */ - - // http://lxr.free-electrons.com/source/include/uapi/linux/i2c.h#L85 - - u32 f = - enable_flag(I2C_FUNC_I2C) | /* 0x00000001(I enabled this one) */ - disable_flag(I2C_FUNC_10BIT_ADDR) | /* 0x00000002 */ - disable_flag(I2C_FUNC_PROTOCOL_MANGLING) | /* 0x00000004 */ - enable_flag_if(I2C_FUNC_SMBUS_PEC, - priv->features & FEATURE_SMBUS_PEC) | - /* 0x00000008 */ - disable_flag(I2C_FUNC_SMBUS_BLOCK_PROC_CALL) | /* 0x00008000 */ - enable_flag(I2C_FUNC_SMBUS_QUICK) | /* 0x00010000 */ - disable_flag(I2C_FUNC_SMBUS_READ_BYTE) | /* 0x00020000 */ - disable_flag(I2C_FUNC_SMBUS_WRITE_BYTE) | /* 0x00040000 */ - disable_flag(I2C_FUNC_SMBUS_READ_BYTE_DATA) | /* 0x00080000 */ - disable_flag(I2C_FUNC_SMBUS_WRITE_BYTE_DATA) | /* 0x00100000 */ - disable_flag(I2C_FUNC_SMBUS_READ_WORD_DATA) | /* 0x00200000 */ - disable_flag(I2C_FUNC_SMBUS_WRITE_WORD_DATA) | /* 0x00400000 */ - disable_flag(I2C_FUNC_SMBUS_PROC_CALL) | /* 0x00800000 */ - disable_flag(I2C_FUNC_SMBUS_READ_BLOCK_DATA) | /* 0x01000000 */ - disable_flag(I2C_FUNC_SMBUS_WRITE_BLOCK_DATA) | /* 0x02000000 */ - enable_flag_if(I2C_FUNC_SMBUS_READ_I2C_BLOCK, - priv->features & FEATURE_I2C_BLOCK_READ) | - /* 0x04000000 */ - enable_flag(I2C_FUNC_SMBUS_WRITE_I2C_BLOCK) | /* 0x08000000 */ - - enable_flag(I2C_FUNC_SMBUS_BYTE) | /* _READ_BYTE _WRITE_BYTE */ - enable_flag(I2C_FUNC_SMBUS_BYTE_DATA) | /* _READ_BYTE_DATA - * _WRITE_BYTE_DATA - */ - enable_flag(I2C_FUNC_SMBUS_WORD_DATA) | /* _READ_WORD_DATA - * _WRITE_WORD_DATA - */ - enable_flag(I2C_FUNC_SMBUS_BLOCK_DATA) | /* _READ_BLOCK_DATA - * _WRITE_BLOCK_DATA - */ - disable_flag(I2C_FUNC_SMBUS_I2C_BLOCK) | /* _READ_I2C_BLOCK - * _WRITE_I2C_BLOCK - */ - disable_flag(I2C_FUNC_SMBUS_EMUL); /* _QUICK _BYTE - * _BYTE_DATA _WORD_DATA - * _PROC_CALL - * _WRITE_BLOCK_DATA - * _I2C_BLOCK _PEC - */ - return f; -} - -#undef enable_flag -#undef disable_flag -#undef enable_flag_if - -static const struct i2c_algorithm smbus_algorithm = { - .smbus_xfer = i801_access, - .functionality = i801_func, -}; - -/******************************** - *** Part 2 - Driver Handlers *** - ********************************/ -static int kpc_i2c_probe(struct platform_device *pldev) -{ - int err; - struct kpc_i2c *priv; - struct resource *res; - - priv = devm_kzalloc(&pldev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - i2c_set_adapdata(&priv->adapter, priv); - priv->adapter.owner = THIS_MODULE; - priv->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - priv->adapter.algo = &smbus_algorithm; - - res = platform_get_resource(pldev, IORESOURCE_MEM, 0); - if (!res) - return -ENXIO; - - priv->smba = (unsigned long)devm_ioremap(&pldev->dev, - res->start, - resource_size(res)); - if (!priv->smba) - return -ENOMEM; - - platform_set_drvdata(pldev, priv); - - priv->features |= FEATURE_IDF; - priv->features |= FEATURE_I2C_BLOCK_READ; - priv->features |= FEATURE_SMBUS_PEC; - priv->features |= FEATURE_BLOCK_BUFFER; - - //init_MUTEX(&lddata->sem); - - /* set up the sysfs linkage to our parent device */ - priv->adapter.dev.parent = &pldev->dev; - - /* Retry up to 3 times on lost arbitration */ - priv->adapter.retries = 3; - - snprintf(priv->adapter.name, sizeof(priv->adapter.name), - "Fake SMBus I801 adapter"); - - err = i2c_add_adapter(&priv->adapter); - if (err) { - dev_err(&priv->adapter.dev, "Failed to add SMBus adapter\n"); - return err; - } - - return 0; -} - -static int kpc_i2c_remove(struct platform_device *pldev) -{ - struct kpc_i2c *lddev; - - lddev = (struct kpc_i2c *)platform_get_drvdata(pldev); - - i2c_del_adapter(&lddev->adapter); - - //TODO: Figure out the right thing to do here... - //pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg); - //pci_release_region(dev, SMBBAR); - //pci_set_drvdata(dev, NULL); - - //cdev_del(&lddev->cdev); - - return 0; -} - -static struct platform_driver kpc_i2c_driver = { - .probe = kpc_i2c_probe, - .remove = kpc_i2c_remove, - .driver = { - .name = KP_DRIVER_NAME_I2C, - }, -}; - -module_platform_driver(kpc_i2c_driver); diff --git a/drivers/staging/kpc2000/kpc2000_spi.c b/drivers/staging/kpc2000/kpc2000_spi.c deleted file mode 100644 index 16ca18b8aa15..000000000000 --- a/drivers/staging/kpc2000/kpc2000_spi.c +++ /dev/null @@ -1,517 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * KP2000 SPI controller driver - * - * Copyright (C) 2014-2018 Daktronics - * Author: Matt Sickler <matt.sickler@daktronics.com> - * Very loosely based on spi-omap2-mcspi.c - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/io-64-nonatomic-lo-hi.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/delay.h> -#include <linux/platform_device.h> -#include <linux/err.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/slab.h> -#include <linux/pm_runtime.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/gcd.h> -#include <linux/spi/spi.h> -#include <linux/spi/flash.h> -#include <linux/mtd/partitions.h> - -#include "kpc.h" - -static struct mtd_partition p2kr0_spi0_parts[] = { - { .name = "SLOT_0", .size = 7798784, .offset = 0, }, - { .name = "SLOT_1", .size = 7798784, .offset = MTDPART_OFS_NXTBLK}, - { .name = "SLOT_2", .size = 7798784, .offset = MTDPART_OFS_NXTBLK}, - { .name = "SLOT_3", .size = 7798784, .offset = MTDPART_OFS_NXTBLK}, - { .name = "CS0_EXTRA", .size = MTDPART_SIZ_FULL, .offset = MTDPART_OFS_NXTBLK}, -}; - -static struct mtd_partition p2kr0_spi1_parts[] = { - { .name = "SLOT_4", .size = 7798784, .offset = 0, }, - { .name = "SLOT_5", .size = 7798784, .offset = MTDPART_OFS_NXTBLK}, - { .name = "SLOT_6", .size = 7798784, .offset = MTDPART_OFS_NXTBLK}, - { .name = "SLOT_7", .size = 7798784, .offset = MTDPART_OFS_NXTBLK}, - { .name = "CS1_EXTRA", .size = MTDPART_SIZ_FULL, .offset = MTDPART_OFS_NXTBLK}, -}; - -static struct flash_platform_data p2kr0_spi0_pdata = { - .name = "SPI0", - .nr_parts = ARRAY_SIZE(p2kr0_spi0_parts), - .parts = p2kr0_spi0_parts, -}; - -static struct flash_platform_data p2kr0_spi1_pdata = { - .name = "SPI1", - .nr_parts = ARRAY_SIZE(p2kr0_spi1_parts), - .parts = p2kr0_spi1_parts, -}; - -static struct spi_board_info p2kr0_board_info[] = { - { - .modalias = "n25q256a11", - .bus_num = 1, - .chip_select = 0, - .mode = SPI_MODE_0, - .platform_data = &p2kr0_spi0_pdata - }, - { - .modalias = "n25q256a11", - .bus_num = 1, - .chip_select = 1, - .mode = SPI_MODE_0, - .platform_data = &p2kr0_spi1_pdata - }, -}; - -/*************** - * SPI Defines * - ***************/ -#define KP_SPI_REG_CONFIG 0x0 /* 0x00 */ -#define KP_SPI_REG_STATUS 0x1 /* 0x08 */ -#define KP_SPI_REG_FFCTRL 0x2 /* 0x10 */ -#define KP_SPI_REG_TXDATA 0x3 /* 0x18 */ -#define KP_SPI_REG_RXDATA 0x4 /* 0x20 */ - -#define KP_SPI_CLK 48000000 -#define KP_SPI_MAX_FIFODEPTH 64 -#define KP_SPI_MAX_FIFOWCNT 0xFFFF - -#define KP_SPI_REG_CONFIG_TRM_TXRX 0 -#define KP_SPI_REG_CONFIG_TRM_RX 1 -#define KP_SPI_REG_CONFIG_TRM_TX 2 - -#define KP_SPI_REG_STATUS_RXS 0x01 -#define KP_SPI_REG_STATUS_TXS 0x02 -#define KP_SPI_REG_STATUS_EOT 0x04 -#define KP_SPI_REG_STATUS_TXFFE 0x10 -#define KP_SPI_REG_STATUS_TXFFF 0x20 -#define KP_SPI_REG_STATUS_RXFFE 0x40 -#define KP_SPI_REG_STATUS_RXFFF 0x80 - -/****************** - * SPI Structures * - ******************/ -struct kp_spi { - struct spi_master *master; - u64 __iomem *base; - struct device *dev; -}; - -struct kp_spi_controller_state { - void __iomem *base; - s64 conf_cache; -}; - -union kp_spi_config { - /* use this to access individual elements */ - struct __packed spi_config_bitfield { - unsigned int pha : 1; /* spim_clk Phase */ - unsigned int pol : 1; /* spim_clk Polarity */ - unsigned int epol : 1; /* spim_csx Polarity */ - unsigned int dpe : 1; /* Transmission Enable */ - unsigned int wl : 5; /* Word Length */ - unsigned int : 3; - unsigned int trm : 2; /* TxRx Mode */ - unsigned int cs : 4; /* Chip Select */ - unsigned int wcnt : 7; /* Word Count */ - unsigned int ffen : 1; /* FIFO Enable */ - unsigned int spi_en : 1; /* SPI Enable */ - unsigned int : 5; - } bitfield; - /* use this to grab the whole register */ - u32 reg; -}; - -union kp_spi_status { - struct __packed spi_status_bitfield { - unsigned int rx : 1; /* Rx Status */ - unsigned int tx : 1; /* Tx Status */ - unsigned int eo : 1; /* End of Transfer */ - unsigned int : 1; - unsigned int txffe : 1; /* Tx FIFO Empty */ - unsigned int txfff : 1; /* Tx FIFO Full */ - unsigned int rxffe : 1; /* Rx FIFO Empty */ - unsigned int rxfff : 1; /* Rx FIFO Full */ - unsigned int : 24; - } bitfield; - u32 reg; -}; - -union kp_spi_ffctrl { - struct __packed spi_ffctrl_bitfield { - unsigned int ffstart : 1; /* FIFO Start */ - unsigned int : 31; - } bitfield; - u32 reg; -}; - -/*************** - * SPI Helpers * - ***************/ - static inline u64 -kp_spi_read_reg(struct kp_spi_controller_state *cs, int idx) -{ - u64 __iomem *addr = cs->base; - - addr += idx; - if ((idx == KP_SPI_REG_CONFIG) && (cs->conf_cache >= 0)) - return cs->conf_cache; - - return readq(addr); -} - - static inline void -kp_spi_write_reg(struct kp_spi_controller_state *cs, int idx, u64 val) -{ - u64 __iomem *addr = cs->base; - - addr += idx; - writeq(val, addr); - if (idx == KP_SPI_REG_CONFIG) - cs->conf_cache = val; -} - - static int -kp_spi_wait_for_reg_bit(struct kp_spi_controller_state *cs, int idx, - unsigned long bit) -{ - unsigned long timeout; - - timeout = jiffies + msecs_to_jiffies(1000); - while (!(kp_spi_read_reg(cs, idx) & bit)) { - if (time_after(jiffies, timeout)) { - if (!(kp_spi_read_reg(cs, idx) & bit)) - return -ETIMEDOUT; - else - return 0; - } - cpu_relax(); - } - return 0; -} - - static unsigned -kp_spi_txrx_pio(struct spi_device *spidev, struct spi_transfer *transfer) -{ - struct kp_spi_controller_state *cs = spidev->controller_state; - unsigned int count = transfer->len; - unsigned int c = count; - - int i; - int res; - u8 *rx = transfer->rx_buf; - const u8 *tx = transfer->tx_buf; - int processed = 0; - - if (tx) { - for (i = 0 ; i < c ; i++) { - char val = *tx++; - - res = kp_spi_wait_for_reg_bit(cs, KP_SPI_REG_STATUS, - KP_SPI_REG_STATUS_TXS); - if (res < 0) - goto out; - - kp_spi_write_reg(cs, KP_SPI_REG_TXDATA, val); - processed++; - } - } else if (rx) { - for (i = 0 ; i < c ; i++) { - char test = 0; - - kp_spi_write_reg(cs, KP_SPI_REG_TXDATA, 0x00); - res = kp_spi_wait_for_reg_bit(cs, KP_SPI_REG_STATUS, - KP_SPI_REG_STATUS_RXS); - if (res < 0) - goto out; - - test = kp_spi_read_reg(cs, KP_SPI_REG_RXDATA); - *rx++ = test; - processed++; - } - } - - if (kp_spi_wait_for_reg_bit(cs, KP_SPI_REG_STATUS, - KP_SPI_REG_STATUS_EOT) < 0) { - //TODO: Figure out how to abort transaction?? - //Ths has never happened in practice though... - } - -out: - return processed; -} - -/***************** - * SPI Functions * - *****************/ - static int -kp_spi_setup(struct spi_device *spidev) -{ - union kp_spi_config sc; - struct kp_spi *kpspi = spi_master_get_devdata(spidev->master); - struct kp_spi_controller_state *cs; - - /* setup controller state */ - cs = spidev->controller_state; - if (!cs) { - cs = kzalloc(sizeof(*cs), GFP_KERNEL); - if (!cs) - return -ENOMEM; - cs->base = kpspi->base; - cs->conf_cache = -1; - spidev->controller_state = cs; - } - - /* set config register */ - sc.bitfield.wl = spidev->bits_per_word - 1; - sc.bitfield.cs = spidev->chip_select; - sc.bitfield.spi_en = 0; - sc.bitfield.trm = 0; - sc.bitfield.ffen = 0; - kp_spi_write_reg(spidev->controller_state, KP_SPI_REG_CONFIG, sc.reg); - return 0; -} - - static int -kp_spi_transfer_one_message(struct spi_master *master, struct spi_message *m) -{ - struct kp_spi_controller_state *cs; - struct spi_device *spidev; - struct kp_spi *kpspi; - struct spi_transfer *transfer; - union kp_spi_config sc; - int status = 0; - - spidev = m->spi; - kpspi = spi_master_get_devdata(master); - m->actual_length = 0; - m->status = 0; - - cs = spidev->controller_state; - - /* reject invalid messages and transfers */ - if (list_empty(&m->transfers)) - return -EINVAL; - - /* validate input */ - list_for_each_entry(transfer, &m->transfers, transfer_list) { - const void *tx_buf = transfer->tx_buf; - void *rx_buf = transfer->rx_buf; - unsigned int len = transfer->len; - - if (transfer->speed_hz > KP_SPI_CLK || - (len && !(rx_buf || tx_buf))) { - dev_dbg(kpspi->dev, " transfer: %d Hz, %d %s%s, %d bpw\n", - transfer->speed_hz, - len, - tx_buf ? "tx" : "", - rx_buf ? "rx" : "", - transfer->bits_per_word); - dev_dbg(kpspi->dev, " transfer -EINVAL\n"); - return -EINVAL; - } - if (transfer->speed_hz && - transfer->speed_hz < (KP_SPI_CLK >> 15)) { - dev_dbg(kpspi->dev, "speed_hz %d below minimum %d Hz\n", - transfer->speed_hz, - KP_SPI_CLK >> 15); - dev_dbg(kpspi->dev, " speed_hz -EINVAL\n"); - return -EINVAL; - } - } - - /* assert chip select to start the sequence*/ - sc.reg = kp_spi_read_reg(cs, KP_SPI_REG_CONFIG); - sc.bitfield.spi_en = 1; - kp_spi_write_reg(cs, KP_SPI_REG_CONFIG, sc.reg); - - /* work */ - if (kp_spi_wait_for_reg_bit(cs, KP_SPI_REG_STATUS, - KP_SPI_REG_STATUS_EOT) < 0) { - dev_info(kpspi->dev, "EOT timed out\n"); - goto out; - } - - /* do the transfers for this message */ - list_for_each_entry(transfer, &m->transfers, transfer_list) { - if (!transfer->tx_buf && !transfer->rx_buf && - transfer->len) { - status = -EINVAL; - goto error; - } - - /* transfer */ - if (transfer->len) { - unsigned int word_len = spidev->bits_per_word; - unsigned int count; - - /* set up the transfer... */ - sc.reg = kp_spi_read_reg(cs, KP_SPI_REG_CONFIG); - - /* ...direction */ - if (transfer->tx_buf) - sc.bitfield.trm = KP_SPI_REG_CONFIG_TRM_TX; - else if (transfer->rx_buf) - sc.bitfield.trm = KP_SPI_REG_CONFIG_TRM_RX; - - /* ...word length */ - if (transfer->bits_per_word) - word_len = transfer->bits_per_word; - sc.bitfield.wl = word_len - 1; - - /* ...chip select */ - sc.bitfield.cs = spidev->chip_select; - - /* ...and write the new settings */ - kp_spi_write_reg(cs, KP_SPI_REG_CONFIG, sc.reg); - - /* do the transfer */ - count = kp_spi_txrx_pio(spidev, transfer); - m->actual_length += count; - - if (count != transfer->len) { - status = -EIO; - goto error; - } - } - - if (transfer->delay.value) - ndelay(spi_delay_to_ns(&transfer->delay, transfer)); - } - - /* de-assert chip select to end the sequence */ - sc.reg = kp_spi_read_reg(cs, KP_SPI_REG_CONFIG); - sc.bitfield.spi_en = 0; - kp_spi_write_reg(cs, KP_SPI_REG_CONFIG, sc.reg); - -out: - /* done work */ - spi_finalize_current_message(master); - return 0; - -error: - m->status = status; - return status; -} - - static void -kp_spi_cleanup(struct spi_device *spidev) -{ - struct kp_spi_controller_state *cs = spidev->controller_state; - - kfree(cs); -} - -/****************** - * Probe / Remove * - ******************/ - static int -kp_spi_probe(struct platform_device *pldev) -{ - struct kpc_core_device_platdata *drvdata; - struct spi_master *master; - struct kp_spi *kpspi; - struct resource *r; - int status = 0; - int i; - - drvdata = pldev->dev.platform_data; - if (!drvdata) { - dev_err(&pldev->dev, "%s: platform_data is NULL\n", __func__); - return -ENODEV; - } - - master = spi_alloc_master(&pldev->dev, sizeof(struct kp_spi)); - if (!master) { - dev_err(&pldev->dev, "%s: master allocation failed\n", - __func__); - return -ENOMEM; - } - - /* set up the spi functions */ - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; - master->bits_per_word_mask = (unsigned int)SPI_BPW_RANGE_MASK(4, 32); - master->setup = kp_spi_setup; - master->transfer_one_message = kp_spi_transfer_one_message; - master->cleanup = kp_spi_cleanup; - - platform_set_drvdata(pldev, master); - - kpspi = spi_master_get_devdata(master); - kpspi->master = master; - kpspi->dev = &pldev->dev; - - master->num_chipselect = 4; - if (pldev->id != -1) - master->bus_num = pldev->id; - - r = platform_get_resource(pldev, IORESOURCE_MEM, 0); - if (!r) { - dev_err(&pldev->dev, "%s: Unable to get platform resources\n", - __func__); - status = -ENODEV; - goto free_master; - } - - kpspi->base = devm_ioremap(&pldev->dev, r->start, - resource_size(r)); - - status = spi_register_master(master); - if (status < 0) { - dev_err(&pldev->dev, "Unable to register SPI device\n"); - goto free_master; - } - - /* register the slave boards */ -#define NEW_SPI_DEVICE_FROM_BOARD_INFO_TABLE(table) \ - for (i = 0 ; i < ARRAY_SIZE(table) ; i++) { \ - spi_new_device(master, &table[i]); \ - } - - switch ((drvdata->card_id & 0xFFFF0000) >> 16) { - case PCI_DEVICE_ID_DAKTRONICS_KADOKA_P2KR0: - NEW_SPI_DEVICE_FROM_BOARD_INFO_TABLE(p2kr0_board_info); - break; - default: - dev_err(&pldev->dev, "Unknown hardware, cant know what partition table to use!\n"); - goto free_master; - } - - return status; - -free_master: - spi_master_put(master); - return status; -} - - static int -kp_spi_remove(struct platform_device *pldev) -{ - struct spi_master *master = platform_get_drvdata(pldev); - - spi_unregister_master(master); - return 0; -} - -static struct platform_driver kp_spi_driver = { - .driver = { - .name = KP_DRIVER_NAME_SPI, - }, - .probe = kp_spi_probe, - .remove = kp_spi_remove, -}; - -module_platform_driver(kp_spi_driver); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:kp_spi"); diff --git a/drivers/staging/kpc2000/kpc_dma/Makefile b/drivers/staging/kpc2000/kpc_dma/Makefile deleted file mode 100644 index fe5db532c8c8..000000000000 --- a/drivers/staging/kpc2000/kpc_dma/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 - -obj-m := kpc_dma.o -kpc_dma-objs += dma.o -kpc_dma-objs += fileops.o -kpc_dma-objs += kpc_dma_driver.o diff --git a/drivers/staging/kpc2000/kpc_dma/dma.c b/drivers/staging/kpc2000/kpc_dma/dma.c deleted file mode 100644 index e169ac609ba4..000000000000 --- a/drivers/staging/kpc2000/kpc_dma/dma.c +++ /dev/null @@ -1,270 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -#include <linux/init.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/io.h> -#include <linux/export.h> -#include <linux/slab.h> -#include <linux/platform_device.h> -#include <linux/fs.h> -#include <linux/rwsem.h> -#include "kpc_dma_driver.h" - -/********** IRQ Handlers **********/ -static -irqreturn_t ndd_irq_handler(int irq, void *dev_id) -{ - struct kpc_dma_device *ldev = (struct kpc_dma_device *)dev_id; - - if ((GetEngineControl(ldev) & ENG_CTL_IRQ_ACTIVE) || - (ldev->desc_completed->MyDMAAddr != GetEngineCompletePtr(ldev))) - schedule_work(&ldev->irq_work); - - return IRQ_HANDLED; -} - -static -void ndd_irq_worker(struct work_struct *ws) -{ - struct kpc_dma_descriptor *cur; - struct kpc_dma_device *eng = container_of(ws, struct kpc_dma_device, irq_work); - - lock_engine(eng); - - if (GetEngineCompletePtr(eng) == 0) - goto out; - - if (eng->desc_completed->MyDMAAddr == GetEngineCompletePtr(eng)) - goto out; - - cur = eng->desc_completed; - do { - cur = cur->Next; - dev_dbg(&eng->pldev->dev, "Handling completed descriptor %p (acd = %p)\n", - cur, cur->acd); - BUG_ON(cur == eng->desc_next); // Ordering failure. - - if (cur->DescControlFlags & DMA_DESC_CTL_SOP) { - eng->accumulated_bytes = 0; - eng->accumulated_flags = 0; - } - - eng->accumulated_bytes += cur->DescByteCount; - if (cur->DescStatusFlags & DMA_DESC_STS_ERROR) - eng->accumulated_flags |= ACD_FLAG_ENG_ACCUM_ERROR; - - if (cur->DescStatusFlags & DMA_DESC_STS_SHORT) - eng->accumulated_flags |= ACD_FLAG_ENG_ACCUM_SHORT; - - if (cur->DescControlFlags & DMA_DESC_CTL_EOP) { - if (cur->acd) - transfer_complete_cb(cur->acd, eng->accumulated_bytes, - eng->accumulated_flags | ACD_FLAG_DONE); - } - - eng->desc_completed = cur; - } while (cur->MyDMAAddr != GetEngineCompletePtr(eng)); - - out: - SetClearEngineControl(eng, ENG_CTL_IRQ_ACTIVE, 0); - - unlock_engine(eng); -} - -/********** DMA Engine Init/Teardown **********/ -void start_dma_engine(struct kpc_dma_device *eng) -{ - eng->desc_next = eng->desc_pool_first; - eng->desc_completed = eng->desc_pool_last; - - // Setup the engine pointer registers - SetEngineNextPtr(eng, eng->desc_pool_first); - SetEngineSWPtr(eng, eng->desc_pool_first); - ClearEngineCompletePtr(eng); - - WriteEngineControl(eng, ENG_CTL_DMA_ENABLE | ENG_CTL_IRQ_ENABLE); -} - -int setup_dma_engine(struct kpc_dma_device *eng, u32 desc_cnt) -{ - u32 caps; - struct kpc_dma_descriptor *cur; - struct kpc_dma_descriptor *next; - dma_addr_t next_handle; - dma_addr_t head_handle; - unsigned int i; - int rv; - - caps = GetEngineCapabilities(eng); - - if (WARN(!(caps & ENG_CAP_PRESENT), "%s() called for DMA Engine at %p which isn't present in hardware!\n", __func__, eng)) - return -ENXIO; - - if (caps & ENG_CAP_DIRECTION) - eng->dir = DMA_FROM_DEVICE; - else - eng->dir = DMA_TO_DEVICE; - - eng->desc_pool_cnt = desc_cnt; - eng->desc_pool = dma_pool_create("KPC DMA Descriptors", &eng->pldev->dev, - sizeof(struct kpc_dma_descriptor), - DMA_DESC_ALIGNMENT, 4096); - - eng->desc_pool_first = dma_pool_alloc(eng->desc_pool, GFP_KERNEL | GFP_DMA, &head_handle); - if (!eng->desc_pool_first) { - dev_err(&eng->pldev->dev, "%s: couldn't allocate desc_pool_first!\n", __func__); - dma_pool_destroy(eng->desc_pool); - return -ENOMEM; - } - - eng->desc_pool_first->MyDMAAddr = head_handle; - clear_desc(eng->desc_pool_first); - - cur = eng->desc_pool_first; - for (i = 1 ; i < eng->desc_pool_cnt ; i++) { - next = dma_pool_alloc(eng->desc_pool, GFP_KERNEL | GFP_DMA, &next_handle); - if (!next) - goto done_alloc; - - clear_desc(next); - next->MyDMAAddr = next_handle; - - cur->DescNextDescPtr = next_handle; - cur->Next = next; - cur = next; - } - - done_alloc: - // Link the last descriptor back to the first, so it's a circular linked list - cur->Next = eng->desc_pool_first; - cur->DescNextDescPtr = eng->desc_pool_first->MyDMAAddr; - - eng->desc_pool_last = cur; - eng->desc_completed = eng->desc_pool_last; - - // Setup work queue - INIT_WORK(&eng->irq_work, ndd_irq_worker); - - // Grab IRQ line - rv = request_irq(eng->irq, ndd_irq_handler, IRQF_SHARED, - KP_DRIVER_NAME_DMA_CONTROLLER, eng); - if (rv) { - dev_err(&eng->pldev->dev, "%s: failed to request_irq: %d\n", __func__, rv); - return rv; - } - - // Turn on the engine! - start_dma_engine(eng); - unlock_engine(eng); - - return 0; -} - -void stop_dma_engine(struct kpc_dma_device *eng) -{ - unsigned long timeout; - - // Disable the descriptor engine - WriteEngineControl(eng, 0); - - // Wait for descriptor engine to finish current operaion - timeout = jiffies + (HZ / 2); - while (GetEngineControl(eng) & ENG_CTL_DMA_RUNNING) { - if (time_after(jiffies, timeout)) { - dev_crit(&eng->pldev->dev, "DMA_RUNNING still asserted!\n"); - break; - } - } - - // Request a reset - WriteEngineControl(eng, ENG_CTL_DMA_RESET_REQUEST); - - // Wait for reset request to be processed - timeout = jiffies + (HZ / 2); - while (GetEngineControl(eng) & (ENG_CTL_DMA_RUNNING | ENG_CTL_DMA_RESET_REQUEST)) { - if (time_after(jiffies, timeout)) { - dev_crit(&eng->pldev->dev, "ENG_CTL_DMA_RESET_REQUEST still asserted!\n"); - break; - } - } - - // Request a reset - WriteEngineControl(eng, ENG_CTL_DMA_RESET); - - // And wait for reset to complete - timeout = jiffies + (HZ / 2); - while (GetEngineControl(eng) & ENG_CTL_DMA_RESET) { - if (time_after(jiffies, timeout)) { - dev_crit(&eng->pldev->dev, "DMA_RESET still asserted!\n"); - break; - } - } - - // Clear any persistent bits just to make sure there is no residue from the reset - SetClearEngineControl(eng, (ENG_CTL_IRQ_ACTIVE | ENG_CTL_DESC_COMPLETE | - ENG_CTL_DESC_ALIGN_ERR | ENG_CTL_DESC_FETCH_ERR | - ENG_CTL_SW_ABORT_ERR | ENG_CTL_DESC_CHAIN_END | - ENG_CTL_DMA_WAITING_PERSIST), 0); - - // Reset performance counters - - // Completely disable the engine - WriteEngineControl(eng, 0); -} - -void destroy_dma_engine(struct kpc_dma_device *eng) -{ - struct kpc_dma_descriptor *cur; - dma_addr_t cur_handle; - unsigned int i; - - stop_dma_engine(eng); - - cur = eng->desc_pool_first; - cur_handle = eng->desc_pool_first->MyDMAAddr; - - for (i = 0 ; i < eng->desc_pool_cnt ; i++) { - struct kpc_dma_descriptor *next = cur->Next; - dma_addr_t next_handle = cur->DescNextDescPtr; - - dma_pool_free(eng->desc_pool, cur, cur_handle); - cur_handle = next_handle; - cur = next; - } - - dma_pool_destroy(eng->desc_pool); - - free_irq(eng->irq, eng); -} - -/********** Helper Functions **********/ -int count_descriptors_available(struct kpc_dma_device *eng) -{ - u32 count = 0; - struct kpc_dma_descriptor *cur = eng->desc_next; - - while (cur != eng->desc_completed) { - BUG_ON(!cur); - count++; - cur = cur->Next; - } - return count; -} - -void clear_desc(struct kpc_dma_descriptor *desc) -{ - if (!desc) - return; - desc->DescByteCount = 0; - desc->DescStatusErrorFlags = 0; - desc->DescStatusFlags = 0; - desc->DescUserControlLS = 0; - desc->DescUserControlMS = 0; - desc->DescCardAddrLS = 0; - desc->DescBufferByteCount = 0; - desc->DescCardAddrMS = 0; - desc->DescControlFlags = 0; - desc->DescSystemAddrLS = 0; - desc->DescSystemAddrMS = 0; - desc->acd = NULL; -} diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c deleted file mode 100644 index 10dcd6646b01..000000000000 --- a/drivers/staging/kpc2000/kpc_dma/fileops.c +++ /dev/null @@ -1,363 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -#include <linux/module.h> -#include <linux/init.h> -#include <linux/mm.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/highmem.h> -#include <linux/pagemap.h> -#include "kpc_dma_driver.h" -#include "uapi.h" - -/********** Helper Functions **********/ -static inline -unsigned int count_pages(unsigned long iov_base, size_t iov_len) -{ - unsigned long first = (iov_base & PAGE_MASK) >> PAGE_SHIFT; - unsigned long last = ((iov_base + iov_len - 1) & PAGE_MASK) >> PAGE_SHIFT; - - return last - first + 1; -} - -static inline -unsigned int count_parts_for_sge(struct scatterlist *sg) -{ - return DIV_ROUND_UP(sg_dma_len(sg), 0x80000); -} - -/********** Transfer Helpers **********/ -static int kpc_dma_transfer(struct dev_private_data *priv, - unsigned long iov_base, size_t iov_len) -{ - unsigned int i = 0; - int rv = 0, nr_pages = 0; - struct kpc_dma_device *ldev; - struct aio_cb_data *acd; - DECLARE_COMPLETION_ONSTACK(done); - u32 desc_needed = 0; - struct scatterlist *sg; - u32 num_descrs_avail; - struct kpc_dma_descriptor *desc; - unsigned int pcnt; - unsigned int p; - u64 card_addr; - u64 dma_addr; - u64 user_ctl; - - ldev = priv->ldev; - - acd = kzalloc(sizeof(*acd), GFP_KERNEL); - if (!acd) { - dev_err(&priv->ldev->pldev->dev, "Couldn't kmalloc space for the aio data\n"); - return -ENOMEM; - } - memset(acd, 0x66, sizeof(struct aio_cb_data)); - - acd->priv = priv; - acd->ldev = priv->ldev; - acd->cpl = &done; - acd->flags = 0; - acd->len = iov_len; - acd->page_count = count_pages(iov_base, iov_len); - - // Allocate an array of page pointers - acd->user_pages = kcalloc(acd->page_count, sizeof(struct page *), - GFP_KERNEL); - if (!acd->user_pages) { - dev_err(&priv->ldev->pldev->dev, "Couldn't kmalloc space for the page pointers\n"); - rv = -ENOMEM; - goto err_alloc_userpages; - } - - // Lock the user buffer pages in memory, and hold on to the page pointers (for the sglist) - mmap_read_lock(current->mm); /* get memory map semaphore */ - rv = pin_user_pages(iov_base, acd->page_count, FOLL_TOUCH | FOLL_WRITE, - acd->user_pages, NULL); - mmap_read_unlock(current->mm); /* release the semaphore */ - if (rv != acd->page_count) { - nr_pages = rv; - if (rv > 0) - rv = -EFAULT; - - dev_err(&priv->ldev->pldev->dev, "Couldn't pin_user_pages (%d)\n", rv); - goto unpin_pages; - } - nr_pages = acd->page_count; - - // Allocate and setup the sg_table (scatterlist entries) - rv = sg_alloc_table_from_pages(&acd->sgt, acd->user_pages, acd->page_count, - iov_base & (PAGE_SIZE - 1), iov_len, GFP_KERNEL); - if (rv) { - dev_err(&priv->ldev->pldev->dev, "Couldn't alloc sg_table (%d)\n", rv); - goto unpin_pages; - } - - // Setup the DMA mapping for all the sg entries - acd->mapped_entry_count = dma_map_sg(&ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, - ldev->dir); - if (acd->mapped_entry_count <= 0) { - dev_err(&priv->ldev->pldev->dev, "Couldn't dma_map_sg (%d)\n", - acd->mapped_entry_count); - goto free_table; - } - - // Calculate how many descriptors are actually needed for this transfer. - for_each_sg(acd->sgt.sgl, sg, acd->mapped_entry_count, i) { - desc_needed += count_parts_for_sge(sg); - } - - lock_engine(ldev); - - // Figoure out how many descriptors are available and return an error if there aren't enough - num_descrs_avail = count_descriptors_available(ldev); - dev_dbg(&priv->ldev->pldev->dev, - " mapped_entry_count = %d num_descrs_needed = %d num_descrs_avail = %d\n", - acd->mapped_entry_count, desc_needed, num_descrs_avail); - - if (desc_needed >= ldev->desc_pool_cnt) { - dev_warn(&priv->ldev->pldev->dev, - " mapped_entry_count = %d num_descrs_needed = %d num_descrs_avail = %d TOO MANY to ever complete!\n", - acd->mapped_entry_count, desc_needed, num_descrs_avail); - rv = -EAGAIN; - goto err_descr_too_many; - } - if (desc_needed > num_descrs_avail) { - dev_warn(&priv->ldev->pldev->dev, - " mapped_entry_count = %d num_descrs_needed = %d num_descrs_avail = %d Too many to complete right now.\n", - acd->mapped_entry_count, desc_needed, num_descrs_avail); - rv = -EMSGSIZE; - goto err_descr_too_many; - } - - // Loop through all the sg table entries and fill out a descriptor for each one. - desc = ldev->desc_next; - card_addr = acd->priv->card_addr; - for_each_sg(acd->sgt.sgl, sg, acd->mapped_entry_count, i) { - pcnt = count_parts_for_sge(sg); - for (p = 0 ; p < pcnt ; p++) { - // Fill out the descriptor - BUG_ON(!desc); - clear_desc(desc); - if (p != pcnt - 1) - desc->DescByteCount = 0x80000; - else - desc->DescByteCount = sg_dma_len(sg) - (p * 0x80000); - - desc->DescBufferByteCount = desc->DescByteCount; - - desc->DescControlFlags |= DMA_DESC_CTL_IRQONERR; - if (i == 0 && p == 0) - desc->DescControlFlags |= DMA_DESC_CTL_SOP; - if (i == acd->mapped_entry_count - 1 && p == pcnt - 1) - desc->DescControlFlags |= DMA_DESC_CTL_EOP | DMA_DESC_CTL_IRQONDONE; - - desc->DescCardAddrLS = (card_addr & 0xFFFFFFFF); - desc->DescCardAddrMS = (card_addr >> 32) & 0xF; - card_addr += desc->DescByteCount; - - dma_addr = sg_dma_address(sg) + (p * 0x80000); - desc->DescSystemAddrLS = (dma_addr & 0x00000000FFFFFFFFUL) >> 0; - desc->DescSystemAddrMS = (dma_addr & 0xFFFFFFFF00000000UL) >> 32; - - user_ctl = acd->priv->user_ctl; - if (i == acd->mapped_entry_count - 1 && p == pcnt - 1) - user_ctl = acd->priv->user_ctl_last; - - desc->DescUserControlLS = (user_ctl & 0x00000000FFFFFFFFUL) >> 0; - desc->DescUserControlMS = (user_ctl & 0xFFFFFFFF00000000UL) >> 32; - - if (i == acd->mapped_entry_count - 1 && p == pcnt - 1) - desc->acd = acd; - - dev_dbg(&priv->ldev->pldev->dev, " Filled descriptor %p (acd = %p)\n", - desc, desc->acd); - - ldev->desc_next = desc->Next; - desc = desc->Next; - } - } - - // Send the filled descriptors off to the hardware to process! - SetEngineSWPtr(ldev, ldev->desc_next); - - unlock_engine(ldev); - - rv = wait_for_completion_interruptible(&done); - /* - * If the user aborted (rv == -ERESTARTSYS), we're no longer responsible - * for cleaning up the acd - */ - if (rv == -ERESTARTSYS) - acd->cpl = NULL; - if (rv == 0) { - rv = acd->len; - kfree(acd); - } - return rv; - - err_descr_too_many: - unlock_engine(ldev); - dma_unmap_sg(&ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, ldev->dir); - free_table: - sg_free_table(&acd->sgt); - - unpin_pages: - if (nr_pages > 0) - unpin_user_pages(acd->user_pages, nr_pages); - kfree(acd->user_pages); - err_alloc_userpages: - kfree(acd); - dev_dbg(&priv->ldev->pldev->dev, "%s returning with error %d\n", __func__, rv); - return rv; -} - -void transfer_complete_cb(struct aio_cb_data *acd, size_t xfr_count, u32 flags) -{ - unsigned int i; - - BUG_ON(!acd); - BUG_ON(!acd->user_pages); - BUG_ON(!acd->sgt.sgl); - BUG_ON(!acd->ldev); - BUG_ON(!acd->ldev->pldev); - - dma_unmap_sg(&acd->ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, acd->ldev->dir); - - for (i = 0 ; i < acd->page_count ; i++) { - if (!PageReserved(acd->user_pages[i])) - set_page_dirty_lock(acd->user_pages[i]); - } - - unpin_user_pages(acd->user_pages, acd->page_count); - - sg_free_table(&acd->sgt); - - kfree(acd->user_pages); - - acd->flags = flags; - - if (acd->cpl) { - complete(acd->cpl); - } else { - /* - * There's no completion, so we're responsible for cleaning up - * the acd - */ - kfree(acd); - } -} - -/********** Fileops **********/ -static -int kpc_dma_open(struct inode *inode, struct file *filp) -{ - struct dev_private_data *priv; - struct kpc_dma_device *ldev = kpc_dma_lookup_device(iminor(inode)); - - if (!ldev) - return -ENODEV; - - if (!atomic_dec_and_test(&ldev->open_count)) { - atomic_inc(&ldev->open_count); - return -EBUSY; /* already open */ - } - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->ldev = ldev; - filp->private_data = priv; - - return 0; -} - -static -int kpc_dma_close(struct inode *inode, struct file *filp) -{ - struct kpc_dma_descriptor *cur; - struct dev_private_data *priv = (struct dev_private_data *)filp->private_data; - struct kpc_dma_device *eng = priv->ldev; - - lock_engine(eng); - - stop_dma_engine(eng); - - cur = eng->desc_completed->Next; - while (cur != eng->desc_next) { - dev_dbg(&eng->pldev->dev, "Aborting descriptor %p (acd = %p)\n", cur, cur->acd); - if (cur->DescControlFlags & DMA_DESC_CTL_EOP) { - if (cur->acd) - transfer_complete_cb(cur->acd, 0, ACD_FLAG_ABORT); - } - - clear_desc(cur); - eng->desc_completed = cur; - - cur = cur->Next; - } - - start_dma_engine(eng); - - unlock_engine(eng); - - atomic_inc(&priv->ldev->open_count); /* release the device */ - kfree(priv); - return 0; -} - -static -ssize_t kpc_dma_read(struct file *filp, char __user *user_buf, size_t count, loff_t *ppos) -{ - struct dev_private_data *priv = (struct dev_private_data *)filp->private_data; - - if (priv->ldev->dir != DMA_FROM_DEVICE) - return -EMEDIUMTYPE; - - return kpc_dma_transfer(priv, (unsigned long)user_buf, count); -} - -static -ssize_t kpc_dma_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *ppos) -{ - struct dev_private_data *priv = (struct dev_private_data *)filp->private_data; - - if (priv->ldev->dir != DMA_TO_DEVICE) - return -EMEDIUMTYPE; - - return kpc_dma_transfer(priv, (unsigned long)user_buf, count); -} - -static -long kpc_dma_ioctl(struct file *filp, unsigned int ioctl_num, unsigned long ioctl_param) -{ - struct dev_private_data *priv = (struct dev_private_data *)filp->private_data; - - switch (ioctl_num) { - case KND_IOCTL_SET_CARD_ADDR: - priv->card_addr = ioctl_param; return priv->card_addr; - case KND_IOCTL_SET_USER_CTL: - priv->user_ctl = ioctl_param; return priv->user_ctl; - case KND_IOCTL_SET_USER_CTL_LAST: - priv->user_ctl_last = ioctl_param; return priv->user_ctl_last; - case KND_IOCTL_GET_USER_STS: - return priv->user_sts; - } - - return -ENOTTY; -} - -const struct file_operations kpc_dma_fops = { - .owner = THIS_MODULE, - .open = kpc_dma_open, - .release = kpc_dma_close, - .read = kpc_dma_read, - .write = kpc_dma_write, - .unlocked_ioctl = kpc_dma_ioctl, -}; - diff --git a/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.c b/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.c deleted file mode 100644 index 175fe8b0d055..000000000000 --- a/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.c +++ /dev/null @@ -1,249 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -#include <linux/init.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/io.h> -#include <linux/export.h> -#include <linux/slab.h> -#include <linux/platform_device.h> -#include <linux/fs.h> -#include <linux/rwsem.h> -#include "kpc_dma_driver.h" - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Matt.Sickler@daktronics.com"); - -#define KPC_DMA_CHAR_MAJOR UNNAMED_MAJOR -#define KPC_DMA_NUM_MINORS BIT(MINORBITS) -static DEFINE_MUTEX(kpc_dma_mtx); -static int assigned_major_num; -static LIST_HEAD(kpc_dma_list); - -/********** kpc_dma_list list management **********/ -struct kpc_dma_device *kpc_dma_lookup_device(int minor) -{ - struct kpc_dma_device *c; - - mutex_lock(&kpc_dma_mtx); - list_for_each_entry(c, &kpc_dma_list, list) { - if (c->pldev->id == minor) - goto out; - } - c = NULL; // not-found case -out: - mutex_unlock(&kpc_dma_mtx); - return c; -} - -static void kpc_dma_add_device(struct kpc_dma_device *ldev) -{ - mutex_lock(&kpc_dma_mtx); - list_add(&ldev->list, &kpc_dma_list); - mutex_unlock(&kpc_dma_mtx); -} - -static void kpc_dma_del_device(struct kpc_dma_device *ldev) -{ - mutex_lock(&kpc_dma_mtx); - list_del(&ldev->list); - mutex_unlock(&kpc_dma_mtx); -} - -/********** SysFS Attributes **********/ -static ssize_t engine_regs_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct kpc_dma_device *ldev; - struct platform_device *pldev = to_platform_device(dev); - - if (!pldev) - return 0; - ldev = platform_get_drvdata(pldev); - if (!ldev) - return 0; - - return scnprintf(buf, PAGE_SIZE, - "EngineControlStatus = 0x%08x\n" - "RegNextDescPtr = 0x%08x\n" - "RegSWDescPtr = 0x%08x\n" - "RegCompletedDescPtr = 0x%08x\n" - "desc_pool_first = %p\n" - "desc_pool_last = %p\n" - "desc_next = %p\n" - "desc_completed = %p\n", - readl(ldev->eng_regs + 1), - readl(ldev->eng_regs + 2), - readl(ldev->eng_regs + 3), - readl(ldev->eng_regs + 4), - ldev->desc_pool_first, - ldev->desc_pool_last, - ldev->desc_next, - ldev->desc_completed - ); -} -static DEVICE_ATTR_RO(engine_regs); - -static const struct attribute *ndd_attr_list[] = { - &dev_attr_engine_regs.attr, - NULL, -}; - -static struct class *kpc_dma_class; - -/********** Platform Driver Functions **********/ -static -int kpc_dma_probe(struct platform_device *pldev) -{ - struct resource *r = NULL; - int rv = 0; - dev_t dev; - - struct kpc_dma_device *ldev = kzalloc(sizeof(*ldev), GFP_KERNEL); - - if (!ldev) { - dev_err(&pldev->dev, "%s: unable to kzalloc space for kpc_dma_device\n", __func__); - rv = -ENOMEM; - goto err_rv; - } - - INIT_LIST_HEAD(&ldev->list); - - ldev->pldev = pldev; - platform_set_drvdata(pldev, ldev); - atomic_set(&ldev->open_count, 1); - - mutex_init(&ldev->sem); - lock_engine(ldev); - - // Get Engine regs resource - r = platform_get_resource(pldev, IORESOURCE_MEM, 0); - if (!r) { - dev_err(&ldev->pldev->dev, "%s: didn't get the engine regs resource!\n", __func__); - rv = -ENXIO; - goto err_kfree; - } - ldev->eng_regs = ioremap(r->start, resource_size(r)); - if (!ldev->eng_regs) { - dev_err(&ldev->pldev->dev, "%s: failed to ioremap engine regs!\n", __func__); - rv = -ENXIO; - goto err_kfree; - } - - r = platform_get_resource(pldev, IORESOURCE_IRQ, 0); - if (!r) { - dev_err(&ldev->pldev->dev, "%s: didn't get the IRQ resource!\n", __func__); - rv = -ENXIO; - goto err_kfree; - } - ldev->irq = r->start; - - // Setup miscdev struct - dev = MKDEV(assigned_major_num, pldev->id); - ldev->kpc_dma_dev = device_create(kpc_dma_class, &pldev->dev, dev, ldev, - "kpc_dma%d", pldev->id); - if (IS_ERR(ldev->kpc_dma_dev)) { - rv = PTR_ERR(ldev->kpc_dma_dev); - dev_err(&ldev->pldev->dev, "%s: device_create failed: %d\n", __func__, rv); - goto err_kfree; - } - - // Setup the DMA engine - rv = setup_dma_engine(ldev, 30); - if (rv) { - dev_err(&ldev->pldev->dev, "%s: failed to setup_dma_engine: %d\n", __func__, rv); - goto err_misc_dereg; - } - - // Setup the sysfs files - rv = sysfs_create_files(&(ldev->pldev->dev.kobj), ndd_attr_list); - if (rv) { - dev_err(&ldev->pldev->dev, "%s: Failed to add sysfs files: %d\n", __func__, rv); - goto err_destroy_eng; - } - - kpc_dma_add_device(ldev); - - return 0; - - err_destroy_eng: - destroy_dma_engine(ldev); - err_misc_dereg: - device_destroy(kpc_dma_class, dev); - err_kfree: - kfree(ldev); - err_rv: - return rv; -} - -static -int kpc_dma_remove(struct platform_device *pldev) -{ - struct kpc_dma_device *ldev = platform_get_drvdata(pldev); - - if (!ldev) - return -ENXIO; - - lock_engine(ldev); - sysfs_remove_files(&(ldev->pldev->dev.kobj), ndd_attr_list); - destroy_dma_engine(ldev); - kpc_dma_del_device(ldev); - device_destroy(kpc_dma_class, MKDEV(assigned_major_num, ldev->pldev->id)); - kfree(ldev); - - return 0; -} - -/********** Driver Functions **********/ -static struct platform_driver kpc_dma_plat_driver_i = { - .probe = kpc_dma_probe, - .remove = kpc_dma_remove, - .driver = { - .name = KP_DRIVER_NAME_DMA_CONTROLLER, - }, -}; - -static -int __init kpc_dma_driver_init(void) -{ - int err; - - err = __register_chrdev(KPC_DMA_CHAR_MAJOR, 0, KPC_DMA_NUM_MINORS, - "kpc_dma", &kpc_dma_fops); - if (err < 0) { - pr_err("Can't allocate a major number (%d) for kpc_dma (err = %d)\n", - KPC_DMA_CHAR_MAJOR, err); - goto fail_chrdev_register; - } - assigned_major_num = err; - - kpc_dma_class = class_create(THIS_MODULE, "kpc_dma"); - err = PTR_ERR(kpc_dma_class); - if (IS_ERR(kpc_dma_class)) { - pr_err("Can't create class kpc_dma (err = %d)\n", err); - goto fail_class_create; - } - - err = platform_driver_register(&kpc_dma_plat_driver_i); - if (err) { - pr_err("Can't register platform driver for kpc_dma (err = %d)\n", err); - goto fail_platdriver_register; - } - - return err; - -fail_platdriver_register: - class_destroy(kpc_dma_class); -fail_class_create: - __unregister_chrdev(KPC_DMA_CHAR_MAJOR, 0, KPC_DMA_NUM_MINORS, "kpc_dma"); -fail_chrdev_register: - return err; -} -module_init(kpc_dma_driver_init); - -static -void __exit kpc_dma_driver_exit(void) -{ - platform_driver_unregister(&kpc_dma_plat_driver_i); - class_destroy(kpc_dma_class); - __unregister_chrdev(KPC_DMA_CHAR_MAJOR, 0, KPC_DMA_NUM_MINORS, "kpc_dma"); -} -module_exit(kpc_dma_driver_exit); diff --git a/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.h b/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.h deleted file mode 100644 index 8b9c978257b9..000000000000 --- a/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.h +++ /dev/null @@ -1,222 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -#ifndef KPC_DMA_DRIVER_H -#define KPC_DMA_DRIVER_H -#include <linux/platform_device.h> -#include <linux/cdev.h> -#include <linux/kfifo.h> -#include <linux/list.h> -#include <linux/spinlock.h> -#include <linux/sched.h> -#include <linux/miscdevice.h> -#include <linux/rwsem.h> -#include <linux/dma-mapping.h> -#include <linux/dmapool.h> -#include <linux/pci.h> -#include <linux/interrupt.h> -#include <linux/workqueue.h> -#include <linux/bitops.h> -#include "../kpc.h" - -struct kp2000_device; -struct kpc_dma_device { - struct list_head list; - struct platform_device *pldev; - u32 __iomem *eng_regs; - struct device *kpc_dma_dev; - struct kobject kobj; - char name[16]; - - int dir; // DMA_FROM_DEVICE || DMA_TO_DEVICE - struct mutex sem; - unsigned int irq; - struct work_struct irq_work; - - atomic_t open_count; - - size_t accumulated_bytes; - u32 accumulated_flags; - - // Descriptor "Pool" housekeeping - u32 desc_pool_cnt; - struct dma_pool *desc_pool; - struct kpc_dma_descriptor *desc_pool_first; - struct kpc_dma_descriptor *desc_pool_last; - - struct kpc_dma_descriptor *desc_next; - struct kpc_dma_descriptor *desc_completed; -}; - -struct dev_private_data { - struct kpc_dma_device *ldev; - u64 card_addr; - u64 user_ctl; - u64 user_ctl_last; - u64 user_sts; -}; - -struct kpc_dma_device *kpc_dma_lookup_device(int minor); - -extern const struct file_operations kpc_dma_fops; - -#define ENG_CAP_PRESENT 0x00000001 -#define ENG_CAP_DIRECTION 0x00000002 -#define ENG_CAP_TYPE_MASK 0x000000F0 -#define ENG_CAP_NUMBER_MASK 0x0000FF00 -#define ENG_CAP_CARD_ADDR_SIZE_MASK 0x007F0000 -#define ENG_CAP_DESC_MAX_BYTE_CNT_MASK 0x3F000000 -#define ENG_CAP_PERF_SCALE_MASK 0xC0000000 - -#define ENG_CTL_IRQ_ENABLE BIT(0) -#define ENG_CTL_IRQ_ACTIVE BIT(1) -#define ENG_CTL_DESC_COMPLETE BIT(2) -#define ENG_CTL_DESC_ALIGN_ERR BIT(3) -#define ENG_CTL_DESC_FETCH_ERR BIT(4) -#define ENG_CTL_SW_ABORT_ERR BIT(5) -#define ENG_CTL_DESC_CHAIN_END BIT(7) -#define ENG_CTL_DMA_ENABLE BIT(8) -#define ENG_CTL_DMA_RUNNING BIT(10) -#define ENG_CTL_DMA_WAITING BIT(11) -#define ENG_CTL_DMA_WAITING_PERSIST BIT(12) -#define ENG_CTL_DMA_RESET_REQUEST BIT(14) -#define ENG_CTL_DMA_RESET BIT(15) -#define ENG_CTL_DESC_FETCH_ERR_CLASS_MASK 0x700000 - -struct aio_cb_data { - struct dev_private_data *priv; - struct kpc_dma_device *ldev; - struct completion *cpl; - unsigned char flags; - size_t len; - - unsigned int page_count; - struct page **user_pages; - struct sg_table sgt; - int mapped_entry_count; -}; - -#define ACD_FLAG_DONE 0 -#define ACD_FLAG_ABORT 1 -#define ACD_FLAG_ENG_ACCUM_ERROR 4 -#define ACD_FLAG_ENG_ACCUM_SHORT 5 - -struct kpc_dma_descriptor { - struct { - volatile u32 DescByteCount :20; - volatile u32 DescStatusErrorFlags :4; - volatile u32 DescStatusFlags :8; - }; - volatile u32 DescUserControlLS; - volatile u32 DescUserControlMS; - volatile u32 DescCardAddrLS; - struct { - volatile u32 DescBufferByteCount :20; - volatile u32 DescCardAddrMS :4; - volatile u32 DescControlFlags :8; - }; - volatile u32 DescSystemAddrLS; - volatile u32 DescSystemAddrMS; - volatile u32 DescNextDescPtr; - - dma_addr_t MyDMAAddr; - struct kpc_dma_descriptor *Next; - - struct aio_cb_data *acd; -} __attribute__((packed)); -// DescControlFlags: -#define DMA_DESC_CTL_SOP BIT(7) -#define DMA_DESC_CTL_EOP BIT(6) -#define DMA_DESC_CTL_AFIFO BIT(2) -#define DMA_DESC_CTL_IRQONERR BIT(1) -#define DMA_DESC_CTL_IRQONDONE BIT(0) -// DescStatusFlags: -#define DMA_DESC_STS_SOP BIT(7) -#define DMA_DESC_STS_EOP BIT(6) -#define DMA_DESC_STS_ERROR BIT(4) -#define DMA_DESC_STS_USMSZ BIT(3) -#define DMA_DESC_STS_USLSZ BIT(2) -#define DMA_DESC_STS_SHORT BIT(1) -#define DMA_DESC_STS_COMPLETE BIT(0) -// DescStatusErrorFlags: -#define DMA_DESC_ESTS_ECRC BIT(2) -#define DMA_DESC_ESTS_POISON BIT(1) -#define DMA_DESC_ESTS_UNSUCCESSFUL BIT(0) - -#define DMA_DESC_ALIGNMENT 0x20 - -static inline -u32 GetEngineCapabilities(struct kpc_dma_device *eng) -{ - return readl(eng->eng_regs + 0); -} - -static inline -void WriteEngineControl(struct kpc_dma_device *eng, u32 value) -{ - writel(value, eng->eng_regs + 1); -} - -static inline -u32 GetEngineControl(struct kpc_dma_device *eng) -{ - return readl(eng->eng_regs + 1); -} - -static inline -void SetClearEngineControl(struct kpc_dma_device *eng, u32 set_bits, u32 clear_bits) -{ - u32 val = GetEngineControl(eng); - - val |= set_bits; - val &= ~clear_bits; - WriteEngineControl(eng, val); -} - -static inline -void SetEngineNextPtr(struct kpc_dma_device *eng, struct kpc_dma_descriptor *desc) -{ - writel(desc->MyDMAAddr, eng->eng_regs + 2); -} - -static inline -void SetEngineSWPtr(struct kpc_dma_device *eng, struct kpc_dma_descriptor *desc) -{ - writel(desc->MyDMAAddr, eng->eng_regs + 3); -} - -static inline -void ClearEngineCompletePtr(struct kpc_dma_device *eng) -{ - writel(0, eng->eng_regs + 4); -} - -static inline -u32 GetEngineCompletePtr(struct kpc_dma_device *eng) -{ - return readl(eng->eng_regs + 4); -} - -static inline -void lock_engine(struct kpc_dma_device *eng) -{ - BUG_ON(!eng); - mutex_lock(&eng->sem); -} - -static inline -void unlock_engine(struct kpc_dma_device *eng) -{ - BUG_ON(!eng); - mutex_unlock(&eng->sem); -} - -/// Shared Functions -void start_dma_engine(struct kpc_dma_device *eng); -int setup_dma_engine(struct kpc_dma_device *eng, u32 desc_cnt); -void stop_dma_engine(struct kpc_dma_device *eng); -void destroy_dma_engine(struct kpc_dma_device *eng); -void clear_desc(struct kpc_dma_descriptor *desc); -int count_descriptors_available(struct kpc_dma_device *eng); -void transfer_complete_cb(struct aio_cb_data *acd, size_t xfr_count, u32 flags); - -#endif /* KPC_DMA_DRIVER_H */ - diff --git a/drivers/staging/kpc2000/kpc_dma/uapi.h b/drivers/staging/kpc2000/kpc_dma/uapi.h deleted file mode 100644 index 5ff6a1a36ff9..000000000000 --- a/drivers/staging/kpc2000/kpc_dma/uapi.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -#ifndef KPC_DMA_DRIVER_UAPI_H_ -#define KPC_DMA_DRIVER_UAPI_H_ -#include <linux/ioctl.h> - -#define KND_IOCTL_SET_CARD_ADDR _IOW('k', 1, __u32) -#define KND_IOCTL_SET_USER_CTL _IOW('k', 2, __u64) -#define KND_IOCTL_SET_USER_CTL_LAST _IOW('k', 4, __u64) -#define KND_IOCTL_GET_USER_STS _IOR('k', 3, __u64) - -#endif /* KPC_DMA_DRIVER_UAPI_H_ */ |