diff options
Diffstat (limited to 'drivers')
658 files changed, 31229 insertions, 15377 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index ccbeab9500ec..00dd309b6682 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -542,10 +542,10 @@ config ACPI_PFRUT if ARM64 source "drivers/acpi/arm64/Kconfig" +endif config ACPI_PPTT bool -endif config ACPI_PCC bool "ACPI PCC Address Space" diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index feb36c0b9446..3fc5a0d54f6e 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -131,3 +131,5 @@ obj-y += dptf/ obj-$(CONFIG_ARM64) += arm64/ obj-$(CONFIG_ACPI_VIOT) += viot.o + +obj-$(CONFIG_RISCV) += riscv/ diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 3269a888fb7a..f725813d0cce 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -276,7 +276,7 @@ acpi_map_lookup_virt(void __iomem *virt, acpi_size size) return NULL; } -#if defined(CONFIG_IA64) || defined(CONFIG_ARM64) +#if defined(CONFIG_IA64) || defined(CONFIG_ARM64) || defined(CONFIG_RISCV) /* ioremap will take care of cache attributes */ #define should_use_kmap(pfn) 0 #else diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 2ac48cda5b20..d6606a9f2da6 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -106,6 +106,32 @@ static int map_gicc_mpidr(struct acpi_subtable_header *entry, return -EINVAL; } +/* + * Retrieve the RISC-V hartid for the processor + */ +static int map_rintc_hartid(struct acpi_subtable_header *entry, + int device_declaration, u32 acpi_id, + phys_cpuid_t *hartid) +{ + struct acpi_madt_rintc *rintc = + container_of(entry, struct acpi_madt_rintc, header); + + if (!(rintc->flags & ACPI_MADT_ENABLED)) + return -ENODEV; + + /* device_declaration means Device object in DSDT, in the + * RISC-V, logical processors are required to + * have a Processor Device object in the DSDT, so we should + * check device_declaration here + */ + if (device_declaration && rintc->uid == acpi_id) { + *hartid = rintc->hart_id; + return 0; + } + + return -EINVAL; +} + static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt, int type, u32 acpi_id) { @@ -136,6 +162,9 @@ static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt, } else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) { if (!map_gicc_mpidr(header, type, acpi_id, &phys_id)) break; + } else if (header->type == ACPI_MADT_TYPE_RINTC) { + if (!map_rintc_hartid(header, type, acpi_id, &phys_id)) + break; } entry += header->length; } diff --git a/drivers/acpi/riscv/Makefile b/drivers/acpi/riscv/Makefile new file mode 100644 index 000000000000..8b3b126e0b94 --- /dev/null +++ b/drivers/acpi/riscv/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-y += rhct.o diff --git a/drivers/acpi/riscv/rhct.c b/drivers/acpi/riscv/rhct.c new file mode 100644 index 000000000000..b280b3e9c7d9 --- /dev/null +++ b/drivers/acpi/riscv/rhct.c @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2022-2023, Ventana Micro Systems Inc + * Author: Sunil V L <sunilvl@ventanamicro.com> + * + */ + +#define pr_fmt(fmt) "ACPI: RHCT: " fmt + +#include <linux/acpi.h> + +static struct acpi_table_header *acpi_get_rhct(void) +{ + static struct acpi_table_header *rhct; + acpi_status status; + + /* + * RHCT will be used at runtime on every CPU, so we + * don't need to call acpi_put_table() to release the table mapping. + */ + if (!rhct) { + status = acpi_get_table(ACPI_SIG_RHCT, 0, &rhct); + if (ACPI_FAILURE(status)) { + pr_warn_once("No RHCT table found\n"); + return NULL; + } + } + + return rhct; +} + +/* + * During early boot, the caller should call acpi_get_table() and pass its pointer to + * these functions(and free up later). At run time, since this table can be used + * multiple times, NULL may be passed in order to use the cached table. + */ +int acpi_get_riscv_isa(struct acpi_table_header *table, unsigned int cpu, const char **isa) +{ + struct acpi_rhct_node_header *node, *ref_node, *end; + u32 size_hdr = sizeof(struct acpi_rhct_node_header); + u32 size_hartinfo = sizeof(struct acpi_rhct_hart_info); + struct acpi_rhct_hart_info *hart_info; + struct acpi_rhct_isa_string *isa_node; + struct acpi_table_rhct *rhct; + u32 *hart_info_node_offset; + u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu); + + BUG_ON(acpi_disabled); + + if (!table) { + rhct = (struct acpi_table_rhct *)acpi_get_rhct(); + if (!rhct) + return -ENOENT; + } else { + rhct = (struct acpi_table_rhct *)table; + } + + end = ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, rhct->header.length); + + for (node = ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, rhct->node_offset); + node < end; + node = ACPI_ADD_PTR(struct acpi_rhct_node_header, node, node->length)) { + if (node->type == ACPI_RHCT_NODE_TYPE_HART_INFO) { + hart_info = ACPI_ADD_PTR(struct acpi_rhct_hart_info, node, size_hdr); + hart_info_node_offset = ACPI_ADD_PTR(u32, hart_info, size_hartinfo); + if (acpi_cpu_id != hart_info->uid) + continue; + + for (int i = 0; i < hart_info->num_offsets; i++) { + ref_node = ACPI_ADD_PTR(struct acpi_rhct_node_header, + rhct, hart_info_node_offset[i]); + if (ref_node->type == ACPI_RHCT_NODE_TYPE_ISA_STRING) { + isa_node = ACPI_ADD_PTR(struct acpi_rhct_isa_string, + ref_node, size_hdr); + *isa = isa_node->isa; + return 0; + } + } + } + } + + return -1; +} diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 7b4680da57d7..8ab0a82b4da4 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -220,6 +220,16 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) } break; + case ACPI_MADT_TYPE_RINTC: + { + struct acpi_madt_rintc *p = (struct acpi_madt_rintc *)header; + + pr_debug("RISC-V INTC (acpi_uid[0x%04x] hart_id[0x%llx] %s)\n", + p->uid, p->hart_id, + (p->flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled"); + } + break; + default: pr_warn("Found unsupported MADT entry (type = 0x%x)\n", header->type); diff --git a/drivers/ata/ahci_brcm.c b/drivers/ata/ahci_brcm.c index 4e3dc2b6d67f..70c3a33eee6f 100644 --- a/drivers/ata/ahci_brcm.c +++ b/drivers/ata/ahci_brcm.c @@ -544,7 +544,7 @@ out_reset: return ret; } -static int brcm_ahci_remove(struct platform_device *pdev) +static void brcm_ahci_remove(struct platform_device *pdev) { struct ata_host *host = dev_get_drvdata(&pdev->dev); struct ahci_host_priv *hpriv = host->private_data; @@ -552,7 +552,7 @@ static int brcm_ahci_remove(struct platform_device *pdev) brcm_sata_phys_disable(priv); - return ata_platform_remove_one(pdev); + ata_platform_remove_one(pdev); } static void brcm_ahci_shutdown(struct platform_device *pdev) @@ -573,7 +573,7 @@ static SIMPLE_DEV_PM_OPS(ahci_brcm_pm_ops, brcm_ahci_suspend, brcm_ahci_resume); static struct platform_driver brcm_ahci_driver = { .probe = brcm_ahci_probe, - .remove = brcm_ahci_remove, + .remove_new = brcm_ahci_remove, .shutdown = brcm_ahci_shutdown, .driver = { .name = DRV_NAME, diff --git a/drivers/ata/ahci_ceva.c b/drivers/ata/ahci_ceva.c index bc027468decb..c2b6be083af4 100644 --- a/drivers/ata/ahci_ceva.c +++ b/drivers/ata/ahci_ceva.c @@ -369,7 +369,7 @@ MODULE_DEVICE_TABLE(of, ceva_ahci_of_match); static struct platform_driver ceva_ahci_driver = { .probe = ceva_ahci_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = DRV_NAME, .of_match_table = ceva_ahci_of_match, diff --git a/drivers/ata/ahci_da850.c b/drivers/ata/ahci_da850.c index ca0924dc5bd2..55a6627d5450 100644 --- a/drivers/ata/ahci_da850.c +++ b/drivers/ata/ahci_da850.c @@ -238,7 +238,7 @@ MODULE_DEVICE_TABLE(of, ahci_da850_of_match); static struct platform_driver ahci_da850_driver = { .probe = ahci_da850_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = DRV_NAME, .of_match_table = ahci_da850_of_match, diff --git a/drivers/ata/ahci_dm816.c b/drivers/ata/ahci_dm816.c index b08547b877a1..4cb70064fb99 100644 --- a/drivers/ata/ahci_dm816.c +++ b/drivers/ata/ahci_dm816.c @@ -182,7 +182,7 @@ MODULE_DEVICE_TABLE(of, ahci_dm816_of_match); static struct platform_driver ahci_dm816_driver = { .probe = ahci_dm816_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = AHCI_DM816_DRV_NAME, .of_match_table = ahci_dm816_of_match, diff --git a/drivers/ata/ahci_dwc.c b/drivers/ata/ahci_dwc.c index 4bfbb09cdc02..9604a2f6ed48 100644 --- a/drivers/ata/ahci_dwc.c +++ b/drivers/ata/ahci_dwc.c @@ -478,7 +478,7 @@ MODULE_DEVICE_TABLE(of, ahci_dwc_of_match); static struct platform_driver ahci_dwc_driver = { .probe = ahci_dwc_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .shutdown = ahci_platform_shutdown, .driver = { .name = DRV_NAME, diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index 3a8c248e7c0e..9fa005965f3b 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c @@ -1223,7 +1223,7 @@ static SIMPLE_DEV_PM_OPS(ahci_imx_pm_ops, imx_ahci_suspend, imx_ahci_resume); static struct platform_driver imx_ahci_driver = { .probe = imx_ahci_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = DRV_NAME, .of_match_table = imx_ahci_of_match, diff --git a/drivers/ata/ahci_mtk.c b/drivers/ata/ahci_mtk.c index 0bf83a297091..5083fb6c4927 100644 --- a/drivers/ata/ahci_mtk.c +++ b/drivers/ata/ahci_mtk.c @@ -173,7 +173,7 @@ MODULE_DEVICE_TABLE(of, ahci_of_match); static struct platform_driver mtk_ahci_driver = { .probe = mtk_ahci_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = DRV_NAME, .of_match_table = ahci_of_match, diff --git a/drivers/ata/ahci_mvebu.c b/drivers/ata/ahci_mvebu.c index 596cf017f427..764501518582 100644 --- a/drivers/ata/ahci_mvebu.c +++ b/drivers/ata/ahci_mvebu.c @@ -245,7 +245,7 @@ MODULE_DEVICE_TABLE(of, ahci_mvebu_of_match); static struct platform_driver ahci_mvebu_driver = { .probe = ahci_mvebu_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .suspend = ahci_mvebu_suspend, .resume = ahci_mvebu_resume, .driver = { diff --git a/drivers/ata/ahci_octeon.c b/drivers/ata/ahci_octeon.c index 5021ab3ede49..e89807fa928e 100644 --- a/drivers/ata/ahci_octeon.c +++ b/drivers/ata/ahci_octeon.c @@ -16,7 +16,6 @@ #include <linux/of_platform.h> #include <asm/octeon/octeon.h> -#include <asm/bitfield.h> #define CVMX_SATA_UCTL_SHIM_CFG 0xE8 diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 299ee686ac49..ab30c7138d73 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -96,7 +96,7 @@ MODULE_DEVICE_TABLE(acpi, ahci_acpi_match); static struct platform_driver ahci_driver = { .probe = ahci_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .shutdown = ahci_platform_shutdown, .driver = { .name = DRV_NAME, diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c index 0ba764d283c8..3d01b118c9a1 100644 --- a/drivers/ata/ahci_qoriq.c +++ b/drivers/ata/ahci_qoriq.c @@ -359,7 +359,7 @@ static SIMPLE_DEV_PM_OPS(ahci_qoriq_pm_ops, ahci_platform_suspend, static struct platform_driver ahci_qoriq_driver = { .probe = ahci_qoriq_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = DRV_NAME, .of_match_table = ahci_qoriq_of_match, diff --git a/drivers/ata/ahci_seattle.c b/drivers/ata/ahci_seattle.c index 9eda7bbd2151..2c32d58c6ae7 100644 --- a/drivers/ata/ahci_seattle.c +++ b/drivers/ata/ahci_seattle.c @@ -187,7 +187,7 @@ MODULE_DEVICE_TABLE(acpi, ahci_acpi_match); static struct platform_driver ahci_seattle_driver = { .probe = ahci_seattle_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = DRV_NAME, .acpi_match_table = ahci_acpi_match, diff --git a/drivers/ata/ahci_st.c b/drivers/ata/ahci_st.c index f2c1edb36986..d4a626f87963 100644 --- a/drivers/ata/ahci_st.c +++ b/drivers/ata/ahci_st.c @@ -239,7 +239,7 @@ static struct platform_driver st_ahci_driver = { .of_match_table = st_ahci_match, }, .probe = st_ahci_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, }; module_platform_driver(st_ahci_driver); diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c index 076c12b4ba08..04531fa95e40 100644 --- a/drivers/ata/ahci_sunxi.c +++ b/drivers/ata/ahci_sunxi.c @@ -292,7 +292,7 @@ MODULE_DEVICE_TABLE(of, ahci_sunxi_of_match); static struct platform_driver ahci_sunxi_driver = { .probe = ahci_sunxi_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = DRV_NAME, .of_match_table = ahci_sunxi_of_match, diff --git a/drivers/ata/ahci_tegra.c b/drivers/ata/ahci_tegra.c index 8e5e2b359f2d..21c20793e517 100644 --- a/drivers/ata/ahci_tegra.c +++ b/drivers/ata/ahci_tegra.c @@ -609,7 +609,7 @@ deinit_controller: static struct platform_driver tegra_ahci_driver = { .probe = tegra_ahci_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = DRV_NAME, .of_match_table = tegra_ahci_of_match, diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c index 83f5ff54ef5b..eb773f2e28fc 100644 --- a/drivers/ata/ahci_xgene.c +++ b/drivers/ata/ahci_xgene.c @@ -868,7 +868,7 @@ disable_resources: static struct platform_driver xgene_ahci_driver = { .probe = xgene_ahci_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = DRV_NAME, .of_match_table = xgene_ahci_of_match, diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 9c2cb6cbea76..06aec35f88f2 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -975,44 +975,43 @@ int ahci_reset_controller(struct ata_host *host) void __iomem *mmio = hpriv->mmio; u32 tmp; - /* we must be in AHCI mode, before using anything - * AHCI-specific, such as HOST_RESET. + /* + * We must be in AHCI mode, before using anything AHCI-specific, such + * as HOST_RESET. */ ahci_enable_ahci(mmio); - /* global controller reset */ - if (!ahci_skip_host_reset) { - tmp = readl(mmio + HOST_CTL); - if ((tmp & HOST_RESET) == 0) { - writel(tmp | HOST_RESET, mmio + HOST_CTL); - readl(mmio + HOST_CTL); /* flush */ - } + /* Global controller reset */ + if (ahci_skip_host_reset) { + dev_info(host->dev, "Skipping global host reset\n"); + return 0; + } - /* - * to perform host reset, OS should set HOST_RESET - * and poll until this bit is read to be "0". - * reset must complete within 1 second, or - * the hardware should be considered fried. - */ - tmp = ata_wait_register(NULL, mmio + HOST_CTL, HOST_RESET, - HOST_RESET, 10, 1000); + tmp = readl(mmio + HOST_CTL); + if (!(tmp & HOST_RESET)) { + writel(tmp | HOST_RESET, mmio + HOST_CTL); + readl(mmio + HOST_CTL); /* flush */ + } - if (tmp & HOST_RESET) { - dev_err(host->dev, "controller reset failed (0x%x)\n", - tmp); - return -EIO; - } + /* + * To perform host reset, OS should set HOST_RESET and poll until this + * bit is read to be "0". Reset must complete within 1 second, or the + * hardware should be considered fried. + */ + tmp = ata_wait_register(NULL, mmio + HOST_CTL, HOST_RESET, + HOST_RESET, 10, 1000); + if (tmp & HOST_RESET) { + dev_err(host->dev, "Controller reset failed (0x%x)\n", + tmp); + return -EIO; + } - /* turn on AHCI mode */ - ahci_enable_ahci(mmio); + /* Turn on AHCI mode */ + ahci_enable_ahci(mmio); - /* Some registers might be cleared on reset. Restore - * initial values. - */ - if (!(hpriv->flags & AHCI_HFLAG_NO_WRITE_TO_RO)) - ahci_restore_initial_config(host); - } else - dev_info(host->dev, "skipping global host reset\n"); + /* Some registers might be cleared on reset. Restore initial values. */ + if (!(hpriv->flags & AHCI_HFLAG_NO_WRITE_TO_RO)) + ahci_restore_initial_config(host); return 0; } diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index b4f246f0cac7..d37ab6087f2f 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -665,12 +665,33 @@ u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev) return block; } +/* + * Set a taskfile command duration limit index. + */ +static inline void ata_set_tf_cdl(struct ata_queued_cmd *qc, int cdl) +{ + struct ata_taskfile *tf = &qc->tf; + + if (tf->protocol == ATA_PROT_NCQ) + tf->auxiliary |= cdl; + else + tf->feature |= cdl; + + /* + * Mark this command as having a CDL and request the result + * task file so that we can inspect the sense data available + * bit on completion. + */ + qc->flags |= ATA_QCFLAG_HAS_CDL | ATA_QCFLAG_RESULT_TF; +} + /** * ata_build_rw_tf - Build ATA taskfile for given read/write request * @qc: Metadata associated with the taskfile to build * @block: Block address * @n_block: Number of blocks * @tf_flags: RW/FUA etc... + * @cdl: Command duration limit index * @class: IO priority class * * LOCKING: @@ -685,7 +706,7 @@ u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev) * -EINVAL if the request is invalid. */ int ata_build_rw_tf(struct ata_queued_cmd *qc, u64 block, u32 n_block, - unsigned int tf_flags, int class) + unsigned int tf_flags, int cdl, int class) { struct ata_taskfile *tf = &qc->tf; struct ata_device *dev = qc->dev; @@ -724,11 +745,20 @@ int ata_build_rw_tf(struct ata_queued_cmd *qc, u64 block, u32 n_block, if (dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLED && class == IOPRIO_CLASS_RT) tf->hob_nsect |= ATA_PRIO_HIGH << ATA_SHIFT_PRIO; + + if ((dev->flags & ATA_DFLAG_CDL_ENABLED) && cdl) + ata_set_tf_cdl(qc, cdl); + } else if (dev->flags & ATA_DFLAG_LBA) { tf->flags |= ATA_TFLAG_LBA; - /* We need LBA48 for FUA writes */ - if (!(tf->flags & ATA_TFLAG_FUA) && lba_28_ok(block, n_block)) { + if ((dev->flags & ATA_DFLAG_CDL_ENABLED) && cdl) + ata_set_tf_cdl(qc, cdl); + + /* Both FUA writes and a CDL index require 48-bit commands */ + if (!(tf->flags & ATA_TFLAG_FUA) && + !(qc->flags & ATA_QCFLAG_HAS_CDL) && + lba_28_ok(block, n_block)) { /* use LBA28 */ tf->device |= (block >> 24) & 0xf; } else if (lba_48_ok(block, n_block)) { @@ -2367,6 +2397,139 @@ static void ata_dev_config_trusted(struct ata_device *dev) dev->flags |= ATA_DFLAG_TRUSTED; } +static void ata_dev_config_cdl(struct ata_device *dev) +{ + struct ata_port *ap = dev->link->ap; + unsigned int err_mask; + bool cdl_enabled; + u64 val; + + if (ata_id_major_version(dev->id) < 12) + goto not_supported; + + if (!ata_log_supported(dev, ATA_LOG_IDENTIFY_DEVICE) || + !ata_identify_page_supported(dev, ATA_LOG_SUPPORTED_CAPABILITIES) || + !ata_identify_page_supported(dev, ATA_LOG_CURRENT_SETTINGS)) + goto not_supported; + + err_mask = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, + ATA_LOG_SUPPORTED_CAPABILITIES, + ap->sector_buf, 1); + if (err_mask) + goto not_supported; + + /* Check Command Duration Limit Supported bits */ + val = get_unaligned_le64(&ap->sector_buf[168]); + if (!(val & BIT_ULL(63)) || !(val & BIT_ULL(0))) + goto not_supported; + + /* Warn the user if command duration guideline is not supported */ + if (!(val & BIT_ULL(1))) + ata_dev_warn(dev, + "Command duration guideline is not supported\n"); + + /* + * We must have support for the sense data for successful NCQ commands + * log indicated by the successful NCQ command sense data supported bit. + */ + val = get_unaligned_le64(&ap->sector_buf[8]); + if (!(val & BIT_ULL(63)) || !(val & BIT_ULL(47))) { + ata_dev_warn(dev, + "CDL supported but Successful NCQ Command Sense Data is not supported\n"); + goto not_supported; + } + + /* Without NCQ autosense, the successful NCQ commands log is useless. */ + if (!ata_id_has_ncq_autosense(dev->id)) { + ata_dev_warn(dev, + "CDL supported but NCQ autosense is not supported\n"); + goto not_supported; + } + + /* + * If CDL is marked as enabled, make sure the feature is enabled too. + * Conversely, if CDL is disabled, make sure the feature is turned off. + */ + err_mask = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, + ATA_LOG_CURRENT_SETTINGS, + ap->sector_buf, 1); + if (err_mask) + goto not_supported; + + val = get_unaligned_le64(&ap->sector_buf[8]); + cdl_enabled = val & BIT_ULL(63) && val & BIT_ULL(21); + if (dev->flags & ATA_DFLAG_CDL_ENABLED) { + if (!cdl_enabled) { + /* Enable CDL on the device */ + err_mask = ata_dev_set_feature(dev, SETFEATURES_CDL, 1); + if (err_mask) { + ata_dev_err(dev, + "Enable CDL feature failed\n"); + goto not_supported; + } + } + } else { + if (cdl_enabled) { + /* Disable CDL on the device */ + err_mask = ata_dev_set_feature(dev, SETFEATURES_CDL, 0); + if (err_mask) { + ata_dev_err(dev, + "Disable CDL feature failed\n"); + goto not_supported; + } + } + } + + /* + * While CDL itself has to be enabled using sysfs, CDL requires that + * sense data for successful NCQ commands is enabled to work properly. + * Just like ata_dev_config_sense_reporting(), enable it unconditionally + * if supported. + */ + if (!(val & BIT_ULL(63)) || !(val & BIT_ULL(18))) { + err_mask = ata_dev_set_feature(dev, + SETFEATURE_SENSE_DATA_SUCC_NCQ, 0x1); + if (err_mask) { + ata_dev_warn(dev, + "failed to enable Sense Data for successful NCQ commands, Emask 0x%x\n", + err_mask); + goto not_supported; + } + } + + /* + * Allocate a buffer to handle reading the sense data for successful + * NCQ Commands log page for commands using a CDL with one of the limit + * policy set to 0xD (successful completion with sense data available + * bit set). + */ + if (!ap->ncq_sense_buf) { + ap->ncq_sense_buf = kmalloc(ATA_LOG_SENSE_NCQ_SIZE, GFP_KERNEL); + if (!ap->ncq_sense_buf) + goto not_supported; + } + + /* + * Command duration limits is supported: cache the CDL log page 18h + * (command duration descriptors). + */ + err_mask = ata_read_log_page(dev, ATA_LOG_CDL, 0, ap->sector_buf, 1); + if (err_mask) { + ata_dev_warn(dev, "Read Command Duration Limits log failed\n"); + goto not_supported; + } + + memcpy(dev->cdl, ap->sector_buf, ATA_LOG_CDL_SIZE); + dev->flags |= ATA_DFLAG_CDL; + + return; + +not_supported: + dev->flags &= ~(ATA_DFLAG_CDL | ATA_DFLAG_CDL_ENABLED); + kfree(ap->ncq_sense_buf); + ap->ncq_sense_buf = NULL; +} + static int ata_dev_config_lba(struct ata_device *dev) { const u16 *id = dev->id; @@ -2534,13 +2697,14 @@ static void ata_dev_print_features(struct ata_device *dev) return; ata_dev_info(dev, - "Features:%s%s%s%s%s%s%s\n", + "Features:%s%s%s%s%s%s%s%s\n", dev->flags & ATA_DFLAG_FUA ? " FUA" : "", dev->flags & ATA_DFLAG_TRUSTED ? " Trust" : "", dev->flags & ATA_DFLAG_DA ? " Dev-Attention" : "", dev->flags & ATA_DFLAG_DEVSLP ? " Dev-Sleep" : "", dev->flags & ATA_DFLAG_NCQ_SEND_RECV ? " NCQ-sndrcv" : "", dev->flags & ATA_DFLAG_NCQ_PRIO ? " NCQ-prio" : "", + dev->flags & ATA_DFLAG_CDL ? " CDL" : "", dev->cpr_log ? " CPR" : ""); } @@ -2702,6 +2866,7 @@ int ata_dev_configure(struct ata_device *dev) ata_dev_config_zac(dev); ata_dev_config_trusted(dev); ata_dev_config_cpr(dev); + ata_dev_config_cdl(dev); dev->cdb_len = 32; if (print_info) @@ -3802,11 +3967,7 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class, return -ENODEV; /* fail early if !ATA && !ATAPI to avoid issuing [P]IDENTIFY to PMP */ - if (ata_class_enabled(new_class) && - new_class != ATA_DEV_ATA && - new_class != ATA_DEV_ATAPI && - new_class != ATA_DEV_ZAC && - new_class != ATA_DEV_SEMB) { + if (ata_class_enabled(new_class) && new_class == ATA_DEV_PMP) { ata_dev_info(dev, "class mismatch %u != %u\n", dev->class, new_class); rc = -ENODEV; @@ -4766,6 +4927,36 @@ void ata_qc_complete(struct ata_queued_cmd *qc) fill_result_tf(qc); trace_ata_qc_complete_done(qc); + + /* + * For CDL commands that completed without an error, check if + * we have sense data (ATA_SENSE is set). If we do, then the + * command may have been aborted by the device due to a limit + * timeout using the policy 0xD. For these commands, invoke EH + * to get the command sense data. + */ + if (qc->result_tf.status & ATA_SENSE && + ((ata_is_ncq(qc->tf.protocol) && + dev->flags & ATA_DFLAG_CDL_ENABLED) || + (!(ata_is_ncq(qc->tf.protocol) && + ata_id_sense_reporting_enabled(dev->id))))) { + /* + * Tell SCSI EH to not overwrite scmd->result even if + * this command is finished with result SAM_STAT_GOOD. + */ + qc->scsicmd->flags |= SCMD_FORCE_EH_SUCCESS; + qc->flags |= ATA_QCFLAG_EH_SUCCESS_CMD; + ehi->dev_action[dev->devno] |= ATA_EH_GET_SUCCESS_SENSE; + + /* + * set pending so that ata_qc_schedule_eh() does not + * trigger fast drain, and freeze the port. + */ + ap->pflags |= ATA_PFLAG_EH_PENDING; + ata_qc_schedule_eh(qc); + return; + } + /* Some commands need post-processing after successful * completion. */ @@ -5398,6 +5589,7 @@ static void ata_host_release(struct kref *kref) kfree(ap->pmp_link); kfree(ap->slave_link); + kfree(ap->ncq_sense_buf); kfree(ap); host->ports[i] = NULL; } @@ -6142,13 +6334,11 @@ EXPORT_SYMBOL_GPL(ata_pci_device_resume); * LOCKING: * Inherited from platform layer (may sleep). */ -int ata_platform_remove_one(struct platform_device *pdev) +void ata_platform_remove_one(struct platform_device *pdev) { struct ata_host *host = platform_get_drvdata(pdev); ata_host_detach(host); - - return 0; } EXPORT_SYMBOL_GPL(ata_platform_remove_one); diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 6f8d14191593..35e03679b0bf 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1401,8 +1401,11 @@ unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key) * * LOCKING: * Kernel thread context (may sleep). + * + * RETURNS: + * true if sense data could be fetched, false otherwise. */ -static void ata_eh_request_sense(struct ata_queued_cmd *qc) +static bool ata_eh_request_sense(struct ata_queued_cmd *qc) { struct scsi_cmnd *cmd = qc->scsicmd; struct ata_device *dev = qc->dev; @@ -1411,15 +1414,12 @@ static void ata_eh_request_sense(struct ata_queued_cmd *qc) if (ata_port_is_frozen(qc->ap)) { ata_dev_warn(dev, "sense data available but port frozen\n"); - return; + return false; } - if (!cmd || qc->flags & ATA_QCFLAG_SENSE_VALID) - return; - if (!ata_id_sense_reporting_enabled(dev->id)) { ata_dev_warn(qc->dev, "sense data reporting disabled\n"); - return; + return false; } ata_tf_init(dev, &tf); @@ -1432,13 +1432,19 @@ static void ata_eh_request_sense(struct ata_queued_cmd *qc) /* Ignore err_mask; ATA_ERR might be set */ if (tf.status & ATA_SENSE) { if (ata_scsi_sense_is_valid(tf.lbah, tf.lbam, tf.lbal)) { - ata_scsi_set_sense(dev, cmd, tf.lbah, tf.lbam, tf.lbal); + /* Set sense without also setting scsicmd->result */ + scsi_build_sense_buffer(dev->flags & ATA_DFLAG_D_SENSE, + cmd->sense_buffer, tf.lbah, + tf.lbam, tf.lbal); qc->flags |= ATA_QCFLAG_SENSE_VALID; + return true; } } else { ata_dev_warn(dev, "request sense failed stat %02x emask %x\n", tf.status, err_mask); } + + return false; } /** @@ -1588,8 +1594,9 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc) * was not included in the NCQ command error log * (i.e. NCQ autosense is not supported by the device). */ - if (!(qc->flags & ATA_QCFLAG_SENSE_VALID) && (stat & ATA_SENSE)) - ata_eh_request_sense(qc); + if (!(qc->flags & ATA_QCFLAG_SENSE_VALID) && + (stat & ATA_SENSE) && ata_eh_request_sense(qc)) + set_status_byte(qc->scsicmd, SAM_STAT_CHECK_CONDITION); if (err & ATA_ICRC) qc->err_mask |= AC_ERR_ATA_BUS; if (err & (ATA_UNC | ATA_AMNF)) @@ -1817,9 +1824,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, verdict = ata_eh_speed_down_verdict(dev); /* turn off NCQ? */ - if ((verdict & ATA_EH_SPDN_NCQ_OFF) && - (dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ | - ATA_DFLAG_NCQ_OFF)) == ATA_DFLAG_NCQ) { + if ((verdict & ATA_EH_SPDN_NCQ_OFF) && ata_ncq_enabled(dev)) { dev->flags |= ATA_DFLAG_NCQ_OFF; ata_dev_warn(dev, "NCQ disabled due to excessive errors\n"); goto done; @@ -1910,6 +1915,99 @@ static inline bool ata_eh_quiet(struct ata_queued_cmd *qc) return qc->flags & ATA_QCFLAG_QUIET; } +static int ata_eh_read_sense_success_non_ncq(struct ata_link *link) +{ + struct ata_port *ap = link->ap; + struct ata_queued_cmd *qc; + + qc = __ata_qc_from_tag(ap, link->active_tag); + if (!qc) + return -EIO; + + if (!(qc->flags & ATA_QCFLAG_EH) || + !(qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) || + qc->err_mask) + return -EIO; + + if (!ata_eh_request_sense(qc)) + return -EIO; + + /* + * If we have sense data, call scsi_check_sense() in order to set the + * correct SCSI ML byte (if any). No point in checking the return value, + * since the command has already completed successfully. + */ + scsi_check_sense(qc->scsicmd); + + return 0; +} + +static void ata_eh_get_success_sense(struct ata_link *link) +{ + struct ata_eh_context *ehc = &link->eh_context; + struct ata_device *dev = link->device; + struct ata_port *ap = link->ap; + struct ata_queued_cmd *qc; + int tag, ret = 0; + + if (!(ehc->i.dev_action[dev->devno] & ATA_EH_GET_SUCCESS_SENSE)) + return; + + /* if frozen, we can't do much */ + if (ata_port_is_frozen(ap)) { + ata_dev_warn(dev, + "successful sense data available but port frozen\n"); + goto out; + } + + /* + * If the link has sactive set, then we have outstanding NCQ commands + * and have to read the Successful NCQ Commands log to get the sense + * data. Otherwise, we are dealing with a non-NCQ command and use + * request sense ext command to retrieve the sense data. + */ + if (link->sactive) + ret = ata_eh_read_sense_success_ncq_log(link); + else + ret = ata_eh_read_sense_success_non_ncq(link); + if (ret) + goto out; + + ata_eh_done(link, dev, ATA_EH_GET_SUCCESS_SENSE); + return; + +out: + /* + * If we failed to get sense data for a successful command that ought to + * have sense data, we cannot simply return BLK_STS_OK to user space. + * This is because we can't know if the sense data that we couldn't get + * was actually "DATA CURRENTLY UNAVAILABLE". Reporting such a command + * as success to user space would result in a silent data corruption. + * Thus, add a bogus ABORTED_COMMAND sense data to such commands, such + * that SCSI will report these commands as BLK_STS_IOERR to user space. + */ + ata_qc_for_each_raw(ap, qc, tag) { + if (!(qc->flags & ATA_QCFLAG_EH) || + !(qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) || + qc->err_mask || + ata_dev_phys_link(qc->dev) != link) + continue; + + /* We managed to get sense for this success command, skip. */ + if (qc->flags & ATA_QCFLAG_SENSE_VALID) + continue; + + /* This success command did not have any sense data, skip. */ + if (!(qc->result_tf.status & ATA_SENSE)) + continue; + + /* This success command had sense data, but we failed to get. */ + ata_scsi_set_sense(dev, qc->scsicmd, ABORTED_COMMAND, 0, 0); + qc->flags |= ATA_QCFLAG_SENSE_VALID; + } + ata_eh_done(link, dev, ATA_EH_GET_SUCCESS_SENSE); +} + /** * ata_eh_link_autopsy - analyze error and determine recovery action * @link: host link to perform autopsy on @@ -1950,6 +2048,14 @@ static void ata_eh_link_autopsy(struct ata_link *link) /* analyze NCQ failure */ ata_eh_analyze_ncq_error(link); + /* + * Check if this was a successful command that simply needs sense data. + * Since the sense data is not part of the completion, we need to fetch + * it using an additional command. Since this can't be done from irq + * context, the sense data for successful commands are fetched by EH. + */ + ata_eh_get_success_sense(link); + /* any real error trumps AC_ERR_OTHER */ if (ehc->i.err_mask & ~AC_ERR_OTHER) ehc->i.err_mask &= ~AC_ERR_OTHER; @@ -1959,6 +2065,7 @@ static void ata_eh_link_autopsy(struct ata_link *link) ata_qc_for_each_raw(ap, qc, tag) { if (!(qc->flags & ATA_QCFLAG_EH) || qc->flags & ATA_QCFLAG_RETRY || + qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD || ata_dev_phys_link(qc->dev) != link) continue; @@ -3813,16 +3920,30 @@ void ata_eh_finish(struct ata_port *ap) * generate sense data in this function, * considering both err_mask and tf. */ - if (qc->flags & ATA_QCFLAG_RETRY) + if (qc->flags & ATA_QCFLAG_RETRY) { + /* + * Since qc->err_mask is set, ata_eh_qc_retry() + * will not increment scmd->allowed, so upper + * layer will only retry the command if it has + * not already been retried too many times. + */ ata_eh_qc_retry(qc); - else + } else { ata_eh_qc_complete(qc); + } } else { - if (qc->flags & ATA_QCFLAG_SENSE_VALID) { + if (qc->flags & ATA_QCFLAG_SENSE_VALID || + qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) { ata_eh_qc_complete(qc); } else { /* feed zero TF to sense generation */ memset(&qc->result_tf, 0, sizeof(qc->result_tf)); + /* + * Since qc->err_mask is not set, + * ata_eh_qc_retry() will increment + * scmd->allowed, so upper layer is guaranteed + * to retry the command. + */ ata_eh_qc_retry(qc); } } diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c index f3e7396e3191..85e279a12f62 100644 --- a/drivers/ata/libata-sata.c +++ b/drivers/ata/libata-sata.c @@ -11,7 +11,9 @@ #include <linux/module.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_device.h> +#include <scsi/scsi_eh.h> #include <linux/libata.h> +#include <asm/unaligned.h> #include "libata.h" #include "libata-transport.h" @@ -907,10 +909,17 @@ static ssize_t ata_ncq_prio_enable_store(struct device *device, goto unlock; } - if (input) + if (input) { + if (dev->flags & ATA_DFLAG_CDL_ENABLED) { + ata_dev_err(dev, + "CDL must be disabled to enable NCQ priority\n"); + rc = -EINVAL; + goto unlock; + } dev->flags |= ATA_DFLAG_NCQ_PRIO_ENABLED; - else + } else { dev->flags &= ~ATA_DFLAG_NCQ_PRIO_ENABLED; + } unlock: spin_unlock_irq(ap->lock); @@ -1023,7 +1032,6 @@ EXPORT_SYMBOL_GPL(dev_attr_sw_activity); /** * ata_change_queue_depth - Set a device maximum queue depth * @ap: ATA port of the target device - * @dev: target ATA device * @sdev: SCSI device to configure queue depth for * @queue_depth: new queue depth * @@ -1031,33 +1039,47 @@ EXPORT_SYMBOL_GPL(dev_attr_sw_activity); * and libata. * */ -int ata_change_queue_depth(struct ata_port *ap, struct ata_device *dev, - struct scsi_device *sdev, int queue_depth) +int ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev, + int queue_depth) { + struct ata_device *dev; unsigned long flags; + int max_queue_depth; - if (!dev || !ata_dev_enabled(dev)) - return sdev->queue_depth; + spin_lock_irqsave(ap->lock, flags); - if (queue_depth < 1 || queue_depth == sdev->queue_depth) + dev = ata_scsi_find_dev(ap, sdev); + if (!dev || queue_depth < 1 || queue_depth == sdev->queue_depth) { + spin_unlock_irqrestore(ap->lock, flags); return sdev->queue_depth; + } - /* NCQ enabled? */ - spin_lock_irqsave(ap->lock, flags); - dev->flags &= ~ATA_DFLAG_NCQ_OFF; - if (queue_depth == 1 || !ata_ncq_enabled(dev)) { + /* + * Make sure that the queue depth requested does not exceed the device + * capabilities. + */ + max_queue_depth = min(ATA_MAX_QUEUE, sdev->host->can_queue); + max_queue_depth = min(max_queue_depth, ata_id_queue_depth(dev->id)); + if (queue_depth > max_queue_depth) { + spin_unlock_irqrestore(ap->lock, flags); + return -EINVAL; + } + + /* + * If NCQ is not supported by the device or if the target queue depth + * is 1 (to disable drive side command queueing), turn off NCQ. + */ + if (queue_depth == 1 || !ata_ncq_supported(dev)) { dev->flags |= ATA_DFLAG_NCQ_OFF; queue_depth = 1; + } else { + dev->flags &= ~ATA_DFLAG_NCQ_OFF; } - spin_unlock_irqrestore(ap->lock, flags); - /* limit and apply queue depth */ - queue_depth = min(queue_depth, sdev->host->can_queue); - queue_depth = min(queue_depth, ata_id_queue_depth(dev->id)); - queue_depth = min(queue_depth, ATA_MAX_QUEUE); + spin_unlock_irqrestore(ap->lock, flags); - if (sdev->queue_depth == queue_depth) - return -EINVAL; + if (queue_depth == sdev->queue_depth) + return sdev->queue_depth; return scsi_change_queue_depth(sdev, queue_depth); } @@ -1082,8 +1104,7 @@ int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth) { struct ata_port *ap = ata_shost_to_port(sdev->host); - return ata_change_queue_depth(ap, ata_scsi_find_dev(ap, sdev), - sdev, queue_depth); + return ata_change_queue_depth(ap, sdev, queue_depth); } EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth); @@ -1402,6 +1423,95 @@ static int ata_eh_read_log_10h(struct ata_device *dev, } /** + * ata_eh_read_sense_success_ncq_log - Read the sense data for successful + * NCQ commands log + * @link: ATA link to get sense data for + * + * Read the sense data for successful NCQ commands log page to obtain + * sense data for all NCQ commands that completed successfully with + * the sense data available bit set. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * 0 on success, -errno otherwise. + */ +int ata_eh_read_sense_success_ncq_log(struct ata_link *link) +{ + struct ata_device *dev = link->device; + struct ata_port *ap = dev->link->ap; + u8 *buf = ap->ncq_sense_buf; + struct ata_queued_cmd *qc; + unsigned int err_mask, tag; + u8 *sense, sk = 0, asc = 0, ascq = 0; + u64 sense_valid, val; + int ret = 0; + + err_mask = ata_read_log_page(dev, ATA_LOG_SENSE_NCQ, 0, buf, 2); + if (err_mask) { + ata_dev_err(dev, + "Failed to read Sense Data for Successful NCQ Commands log\n"); + return -EIO; + } + + /* Check the log header */ + val = get_unaligned_le64(&buf[0]); + if ((val & 0xffff) != 1 || ((val >> 16) & 0xff) != 0x0f) { + ata_dev_err(dev, + "Invalid Sense Data for Successful NCQ Commands log\n"); + return -EIO; + } + + sense_valid = (u64)buf[8] | ((u64)buf[9] << 8) | + ((u64)buf[10] << 16) | ((u64)buf[11] << 24); + + ata_qc_for_each_raw(ap, qc, tag) { + if (!(qc->flags & ATA_QCFLAG_EH) || + !(qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) || + qc->err_mask || + ata_dev_phys_link(qc->dev) != link) + continue; + + /* + * If the command does not have any sense data, clear ATA_SENSE. + * Keep ATA_QCFLAG_EH_SUCCESS_CMD so that command is finished. + */ + if (!(sense_valid & (1ULL << tag))) { + qc->result_tf.status &= ~ATA_SENSE; + continue; + } + + sense = &buf[32 + 24 * tag]; + sk = sense[0]; + asc = sense[1]; + ascq = sense[2]; + + if (!ata_scsi_sense_is_valid(sk, asc, ascq)) { + ret = -EIO; + continue; + } + + /* Set sense without also setting scsicmd->result */ + scsi_build_sense_buffer(dev->flags & ATA_DFLAG_D_SENSE, + qc->scsicmd->sense_buffer, sk, + asc, ascq); + qc->flags |= ATA_QCFLAG_SENSE_VALID; + + /* + * If we have sense data, call scsi_check_sense() in order to + * set the correct SCSI ML byte (if any). No point in checking + * the return value, since the command has already completed + * successfully. + */ + scsi_check_sense(qc->scsicmd); + } + + return ret; +} +EXPORT_SYMBOL_GPL(ata_eh_read_sense_success_ncq_log); + +/** * ata_eh_analyze_ncq_error - analyze NCQ error * @link: ATA link to analyze NCQ error for * @@ -1481,6 +1591,7 @@ void ata_eh_analyze_ncq_error(struct ata_link *link) ata_qc_for_each_raw(ap, qc, tag) { if (!(qc->flags & ATA_QCFLAG_EH) || + qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD || ata_dev_phys_link(qc->dev) != link) continue; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 551077cea4e4..370d18aca71e 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -37,7 +37,7 @@ #include "libata.h" #include "libata-transport.h" -#define ATA_SCSI_RBUF_SIZE 576 +#define ATA_SCSI_RBUF_SIZE 2048 static DEFINE_SPINLOCK(ata_scsi_rbuf_lock); static u8 ata_scsi_rbuf[ATA_SCSI_RBUF_SIZE]; @@ -47,15 +47,19 @@ typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc); static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev); -#define RW_RECOVERY_MPAGE 0x1 -#define RW_RECOVERY_MPAGE_LEN 12 -#define CACHE_MPAGE 0x8 -#define CACHE_MPAGE_LEN 20 -#define CONTROL_MPAGE 0xa -#define CONTROL_MPAGE_LEN 12 -#define ALL_MPAGES 0x3f -#define ALL_SUB_MPAGES 0xff - +#define RW_RECOVERY_MPAGE 0x1 +#define RW_RECOVERY_MPAGE_LEN 12 +#define CACHE_MPAGE 0x8 +#define CACHE_MPAGE_LEN 20 +#define CONTROL_MPAGE 0xa +#define CONTROL_MPAGE_LEN 12 +#define ALL_MPAGES 0x3f +#define ALL_SUB_MPAGES 0xff +#define CDL_T2A_SUB_MPAGE 0x07 +#define CDL_T2B_SUB_MPAGE 0x08 +#define CDL_T2_SUB_MPAGE_LEN 232 +#define ATA_FEATURE_SUB_MPAGE 0xf2 +#define ATA_FEATURE_SUB_MPAGE_LEN 16 static const u8 def_rw_recovery_mpage[RW_RECOVERY_MPAGE_LEN] = { RW_RECOVERY_MPAGE, @@ -209,9 +213,6 @@ void ata_scsi_set_sense(struct ata_device *dev, struct scsi_cmnd *cmd, { bool d_sense = (dev->flags & ATA_DFLAG_D_SENSE); - if (!cmd) - return; - scsi_build_sense(cmd, d_sense, sk, asc, ascq); } @@ -221,9 +222,6 @@ void ata_scsi_set_sense_information(struct ata_device *dev, { u64 information; - if (!cmd) - return; - information = ata_tf_read_block(tf, dev); if (information == U64_MAX) return; @@ -1122,7 +1120,7 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct ata_device *dev) if (dev->flags & ATA_DFLAG_AN) set_bit(SDEV_EVT_MEDIA_CHANGE, sdev->supported_events); - if (dev->flags & ATA_DFLAG_NCQ) + if (ata_ncq_supported(dev)) depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id)); depth = min(ATA_MAX_QUEUE, depth); scsi_change_queue_depth(sdev, depth); @@ -1383,6 +1381,18 @@ static inline void scsi_16_lba_len(const u8 *cdb, u64 *plba, u32 *plen) } /** + * scsi_dld - Get duration limit descriptor index + * @cdb: SCSI command to translate + * + * Returns the dld bits indicating the index of a command duration limit + * descriptor. + */ +static inline int scsi_dld(const u8 *cdb) +{ + return ((cdb[1] & 0x01) << 2) | ((cdb[14] >> 6) & 0x03); +} + +/** * ata_scsi_verify_xlat - Translate SCSI VERIFY command into an ATA one * @qc: Storage for translated ATA taskfile * @@ -1550,6 +1560,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) struct request *rq = scsi_cmd_to_rq(scmd); int class = IOPRIO_PRIO_CLASS(req_get_ioprio(rq)); unsigned int tf_flags = 0; + int dld = 0; u64 block; u32 n_block; int rc; @@ -1600,6 +1611,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) goto invalid_fld; } scsi_16_lba_len(cdb, &block, &n_block); + dld = scsi_dld(cdb); if (cdb[1] & (1 << 3)) tf_flags |= ATA_TFLAG_FUA; if (!ata_check_nblocks(scmd, n_block)) @@ -1624,7 +1636,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) qc->flags |= ATA_QCFLAG_IO; qc->nbytes = n_block * scmd->device->sector_size; - rc = ata_build_rw_tf(qc, block, n_block, tf_flags, class); + rc = ata_build_rw_tf(qc, block, n_block, tf_flags, dld, class); if (likely(rc == 0)) return 0; @@ -2203,10 +2215,123 @@ static unsigned int ata_msense_caching(u16 *id, u8 *buf, bool changeable) return sizeof(def_cache_mpage); } +/* + * Simulate MODE SENSE control mode page, sub-page 0. + */ +static unsigned int ata_msense_control_spg0(struct ata_device *dev, u8 *buf, + bool changeable) +{ + modecpy(buf, def_control_mpage, + sizeof(def_control_mpage), changeable); + if (changeable) { + /* ata_mselect_control() */ + buf[2] |= (1 << 2); + } else { + bool d_sense = (dev->flags & ATA_DFLAG_D_SENSE); + + /* descriptor format sense data */ + buf[2] |= (d_sense << 2); + } + + return sizeof(def_control_mpage); +} + +/* + * Translate an ATA duration limit in microseconds to a SCSI duration limit + * using the t2cdlunits 0xa (10ms). Since the SCSI duration limits are 2-bytes + * only, take care of overflows. + */ +static inline u16 ata_xlat_cdl_limit(u8 *buf) +{ + u32 limit = get_unaligned_le32(buf); + + return min_t(u32, limit / 10000, 65535); +} + +/* + * Simulate MODE SENSE control mode page, sub-pages 07h and 08h + * (command duration limits T2A and T2B mode pages). + */ +static unsigned int ata_msense_control_spgt2(struct ata_device *dev, u8 *buf, + u8 spg) +{ + u8 *b, *cdl = dev->cdl, *desc; + u32 policy; + int i; + + /* + * Fill the subpage. The first four bytes of the T2A/T2B mode pages + * are a header. The PAGE LENGTH field is the size of the page + * excluding the header. + */ + buf[0] = CONTROL_MPAGE; + buf[1] = spg; + put_unaligned_be16(CDL_T2_SUB_MPAGE_LEN - 4, &buf[2]); + if (spg == CDL_T2A_SUB_MPAGE) { + /* + * Read descriptors map to the T2A page: + * set perf_vs_duration_guidleine. + */ + buf[7] = (cdl[0] & 0x03) << 4; + desc = cdl + 64; + } else { + /* Write descriptors map to the T2B page */ + desc = cdl + 288; + } + + /* Fill the T2 page descriptors */ + b = &buf[8]; + policy = get_unaligned_le32(&cdl[0]); + for (i = 0; i < 7; i++, b += 32, desc += 32) { + /* t2cdlunits: fixed to 10ms */ + b[0] = 0x0a; + + /* Max inactive time and its policy */ + put_unaligned_be16(ata_xlat_cdl_limit(&desc[8]), &b[2]); + b[6] = ((policy >> 8) & 0x0f) << 4; + + /* Max active time and its policy */ + put_unaligned_be16(ata_xlat_cdl_limit(&desc[4]), &b[4]); + b[6] |= (policy >> 4) & 0x0f; + + /* Command duration guideline and its policy */ + put_unaligned_be16(ata_xlat_cdl_limit(&desc[16]), &b[10]); + b[14] = policy & 0x0f; + } + + return CDL_T2_SUB_MPAGE_LEN; +} + +/* + * Simulate MODE SENSE control mode page, sub-page f2h + * (ATA feature control mode page). + */ +static unsigned int ata_msense_control_ata_feature(struct ata_device *dev, + u8 *buf) +{ + /* PS=0, SPF=1 */ + buf[0] = CONTROL_MPAGE | (1 << 6); + buf[1] = ATA_FEATURE_SUB_MPAGE; + + /* + * The first four bytes of ATA Feature Control mode page are a header. + * The PAGE LENGTH field is the size of the page excluding the header. + */ + put_unaligned_be16(ATA_FEATURE_SUB_MPAGE_LEN - 4, &buf[2]); + + if (dev->flags & ATA_DFLAG_CDL) + buf[4] = 0x02; /* Support T2A and T2B pages */ + else + buf[4] = 0; + + return ATA_FEATURE_SUB_MPAGE_LEN; +} + /** * ata_msense_control - Simulate MODE SENSE control mode page * @dev: ATA device of interest * @buf: output buffer + * @spg: sub-page code * @changeable: whether changeable parameters are requested * * Generate a generic MODE SENSE control mode page. @@ -2215,17 +2340,27 @@ static unsigned int ata_msense_caching(u16 *id, u8 *buf, bool changeable) * None. */ static unsigned int ata_msense_control(struct ata_device *dev, u8 *buf, - bool changeable) + u8 spg, bool changeable) { - modecpy(buf, def_control_mpage, sizeof(def_control_mpage), changeable); - if (changeable) { - buf[2] |= (1 << 2); /* ata_mselect_control() */ - } else { - bool d_sense = (dev->flags & ATA_DFLAG_D_SENSE); - - buf[2] |= (d_sense << 2); /* descriptor format sense data */ + unsigned int n; + + switch (spg) { + case 0: + return ata_msense_control_spg0(dev, buf, changeable); + case CDL_T2A_SUB_MPAGE: + case CDL_T2B_SUB_MPAGE: + return ata_msense_control_spgt2(dev, buf, spg); + case ATA_FEATURE_SUB_MPAGE: + return ata_msense_control_ata_feature(dev, buf); + case ALL_SUB_MPAGES: + n = ata_msense_control_spg0(dev, buf, changeable); + n += ata_msense_control_spgt2(dev, buf + n, CDL_T2A_SUB_MPAGE); + n += ata_msense_control_spgt2(dev, buf + n, CDL_T2A_SUB_MPAGE); + n += ata_msense_control_ata_feature(dev, buf + n); + return n; + default: + return 0; } - return sizeof(def_control_mpage); } /** @@ -2298,13 +2433,25 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) pg = scsicmd[2] & 0x3f; spg = scsicmd[3]; + /* - * No mode subpages supported (yet) but asking for _all_ - * subpages may be valid + * Supported subpages: all subpages and sub-pages 07h, 08h and f2h of + * the control page. */ - if (spg && (spg != ALL_SUB_MPAGES)) { - fp = 3; - goto invalid_fld; + if (spg) { + switch (spg) { + case ALL_SUB_MPAGES: + break; + case CDL_T2A_SUB_MPAGE: + case CDL_T2B_SUB_MPAGE: + case ATA_FEATURE_SUB_MPAGE: + if (dev->flags & ATA_DFLAG_CDL && pg == CONTROL_MPAGE) + break; + fallthrough; + default: + fp = 3; + goto invalid_fld; + } } switch(pg) { @@ -2317,13 +2464,13 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) break; case CONTROL_MPAGE: - p += ata_msense_control(args->dev, p, page_control == 1); + p += ata_msense_control(args->dev, p, spg, page_control == 1); break; case ALL_MPAGES: p += ata_msense_rw_recovery(p, page_control == 1); p += ata_msense_caching(args->id, p, page_control == 1); - p += ata_msense_control(args->dev, p, page_control == 1); + p += ata_msense_control(args->dev, p, spg, page_control == 1); break; default: /* invalid page code */ @@ -2342,10 +2489,7 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) memcpy(rbuf + 4, sat_blk_desc, sizeof(sat_blk_desc)); } } else { - unsigned int output_len = p - rbuf - 2; - - rbuf[0] = output_len >> 8; - rbuf[1] = output_len; + put_unaligned_be16(p - rbuf - 2, &rbuf[0]); rbuf[3] |= dpofua; if (ebd) { rbuf[7] = sizeof(sat_blk_desc); @@ -3260,7 +3404,7 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf) { struct ata_device *dev = args->dev; u8 *cdb = args->cmd->cmnd; - u8 supported = 0; + u8 supported = 0, cdlp = 0, rwcdlp = 0; unsigned int err = 0; if (cdb[2] != 1 && cdb[2] != 3) { @@ -3287,10 +3431,8 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf) case MAINTENANCE_IN: case READ_6: case READ_10: - case READ_16: case WRITE_6: case WRITE_10: - case WRITE_16: case ATA_12: case ATA_16: case VERIFY: @@ -3300,6 +3442,28 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf) case START_STOP: supported = 3; break; + case READ_16: + supported = 3; + if (dev->flags & ATA_DFLAG_CDL) { + /* + * CDL read descriptors map to the T2A page, that is, + * rwcdlp = 0x01 and cdlp = 0x01 + */ + rwcdlp = 0x01; + cdlp = 0x01 << 3; + } + break; + case WRITE_16: + supported = 3; + if (dev->flags & ATA_DFLAG_CDL) { + /* + * CDL write descriptors map to the T2B page, that is, + * rwcdlp = 0x01 and cdlp = 0x02 + */ + rwcdlp = 0x01; + cdlp = 0x02 << 3; + } + break; case ZBC_IN: case ZBC_OUT: if (ata_id_zoned_cap(dev->id) || @@ -3315,7 +3479,9 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf) break; } out: - rbuf[1] = supported; /* supported */ + /* One command format */ + rbuf[0] = rwcdlp; + rbuf[1] = cdlp | supported; return err; } @@ -3605,20 +3771,11 @@ static int ata_mselect_caching(struct ata_queued_cmd *qc, return 0; } -/** - * ata_mselect_control - Simulate MODE SELECT for control page - * @qc: Storage for translated ATA taskfile - * @buf: input buffer - * @len: number of valid bytes in the input buffer - * @fp: out parameter for the failed field on error - * - * Prepare a taskfile to modify caching information for the device. - * - * LOCKING: - * None. +/* + * Simulate MODE SELECT control mode page, sub-page 0. */ -static int ata_mselect_control(struct ata_queued_cmd *qc, - const u8 *buf, int len, u16 *fp) +static int ata_mselect_control_spg0(struct ata_queued_cmd *qc, + const u8 *buf, int len, u16 *fp) { struct ata_device *dev = qc->dev; u8 mpage[CONTROL_MPAGE_LEN]; @@ -3640,7 +3797,7 @@ static int ata_mselect_control(struct ata_queued_cmd *qc, /* * Check that read-only bits are not modified. */ - ata_msense_control(dev, mpage, false); + ata_msense_control_spg0(dev, mpage, false); for (i = 0; i < CONTROL_MPAGE_LEN - 2; i++) { if (i == 0) continue; @@ -3656,6 +3813,84 @@ static int ata_mselect_control(struct ata_queued_cmd *qc, return 0; } +/* + * Translate MODE SELECT control mode page, sub-pages f2h (ATA feature mode + * page) into a SET FEATURES command. + */ +static unsigned int ata_mselect_control_ata_feature(struct ata_queued_cmd *qc, + const u8 *buf, int len, + u16 *fp) +{ + struct ata_device *dev = qc->dev; + struct ata_taskfile *tf = &qc->tf; + u8 cdl_action; + + /* + * The first four bytes of ATA Feature Control mode page are a header, + * so offsets in mpage are off by 4 compared to buf. Same for len. + */ + if (len != ATA_FEATURE_SUB_MPAGE_LEN - 4) { + *fp = min(len, ATA_FEATURE_SUB_MPAGE_LEN - 4); + return -EINVAL; + } + + /* Check cdl_ctrl */ + switch (buf[0] & 0x03) { + case 0: + /* Disable CDL */ + cdl_action = 0; + dev->flags &= ~ATA_DFLAG_CDL_ENABLED; + break; + case 0x02: + /* Enable CDL T2A/T2B: NCQ priority must be disabled */ + if (dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLED) { + ata_dev_err(dev, + "NCQ priority must be disabled to enable CDL\n"); + return -EINVAL; + } + cdl_action = 1; + dev->flags |= ATA_DFLAG_CDL_ENABLED; + break; + default: + *fp = 0; + return -EINVAL; + } + + tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR; + tf->protocol = ATA_PROT_NODATA; + tf->command = ATA_CMD_SET_FEATURES; + tf->feature = SETFEATURES_CDL; + tf->nsect = cdl_action; + + return 1; +} + +/** + * ata_mselect_control - Simulate MODE SELECT for control page + * @qc: Storage for translated ATA taskfile + * @spg: target sub-page of the control page + * @buf: input buffer + * @len: number of valid bytes in the input buffer + * @fp: out parameter for the failed field on error + * + * Prepare a taskfile to modify caching information for the device. + * + * LOCKING: + * None. + */ +static int ata_mselect_control(struct ata_queued_cmd *qc, u8 spg, + const u8 *buf, int len, u16 *fp) +{ + switch (spg) { + case 0: + return ata_mselect_control_spg0(qc, buf, len, fp); + case ATA_FEATURE_SUB_MPAGE: + return ata_mselect_control_ata_feature(qc, buf, len, fp); + default: + return -EINVAL; + } +} + /** * ata_scsi_mode_select_xlat - Simulate MODE SELECT 6, 10 commands * @qc: Storage for translated ATA taskfile @@ -3673,7 +3908,7 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) const u8 *cdb = scmd->cmnd; u8 pg, spg; unsigned six_byte, pg_len, hdr_len, bd_len; - int len; + int len, ret; u16 fp = (u16)-1; u8 bp = 0xff; u8 buffer[64]; @@ -3758,13 +3993,29 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) } /* - * No mode subpages supported (yet) but asking for _all_ - * subpages may be valid + * Supported subpages: all subpages and ATA feature sub-page f2h of + * the control page. */ - if (spg && (spg != ALL_SUB_MPAGES)) { - fp = (p[0] & 0x40) ? 1 : 0; - fp += hdr_len + bd_len; - goto invalid_param; + if (spg) { + switch (spg) { + case ALL_SUB_MPAGES: + /* All subpages is not supported for the control page */ + if (pg == CONTROL_MPAGE) { + fp = (p[0] & 0x40) ? 1 : 0; + fp += hdr_len + bd_len; + goto invalid_param; + } + break; + case ATA_FEATURE_SUB_MPAGE: + if (qc->dev->flags & ATA_DFLAG_CDL && + pg == CONTROL_MPAGE) + break; + fallthrough; + default: + fp = (p[0] & 0x40) ? 1 : 0; + fp += hdr_len + bd_len; + goto invalid_param; + } } if (pg_len > len) goto invalid_param_len; @@ -3777,14 +4028,16 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) } break; case CONTROL_MPAGE: - if (ata_mselect_control(qc, p, pg_len, &fp) < 0) { + ret = ata_mselect_control(qc, spg, p, pg_len, &fp); + if (ret < 0) { fp += hdr_len + bd_len; goto invalid_param; - } else { - goto skip; /* No ATA command to send */ } + if (!ret) + goto skip; /* No ATA command to send */ break; - default: /* invalid page code */ + default: + /* Invalid page code */ fp = bd_len + hdr_len; goto invalid_param; } diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 926d0d33cd29..cf993885d2b2 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -45,7 +45,7 @@ static inline void ata_force_cbl(struct ata_port *ap) { } extern u64 ata_tf_to_lba(const struct ata_taskfile *tf); extern u64 ata_tf_to_lba48(const struct ata_taskfile *tf); extern int ata_build_rw_tf(struct ata_queued_cmd *qc, u64 block, u32 n_block, - unsigned int tf_flags, int class); + unsigned int tf_flags, int dld, int class); extern u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev); extern unsigned ata_exec_internal(struct ata_device *dev, diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c index 99a2ce723495..b1daa4d3fcd9 100644 --- a/drivers/ata/pata_ixp4xx_cf.c +++ b/drivers/ata/pata_ixp4xx_cf.c @@ -303,7 +303,7 @@ static struct platform_driver ixp4xx_pata_platform_driver = { .of_match_table = ixp4xx_pata_of_match, }, .probe = ixp4xx_pata_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, }; module_platform_driver(ixp4xx_pata_platform_driver); diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c index b1ce9f1761af..ff538b858928 100644 --- a/drivers/ata/pata_octeon_cf.c +++ b/drivers/ata/pata_octeon_cf.c @@ -16,6 +16,7 @@ #include <linux/slab.h> #include <linux/irq.h> #include <linux/of.h> +#include <linux/of_address.h> #include <linux/of_platform.h> #include <linux/platform_device.h> #include <scsi/scsi_host.h> @@ -804,9 +805,7 @@ static int octeon_cf_probe(struct platform_device *pdev) struct resource *res_cs0, *res_cs1; bool is_16bit; - const __be32 *cs_num; - struct property *reg_prop; - int n_addr, n_size, reg_len; + u64 reg; struct device_node *node; void __iomem *cs0; void __iomem *cs1 = NULL; @@ -834,15 +833,10 @@ static int octeon_cf_probe(struct platform_device *pdev) else is_16bit = false; - n_addr = of_n_addr_cells(node); - n_size = of_n_size_cells(node); - - reg_prop = of_find_property(node, "reg", ®_len); - if (!reg_prop || reg_len < sizeof(__be32)) - return -EINVAL; - - cs_num = reg_prop->value; - cf_port->cs0 = be32_to_cpup(cs_num); + rv = of_property_read_reg(node, 0, ®, NULL); + if (rv < 0) + return rv; + cf_port->cs0 = upper_32_bits(reg); if (cf_port->is_true_ide) { struct device_node *dma_node; @@ -884,13 +878,12 @@ static int octeon_cf_probe(struct platform_device *pdev) cs1 = devm_ioremap(&pdev->dev, res_cs1->start, resource_size(res_cs1)); if (!cs1) - return rv; - - if (reg_len < (n_addr + n_size + 1) * sizeof(__be32)) return -EINVAL; - cs_num += n_addr + n_size; - cf_port->cs1 = be32_to_cpup(cs_num); + rv = of_property_read_reg(node, 1, ®, NULL); + if (rv < 0) + return rv; + cf_port->cs1 = upper_32_bits(reg); } res_cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c index 178b28eff170..4956f0f5b93f 100644 --- a/drivers/ata/pata_of_platform.c +++ b/drivers/ata/pata_of_platform.c @@ -89,7 +89,7 @@ static struct platform_driver pata_of_platform_driver = { .of_match_table = pata_of_platform_match, }, .probe = pata_of_platform_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, }; module_platform_driver(pata_of_platform_driver); diff --git a/drivers/ata/pata_parport/aten.c b/drivers/ata/pata_parport/aten.c index 1bd248c42f8b..8328a49a95ef 100644 --- a/drivers/ata/pata_parport/aten.c +++ b/drivers/ata/pata_parport/aten.c @@ -1,13 +1,12 @@ -/* - aten.c (c) 1997-8 Grant R. Guenther <grant@torque.net> - Under the terms of the GNU General Public License. - - aten.c is a low-level protocol driver for the ATEN EH-100 - parallel port adapter. The EH-100 supports 4-bit and 8-bit - modes only. There is also an EH-132 which supports EPP mode - transfers. The EH-132 is not yet supported. - -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1997-8 Grant R. Guenther <grant@torque.net> + * + * aten.c is a low-level protocol driver for the ATEN EH-100 + * parallel port adapter. The EH-100 supports 4-bit and 8-bit + * modes only. There is also an EH-132 which supports EPP mode + * transfers. The EH-132 is not yet supported. + */ #include <linux/module.h> #include <linux/init.h> @@ -20,36 +19,36 @@ #define j44(a,b) ((((a>>4)&0x0f)|(b&0xf0))^0x88) -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set -*/ - +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + */ static int cont_map[2] = { 0x08, 0x20 }; static void aten_write_regr(struct pi_adapter *pi, int cont, int regr, int val) - -{ int r; - - r = regr + cont_map[cont] + 0x80; +{ + int r = regr + cont_map[cont] + 0x80; w0(r); w2(0xe); w2(6); w0(val); w2(7); w2(6); w2(0xc); } static int aten_read_regr(struct pi_adapter *pi, int cont, int regr) +{ + int a, b, r; -{ int a, b, r; - - r = regr + cont_map[cont] + 0x40; + r = regr + cont_map[cont] + 0x40; switch (pi->mode) { - case 0: w0(r); w2(0xe); w2(6); + case 0: + w0(r); w2(0xe); w2(6); w2(7); w2(6); w2(0); a = r1(); w0(0x10); b = r1(); w2(0xc); return j44(a,b); - case 1: r |= 0x10; - w0(r); w2(0xe); w2(6); w0(0xff); + case 1: + r |= 0x10; + w0(r); w2(0xe); w2(6); w0(0xff); w2(0x27); w2(0x26); w2(0x20); a = r0(); w2(0x26); w2(0xc); @@ -59,27 +58,30 @@ static int aten_read_regr(struct pi_adapter *pi, int cont, int regr) } static void aten_read_block(struct pi_adapter *pi, char *buf, int count) - -{ int k, a, b, c, d; +{ + int k, a, b, c, d; switch (pi->mode) { - case 0: w0(0x48); w2(0xe); w2(6); - for (k=0;k<count/2;k++) { + case 0: + w0(0x48); w2(0xe); w2(6); + for (k = 0; k < count / 2; k++) { w2(7); w2(6); w2(2); a = r1(); w0(0x58); b = r1(); w2(0); d = r1(); w0(0x48); c = r1(); - buf[2*k] = j44(c,d); - buf[2*k+1] = j44(a,b); + buf[2 * k] = j44(c, d); + buf[2 * k + 1] = j44(a, b); } w2(0xc); break; - case 1: w0(0x58); w2(0xe); w2(6); - for (k=0;k<count/2;k++) { + case 1: + w0(0x58); w2(0xe); w2(6); + for (k = 0; k < count / 2; k++) { w2(0x27); w2(0x26); w2(0x22); a = r0(); w2(0x20); b = r0(); - buf[2*k] = b; buf[2*k+1] = a; + buf[2 * k] = b; + buf[2 * k + 1] = a; } w2(0x26); w2(0xc); break; @@ -87,36 +89,37 @@ static void aten_read_block(struct pi_adapter *pi, char *buf, int count) } static void aten_write_block(struct pi_adapter *pi, char *buf, int count) - -{ int k; +{ + int k; w0(0x88); w2(0xe); w2(6); - for (k=0;k<count/2;k++) { - w0(buf[2*k+1]); w2(0xe); w2(6); - w0(buf[2*k]); w2(7); w2(6); + for (k = 0; k < count / 2; k++) { + w0(buf[2 * k + 1]); w2(0xe); w2(6); + w0(buf[2 * k]); w2(7); w2(6); } w2(0xc); } static void aten_connect(struct pi_adapter *pi) - -{ pi->saved_r0 = r0(); - pi->saved_r2 = r2(); - w2(0xc); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); + w2(0xc); } static void aten_disconnect(struct pi_adapter *pi) - -{ w0(pi->saved_r0); - w2(pi->saved_r2); -} +{ + w0(pi->saved_r0); + w2(pi->saved_r2); +} static void aten_log_adapter(struct pi_adapter *pi) +{ + char *mode_string[2] = { "4-bit", "8-bit" }; -{ char *mode_string[2] = {"4-bit","8-bit"}; - - dev_info(&pi->dev, "ATEN EH-100 at 0x%x, mode %d (%s), delay %d\n", - pi->port, pi->mode, mode_string[pi->mode], pi->delay); + dev_info(&pi->dev, + "ATEN EH-100 at 0x%x, mode %d (%s), delay %d\n", + pi->port, pi->mode, mode_string[pi->mode], pi->delay); } static struct pi_protocol aten = { diff --git a/drivers/ata/pata_parport/bpck.c b/drivers/ata/pata_parport/bpck.c index 1c5035a09554..9f4309f9b57f 100644 --- a/drivers/ata/pata_parport/bpck.c +++ b/drivers/ata/pata_parport/bpck.c @@ -1,11 +1,10 @@ -/* - bpck.c (c) 1996-8 Grant R. Guenther <grant@torque.net> - Under the terms of the GNU General Public License. - - bpck.c is a low-level protocol driver for the MicroSolutions - "backpack" parallel port IDE adapter. - -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1996-1998 Grant R. Guenther <grant@torque.net> + * + * bpck.c is a low-level protocol driver for the MicroSolutions + * "backpack" parallel port IDE adapter. + */ #include <linux/module.h> #include <linux/init.h> @@ -29,59 +28,57 @@ #define j44(l,h) (((l>>3)&0x7)|((l>>4)&0x8)|((h<<1)&0x70)|(h&0x80)) -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set - cont = 2 - use internal bpck register addressing -*/ - +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + * cont = 2 - use internal bpck register addressing + */ static int cont_map[3] = { 0x40, 0x48, 0 }; static int bpck_read_regr(struct pi_adapter *pi, int cont, int regr) - -{ int r, l, h; +{ + int r, l, h; r = regr + cont_map[cont]; switch (pi->mode) { - - case 0: w0(r & 0xf); w0(r); t2(2); t2(4); + case 0: + w0(r & 0xf); w0(r); t2(2); t2(4); l = r1(); - t2(4); - h = r1(); - return j44(l,h); - - case 1: w0(r & 0xf); w0(r); t2(2); - e2(); t2(0x20); + t2(4); + h = r1(); + return j44(l, h); + case 1: + w0(r & 0xf); w0(r); t2(2); + e2(); t2(0x20); t2(4); h = r0(); - t2(1); t2(0x20); - return h; - + t2(1); t2(0x20); + return h; case 2: case 3: - case 4: w0(r); w2(9); w2(0); w2(0x20); + case 4: + w0(r); w2(9); w2(0); w2(0x20); h = r4(); w2(0); return h; } return -1; -} +} static void bpck_write_regr(struct pi_adapter *pi, int cont, int regr, int val) - -{ int r; +{ + int r; r = regr + cont_map[cont]; switch (pi->mode) { - case 0: case 1: w0(r); t2(2); w0(val); o2(); t2(4); t2(1); break; - case 2: case 3: case 4: w0(r); w2(9); w2(0); @@ -97,210 +94,249 @@ static void bpck_write_regr(struct pi_adapter *pi, int cont, int regr, int val) #define RR(r) (bpck_read_regr(pi,2,r)) static void bpck_write_block(struct pi_adapter *pi, char *buf, int count) - -{ int i; +{ + int i; switch (pi->mode) { - case 0: WR(4,0x40); + case 0: + WR(4, 0x40); + w0(0x40); t2(2); t2(1); + for (i = 0; i < count; i++) { + w0(buf[i]); + t2(4); + } + WR(4, 0); + break; + + case 1: + WR(4, 0x50); w0(0x40); t2(2); t2(1); - for (i=0;i<count;i++) { w0(buf[i]); t2(4); } - WR(4,0); + for (i = 0; i < count; i++) { + w0(buf[i]); + t2(4); + } + WR(4, 0x10); break; - case 1: WR(4,0x50); - w0(0x40); t2(2); t2(1); - for (i=0;i<count;i++) { w0(buf[i]); t2(4); } - WR(4,0x10); + case 2: + WR(4, 0x48); + w0(0x40); w2(9); w2(0); w2(1); + for (i = 0; i < count; i++) + w4(buf[i]); + w2(0); + WR(4, 8); break; - case 2: WR(4,0x48); + case 3: + WR(4, 0x48); w0(0x40); w2(9); w2(0); w2(1); - for (i=0;i<count;i++) w4(buf[i]); + for (i = 0; i < count / 2; i++) + w4w(((u16 *)buf)[i]); w2(0); - WR(4,8); + WR(4, 8); break; - case 3: WR(4,0x48); - w0(0x40); w2(9); w2(0); w2(1); - for (i=0;i<count/2;i++) w4w(((u16 *)buf)[i]); - w2(0); - WR(4,8); - break; - - case 4: WR(4,0x48); - w0(0x40); w2(9); w2(0); w2(1); - for (i=0;i<count/4;i++) w4l(((u32 *)buf)[i]); - w2(0); - WR(4,8); - break; + case 4: + WR(4, 0x48); + w0(0x40); w2(9); w2(0); w2(1); + for (i = 0; i < count / 4; i++) + w4l(((u32 *)buf)[i]); + w2(0); + WR(4, 8); + break; } } static void bpck_read_block(struct pi_adapter *pi, char *buf, int count) - -{ int i, l, h; +{ + int i, l, h; switch (pi->mode) { - case 0: WR(4,0x40); + case 0: + WR(4, 0x40); w0(0x40); t2(2); - for (i=0;i<count;i++) { - t2(4); l = r1(); - t2(4); h = r1(); - buf[i] = j44(l,h); + for (i = 0; i < count; i++) { + t2(4); l = r1(); + t2(4); h = r1(); + buf[i] = j44(l, h); } - WR(4,0); + WR(4, 0); break; - case 1: WR(4,0x50); + case 1: + WR(4, 0x50); w0(0x40); t2(2); t2(0x20); - for(i=0;i<count;i++) { t2(4); buf[i] = r0(); } - t2(1); t2(0x20); - WR(4,0x10); + for (i = 0; i < count; i++) { + t2(4); + buf[i] = r0(); + } + t2(1); t2(0x20); + WR(4, 0x10); break; - case 2: WR(4,0x48); + case 2: + WR(4, 0x48); w0(0x40); w2(9); w2(0); w2(0x20); - for (i=0;i<count;i++) buf[i] = r4(); + for (i = 0; i < count; i++) + buf[i] = r4(); w2(0); - WR(4,8); + WR(4, 8); break; - case 3: WR(4,0x48); - w0(0x40); w2(9); w2(0); w2(0x20); - for (i=0;i<count/2;i++) ((u16 *)buf)[i] = r4w(); - w2(0); - WR(4,8); - break; + case 3: + WR(4, 0x48); + w0(0x40); w2(9); w2(0); w2(0x20); + for (i = 0; i < count / 2; i++) + ((u16 *)buf)[i] = r4w(); + w2(0); + WR(4, 8); + break; - case 4: WR(4,0x48); - w0(0x40); w2(9); w2(0); w2(0x20); - for (i=0;i<count/4;i++) ((u32 *)buf)[i] = r4l(); - w2(0); - WR(4,8); - break; + case 4: + WR(4, 0x48); + w0(0x40); w2(9); w2(0); w2(0x20); + for (i = 0; i < count / 4; i++) + ((u32 *)buf)[i] = r4l(); + w2(0); + WR(4, 8); + break; } } static int bpck_probe_unit(struct pi_adapter *pi) - -{ int o1, o0, f7, id; +{ + int o1, o0, f7, id; int t, s; id = pi->unit; s = 0; - w2(4); w2(0xe); r2(); t2(2); + w2(4); w2(0xe); r2(); t2(2); o1 = r1()&0xf8; o0 = r0(); w0(255-id); w2(4); w0(id); t2(8); t2(8); t2(8); t2(2); t = r1()&0xf8; f7 = ((id % 8) == 7); - if ((f7) || (t != o1)) { t2(2); s = r1()&0xf8; } + if ((f7) || (t != o1)) { + t2(2); + s = r1() & 0xf8; + } if ((t == o1) && ((!f7) || (s == o1))) { w2(0x4c); w0(o0); - return 0; + return 0; } t2(8); w0(0); t2(2); w2(0x4c); w0(o0); return 1; } - -static void bpck_connect(struct pi_adapter *pi) -{ pi->saved_r0 = r0(); +static void bpck_connect(struct pi_adapter *pi) +{ + pi->saved_r0 = r0(); w0(0xff-pi->unit); w2(4); w0(pi->unit); - t2(8); t2(8); t2(8); + t2(8); t2(8); t2(8); t2(2); t2(2); - - switch (pi->mode) { - case 0: t2(8); WR(4,0); + switch (pi->mode) { + case 0: + t2(8); WR(4, 0); break; - - case 1: t2(8); WR(4,0x10); + case 1: + t2(8); WR(4, 0x10); break; - case 2: - case 3: - case 4: w2(0); WR(4,8); + case 3: + case 4: + w2(0); WR(4, 8); break; - } WR(5,8); -/* if (pi->devtype == PI_PCD) { possibly wrong, purpose unknown */ - WR(0x46,0x10); /* fiddle with ESS logic ??? */ - WR(0x4c,0x38); - WR(0x4d,0x88); - WR(0x46,0xa0); - WR(0x41,0); - WR(0x4e,8); -/* }*/ + /* + * Possibly wrong, purpose unknown (fiddle with ESS logic ???) + * if (pi->devtype == PI_PCD) { + */ + WR(0x46, 0x10); + WR(0x4c, 0x38); + WR(0x4d, 0x88); + WR(0x46, 0xa0); + WR(0x41, 0); + WR(0x4e, 8); + /* } */ } static void bpck_disconnect(struct pi_adapter *pi) - -{ w0(0); - if (pi->mode >= 2) { w2(9); w2(0); } else t2(2); +{ + w0(0); + if (pi->mode >= 2) { + w2(9); w2(0); + } else { + t2(2); + } w2(0x4c); w0(pi->saved_r0); -} +} static void bpck_force_spp(struct pi_adapter *pi) +{ + /* This fakes the EPP protocol to turn off EPP ... */ + pi->saved_r0 = r0(); + w0(0xff-pi->unit); w2(4); w0(pi->unit); + t2(8); t2(8); t2(8); + t2(2); t2(2); -/* This fakes the EPP protocol to turn off EPP ... */ - -{ pi->saved_r0 = r0(); - w0(0xff-pi->unit); w2(4); w0(pi->unit); - t2(8); t2(8); t2(8); - t2(2); t2(2); - - w2(0); - w0(4); w2(9); w2(0); - w0(0); w2(1); w2(3); w2(0); - w0(0); w2(9); w2(0); - w2(0x4c); w0(pi->saved_r0); + w2(0); + w0(4); w2(9); w2(0); + w0(0); w2(1); w2(3); w2(0); + w0(0); w2(9); w2(0); + w2(0x4c); w0(pi->saved_r0); } #define TEST_LEN 16 static int bpck_test_proto(struct pi_adapter *pi) - -{ int i, e, l, h, om; +{ + int i, e, l, h, om; char buf[TEST_LEN]; bpck_force_spp(pi); switch (pi->mode) { - case 0: bpck_connect(pi); - WR(0x13,0x7f); + case 0: + bpck_connect(pi); + WR(0x13, 0x7f); w0(0x13); t2(2); - for(i=0;i<TEST_LEN;i++) { - t2(4); l = r1(); - t2(4); h = r1(); - buf[i] = j44(l,h); + for (i = 0; i < TEST_LEN; i++) { + t2(4); l = r1(); + t2(4); h = r1(); + buf[i] = j44(l, h); } bpck_disconnect(pi); break; - case 1: bpck_connect(pi); - WR(0x13,0x7f); - w0(0x13); t2(2); t2(0x20); - for(i=0;i<TEST_LEN;i++) { t2(4); buf[i] = r0(); } - t2(1); t2(0x20); + case 1: + bpck_connect(pi); + WR(0x13, 0x7f); + w0(0x13); t2(2); t2(0x20); + for (i = 0; i < TEST_LEN; i++) { + t2(4); + buf[i] = r0(); + } + t2(1); t2(0x20); bpck_disconnect(pi); break; case 2: case 3: - case 4: om = pi->mode; + case 4: + om = pi->mode; pi->mode = 0; bpck_connect(pi); - WR(7,3); - WR(4,8); + WR(7, 3); + WR(4, 8); bpck_disconnect(pi); pi->mode = om; @@ -308,34 +344,44 @@ static int bpck_test_proto(struct pi_adapter *pi) w0(0x13); w2(9); w2(1); w0(0); w2(3); w2(0); w2(0xe0); switch (pi->mode) { - case 2: for (i=0;i<TEST_LEN;i++) buf[i] = r4(); - break; - case 3: for (i=0;i<TEST_LEN/2;i++) ((u16 *)buf)[i] = r4w(); - break; - case 4: for (i=0;i<TEST_LEN/4;i++) ((u32 *)buf)[i] = r4l(); - break; + case 2: + for (i = 0; i < TEST_LEN; i++) + buf[i] = r4(); + break; + case 3: + for (i = 0; i < TEST_LEN / 2; i++) + ((u16 *)buf)[i] = r4w(); + break; + case 4: + for (i = 0; i < TEST_LEN / 4; i++) + ((u32 *)buf)[i] = r4l(); + break; } w2(0); - WR(7,0); + WR(7, 0); bpck_disconnect(pi); - break; } dev_dbg(&pi->dev, "bpck: 0x%x unit %d mode %d: ", pi->port, pi->unit, pi->mode); - print_hex_dump_debug("bpck: ", DUMP_PREFIX_NONE, TEST_LEN, 1, buf, TEST_LEN, false); + print_hex_dump_debug("bpck: ", DUMP_PREFIX_NONE, TEST_LEN, 1, buf, + TEST_LEN, false); e = 0; - for (i=0;i<TEST_LEN;i++) if (buf[i] != (i+1)) e++; + for (i = 0; i < TEST_LEN; i++) { + if (buf[i] != i + 1) + e++; + } + return e; } static void bpck_read_eeprom(struct pi_adapter *pi, char *buf) - -{ int i, j, k, p, v, f, om, od; +{ + int i, j, k, p, v, f, om, od; bpck_force_spp(pi); @@ -343,77 +389,97 @@ static void bpck_read_eeprom(struct pi_adapter *pi, char *buf) pi->mode = 0; pi->delay = 6; bpck_connect(pi); - - WR(4,0); - for (i=0;i<64;i++) { - WR(6,8); - WR(6,0xc); - p = 0x100; - for (k=0;k<9;k++) { - f = (((i + 0x180) & p) != 0) * 2; - WR(6,f+0xc); - WR(6,f+0xd); - WR(6,f+0xc); - p = (p >> 1); - } - for (j=0;j<2;j++) { - v = 0; - for (k=0;k<8;k++) { - WR(6,0xc); - WR(6,0xd); - WR(6,0xc); - f = RR(0); - v = 2*v + (f == 0x84); + + WR(4, 0); + for (i = 0; i < 64; i++) { + WR(6, 8); + WR(6, 0xc); + p = 0x100; + for (k = 0; k < 9; k++) { + f = (((i + 0x180) & p) != 0) * 2; + WR(6, f + 0xc); + WR(6, f + 0xd); + WR(6, f + 0xc); + p = (p >> 1); + } + for (j = 0; j < 2; j++) { + v = 0; + for (k = 0; k < 8; k++) { + WR(6, 0xc); + WR(6, 0xd); + WR(6, 0xc); + f = RR(0); + v = 2 * v + (f == 0x84); + } + buf[2 * i + 1 - j] = v; } - buf[2*i+1-j] = v; - } } - WR(6,8); - WR(6,0); - WR(5,8); + WR(6, 8); + WR(6, 0); + WR(5, 8); bpck_disconnect(pi); if (om >= 2) { - bpck_connect(pi); - WR(7,3); - WR(4,8); - bpck_disconnect(pi); + bpck_connect(pi); + WR(7, 3); + WR(4, 8); + bpck_disconnect(pi); } pi->mode = om; pi->delay = od; } -static int bpck_test_port(struct pi_adapter *pi) /* check for 8-bit port */ - -{ int i, r, m; +static int bpck_test_port(struct pi_adapter *pi) +{ + int i, r, m; + /* Check for 8-bit port */ w2(0x2c); i = r0(); w0(255-i); r = r0(); w0(i); m = -1; - if (r == i) m = 2; - if (r == (255-i)) m = 0; + if (r == i) + m = 2; + if (r == (255-i)) + m = 0; + + w2(0xc); + i = r0(); + w0(255-i); + r = r0(); + w0(i); + if (r != (255-i)) + m = -1; + + if (m == 0) { + w2(6); + w2(0xc); + r = r0(); + w0(0xaa); + w0(r); + w0(0xaa); + } + if (m == 2) { + w2(0x26); + w2(0xc); + } - w2(0xc); i = r0(); w0(255-i); r = r0(); w0(i); - if (r != (255-i)) m = -1; - - if (m == 0) { w2(6); w2(0xc); r = r0(); w0(0xaa); w0(r); w0(0xaa); } - if (m == 2) { w2(0x26); w2(0xc); } + if (m == -1) + return 0; - if (m == -1) return 0; return 5; } static void bpck_log_adapter(struct pi_adapter *pi) - -{ char *mode_string[5] = { "4-bit","8-bit","EPP-8", - "EPP-16","EPP-32" }; +{ + char *mode_str[5] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32" }; char scratch[128]; bpck_read_eeprom(pi,scratch); print_hex_dump_bytes("bpck EEPROM: ", DUMP_PREFIX_NONE, scratch, 128); - dev_info(&pi->dev, "backpack %8.8s unit %d at 0x%x, mode %d (%s), delay %d\n", + dev_info(&pi->dev, + "backpack %8.8s unit %d at 0x%x, mode %d (%s), delay %d\n", &scratch[110], pi->unit, pi->port, pi->mode, - mode_string[pi->mode], pi->delay); + mode_str[pi->mode], pi->delay); } static struct pi_protocol bpck = { diff --git a/drivers/ata/pata_parport/bpck6.c b/drivers/ata/pata_parport/bpck6.c index 76febd07a9bb..c6dbd14120d1 100644 --- a/drivers/ata/pata_parport/bpck6.c +++ b/drivers/ata/pata_parport/bpck6.c @@ -1,15 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* - backpack.c (c) 2001 Micro Solutions Inc. - Released under the terms of the GNU General Public license - - backpack.c is a low-level protocol driver for the Micro Solutions - "BACKPACK" parallel port IDE adapter - (Works on Series 6 drives) - - Written by: Ken Hahn (linux-dev@micro-solutions.com) - Clive Turvey (linux-dev@micro-solutions.com) - -*/ + * (c) 2001 Micro Solutions Inc. + * + * backpack.c is a low-level protocol driver for the Micro Solutions + * "BACKPACK" parallel port IDE adapter (works on Series 6 drives). + * + * Written by: Ken Hahn (linux-dev@micro-solutions.com) + * Clive Turvey (linux-dev@micro-solutions.com) + */ #include <linux/module.h> #include <linux/init.h> @@ -326,11 +324,14 @@ static int bpck6_open(struct pi_adapter *pi) if (j != k) goto fail; - if (i & 4) // EPP + if (i & 4) { + /* EPP */ parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT | PARPORT_CONTROL_INIT, 0); - else // PPC/ECP + } else { + /* PPC/ECP */ parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT, 0); + } pi->private = 0; @@ -347,17 +348,20 @@ fail: parport_write_control(pi->pardev->port, pi->saved_r2); parport_write_data(pi->pardev->port, pi->saved_r0); - return 0; // FAIL + return 0; } static void bpck6_deselect(struct pi_adapter *pi) { - if (mode_map[pi->mode] & 4) // EPP + if (mode_map[pi->mode] & 4) { + /* EPP */ parport_frob_control(pi->pardev->port, PARPORT_CONTROL_INIT, - PARPORT_CONTROL_INIT); - else // PPC/ECP + PARPORT_CONTROL_INIT); + } else { + /* PPC/ECP */ parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT, - PARPORT_CONTROL_SELECT); + PARPORT_CONTROL_SELECT); + } parport_write_data(pi->pardev->port, pi->saved_r0); parport_write_control(pi->pardev->port, @@ -386,7 +390,8 @@ static void bpck6_disconnect(struct pi_adapter *pi) bpck6_deselect(pi); } -static int bpck6_test_port(struct pi_adapter *pi) /* check for 8-bit port */ +/* check for 8-bit port */ +static int bpck6_test_port(struct pi_adapter *pi) { dev_dbg(&pi->dev, "PARPORT indicates modes=%x for lp=0x%lx\n", pi->pardev->port->modes, pi->pardev->port->base); @@ -413,28 +418,26 @@ static int bpck6_probe_unit(struct pi_adapter *pi) dev_dbg(&pi->dev, "ppc_open returned %2x\n", out); - if(out) - { + if (out) { bpck6_deselect(pi); dev_dbg(&pi->dev, "leaving probe\n"); pi->mode = saved_mode; - return(1); + return 1; } - else - { - dev_dbg(&pi->dev, "Failed open\n"); - pi->mode = saved_mode; - return(0); - } + + dev_dbg(&pi->dev, "Failed open\n"); + pi->mode = saved_mode; + + return 0; } static void bpck6_log_adapter(struct pi_adapter *pi) { - char *mode_string[5]= - {"4-bit","8-bit","EPP-8","EPP-16","EPP-32"}; + char *mode_string[5] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32" }; - dev_info(&pi->dev, "Micro Solutions BACKPACK Drive unit %d at 0x%x, mode:%d (%s), delay %d\n", - pi->unit, pi->port, pi->mode, mode_string[pi->mode], pi->delay); + dev_info(&pi->dev, + "Micro Solutions BACKPACK Drive unit %d at 0x%x, mode:%d (%s), delay %d\n", + pi->unit, pi->port, pi->mode, mode_string[pi->mode], pi->delay); } static struct pi_protocol bpck6 = { diff --git a/drivers/ata/pata_parport/comm.c b/drivers/ata/pata_parport/comm.c index 4c2f9ad60ad8..cc5485bd0a5b 100644 --- a/drivers/ata/pata_parport/comm.c +++ b/drivers/ata/pata_parport/comm.c @@ -1,12 +1,11 @@ -/* - comm.c (c) 1997-8 Grant R. Guenther <grant@torque.net> - Under the terms of the GNU General Public License. - - comm.c is a low-level protocol driver for some older models - of the DataStor "Commuter" parallel to IDE adapter. Some of - the parallel port devices marketed by Arista currently - use this adapter. -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1997-1998 Grant R. Guenther <grant@torque.net> + * + * comm.c is a low-level protocol driver for some older models of the DataStor + * "Commuter" parallel to IDE adapter. Some of the parallel port devices + * marketed by Arista currently use this adapter. + */ #include <linux/module.h> #include <linux/init.h> @@ -17,165 +16,172 @@ #include <asm/io.h> #include "pata_parport.h" -/* mode codes: 0 nybble reads, 8-bit writes - 1 8-bit reads and writes - 2 8-bit EPP mode -*/ +/* + * mode codes: 0 nybble reads, 8-bit writes + * 1 8-bit reads and writes + * 2 8-bit EPP mode + */ -#define j44(a,b) (((a>>3)&0x0f)|((b<<1)&0xf0)) +#define j44(a, b) (((a >> 3) & 0x0f) | ((b << 1) & 0xf0)) #define P1 w2(5);w2(0xd);w2(0xd);w2(5);w2(4); #define P2 w2(5);w2(7);w2(7);w2(5);w2(4); -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set -*/ - +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + */ static int cont_map[2] = { 0x08, 0x10 }; static int comm_read_regr(struct pi_adapter *pi, int cont, int regr) - -{ int l, h, r; +{ + int l, h, r; r = regr + cont_map[cont]; - switch (pi->mode) { + switch (pi->mode) { + case 0: + w0(r); P1; w0(0); + w2(6); l = r1(); w0(0x80); h = r1(); w2(4); + return j44(l, h); - case 0: w0(r); P1; w0(0); - w2(6); l = r1(); w0(0x80); h = r1(); w2(4); - return j44(l,h); - - case 1: w0(r+0x20); P1; - w0(0); w2(0x26); h = r0(); w2(4); - return h; + case 1: + w0(r+0x20); P1; + w0(0); w2(0x26); h = r0(); w2(4); + return h; case 2: case 3: - case 4: w3(r+0x20); (void)r1(); - w2(0x24); h = r4(); w2(4); - return h; + case 4: + w3(r+0x20); (void)r1(); + w2(0x24); h = r4(); w2(4); + return h; + } - } - return -1; -} + return -1; +} static void comm_write_regr(struct pi_adapter *pi, int cont, int regr, int val) +{ + int r = regr + cont_map[cont]; -{ int r; - - r = regr + cont_map[cont]; - - switch (pi->mode) { - - case 0: - case 1: w0(r); P1; w0(val); P2; + switch (pi->mode) { + case 0: + case 1: + w0(r); P1; w0(val); P2; break; - case 2: case 3: - case 4: w3(r); (void)r1(); w4(val); - break; - } + case 4: + w3(r); (void)r1(); w4(val); + break; + } } static void comm_connect(struct pi_adapter *pi) - -{ pi->saved_r0 = r0(); - pi->saved_r2 = r2(); - w2(4); w0(0xff); w2(6); - w2(4); w0(0xaa); w2(6); - w2(4); w0(0x00); w2(6); - w2(4); w0(0x87); w2(6); - w2(4); w0(0xe0); w2(0xc); w2(0xc); w2(4); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); + w2(4); w0(0xff); w2(6); + w2(4); w0(0xaa); w2(6); + w2(4); w0(0x00); w2(6); + w2(4); w0(0x87); w2(6); + w2(4); w0(0xe0); w2(0xc); w2(0xc); w2(4); } static void comm_disconnect(struct pi_adapter *pi) -{ w2(0); w2(0); w2(0); w2(4); +{ + w2(0); w2(0); w2(0); w2(4); w0(pi->saved_r0); - w2(pi->saved_r2); -} + w2(pi->saved_r2); +} static void comm_read_block(struct pi_adapter *pi, char *buf, int count) - -{ int i, l, h; - - switch (pi->mode) { - - case 0: w0(0x48); P1; - for(i=0;i<count;i++) { - w0(0); w2(6); l = r1(); - w0(0x80); h = r1(); w2(4); - buf[i] = j44(l,h); - } - break; - - case 1: w0(0x68); P1; w0(0); - for(i=0;i<count;i++) { - w2(0x26); buf[i] = r0(); w2(0x24); - } +{ + int i, l, h; + + switch (pi->mode) { + case 0: + w0(0x48); P1; + for (i = 0; i < count; i++) { + w0(0); w2(6); l = r1(); + w0(0x80); h = r1(); w2(4); + buf[i] = j44(l, h); + } + break; + case 1: + w0(0x68); P1; w0(0); + for (i = 0; i < count; i++) { + w2(0x26); + buf[i] = r0(); + w2(0x24); + } w2(4); break; - - case 2: w3(0x68); (void)r1(); w2(0x24); - for (i=0;i<count;i++) buf[i] = r4(); + case 2: + w3(0x68); (void)r1(); w2(0x24); + for (i = 0; i < count; i++) + buf[i] = r4(); + w2(4); + break; + case 3: + w3(0x68); (void)r1(); w2(0x24); + for (i = 0; i < count / 2; i++) + ((u16 *)buf)[i] = r4w(); + w2(4); + break; + case 4: + w3(0x68); (void)r1(); w2(0x24); + for (i = 0; i < count / 4; i++) + ((u32 *)buf)[i] = r4l(); w2(4); break; - - case 3: w3(0x68); (void)r1(); w2(0x24); - for (i=0;i<count/2;i++) ((u16 *)buf)[i] = r4w(); - w2(4); - break; - - case 4: w3(0x68); (void)r1(); w2(0x24); - for (i=0;i<count/4;i++) ((u32 *)buf)[i] = r4l(); - w2(4); - break; - } } /* NB: Watch out for the byte swapped writes ! */ - static void comm_write_block(struct pi_adapter *pi, char *buf, int count) - -{ int k; - - switch (pi->mode) { - - case 0: - case 1: w0(0x68); P1; - for (k=0;k<count;k++) { - w2(5); w0(buf[k^1]); w2(7); - } - w2(5); w2(4); - break; - - case 2: w3(0x48); (void)r1(); - for (k=0;k<count;k++) w4(buf[k^1]); - break; - - case 3: w3(0x48); (void)r1(); +{ + int k; + + switch (pi->mode) { + case 0: + case 1: + w0(0x68); P1; + for (k = 0; k < count; k++) { + w2(5); + w0(buf[k ^ 1]); + w2(7); + } + w2(5); w2(4); + break; + case 2: + w3(0x48); (void)r1(); + for (k = 0; k < count; k++) + w4(buf[k ^ 1]); + break; + case 3: + w3(0x48); (void)r1(); for (k = 0; k < count / 2; k++) w4w(swab16(((u16 *)buf)[k])); - break; - - case 4: w3(0x48); (void)r1(); + break; + case 4: + w3(0x48); (void)r1(); for (k = 0; k < count / 4; k++) w4l(swab16(((u16 *)buf)[2 * k]) | swab16(((u16 *)buf)[2 * k + 1]) << 16); - break; - - + break; } } static void comm_log_adapter(struct pi_adapter *pi) -{ char *mode_string[5] = {"4-bit","8-bit","EPP-8","EPP-16","EPP-32"}; +{ char *mode_string[5] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32" }; - dev_info(&pi->dev, "DataStor Commuter at 0x%x, mode %d (%s), delay %d\n", - pi->port, pi->mode, mode_string[pi->mode], pi->delay); + dev_info(&pi->dev, + "DataStor Commuter at 0x%x, mode %d (%s), delay %d\n", + pi->port, pi->mode, mode_string[pi->mode], pi->delay); } static struct pi_protocol comm = { diff --git a/drivers/ata/pata_parport/dstr.c b/drivers/ata/pata_parport/dstr.c index 2524684be206..368d7c7962a9 100644 --- a/drivers/ata/pata_parport/dstr.c +++ b/drivers/ata/pata_parport/dstr.c @@ -1,11 +1,10 @@ -/* - dstr.c (c) 1997-8 Grant R. Guenther <grant@torque.net> - Under the terms of the GNU General Public License. - - dstr.c is a low-level protocol driver for the - DataStor EP2000 parallel to IDE adapter chip. - -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1997-1998 Grant R. Guenther <grant@torque.net> + * + * dstr.c is a low-level protocol driver for the DataStor EP2000 parallel + * to IDE adapter chip. + */ #include <linux/module.h> #include <linux/init.h> @@ -16,178 +15,202 @@ #include <asm/io.h> #include "pata_parport.h" -/* mode codes: 0 nybble reads, 8-bit writes - 1 8-bit reads and writes - 2 8-bit EPP mode - 3 EPP-16 - 4 EPP-32 -*/ +/* + * mode codes: 0 nybble reads, 8-bit writes + * 1 8-bit reads and writes + * 2 8-bit EPP mode + * 3 EPP-16 + * 4 EPP-32 + */ -#define j44(a,b) (((a>>3)&0x07)|((~a>>4)&0x08)|((b<<1)&0x70)|((~b)&0x80)) +#define j44(a, b) (((a >> 3) & 0x07) | ((~a >> 4) & 0x08) | \ + ((b << 1) & 0x70) | ((~b) & 0x80)) #define P1 w2(5);w2(0xd);w2(5);w2(4); #define P2 w2(5);w2(7);w2(5);w2(4); #define P3 w2(6);w2(4);w2(6);w2(4); -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set -*/ - +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + */ static int cont_map[2] = { 0x20, 0x40 }; static int dstr_read_regr(struct pi_adapter *pi, int cont, int regr) +{ + int a, b, r; -{ int a, b, r; - - r = regr + cont_map[cont]; + r = regr + cont_map[cont]; w0(0x81); P1; - if (pi->mode) { w0(0x11); } else { w0(1); } + if (pi->mode) + w0(0x11); + else + w0(1); P2; w0(r); P1; - switch (pi->mode) { - - case 0: w2(6); a = r1(); w2(4); w2(6); b = r1(); w2(4); - return j44(a,b); - - case 1: w0(0); w2(0x26); a = r0(); w2(4); - return a; - + switch (pi->mode) { + case 0: + w2(6); a = r1(); w2(4); w2(6); b = r1(); w2(4); + return j44(a, b); + case 1: + w0(0); w2(0x26); a = r0(); w2(4); + return a; case 2: case 3: - case 4: w2(0x24); a = r4(); w2(4); - return a; + case 4: + w2(0x24); a = r4(); w2(4); + return a; + } - } - return -1; -} + return -1; +} static void dstr_write_regr(struct pi_adapter *pi, int cont, int regr, int val) +{ + int r = regr + cont_map[cont]; -{ int r; - - r = regr + cont_map[cont]; - - w0(0x81); P1; - if (pi->mode >= 2) { w0(0x11); } else { w0(1); } + w0(0x81); P1; + if (pi->mode >= 2) + w0(0x11); + else + w0(1); P2; w0(r); P1; - - switch (pi->mode) { - case 0: - case 1: w0(val); w2(5); w2(7); w2(5); w2(4); + switch (pi->mode) { + case 0: + case 1: + w0(val); w2(5); w2(7); w2(5); w2(4); break; - case 2: case 3: - case 4: w4(val); - break; - } + case 4: + w4(val); + break; + } } -#define CCP(x) w0(0xff);w2(0xc);w2(4);\ - w0(0xaa);w0(0x55);w0(0);w0(0xff);w0(0x87);w0(0x78);\ - w0(x);w2(5);w2(4); +#define CCP(x) \ + do { \ + w0(0xff); w2(0xc); w2(4); \ + w0(0xaa); w0(0x55); w0(0); w0(0xff); \ + w0(0x87); w0(0x78); \ + w0(x); w2(5); w2(4); \ + } while (0) static void dstr_connect(struct pi_adapter *pi) - -{ pi->saved_r0 = r0(); - pi->saved_r2 = r2(); - w2(4); CCP(0xe0); w0(0xff); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); + w2(4); CCP(0xe0); w0(0xff); } static void dstr_disconnect(struct pi_adapter *pi) - -{ CCP(0x30); - w0(pi->saved_r0); - w2(pi->saved_r2); -} +{ + CCP(0x30); + w0(pi->saved_r0); + w2(pi->saved_r2); +} static void dstr_read_block(struct pi_adapter *pi, char *buf, int count) - -{ int k, a, b; +{ + int k, a, b; w0(0x81); P1; - if (pi->mode) { w0(0x19); } else { w0(9); } + if (pi->mode) + w0(0x19); + else + w0(9); P2; w0(0x82); P1; P3; w0(0x20); P1; - switch (pi->mode) { - - case 0: for (k=0;k<count;k++) { - w2(6); a = r1(); w2(4); - w2(6); b = r1(); w2(4); - buf[k] = j44(a,b); - } - break; - - case 1: w0(0); - for (k=0;k<count;k++) { - w2(0x26); buf[k] = r0(); w2(0x24); - } - w2(4); - break; - - case 2: w2(0x24); - for (k=0;k<count;k++) buf[k] = r4(); - w2(4); - break; - - case 3: w2(0x24); - for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w(); - w2(4); - break; - - case 4: w2(0x24); - for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l(); - w2(4); - break; - - } + switch (pi->mode) { + case 0: + for (k = 0; k < count; k++) { + w2(6); a = r1(); w2(4); + w2(6); b = r1(); w2(4); + buf[k] = j44(a, b); + } + break; + case 1: + w0(0); + for (k = 0; k < count; k++) { + w2(0x26); + buf[k] = r0(); + w2(0x24); + } + w2(4); + break; + case 2: + w2(0x24); + for (k = 0; k < count; k++) + buf[k] = r4(); + w2(4); + break; + case 3: + w2(0x24); + for (k = 0; k < count / 2; k++) + ((u16 *)buf)[k] = r4w(); + w2(4); + break; + case 4: + w2(0x24); + for (k = 0; k < count / 4; k++) + ((u32 *)buf)[k] = r4l(); + w2(4); + break; + } } static void dstr_write_block(struct pi_adapter *pi, char *buf, int count) +{ + int k; -{ int k; - - w0(0x81); P1; - if (pi->mode) { w0(0x19); } else { w0(9); } - P2; w0(0x82); P1; P3; w0(0x20); P1; - - switch (pi->mode) { - - case 0: - case 1: for (k=0;k<count;k++) { - w2(5); w0(buf[k]); w2(7); - } - w2(5); w2(4); - break; + w0(0x81); P1; + if (pi->mode) + w0(0x19); + else + w0(9); + P2; w0(0x82); P1; P3; w0(0x20); P1; - case 2: w2(0xc5); - for (k=0;k<count;k++) w4(buf[k]); + switch (pi->mode) { + case 0: + case 1: + for (k = 0; k < count; k++) { + w2(5); + w0(buf[k]); + w2(7); + } + w2(5); w2(4); + break; + case 2: + w2(0xc5); + for (k = 0; k < count; k++) + w4(buf[k]); w2(0xc4); - break; - - case 3: w2(0xc5); - for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]); - w2(0xc4); - break; - - case 4: w2(0xc5); - for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]); - w2(0xc4); - break; - - } + break; + case 3: + w2(0xc5); + for (k = 0; k < count / 2; k++) + w4w(((u16 *)buf)[k]); + w2(0xc4); + break; + case 4: + w2(0xc5); + for (k = 0; k < count / 4; k++) + w4l(((u32 *)buf)[k]); + w2(0xc4); + break; + } } - static void dstr_log_adapter(struct pi_adapter *pi) -{ char *mode_string[5] = {"4-bit","8-bit","EPP-8", - "EPP-16","EPP-32"}; +{ + char *mode_string[5] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32" }; - dev_info(&pi->dev, "DataStor EP2000 at 0x%x, mode %d (%s), delay %d\n", - pi->port, pi->mode, mode_string[pi->mode], pi->delay); + dev_info(&pi->dev, + "DataStor EP2000 at 0x%x, mode %d (%s), delay %d\n", + pi->port, pi->mode, mode_string[pi->mode], pi->delay); } static struct pi_protocol dstr = { diff --git a/drivers/ata/pata_parport/epat.c b/drivers/ata/pata_parport/epat.c index b146999368ae..016bd96bce89 100644 --- a/drivers/ata/pata_parport/epat.c +++ b/drivers/ata/pata_parport/epat.c @@ -1,13 +1,12 @@ -/* - epat.c (c) 1997-8 Grant R. Guenther <grant@torque.net> - Under the terms of the GNU General Public License. - - This is the low level protocol driver for the EPAT parallel - to IDE adapter from Shuttle Technologies. This adapter is - used in many popular parallel port disk products such as the - SyQuest EZ drives, the Avatar Shark and the Imation SuperDisk. - -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1997-1998 Grant R. Guenther <grant@torque.net> + * + * This is the low level protocol driver for the EPAT parallel + * to IDE adapter from Shuttle Technologies. This adapter is + * used in many popular parallel port disk products such as the + * SyQuest EZ drives, the Avatar Shark and the Imation SuperDisk. + */ #include <linux/module.h> #include <linux/init.h> @@ -18,276 +17,313 @@ #include <asm/io.h> #include "pata_parport.h" -#define j44(a,b) (((a>>4)&0x0f)+(b&0xf0)) -#define j53(a,b) (((a>>3)&0x1f)+((b<<4)&0xe0)) +#define j44(a, b) (((a >> 4) & 0x0f) + (b & 0xf0)) +#define j53(a, b) (((a >> 3) & 0x1f) + ((b << 4) & 0xe0)) static int epatc8; module_param(epatc8, int, 0); -MODULE_PARM_DESC(epatc8, "support for the Shuttle EP1284 chip, " - "used in any recent Imation SuperDisk (LS-120) drive."); - -/* cont = 0 IDE register file - cont = 1 IDE control registers - cont = 2 internal EPAT registers -*/ - +MODULE_PARM_DESC(epatc8, + "support for the Shuttle EP1284 chip, " + "used in any recent Imation SuperDisk (LS-120) drive."); + +/* + * cont = 0 IDE register file + * cont = 1 IDE control registers + * cont = 2 internal EPAT registers + */ static int cont_map[3] = { 0x18, 0x10, 0 }; static void epat_write_regr(struct pi_adapter *pi, int cont, int regr, int val) - -{ int r; - - r = regr + cont_map[cont]; +{ + int r = regr + cont_map[cont]; switch (pi->mode) { - case 0: case 1: - case 2: w0(0x60+r); w2(1); w0(val); w2(4); + case 2: + w0(0x60+r); w2(1); w0(val); w2(4); break; - case 3: case 4: - case 5: w3(0x40+r); w4(val); + case 5: + w3(0x40+r); w4(val); break; - } } static int epat_read_regr(struct pi_adapter *pi, int cont, int regr) - -{ int a, b, r; +{ + int a, b, r; r = regr + cont_map[cont]; switch (pi->mode) { - case 0: w0(r); w2(1); w2(3); + case 0: + w0(r); w2(1); w2(3); a = r1(); w2(4); b = r1(); - return j44(a,b); - - case 1: w0(0x40+r); w2(1); w2(4); + return j44(a, b); + case 1: + w0(0x40+r); w2(1); w2(4); a = r1(); b = r2(); w0(0xff); - return j53(a,b); - - case 2: w0(0x20+r); w2(1); w2(0x25); + return j53(a, b); + case 2: + w0(0x20+r); w2(1); w2(0x25); a = r0(); w2(4); return a; - case 3: case 4: - case 5: w3(r); w2(0x24); a = r4(); w2(4); + case 5: + w3(r); w2(0x24); a = r4(); w2(4); return a; - } + return -1; /* never gets here */ } static void epat_read_block(struct pi_adapter *pi, char *buf, int count) - -{ int k, ph, a, b; +{ + int k, ph, a, b; switch (pi->mode) { - case 0: w0(7); w2(1); w2(3); w0(0xff); + case 0: + w0(7); w2(1); w2(3); w0(0xff); ph = 0; - for(k=0;k<count;k++) { - if (k == count-1) w0(0xfd); - w2(6+ph); a = r1(); - if (a & 8) b = a; - else { w2(4+ph); b = r1(); } - buf[k] = j44(a,b); + for (k = 0; k < count; k++) { + if (k == count-1) + w0(0xfd); + w2(6 + ph); a = r1(); + if (a & 8) { + b = a; + } else { + w2(4+ph); b = r1(); + } + buf[k] = j44(a, b); ph = 1 - ph; } w0(0); w2(4); break; - case 1: w0(0x47); w2(1); w2(5); w0(0xff); + case 1: + w0(0x47); w2(1); w2(5); w0(0xff); ph = 0; - for(k=0;k<count;k++) { - if (k == count-1) w0(0xfd); - w2(4+ph); + for (k = 0; k < count; k++) { + if (k == count - 1) + w0(0xfd); + w2(4 + ph); a = r1(); b = r2(); - buf[k] = j53(a,b); + buf[k] = j53(a, b); ph = 1 - ph; } w0(0); w2(4); break; - case 2: w0(0x27); w2(1); w2(0x25); w0(0); + case 2: + w0(0x27); w2(1); w2(0x25); w0(0); ph = 0; - for(k=0;k<count-1;k++) { - w2(0x24+ph); + for (k = 0; k < count - 1; k++) { + w2(0x24 + ph); buf[k] = r0(); ph = 1 - ph; } - w2(0x26); w2(0x27); buf[count-1] = r0(); + w2(0x26); w2(0x27); + buf[count - 1] = r0(); w2(0x25); w2(4); break; - case 3: w3(0x80); w2(0x24); - for(k=0;k<count-1;k++) buf[k] = r4(); - w2(4); w3(0xa0); w2(0x24); buf[count-1] = r4(); + case 3: + w3(0x80); w2(0x24); + for (k = 0; k < count - 1; k++) + buf[k] = r4(); + w2(4); w3(0xa0); w2(0x24); + buf[count - 1] = r4(); w2(4); break; - case 4: w3(0x80); w2(0x24); - for(k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w(); - buf[count-2] = r4(); - w2(4); w3(0xa0); w2(0x24); buf[count-1] = r4(); + case 4: + w3(0x80); w2(0x24); + for (k = 0; k < count / 2 - 1; k++) + ((u16 *)buf)[k] = r4w(); + buf[count - 2] = r4(); + w2(4); w3(0xa0); w2(0x24); + buf[count - 1] = r4(); w2(4); break; - case 5: w3(0x80); w2(0x24); - for(k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l(); - for(k=count-4;k<count-1;k++) buf[k] = r4(); - w2(4); w3(0xa0); w2(0x24); buf[count-1] = r4(); + case 5: + w3(0x80); w2(0x24); + for (k = 0; k < count / 4 - 1; k++) + ((u32 *)buf)[k] = r4l(); + for (k = count - 4; k < count - 1; k++) + buf[k] = r4(); + w2(4); w3(0xa0); w2(0x24); + buf[count - 1] = r4(); w2(4); break; - } } static void epat_write_block(struct pi_adapter *pi, char *buf, int count) - -{ int ph, k; +{ + int ph, k; switch (pi->mode) { - case 0: case 1: - case 2: w0(0x67); w2(1); w2(5); + case 2: + w0(0x67); w2(1); w2(5); ph = 0; - for(k=0;k<count;k++) { + for (k = 0; k < count; k++) { w0(buf[k]); - w2(4+ph); + w2(4 + ph); ph = 1 - ph; } w2(7); w2(4); break; - - case 3: w3(0xc0); - for(k=0;k<count;k++) w4(buf[k]); + case 3: + w3(0xc0); + for (k = 0; k < count; k++) + w4(buf[k]); w2(4); break; - - case 4: w3(0xc0); - for(k=0;k<(count/2);k++) w4w(((u16 *)buf)[k]); + case 4: + w3(0xc0); + for (k = 0; k < count / 2; k++) + w4w(((u16 *)buf)[k]); w2(4); break; - - case 5: w3(0xc0); - for(k=0;k<(count/4);k++) w4l(((u32 *)buf)[k]); + case 5: + w3(0xc0); + for (k = 0; k < count / 4; k++) + w4l(((u32 *)buf)[k]); w2(4); break; - } } /* these macros access the EPAT registers in native addressing */ -#define WR(r,v) epat_write_regr(pi,2,r,v) -#define RR(r) (epat_read_regr(pi,2,r)) +#define WR(r, v) epat_write_regr(pi, 2, r, v) +#define RR(r) epat_read_regr(pi, 2, r) /* and these access the IDE task file */ -#define WRi(r,v) epat_write_regr(pi,0,r,v) -#define RRi(r) (epat_read_regr(pi,0,r)) +#define WRi(r, v) epat_write_regr(pi, 0, r, v) +#define RRi(r) epat_read_regr(pi, 0, r) /* FIXME: the CPP stuff should be fixed to handle multiple EPATs on a chain */ -#define CPP(x) w2(4);w0(0x22);w0(0xaa);w0(0x55);w0(0);w0(0xff);\ - w0(0x87);w0(0x78);w0(x);w2(4);w2(5);w2(4);w0(0xff); +#define CPP(x) \ + do { \ + w2(4); w0(0x22); w0(0xaa); \ + w0(0x55); w0(0); w0(0xff); \ + w0(0x87); w0(0x78); w0(x); \ + w2(4); w2(5); w2(4); w0(0xff); \ + } while (0) static void epat_connect(struct pi_adapter *pi) - -{ pi->saved_r0 = r0(); - pi->saved_r2 = r2(); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); /* Initialize the chip */ CPP(0); if (epatc8) { - CPP(0x40);CPP(0xe0); - w0(0);w2(1);w2(4); - WR(0x8,0x12);WR(0xc,0x14);WR(0x12,0x10); - WR(0xe,0xf);WR(0xf,4); + CPP(0x40); CPP(0xe0); + w0(0); w2(1); w2(4); + WR(0x8, 0x12); + WR(0xc, 0x14); + WR(0x12, 0x10); + WR(0xe, 0xf); + WR(0xf, 4); /* WR(0xe,0xa);WR(0xf,4); */ - WR(0xe,0xd);WR(0xf,0); + WR(0xe, 0xd); + WR(0xf, 0); /* CPP(0x30); */ } /* Connect to the chip */ CPP(0xe0); - w0(0);w2(1);w2(4); /* Idle into SPP */ + w0(0); w2(1); w2(4); /* Idle into SPP */ if (pi->mode >= 3) { - w0(0);w2(1);w2(4);w2(0xc); - /* Request EPP */ - w0(0x40);w2(6);w2(7);w2(4);w2(0xc);w2(4); + w0(0); w2(1); w2(4); w2(0xc); + /* Request EPP */ + w0(0x40); w2(6); w2(7); w2(4); w2(0xc); w2(4); } if (!epatc8) { - WR(8,0x10); WR(0xc,0x14); WR(0xa,0x38); WR(0x12,0x10); + WR(8, 0x10); + WR(0xc, 0x14); + WR(0xa, 0x38); + WR(0x12, 0x10); } } static void epat_disconnect(struct pi_adapter *pi) -{ CPP(0x30); +{ + CPP(0x30); w0(pi->saved_r0); w2(pi->saved_r2); } static int epat_test_proto(struct pi_adapter *pi) - -{ int k, j, f, cc; - int e[2] = {0,0}; +{ + int k, j, f, cc; + int e[2] = { 0, 0 }; char scratch[512]; - epat_connect(pi); + epat_connect(pi); cc = RR(0xd); epat_disconnect(pi); epat_connect(pi); for (j=0;j<2;j++) { - WRi(6,0xa0+j*0x10); - for (k=0;k<256;k++) { - WRi(2,k^0xaa); - WRi(3,k^0x55); - if (RRi(2) != (k^0xaa)) e[j]++; - } - } - epat_disconnect(pi); - - f = 0; - epat_connect(pi); - WR(0x13,1); WR(0x13,0); WR(0xa,0x11); - epat_read_block(pi,scratch,512); - - for (k=0;k<256;k++) { - if ((scratch[2*k] & 0xff) != k) f++; - if ((scratch[2*k+1] & 0xff) != (0xff-k)) f++; - } - epat_disconnect(pi); + WRi(6, 0xa0 + j * 0x10); + for (k = 0; k < 256; k++) { + WRi(2, k ^ 0xaa); + WRi(3, k ^ 0x55); + if (RRi(2) != (k ^ 0xaa)) + e[j]++; + } + } + epat_disconnect(pi); - dev_dbg(&pi->dev, "epat: port 0x%x, mode %d, ccr %x, test=(%d,%d,%d)\n", - pi->port, pi->mode, cc, e[0], e[1], f); - - return (e[0] && e[1]) || f; + f = 0; + epat_connect(pi); + WR(0x13, 1); WR(0x13, 0); WR(0xa, 0x11); + epat_read_block(pi, scratch, 512); + + for (k = 0; k < 256; k++) { + if ((scratch[2 * k] & 0xff) != k) + f++; + if ((scratch[2 * k + 1] & 0xff) != 0xff - k) + f++; + } + epat_disconnect(pi); + + dev_dbg(&pi->dev, + "epat: port 0x%x, mode %d, ccr %x, test=(%d,%d,%d)\n", + pi->port, pi->mode, cc, e[0], e[1], f); + + return (e[0] && e[1]) || f; } static void epat_log_adapter(struct pi_adapter *pi) - -{ int ver; - char *mode_string[6] = - {"4-bit","5/3","8-bit","EPP-8","EPP-16","EPP-32"}; +{ + int ver; + char *mode_string[6] = + { "4-bit", "5/3", "8-bit", "EPP-8", "EPP-16", "EPP-32" }; epat_connect(pi); - WR(0xa,0x38); /* read the version code */ - ver = RR(0xb); - epat_disconnect(pi); + WR(0xa, 0x38); /* read the version code */ + ver = RR(0xb); + epat_disconnect(pi); - dev_info(&pi->dev, "Shuttle EPAT chip %x at 0x%x, mode %d (%s), delay %d\n", + dev_info(&pi->dev, + "Shuttle EPAT chip %x at 0x%x, mode %d (%s), delay %d\n", ver, pi->port, pi->mode, mode_string[pi->mode], pi->delay); } diff --git a/drivers/ata/pata_parport/epia.c b/drivers/ata/pata_parport/epia.c index f6db2f79fe99..920e9f40d401 100644 --- a/drivers/ata/pata_parport/epia.c +++ b/drivers/ata/pata_parport/epia.c @@ -1,14 +1,13 @@ -/* - epia.c (c) 1997-8 Grant R. Guenther <grant@torque.net> - Under the terms of the GNU General Public License. - - epia.c is a low-level protocol driver for Shuttle Technologies - EPIA parallel to IDE adapter chip. This device is now obsolete - and has been replaced with the EPAT chip, which is supported - by epat.c, however, some devices based on EPIA are still - available. - -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1997-1998 Grant R. Guenther <grant@torque.net> + * + * epia.c is a low-level protocol driver for Shuttle Technologies + * EPIA parallel to IDE adapter chip. This device is now obsolete + * and has been replaced with the EPAT chip, which is supported + * by epat.c, however, some devices based on EPIA are still + * available. + */ #include <linux/module.h> #include <linux/init.h> @@ -19,255 +18,274 @@ #include <asm/io.h> #include "pata_parport.h" -/* mode codes: 0 nybble reads on port 1, 8-bit writes - 1 5/3 reads on ports 1 & 2, 8-bit writes - 2 8-bit reads and writes - 3 8-bit EPP mode - 4 16-bit EPP - 5 32-bit EPP -*/ - -#define j44(a,b) (((a>>4)&0x0f)+(b&0xf0)) -#define j53(a,b) (((a>>3)&0x1f)+((b<<4)&0xe0)) - -/* cont = 0 IDE register file - cont = 1 IDE control registers -*/ - +/* + * mode codes: 0 nybble reads on port 1, 8-bit writes + * 1 5/3 reads on ports 1 & 2, 8-bit writes + * 2 8-bit reads and writes + * 3 8-bit EPP mode + * 4 16-bit EPP + * 5 32-bit EPP + */ + +#define j44(a, b) (((a >> 4) & 0x0f) + (b & 0xf0)) +#define j53(a, b) (((a >> 3) & 0x1f) + ((b << 4) & 0xe0)) + +/* + * cont = 0 IDE register file + * cont = 1 IDE control registers + */ static int cont_map[2] = { 0, 0x80 }; static int epia_read_regr(struct pi_adapter *pi, int cont, int regr) - -{ int a, b, r; +{ + int a, b, r; regr += cont_map[cont]; - switch (pi->mode) { - - case 0: r = regr^0x39; - w0(r); w2(1); w2(3); w0(r); - a = r1(); w2(1); b = r1(); w2(4); - return j44(a,b); - - case 1: r = regr^0x31; - w0(r); w2(1); w0(r&0x37); - w2(3); w2(5); w0(r|0xf0); - a = r1(); b = r2(); w2(4); - return j53(a,b); - - case 2: r = regr^0x29; - w0(r); w2(1); w2(0X21); w2(0x23); - a = r0(); w2(4); - return a; - + switch (pi->mode) { + case 0: + r = regr ^ 0x39; + w0(r); w2(1); w2(3); w0(r); + a = r1(); w2(1); b = r1(); w2(4); + return j44(a, b); + case 1: + r = regr ^ 0x31; + w0(r); w2(1); w0(r & 0x37); + w2(3); w2(5); w0(r | 0xf0); + a = r1(); b = r2(); w2(4); + return j53(a, b); + case 2: + r = regr^0x29; + w0(r); w2(1); w2(0X21); w2(0x23); + a = r0(); w2(4); + return a; case 3: case 4: - case 5: w3(regr); w2(0x24); a = r4(); w2(4); - return a; + case 5: + w3(regr); w2(0x24); a = r4(); w2(4); + return a; + } - } - return -1; -} + return -1; +} static void epia_write_regr(struct pi_adapter *pi, int cont, int regr, int val) - -{ int r; +{ + int r; regr += cont_map[cont]; - switch (pi->mode) { - - case 0: - case 1: - case 2: r = regr^0x19; - w0(r); w2(1); w0(val); w2(3); w2(4); - break; - + switch (pi->mode) { + case 0: + case 1: + case 2: + r = regr ^ 0x19; + w0(r); w2(1); w0(val); w2(3); w2(4); + break; case 3: case 4: - case 5: r = regr^0x40; - w3(r); w4(val); w2(4); - break; - } + case 5: + r = regr ^ 0x40; + w3(r); w4(val); w2(4); + break; + } } -#define WR(r,v) epia_write_regr(pi,0,r,v) -#define RR(r) (epia_read_regr(pi,0,r)) - -/* The use of register 0x84 is entirely unclear - it seems to control - some EPP counters ... currently we know about 3 different block - sizes: the standard 512 byte reads and writes, 12 byte writes and - 2048 byte reads (the last two being used in the CDrom drivers. -*/ +#define WR(r, v) epia_write_regr(pi, 0, r, v) +#define RR(r) epia_read_regr(pi, 0, r) +/* + * The use of register 0x84 is entirely unclear - it seems to control + * some EPP counters ... currently we know about 3 different block + * sizes: the standard 512 byte reads and writes, 12 byte writes and + * 2048 byte reads (the last two being used in the CDrom drivers. + */ static void epia_connect(struct pi_adapter *pi) - -{ pi->saved_r0 = r0(); - pi->saved_r2 = r2(); - - w2(4); w0(0xa0); w0(0x50); w0(0xc0); w0(0x30); w0(0xa0); w0(0); - w2(1); w2(4); - if (pi->mode >= 3) { - w0(0xa); w2(1); w2(4); w0(0x82); w2(4); w2(0xc); w2(4); - w2(0x24); w2(0x26); w2(4); - } - WR(0x86,8); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); + + w2(4); w0(0xa0); w0(0x50); w0(0xc0); w0(0x30); w0(0xa0); w0(0); + w2(1); w2(4); + if (pi->mode >= 3) { + w0(0xa); w2(1); w2(4); w0(0x82); w2(4); w2(0xc); w2(4); + w2(0x24); w2(0x26); w2(4); + } + WR(0x86, 8); } static void epia_disconnect(struct pi_adapter *pi) - -{ /* WR(0x84,0x10); */ - w0(pi->saved_r0); - w2(1); w2(4); - w0(pi->saved_r0); - w2(pi->saved_r2); -} +{ + /* WR(0x84,0x10); */ + w0(pi->saved_r0); + w2(1); w2(4); + w0(pi->saved_r0); + w2(pi->saved_r2); +} static void epia_read_block(struct pi_adapter *pi, char *buf, int count) -{ int k, ph, a, b; - - switch (pi->mode) { - - case 0: w0(0x81); w2(1); w2(3); w0(0xc1); - ph = 1; - for (k=0;k<count;k++) { - w2(2+ph); a = r1(); - w2(4+ph); b = r1(); - buf[k] = j44(a,b); - ph = 1 - ph; - } - w0(0); w2(4); - break; - - case 1: w0(0x91); w2(1); w0(0x10); w2(3); - w0(0x51); w2(5); w0(0xd1); - ph = 1; - for (k=0;k<count;k++) { - w2(4+ph); - a = r1(); b = r2(); - buf[k] = j53(a,b); - ph = 1 - ph; - } - w0(0); w2(4); - break; - - case 2: w0(0x89); w2(1); w2(0x23); w2(0x21); - ph = 1; - for (k=0;k<count;k++) { - w2(0x24+ph); - buf[k] = r0(); - ph = 1 - ph; - } - w2(6); w2(4); - break; - - case 3: if (count > 512) WR(0x84,3); +{ + int k, ph, a, b; + + switch (pi->mode) { + case 0: + w0(0x81); w2(1); w2(3); w0(0xc1); + ph = 1; + for (k = 0; k < count; k++) { + w2(2+ph); a = r1(); + w2(4+ph); b = r1(); + buf[k] = j44(a, b); + ph = 1 - ph; + } + w0(0); w2(4); + break; + case 1: + w0(0x91); w2(1); w0(0x10); w2(3); + w0(0x51); w2(5); w0(0xd1); + ph = 1; + for (k = 0; k < count; k++) { + w2(4 + ph); + a = r1(); b = r2(); + buf[k] = j53(a, b); + ph = 1 - ph; + } + w0(0); w2(4); + break; + case 2: + w0(0x89); w2(1); w2(0x23); w2(0x21); + ph = 1; + for (k = 0; k < count; k++) { + w2(0x24 + ph); + buf[k] = r0(); + ph = 1 - ph; + } + w2(6); w2(4); + break; + case 3: + if (count > 512) + WR(0x84, 3); w3(0); w2(0x24); - for (k=0;k<count;k++) buf[k] = r4(); - w2(4); WR(0x84,0); - break; - - case 4: if (count > 512) WR(0x84,3); + for (k = 0; k < count; k++) + buf[k] = r4(); + w2(4); WR(0x84, 0); + break; + case 4: + if (count > 512) + WR(0x84, 3); w3(0); w2(0x24); - for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w(); - w2(4); WR(0x84,0); - break; - - case 5: if (count > 512) WR(0x84,3); + for (k = 0; k < count / 2; k++) + ((u16 *)buf)[k] = r4w(); + w2(4); WR(0x84, 0); + break; + case 5: + if (count > 512) + WR(0x84, 3); w3(0); w2(0x24); - for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l(); - w2(4); WR(0x84,0); - break; - - } + for (k = 0; k < count / 4; k++) + ((u32 *)buf)[k] = r4l(); + w2(4); WR(0x84, 0); + break; + } } static void epia_write_block(struct pi_adapter *pi, char *buf, int count) - -{ int ph, k, last, d; - - switch (pi->mode) { - - case 0: - case 1: - case 2: w0(0xa1); w2(1); w2(3); w2(1); w2(5); - ph = 0; last = 0x8000; - for (k=0;k<count;k++) { - d = buf[k]; - if (d != last) { last = d; w0(d); } - w2(4+ph); - ph = 1 - ph; - } - w2(7); w2(4); - break; - - case 3: if (count < 512) WR(0x84,1); +{ + int ph, k, last, d; + + switch (pi->mode) { + case 0: + case 1: + case 2: + w0(0xa1); w2(1); w2(3); w2(1); w2(5); + ph = 0; last = 0x8000; + for (k = 0; k < count; k++) { + d = buf[k]; + if (d != last) { + last = d; + w0(d); + } + w2(4 + ph); + ph = 1 - ph; + } + w2(7); w2(4); + break; + case 3: + if (count < 512) + WR(0x84, 1); w3(0x40); - for (k=0;k<count;k++) w4(buf[k]); - if (count < 512) WR(0x84,0); - break; - - case 4: if (count < 512) WR(0x84,1); + for (k = 0; k < count; k++) + w4(buf[k]); + if (count < 512) + WR(0x84, 0); + break; + case 4: + if (count < 512) + WR(0x84, 1); w3(0x40); - for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]); - if (count < 512) WR(0x84,0); - break; - - case 5: if (count < 512) WR(0x84,1); + for (k = 0; k < count / 2; k++) + w4w(((u16 *)buf)[k]); + if (count < 512) + WR(0x84, 0); + break; + case 5: + if (count < 512) + WR(0x84, 1); w3(0x40); - for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]); - if (count < 512) WR(0x84,0); - break; - - } - + for (k = 0; k < count / 4; k++) + w4l(((u32 *)buf)[k]); + if (count < 512) + WR(0x84, 0); + break; + } } static int epia_test_proto(struct pi_adapter *pi) - -{ int j, k, f; - int e[2] = {0,0}; +{ + int j, k, f; + int e[2] = { 0, 0 }; char scratch[512]; - epia_connect(pi); - for (j=0;j<2;j++) { - WR(6,0xa0+j*0x10); - for (k=0;k<256;k++) { - WR(2,k^0xaa); - WR(3,k^0x55); - if (RR(2) != (k^0xaa)) e[j]++; - } - WR(2,1); WR(3,1); - } - epia_disconnect(pi); - - f = 0; - epia_connect(pi); - WR(0x84,8); - epia_read_block(pi,scratch,512); - for (k=0;k<256;k++) { - if ((scratch[2*k] & 0xff) != ((k+1) & 0xff)) f++; - if ((scratch[2*k+1] & 0xff) != ((-2-k) & 0xff)) f++; - } - WR(0x84,0); - epia_disconnect(pi); + epia_connect(pi); + for (j = 0; j < 2; j++) { + WR(6, 0xa0 + j * 0x10); + for (k = 0; k < 256; k++) { + WR(2, k ^ 0xaa); + WR(3, k ^ 0x55); + if (RR(2) != (k ^ 0xaa)) + e[j]++; + } + WR(2, 1); WR(3, 1); + } + epia_disconnect(pi); + + f = 0; + epia_connect(pi); + WR(0x84, 8); + epia_read_block(pi, scratch, 512); + for (k = 0; k < 256; k++) { + if ((scratch[2 * k] & 0xff) != ((k + 1) & 0xff)) + f++; + if ((scratch[2 * k + 1] & 0xff) != ((-2 - k) & 0xff)) + f++; + } + WR(0x84, 0); + epia_disconnect(pi); dev_dbg(&pi->dev, "epia: port 0x%x, mode %d, test=(%d,%d,%d)\n", - pi->port, pi->mode, e[0], e[1], f); - - return (e[0] && e[1]) || f; + pi->port, pi->mode, e[0], e[1], f); + return (e[0] && e[1]) || f; } static void epia_log_adapter(struct pi_adapter *pi) +{ + char *mode[6] = { "4-bit", "5/3", "8-bit", "EPP-8", "EPP-16", "EPP-32"}; -{ char *mode_string[6] = {"4-bit","5/3","8-bit", - "EPP-8","EPP-16","EPP-32"}; - - dev_info(&pi->dev, "Shuttle EPIA at 0x%x, mode %d (%s), delay %d\n", - pi->port, pi->mode, mode_string[pi->mode], pi->delay); + dev_info(&pi->dev, + "Shuttle EPIA at 0x%x, mode %d (%s), delay %d\n", + pi->port, pi->mode, mode[pi->mode], pi->delay); } static struct pi_protocol epia = { diff --git a/drivers/ata/pata_parport/fit2.c b/drivers/ata/pata_parport/fit2.c index fd3b2ce426a5..6524f3033b1e 100644 --- a/drivers/ata/pata_parport/fit2.c +++ b/drivers/ata/pata_parport/fit2.c @@ -1,17 +1,16 @@ -/* - fit2.c (c) 1998 Grant R. Guenther <grant@torque.net> - Under the terms of the GNU General Public License. - - fit2.c is a low-level protocol driver for the older version - of the Fidelity International Technology parallel port adapter. - This adapter is used in their TransDisk 2000 and older TransDisk - 3000 portable hard-drives. As far as I can tell, this device - supports 4-bit mode _only_. - - Newer models of the FIT products use an enhanced protocol. - The "fit3" protocol module should support current drives. - -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1998 Grant R. Guenther <grant@torque.net> + * + * fit2.c is a low-level protocol driver for the older version + * of the Fidelity International Technology parallel port adapter. + * This adapter is used in their TransDisk 2000 and older TransDisk + * 3000 portable hard-drives. As far as I can tell, this device + * supports 4-bit mode _only_. + * + * Newer models of the FIT products use an enhanced protocol. + * The "fit3" protocol module should support current drives. + */ #include <linux/module.h> #include <linux/init.h> @@ -22,99 +21,97 @@ #include <asm/io.h> #include "pata_parport.h" -#define j44(a,b) (((a>>4)&0x0f)|(b&0xf0)) - -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set +#define j44(a, b) (((a >> 4) & 0x0f) | (b & 0xf0)) -NB: The FIT adapter does not appear to use the control registers. -So, we map ALT_STATUS to STATUS and NO-OP writes to the device -control register - this means that IDE reset will not work on these -devices. - -*/ +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + * + * NB: The FIT adapter does not appear to use the control registers. + * So, we map ALT_STATUS to STATUS and NO-OP writes to the device + * control register - this means that IDE reset will not work on these + * devices. + */ static void fit2_write_regr(struct pi_adapter *pi, int cont, int regr, int val) - -{ if (cont == 1) return; +{ + if (cont == 1) + return; w2(0xc); w0(regr); w2(4); w0(val); w2(5); w0(0); w2(4); } static int fit2_read_regr(struct pi_adapter *pi, int cont, int regr) - -{ int a, b, r; +{ + int a, b, r; if (cont) { - if (regr != 6) return 0xff; - r = 7; - } else r = regr + 0x10; + if (regr != 6) + return 0xff; + r = 7; + } else { + r = regr + 0x10; + } - w2(0xc); w0(r); w2(4); w2(5); - w0(0); a = r1(); - w0(1); b = r1(); + w2(0xc); w0(r); w2(4); w2(5); + w0(0); a = r1(); + w0(1); b = r1(); w2(4); - return j44(a,b); - + return j44(a, b); } static void fit2_read_block(struct pi_adapter *pi, char *buf, int count) - -{ int k, a, b, c, d; +{ + int k, a, b, c, d; w2(0xc); w0(0x10); - for (k=0;k<count/4;k++) { - + for (k = 0; k < count / 4; k++) { w2(4); w2(5); w0(0); a = r1(); w0(1); b = r1(); - w0(3); c = r1(); w0(2); d = r1(); - buf[4*k+0] = j44(a,b); - buf[4*k+1] = j44(d,c); - - w2(4); w2(5); - a = r1(); w0(3); b = r1(); - w0(1); c = r1(); w0(0); d = r1(); - buf[4*k+2] = j44(d,c); - buf[4*k+3] = j44(a,b); + w0(3); c = r1(); w0(2); d = r1(); + buf[4 * k + 0] = j44(a, b); + buf[4 * k + 1] = j44(d, c); + w2(4); w2(5); + a = r1(); w0(3); b = r1(); + w0(1); c = r1(); w0(0); d = r1(); + buf[4 * k + 2] = j44(d, c); + buf[4 * k + 3] = j44(a, b); } w2(4); - } static void fit2_write_block(struct pi_adapter *pi, char *buf, int count) +{ + int k; -{ int k; - - - w2(0xc); w0(0); - for (k=0;k<count/2;k++) { - w2(4); w0(buf[2*k]); - w2(5); w0(buf[2*k+1]); + w2(0xc); w0(0); + for (k = 0; k < count / 2; k++) { + w2(4); w0(buf[2 * k]); + w2(5); w0(buf[2 * k + 1]); } w2(4); } static void fit2_connect(struct pi_adapter *pi) - -{ pi->saved_r0 = r0(); - pi->saved_r2 = r2(); - w2(0xcc); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); + w2(0xcc); } static void fit2_disconnect(struct pi_adapter *pi) - -{ w0(pi->saved_r0); - w2(pi->saved_r2); -} +{ + w0(pi->saved_r0); + w2(pi->saved_r2); +} static void fit2_log_adapter(struct pi_adapter *pi) - { dev_info(&pi->dev, "FIT 2000 adapter at 0x%x, delay %d\n", - pi->port, pi->delay); + pi->port, pi->delay); } diff --git a/drivers/ata/pata_parport/fit3.c b/drivers/ata/pata_parport/fit3.c index 75df656ac472..c172a38ae67d 100644 --- a/drivers/ata/pata_parport/fit3.c +++ b/drivers/ata/pata_parport/fit3.c @@ -1,21 +1,20 @@ -/* - fit3.c (c) 1998 Grant R. Guenther <grant@torque.net> - Under the terms of the GNU General Public License. - - fit3.c is a low-level protocol driver for newer models - of the Fidelity International Technology parallel port adapter. - This adapter is used in their TransDisk 3000 portable - hard-drives, as well as CD-ROM, PD-CD and other devices. - - The TD-2000 and certain older devices use a different protocol. - Try the fit2 protocol module with them. - - NB: The FIT adapters do not appear to support the control - registers. So, we map ALT_STATUS to STATUS and NO-OP writes - to the device control register - this means that IDE reset - will not work on these devices. - -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1998 Grant R. Guenther <grant@torque.net> + * + * fit3.c is a low-level protocol driver for newer models + * of the Fidelity International Technology parallel port adapter. + * This adapter is used in their TransDisk 3000 portable + * hard-drives, as well as CD-ROM, PD-CD and other devices. + * + * The TD-2000 and certain older devices use a different protocol. + * Try the fit2 protocol module with them. + * + * NB: The FIT adapters do not appear to support the control + * registers. So, we map ALT_STATUS to STATUS and NO-OP writes + * to the device control register - this means that IDE reset + * will not work on these devices. + */ #include <linux/module.h> #include <linux/init.h> @@ -26,152 +25,155 @@ #include <asm/io.h> #include "pata_parport.h" -#define j44(a,b) (((a>>3)&0x0f)|((b<<1)&0xf0)) - -#define w7(byte) {out_p(7,byte);} -#define r7() (in_p(7) & 0xff) +#define j44(a, b) (((a >> 3) & 0x0f) | ((b << 1) & 0xf0)) -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set +#define w7(byte) out_p(7, byte) +#define r7() (in_p(7) & 0xff) -*/ +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + */ static void fit3_write_regr(struct pi_adapter *pi, int cont, int regr, int val) - -{ if (cont == 1) return; +{ + if (cont == 1) + return; switch (pi->mode) { - case 0: - case 1: w2(0xc); w0(regr); w2(0x8); w2(0xc); - w0(val); w2(0xd); + case 1: + w2(0xc); w0(regr); w2(0x8); w2(0xc); + w0(val); w2(0xd); w0(0); w2(0xc); break; - - case 2: w2(0xc); w0(regr); w2(0x8); w2(0xc); + case 2: + w2(0xc); w0(regr); w2(0x8); w2(0xc); w4(val); w4(0); w2(0xc); break; - } } static int fit3_read_regr(struct pi_adapter *pi, int cont, int regr) - -{ int a, b; +{ + int a, b; if (cont) { - if (regr != 6) return 0xff; - regr = 7; - } + if (regr != 6) + return 0xff; + regr = 7; + } switch (pi->mode) { - - case 0: w2(0xc); w0(regr + 0x10); w2(0x8); w2(0xc); + case 0: + w2(0xc); w0(regr + 0x10); w2(0x8); w2(0xc); w2(0xd); a = r1(); - w2(0xf); b = r1(); + w2(0xf); b = r1(); w2(0xc); - return j44(a,b); - - case 1: w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc); - w2(0xec); w2(0xee); w2(0xef); a = r0(); + return j44(a, b); + case 1: + w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc); + w2(0xec); w2(0xee); w2(0xef); a = r0(); w2(0xc); return a; - - case 2: w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc); - w2(0xec); - a = r4(); b = r4(); + case 2: + w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc); + w2(0xec); + a = r4(); b = r4(); w2(0xc); return a; - } - return -1; + return -1; } static void fit3_read_block(struct pi_adapter *pi, char *buf, int count) - -{ int k, a, b, c, d; +{ + int k, a, b, c, d; switch (pi->mode) { - - case 0: w2(0xc); w0(0x10); w2(0x8); w2(0xc); - for (k=0;k<count/2;k++) { - w2(0xd); a = r1(); - w2(0xf); b = r1(); - w2(0xc); c = r1(); - w2(0xe); d = r1(); - buf[2*k ] = j44(a,b); - buf[2*k+1] = j44(c,d); + case 0: + w2(0xc); w0(0x10); w2(0x8); w2(0xc); + for (k = 0; k < count / 2; k++) { + w2(0xd); a = r1(); + w2(0xf); b = r1(); + w2(0xc); c = r1(); + w2(0xe); d = r1(); + buf[2 * k] = j44(a, b); + buf[2 * k + 1] = j44(c, d); } w2(0xc); break; - - case 1: w2(0xc); w0(0x90); w2(0x8); w2(0xc); + case 1: + w2(0xc); w0(0x90); w2(0x8); w2(0xc); w2(0xec); w2(0xee); - for (k=0;k<count/2;k++) { - w2(0xef); a = r0(); - w2(0xee); b = r0(); - buf[2*k ] = a; - buf[2*k+1] = b; + for (k = 0; k < count / 2; k++) { + w2(0xef); a = r0(); + w2(0xee); b = r0(); + buf[2 * k] = a; + buf[2 * k + 1] = b; } - w2(0xec); + w2(0xec); w2(0xc); break; - - case 2: w2(0xc); w0(0x90); w2(0x8); w2(0xc); - w2(0xec); - for (k=0;k<count;k++) buf[k] = r4(); - w2(0xc); + case 2: + w2(0xc); w0(0x90); w2(0x8); w2(0xc); + w2(0xec); + for (k = 0; k < count; k++) + buf[k] = r4(); + w2(0xc); break; - } } static void fit3_write_block(struct pi_adapter *pi, char *buf, int count) +{ + int k; -{ int k; - - switch (pi->mode) { - + switch (pi->mode) { case 0: - case 1: w2(0xc); w0(0); w2(0x8); w2(0xc); - for (k=0;k<count/2;k++) { - w0(buf[2*k ]); w2(0xd); - w0(buf[2*k+1]); w2(0xc); + case 1: + w2(0xc); w0(0); w2(0x8); w2(0xc); + for (k = 0; k < count / 2; k++) { + w0(buf[2 * k]); w2(0xd); + w0(buf[2 * k + 1]); w2(0xc); } break; - - case 2: w2(0xc); w0(0); w2(0x8); w2(0xc); - for (k=0;k<count;k++) w4(buf[k]); - w2(0xc); + case 2: + w2(0xc); w0(0); w2(0x8); w2(0xc); + for (k = 0; k < count; k++) + w4(buf[k]); + w2(0xc); break; } } static void fit3_connect(struct pi_adapter *pi) - -{ pi->saved_r0 = r0(); - pi->saved_r2 = r2(); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); w2(0xc); w0(0); w2(0xa); - if (pi->mode == 2) { - w2(0xc); w0(0x9); w2(0x8); w2(0xc); - } + if (pi->mode == 2) { + w2(0xc); w0(0x9); + w2(0x8); w2(0xc); + } } static void fit3_disconnect(struct pi_adapter *pi) - -{ w2(0xc); w0(0xa); w2(0x8); w2(0xc); +{ + w2(0xc); w0(0xa); w2(0x8); w2(0xc); w0(pi->saved_r0); - w2(pi->saved_r2); -} + w2(pi->saved_r2); +} static void fit3_log_adapter(struct pi_adapter *pi) +{ + char *mode_string[3] = { "4-bit", "8-bit", "EPP"}; -{ char *mode_string[3] = {"4-bit","8-bit","EPP"}; - - dev_info(&pi->dev, "FIT 3000 adapter at 0x%x, mode %d (%s), delay %d\n", - pi->port, pi->mode, mode_string[pi->mode], pi->delay); + dev_info(&pi->dev, + "FIT 3000 adapter at 0x%x, mode %d (%s), delay %d\n", + pi->port, pi->mode, mode_string[pi->mode], pi->delay); } static struct pi_protocol fit3 = { diff --git a/drivers/ata/pata_parport/friq.c b/drivers/ata/pata_parport/friq.c index 1647264cd9a8..dc428f54fe0c 100644 --- a/drivers/ata/pata_parport/friq.c +++ b/drivers/ata/pata_parport/friq.c @@ -1,24 +1,23 @@ -/* - friq.c (c) 1998 Grant R. Guenther <grant@torque.net> - Under the terms of the GNU General Public License - - friq.c is a low-level protocol driver for the Freecom "IQ" - parallel port IDE adapter. Early versions of this adapter - use the 'frpw' protocol. - - Freecom uses this adapter in a battery powered external - CD-ROM drive. It is also used in LS-120 drives by - Maxell and Panasonic, and other devices. - - The battery powered drive requires software support to - control the power to the drive. This module enables the - drive power when the high level driver (pcd) is loaded - and disables it when the module is unloaded. Note, if - the friq module is built in to the kernel, the power - will never be switched off, so other means should be - used to conserve battery power. - -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1998 Grant R. Guenther <grant@torque.net> + * + * friq.c is a low-level protocol driver for the Freecom "IQ" + * parallel port IDE adapter. Early versions of this adapter + * use the 'frpw' protocol. + * + * Freecom uses this adapter in a battery powered external + * CD-ROM drive. It is also used in LS-120 drives by + * Maxell and Panasonic, and other devices. + * + * The battery powered drive requires software support to + * control the power to the drive. This module enables the + * drive power when the high level driver (pcd) is loaded + * and disables it when the module is unloaded. Note, if + * the friq module is built in to the kernel, the power + * will never be switched off, so other means should be + * used to conserve battery power. + */ #include <linux/module.h> #include <linux/init.h> @@ -29,197 +28,206 @@ #include <asm/io.h> #include "pata_parport.h" -#define CMD(x) w2(4);w0(0xff);w0(0xff);w0(0x73);w0(0x73);\ - w0(0xc9);w0(0xc9);w0(0x26);w0(0x26);w0(x);w0(x); +#define CMD(x) \ + do { \ + w2(4); w0(0xff); w0(0xff); w0(0x73); w0(0x73); \ + w0(0xc9); w0(0xc9); w0(0x26); \ + w0(0x26); w0(x); w0(x); \ + } while (0) -#define j44(l,h) (((l>>4)&0x0f)|(h&0xf0)) +#define j44(l, h) (((l >> 4) & 0x0f) | (h & 0xf0)) -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set -*/ - -static int cont_map[2] = { 0x08, 0x10 }; +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + */ +static int cont_map[2] = { 0x08, 0x10 }; static int friq_read_regr(struct pi_adapter *pi, int cont, int regr) - -{ int h,l,r; +{ + int h, l, r; r = regr + cont_map[cont]; CMD(r); w2(6); l = r1(); w2(4); h = r1(); - w2(4); - - return j44(l,h); + w2(4); + return j44(l, h); } static void friq_write_regr(struct pi_adapter *pi, int cont, int regr, int val) - -{ int r; - - r = regr + cont_map[cont]; +{ + int r = regr + cont_map[cont]; CMD(r); w0(val); - w2(5);w2(7);w2(5);w2(4); + w2(5); w2(7); w2(5); w2(4); } static void friq_read_block_int(struct pi_adapter *pi, char *buf, int count, int regr) +{ + int h, l, k, ph; -{ int h, l, k, ph; - - switch(pi->mode) { - - case 0: CMD(regr); - for (k=0;k<count;k++) { - w2(6); l = r1(); - w2(4); h = r1(); - buf[k] = j44(l,h); - } - w2(4); - break; - - case 1: ph = 2; - CMD(regr+0xc0); - w0(0xff); - for (k=0;k<count;k++) { - w2(0xa4 + ph); - buf[k] = r0(); - ph = 2 - ph; - } - w2(0xac); w2(0xa4); w2(4); - break; - - case 2: CMD(regr+0x80); - for (k=0;k<count-2;k++) buf[k] = r4(); + switch (pi->mode) { + case 0: + CMD(regr); + for (k = 0; k < count; k++) { + w2(6); l = r1(); + w2(4); h = r1(); + buf[k] = j44(l, h); + } + w2(4); + break; + case 1: + ph = 2; + CMD(regr + 0xc0); + w0(0xff); + for (k = 0; k < count; k++) { + w2(0xa4 + ph); + buf[k] = r0(); + ph = 2 - ph; + } + w2(0xac); w2(0xa4); w2(4); + break; + case 2: + CMD(regr + 0x80); + for (k = 0; k < count - 2; k++) + buf[k] = r4(); w2(0xac); w2(0xa4); - buf[count-2] = r4(); - buf[count-1] = r4(); + buf[count - 2] = r4(); + buf[count - 1] = r4(); w2(4); break; - - case 3: CMD(regr+0x80); - for (k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w(); - w2(0xac); w2(0xa4); - buf[count-2] = r4(); - buf[count-1] = r4(); - w2(4); - break; - - case 4: CMD(regr+0x80); - for (k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l(); - buf[count-4] = r4(); - buf[count-3] = r4(); - w2(0xac); w2(0xa4); - buf[count-2] = r4(); - buf[count-1] = r4(); - w2(4); - break; - - } + case 3: + CMD(regr + 0x80); + for (k = 0; k < count / 2 - 1; k++) + ((u16 *)buf)[k] = r4w(); + w2(0xac); w2(0xa4); + buf[count - 2] = r4(); + buf[count - 1] = r4(); + w2(4); + break; + case 4: + CMD(regr + 0x80); + for (k = 0; k < count / 4 - 1; k++) + ((u32 *)buf)[k] = r4l(); + buf[count - 4] = r4(); + buf[count - 3] = r4(); + w2(0xac); w2(0xa4); + buf[count - 2] = r4(); + buf[count - 1] = r4(); + w2(4); + break; + } } static void friq_read_block(struct pi_adapter *pi, char *buf, int count) - -{ friq_read_block_int(pi,buf,count,0x08); +{ + friq_read_block_int(pi, buf, count, 0x08); } static void friq_write_block(struct pi_adapter *pi, char *buf, int count) - -{ int k; - - switch(pi->mode) { +{ + int k; + switch (pi->mode) { case 0: - case 1: CMD(8); w2(5); - for (k=0;k<count;k++) { + case 1: + CMD(8); w2(5); + for (k = 0; k < count; k++) { w0(buf[k]); - w2(7);w2(5); + w2(7); w2(5); } w2(4); break; - - case 2: CMD(0xc8); w2(5); - for (k=0;k<count;k++) w4(buf[k]); + case 2: + CMD(0xc8); w2(5); + for (k = 0; k < count; k++) + w4(buf[k]); + w2(4); + break; + case 3: + CMD(0xc8); w2(5); + for (k = 0; k < count / 2; k++) + w4w(((u16 *)buf)[k]); + w2(4); + break; + case 4: + CMD(0xc8); w2(5); + for (k = 0; k < count / 4; k++) + w4l(((u32 *)buf)[k]); w2(4); break; - - case 3: CMD(0xc8); w2(5); - for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]); - w2(4); - break; - - case 4: CMD(0xc8); w2(5); - for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]); - w2(4); - break; - } +} } static void friq_connect(struct pi_adapter *pi) - -{ pi->saved_r0 = r0(); - pi->saved_r2 = r2(); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); w2(4); } static void friq_disconnect(struct pi_adapter *pi) - -{ CMD(0x20); +{ + CMD(0x20); w0(pi->saved_r0); - w2(pi->saved_r2); -} + w2(pi->saved_r2); +} static int friq_test_proto(struct pi_adapter *pi) - -{ int j, k, r; - int e[2] = {0,0}; +{ + int j, k, r; + int e[2] = { 0, 0 }; char scratch[512]; - pi->saved_r0 = r0(); + pi->saved_r0 = r0(); w0(0xff); udelay(20); CMD(0x3d); /* turn the power on */ udelay(500); w0(pi->saved_r0); friq_connect(pi); - for (j=0;j<2;j++) { - friq_write_regr(pi,0,6,0xa0+j*0x10); - for (k=0;k<256;k++) { - friq_write_regr(pi,0,2,k^0xaa); - friq_write_regr(pi,0,3,k^0x55); - if (friq_read_regr(pi,0,2) != (k^0xaa)) e[j]++; - } - } + for (j = 0; j < 2; j++) { + friq_write_regr(pi, 0, 6, 0xa0 + j * 0x10); + for (k = 0; k < 256; k++) { + friq_write_regr(pi, 0, 2, k ^ 0xaa); + friq_write_regr(pi, 0, 3, k ^ 0x55); + if (friq_read_regr(pi, 0, 2) != (k ^ 0xaa)) + e[j]++; + } + } friq_disconnect(pi); friq_connect(pi); - friq_read_block_int(pi,scratch,512,0x10); - r = 0; - for (k=0;k<128;k++) if (scratch[k] != k) r++; + friq_read_block_int(pi, scratch, 512, 0x10); + r = 0; + for (k = 0; k < 128; k++) { + if (scratch[k] != k) + r++; + } friq_disconnect(pi); - dev_dbg(&pi->dev, "friq: port 0x%x, mode %d, test=(%d,%d,%d)\n", - pi->port, pi->mode, e[0], e[1], r); + dev_dbg(&pi->dev, + "friq: port 0x%x, mode %d, test=(%d,%d,%d)\n", + pi->port, pi->mode, e[0], e[1], r); - return (r || (e[0] && e[1])); + return r || (e[0] && e[1]); } - static void friq_log_adapter(struct pi_adapter *pi) +{ + char *mode_string[6] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32"}; -{ char *mode_string[6] = {"4-bit","8-bit", - "EPP-8","EPP-16","EPP-32"}; - - dev_info(&pi->dev, "Freecom IQ ASIC-2 adapter at 0x%x, mode %d (%s), delay %d\n", - pi->port, pi->mode, mode_string[pi->mode], pi->delay); + dev_info(&pi->dev, + "Freecom IQ ASIC-2 adapter at 0x%x, mode %d (%s), delay %d\n", + pi->port, pi->mode, mode_string[pi->mode], pi->delay); pi->private = 1; friq_connect(pi); CMD(0x9e); /* disable sleep timer */ friq_disconnect(pi); - } static void friq_release_proto(struct pi_adapter *pi) diff --git a/drivers/ata/pata_parport/frpw.c b/drivers/ata/pata_parport/frpw.c index 3ec0abf16fa6..28d9bb2c6baf 100644 --- a/drivers/ata/pata_parport/frpw.c +++ b/drivers/ata/pata_parport/frpw.c @@ -1,17 +1,15 @@ -/* - frpw.c (c) 1996-8 Grant R. Guenther <grant@torque.net> - Under the terms of the GNU General Public License - - frpw.c is a low-level protocol driver for the Freecom "Power" - parallel port IDE adapter. - - Some applications of this adapter may require a "printer" reset - prior to loading the driver. This can be done by loading and - unloading the "lp" driver, or it can be done by this driver - if you define FRPW_HARD_RESET. The latter is not recommended - as it may upset devices on other ports. - -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1996-1998 Grant R. Guenther <grant@torque.net> + * + * frpw.c is a low-level protocol driver for the Freecom "Power" parallel port + * IDE adapter. + * + * Some applications of this adapter may require a "printer" reset prior to + * loading the driver. This can be done by loading and unloading the "lp" + * driver, or it can be done by this driver if you define FRPW_HARD_RESET. + * The latter is not recommended as it may upset devices on other ports. + */ #include <linux/module.h> #include <linux/init.h> @@ -25,15 +23,15 @@ #define cec4 w2(0xc);w2(0xe);w2(0xe);w2(0xc);w2(4);w2(4);w2(4); #define j44(l,h) (((l>>4)&0x0f)|(h&0xf0)) -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set -*/ - +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + */ static int cont_map[2] = { 0x08, 0x10 }; static int frpw_read_regr(struct pi_adapter *pi, int cont, int regr) - -{ int h,l,r; +{ + int h, l, r; r = regr + cont_map[cont]; @@ -41,145 +39,156 @@ static int frpw_read_regr(struct pi_adapter *pi, int cont, int regr) w0(r); cec4; w2(6); l = r1(); w2(4); h = r1(); - w2(4); - - return j44(l,h); + w2(4); + return j44(l, h); } static void frpw_write_regr(struct pi_adapter *pi, int cont, int regr, int val) +{ + int r = regr + cont_map[cont]; -{ int r; - - r = regr + cont_map[cont]; - - w2(4); w0(r); cec4; + w2(4); w0(r); cec4; w0(val); - w2(5);w2(7);w2(5);w2(4); + w2(5); w2(7); w2(5); w2(4); } -static void frpw_read_block_int(struct pi_adapter *pi, char *buf, int count, int regr) - -{ int h, l, k, ph; - - switch(pi->mode) { - - case 0: w2(4); w0(regr); cec4; - for (k=0;k<count;k++) { - w2(6); l = r1(); - w2(4); h = r1(); - buf[k] = j44(l,h); - } - w2(4); - break; - - case 1: ph = 2; - w2(4); w0(regr + 0xc0); cec4; - w0(0xff); - for (k=0;k<count;k++) { - w2(0xa4 + ph); - buf[k] = r0(); - ph = 2 - ph; - } - w2(0xac); w2(0xa4); w2(4); - break; - - case 2: w2(4); w0(regr + 0x80); cec4; - for (k=0;k<count;k++) buf[k] = r4(); - w2(0xac); w2(0xa4); - w2(4); - break; - - case 3: w2(4); w0(regr + 0x80); cec4; - for (k=0;k<count-2;k++) buf[k] = r4(); +static void frpw_read_block_int(struct pi_adapter *pi, char *buf, int count, + int regr) +{ + int h, l, k, ph; + + switch (pi->mode) { + case 0: + w2(4); w0(regr); cec4; + for (k = 0; k < count; k++) { + w2(6); l = r1(); + w2(4); h = r1(); + buf[k] = j44(l, h); + } + w2(4); + break; + + case 1: + ph = 2; + w2(4); w0(regr + 0xc0); cec4; + w0(0xff); + for (k = 0; k < count; k++) { + w2(0xa4 + ph); + buf[k] = r0(); + ph = 2 - ph; + } + w2(0xac); w2(0xa4); w2(4); + break; + + case 2: + w2(4); w0(regr + 0x80); cec4; + for (k = 0; k < count; k++) + buf[k] = r4(); w2(0xac); w2(0xa4); - buf[count-2] = r4(); - buf[count-1] = r4(); w2(4); break; - case 4: w2(4); w0(regr + 0x80); cec4; - for (k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w(); - w2(0xac); w2(0xa4); - buf[count-2] = r4(); - buf[count-1] = r4(); - w2(4); - break; - - case 5: w2(4); w0(regr + 0x80); cec4; - for (k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l(); - buf[count-4] = r4(); - buf[count-3] = r4(); - w2(0xac); w2(0xa4); - buf[count-2] = r4(); - buf[count-1] = r4(); - w2(4); - break; + case 3: + w2(4); w0(regr + 0x80); cec4; + for (k = 0; k < count - 2; k++) + buf[k] = r4(); + w2(0xac); w2(0xa4); + buf[count - 2] = r4(); + buf[count - 1] = r4(); + w2(4); + break; + + case 4: + w2(4); w0(regr + 0x80); cec4; + for (k = 0; k < count / 2 - 1; k++) + ((u16 *)buf)[k] = r4w(); + w2(0xac); w2(0xa4); + buf[count - 2] = r4(); + buf[count - 1] = r4(); + w2(4); + break; + case 5: + w2(4); w0(regr + 0x80); cec4; + for (k = 0; k < count / 4 - 1; k++) + ((u32 *)buf)[k] = r4l(); + buf[count - 4] = r4(); + buf[count - 3] = r4(); + w2(0xac); w2(0xa4); + buf[count - 2] = r4(); + buf[count - 1] = r4(); + w2(4); + break; } } static void frpw_read_block(struct pi_adapter *pi, char *buf, int count) - -{ frpw_read_block_int(pi,buf,count,0x08); +{ + frpw_read_block_int(pi, buf, count, 0x08); } static void frpw_write_block(struct pi_adapter *pi, char *buf, int count) - -{ int k; - - switch(pi->mode) { +{ + int k; + switch (pi->mode) { case 0: case 1: - case 2: w2(4); w0(8); cec4; w2(5); - for (k=0;k<count;k++) { + case 2: + w2(4); w0(8); cec4; w2(5); + for (k = 0; k < count; k++) { w0(buf[k]); - w2(7);w2(5); + w2(7); w2(5); } w2(4); break; - case 3: w2(4); w0(0xc8); cec4; w2(5); - for (k=0;k<count;k++) w4(buf[k]); + case 3: + w2(4); w0(0xc8); cec4; w2(5); + for (k = 0; k < count; k++) + w4(buf[k]); w2(4); break; - case 4: w2(4); w0(0xc8); cec4; w2(5); - for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]); - w2(4); - break; + case 4: + w2(4); w0(0xc8); cec4; w2(5); + for (k = 0; k < count / 2; k++) + w4w(((u16 *)buf)[k]); + w2(4); + break; - case 5: w2(4); w0(0xc8); cec4; w2(5); - for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]); - w2(4); - break; + case 5: + w2(4); w0(0xc8); cec4; w2(5); + for (k = 0; k < count / 4; k++) + w4l(((u32 *)buf)[k]); + w2(4); + break; } } static void frpw_connect(struct pi_adapter *pi) - -{ pi->saved_r0 = r0(); - pi->saved_r2 = r2(); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); w2(4); } static void frpw_disconnect(struct pi_adapter *pi) - -{ w2(4); w0(0x20); cec4; +{ + w2(4); w0(0x20); cec4; w0(pi->saved_r0); - w2(pi->saved_r2); -} - -/* Stub logic to see if PNP string is available - used to distinguish - between the Xilinx and ASIC implementations of the Freecom adapter. -*/ + w2(pi->saved_r2); +} +/* + * Stub logic to see if PNP string is available - used to distinguish + * between the Xilinx and ASIC implementations of the Freecom adapter. + * returns chip_type: 0 = Xilinx, 1 = ASIC + */ static int frpw_test_pnp(struct pi_adapter *pi) - -/* returns chip_type: 0 = Xilinx, 1 = ASIC */ - -{ int olddelay, a, b; +{ + int olddelay, a, b; #ifdef FRPW_HARD_RESET w0(0); w2(8); udelay(50); w2(0xc); /* parallel bus reset */ @@ -191,7 +200,7 @@ static int frpw_test_pnp(struct pi_adapter *pi) pi->saved_r0 = r0(); pi->saved_r2 = r2(); - + w2(4); w0(4); w2(6); w2(7); a = r1() & 0xff; w2(4); b = r1() & 0xff; w2(0xc); w2(0xe); w2(4); @@ -200,65 +209,70 @@ static int frpw_test_pnp(struct pi_adapter *pi) w0(pi->saved_r0); w2(pi->saved_r2); - return ((~a&0x40) && (b&0x40)); -} - -/* We use the pi->private to remember the result of the PNP test. - To make this work, private = port*2 + chip. Yes, I know it's - a hack :-( -*/ + return ((~a & 0x40) && (b & 0x40)); +} +/* + * We use the pi->private to remember the result of the PNP test. + * To make this work, private = port*2 + chip. Yes, I know it's a hack :-( + */ static int frpw_test_proto(struct pi_adapter *pi) - -{ int j, k, r; - int e[2] = {0,0}; +{ + int j, k, r; + int e[2] = { 0, 0 }; char scratch[512]; - if ((pi->private>>1) != pi->port) - pi->private = frpw_test_pnp(pi) + 2*pi->port; + if ((pi->private >> 1) != pi->port) + pi->private = frpw_test_pnp(pi) + 2*pi->port; - if (((pi->private%2) == 0) && (pi->mode > 2)) { - dev_dbg(&pi->dev, "frpw: Xilinx does not support mode %d\n", pi->mode); - return 1; + if (((pi->private & 0x1) == 0) && (pi->mode > 2)) { + dev_dbg(&pi->dev, + "frpw: Xilinx does not support mode %d\n", pi->mode); + return 1; } - if (((pi->private%2) == 1) && (pi->mode == 2)) { + if (((pi->private & 0x1) == 1) && (pi->mode == 2)) { dev_dbg(&pi->dev, "frpw: ASIC does not support mode 2\n"); - return 1; + return 1; } frpw_connect(pi); - for (j=0;j<2;j++) { - frpw_write_regr(pi,0,6,0xa0+j*0x10); - for (k=0;k<256;k++) { - frpw_write_regr(pi,0,2,k^0xaa); - frpw_write_regr(pi,0,3,k^0x55); - if (frpw_read_regr(pi,0,2) != (k^0xaa)) e[j]++; - } - } + for (j = 0; j < 2; j++) { + frpw_write_regr(pi, 0, 6, 0xa0 + j * 0x10); + for (k = 0; k < 256; k++) { + frpw_write_regr(pi, 0, 2, k ^ 0xaa); + frpw_write_regr(pi, 0, 3, k ^ 0x55); + if (frpw_read_regr(pi, 0, 2) != (k ^ 0xaa)) + e[j]++; + } + } frpw_disconnect(pi); frpw_connect(pi); - frpw_read_block_int(pi,scratch,512,0x10); - r = 0; - for (k=0;k<128;k++) if (scratch[k] != k) r++; + frpw_read_block_int(pi, scratch, 512, 0x10); + r = 0; + for (k = 0; k < 128; k++) { + if (scratch[k] != k) + r++; + } frpw_disconnect(pi); - dev_dbg(&pi->dev, "frpw: port 0x%x, chip %ld, mode %d, test=(%d,%d,%d)\n", - pi->port, (pi->private%2), pi->mode, e[0], e[1], r); + dev_dbg(&pi->dev, + "frpw: port 0x%x, chip %ld, mode %d, test=(%d,%d,%d)\n", + pi->port, (pi->private%2), pi->mode, e[0], e[1], r); - return (r || (e[0] && e[1])); + return r || (e[0] && e[1]); } - static void frpw_log_adapter(struct pi_adapter *pi) -{ char *mode_string[6] = {"4-bit","8-bit","EPP", - "EPP-8","EPP-16","EPP-32"}; +{ + char *mode[6] = { "4-bit", "8-bit", "EPP", "EPP-8", "EPP-16", "EPP-32"}; - dev_info(&pi->dev, "Freecom (%s) adapter at 0x%x, mode %d (%s), delay %d\n", - ((pi->private % 2) == 0) ? "Xilinx" : "ASIC", - pi->port, pi->mode, mode_string[pi->mode], pi->delay); + dev_info(&pi->dev, + "Freecom (%s) adapter at 0x%x, mode %d (%s), delay %d\n", + ((pi->private & 0x1) == 0) ? "Xilinx" : "ASIC", + pi->port, pi->mode, mode[pi->mode], pi->delay); } static struct pi_protocol frpw = { diff --git a/drivers/ata/pata_parport/kbic.c b/drivers/ata/pata_parport/kbic.c index 8213e62f8f00..6023e071516d 100644 --- a/drivers/ata/pata_parport/kbic.c +++ b/drivers/ata/pata_parport/kbic.c @@ -1,16 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* - kbic.c (c) 1997-8 Grant R. Guenther <grant@torque.net> - Under the terms of the GNU General Public License. - - This is a low-level driver for the KBIC-951A and KBIC-971A - parallel to IDE adapter chips from KingByte Information Systems. - - The chips are almost identical, however, the wakeup code - required for the 971A interferes with the correct operation of - the 951A, so this driver registers itself twice, once for - each chip. - -*/ + * (c) 1997-1998 Grant R. Guenther <grant@torque.net> + * + * This is a low-level driver for the KBIC-951A and KBIC-971A + * parallel to IDE adapter chips from KingByte Information Systems. + * + * The chips are almost identical, however, the wakeup code + * required for the 971A interferes with the correct operation of + * the 951A, so this driver registers itself twice, once for + * each chip. + */ #include <linux/module.h> #include <linux/init.h> @@ -21,212 +20,223 @@ #include <asm/io.h> #include "pata_parport.h" -#define r12w() (delay_p,inw(pi->port+1)&0xffff) +#define r12w() (delay_p, inw(pi->port + 1) & 0xffff) -#define j44(a,b) ((((a>>4)&0x0f)|(b&0xf0))^0x88) -#define j53(w) (((w>>3)&0x1f)|((w>>4)&0xe0)) +#define j44(a, b) ((((a >> 4) & 0x0f) | (b & 0xf0)) ^ 0x88) +#define j53(w) (((w >> 3) & 0x1f) | ((w >> 4) & 0xe0)) -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set -*/ - -static int cont_map[2] = { 0x80, 0x40 }; +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + */ +static int cont_map[2] = { 0x80, 0x40 }; static int kbic_read_regr(struct pi_adapter *pi, int cont, int regr) +{ + int a, b, s; -{ int a, b, s; - - s = cont_map[cont]; + s = cont_map[cont]; switch (pi->mode) { - - case 0: w0(regr|0x18|s); w2(4); w2(6); w2(4); w2(1); w0(8); - a = r1(); w0(0x28); b = r1(); w2(4); - return j44(a,b); - - case 1: w0(regr|0x38|s); w2(4); w2(6); w2(4); w2(5); w0(8); + case 0: + w0(regr | 0x18 | s); w2(4); w2(6); w2(4); w2(1); w0(8); + a = r1(); w0(0x28); b = r1(); w2(4); + return j44(a, b); + case 1: + w0(regr|0x38 | s); w2(4); w2(6); w2(4); w2(5); w0(8); a = r12w(); w2(4); return j53(a); - - case 2: w0(regr|0x08|s); w2(4); w2(6); w2(4); w2(0xa5); w2(0xa1); + case 2: + w0(regr | 0x08 | s); w2(4); w2(6); w2(4); w2(0xa5); w2(0xa1); a = r0(); w2(4); - return a; - + return a; case 3: case 4: - case 5: w0(0x20|s); w2(4); w2(6); w2(4); w3(regr); + case 5: + w0(0x20 | s); w2(4); w2(6); w2(4); w3(regr); a = r4(); b = r4(); w2(4); w2(0); w2(4); return a; - } + return -1; -} +} static void kbic_write_regr(struct pi_adapter *pi, int cont, int regr, int val) +{ + int s = cont_map[cont]; -{ int s; - - s = cont_map[cont]; - - switch (pi->mode) { - - case 0: - case 1: - case 2: w0(regr|0x10|s); w2(4); w2(6); w2(4); + switch (pi->mode) { + case 0: + case 1: + case 2: + w0(regr | 0x10 | s); w2(4); w2(6); w2(4); w0(val); w2(5); w2(4); break; - case 3: case 4: - case 5: w0(0x20|s); w2(4); w2(6); w2(4); w3(regr); + case 5: + w0(0x20 | s); w2(4); w2(6); w2(4); w3(regr); w4(val); w4(val); w2(4); w2(0); w2(4); - break; - + break; } } static void k951_connect(struct pi_adapter *pi) - -{ pi->saved_r0 = r0(); - pi->saved_r2 = r2(); - w2(4); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); + w2(4); } static void k951_disconnect(struct pi_adapter *pi) - -{ w0(pi->saved_r0); - w2(pi->saved_r2); +{ + w0(pi->saved_r0); + w2(pi->saved_r2); } -#define CCP(x) w2(0xc4);w0(0xaa);w0(0x55);w0(0);w0(0xff);w0(0x87);\ - w0(0x78);w0(x);w2(0xc5);w2(0xc4);w0(0xff); +#define CCP(x) \ + do { \ + w2(0xc4); w0(0xaa); w0(0x55); \ + w0(0); w0(0xff); w0(0x87); \ + w0(0x78); w0(x); w2(0xc5); \ + w2(0xc4); w0(0xff); \ + } while (0) static void k971_connect(struct pi_adapter *pi) - -{ pi->saved_r0 = r0(); - pi->saved_r2 = r2(); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); CCP(0x20); - w2(4); + w2(4); } static void k971_disconnect(struct pi_adapter *pi) - -{ CCP(0x30); +{ + CCP(0x30); w0(pi->saved_r0); - w2(pi->saved_r2); + w2(pi->saved_r2); } -/* counts must be congruent to 0 MOD 4, but all known applications - have this property. -*/ - +/* + * count must be congruent to 0 MOD 4, but all known applications + *have this property. + */ static void kbic_read_block(struct pi_adapter *pi, char *buf, int count) +{ + int k, a, b; -{ int k, a, b; - - switch (pi->mode) { - - case 0: w0(0x98); w2(4); w2(6); w2(4); - for (k=0;k<count/2;k++) { - w2(1); w0(8); a = r1(); - w0(0x28); b = r1(); - buf[2*k] = j44(a,b); - w2(5); b = r1(); - w0(8); a = r1(); - buf[2*k+1] = j44(a,b); + switch (pi->mode) { + case 0: + w0(0x98); w2(4); w2(6); w2(4); + for (k = 0; k < count / 2; k++) { + w2(1); w0(8); + a = r1(); + w0(0x28); + b = r1(); + buf[2 * k] = j44(a, b); + w2(5); + b = r1(); + w0(8); + a = r1(); + buf[2 * k + 1] = j44(a, b); w2(4); - } - break; - - case 1: w0(0xb8); w2(4); w2(6); w2(4); - for (k=0;k<count/4;k++) { - w0(0xb8); - w2(4); w2(5); - w0(8); buf[4*k] = j53(r12w()); - w0(0xb8); buf[4*k+1] = j53(r12w()); + } + break; + case 1: + w0(0xb8); w2(4); w2(6); w2(4); + for (k = 0; k < count / 4; k++) { + w0(0xb8); w2(4); w2(5); - buf[4*k+3] = j53(r12w()); - w0(8); buf[4*k+2] = j53(r12w()); - } - w2(4); - break; - - case 2: w0(0x88); w2(4); w2(6); w2(4); - for (k=0;k<count/2;k++) { - w2(0xa0); w2(0xa1); buf[2*k] = r0(); - w2(0xa5); buf[2*k+1] = r0(); - } - w2(4); - break; - - case 3: w0(0xa0); w2(4); w2(6); w2(4); w3(0); - for (k=0;k<count;k++) buf[k] = r4(); - w2(4); w2(0); w2(4); - break; - - case 4: w0(0xa0); w2(4); w2(6); w2(4); w3(0); - for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w(); - w2(4); w2(0); w2(4); - break; - - case 5: w0(0xa0); w2(4); w2(6); w2(4); w3(0); - for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l(); - w2(4); w2(0); w2(4); - break; - - - } + w0(8); + buf[4 * k] = j53(r12w()); + w0(0xb8); + buf[4 * k + 1] = j53(r12w()); + w2(4); w2(5); + buf[4 * k + 3] = j53(r12w()); + w0(8); + buf[4 * k + 2] = j53(r12w()); + } + w2(4); + break; + case 2: + w0(0x88); w2(4); w2(6); w2(4); + for (k = 0; k < count / 2; k++) { + w2(0xa0); w2(0xa1); + buf[2 * k] = r0(); + w2(0xa5); + buf[2 * k + 1] = r0(); + } + w2(4); + break; + case 3: + w0(0xa0); w2(4); w2(6); w2(4); w3(0); + for (k = 0; k < count; k++) + buf[k] = r4(); + w2(4); w2(0); w2(4); + break; + case 4: + w0(0xa0); w2(4); w2(6); w2(4); w3(0); + for (k = 0; k < count / 2; k++) + ((u16 *)buf)[k] = r4w(); + w2(4); w2(0); w2(4); + break; + case 5: + w0(0xa0); w2(4); w2(6); w2(4); w3(0); + for (k = 0; k < count / 4; k++) + ((u32 *)buf)[k] = r4l(); + w2(4); w2(0); w2(4); + break; + } } static void kbic_write_block(struct pi_adapter *pi, char *buf, int count) +{ + int k; -{ int k; - - switch (pi->mode) { - - case 0: - case 1: - case 2: w0(0x90); w2(4); w2(6); w2(4); - for(k=0;k<count/2;k++) { - w0(buf[2*k+1]); w2(0); w2(4); - w0(buf[2*k]); w2(5); w2(4); + switch (pi->mode) { + case 0: + case 1: + case 2: + w0(0x90); w2(4); w2(6); w2(4); + for (k = 0; k < count / 2; k++) { + w0(buf[2 * k + 1]); + w2(0); w2(4); + w0(buf[2 * k]); + w2(5); w2(4); } break; - - case 3: w0(0xa0); w2(4); w2(6); w2(4); w3(0); - for(k=0;k<count/2;k++) { - w4(buf[2*k+1]); - w4(buf[2*k]); - } + case 3: + w0(0xa0); w2(4); w2(6); w2(4); w3(0); + for (k = 0; k < count / 2; k++) { + w4(buf[2 * k + 1]); + w4(buf[2 * k]); + } w2(4); w2(0); w2(4); break; - - case 4: w0(0xa0); w2(4); w2(6); w2(4); w3(0); + case 4: + w0(0xa0); w2(4); w2(6); w2(4); w3(0); for (k = 0; k < count / 2; k++) w4w(swab16(((u16 *)buf)[k])); - w2(4); w2(0); w2(4); - break; - - case 5: w0(0xa0); w2(4); w2(6); w2(4); w3(0); + w2(4); w2(0); w2(4); + break; + case 5: + w0(0xa0); w2(4); w2(6); w2(4); w3(0); for (k = 0; k < count / 4; k++) w4l(swab16(((u16 *)buf)[2 * k]) | swab16(((u16 *)buf)[2 * k + 1]) << 16); - w2(4); w2(0); w2(4); - break; - - } - + w2(4); w2(0); w2(4); + break; + } } static void kbic_log_adapter(struct pi_adapter *pi, char *chip) - -{ char *mode_string[6] = {"4-bit","5/3","8-bit", - "EPP-8","EPP_16","EPP-32"}; +{ + char *mode[6] = { "4-bit", "5/3", "8-bit", "EPP-8", "EPP_16", "EPP-32"}; dev_info(&pi->dev, "KingByte %s at 0x%x, mode %d (%s), delay %d\n", - chip, pi->port, pi->mode, mode_string[pi->mode], pi->delay); + chip, pi->port, pi->mode, mode[pi->mode], pi->delay); } static void k951_log_adapter(struct pi_adapter *pi) diff --git a/drivers/ata/pata_parport/ktti.c b/drivers/ata/pata_parport/ktti.c index 4890b1f12348..bca6c20ef617 100644 --- a/drivers/ata/pata_parport/ktti.c +++ b/drivers/ata/pata_parport/ktti.c @@ -1,12 +1,11 @@ -/* - ktti.c (c) 1998 Grant R. Guenther <grant@torque.net> - Under the terms of the GNU General Public License. - - ktti.c is a low-level protocol driver for the KT Technology - parallel port adapter. This adapter is used in the "PHd" - portable hard-drives. As far as I can tell, this device - supports 4-bit mode _only_. - +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1998 Grant R. Guenther <grant@torque.net> + * + * ktti.c is a low-level protocol driver for the KT Technology + * parallel port adapter. This adapter is used in the "PHd" + * portable hard-drives. As far as I can tell, this device + * supports 4-bit mode _only_. */ #include <linux/module.h> @@ -18,80 +17,76 @@ #include <asm/io.h> #include "pata_parport.h" -#define j44(a,b) (((a>>4)&0x0f)|(b&0xf0)) +#define j44(a, b) (((a >> 4) & 0x0f) | (b & 0xf0)) -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set -*/ - -static int cont_map[2] = { 0x10, 0x08 }; +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + */ +static int cont_map[2] = { 0x10, 0x08 }; static void ktti_write_regr(struct pi_adapter *pi, int cont, int regr, int val) +{ + int r = regr + cont_map[cont]; -{ int r; - - r = regr + cont_map[cont]; - - w0(r); w2(0xb); w2(0xa); w2(3); w2(6); + w0(r); w2(0xb); w2(0xa); w2(3); w2(6); w0(val); w2(3); w0(0); w2(6); w2(0xb); } static int ktti_read_regr(struct pi_adapter *pi, int cont, int regr) - -{ int a, b, r; +{ + int a, b, r; r = regr + cont_map[cont]; - w0(r); w2(0xb); w2(0xa); w2(9); w2(0xc); w2(9); + w0(r); w2(0xb); w2(0xa); w2(9); w2(0xc); w2(9); a = r1(); w2(0xc); b = r1(); w2(9); w2(0xc); w2(9); - return j44(a,b); - + return j44(a, b); } static void ktti_read_block(struct pi_adapter *pi, char *buf, int count) +{ + int k, a, b; -{ int k, a, b; - - for (k=0;k<count/2;k++) { + for (k = 0; k < count / 2; k++) { w0(0x10); w2(0xb); w2(0xa); w2(9); w2(0xc); w2(9); a = r1(); w2(0xc); b = r1(); w2(9); - buf[2*k] = j44(a,b); + buf[2*k] = j44(a, b); a = r1(); w2(0xc); b = r1(); w2(9); - buf[2*k+1] = j44(a,b); + buf[2*k+1] = j44(a, b); } } static void ktti_write_block(struct pi_adapter *pi, char *buf, int count) +{ + int k; -{ int k; - - for (k=0;k<count/2;k++) { + for (k = 0; k < count / 2; k++) { w0(0x10); w2(0xb); w2(0xa); w2(3); w2(6); - w0(buf[2*k]); w2(3); - w0(buf[2*k+1]); w2(6); + w0(buf[2 * k]); w2(3); + w0(buf[2 * k + 1]); w2(6); w2(0xb); } } static void ktti_connect(struct pi_adapter *pi) - -{ pi->saved_r0 = r0(); - pi->saved_r2 = r2(); - w2(0xb); w2(0xa); w0(0); w2(3); w2(6); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); + w2(0xb); w2(0xa); w0(0); w2(3); w2(6); } static void ktti_disconnect(struct pi_adapter *pi) - -{ w2(0xb); w2(0xa); w0(0xa0); w2(3); w2(4); +{ + w2(0xb); w2(0xa); w0(0xa0); w2(3); w2(4); w0(pi->saved_r0); - w2(pi->saved_r2); -} + w2(pi->saved_r2); +} static void ktti_log_adapter(struct pi_adapter *pi) - { dev_info(&pi->dev, "KT adapter at 0x%x, delay %d\n", - pi->port, pi->delay); + pi->port, pi->delay); } static struct pi_protocol ktti = { diff --git a/drivers/ata/pata_parport/on20.c b/drivers/ata/pata_parport/on20.c index 276ace12d490..34e69da2bec8 100644 --- a/drivers/ata/pata_parport/on20.c +++ b/drivers/ata/pata_parport/on20.c @@ -1,10 +1,10 @@ -/* - on20.c (c) 1996-8 Grant R. Guenther <grant@torque.net> - Under the terms of the GNU General Public License. - - on20.c is a low-level protocol driver for the - Onspec 90c20 parallel to IDE adapter. -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1996-1998 Grant R. Guenther <grant@torque.net> + * + * on20.c is a low-level protocol driver for the + * Onspec 90c20 parallel to IDE adapter. + */ #include <linux/module.h> #include <linux/init.h> @@ -15,99 +15,114 @@ #include <asm/io.h> #include "pata_parport.h" -#define op(f) w2(4);w0(f);w2(5);w2(0xd);w2(5);w2(0xd);w2(5);w2(4); -#define vl(v) w2(4);w0(v);w2(5);w2(7);w2(5);w2(4); - -#define j44(a,b) (((a>>4)&0x0f)|(b&0xf0)) - -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set -*/ - -static int on20_read_regr(struct pi_adapter *pi, int cont, int regr) - -{ int h,l, r ; +#define op(f) \ + do { \ + w2(4); w0(f); w2(5); w2(0xd); \ + w2(5); w2(0xd); w2(5); w2(4); \ + } while (0) - r = (regr<<2) + 1 + cont; +#define vl(v) \ + do { \ + w2(4); w0(v); w2(5); \ + w2(7); w2(5); w2(4); \ + } while (0) - op(1); vl(r); op(0); +#define j44(a, b) (((a >> 4) & 0x0f) | (b & 0xf0)) - switch (pi->mode) { - - case 0: w2(4); w2(6); l = r1(); - w2(4); w2(6); h = r1(); - w2(4); w2(6); w2(4); w2(6); w2(4); - return j44(l,h); - - case 1: w2(4); w2(0x26); r = r0(); - w2(4); w2(0x26); w2(4); - return r; +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + */ +static int on20_read_regr(struct pi_adapter *pi, int cont, int regr) +{ + int h, l, r; + + r = (regr << 2) + 1 + cont; + + op(1); vl(r); op(0); + + switch (pi->mode) { + case 0: + w2(4); w2(6); l = r1(); + w2(4); w2(6); h = r1(); + w2(4); w2(6); w2(4); w2(6); w2(4); + return j44(l, h); + case 1: + w2(4); w2(0x26); r = r0(); + w2(4); w2(0x26); w2(4); + return r; } + return -1; -} +} static void on20_write_regr(struct pi_adapter *pi, int cont, int regr, int val) +{ + int r = (regr << 2) + 1 + cont; -{ int r; - - r = (regr<<2) + 1 + cont; - - op(1); vl(r); - op(0); vl(val); + op(1); vl(r); + op(0); vl(val); op(0); vl(val); } static void on20_connect(struct pi_adapter *pi) - -{ pi->saved_r0 = r0(); - pi->saved_r2 = r2(); - - w2(4);w0(0);w2(0xc);w2(4);w2(6);w2(4);w2(6);w2(4); - if (pi->mode) { op(2); vl(8); op(2); vl(9); } - else { op(2); vl(0); op(2); vl(8); } +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); + + w2(4); w0(0); w2(0xc); w2(4); w2(6); w2(4); w2(6); w2(4); + if (pi->mode) { + op(2); vl(8); op(2); vl(9); + } else { + op(2); vl(0); op(2); vl(8); + } } static void on20_disconnect(struct pi_adapter *pi) - -{ w2(4);w0(7);w2(4);w2(0xc);w2(4); - w0(pi->saved_r0); - w2(pi->saved_r2); -} +{ + w2(4); w0(7); w2(4); w2(0xc); w2(4); + w0(pi->saved_r0); + w2(pi->saved_r2); +} static void on20_read_block(struct pi_adapter *pi, char *buf, int count) - -{ int k, l, h; +{ + int k, l, h; op(1); vl(1); op(0); - for (k=0;k<count;k++) - if (pi->mode) { - w2(4); w2(0x26); buf[k] = r0(); - } else { - w2(6); l = r1(); w2(4); - w2(6); h = r1(); w2(4); - buf[k] = j44(l,h); - } + for (k = 0; k < count; k++) { + if (pi->mode) { + w2(4); w2(0x26); buf[k] = r0(); + } else { + w2(6); l = r1(); w2(4); + w2(6); h = r1(); w2(4); + buf[k] = j44(l, h); + } + } w2(4); } static void on20_write_block(struct pi_adapter *pi, char *buf, int count) - -{ int k; +{ + int k; op(1); vl(1); op(0); - for (k=0;k<count;k++) { w2(5); w0(buf[k]); w2(7); } + for (k = 0; k < count; k++) { + w2(5); w0(buf[k]); w2(7); + } w2(4); } static void on20_log_adapter(struct pi_adapter *pi) +{ + char *mode_string[2] = { "4-bit", "8-bit" }; -{ char *mode_string[2] = {"4-bit","8-bit"}; - - dev_info(&pi->dev, "OnSpec 90c20 at 0x%x, mode %d (%s), delay %d\n", - pi->port, pi->mode, mode_string[pi->mode], pi->delay); + dev_info(&pi->dev, + "OnSpec 90c20 at 0x%x, mode %d (%s), delay %d\n", + pi->port, pi->mode, mode_string[pi->mode], pi->delay); } static struct pi_protocol on20 = { diff --git a/drivers/ata/pata_parport/on26.c b/drivers/ata/pata_parport/on26.c index dc47a54b121f..5da317b394c1 100644 --- a/drivers/ata/pata_parport/on26.c +++ b/drivers/ata/pata_parport/on26.c @@ -1,11 +1,10 @@ -/* - on26.c (c) 1997-8 Grant R. Guenther <grant@torque.net> - Under the terms of the GNU General Public License. - - on26.c is a low-level protocol driver for the - OnSpec 90c26 parallel to IDE adapter chip. - -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1997-1998 Grant R. Guenther <grant@torque.net> + * + * on26.c is a low-level protocol driver for the + * OnSpec 90c26 parallel to IDE adapter chip. + */ #include <linux/module.h> #include <linux/init.h> @@ -16,260 +15,281 @@ #include <asm/io.h> #include "pata_parport.h" -/* mode codes: 0 nybble reads, 8-bit writes - 1 8-bit reads and writes - 2 8-bit EPP mode - 3 EPP-16 - 4 EPP-32 -*/ +/* + * mode codes: 0 nybble reads, 8-bit writes + * 1 8-bit reads and writes + * 2 8-bit EPP mode + * 3 EPP-16 + * 4 EPP-32 + */ -#define j44(a,b) (((a>>4)&0x0f)|(b&0xf0)) +#define j44(a, b) (((a >> 4) & 0x0f) | (b & 0xf0)) -#define P1 w2(5);w2(0xd);w2(5);w2(0xd);w2(5);w2(4); -#define P2 w2(5);w2(7);w2(5);w2(4); +#define P1 \ + do { \ + w2(5); w2(0xd); w2(5); w2(0xd); w2(5); w2(4); \ + } while (0) -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set -*/ - -static int on26_read_regr(struct pi_adapter *pi, int cont, int regr) +#define P2 \ + do { \ + w2(5); w2(7); w2(5); w2(4); \ + } while (0) -{ int a, b, r; +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + */ - r = (regr<<2) + 1 + cont; +static int on26_read_regr(struct pi_adapter *pi, int cont, int regr) +{ + int a, b, r; - switch (pi->mode) { + r = (regr << 2) + 1 + cont; - case 0: w0(1); P1; w0(r); P2; w0(0); P1; + switch (pi->mode) { + case 0: + w0(1); P1; w0(r); P2; w0(0); P1; w2(6); a = r1(); w2(4); w2(6); b = r1(); w2(4); w2(6); w2(4); w2(6); w2(4); - return j44(a,b); - - case 1: w0(1); P1; w0(r); P2; w0(0); P1; + return j44(a, b); + case 1: + w0(1); P1; w0(r); P2; w0(0); P1; w2(0x26); a = r0(); w2(4); w2(0x26); w2(4); - return a; - + return a; case 2: case 3: - case 4: w3(1); w3(1); w2(5); w4(r); w2(4); + case 4: + w3(1); w3(1); w2(5); w4(r); w2(4); w3(0); w3(0); w2(0x24); a = r4(); w2(4); w2(0x24); (void)r4(); w2(4); - return a; + return a; + } - } - return -1; -} + return -1; +} static void on26_write_regr(struct pi_adapter *pi, int cont, int regr, int val) +{ + int r = (regr << 2) + 1 + cont; -{ int r; - - r = (regr<<2) + 1 + cont; - - switch (pi->mode) { - - case 0: - case 1: w0(1); P1; w0(r); P2; w0(0); P1; + switch (pi->mode) { + case 0: + case 1: + w0(1); P1; w0(r); P2; w0(0); P1; w0(val); P2; w0(val); P2; break; - case 2: case 3: - case 4: w3(1); w3(1); w2(5); w4(r); w2(4); - w3(0); w3(0); + case 4: + w3(1); w3(1); w2(5); w4(r); w2(4); + w3(0); w3(0); w2(5); w4(val); w2(4); w2(5); w4(val); w2(4); - break; - } + break; + } } -#define CCP(x) w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff);\ - w0(0x87);w0(0x78);w0(x);w2(4);w2(5);w2(4);w0(0xff); +#define CCP(x) \ + do { \ + w0(0xfe); w0(0xaa); w0(0x55); w0(0); \ + w0(0xff); w0(0x87); w0(0x78); w0(x); \ + w2(4); w2(5); w2(4); w0(0xff); \ + } while (0) static void on26_connect(struct pi_adapter *pi) - -{ int x; +{ + int x; pi->saved_r0 = r0(); - pi->saved_r2 = r2(); + pi->saved_r2 = r2(); - CCP(0x20); - x = 8; if (pi->mode) x = 9; + CCP(0x20); + if (pi->mode) + x = 9; + else + x = 8; w0(2); P1; w0(8); P2; w0(2); P1; w0(x); P2; } static void on26_disconnect(struct pi_adapter *pi) - -{ if (pi->mode >= 2) { w3(4); w3(4); w3(4); w3(4); } - else { w0(4); P1; w0(4); P1; } +{ + if (pi->mode >= 2) { + w3(4); w3(4); w3(4); w3(4); + } else { + w0(4); P1; w0(4); P1; + } CCP(0x30); - w0(pi->saved_r0); - w2(pi->saved_r2); -} + w0(pi->saved_r0); + w2(pi->saved_r2); +} #define RESET_WAIT 200 -static int on26_test_port(struct pi_adapter *pi) /* hard reset */ +/* hard reset */ +static int on26_test_port(struct pi_adapter *pi) +{ + int i, m, d, x = 0, y = 0; -{ int i, m, d, x=0, y=0; - - pi->saved_r0 = r0(); - pi->saved_r2 = r2(); - - d = pi->delay; - m = pi->mode; - pi->delay = 5; - pi->mode = 0; - - w2(0xc); - - CCP(0x30); CCP(0); - - w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff); - i = ((r1() & 0xf0) << 4); w0(0x87); - i |= (r1() & 0xf0); w0(0x78); - w0(0x20);w2(4);w2(5); - i |= ((r1() & 0xf0) >> 4); - w2(4);w0(0xff); - - if (i == 0xb5f) { - - w0(2); P1; w0(0); P2; - w0(3); P1; w0(0); P2; - w0(2); P1; w0(8); P2; udelay(100); - w0(2); P1; w0(0xa); P2; udelay(100); - w0(2); P1; w0(8); P2; udelay(1000); - - on26_write_regr(pi,0,6,0xa0); - - for (i=0;i<RESET_WAIT;i++) { - on26_write_regr(pi,0,6,0xa0); - x = on26_read_regr(pi,0,7); - on26_write_regr(pi,0,6,0xb0); - y = on26_read_regr(pi,0,7); - if (!((x&0x80)||(y&0x80))) break; - mdelay(100); - } - - if (i == RESET_WAIT) - dev_err(&pi->dev, "on26: Device reset failed (%x,%x)\n", x, y); - - w0(4); P1; w0(4); P1; - } + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); + + d = pi->delay; + m = pi->mode; + pi->delay = 5; + pi->mode = 0; + + w2(0xc); + + CCP(0x30); CCP(0); + + w0(0xfe); w0(0xaa); w0(0x55); w0(0); w0(0xff); + i = ((r1() & 0xf0) << 4); w0(0x87); + i |= (r1() & 0xf0); w0(0x78); + w0(0x20); w2(4); w2(5); + i |= ((r1() & 0xf0) >> 4); + w2(4); w0(0xff); + + if (i == 0xb5f) { + w0(2); P1; w0(0); P2; + w0(3); P1; w0(0); P2; + w0(2); P1; w0(8); P2; udelay(100); + w0(2); P1; w0(0xa); P2; udelay(100); + w0(2); P1; w0(8); P2; udelay(1000); + + on26_write_regr(pi, 0, 6, 0xa0); + + for (i = 0; i < RESET_WAIT; i++) { + on26_write_regr(pi, 0, 6, 0xa0); + x = on26_read_regr(pi, 0, 7); + on26_write_regr(pi, 0, 6, 0xb0); + y = on26_read_regr(pi, 0, 7); + if (!((x & 0x80) || (y & 0x80))) + break; + mdelay(100); + } + + if (i == RESET_WAIT) + dev_err(&pi->dev, + "on26: Device reset failed (%x,%x)\n", x, y); + + w0(4); P1; w0(4); P1; + } - CCP(0x30); + CCP(0x30); - pi->delay = d; - pi->mode = m; - w0(pi->saved_r0); - w2(pi->saved_r2); + pi->delay = d; + pi->mode = m; + w0(pi->saved_r0); + w2(pi->saved_r2); - return 5; + return 5; } - static void on26_read_block(struct pi_adapter *pi, char *buf, int count) +{ + int k, a, b; -{ int k, a, b; - - switch (pi->mode) { - - case 0: w0(1); P1; w0(1); P2; w0(2); P1; w0(0x18); P2; w0(0); P1; + switch (pi->mode) { + case 0: + w0(1); P1; w0(1); P2; w0(2); P1; w0(0x18); P2; w0(0); P1; udelay(10); - for (k=0;k<count;k++) { - w2(6); a = r1(); - w2(4); b = r1(); - buf[k] = j44(a,b); - } - w0(2); P1; w0(8); P2; - break; - - case 1: w0(1); P1; w0(1); P2; w0(2); P1; w0(0x19); P2; w0(0); P1; + for (k = 0; k < count; k++) { + w2(6); a = r1(); + w2(4); b = r1(); + buf[k] = j44(a, b); + } + w0(2); P1; w0(8); P2; + break; + case 1: + w0(1); P1; w0(1); P2; w0(2); P1; w0(0x19); P2; w0(0); P1; + udelay(10); + for (k = 0; k < count / 2; k++) { + w2(0x26); buf[2 * k] = r0(); + w2(0x24); buf[2 * k + 1] = r0(); + } + w0(2); P1; w0(9); P2; + break; + case 2: + w3(1); w3(1); w2(5); w4(1); w2(4); + w3(0); w3(0); w2(0x24); + udelay(10); + for (k = 0; k < count; k++) + buf[k] = r4(); + w2(4); + break; + case 3: + w3(1); w3(1); w2(5); w4(1); w2(4); + w3(0); w3(0); w2(0x24); udelay(10); - for (k=0;k<count/2;k++) { - w2(0x26); buf[2*k] = r0(); - w2(0x24); buf[2*k+1] = r0(); - } - w0(2); P1; w0(9); P2; - break; - - case 2: w3(1); w3(1); w2(5); w4(1); w2(4); + for (k = 0; k < count / 2; k++) + ((u16 *)buf)[k] = r4w(); + w2(4); + break; + case 4: + w3(1); w3(1); w2(5); w4(1); w2(4); w3(0); w3(0); w2(0x24); udelay(10); - for (k=0;k<count;k++) buf[k] = r4(); - w2(4); - break; - - case 3: w3(1); w3(1); w2(5); w4(1); w2(4); - w3(0); w3(0); w2(0x24); - udelay(10); - for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w(); - w2(4); - break; - - case 4: w3(1); w3(1); w2(5); w4(1); w2(4); - w3(0); w3(0); w2(0x24); - udelay(10); - for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l(); - w2(4); - break; - - } + for (k = 0; k < count / 4; k++) + ((u32 *)buf)[k] = r4l(); + w2(4); + break; + } } static void on26_write_block(struct pi_adapter *pi, char *buf, int count) - -{ int k; - - switch (pi->mode) { - - case 0: - case 1: w0(1); P1; w0(1); P2; - w0(2); P1; w0(0x18+pi->mode); P2; w0(0); P1; +{ + int k; + + switch (pi->mode) { + case 0: + case 1: + w0(1); P1; w0(1); P2; + w0(2); P1; w0(0x18 + pi->mode); P2; w0(0); P1; udelay(10); - for (k=0;k<count/2;k++) { - w2(5); w0(buf[2*k]); - w2(7); w0(buf[2*k+1]); - } - w2(5); w2(4); - w0(2); P1; w0(8+pi->mode); P2; - break; - - case 2: w3(1); w3(1); w2(5); w4(1); w2(4); + for (k = 0; k < count / 2; k++) { + w2(5); w0(buf[2 * k]); + w2(7); w0(buf[2 * k + 1]); + } + w2(5); w2(4); + w0(2); P1; w0(8 + pi->mode); P2; + break; + case 2: + w3(1); w3(1); w2(5); w4(1); w2(4); w3(0); w3(0); w2(0xc5); udelay(10); - for (k=0;k<count;k++) w4(buf[k]); + for (k = 0; k < count; k++) + w4(buf[k]); w2(0xc4); - break; - - case 3: w3(1); w3(1); w2(5); w4(1); w2(4); - w3(0); w3(0); w2(0xc5); - udelay(10); - for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]); - w2(0xc4); - break; - - case 4: w3(1); w3(1); w2(5); w4(1); w2(4); - w3(0); w3(0); w2(0xc5); - udelay(10); - for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]); - w2(0xc4); - break; - - } - + break; + case 3: + w3(1); w3(1); w2(5); w4(1); w2(4); + w3(0); w3(0); w2(0xc5); + udelay(10); + for (k = 0; k < count / 2; k++) + w4w(((u16 *)buf)[k]); + w2(0xc4); + break; + case 4: + w3(1); w3(1); w2(5); w4(1); w2(4); + w3(0); w3(0); w2(0xc5); + udelay(10); + for (k = 0; k < count / 4; k++) + w4l(((u32 *)buf)[k]); + w2(0xc4); + break; + } } static void on26_log_adapter(struct pi_adapter *pi) +{ + char *mode_string[5] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32" }; -{ char *mode_string[5] = {"4-bit","8-bit","EPP-8", - "EPP-16","EPP-32"}; - - dev_info(&pi->dev, "OnSpec 90c26 at 0x%x, mode %d (%s), delay %d\n", - pi->port, pi->mode, mode_string[pi->mode], pi->delay); + dev_info(&pi->dev, + "OnSpec 90c26 at 0x%x, mode %d (%s), delay %d\n", + pi->port, pi->mode, mode_string[pi->mode], pi->delay); } static struct pi_protocol on26 = { diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c index 87479bc893b2..232c3dad7ee8 100644 --- a/drivers/ata/pata_platform.c +++ b/drivers/ata/pata_platform.c @@ -223,7 +223,7 @@ static int pata_platform_probe(struct platform_device *pdev) static struct platform_driver pata_platform_driver = { .probe = pata_platform_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = DRV_NAME, }, diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c index 8237ece4a46f..d6b324d03e59 100644 --- a/drivers/ata/sata_highbank.c +++ b/drivers/ata/sata_highbank.c @@ -614,7 +614,7 @@ static SIMPLE_DEV_PM_OPS(ahci_highbank_pm_ops, ahci_highbank_suspend, ahci_highbank_resume); static struct platform_driver ahci_highbank_driver = { - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = "highbank-ahci", .of_match_table = ahci_of_match, diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c index c47c3fb434d5..598a872f6a08 100644 --- a/drivers/ata/sata_svw.c +++ b/drivers/ata/sata_svw.c @@ -32,6 +32,7 @@ #include <scsi/scsi.h> #include <linux/libata.h> #include <linux/of.h> +#include <linux/of_address.h> #define DRV_NAME "sata_svw" #define DRV_VERSION "2.3" @@ -319,10 +320,11 @@ static int k2_sata_show_info(struct seq_file *m, struct Scsi_Host *shost) /* Match it to a port node */ index = (ap == ap->host->ports[0]) ? 0 : 1; for (np = np->child; np != NULL; np = np->sibling) { - const u32 *reg = of_get_property(np, "reg", NULL); - if (!reg) + u64 reg; + + if (of_property_read_reg(np, 0, ®, NULL)) continue; - if (index == *reg) { + if (index == reg) { seq_printf(m, "devspec: %pOF\n", np); break; } diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 4fdf07ae3c54..e0b3786ca51b 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -335,9 +335,20 @@ config HW_RANDOM_HISI If unsure, say Y. +config HW_RANDOM_HISTB + tristate "Hisilicon STB Random Number Generator support" + depends on ARCH_HISI || COMPILE_TEST + default ARCH_HISI + help + This driver provides kernel-side support for the Random Number + Generator hardware found on Hisilicon Hi37xx SoC. + + To compile this driver as a module, choose M here: the + module will be called histb-rng. + config HW_RANDOM_ST tristate "ST Microelectronics HW Random Number Generator support" - depends on HW_RANDOM && ARCH_STI + depends on HW_RANDOM && (ARCH_STI || COMPILE_TEST) help This driver provides kernel-side support for the Random Number Generator hardware found on STi series of SoCs. @@ -400,9 +411,9 @@ config HW_RANDOM_POLARFIRE_SOC config HW_RANDOM_MESON tristate "Amlogic Meson Random Number Generator support" - depends on HW_RANDOM depends on ARCH_MESON || COMPILE_TEST - default y + depends on HAS_IOMEM && OF + default HW_RANDOM if ARCH_MESON help This driver provides kernel-side support for the Random Number Generator hardware found on Amlogic Meson SoCs. @@ -427,9 +438,9 @@ config HW_RANDOM_CAVIUM config HW_RANDOM_MTK tristate "Mediatek Random Number Generator support" - depends on HW_RANDOM depends on ARCH_MEDIATEK || COMPILE_TEST - default y + depends on HAS_IOMEM && OF + default HW_RANDOM if ARCH_MEDIATEK help This driver provides kernel-side support for the Random Number Generator hardware found on Mediatek SoCs. @@ -456,7 +467,8 @@ config HW_RANDOM_S390 config HW_RANDOM_EXYNOS tristate "Samsung Exynos True Random Number Generator support" depends on ARCH_EXYNOS || COMPILE_TEST - default HW_RANDOM + depends on HAS_IOMEM + default HW_RANDOM if ARCH_EXYNOS help This driver provides support for the True Random Number Generator available in Exynos SoCs. @@ -483,7 +495,8 @@ config HW_RANDOM_OPTEE config HW_RANDOM_NPCM tristate "NPCM Random Number Generator support" depends on ARCH_NPCM || COMPILE_TEST - default HW_RANDOM + depends on HAS_IOMEM + default HW_RANDOM if ARCH_NPCM help This driver provides support for the Random Number Generator hardware available in Nuvoton NPCM SoCs. diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index 09bde4a0f971..32549a1186dc 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o obj-$(CONFIG_HW_RANDOM_HISI) += hisi-rng.o +obj-$(CONFIG_HW_RANDOM_HISTB) += histb-rng.o obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o obj-$(CONFIG_HW_RANDOM_ST) += st-rng.o diff --git a/drivers/char/hw_random/cn10k-rng.c b/drivers/char/hw_random/cn10k-rng.c index c1193f85982c..0cd7e1a8e499 100644 --- a/drivers/char/hw_random/cn10k-rng.c +++ b/drivers/char/hw_random/cn10k-rng.c @@ -23,14 +23,49 @@ #define RNM_PF_RANDOM 0x400 #define RNM_TRNG_RESULT 0x408 +/* Extended TRNG Read and Status Registers */ +#define RNM_PF_TRNG_DAT 0x1000 +#define RNM_PF_TRNG_RES 0x1008 + struct cn10k_rng { void __iomem *reg_base; struct hwrng ops; struct pci_dev *pdev; + /* Octeon CN10K-A A0/A1, CNF10K-A A0/A1 and CNF10K-B A0/B0 + * does not support extended TRNG registers + */ + bool extended_trng_regs; }; #define PLAT_OCTEONTX_RESET_RNG_EBG_HEALTH_STATE 0xc2000b0f +#define PCI_SUBSYS_DEVID_CN10K_A_RNG 0xB900 +#define PCI_SUBSYS_DEVID_CNF10K_A_RNG 0xBA00 +#define PCI_SUBSYS_DEVID_CNF10K_B_RNG 0xBC00 + +static bool cn10k_is_extended_trng_regs_supported(struct pci_dev *pdev) +{ + /* CN10K-A A0/A1 */ + if ((pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_RNG) && + (!pdev->revision || (pdev->revision & 0xff) == 0x50 || + (pdev->revision & 0xff) == 0x51)) + return false; + + /* CNF10K-A A0 */ + if ((pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_RNG) && + (!pdev->revision || (pdev->revision & 0xff) == 0x60 || + (pdev->revision & 0xff) == 0x61)) + return false; + + /* CNF10K-B A0/B0 */ + if ((pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_B_RNG) && + (!pdev->revision || (pdev->revision & 0xff) == 0x70 || + (pdev->revision & 0xff) == 0x74)) + return false; + + return true; +} + static unsigned long reset_rng_health_state(struct cn10k_rng *rng) { struct arm_smccc_res res; @@ -63,9 +98,23 @@ static int check_rng_health(struct cn10k_rng *rng) return 0; } -static void cn10k_read_trng(struct cn10k_rng *rng, u64 *value) +/* Returns true when valid data available otherwise return false */ +static bool cn10k_read_trng(struct cn10k_rng *rng, u64 *value) { + u16 retry_count = 0; u64 upper, lower; + u64 status; + + if (rng->extended_trng_regs) { + do { + *value = readq(rng->reg_base + RNM_PF_TRNG_DAT); + if (*value) + return true; + status = readq(rng->reg_base + RNM_PF_TRNG_RES); + if (!status && (retry_count++ > 0x1000)) + return false; + } while (!status); + } *value = readq(rng->reg_base + RNM_PF_RANDOM); @@ -82,6 +131,7 @@ static void cn10k_read_trng(struct cn10k_rng *rng, u64 *value) *value = (upper & 0xFFFFFFFF00000000) | (lower & 0xFFFFFFFF); } + return true; } static int cn10k_rng_read(struct hwrng *hwrng, void *data, @@ -100,7 +150,8 @@ static int cn10k_rng_read(struct hwrng *hwrng, void *data, size = max; while (size >= 8) { - cn10k_read_trng(rng, &value); + if (!cn10k_read_trng(rng, &value)) + goto out; *((u64 *)pos) = value; size -= 8; @@ -108,7 +159,8 @@ static int cn10k_rng_read(struct hwrng *hwrng, void *data, } if (size > 0) { - cn10k_read_trng(rng, &value); + if (!cn10k_read_trng(rng, &value)) + goto out; while (size > 0) { *pos = (u8)value; @@ -118,6 +170,7 @@ static int cn10k_rng_read(struct hwrng *hwrng, void *data, } } +out: return max - size; } @@ -144,9 +197,11 @@ static int cn10k_rng_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (!rng->ops.name) return -ENOMEM; - rng->ops.read = cn10k_rng_read; + rng->ops.read = cn10k_rng_read; rng->ops.priv = (unsigned long)rng; + rng->extended_trng_regs = cn10k_is_extended_trng_regs_supported(pdev); + reset_rng_health_state(rng); err = devm_hwrng_register(&pdev->dev, &rng->ops); diff --git a/drivers/crypto/hisilicon/trng/trng-stb.c b/drivers/char/hw_random/histb-rng.c index 29200a7d3d81..f652e1135e4b 100644 --- a/drivers/crypto/hisilicon/trng/trng-stb.c +++ b/drivers/char/hw_random/histb-rng.c @@ -1,31 +1,27 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT /* - * Device driver for True RNG in HiSTB SoCs - * * Copyright (c) 2023 David Yang */ -#include <crypto/internal/rng.h> -#include <linux/device.h> #include <linux/err.h> #include <linux/hw_random.h> #include <linux/io.h> #include <linux/iopoll.h> #include <linux/kernel.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/mutex.h> -#include <linux/of_device.h> +#include <linux/platform_device.h> -#define HISTB_TRNG_CTRL 0x0 +#define RNG_CTRL 0x0 #define RNG_SOURCE GENMASK(1, 0) #define DROP_ENABLE BIT(5) #define POST_PROCESS_ENABLE BIT(7) #define POST_PROCESS_DEPTH GENMASK(15, 8) -#define HISTB_TRNG_NUMBER 0x4 -#define HISTB_TRNG_STAT 0x8 +#define RNG_NUMBER 0x4 +#define RNG_STAT 0x8 #define DATA_COUNT GENMASK(2, 0) /* max 4 */ -struct histb_trng_priv { +struct histb_rng_priv { struct hwrng rng; void __iomem *base; }; @@ -35,19 +31,19 @@ struct histb_trng_priv { * depth = 1 -> ~1ms * depth = 255 -> ~16ms */ -static int histb_trng_wait(void __iomem *base) +static int histb_rng_wait(void __iomem *base) { u32 val; - return readl_relaxed_poll_timeout(base + HISTB_TRNG_STAT, val, + return readl_relaxed_poll_timeout(base + RNG_STAT, val, val & DATA_COUNT, 1000, 30 * 1000); } -static void histb_trng_init(void __iomem *base, unsigned int depth) +static void histb_rng_init(void __iomem *base, unsigned int depth) { u32 val; - val = readl_relaxed(base + HISTB_TRNG_CTRL); + val = readl_relaxed(base + RNG_CTRL); val &= ~RNG_SOURCE; val |= 2; @@ -58,72 +54,72 @@ static void histb_trng_init(void __iomem *base, unsigned int depth) val |= POST_PROCESS_ENABLE; val |= DROP_ENABLE; - writel_relaxed(val, base + HISTB_TRNG_CTRL); + writel_relaxed(val, base + RNG_CTRL); } -static int histb_trng_read(struct hwrng *rng, void *data, size_t max, bool wait) +static int histb_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) { - struct histb_trng_priv *priv = container_of(rng, typeof(*priv), rng); + struct histb_rng_priv *priv = container_of(rng, typeof(*priv), rng); void __iomem *base = priv->base; for (int i = 0; i < max; i += sizeof(u32)) { - if (!(readl_relaxed(base + HISTB_TRNG_STAT) & DATA_COUNT)) { + if (!(readl_relaxed(base + RNG_STAT) & DATA_COUNT)) { if (!wait) return i; - if (histb_trng_wait(base)) { + if (histb_rng_wait(base)) { pr_err("failed to generate random number, generated %d\n", i); return i ? i : -ETIMEDOUT; } } - *(u32 *) (data + i) = readl_relaxed(base + HISTB_TRNG_NUMBER); + *(u32 *) (data + i) = readl_relaxed(base + RNG_NUMBER); } return max; } -static unsigned int histb_trng_get_depth(void __iomem *base) +static unsigned int histb_rng_get_depth(void __iomem *base) { - return (readl_relaxed(base + HISTB_TRNG_CTRL) & POST_PROCESS_DEPTH) >> 8; + return (readl_relaxed(base + RNG_CTRL) & POST_PROCESS_DEPTH) >> 8; } static ssize_t depth_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct histb_trng_priv *priv = dev_get_drvdata(dev); + struct histb_rng_priv *priv = dev_get_drvdata(dev); void __iomem *base = priv->base; - return sprintf(buf, "%d\n", histb_trng_get_depth(base)); + return sprintf(buf, "%d\n", histb_rng_get_depth(base)); } static ssize_t depth_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct histb_trng_priv *priv = dev_get_drvdata(dev); + struct histb_rng_priv *priv = dev_get_drvdata(dev); void __iomem *base = priv->base; unsigned int depth; if (kstrtouint(buf, 0, &depth)) return -ERANGE; - histb_trng_init(base, depth); + histb_rng_init(base, depth); return count; } static DEVICE_ATTR_RW(depth); -static struct attribute *histb_trng_attrs[] = { +static struct attribute *histb_rng_attrs[] = { &dev_attr_depth.attr, NULL, }; -ATTRIBUTE_GROUPS(histb_trng); +ATTRIBUTE_GROUPS(histb_rng); -static int histb_trng_probe(struct platform_device *pdev) +static int histb_rng_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct histb_trng_priv *priv; + struct histb_rng_priv *priv; void __iomem *base; int ret; @@ -133,17 +129,17 @@ static int histb_trng_probe(struct platform_device *pdev) base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) - return -ENOMEM; + return PTR_ERR(base); - histb_trng_init(base, 144); - if (histb_trng_wait(base)) { + histb_rng_init(base, 144); + if (histb_rng_wait(base)) { dev_err(dev, "cannot bring up device\n"); return -ENODEV; } priv->base = base; priv->rng.name = pdev->name; - priv->rng.read = histb_trng_read; + priv->rng.read = histb_rng_read; ret = devm_hwrng_register(dev, &priv->rng); if (ret) { dev_err(dev, "failed to register hwrng: %d\n", ret); @@ -155,22 +151,23 @@ static int histb_trng_probe(struct platform_device *pdev) return 0; } -static const struct of_device_id histb_trng_of_match[] = { - { .compatible = "hisilicon,histb-trng", }, +static const struct of_device_id histb_rng_of_match[] = { + { .compatible = "hisilicon,histb-rng", }, { } }; +MODULE_DEVICE_TABLE(of, histb_rng_of_match); -static struct platform_driver histb_trng_driver = { - .probe = histb_trng_probe, +static struct platform_driver histb_rng_driver = { + .probe = histb_rng_probe, .driver = { - .name = "histb-trng", - .of_match_table = histb_trng_of_match, - .dev_groups = histb_trng_groups, + .name = "histb-rng", + .of_match_table = histb_rng_of_match, + .dev_groups = histb_rng_groups, }, }; -module_platform_driver(histb_trng_driver); +module_platform_driver(histb_rng_driver); -MODULE_DESCRIPTION("HiSTB True RNG"); +MODULE_DESCRIPTION("Hisilicon STB random number generator driver"); MODULE_LICENSE("Dual MIT/GPL"); MODULE_AUTHOR("David Yang <mmyangfl@gmail.com>"); diff --git a/drivers/char/hw_random/imx-rngc.c b/drivers/char/hw_random/imx-rngc.c index a1c24148ed31..bf07f17f78c8 100644 --- a/drivers/char/hw_random/imx-rngc.c +++ b/drivers/char/hw_random/imx-rngc.c @@ -17,6 +17,7 @@ #include <linux/hw_random.h> #include <linux/completion.h> #include <linux/io.h> +#include <linux/bitfield.h> #define RNGC_VER_ID 0x0000 #define RNGC_COMMAND 0x0004 @@ -26,7 +27,7 @@ #define RNGC_FIFO 0x0014 /* the fields in the ver id register */ -#define RNGC_TYPE_SHIFT 28 +#define RNG_TYPE GENMASK(31, 28) #define RNGC_VER_MAJ_SHIFT 8 /* the rng_type field */ @@ -34,20 +35,19 @@ #define RNGC_TYPE_RNGC 0x2 -#define RNGC_CMD_CLR_ERR 0x00000020 -#define RNGC_CMD_CLR_INT 0x00000010 -#define RNGC_CMD_SEED 0x00000002 -#define RNGC_CMD_SELF_TEST 0x00000001 +#define RNGC_CMD_CLR_ERR BIT(5) +#define RNGC_CMD_CLR_INT BIT(4) +#define RNGC_CMD_SEED BIT(1) +#define RNGC_CMD_SELF_TEST BIT(0) -#define RNGC_CTRL_MASK_ERROR 0x00000040 -#define RNGC_CTRL_MASK_DONE 0x00000020 -#define RNGC_CTRL_AUTO_SEED 0x00000010 +#define RNGC_CTRL_MASK_ERROR BIT(6) +#define RNGC_CTRL_MASK_DONE BIT(5) +#define RNGC_CTRL_AUTO_SEED BIT(4) -#define RNGC_STATUS_ERROR 0x00010000 -#define RNGC_STATUS_FIFO_LEVEL_MASK 0x00000f00 -#define RNGC_STATUS_FIFO_LEVEL_SHIFT 8 -#define RNGC_STATUS_SEED_DONE 0x00000020 -#define RNGC_STATUS_ST_DONE 0x00000010 +#define RNGC_STATUS_ERROR BIT(16) +#define RNGC_STATUS_FIFO_LEVEL_MASK GENMASK(11, 8) +#define RNGC_STATUS_SEED_DONE BIT(5) +#define RNGC_STATUS_ST_DONE BIT(4) #define RNGC_ERROR_STATUS_STAT_ERR 0x00000008 @@ -110,7 +110,7 @@ static int imx_rngc_self_test(struct imx_rngc *rngc) cmd = readl(rngc->base + RNGC_COMMAND); writel(cmd | RNGC_CMD_SELF_TEST, rngc->base + RNGC_COMMAND); - ret = wait_for_completion_timeout(&rngc->rng_op_done, RNGC_TIMEOUT); + ret = wait_for_completion_timeout(&rngc->rng_op_done, msecs_to_jiffies(RNGC_TIMEOUT)); imx_rngc_irq_mask_clear(rngc); if (!ret) return -ETIMEDOUT; @@ -122,7 +122,6 @@ static int imx_rngc_read(struct hwrng *rng, void *data, size_t max, bool wait) { struct imx_rngc *rngc = container_of(rng, struct imx_rngc, rng); unsigned int status; - unsigned int level; int retval = 0; while (max >= sizeof(u32)) { @@ -132,11 +131,7 @@ static int imx_rngc_read(struct hwrng *rng, void *data, size_t max, bool wait) if (status & RNGC_STATUS_ERROR) break; - /* how many random numbers are in FIFO? [0-16] */ - level = (status & RNGC_STATUS_FIFO_LEVEL_MASK) >> - RNGC_STATUS_FIFO_LEVEL_SHIFT; - - if (level) { + if (status & RNGC_STATUS_FIFO_LEVEL_MASK) { /* retrieve a random number from FIFO */ *(u32 *)data = readl(rngc->base + RNGC_FIFO); @@ -187,9 +182,7 @@ static int imx_rngc_init(struct hwrng *rng) cmd = readl(rngc->base + RNGC_COMMAND); writel(cmd | RNGC_CMD_SEED, rngc->base + RNGC_COMMAND); - ret = wait_for_completion_timeout(&rngc->rng_op_done, - RNGC_TIMEOUT); - + ret = wait_for_completion_timeout(&rngc->rng_op_done, msecs_to_jiffies(RNGC_TIMEOUT)); if (!ret) { ret = -ETIMEDOUT; goto err; @@ -229,7 +222,7 @@ static void imx_rngc_cleanup(struct hwrng *rng) imx_rngc_irq_mask_clear(rngc); } -static int imx_rngc_probe(struct platform_device *pdev) +static int __init imx_rngc_probe(struct platform_device *pdev) { struct imx_rngc *rngc; int ret; @@ -256,7 +249,7 @@ static int imx_rngc_probe(struct platform_device *pdev) return irq; ver_id = readl(rngc->base + RNGC_VER_ID); - rng_type = ver_id >> RNGC_TYPE_SHIFT; + rng_type = FIELD_GET(RNG_TYPE, ver_id); /* * This driver supports only RNGC and RNGB. (There's a different * driver for RNGA.) @@ -305,7 +298,7 @@ static int imx_rngc_probe(struct platform_device *pdev) return 0; } -static int __maybe_unused imx_rngc_suspend(struct device *dev) +static int imx_rngc_suspend(struct device *dev) { struct imx_rngc *rngc = dev_get_drvdata(dev); @@ -314,7 +307,7 @@ static int __maybe_unused imx_rngc_suspend(struct device *dev) return 0; } -static int __maybe_unused imx_rngc_resume(struct device *dev) +static int imx_rngc_resume(struct device *dev) { struct imx_rngc *rngc = dev_get_drvdata(dev); @@ -323,10 +316,10 @@ static int __maybe_unused imx_rngc_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(imx_rngc_pm_ops, imx_rngc_suspend, imx_rngc_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(imx_rngc_pm_ops, imx_rngc_suspend, imx_rngc_resume); static const struct of_device_id imx_rngc_dt_ids[] = { - { .compatible = "fsl,imx25-rngb", .data = NULL, }, + { .compatible = "fsl,imx25-rngb" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, imx_rngc_dt_ids); @@ -334,7 +327,7 @@ MODULE_DEVICE_TABLE(of, imx_rngc_dt_ids); static struct platform_driver imx_rngc_driver = { .driver = { .name = KBUILD_MODNAME, - .pm = &imx_rngc_pm_ops, + .pm = pm_sleep_ptr(&imx_rngc_pm_ops), .of_match_table = imx_rngc_dt_ids, }, }; diff --git a/drivers/char/hw_random/st-rng.c b/drivers/char/hw_random/st-rng.c index 15ba1e6fae4d..6e9dfac9fc9f 100644 --- a/drivers/char/hw_random/st-rng.c +++ b/drivers/char/hw_random/st-rng.c @@ -42,7 +42,6 @@ struct st_rng_data { void __iomem *base; - struct clk *clk; struct hwrng ops; }; @@ -85,26 +84,18 @@ static int st_rng_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); - clk = devm_clk_get(&pdev->dev, NULL); + clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(clk)) return PTR_ERR(clk); - ret = clk_prepare_enable(clk); - if (ret) - return ret; - ddata->ops.priv = (unsigned long)ddata; ddata->ops.read = st_rng_read; ddata->ops.name = pdev->name; ddata->base = base; - ddata->clk = clk; - - dev_set_drvdata(&pdev->dev, ddata); ret = devm_hwrng_register(&pdev->dev, &ddata->ops); if (ret) { dev_err(&pdev->dev, "Failed to register HW RNG\n"); - clk_disable_unprepare(clk); return ret; } @@ -113,15 +104,6 @@ static int st_rng_probe(struct platform_device *pdev) return 0; } -static int st_rng_remove(struct platform_device *pdev) -{ - struct st_rng_data *ddata = dev_get_drvdata(&pdev->dev); - - clk_disable_unprepare(ddata->clk); - - return 0; -} - static const struct of_device_id st_rng_match[] __maybe_unused = { { .compatible = "st,rng" }, {}, @@ -134,7 +116,6 @@ static struct platform_driver st_rng_driver = { .of_match_table = of_match_ptr(st_rng_match), }, .probe = st_rng_probe, - .remove = st_rng_remove }; module_platform_driver(st_rng_driver); diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index f7690e0f92ed..e41a84e6b4b5 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c @@ -4,6 +4,7 @@ * Copyright (C) 2007, 2008 Rusty Russell IBM Corporation */ +#include <asm/barrier.h> #include <linux/err.h> #include <linux/hw_random.h> #include <linux/scatterlist.h> @@ -37,13 +38,13 @@ struct virtrng_info { static void random_recv_done(struct virtqueue *vq) { struct virtrng_info *vi = vq->vdev->priv; + unsigned int len; /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */ - if (!virtqueue_get_buf(vi->vq, &vi->data_avail)) + if (!virtqueue_get_buf(vi->vq, &len)) return; - vi->data_idx = 0; - + smp_store_release(&vi->data_avail, len); complete(&vi->have_data); } @@ -52,7 +53,6 @@ static void request_entropy(struct virtrng_info *vi) struct scatterlist sg; reinit_completion(&vi->have_data); - vi->data_avail = 0; vi->data_idx = 0; sg_init_one(&sg, vi->data, sizeof(vi->data)); @@ -88,7 +88,7 @@ static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) read = 0; /* copy available data */ - if (vi->data_avail) { + if (smp_load_acquire(&vi->data_avail)) { chunk = copy_data(vi, buf, size); size -= chunk; read += chunk; diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c index 5f0f10c7e222..da3071b387eb 100644 --- a/drivers/clocksource/timer-riscv.c +++ b/drivers/clocksource/timer-riscv.c @@ -10,6 +10,7 @@ #define pr_fmt(fmt) "riscv-timer: " fmt +#include <linux/acpi.h> #include <linux/clocksource.h> #include <linux/clockchips.h> #include <linux/cpu.h> @@ -124,61 +125,28 @@ static irqreturn_t riscv_timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static int __init riscv_timer_init_dt(struct device_node *n) +static int __init riscv_timer_init_common(void) { - int cpuid, error; - unsigned long hartid; - struct device_node *child; + int error; struct irq_domain *domain; + struct fwnode_handle *intc_fwnode = riscv_get_intc_hwnode(); - error = riscv_of_processor_hartid(n, &hartid); - if (error < 0) { - pr_warn("Not valid hartid for node [%pOF] error = [%lu]\n", - n, hartid); - return error; - } - - cpuid = riscv_hartid_to_cpuid(hartid); - if (cpuid < 0) { - pr_warn("Invalid cpuid for hartid [%lu]\n", hartid); - return cpuid; - } - - if (cpuid != smp_processor_id()) - return 0; - - child = of_find_compatible_node(NULL, NULL, "riscv,timer"); - if (child) { - riscv_timer_cannot_wake_cpu = of_property_read_bool(child, - "riscv,timer-cannot-wake-cpu"); - of_node_put(child); - } - - domain = NULL; - child = of_get_compatible_child(n, "riscv,cpu-intc"); - if (!child) { - pr_err("Failed to find INTC node [%pOF]\n", n); - return -ENODEV; - } - domain = irq_find_host(child); - of_node_put(child); + domain = irq_find_matching_fwnode(intc_fwnode, DOMAIN_BUS_ANY); if (!domain) { - pr_err("Failed to find IRQ domain for node [%pOF]\n", n); + pr_err("Failed to find irq_domain for INTC node [%pfwP]\n", + intc_fwnode); return -ENODEV; } riscv_clock_event_irq = irq_create_mapping(domain, RV_IRQ_TIMER); if (!riscv_clock_event_irq) { - pr_err("Failed to map timer interrupt for node [%pOF]\n", n); + pr_err("Failed to map timer interrupt for node [%pfwP]\n", intc_fwnode); return -ENODEV; } - pr_info("%s: Registering clocksource cpuid [%d] hartid [%lu]\n", - __func__, cpuid, hartid); error = clocksource_register_hz(&riscv_clocksource, riscv_timebase); if (error) { - pr_err("RISCV timer register failed [%d] for cpu = [%d]\n", - error, cpuid); + pr_err("RISCV timer registration failed [%d]\n", error); return error; } @@ -207,4 +175,46 @@ static int __init riscv_timer_init_dt(struct device_node *n) return error; } +static int __init riscv_timer_init_dt(struct device_node *n) +{ + int cpuid, error; + unsigned long hartid; + struct device_node *child; + + error = riscv_of_processor_hartid(n, &hartid); + if (error < 0) { + pr_warn("Invalid hartid for node [%pOF] error = [%lu]\n", + n, hartid); + return error; + } + + cpuid = riscv_hartid_to_cpuid(hartid); + if (cpuid < 0) { + pr_warn("Invalid cpuid for hartid [%lu]\n", hartid); + return cpuid; + } + + if (cpuid != smp_processor_id()) + return 0; + + child = of_find_compatible_node(NULL, NULL, "riscv,timer"); + if (child) { + riscv_timer_cannot_wake_cpu = of_property_read_bool(child, + "riscv,timer-cannot-wake-cpu"); + of_node_put(child); + } + + return riscv_timer_init_common(); +} + TIMER_OF_DECLARE(riscv_timer, "riscv", riscv_timer_init_dt); + +#ifdef CONFIG_ACPI +static int __init riscv_timer_acpi_init(struct acpi_table_header *table) +{ + return riscv_timer_init_common(); +} + +TIMER_ACPI_DECLARE(aclint_mtimer, ACPI_SIG_RHCT, riscv_timer_acpi_init); + +#endif diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 9c440cd0fed0..9f5b2d28bff5 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -807,5 +807,6 @@ config CRYPTO_DEV_SA2UL acceleration for cryptographic algorithms on these devices. source "drivers/crypto/aspeed/Kconfig" +source "drivers/crypto/starfive/Kconfig" endif # CRYPTO_HW diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 51d36701e785..d859d6a5f3a4 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -50,3 +50,4 @@ obj-y += xilinx/ obj-y += hisilicon/ obj-$(CONFIG_CRYPTO_DEV_AMLOGIC_GXL) += amlogic/ obj-y += intel/ +obj-y += starfive/ diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index aac64b555204..432beabd79e6 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -389,7 +389,7 @@ static struct i2c_driver atmel_ecc_driver = { .name = "atmel-ecc", .of_match_table = of_match_ptr(atmel_ecc_dt_ids), }, - .probe_new = atmel_ecc_probe, + .probe = atmel_ecc_probe, .remove = atmel_ecc_remove, .id_table = atmel_ecc_id, }; diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index 44a185a84760..c77f482d2a97 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -141,7 +141,7 @@ static const struct i2c_device_id atmel_sha204a_id[] = { MODULE_DEVICE_TABLE(i2c, atmel_sha204a_id); static struct i2c_driver atmel_sha204a_driver = { - .probe_new = atmel_sha204a_probe, + .probe = atmel_sha204a_probe, .remove = atmel_sha204a_remove, .id_table = atmel_sha204a_id, diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig index ec6a9e6ad4d2..c631f99e415f 100644 --- a/drivers/crypto/caam/Kconfig +++ b/drivers/crypto/caam/Kconfig @@ -162,6 +162,15 @@ config CRYPTO_DEV_FSL_CAAM_PRNG_API config CRYPTO_DEV_FSL_CAAM_BLOB_GEN bool +config CRYPTO_DEV_FSL_CAAM_RNG_TEST + bool "Test caam rng" + select CRYPTO_DEV_FSL_CAAM_RNG_API + help + Selecting this will enable a self-test to run for the + caam RNG. + This test is several minutes long and executes + just before the RNG is registered with the hw_random API. + endif # CRYPTO_DEV_FSL_CAAM_JR endif # CRYPTO_DEV_FSL_CAAM diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c index 50eb55da45c2..b3d14a7f4dd1 100644 --- a/drivers/crypto/caam/caamrng.c +++ b/drivers/crypto/caam/caamrng.c @@ -172,6 +172,50 @@ static void caam_cleanup(struct hwrng *rng) kfifo_free(&ctx->fifo); } +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST +static inline void test_len(struct hwrng *rng, size_t len, bool wait) +{ + u8 *buf; + int read_len; + struct caam_rng_ctx *ctx = to_caam_rng_ctx(rng); + struct device *dev = ctx->ctrldev; + + buf = kcalloc(CAAM_RNG_MAX_FIFO_STORE_SIZE, sizeof(u8), GFP_KERNEL); + + while (len > 0) { + read_len = rng->read(rng, buf, len, wait); + + if (read_len < 0 || (read_len == 0 && wait)) { + dev_err(dev, "RNG Read FAILED received %d bytes\n", + read_len); + kfree(buf); + return; + } + + print_hex_dump_debug("random bytes@: ", + DUMP_PREFIX_ADDRESS, 16, 4, + buf, read_len, 1); + + len = len - read_len; + } + + kfree(buf); +} + +static inline void test_mode_once(struct hwrng *rng, bool wait) +{ + test_len(rng, 32, wait); + test_len(rng, 64, wait); + test_len(rng, 128, wait); +} + +static void self_test(struct hwrng *rng) +{ + pr_info("Executing RNG SELF-TEST with wait\n"); + test_mode_once(rng, true); +} +#endif + static int caam_init(struct hwrng *rng) { struct caam_rng_ctx *ctx = to_caam_rng_ctx(rng); @@ -258,6 +302,10 @@ int caam_rng_init(struct device *ctrldev) return ret; } +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST + self_test(&ctx->rng); +#endif + devres_close_group(ctrldev, caam_rng_init); return 0; } diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c index bedcc2ab3a00..ff9ddbbca377 100644 --- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c @@ -79,6 +79,15 @@ static void build_deinstantiation_desc(u32 *desc, int handle) append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TYPE_HALT); } +static const struct of_device_id imx8m_machine_match[] = { + { .compatible = "fsl,imx8mm", }, + { .compatible = "fsl,imx8mn", }, + { .compatible = "fsl,imx8mp", }, + { .compatible = "fsl,imx8mq", }, + { .compatible = "fsl,imx8ulp", }, + { } +}; + /* * run_descriptor_deco0 - runs a descriptor on DECO0, under direct control of * the software (no JR/QI used). @@ -105,10 +114,7 @@ static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc, * Apparently on i.MX8M{Q,M,N,P} it doesn't matter if virt_en == 1 * and the following steps should be performed regardless */ - of_machine_is_compatible("fsl,imx8mq") || - of_machine_is_compatible("fsl,imx8mm") || - of_machine_is_compatible("fsl,imx8mn") || - of_machine_is_compatible("fsl,imx8mp")) { + of_match_node(imx8m_machine_match, of_root)) { clrsetbits_32(&ctrl->deco_rsr, 0, DECORSR_JR0); while (!(rd_reg32(&ctrl->deco_rsr) & DECORSR_VALID) && @@ -344,16 +350,15 @@ static int instantiate_rng(struct device *ctrldev, int state_handle_mask, /* * kick_trng - sets the various parameters for enabling the initialization * of the RNG4 block in CAAM - * @pdev - pointer to the platform device + * @dev - pointer to the controller device * @ent_delay - Defines the length (in system clocks) of each entropy sample. */ -static void kick_trng(struct platform_device *pdev, int ent_delay) +static void kick_trng(struct device *dev, int ent_delay) { - struct device *ctrldev = &pdev->dev; - struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev); + struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev); struct caam_ctrl __iomem *ctrl; struct rng4tst __iomem *r4tst; - u32 val; + u32 val, rtsdctl; ctrl = (struct caam_ctrl __iomem *)ctrlpriv->ctrl; r4tst = &ctrl->r4tst[0]; @@ -369,26 +374,38 @@ static void kick_trng(struct platform_device *pdev, int ent_delay) * Performance-wise, it does not make sense to * set the delay to a value that is lower * than the last one that worked (i.e. the state handles - * were instantiated properly. Thus, instead of wasting - * time trying to set the values controlling the sample - * frequency, the function simply returns. + * were instantiated properly). + */ + rtsdctl = rd_reg32(&r4tst->rtsdctl); + val = (rtsdctl & RTSDCTL_ENT_DLY_MASK) >> RTSDCTL_ENT_DLY_SHIFT; + if (ent_delay > val) { + val = ent_delay; + /* min. freq. count, equal to 1/4 of the entropy sample length */ + wr_reg32(&r4tst->rtfrqmin, val >> 2); + /* max. freq. count, equal to 16 times the entropy sample length */ + wr_reg32(&r4tst->rtfrqmax, val << 4); + } + + wr_reg32(&r4tst->rtsdctl, (val << RTSDCTL_ENT_DLY_SHIFT) | + RTSDCTL_SAMP_SIZE_VAL); + + /* + * To avoid reprogramming the self-test parameters over and over again, + * use RTSDCTL[SAMP_SIZE] as an indicator. */ - val = (rd_reg32(&r4tst->rtsdctl) & RTSDCTL_ENT_DLY_MASK) - >> RTSDCTL_ENT_DLY_SHIFT; - if (ent_delay <= val) - goto start_rng; - - val = rd_reg32(&r4tst->rtsdctl); - val = (val & ~RTSDCTL_ENT_DLY_MASK) | - (ent_delay << RTSDCTL_ENT_DLY_SHIFT); - wr_reg32(&r4tst->rtsdctl, val); - /* min. freq. count, equal to 1/4 of the entropy sample length */ - wr_reg32(&r4tst->rtfrqmin, ent_delay >> 2); - /* disable maximum frequency count */ - wr_reg32(&r4tst->rtfrqmax, RTFRQMAX_DISABLE); - /* read the control register */ - val = rd_reg32(&r4tst->rtmctl); -start_rng: + if ((rtsdctl & RTSDCTL_SAMP_SIZE_MASK) != RTSDCTL_SAMP_SIZE_VAL) { + wr_reg32(&r4tst->rtscmisc, (2 << 16) | 32); + wr_reg32(&r4tst->rtpkrrng, 570); + wr_reg32(&r4tst->rtpkrmax, 1600); + wr_reg32(&r4tst->rtscml, (122 << 16) | 317); + wr_reg32(&r4tst->rtscrl[0], (80 << 16) | 107); + wr_reg32(&r4tst->rtscrl[1], (57 << 16) | 62); + wr_reg32(&r4tst->rtscrl[2], (39 << 16) | 39); + wr_reg32(&r4tst->rtscrl[3], (27 << 16) | 26); + wr_reg32(&r4tst->rtscrl[4], (19 << 16) | 18); + wr_reg32(&r4tst->rtscrl[5], (18 << 16) | 17); + } + /* * select raw sampling in both entropy shifter * and statistical checker; ; put RNG4 into run mode @@ -618,10 +635,115 @@ static bool needs_entropy_delay_adjustment(void) return false; } +static int caam_ctrl_rng_init(struct device *dev) +{ + struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev); + struct caam_ctrl __iomem *ctrl = ctrlpriv->ctrl; + int ret, gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN; + u8 rng_vid; + + if (ctrlpriv->era < 10) { + struct caam_perfmon __iomem *perfmon; + + perfmon = ctrlpriv->total_jobrs ? + (struct caam_perfmon __iomem *)&ctrlpriv->jr[0]->perfmon : + (struct caam_perfmon __iomem *)&ctrl->perfmon; + + rng_vid = (rd_reg32(&perfmon->cha_id_ls) & + CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT; + } else { + struct version_regs __iomem *vreg; + + vreg = ctrlpriv->total_jobrs ? + (struct version_regs __iomem *)&ctrlpriv->jr[0]->vreg : + (struct version_regs __iomem *)&ctrl->vreg; + + rng_vid = (rd_reg32(&vreg->rng) & CHA_VER_VID_MASK) >> + CHA_VER_VID_SHIFT; + } + + /* + * If SEC has RNG version >= 4 and RNG state handle has not been + * already instantiated, do RNG instantiation + * In case of SoCs with Management Complex, RNG is managed by MC f/w. + */ + if (!(ctrlpriv->mc_en && ctrlpriv->pr_support) && rng_vid >= 4) { + ctrlpriv->rng4_sh_init = + rd_reg32(&ctrl->r4tst[0].rdsta); + /* + * If the secure keys (TDKEK, JDKEK, TDSK), were already + * generated, signal this to the function that is instantiating + * the state handles. An error would occur if RNG4 attempts + * to regenerate these keys before the next POR. + */ + gen_sk = ctrlpriv->rng4_sh_init & RDSTA_SKVN ? 0 : 1; + ctrlpriv->rng4_sh_init &= RDSTA_MASK; + do { + int inst_handles = + rd_reg32(&ctrl->r4tst[0].rdsta) & RDSTA_MASK; + /* + * If either SH were instantiated by somebody else + * (e.g. u-boot) then it is assumed that the entropy + * parameters are properly set and thus the function + * setting these (kick_trng(...)) is skipped. + * Also, if a handle was instantiated, do not change + * the TRNG parameters. + */ + if (needs_entropy_delay_adjustment()) + ent_delay = 12000; + if (!(ctrlpriv->rng4_sh_init || inst_handles)) { + dev_info(dev, + "Entropy delay = %u\n", + ent_delay); + kick_trng(dev, ent_delay); + ent_delay += 400; + } + /* + * if instantiate_rng(...) fails, the loop will rerun + * and the kick_trng(...) function will modify the + * upper and lower limits of the entropy sampling + * interval, leading to a successful initialization of + * the RNG. + */ + ret = instantiate_rng(dev, inst_handles, + gen_sk); + /* + * Entropy delay is determined via TRNG characterization. + * TRNG characterization is run across different voltages + * and temperatures. + * If worst case value for ent_dly is identified, + * the loop can be skipped for that platform. + */ + if (needs_entropy_delay_adjustment()) + break; + if (ret == -EAGAIN) + /* + * if here, the loop will rerun, + * so don't hog the CPU + */ + cpu_relax(); + } while ((ret == -EAGAIN) && (ent_delay < RTSDCTL_ENT_DLY_MAX)); + if (ret) { + dev_err(dev, "failed to instantiate RNG"); + return ret; + } + /* + * Set handles initialized by this module as the complement of + * the already initialized ones + */ + ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_MASK; + + /* Enable RDB bit so that RNG works faster */ + clrsetbits_32(&ctrl->scfgr, 0, SCFGR_RDBENABLE); + } + + return 0; +} + /* Probe routine for CAAM top (controller) level */ static int caam_probe(struct platform_device *pdev) { - int ret, ring, gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN; + int ret, ring; u64 caam_id; const struct soc_device_attribute *imx_soc_match; struct device *dev; @@ -631,10 +753,8 @@ static int caam_probe(struct platform_device *pdev) struct caam_perfmon __iomem *perfmon; struct dentry *dfs_root; u32 scfgr, comp_params; - u8 rng_vid; int pg_size; int BLOCK_OFFSET = 0; - bool pr_support = false; bool reg_access = true; ctrlpriv = devm_kzalloc(&pdev->dev, sizeof(*ctrlpriv), GFP_KERNEL); @@ -646,6 +766,9 @@ static int caam_probe(struct platform_device *pdev) nprop = pdev->dev.of_node; imx_soc_match = soc_device_match(caam_imx_soc_table); + if (!imx_soc_match && of_match_node(imx8m_machine_match, of_root)) + return -EPROBE_DEFER; + caam_imx = (bool)imx_soc_match; if (imx_soc_match) { @@ -770,7 +893,8 @@ static int caam_probe(struct platform_device *pdev) mc_version = fsl_mc_get_version(); if (mc_version) - pr_support = check_version(mc_version, 10, 20, 0); + ctrlpriv->pr_support = check_version(mc_version, 10, 20, + 0); else return -EPROBE_DEFER; } @@ -861,9 +985,6 @@ set_dma_mask: return -ENOMEM; } - if (!reg_access) - goto report_live; - comp_params = rd_reg32(&perfmon->comp_parms_ls); ctrlpriv->blob_present = !!(comp_params & CTPR_LS_BLOB); @@ -873,8 +994,6 @@ set_dma_mask: * check both here. */ if (ctrlpriv->era < 10) { - rng_vid = (rd_reg32(&perfmon->cha_id_ls) & - CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT; ctrlpriv->blob_present = ctrlpriv->blob_present && (rd_reg32(&perfmon->cha_num_ls) & CHA_ID_LS_AES_MASK); } else { @@ -884,91 +1003,16 @@ set_dma_mask: (struct version_regs __iomem *)&ctrlpriv->jr[0]->vreg : (struct version_regs __iomem *)&ctrl->vreg; - rng_vid = (rd_reg32(&vreg->rng) & CHA_VER_VID_MASK) >> - CHA_VER_VID_SHIFT; ctrlpriv->blob_present = ctrlpriv->blob_present && (rd_reg32(&vreg->aesa) & CHA_VER_MISC_AES_NUM_MASK); } - /* - * If SEC has RNG version >= 4 and RNG state handle has not been - * already instantiated, do RNG instantiation - * In case of SoCs with Management Complex, RNG is managed by MC f/w. - */ - if (!(ctrlpriv->mc_en && pr_support) && rng_vid >= 4) { - ctrlpriv->rng4_sh_init = - rd_reg32(&ctrl->r4tst[0].rdsta); - /* - * If the secure keys (TDKEK, JDKEK, TDSK), were already - * generated, signal this to the function that is instantiating - * the state handles. An error would occur if RNG4 attempts - * to regenerate these keys before the next POR. - */ - gen_sk = ctrlpriv->rng4_sh_init & RDSTA_SKVN ? 0 : 1; - ctrlpriv->rng4_sh_init &= RDSTA_MASK; - do { - int inst_handles = - rd_reg32(&ctrl->r4tst[0].rdsta) & - RDSTA_MASK; - /* - * If either SH were instantiated by somebody else - * (e.g. u-boot) then it is assumed that the entropy - * parameters are properly set and thus the function - * setting these (kick_trng(...)) is skipped. - * Also, if a handle was instantiated, do not change - * the TRNG parameters. - */ - if (needs_entropy_delay_adjustment()) - ent_delay = 12000; - if (!(ctrlpriv->rng4_sh_init || inst_handles)) { - dev_info(dev, - "Entropy delay = %u\n", - ent_delay); - kick_trng(pdev, ent_delay); - ent_delay += 400; - } - /* - * if instantiate_rng(...) fails, the loop will rerun - * and the kick_trng(...) function will modify the - * upper and lower limits of the entropy sampling - * interval, leading to a successful initialization of - * the RNG. - */ - ret = instantiate_rng(dev, inst_handles, - gen_sk); - /* - * Entropy delay is determined via TRNG characterization. - * TRNG characterization is run across different voltages - * and temperatures. - * If worst case value for ent_dly is identified, - * the loop can be skipped for that platform. - */ - if (needs_entropy_delay_adjustment()) - break; - if (ret == -EAGAIN) - /* - * if here, the loop will rerun, - * so don't hog the CPU - */ - cpu_relax(); - } while ((ret == -EAGAIN) && (ent_delay < RTSDCTL_ENT_DLY_MAX)); - if (ret) { - dev_err(dev, "failed to instantiate RNG"); + if (reg_access) { + ret = caam_ctrl_rng_init(dev); + if (ret) return ret; - } - /* - * Set handles initialized by this module as the complement of - * the already initialized ones - */ - ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_MASK; - - /* Enable RDB bit so that RNG works faster */ - clrsetbits_32(&ctrl->scfgr, 0, SCFGR_RDBENABLE); } -report_live: - /* NOTE: RTIC detection ought to go here, around Si time */ - caam_id = (u64)rd_reg32(&perfmon->caam_id_ms) << 32 | (u64)rd_reg32(&perfmon->caam_id_ls); diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h index 86ed1b91c22d..b4f7bf77f487 100644 --- a/drivers/crypto/caam/intern.h +++ b/drivers/crypto/caam/intern.h @@ -95,6 +95,7 @@ struct caam_drv_private { u8 blob_present; /* Nonzero if BLOB support present in device */ u8 mc_en; /* Nonzero if MC f/w is active */ u8 optee_en; /* Nonzero if OP-TEE f/w is active */ + bool pr_support; /* RNG prediction resistance available */ int secvio_irq; /* Security violation interrupt number */ int virt_en; /* Virtualization enabled in CAAM */ int era; /* CAAM Era (internal HW revision) */ diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h index 66928f8a0c4b..189e74c21f0c 100644 --- a/drivers/crypto/caam/regs.h +++ b/drivers/crypto/caam/regs.h @@ -3,7 +3,7 @@ * CAAM hardware register-level view * * Copyright 2008-2011 Freescale Semiconductor, Inc. - * Copyright 2018 NXP + * Copyright 2018, 2023 NXP */ #ifndef REGS_H @@ -523,6 +523,8 @@ struct rng4tst { #define RTSDCTL_ENT_DLY_MASK (0xffff << RTSDCTL_ENT_DLY_SHIFT) #define RTSDCTL_ENT_DLY_MIN 3200 #define RTSDCTL_ENT_DLY_MAX 12800 +#define RTSDCTL_SAMP_SIZE_MASK 0xffff +#define RTSDCTL_SAMP_SIZE_VAL 512 u32 rtsdctl; /* seed control register */ union { u32 rtsblim; /* PRGM=1: sparse bit limit register */ @@ -534,7 +536,15 @@ struct rng4tst { u32 rtfrqmax; /* PRGM=1: freq. count max. limit register */ u32 rtfrqcnt; /* PRGM=0: freq. count register */ }; - u32 rsvd1[40]; + union { + u32 rtscmc; /* statistical check run monobit count */ + u32 rtscml; /* statistical check run monobit limit */ + }; + union { + u32 rtscrc[6]; /* statistical check run length count */ + u32 rtscrl[6]; /* statistical check run length limit */ + }; + u32 rsvd1[33]; #define RDSTA_SKVT 0x80000000 #define RDSTA_SKVN 0x40000000 #define RDSTA_PR0 BIT(4) diff --git a/drivers/crypto/ccp/platform-access.c b/drivers/crypto/ccp/platform-access.c index 939c924fc383..94367bc49e35 100644 --- a/drivers/crypto/ccp/platform-access.c +++ b/drivers/crypto/ccp/platform-access.c @@ -67,6 +67,11 @@ int psp_send_platform_access_msg(enum psp_platform_access_msg msg, return -ENODEV; pa_dev = psp->platform_access_data; + + if (!pa_dev->vdata->cmdresp_reg || !pa_dev->vdata->cmdbuff_addr_lo_reg || + !pa_dev->vdata->cmdbuff_addr_hi_reg) + return -ENODEV; + cmd = psp->io_regs + pa_dev->vdata->cmdresp_reg; lo = psp->io_regs + pa_dev->vdata->cmdbuff_addr_lo_reg; hi = psp->io_regs + pa_dev->vdata->cmdbuff_addr_hi_reg; diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c index aa15bc4cac2b..b603ad9b8341 100644 --- a/drivers/crypto/ccp/sp-pci.c +++ b/drivers/crypto/ccp/sp-pci.c @@ -361,6 +361,14 @@ static const struct tee_vdata teev1 = { .ring_rptr_reg = 0x10554, /* C2PMSG_21 */ }; +static const struct tee_vdata teev2 = { + .cmdresp_reg = 0x10944, /* C2PMSG_17 */ + .cmdbuff_addr_lo_reg = 0x10948, /* C2PMSG_18 */ + .cmdbuff_addr_hi_reg = 0x1094c, /* C2PMSG_19 */ + .ring_wptr_reg = 0x10950, /* C2PMSG_20 */ + .ring_rptr_reg = 0x10954, /* C2PMSG_21 */ +}; + static const struct platform_access_vdata pa_v1 = { .cmdresp_reg = 0x10570, /* C2PMSG_28 */ .cmdbuff_addr_lo_reg = 0x10574, /* C2PMSG_29 */ @@ -369,6 +377,11 @@ static const struct platform_access_vdata pa_v1 = { .doorbell_cmd_reg = 0x10a40, /* C2PMSG_80 */ }; +static const struct platform_access_vdata pa_v2 = { + .doorbell_button_reg = 0x10a24, /* C2PMSG_73 */ + .doorbell_cmd_reg = 0x10a40, /* C2PMSG_80 */ +}; + static const struct psp_vdata pspv1 = { .sev = &sevv1, .feature_reg = 0x105fc, /* C2PMSG_63 */ @@ -399,6 +412,22 @@ static const struct psp_vdata pspv4 = { .intsts_reg = 0x10694, /* P2CMSG_INTSTS */ }; +static const struct psp_vdata pspv5 = { + .tee = &teev2, + .platform_access = &pa_v2, + .feature_reg = 0x109fc, /* C2PMSG_63 */ + .inten_reg = 0x10510, /* P2CMSG_INTEN */ + .intsts_reg = 0x10514, /* P2CMSG_INTSTS */ +}; + +static const struct psp_vdata pspv6 = { + .sev = &sevv2, + .tee = &teev2, + .feature_reg = 0x109fc, /* C2PMSG_63 */ + .inten_reg = 0x10510, /* P2CMSG_INTEN */ + .intsts_reg = 0x10514, /* P2CMSG_INTSTS */ +}; + #endif static const struct sp_dev_vdata dev_vdata[] = { @@ -453,6 +482,18 @@ static const struct sp_dev_vdata dev_vdata[] = { .psp_vdata = &pspv3, #endif }, + { /* 7 */ + .bar = 2, +#ifdef CONFIG_CRYPTO_DEV_SP_PSP + .psp_vdata = &pspv5, +#endif + }, + { /* 8 */ + .bar = 2, +#ifdef CONFIG_CRYPTO_DEV_SP_PSP + .psp_vdata = &pspv6, +#endif + }, }; static const struct pci_device_id sp_pci_table[] = { { PCI_VDEVICE(AMD, 0x1537), (kernel_ulong_t)&dev_vdata[0] }, @@ -463,6 +504,8 @@ static const struct pci_device_id sp_pci_table[] = { { PCI_VDEVICE(AMD, 0x14CA), (kernel_ulong_t)&dev_vdata[5] }, { PCI_VDEVICE(AMD, 0x15C7), (kernel_ulong_t)&dev_vdata[6] }, { PCI_VDEVICE(AMD, 0x1649), (kernel_ulong_t)&dev_vdata[6] }, + { PCI_VDEVICE(AMD, 0x17E0), (kernel_ulong_t)&dev_vdata[7] }, + { PCI_VDEVICE(AMD, 0x156E), (kernel_ulong_t)&dev_vdata[8] }, /* Last entry must be zero */ { 0, } }; diff --git a/drivers/crypto/hisilicon/Kconfig b/drivers/crypto/hisilicon/Kconfig index e8690c223584..4137a8bf131f 100644 --- a/drivers/crypto/hisilicon/Kconfig +++ b/drivers/crypto/hisilicon/Kconfig @@ -82,10 +82,3 @@ config CRYPTO_DEV_HISI_TRNG select CRYPTO_RNG help Support for HiSilicon TRNG Driver. - -config CRYPTO_DEV_HISTB_TRNG - tristate "Support for HiSTB TRNG Driver" - depends on ARCH_HISI || COMPILE_TEST - select HW_RANDOM - help - Support for HiSTB TRNG Driver. diff --git a/drivers/crypto/hisilicon/Makefile b/drivers/crypto/hisilicon/Makefile index fc51e0edec69..8595a5a5d228 100644 --- a/drivers/crypto/hisilicon/Makefile +++ b/drivers/crypto/hisilicon/Makefile @@ -5,4 +5,4 @@ obj-$(CONFIG_CRYPTO_DEV_HISI_SEC2) += sec2/ obj-$(CONFIG_CRYPTO_DEV_HISI_QM) += hisi_qm.o hisi_qm-objs = qm.o sgl.o debugfs.o obj-$(CONFIG_CRYPTO_DEV_HISI_ZIP) += zip/ -obj-y += trng/ +obj-$(CONFIG_CRYPTO_DEV_HISI_TRNG) += trng/ diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index ad0c042b5e66..edc6fd44e7ca 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -610,7 +610,10 @@ EXPORT_SYMBOL_GPL(hisi_qm_wait_mb_ready); static void qm_mb_write(struct hisi_qm *qm, const void *src) { void __iomem *fun_base = qm->io_base + QM_MB_CMD_SEND_BASE; + +#if IS_ENABLED(CONFIG_ARM64) unsigned long tmp0 = 0, tmp1 = 0; +#endif if (!IS_ENABLED(CONFIG_ARM64)) { memcpy_toio(fun_base, src, 16); @@ -618,6 +621,7 @@ static void qm_mb_write(struct hisi_qm *qm, const void *src) return; } +#if IS_ENABLED(CONFIG_ARM64) asm volatile("ldp %0, %1, %3\n" "stp %0, %1, %2\n" "dmb oshst\n" @@ -626,6 +630,7 @@ static void qm_mb_write(struct hisi_qm *qm, const void *src) "+Q" (*((char __iomem *)fun_base)) : "Q" (*((char *)src)) : "memory"); +#endif } static int qm_mb_nolock(struct hisi_qm *qm, struct qm_mailbox *mailbox) diff --git a/drivers/crypto/hisilicon/trng/Makefile b/drivers/crypto/hisilicon/trng/Makefile index cf20b057c66b..d909079f351c 100644 --- a/drivers/crypto/hisilicon/trng/Makefile +++ b/drivers/crypto/hisilicon/trng/Makefile @@ -1,5 +1,2 @@ obj-$(CONFIG_CRYPTO_DEV_HISI_TRNG) += hisi-trng-v2.o hisi-trng-v2-objs = trng.o - -obj-$(CONFIG_CRYPTO_DEV_HISTB_TRNG) += histb-trng.o -histb-trng-objs += trng-stb.o diff --git a/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c b/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c index ed15379a9818..4a18095ae5d8 100644 --- a/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c +++ b/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c @@ -1175,9 +1175,9 @@ static int aead_perform(struct aead_request *req, int encrypt, /* The 12 hmac bytes are scattered, * we need to copy them into a safe buffer */ req_ctx->hmac_virt = dma_pool_alloc(buffer_pool, flags, &dma); - crypt->icv_rev_aes = dma; if (unlikely(!req_ctx->hmac_virt)) goto free_buf_dst; + crypt->icv_rev_aes = dma; if (!encrypt) { scatterwalk_map_and_copy(req_ctx->hmac_virt, req->src, cryptlen, authsize, 0); diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c index 7324b86a4f40..e543a9e24a06 100644 --- a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c +++ b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c @@ -11,37 +11,76 @@ #include "adf_4xxx_hw_data.h" #include "icp_qat_hw.h" +enum adf_fw_objs { + ADF_FW_SYM_OBJ, + ADF_FW_ASYM_OBJ, + ADF_FW_DC_OBJ, + ADF_FW_ADMIN_OBJ, +}; + +static const char * const adf_4xxx_fw_objs[] = { + [ADF_FW_SYM_OBJ] = ADF_4XXX_SYM_OBJ, + [ADF_FW_ASYM_OBJ] = ADF_4XXX_ASYM_OBJ, + [ADF_FW_DC_OBJ] = ADF_4XXX_DC_OBJ, + [ADF_FW_ADMIN_OBJ] = ADF_4XXX_ADMIN_OBJ, +}; + +static const char * const adf_402xx_fw_objs[] = { + [ADF_FW_SYM_OBJ] = ADF_402XX_SYM_OBJ, + [ADF_FW_ASYM_OBJ] = ADF_402XX_ASYM_OBJ, + [ADF_FW_DC_OBJ] = ADF_402XX_DC_OBJ, + [ADF_FW_ADMIN_OBJ] = ADF_402XX_ADMIN_OBJ, +}; + struct adf_fw_config { u32 ae_mask; - char *obj_name; + enum adf_fw_objs obj; }; -static struct adf_fw_config adf_4xxx_fw_cy_config[] = { - {0xF0, ADF_4XXX_SYM_OBJ}, - {0xF, ADF_4XXX_ASYM_OBJ}, - {0x100, ADF_4XXX_ADMIN_OBJ}, +static const struct adf_fw_config adf_fw_cy_config[] = { + {0xF0, ADF_FW_SYM_OBJ}, + {0xF, ADF_FW_ASYM_OBJ}, + {0x100, ADF_FW_ADMIN_OBJ}, }; -static struct adf_fw_config adf_4xxx_fw_dc_config[] = { - {0xF0, ADF_4XXX_DC_OBJ}, - {0xF, ADF_4XXX_DC_OBJ}, - {0x100, ADF_4XXX_ADMIN_OBJ}, +static const struct adf_fw_config adf_fw_dc_config[] = { + {0xF0, ADF_FW_DC_OBJ}, + {0xF, ADF_FW_DC_OBJ}, + {0x100, ADF_FW_ADMIN_OBJ}, }; -static struct adf_fw_config adf_402xx_fw_cy_config[] = { - {0xF0, ADF_402XX_SYM_OBJ}, - {0xF, ADF_402XX_ASYM_OBJ}, - {0x100, ADF_402XX_ADMIN_OBJ}, +static const struct adf_fw_config adf_fw_sym_config[] = { + {0xF0, ADF_FW_SYM_OBJ}, + {0xF, ADF_FW_SYM_OBJ}, + {0x100, ADF_FW_ADMIN_OBJ}, }; -static struct adf_fw_config adf_402xx_fw_dc_config[] = { - {0xF0, ADF_402XX_DC_OBJ}, - {0xF, ADF_402XX_DC_OBJ}, - {0x100, ADF_402XX_ADMIN_OBJ}, +static const struct adf_fw_config adf_fw_asym_config[] = { + {0xF0, ADF_FW_ASYM_OBJ}, + {0xF, ADF_FW_ASYM_OBJ}, + {0x100, ADF_FW_ADMIN_OBJ}, }; +static const struct adf_fw_config adf_fw_asym_dc_config[] = { + {0xF0, ADF_FW_ASYM_OBJ}, + {0xF, ADF_FW_DC_OBJ}, + {0x100, ADF_FW_ADMIN_OBJ}, +}; + +static const struct adf_fw_config adf_fw_sym_dc_config[] = { + {0xF0, ADF_FW_SYM_OBJ}, + {0xF, ADF_FW_DC_OBJ}, + {0x100, ADF_FW_ADMIN_OBJ}, +}; + +static_assert(ARRAY_SIZE(adf_fw_cy_config) == ARRAY_SIZE(adf_fw_dc_config)); +static_assert(ARRAY_SIZE(adf_fw_cy_config) == ARRAY_SIZE(adf_fw_sym_config)); +static_assert(ARRAY_SIZE(adf_fw_cy_config) == ARRAY_SIZE(adf_fw_asym_config)); +static_assert(ARRAY_SIZE(adf_fw_cy_config) == ARRAY_SIZE(adf_fw_asym_dc_config)); +static_assert(ARRAY_SIZE(adf_fw_cy_config) == ARRAY_SIZE(adf_fw_sym_dc_config)); + /* Worker thread to service arbiter mappings */ -static const u32 thrd_to_arb_map_cy[ADF_4XXX_MAX_ACCELENGINES] = { +static const u32 default_thrd_to_arb_map[ADF_4XXX_MAX_ACCELENGINES] = { 0x5555555, 0x5555555, 0x5555555, 0x5555555, 0xAAAAAAA, 0xAAAAAAA, 0xAAAAAAA, 0xAAAAAAA, 0x0 @@ -61,12 +100,26 @@ static struct adf_hw_device_class adf_4xxx_class = { enum dev_services { SVC_CY = 0, + SVC_CY2, SVC_DC, + SVC_SYM, + SVC_ASYM, + SVC_DC_ASYM, + SVC_ASYM_DC, + SVC_DC_SYM, + SVC_SYM_DC, }; static const char *const dev_cfg_services[] = { [SVC_CY] = ADF_CFG_CY, + [SVC_CY2] = ADF_CFG_ASYM_SYM, [SVC_DC] = ADF_CFG_DC, + [SVC_SYM] = ADF_CFG_SYM, + [SVC_ASYM] = ADF_CFG_ASYM, + [SVC_DC_ASYM] = ADF_CFG_DC_ASYM, + [SVC_ASYM_DC] = ADF_CFG_ASYM_DC, + [SVC_DC_SYM] = ADF_CFG_DC_SYM, + [SVC_SYM_DC] = ADF_CFG_SYM_DC, }; static int get_service_enabled(struct adf_accel_dev *accel_dev) @@ -156,45 +209,50 @@ static void set_msix_default_rttable(struct adf_accel_dev *accel_dev) static u32 get_accel_cap(struct adf_accel_dev *accel_dev) { struct pci_dev *pdev = accel_dev->accel_pci_dev.pci_dev; - u32 capabilities_cy, capabilities_dc; + u32 capabilities_sym, capabilities_asym, capabilities_dc; u32 fusectl1; /* Read accelerator capabilities mask */ pci_read_config_dword(pdev, ADF_4XXX_FUSECTL1_OFFSET, &fusectl1); - capabilities_cy = ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC | - ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC | + capabilities_sym = ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC | ICP_ACCEL_CAPABILITIES_CIPHER | ICP_ACCEL_CAPABILITIES_AUTHENTICATION | ICP_ACCEL_CAPABILITIES_SHA3 | ICP_ACCEL_CAPABILITIES_SHA3_EXT | ICP_ACCEL_CAPABILITIES_HKDF | - ICP_ACCEL_CAPABILITIES_ECEDMONT | ICP_ACCEL_CAPABILITIES_CHACHA_POLY | ICP_ACCEL_CAPABILITIES_AESGCM_SPC | ICP_ACCEL_CAPABILITIES_AES_V2; /* A set bit in fusectl1 means the feature is OFF in this SKU */ if (fusectl1 & ICP_ACCEL_4XXX_MASK_CIPHER_SLICE) { - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC; - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_HKDF; - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_CIPHER; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_HKDF; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_CIPHER; } + if (fusectl1 & ICP_ACCEL_4XXX_MASK_UCS_SLICE) { - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_CHACHA_POLY; - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_AESGCM_SPC; - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_AES_V2; - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_CIPHER; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_CHACHA_POLY; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_AESGCM_SPC; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_AES_V2; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_CIPHER; } + if (fusectl1 & ICP_ACCEL_4XXX_MASK_AUTH_SLICE) { - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_AUTHENTICATION; - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_SHA3; - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_SHA3_EXT; - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_CIPHER; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_AUTHENTICATION; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_SHA3; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_SHA3_EXT; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_CIPHER; } + + capabilities_asym = ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC | + ICP_ACCEL_CAPABILITIES_CIPHER | + ICP_ACCEL_CAPABILITIES_ECEDMONT; + if (fusectl1 & ICP_ACCEL_4XXX_MASK_PKE_SLICE) { - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC; - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_ECEDMONT; + capabilities_asym &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC; + capabilities_asym &= ~ICP_ACCEL_CAPABILITIES_ECEDMONT; } capabilities_dc = ICP_ACCEL_CAPABILITIES_COMPRESSION | @@ -211,12 +269,23 @@ static u32 get_accel_cap(struct adf_accel_dev *accel_dev) switch (get_service_enabled(accel_dev)) { case SVC_CY: - return capabilities_cy; + case SVC_CY2: + return capabilities_sym | capabilities_asym; case SVC_DC: return capabilities_dc; + case SVC_SYM: + return capabilities_sym; + case SVC_ASYM: + return capabilities_asym; + case SVC_ASYM_DC: + case SVC_DC_ASYM: + return capabilities_asym | capabilities_dc; + case SVC_SYM_DC: + case SVC_DC_SYM: + return capabilities_sym | capabilities_dc; + default: + return 0; } - - return 0; } static enum dev_sku_info get_sku(struct adf_hw_device_data *self) @@ -227,13 +296,11 @@ static enum dev_sku_info get_sku(struct adf_hw_device_data *self) static const u32 *adf_get_arbiter_mapping(struct adf_accel_dev *accel_dev) { switch (get_service_enabled(accel_dev)) { - case SVC_CY: - return thrd_to_arb_map_cy; case SVC_DC: return thrd_to_arb_map_dc; + default: + return default_thrd_to_arb_map; } - - return NULL; } static void get_arb_info(struct arb_info *arb_info) @@ -304,47 +371,83 @@ static int adf_init_device(struct adf_accel_dev *accel_dev) static u32 uof_get_num_objs(void) { - BUILD_BUG_ON_MSG(ARRAY_SIZE(adf_4xxx_fw_cy_config) != - ARRAY_SIZE(adf_4xxx_fw_dc_config), - "Size mismatch between adf_4xxx_fw_*_config arrays"); - - return ARRAY_SIZE(adf_4xxx_fw_cy_config); + return ARRAY_SIZE(adf_fw_cy_config); } -static char *uof_get_name_4xxx(struct adf_accel_dev *accel_dev, u32 obj_num) +static const char *uof_get_name(struct adf_accel_dev *accel_dev, u32 obj_num, + const char * const fw_objs[], int num_objs) { + int id; + switch (get_service_enabled(accel_dev)) { case SVC_CY: - return adf_4xxx_fw_cy_config[obj_num].obj_name; + case SVC_CY2: + id = adf_fw_cy_config[obj_num].obj; + break; case SVC_DC: - return adf_4xxx_fw_dc_config[obj_num].obj_name; + id = adf_fw_dc_config[obj_num].obj; + break; + case SVC_SYM: + id = adf_fw_sym_config[obj_num].obj; + break; + case SVC_ASYM: + id = adf_fw_asym_config[obj_num].obj; + break; + case SVC_ASYM_DC: + case SVC_DC_ASYM: + id = adf_fw_asym_dc_config[obj_num].obj; + break; + case SVC_SYM_DC: + case SVC_DC_SYM: + id = adf_fw_sym_dc_config[obj_num].obj; + break; + default: + id = -EINVAL; + break; } - return NULL; + if (id < 0 || id > num_objs) + return NULL; + + return fw_objs[id]; } -static char *uof_get_name_402xx(struct adf_accel_dev *accel_dev, u32 obj_num) +static const char *uof_get_name_4xxx(struct adf_accel_dev *accel_dev, u32 obj_num) { - switch (get_service_enabled(accel_dev)) { - case SVC_CY: - return adf_402xx_fw_cy_config[obj_num].obj_name; - case SVC_DC: - return adf_402xx_fw_dc_config[obj_num].obj_name; - } + int num_fw_objs = ARRAY_SIZE(adf_4xxx_fw_objs); - return NULL; + return uof_get_name(accel_dev, obj_num, adf_4xxx_fw_objs, num_fw_objs); +} + +static const char *uof_get_name_402xx(struct adf_accel_dev *accel_dev, u32 obj_num) +{ + int num_fw_objs = ARRAY_SIZE(adf_402xx_fw_objs); + + return uof_get_name(accel_dev, obj_num, adf_402xx_fw_objs, num_fw_objs); } static u32 uof_get_ae_mask(struct adf_accel_dev *accel_dev, u32 obj_num) { switch (get_service_enabled(accel_dev)) { case SVC_CY: - return adf_4xxx_fw_cy_config[obj_num].ae_mask; + return adf_fw_cy_config[obj_num].ae_mask; case SVC_DC: - return adf_4xxx_fw_dc_config[obj_num].ae_mask; + return adf_fw_dc_config[obj_num].ae_mask; + case SVC_CY2: + return adf_fw_cy_config[obj_num].ae_mask; + case SVC_SYM: + return adf_fw_sym_config[obj_num].ae_mask; + case SVC_ASYM: + return adf_fw_asym_config[obj_num].ae_mask; + case SVC_ASYM_DC: + case SVC_DC_ASYM: + return adf_fw_asym_dc_config[obj_num].ae_mask; + case SVC_SYM_DC: + case SVC_DC_SYM: + return adf_fw_sym_dc_config[obj_num].ae_mask; + default: + return 0; } - - return 0; } void adf_init_hw_data_4xxx(struct adf_hw_device_data *hw_data, u32 dev_id) diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h index 085e259c245a..e5b314d2b60e 100644 --- a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h +++ b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h @@ -72,7 +72,7 @@ enum icp_qat_4xxx_slice_mask { ICP_ACCEL_4XXX_MASK_COMPRESS_SLICE = BIT(3), ICP_ACCEL_4XXX_MASK_UCS_SLICE = BIT(4), ICP_ACCEL_4XXX_MASK_EIA3_SLICE = BIT(5), - ICP_ACCEL_4XXX_MASK_SMX_SLICE = BIT(6), + ICP_ACCEL_4XXX_MASK_SMX_SLICE = BIT(7), }; void adf_init_hw_data_4xxx(struct adf_hw_device_data *hw_data, u32 dev_id); diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c index ceb87327a5fe..1a15600361d0 100644 --- a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c @@ -7,6 +7,7 @@ #include <adf_accel_devices.h> #include <adf_cfg.h> #include <adf_common_drv.h> +#include <adf_dbgfs.h> #include "adf_4xxx_hw_data.h" #include "qat_compression.h" @@ -24,11 +25,25 @@ MODULE_DEVICE_TABLE(pci, adf_pci_tbl); enum configs { DEV_CFG_CY = 0, DEV_CFG_DC, + DEV_CFG_SYM, + DEV_CFG_ASYM, + DEV_CFG_ASYM_SYM, + DEV_CFG_ASYM_DC, + DEV_CFG_DC_ASYM, + DEV_CFG_SYM_DC, + DEV_CFG_DC_SYM, }; static const char * const services_operations[] = { ADF_CFG_CY, ADF_CFG_DC, + ADF_CFG_SYM, + ADF_CFG_ASYM, + ADF_CFG_ASYM_SYM, + ADF_CFG_ASYM_DC, + ADF_CFG_DC_ASYM, + ADF_CFG_SYM_DC, + ADF_CFG_DC_SYM, }; static void adf_cleanup_accel(struct adf_accel_dev *accel_dev) @@ -37,8 +52,8 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev) adf_clean_hw_data_4xxx(accel_dev->hw_device); accel_dev->hw_device = NULL; } + adf_dbgfs_exit(accel_dev); adf_cfg_dev_remove(accel_dev); - debugfs_remove(accel_dev->debugfs_dir); adf_devmgr_rm_dev(accel_dev, NULL); } @@ -241,6 +256,21 @@ err: return ret; } +static int adf_no_dev_config(struct adf_accel_dev *accel_dev) +{ + unsigned long val; + int ret; + + val = 0; + ret = adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC, ADF_NUM_DC, + &val, ADF_DEC); + if (ret) + return ret; + + return adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC, ADF_NUM_CY, + &val, ADF_DEC); +} + int adf_gen4_dev_config(struct adf_accel_dev *accel_dev) { char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; @@ -265,11 +295,15 @@ int adf_gen4_dev_config(struct adf_accel_dev *accel_dev) switch (ret) { case DEV_CFG_CY: + case DEV_CFG_ASYM_SYM: ret = adf_crypto_dev_config(accel_dev); break; case DEV_CFG_DC: ret = adf_comp_dev_config(accel_dev); break; + default: + ret = adf_no_dev_config(accel_dev); + break; } if (ret) @@ -289,7 +323,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct adf_accel_dev *accel_dev; struct adf_accel_pci *accel_pci_dev; struct adf_hw_device_data *hw_data; - char name[ADF_DEVICE_NAME_LENGTH]; unsigned int i, bar_nr; unsigned long bar_mask; struct adf_bar *bar; @@ -348,12 +381,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_err; } - /* Create dev top level debugfs entry */ - snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX, - hw_data->dev_class->name, pci_name(pdev)); - - accel_dev->debugfs_dir = debugfs_create_dir(name, NULL); - /* Create device configuration table */ ret = adf_cfg_dev_add(accel_dev); if (ret) @@ -410,6 +437,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_err; } + adf_dbgfs_init(accel_dev); + ret = adf_dev_up(accel_dev, true); if (ret) goto out_err_dev_stop; diff --git a/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c b/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c index bb4dca735ab5..468c9102093f 100644 --- a/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c @@ -16,6 +16,7 @@ #include <adf_accel_devices.h> #include <adf_common_drv.h> #include <adf_cfg.h> +#include <adf_dbgfs.h> #include "adf_c3xxx_hw_data.h" static const struct pci_device_id adf_pci_tbl[] = { @@ -65,8 +66,8 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev) kfree(accel_dev->hw_device); accel_dev->hw_device = NULL; } + adf_dbgfs_exit(accel_dev); adf_cfg_dev_remove(accel_dev); - debugfs_remove(accel_dev->debugfs_dir); adf_devmgr_rm_dev(accel_dev, NULL); } @@ -75,7 +76,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct adf_accel_dev *accel_dev; struct adf_accel_pci *accel_pci_dev; struct adf_hw_device_data *hw_data; - char name[ADF_DEVICE_NAME_LENGTH]; unsigned int i, bar_nr; unsigned long bar_mask; int ret; @@ -142,12 +142,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_err; } - /* Create dev top level debugfs entry */ - snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX, - hw_data->dev_class->name, pci_name(pdev)); - - accel_dev->debugfs_dir = debugfs_create_dir(name, NULL); - /* Create device configuration table */ ret = adf_cfg_dev_add(accel_dev); if (ret) @@ -199,6 +193,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_err_free_reg; } + adf_dbgfs_init(accel_dev); + ret = adf_dev_up(accel_dev, true); if (ret) goto out_err_dev_stop; diff --git a/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c b/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c index e8cc10f64134..d5a0ecca9d0b 100644 --- a/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c @@ -16,6 +16,7 @@ #include <adf_accel_devices.h> #include <adf_common_drv.h> #include <adf_cfg.h> +#include <adf_dbgfs.h> #include "adf_c3xxxvf_hw_data.h" static const struct pci_device_id adf_pci_tbl[] = { @@ -64,8 +65,8 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev) kfree(accel_dev->hw_device); accel_dev->hw_device = NULL; } + adf_dbgfs_exit(accel_dev); adf_cfg_dev_remove(accel_dev); - debugfs_remove(accel_dev->debugfs_dir); pf = adf_devmgr_pci_to_accel_dev(accel_pci_dev->pci_dev->physfn); adf_devmgr_rm_dev(accel_dev, pf); } @@ -76,7 +77,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct adf_accel_dev *pf; struct adf_accel_pci *accel_pci_dev; struct adf_hw_device_data *hw_data; - char name[ADF_DEVICE_NAME_LENGTH]; unsigned int i, bar_nr; unsigned long bar_mask; int ret; @@ -123,12 +123,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw_data->ae_mask = hw_data->get_ae_mask(hw_data); accel_pci_dev->sku = hw_data->get_sku(hw_data); - /* Create dev top level debugfs entry */ - snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX, - hw_data->dev_class->name, pci_name(pdev)); - - accel_dev->debugfs_dir = debugfs_create_dir(name, NULL); - /* Create device configuration table */ ret = adf_cfg_dev_add(accel_dev); if (ret) @@ -173,6 +167,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Completion for VF2PF request/response message exchange */ init_completion(&accel_dev->vf.msg_received); + adf_dbgfs_init(accel_dev); + ret = adf_dev_up(accel_dev, false); if (ret) goto out_err_dev_stop; diff --git a/drivers/crypto/intel/qat/qat_c62x/adf_drv.c b/drivers/crypto/intel/qat/qat_c62x/adf_drv.c index ca18ae14c099..0186921be936 100644 --- a/drivers/crypto/intel/qat/qat_c62x/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_c62x/adf_drv.c @@ -16,6 +16,7 @@ #include <adf_accel_devices.h> #include <adf_common_drv.h> #include <adf_cfg.h> +#include <adf_dbgfs.h> #include "adf_c62x_hw_data.h" static const struct pci_device_id adf_pci_tbl[] = { @@ -65,8 +66,8 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev) kfree(accel_dev->hw_device); accel_dev->hw_device = NULL; } + adf_dbgfs_exit(accel_dev); adf_cfg_dev_remove(accel_dev); - debugfs_remove(accel_dev->debugfs_dir); adf_devmgr_rm_dev(accel_dev, NULL); } @@ -75,7 +76,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct adf_accel_dev *accel_dev; struct adf_accel_pci *accel_pci_dev; struct adf_hw_device_data *hw_data; - char name[ADF_DEVICE_NAME_LENGTH]; unsigned int i, bar_nr; unsigned long bar_mask; int ret; @@ -142,12 +142,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_err; } - /* Create dev top level debugfs entry */ - snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX, - hw_data->dev_class->name, pci_name(pdev)); - - accel_dev->debugfs_dir = debugfs_create_dir(name, NULL); - /* Create device configuration table */ ret = adf_cfg_dev_add(accel_dev); if (ret) @@ -199,6 +193,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_err_free_reg; } + adf_dbgfs_init(accel_dev); + ret = adf_dev_up(accel_dev, true); if (ret) goto out_err_dev_stop; diff --git a/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c b/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c index 37566309df94..c9ae6c0d0dca 100644 --- a/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c @@ -16,6 +16,7 @@ #include <adf_accel_devices.h> #include <adf_common_drv.h> #include <adf_cfg.h> +#include <adf_dbgfs.h> #include "adf_c62xvf_hw_data.h" static const struct pci_device_id adf_pci_tbl[] = { @@ -64,8 +65,8 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev) kfree(accel_dev->hw_device); accel_dev->hw_device = NULL; } + adf_dbgfs_exit(accel_dev); adf_cfg_dev_remove(accel_dev); - debugfs_remove(accel_dev->debugfs_dir); pf = adf_devmgr_pci_to_accel_dev(accel_pci_dev->pci_dev->physfn); adf_devmgr_rm_dev(accel_dev, pf); } @@ -76,7 +77,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct adf_accel_dev *pf; struct adf_accel_pci *accel_pci_dev; struct adf_hw_device_data *hw_data; - char name[ADF_DEVICE_NAME_LENGTH]; unsigned int i, bar_nr; unsigned long bar_mask; int ret; @@ -123,12 +123,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw_data->ae_mask = hw_data->get_ae_mask(hw_data); accel_pci_dev->sku = hw_data->get_sku(hw_data); - /* Create dev top level debugfs entry */ - snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX, - hw_data->dev_class->name, pci_name(pdev)); - - accel_dev->debugfs_dir = debugfs_create_dir(name, NULL); - /* Create device configuration table */ ret = adf_cfg_dev_add(accel_dev); if (ret) @@ -173,6 +167,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Completion for VF2PF request/response message exchange */ init_completion(&accel_dev->vf.msg_received); + adf_dbgfs_init(accel_dev); + ret = adf_dev_up(accel_dev, false); if (ret) goto out_err_dev_stop; diff --git a/drivers/crypto/intel/qat/qat_common/Makefile b/drivers/crypto/intel/qat/qat_common/Makefile index 1fb8d50f509f..38de3aba6e8c 100644 --- a/drivers/crypto/intel/qat/qat_common/Makefile +++ b/drivers/crypto/intel/qat/qat_common/Makefile @@ -27,7 +27,9 @@ intel_qat-objs := adf_cfg.o \ qat_hal.o \ qat_bl.o -intel_qat-$(CONFIG_DEBUG_FS) += adf_transport_debug.o +intel_qat-$(CONFIG_DEBUG_FS) += adf_transport_debug.o \ + adf_dbgfs.o + intel_qat-$(CONFIG_PCI_IOV) += adf_sriov.o adf_vf_isr.o adf_pfvf_utils.o \ adf_pfvf_pf_msg.o adf_pfvf_pf_proto.o \ adf_pfvf_vf_msg.o adf_pfvf_vf_proto.o \ diff --git a/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h b/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h index bd19e6460899..0399417b91fc 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h +++ b/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h @@ -202,7 +202,7 @@ struct adf_hw_device_data { int (*ring_pair_reset)(struct adf_accel_dev *accel_dev, u32 bank_nr); void (*reset_device)(struct adf_accel_dev *accel_dev); void (*set_msix_rttable)(struct adf_accel_dev *accel_dev); - char *(*uof_get_name)(struct adf_accel_dev *accel_dev, u32 obj_num); + const char *(*uof_get_name)(struct adf_accel_dev *accel_dev, u32 obj_num); u32 (*uof_get_num_objs)(void); u32 (*uof_get_ae_mask)(struct adf_accel_dev *accel_dev, u32 obj_num); int (*dev_config)(struct adf_accel_dev *accel_dev); diff --git a/drivers/crypto/intel/qat/qat_common/adf_accel_engine.c b/drivers/crypto/intel/qat/qat_common/adf_accel_engine.c index 4ce2b666929e..6be064dc64c8 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_accel_engine.c +++ b/drivers/crypto/intel/qat/qat_common/adf_accel_engine.c @@ -13,7 +13,7 @@ static int adf_ae_fw_load_images(struct adf_accel_dev *accel_dev, void *fw_addr, struct adf_fw_loader_data *loader_data = accel_dev->fw_loader; struct adf_hw_device_data *hw_device = accel_dev->hw_device; struct icp_qat_fw_loader_handle *loader; - char *obj_name; + const char *obj_name; u32 num_objs; u32 ae_mask; int i; diff --git a/drivers/crypto/intel/qat/qat_common/adf_admin.c b/drivers/crypto/intel/qat/qat_common/adf_admin.c index 3b6184c35081..118775ee02f2 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_admin.c +++ b/drivers/crypto/intel/qat/qat_common/adf_admin.c @@ -286,7 +286,6 @@ int adf_init_admin_pm(struct adf_accel_dev *accel_dev, u32 idle_delay) return adf_send_admin(accel_dev, &req, &resp, ae_mask); } -EXPORT_SYMBOL_GPL(adf_init_admin_pm); int adf_init_admin_comms(struct adf_accel_dev *accel_dev) { diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg.c b/drivers/crypto/intel/qat/qat_common/adf_cfg.c index 1931e5b37f2b..8836f015c39c 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_cfg.c +++ b/drivers/crypto/intel/qat/qat_common/adf_cfg.c @@ -74,15 +74,30 @@ int adf_cfg_dev_add(struct adf_accel_dev *accel_dev) INIT_LIST_HEAD(&dev_cfg_data->sec_list); init_rwsem(&dev_cfg_data->lock); accel_dev->cfg = dev_cfg_data; + return 0; +} +EXPORT_SYMBOL_GPL(adf_cfg_dev_add); - /* accel_dev->debugfs_dir should always be non-NULL here */ - dev_cfg_data->debug = debugfs_create_file("dev_cfg", S_IRUSR, +void adf_cfg_dev_dbgfs_add(struct adf_accel_dev *accel_dev) +{ + struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg; + + dev_cfg_data->debug = debugfs_create_file("dev_cfg", 0400, accel_dev->debugfs_dir, dev_cfg_data, &qat_dev_cfg_fops); - return 0; } -EXPORT_SYMBOL_GPL(adf_cfg_dev_add); + +void adf_cfg_dev_dbgfs_rm(struct adf_accel_dev *accel_dev) +{ + struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg; + + if (!dev_cfg_data) + return; + + debugfs_remove(dev_cfg_data->debug); + dev_cfg_data->debug = NULL; +} static void adf_cfg_section_del_all(struct list_head *head); @@ -116,7 +131,6 @@ void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev) down_write(&dev_cfg_data->lock); adf_cfg_section_del_all(&dev_cfg_data->sec_list); up_write(&dev_cfg_data->lock); - debugfs_remove(dev_cfg_data->debug); kfree(dev_cfg_data); accel_dev->cfg = NULL; } diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg.h b/drivers/crypto/intel/qat/qat_common/adf_cfg.h index 376cde61a60e..c0c9052b2213 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_cfg.h +++ b/drivers/crypto/intel/qat/qat_common/adf_cfg.h @@ -31,6 +31,8 @@ struct adf_cfg_device_data { int adf_cfg_dev_add(struct adf_accel_dev *accel_dev); void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev); +void adf_cfg_dev_dbgfs_add(struct adf_accel_dev *accel_dev); +void adf_cfg_dev_dbgfs_rm(struct adf_accel_dev *accel_dev); int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name); void adf_cfg_del_all(struct adf_accel_dev *accel_dev); int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev, diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h b/drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h index 5d8c3bdb258c..3ae1e5caee0e 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h +++ b/drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h @@ -25,7 +25,15 @@ #define ADF_DC "Dc" #define ADF_CFG_DC "dc" #define ADF_CFG_CY "sym;asym" +#define ADF_CFG_SYM "sym" +#define ADF_CFG_ASYM "asym" +#define ADF_CFG_ASYM_SYM "asym;sym" +#define ADF_CFG_ASYM_DC "asym;dc" +#define ADF_CFG_DC_ASYM "dc;asym" +#define ADF_CFG_SYM_DC "sym;dc" +#define ADF_CFG_DC_SYM "dc;sym" #define ADF_SERVICES_ENABLED "ServicesEnabled" +#define ADF_PM_IDLE_SUPPORT "PmIdleSupport" #define ADF_ETRMGR_COALESCING_ENABLED "InterruptCoalescingEnabled" #define ADF_ETRMGR_COALESCING_ENABLED_FORMAT \ ADF_ETRMGR_BANK "%d" ADF_ETRMGR_COALESCING_ENABLED diff --git a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h index db79759bee61..b8132eb9bc2a 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h +++ b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h @@ -187,7 +187,7 @@ void qat_uclo_del_obj(struct icp_qat_fw_loader_handle *handle); int qat_uclo_wr_mimage(struct icp_qat_fw_loader_handle *handle, void *addr_ptr, int mem_size); int qat_uclo_map_obj(struct icp_qat_fw_loader_handle *handle, - void *addr_ptr, u32 mem_size, char *obj_name); + void *addr_ptr, u32 mem_size, const char *obj_name); int qat_uclo_set_cfg_ae_mask(struct icp_qat_fw_loader_handle *handle, unsigned int cfg_ae_mask); int adf_init_misc_wq(void); diff --git a/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c b/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c new file mode 100644 index 000000000000..d0a2f892e6eb --- /dev/null +++ b/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2023 Intel Corporation */ + +#include <linux/debugfs.h> +#include "adf_accel_devices.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "adf_dbgfs.h" + +/** + * adf_dbgfs_init() - add persistent debugfs entries + * @accel_dev: Pointer to acceleration device. + * + * This function creates debugfs entries that are persistent through a device + * state change (from up to down or vice versa). + */ +void adf_dbgfs_init(struct adf_accel_dev *accel_dev) +{ + char name[ADF_DEVICE_NAME_LENGTH]; + void *ret; + + /* Create dev top level debugfs entry */ + snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX, + accel_dev->hw_device->dev_class->name, + pci_name(accel_dev->accel_pci_dev.pci_dev)); + + ret = debugfs_create_dir(name, NULL); + if (IS_ERR_OR_NULL(ret)) + return; + + accel_dev->debugfs_dir = ret; + + adf_cfg_dev_dbgfs_add(accel_dev); +} +EXPORT_SYMBOL_GPL(adf_dbgfs_init); + +/** + * adf_dbgfs_exit() - remove persistent debugfs entries + * @accel_dev: Pointer to acceleration device. + */ +void adf_dbgfs_exit(struct adf_accel_dev *accel_dev) +{ + adf_cfg_dev_dbgfs_rm(accel_dev); + debugfs_remove(accel_dev->debugfs_dir); +} +EXPORT_SYMBOL_GPL(adf_dbgfs_exit); + +/** + * adf_dbgfs_add() - add non-persistent debugfs entries + * @accel_dev: Pointer to acceleration device. + * + * This function creates debugfs entries that are not persistent through + * a device state change (from up to down or vice versa). + */ +void adf_dbgfs_add(struct adf_accel_dev *accel_dev) +{ + if (!accel_dev->debugfs_dir) + return; +} + +/** + * adf_dbgfs_rm() - remove non-persistent debugfs entries + * @accel_dev: Pointer to acceleration device. + */ +void adf_dbgfs_rm(struct adf_accel_dev *accel_dev) +{ + if (!accel_dev->debugfs_dir) + return; +} diff --git a/drivers/crypto/intel/qat/qat_common/adf_dbgfs.h b/drivers/crypto/intel/qat/qat_common/adf_dbgfs.h new file mode 100644 index 000000000000..e0cb2c2a2ed0 --- /dev/null +++ b/drivers/crypto/intel/qat/qat_common/adf_dbgfs.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright(c) 2023 Intel Corporation */ + +#ifndef ADF_DBGFS_H +#define ADF_DBGFS_H + +#ifdef CONFIG_DEBUG_FS +void adf_dbgfs_init(struct adf_accel_dev *accel_dev); +void adf_dbgfs_add(struct adf_accel_dev *accel_dev); +void adf_dbgfs_rm(struct adf_accel_dev *accel_dev); +void adf_dbgfs_exit(struct adf_accel_dev *accel_dev); +#else +static inline void adf_dbgfs_init(struct adf_accel_dev *accel_dev) +{ +} + +static inline void adf_dbgfs_add(struct adf_accel_dev *accel_dev) +{ +} + +static inline void adf_dbgfs_rm(struct adf_accel_dev *accel_dev) +{ +} + +static inline void adf_dbgfs_exit(struct adf_accel_dev *accel_dev) +{ +} +#endif +#endif diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.c b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.c index 7037c0892a8a..34c6cd8e27c0 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.c +++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.c @@ -23,15 +23,25 @@ struct adf_gen4_pm_data { static int send_host_msg(struct adf_accel_dev *accel_dev) { + char pm_idle_support_cfg[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {}; void __iomem *pmisc = adf_get_pmisc_base(accel_dev); + bool pm_idle_support; u32 msg; + int ret; msg = ADF_CSR_RD(pmisc, ADF_GEN4_PM_HOST_MSG); if (msg & ADF_GEN4_PM_MSG_PENDING) return -EBUSY; + adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, + ADF_PM_IDLE_SUPPORT, pm_idle_support_cfg); + ret = kstrtobool(pm_idle_support_cfg, &pm_idle_support); + if (ret) + pm_idle_support = true; + /* Send HOST_MSG */ - msg = FIELD_PREP(ADF_GEN4_PM_MSG_PAYLOAD_BIT_MASK, PM_SET_MIN); + msg = FIELD_PREP(ADF_GEN4_PM_MSG_PAYLOAD_BIT_MASK, + pm_idle_support ? PM_SET_MIN : PM_NO_CHANGE); msg |= ADF_GEN4_PM_MSG_PENDING; ADF_CSR_WR(pmisc, ADF_GEN4_PM_HOST_MSG, msg); diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h index f8f8a9ee29e5..dd112923e006 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h +++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h @@ -37,6 +37,7 @@ #define ADF_GEN4_PM_DEFAULT_IDLE_FILTER (0x0) #define ADF_GEN4_PM_MAX_IDLE_FILTER (0x7) +#define ADF_GEN4_PM_DEFAULT_IDLE_SUPPORT (0x1) int adf_gen4_enable_pm(struct adf_accel_dev *accel_dev); bool adf_gen4_handle_pm_interrupt(struct adf_accel_dev *accel_dev); diff --git a/drivers/crypto/intel/qat/qat_common/adf_init.c b/drivers/crypto/intel/qat/qat_common/adf_init.c index 0985f64ab11a..826179c98524 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_init.c +++ b/drivers/crypto/intel/qat/qat_common/adf_init.c @@ -7,6 +7,7 @@ #include "adf_accel_devices.h" #include "adf_cfg.h" #include "adf_common_drv.h" +#include "adf_dbgfs.h" static LIST_HEAD(service_table); static DEFINE_MUTEX(service_lock); @@ -216,6 +217,9 @@ static int adf_dev_start(struct adf_accel_dev *accel_dev) clear_bit(ADF_STATUS_STARTED, &accel_dev->status); return -EFAULT; } + + adf_dbgfs_add(accel_dev); + return 0; } @@ -240,6 +244,8 @@ static void adf_dev_stop(struct adf_accel_dev *accel_dev) !test_bit(ADF_STATUS_STARTING, &accel_dev->status)) return; + adf_dbgfs_rm(accel_dev); + clear_bit(ADF_STATUS_STARTING, &accel_dev->status); clear_bit(ADF_STATUS_STARTED, &accel_dev->status); diff --git a/drivers/crypto/intel/qat/qat_common/adf_sysfs.c b/drivers/crypto/intel/qat/qat_common/adf_sysfs.c index 3eb6611ab1b1..a74d2f930367 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_sysfs.c +++ b/drivers/crypto/intel/qat/qat_common/adf_sysfs.c @@ -78,6 +78,13 @@ static ssize_t state_store(struct device *dev, struct device_attribute *attr, static const char * const services_operations[] = { ADF_CFG_CY, ADF_CFG_DC, + ADF_CFG_SYM, + ADF_CFG_ASYM, + ADF_CFG_ASYM_SYM, + ADF_CFG_ASYM_DC, + ADF_CFG_DC_ASYM, + ADF_CFG_SYM_DC, + ADF_CFG_DC_SYM, }; static ssize_t cfg_services_show(struct device *dev, struct device_attribute *attr, @@ -145,12 +152,65 @@ static ssize_t cfg_services_store(struct device *dev, struct device_attribute *a return count; } +static ssize_t pm_idle_enabled_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + char pm_idle_enabled[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {}; + struct adf_accel_dev *accel_dev; + int ret; + + accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); + if (!accel_dev) + return -EINVAL; + + ret = adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, + ADF_PM_IDLE_SUPPORT, pm_idle_enabled); + if (ret) + return sysfs_emit(buf, "1\n"); + + return sysfs_emit(buf, "%s\n", pm_idle_enabled); +} + +static ssize_t pm_idle_enabled_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long pm_idle_enabled_cfg_val; + struct adf_accel_dev *accel_dev; + bool pm_idle_enabled; + int ret; + + ret = kstrtobool(buf, &pm_idle_enabled); + if (ret) + return ret; + + pm_idle_enabled_cfg_val = pm_idle_enabled; + accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); + if (!accel_dev) + return -EINVAL; + + if (adf_dev_started(accel_dev)) { + dev_info(dev, "Device qat_dev%d must be down to set pm_idle_enabled.\n", + accel_dev->accel_id); + return -EINVAL; + } + + ret = adf_cfg_add_key_value_param(accel_dev, ADF_GENERAL_SEC, + ADF_PM_IDLE_SUPPORT, &pm_idle_enabled_cfg_val, + ADF_DEC); + if (ret) + return ret; + + return count; +} +static DEVICE_ATTR_RW(pm_idle_enabled); + static DEVICE_ATTR_RW(state); static DEVICE_ATTR_RW(cfg_services); static struct attribute *qat_attrs[] = { &dev_attr_state.attr, &dev_attr_cfg_services.attr, + &dev_attr_pm_idle_enabled.attr, NULL, }; diff --git a/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h b/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h index 4042739bb6fa..a65059e56248 100644 --- a/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h +++ b/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h @@ -87,8 +87,7 @@ enum icp_qat_capabilities_mask { ICP_ACCEL_CAPABILITIES_AUTHENTICATION = BIT(3), ICP_ACCEL_CAPABILITIES_RESERVED_1 = BIT(4), ICP_ACCEL_CAPABILITIES_COMPRESSION = BIT(5), - ICP_ACCEL_CAPABILITIES_LZS_COMPRESSION = BIT(6), - ICP_ACCEL_CAPABILITIES_RAND = BIT(7), + /* Bits 6-7 are currently reserved */ ICP_ACCEL_CAPABILITIES_ZUC = BIT(8), ICP_ACCEL_CAPABILITIES_SHA3 = BIT(9), /* Bits 10-11 are currently reserved */ diff --git a/drivers/crypto/intel/qat/qat_common/qat_algs.c b/drivers/crypto/intel/qat/qat_common/qat_algs.c index 538dcbfbcd26..3c4bba4a8779 100644 --- a/drivers/crypto/intel/qat/qat_common/qat_algs.c +++ b/drivers/crypto/intel/qat/qat_common/qat_algs.c @@ -106,7 +106,6 @@ static int qat_get_inter_state_size(enum icp_qat_hw_auth_algo qat_hash_alg) default: return -EFAULT; } - return -EFAULT; } static int qat_alg_do_precomputes(struct icp_qat_hw_auth_algo_blk *hash, diff --git a/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c b/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c index 935a7e012946..4128200a9032 100644 --- a/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c +++ b/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c @@ -170,15 +170,14 @@ static void qat_dh_cb(struct icp_qat_fw_pke_resp *resp) } areq->dst_len = req->ctx.dh->p_size; + dma_unmap_single(dev, req->out.dh.r, req->ctx.dh->p_size, + DMA_FROM_DEVICE); if (req->dst_align) { scatterwalk_map_and_copy(req->dst_align, areq->dst, 0, areq->dst_len, 1); kfree_sensitive(req->dst_align); } - dma_unmap_single(dev, req->out.dh.r, req->ctx.dh->p_size, - DMA_FROM_DEVICE); - dma_unmap_single(dev, req->phy_in, sizeof(struct qat_dh_input_params), DMA_TO_DEVICE); dma_unmap_single(dev, req->phy_out, @@ -521,12 +520,14 @@ static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp) err = (err == ICP_QAT_FW_COMN_STATUS_FLAG_OK) ? 0 : -EINVAL; - kfree_sensitive(req->src_align); - dma_unmap_single(dev, req->in.rsa.enc.m, req->ctx.rsa->key_sz, DMA_TO_DEVICE); + kfree_sensitive(req->src_align); + areq->dst_len = req->ctx.rsa->key_sz; + dma_unmap_single(dev, req->out.rsa.enc.c, req->ctx.rsa->key_sz, + DMA_FROM_DEVICE); if (req->dst_align) { scatterwalk_map_and_copy(req->dst_align, areq->dst, 0, areq->dst_len, 1); @@ -534,9 +535,6 @@ static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp) kfree_sensitive(req->dst_align); } - dma_unmap_single(dev, req->out.rsa.enc.c, req->ctx.rsa->key_sz, - DMA_FROM_DEVICE); - dma_unmap_single(dev, req->phy_in, sizeof(struct qat_rsa_input_params), DMA_TO_DEVICE); dma_unmap_single(dev, req->phy_out, diff --git a/drivers/crypto/intel/qat/qat_common/qat_uclo.c b/drivers/crypto/intel/qat/qat_common/qat_uclo.c index 3ba8ca20b3d7..ce837bcc1cab 100644 --- a/drivers/crypto/intel/qat/qat_common/qat_uclo.c +++ b/drivers/crypto/intel/qat/qat_common/qat_uclo.c @@ -1685,7 +1685,7 @@ static void qat_uclo_del_mof(struct icp_qat_fw_loader_handle *handle) } static int qat_uclo_seek_obj_inside_mof(struct icp_qat_mof_handle *mobj_handle, - char *obj_name, char **obj_ptr, + const char *obj_name, char **obj_ptr, unsigned int *obj_size) { struct icp_qat_mof_objhdr *obj_hdr = mobj_handle->obj_table.obj_hdr; @@ -1837,8 +1837,8 @@ static int qat_uclo_check_mof_format(struct icp_qat_mof_file_hdr *mof_hdr) static int qat_uclo_map_mof_obj(struct icp_qat_fw_loader_handle *handle, struct icp_qat_mof_file_hdr *mof_ptr, - u32 mof_size, char *obj_name, char **obj_ptr, - unsigned int *obj_size) + u32 mof_size, const char *obj_name, + char **obj_ptr, unsigned int *obj_size) { struct icp_qat_mof_chunkhdr *mof_chunkhdr; unsigned int file_id = mof_ptr->file_id; @@ -1888,7 +1888,7 @@ static int qat_uclo_map_mof_obj(struct icp_qat_fw_loader_handle *handle, } int qat_uclo_map_obj(struct icp_qat_fw_loader_handle *handle, - void *addr_ptr, u32 mem_size, char *obj_name) + void *addr_ptr, u32 mem_size, const char *obj_name) { char *obj_addr; u32 obj_size; diff --git a/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c b/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c index e18860ab5c8e..1e748e8ce12d 100644 --- a/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c @@ -16,6 +16,7 @@ #include <adf_accel_devices.h> #include <adf_common_drv.h> #include <adf_cfg.h> +#include <adf_dbgfs.h> #include "adf_dh895xcc_hw_data.h" static const struct pci_device_id adf_pci_tbl[] = { @@ -65,8 +66,8 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev) kfree(accel_dev->hw_device); accel_dev->hw_device = NULL; } + adf_dbgfs_exit(accel_dev); adf_cfg_dev_remove(accel_dev); - debugfs_remove(accel_dev->debugfs_dir); adf_devmgr_rm_dev(accel_dev, NULL); } @@ -75,7 +76,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct adf_accel_dev *accel_dev; struct adf_accel_pci *accel_pci_dev; struct adf_hw_device_data *hw_data; - char name[ADF_DEVICE_NAME_LENGTH]; unsigned int i, bar_nr; unsigned long bar_mask; int ret; @@ -140,12 +140,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_err; } - /* Create dev top level debugfs entry */ - snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX, - hw_data->dev_class->name, pci_name(pdev)); - - accel_dev->debugfs_dir = debugfs_create_dir(name, NULL); - /* Create device configuration table */ ret = adf_cfg_dev_add(accel_dev); if (ret) @@ -199,6 +193,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_err_free_reg; } + adf_dbgfs_init(accel_dev); + ret = adf_dev_up(accel_dev, true); if (ret) goto out_err_dev_stop; diff --git a/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c b/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c index 96854a1cd87e..fefb85ceaeb9 100644 --- a/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c @@ -16,6 +16,7 @@ #include <adf_accel_devices.h> #include <adf_common_drv.h> #include <adf_cfg.h> +#include <adf_dbgfs.h> #include "adf_dh895xccvf_hw_data.h" static const struct pci_device_id adf_pci_tbl[] = { @@ -64,8 +65,8 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev) kfree(accel_dev->hw_device); accel_dev->hw_device = NULL; } + adf_dbgfs_exit(accel_dev); adf_cfg_dev_remove(accel_dev); - debugfs_remove(accel_dev->debugfs_dir); pf = adf_devmgr_pci_to_accel_dev(accel_pci_dev->pci_dev->physfn); adf_devmgr_rm_dev(accel_dev, pf); } @@ -76,7 +77,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct adf_accel_dev *pf; struct adf_accel_pci *accel_pci_dev; struct adf_hw_device_data *hw_data; - char name[ADF_DEVICE_NAME_LENGTH]; unsigned int i, bar_nr; unsigned long bar_mask; int ret; @@ -123,12 +123,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw_data->ae_mask = hw_data->get_ae_mask(hw_data); accel_pci_dev->sku = hw_data->get_sku(hw_data); - /* Create dev top level debugfs entry */ - snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX, - hw_data->dev_class->name, pci_name(pdev)); - - accel_dev->debugfs_dir = debugfs_create_dir(name, NULL); - /* Create device configuration table */ ret = adf_cfg_dev_add(accel_dev); if (ret) @@ -173,6 +167,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Completion for VF2PF request/response message exchange */ init_completion(&accel_dev->vf.msg_received); + adf_dbgfs_init(accel_dev); + ret = adf_dev_up(accel_dev, false); if (ret) goto out_err_dev_stop; diff --git a/drivers/crypto/marvell/cesa/cipher.c b/drivers/crypto/marvell/cesa/cipher.c index c6f2fa753b7c..0f37dfd42d85 100644 --- a/drivers/crypto/marvell/cesa/cipher.c +++ b/drivers/crypto/marvell/cesa/cipher.c @@ -297,7 +297,7 @@ static int mv_cesa_des_setkey(struct crypto_skcipher *cipher, const u8 *key, static int mv_cesa_des3_ede_setkey(struct crypto_skcipher *cipher, const u8 *key, unsigned int len) { - struct mv_cesa_des_ctx *ctx = crypto_skcipher_ctx(cipher); + struct mv_cesa_des3_ctx *ctx = crypto_skcipher_ctx(cipher); int err; err = verify_skcipher_des3_key(cipher, key); diff --git a/drivers/crypto/marvell/octeontx2/otx2_cpt_common.h b/drivers/crypto/marvell/octeontx2/otx2_cpt_common.h index 6019066a6451..46b778bbbee4 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cpt_common.h +++ b/drivers/crypto/marvell/octeontx2/otx2_cpt_common.h @@ -40,11 +40,26 @@ enum otx2_cpt_eng_type { }; /* Take mbox id from end of CPT mbox range in AF (range 0xA00 - 0xBFF) */ +#define MBOX_MSG_RX_INLINE_IPSEC_LF_CFG 0xBFE #define MBOX_MSG_GET_ENG_GRP_NUM 0xBFF #define MBOX_MSG_GET_CAPS 0xBFD #define MBOX_MSG_GET_KVF_LIMITS 0xBFC /* + * Message request to config cpt lf for inline inbound ipsec. + * This message is only used between CPT PF <-> CPT VF + */ +struct otx2_cpt_rx_inline_lf_cfg { + struct mbox_msghdr hdr; + u16 sso_pf_func; + u16 param1; + u16 param2; + u16 opcode; + u32 credit; + u32 reserved; +}; + +/* * Message request and response to get engine group number * which has attached a given type of engines (SE, AE, IE) * This messages are only used between CPT PF <=> CPT VF diff --git a/drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c b/drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c index 115997475beb..273ee5352a50 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c @@ -141,6 +141,8 @@ int otx2_cpt_attach_rscrs_msg(struct otx2_cptlfs_info *lfs) req->hdr.sig = OTX2_MBOX_REQ_SIG; req->hdr.pcifunc = 0; req->cptlfs = lfs->lfs_num; + req->cpt_blkaddr = lfs->blkaddr; + req->modify = 1; ret = otx2_cpt_send_mbox_msg(mbox, lfs->pdev); if (ret) return ret; @@ -168,6 +170,7 @@ int otx2_cpt_detach_rsrcs_msg(struct otx2_cptlfs_info *lfs) req->hdr.id = MBOX_MSG_DETACH_RESOURCES; req->hdr.sig = OTX2_MBOX_REQ_SIG; req->hdr.pcifunc = 0; + req->cptlfs = 1; ret = otx2_cpt_send_mbox_msg(mbox, lfs->pdev); if (ret) return ret; diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptlf.c b/drivers/crypto/marvell/octeontx2/otx2_cptlf.c index 71e5f79431af..6edd27ff8c4e 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptlf.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cptlf.c @@ -13,10 +13,10 @@ static void cptlf_do_set_done_time_wait(struct otx2_cptlf_info *lf, { union otx2_cptx_lf_done_wait done_wait; - done_wait.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, - OTX2_CPT_LF_DONE_WAIT); + done_wait.u = otx2_cpt_read64(lf->lfs->reg_base, lf->lfs->blkaddr, + lf->slot, OTX2_CPT_LF_DONE_WAIT); done_wait.s.time_wait = time_wait; - otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot, OTX2_CPT_LF_DONE_WAIT, done_wait.u); } @@ -24,10 +24,10 @@ static void cptlf_do_set_done_num_wait(struct otx2_cptlf_info *lf, int num_wait) { union otx2_cptx_lf_done_wait done_wait; - done_wait.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, - OTX2_CPT_LF_DONE_WAIT); + done_wait.u = otx2_cpt_read64(lf->lfs->reg_base, lf->lfs->blkaddr, + lf->slot, OTX2_CPT_LF_DONE_WAIT); done_wait.s.num_wait = num_wait; - otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot, OTX2_CPT_LF_DONE_WAIT, done_wait.u); } @@ -147,7 +147,7 @@ static void cptlf_set_misc_intrs(struct otx2_cptlfs_info *lfs, u8 enable) irq_misc.s.nwrp = 0x1; for (slot = 0; slot < lfs->lfs_num; slot++) - otx2_cpt_write64(lfs->reg_base, BLKADDR_CPT0, slot, reg, + otx2_cpt_write64(lfs->reg_base, lfs->blkaddr, slot, reg, irq_misc.u); } @@ -157,7 +157,7 @@ static void cptlf_enable_intrs(struct otx2_cptlfs_info *lfs) /* Enable done interrupts */ for (slot = 0; slot < lfs->lfs_num; slot++) - otx2_cpt_write64(lfs->reg_base, BLKADDR_CPT0, slot, + otx2_cpt_write64(lfs->reg_base, lfs->blkaddr, slot, OTX2_CPT_LF_DONE_INT_ENA_W1S, 0x1); /* Enable Misc interrupts */ cptlf_set_misc_intrs(lfs, true); @@ -168,7 +168,7 @@ static void cptlf_disable_intrs(struct otx2_cptlfs_info *lfs) int slot; for (slot = 0; slot < lfs->lfs_num; slot++) - otx2_cpt_write64(lfs->reg_base, BLKADDR_CPT0, slot, + otx2_cpt_write64(lfs->reg_base, lfs->blkaddr, slot, OTX2_CPT_LF_DONE_INT_ENA_W1C, 0x1); cptlf_set_misc_intrs(lfs, false); } @@ -177,7 +177,7 @@ static inline int cptlf_read_done_cnt(struct otx2_cptlf_info *lf) { union otx2_cptx_lf_done irq_cnt; - irq_cnt.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + irq_cnt.u = otx2_cpt_read64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot, OTX2_CPT_LF_DONE); return irq_cnt.s.done; } @@ -189,8 +189,8 @@ static irqreturn_t cptlf_misc_intr_handler(int __always_unused irq, void *arg) struct device *dev; dev = &lf->lfs->pdev->dev; - irq_misc.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, - OTX2_CPT_LF_MISC_INT); + irq_misc.u = otx2_cpt_read64(lf->lfs->reg_base, lf->lfs->blkaddr, + lf->slot, OTX2_CPT_LF_MISC_INT); irq_misc_ack.u = 0x0; if (irq_misc.s.fault) { @@ -222,7 +222,7 @@ static irqreturn_t cptlf_misc_intr_handler(int __always_unused irq, void *arg) } /* Acknowledge interrupts */ - otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot, OTX2_CPT_LF_MISC_INT, irq_misc_ack.u); return IRQ_HANDLED; @@ -237,13 +237,13 @@ static irqreturn_t cptlf_done_intr_handler(int irq, void *arg) /* Read the number of completed requests */ irq_cnt = cptlf_read_done_cnt(lf); if (irq_cnt) { - done_wait.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0, + done_wait.u = otx2_cpt_read64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot, OTX2_CPT_LF_DONE_WAIT); /* Acknowledge the number of completed requests */ - otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot, OTX2_CPT_LF_DONE_ACK, irq_cnt); - otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot, OTX2_CPT_LF_DONE_WAIT, done_wait.u); if (unlikely(!lf->wqe)) { dev_err(&lf->lfs->pdev->dev, "No work for LF %d\n", @@ -393,7 +393,7 @@ int otx2_cptlf_init(struct otx2_cptlfs_info *lfs, u8 eng_grp_mask, int pri, OTX2_CPT_LMT_LF_LMTLINEX(0)); lfs->lf[slot].ioreg = lfs->reg_base + - OTX2_CPT_RVU_FUNC_ADDR_S(BLKADDR_CPT0, slot, + OTX2_CPT_RVU_FUNC_ADDR_S(lfs->blkaddr, slot, OTX2_CPT_LF_NQX(0)); } /* Send request to attach LFs */ diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptlf.h b/drivers/crypto/marvell/octeontx2/otx2_cptlf.h index 4fcaf61a70e3..5302fe3d0e6f 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptlf.h +++ b/drivers/crypto/marvell/octeontx2/otx2_cptlf.h @@ -180,7 +180,7 @@ static inline void otx2_cptlf_set_iqueues_base_addr( for (slot = 0; slot < lfs->lfs_num; slot++) { lf_q_base.u = lfs->lf[slot].iqueue.dma_addr; - otx2_cpt_write64(lfs->reg_base, BLKADDR_CPT0, slot, + otx2_cpt_write64(lfs->reg_base, lfs->blkaddr, slot, OTX2_CPT_LF_Q_BASE, lf_q_base.u); } } @@ -191,7 +191,7 @@ static inline void otx2_cptlf_do_set_iqueue_size(struct otx2_cptlf_info *lf) lf_q_size.s.size_div40 = OTX2_CPT_SIZE_DIV40 + OTX2_CPT_EXTRA_SIZE_DIV40; - otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot, OTX2_CPT_LF_Q_SIZE, lf_q_size.u); } @@ -207,15 +207,16 @@ static inline void otx2_cptlf_do_disable_iqueue(struct otx2_cptlf_info *lf) { union otx2_cptx_lf_ctl lf_ctl = { .u = 0x0 }; union otx2_cptx_lf_inprog lf_inprog; + u8 blkaddr = lf->lfs->blkaddr; int timeout = 20; /* Disable instructions enqueuing */ - otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + otx2_cpt_write64(lf->lfs->reg_base, blkaddr, lf->slot, OTX2_CPT_LF_CTL, lf_ctl.u); /* Wait for instruction queue to become empty */ do { - lf_inprog.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0, + lf_inprog.u = otx2_cpt_read64(lf->lfs->reg_base, blkaddr, lf->slot, OTX2_CPT_LF_INPROG); if (!lf_inprog.s.inflight) break; @@ -234,7 +235,7 @@ static inline void otx2_cptlf_do_disable_iqueue(struct otx2_cptlf_info *lf) * the queue should be empty at this point */ lf_inprog.s.eena = 0x0; - otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + otx2_cpt_write64(lf->lfs->reg_base, blkaddr, lf->slot, OTX2_CPT_LF_INPROG, lf_inprog.u); } @@ -249,14 +250,15 @@ static inline void otx2_cptlf_disable_iqueues(struct otx2_cptlfs_info *lfs) static inline void otx2_cptlf_set_iqueue_enq(struct otx2_cptlf_info *lf, bool enable) { + u8 blkaddr = lf->lfs->blkaddr; union otx2_cptx_lf_ctl lf_ctl; - lf_ctl.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + lf_ctl.u = otx2_cpt_read64(lf->lfs->reg_base, blkaddr, lf->slot, OTX2_CPT_LF_CTL); /* Set iqueue's enqueuing */ lf_ctl.s.ena = enable ? 0x1 : 0x0; - otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + otx2_cpt_write64(lf->lfs->reg_base, blkaddr, lf->slot, OTX2_CPT_LF_CTL, lf_ctl.u); } @@ -269,13 +271,14 @@ static inline void otx2_cptlf_set_iqueue_exec(struct otx2_cptlf_info *lf, bool enable) { union otx2_cptx_lf_inprog lf_inprog; + u8 blkaddr = lf->lfs->blkaddr; - lf_inprog.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + lf_inprog.u = otx2_cpt_read64(lf->lfs->reg_base, blkaddr, lf->slot, OTX2_CPT_LF_INPROG); /* Set iqueue's execution */ lf_inprog.s.eena = enable ? 0x1 : 0x0; - otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + otx2_cpt_write64(lf->lfs->reg_base, blkaddr, lf->slot, OTX2_CPT_LF_INPROG, lf_inprog.u); } @@ -364,6 +367,18 @@ static inline bool otx2_cptlf_started(struct otx2_cptlfs_info *lfs) return atomic_read(&lfs->state) == OTX2_CPTLF_STARTED; } +static inline void otx2_cptlf_set_dev_info(struct otx2_cptlfs_info *lfs, + struct pci_dev *pdev, + void __iomem *reg_base, + struct otx2_mbox *mbox, + int blkaddr) +{ + lfs->pdev = pdev; + lfs->reg_base = reg_base; + lfs->mbox = mbox; + lfs->blkaddr = blkaddr; +} + int otx2_cptlf_init(struct otx2_cptlfs_info *lfs, u8 eng_grp_msk, int pri, int lfs_num); void otx2_cptlf_shutdown(struct otx2_cptlfs_info *lfs); diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf.h b/drivers/crypto/marvell/octeontx2/otx2_cptpf.h index 936174b012e8..a209ec5af381 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptpf.h +++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf.h @@ -31,6 +31,7 @@ struct otx2_cptpf_dev { struct otx2_cptvf_info vf[OTX2_CPT_MAX_VFS_NUM]; struct otx2_cpt_eng_grps eng_grps;/* Engine groups information */ struct otx2_cptlfs_info lfs; /* CPT LFs attached to this PF */ + struct otx2_cptlfs_info cpt1_lfs; /* CPT1 LFs attached to this PF */ /* HW capabilities for each engine type */ union otx2_cpt_eng_caps eng_caps[OTX2_CPT_MAX_ENG_TYPES]; bool is_eng_caps_discovered; @@ -40,6 +41,9 @@ struct otx2_cptpf_dev { struct work_struct afpf_mbox_work; struct workqueue_struct *afpf_mbox_wq; + struct otx2_mbox afpf_mbox_up; + struct work_struct afpf_mbox_up_work; + /* VF <=> PF mbox */ struct otx2_mbox vfpf_mbox; struct workqueue_struct *vfpf_mbox_wq; @@ -52,8 +56,10 @@ struct otx2_cptpf_dev { u8 pf_id; /* RVU PF number */ u8 max_vfs; /* Maximum number of VFs supported by CPT */ u8 enabled_vfs; /* Number of enabled VFs */ + u8 sso_pf_func_ovrd; /* SSO PF_FUNC override bit */ u8 kvf_limits; /* Kernel crypto limits */ bool has_cpt1; + u8 rsrc_req_blkaddr; /* Devlink */ struct devlink *dl; @@ -61,6 +67,7 @@ struct otx2_cptpf_dev { irqreturn_t otx2_cptpf_afpf_mbox_intr(int irq, void *arg); void otx2_cptpf_afpf_mbox_handler(struct work_struct *work); +void otx2_cptpf_afpf_mbox_up_handler(struct work_struct *work); irqreturn_t otx2_cptpf_vfpf_mbox_intr(int irq, void *arg); void otx2_cptpf_vfpf_mbox_handler(struct work_struct *work); diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c b/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c index 30e6acfc93d9..e34223daa327 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c @@ -13,6 +13,8 @@ #define OTX2_CPT_DRV_NAME "rvu_cptpf" #define OTX2_CPT_DRV_STRING "Marvell RVU CPT Physical Function Driver" +#define CPT_UC_RID_CN9K_B0 1 + static void cptpf_enable_vfpf_mbox_intr(struct otx2_cptpf_dev *cptpf, int num_vfs) { @@ -473,10 +475,19 @@ static int cptpf_afpf_mbox_init(struct otx2_cptpf_dev *cptpf) if (err) goto error; + err = otx2_mbox_init(&cptpf->afpf_mbox_up, cptpf->afpf_mbox_base, + pdev, cptpf->reg_base, MBOX_DIR_PFAF_UP, 1); + if (err) + goto mbox_cleanup; + INIT_WORK(&cptpf->afpf_mbox_work, otx2_cptpf_afpf_mbox_handler); + INIT_WORK(&cptpf->afpf_mbox_up_work, otx2_cptpf_afpf_mbox_up_handler); mutex_init(&cptpf->lock); + return 0; +mbox_cleanup: + otx2_mbox_destroy(&cptpf->afpf_mbox); error: destroy_workqueue(cptpf->afpf_mbox_wq); return err; @@ -486,6 +497,33 @@ static void cptpf_afpf_mbox_destroy(struct otx2_cptpf_dev *cptpf) { destroy_workqueue(cptpf->afpf_mbox_wq); otx2_mbox_destroy(&cptpf->afpf_mbox); + otx2_mbox_destroy(&cptpf->afpf_mbox_up); +} + +static ssize_t sso_pf_func_ovrd_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct otx2_cptpf_dev *cptpf = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", cptpf->sso_pf_func_ovrd); +} + +static ssize_t sso_pf_func_ovrd_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct otx2_cptpf_dev *cptpf = dev_get_drvdata(dev); + u8 sso_pf_func_ovrd; + + if (!(cptpf->pdev->revision == CPT_UC_RID_CN9K_B0)) + return count; + + if (kstrtou8(buf, 0, &sso_pf_func_ovrd)) + return -EINVAL; + + cptpf->sso_pf_func_ovrd = sso_pf_func_ovrd; + + return count; } static ssize_t kvf_limits_show(struct device *dev, @@ -518,8 +556,11 @@ static ssize_t kvf_limits_store(struct device *dev, } static DEVICE_ATTR_RW(kvf_limits); +static DEVICE_ATTR_RW(sso_pf_func_ovrd); + static struct attribute *cptpf_attrs[] = { &dev_attr_kvf_limits.attr, + &dev_attr_sso_pf_func_ovrd.attr, NULL }; diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c b/drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c index dee0aa60b698..480b3720f15a 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c @@ -5,6 +5,20 @@ #include "otx2_cptpf.h" #include "rvu_reg.h" +/* Fastpath ipsec opcode with inplace processing */ +#define CPT_INLINE_RX_OPCODE (0x26 | (1 << 6)) +#define CN10K_CPT_INLINE_RX_OPCODE (0x29 | (1 << 6)) + +#define cpt_inline_rx_opcode(pdev) \ +({ \ + u8 opcode; \ + if (is_dev_otx2(pdev)) \ + opcode = CPT_INLINE_RX_OPCODE; \ + else \ + opcode = CN10K_CPT_INLINE_RX_OPCODE; \ + (opcode); \ +}) + /* * CPT PF driver version, It will be incremented by 1 for every feature * addition in CPT mailbox messages. @@ -112,6 +126,139 @@ static int handle_msg_kvf_limits(struct otx2_cptpf_dev *cptpf, return 0; } +static int send_inline_ipsec_inbound_msg(struct otx2_cptpf_dev *cptpf, + int sso_pf_func, u8 slot) +{ + struct cpt_inline_ipsec_cfg_msg *req; + struct pci_dev *pdev = cptpf->pdev; + + req = (struct cpt_inline_ipsec_cfg_msg *) + otx2_mbox_alloc_msg_rsp(&cptpf->afpf_mbox, 0, + sizeof(*req), sizeof(struct msg_rsp)); + if (req == NULL) { + dev_err(&pdev->dev, "RVU MBOX failed to get message.\n"); + return -EFAULT; + } + memset(req, 0, sizeof(*req)); + req->hdr.id = MBOX_MSG_CPT_INLINE_IPSEC_CFG; + req->hdr.sig = OTX2_MBOX_REQ_SIG; + req->hdr.pcifunc = OTX2_CPT_RVU_PFFUNC(cptpf->pf_id, 0); + req->dir = CPT_INLINE_INBOUND; + req->slot = slot; + req->sso_pf_func_ovrd = cptpf->sso_pf_func_ovrd; + req->sso_pf_func = sso_pf_func; + req->enable = 1; + + return otx2_cpt_send_mbox_msg(&cptpf->afpf_mbox, pdev); +} + +static int rx_inline_ipsec_lf_cfg(struct otx2_cptpf_dev *cptpf, u8 egrp, + struct otx2_cpt_rx_inline_lf_cfg *req) +{ + struct nix_inline_ipsec_cfg *nix_req; + struct pci_dev *pdev = cptpf->pdev; + int ret; + + nix_req = (struct nix_inline_ipsec_cfg *) + otx2_mbox_alloc_msg_rsp(&cptpf->afpf_mbox, 0, + sizeof(*nix_req), + sizeof(struct msg_rsp)); + if (nix_req == NULL) { + dev_err(&pdev->dev, "RVU MBOX failed to get message.\n"); + return -EFAULT; + } + memset(nix_req, 0, sizeof(*nix_req)); + nix_req->hdr.id = MBOX_MSG_NIX_INLINE_IPSEC_CFG; + nix_req->hdr.sig = OTX2_MBOX_REQ_SIG; + nix_req->enable = 1; + if (!req->credit || req->credit > OTX2_CPT_INST_QLEN_MSGS) + nix_req->cpt_credit = OTX2_CPT_INST_QLEN_MSGS - 1; + else + nix_req->cpt_credit = req->credit - 1; + nix_req->gen_cfg.egrp = egrp; + if (req->opcode) + nix_req->gen_cfg.opcode = req->opcode; + else + nix_req->gen_cfg.opcode = cpt_inline_rx_opcode(pdev); + nix_req->gen_cfg.param1 = req->param1; + nix_req->gen_cfg.param2 = req->param2; + nix_req->inst_qsel.cpt_pf_func = OTX2_CPT_RVU_PFFUNC(cptpf->pf_id, 0); + nix_req->inst_qsel.cpt_slot = 0; + ret = otx2_cpt_send_mbox_msg(&cptpf->afpf_mbox, pdev); + if (ret) + return ret; + + if (cptpf->has_cpt1) { + ret = send_inline_ipsec_inbound_msg(cptpf, req->sso_pf_func, 1); + if (ret) + return ret; + } + + return send_inline_ipsec_inbound_msg(cptpf, req->sso_pf_func, 0); +} + +static int handle_msg_rx_inline_ipsec_lf_cfg(struct otx2_cptpf_dev *cptpf, + struct mbox_msghdr *req) +{ + struct otx2_cpt_rx_inline_lf_cfg *cfg_req; + u8 egrp; + int ret; + + cfg_req = (struct otx2_cpt_rx_inline_lf_cfg *)req; + if (cptpf->lfs.lfs_num) { + dev_err(&cptpf->pdev->dev, + "LF is already configured for RX inline ipsec.\n"); + return -EEXIST; + } + /* + * Allow LFs to execute requests destined to only grp IE_TYPES and + * set queue priority of each LF to high + */ + egrp = otx2_cpt_get_eng_grp(&cptpf->eng_grps, OTX2_CPT_IE_TYPES); + if (egrp == OTX2_CPT_INVALID_CRYPTO_ENG_GRP) { + dev_err(&cptpf->pdev->dev, + "Engine group for inline ipsec is not available\n"); + return -ENOENT; + } + + otx2_cptlf_set_dev_info(&cptpf->lfs, cptpf->pdev, cptpf->reg_base, + &cptpf->afpf_mbox, BLKADDR_CPT0); + ret = otx2_cptlf_init(&cptpf->lfs, 1 << egrp, OTX2_CPT_QUEUE_HI_PRIO, + 1); + if (ret) { + dev_err(&cptpf->pdev->dev, + "LF configuration failed for RX inline ipsec.\n"); + return ret; + } + + if (cptpf->has_cpt1) { + cptpf->rsrc_req_blkaddr = BLKADDR_CPT1; + otx2_cptlf_set_dev_info(&cptpf->cpt1_lfs, cptpf->pdev, + cptpf->reg_base, &cptpf->afpf_mbox, + BLKADDR_CPT1); + ret = otx2_cptlf_init(&cptpf->cpt1_lfs, 1 << egrp, + OTX2_CPT_QUEUE_HI_PRIO, 1); + if (ret) { + dev_err(&cptpf->pdev->dev, + "LF configuration failed for RX inline ipsec.\n"); + goto lf_cleanup; + } + cptpf->rsrc_req_blkaddr = 0; + } + + ret = rx_inline_ipsec_lf_cfg(cptpf, egrp, cfg_req); + if (ret) + goto lf1_cleanup; + + return 0; + +lf1_cleanup: + otx2_cptlf_shutdown(&cptpf->cpt1_lfs); +lf_cleanup: + otx2_cptlf_shutdown(&cptpf->lfs); + return ret; +} + static int cptpf_handle_vf_req(struct otx2_cptpf_dev *cptpf, struct otx2_cptvf_info *vf, struct mbox_msghdr *req, int size) @@ -132,6 +279,10 @@ static int cptpf_handle_vf_req(struct otx2_cptpf_dev *cptpf, case MBOX_MSG_GET_KVF_LIMITS: err = handle_msg_kvf_limits(cptpf, vf, req); break; + case MBOX_MSG_RX_INLINE_IPSEC_LF_CFG: + err = handle_msg_rx_inline_ipsec_lf_cfg(cptpf, req); + break; + default: err = forward_to_af(cptpf, vf, req, size); break; @@ -224,14 +375,28 @@ void otx2_cptpf_vfpf_mbox_handler(struct work_struct *work) irqreturn_t otx2_cptpf_afpf_mbox_intr(int __always_unused irq, void *arg) { struct otx2_cptpf_dev *cptpf = arg; + struct otx2_mbox_dev *mdev; + struct otx2_mbox *mbox; + struct mbox_hdr *hdr; u64 intr; /* Read the interrupt bits */ intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT); if (intr & 0x1ULL) { - /* Schedule work queue function to process the MBOX request */ - queue_work(cptpf->afpf_mbox_wq, &cptpf->afpf_mbox_work); + mbox = &cptpf->afpf_mbox; + mdev = &mbox->dev[0]; + hdr = mdev->mbase + mbox->rx_start; + if (hdr->num_msgs) + /* Schedule work queue function to process the MBOX request */ + queue_work(cptpf->afpf_mbox_wq, &cptpf->afpf_mbox_work); + + mbox = &cptpf->afpf_mbox_up; + mdev = &mbox->dev[0]; + hdr = mdev->mbase + mbox->rx_start; + if (hdr->num_msgs) + /* Schedule work queue function to process the MBOX request */ + queue_work(cptpf->afpf_mbox_wq, &cptpf->afpf_mbox_up_work); /* Clear and ack the interrupt */ otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT, 0x1ULL); @@ -242,6 +407,7 @@ irqreturn_t otx2_cptpf_afpf_mbox_intr(int __always_unused irq, void *arg) static void process_afpf_mbox_msg(struct otx2_cptpf_dev *cptpf, struct mbox_msghdr *msg) { + struct otx2_cptlfs_info *lfs = &cptpf->lfs; struct device *dev = &cptpf->pdev->dev; struct cpt_rd_wr_reg_msg *rsp_rd_wr; @@ -254,6 +420,8 @@ static void process_afpf_mbox_msg(struct otx2_cptpf_dev *cptpf, msg->sig, msg->id); return; } + if (cptpf->rsrc_req_blkaddr == BLKADDR_CPT1) + lfs = &cptpf->cpt1_lfs; switch (msg->id) { case MBOX_MSG_READY: @@ -273,11 +441,14 @@ static void process_afpf_mbox_msg(struct otx2_cptpf_dev *cptpf, break; case MBOX_MSG_ATTACH_RESOURCES: if (!msg->rc) - cptpf->lfs.are_lfs_attached = 1; + lfs->are_lfs_attached = 1; break; case MBOX_MSG_DETACH_RESOURCES: if (!msg->rc) - cptpf->lfs.are_lfs_attached = 0; + lfs->are_lfs_attached = 0; + break; + case MBOX_MSG_CPT_INLINE_IPSEC_CFG: + case MBOX_MSG_NIX_INLINE_IPSEC_CFG: break; default: @@ -367,3 +538,71 @@ void otx2_cptpf_afpf_mbox_handler(struct work_struct *work) } otx2_mbox_reset(afpf_mbox, 0); } + +static void handle_msg_cpt_inst_lmtst(struct otx2_cptpf_dev *cptpf, + struct mbox_msghdr *msg) +{ + struct cpt_inst_lmtst_req *req = (struct cpt_inst_lmtst_req *)msg; + struct otx2_cptlfs_info *lfs = &cptpf->lfs; + struct msg_rsp *rsp; + + if (cptpf->lfs.lfs_num) + lfs->ops->send_cmd((union otx2_cpt_inst_s *)req->inst, 1, + &lfs->lf[0]); + + rsp = (struct msg_rsp *)otx2_mbox_alloc_msg(&cptpf->afpf_mbox_up, 0, + sizeof(*rsp)); + if (!rsp) + return; + + rsp->hdr.id = msg->id; + rsp->hdr.sig = OTX2_MBOX_RSP_SIG; + rsp->hdr.pcifunc = 0; + rsp->hdr.rc = 0; +} + +static void process_afpf_mbox_up_msg(struct otx2_cptpf_dev *cptpf, + struct mbox_msghdr *msg) +{ + if (msg->id >= MBOX_MSG_MAX) { + dev_err(&cptpf->pdev->dev, + "MBOX msg with unknown ID %d\n", msg->id); + return; + } + + switch (msg->id) { + case MBOX_MSG_CPT_INST_LMTST: + handle_msg_cpt_inst_lmtst(cptpf, msg); + break; + default: + otx2_reply_invalid_msg(&cptpf->afpf_mbox_up, 0, 0, msg->id); + } +} + +void otx2_cptpf_afpf_mbox_up_handler(struct work_struct *work) +{ + struct otx2_cptpf_dev *cptpf; + struct otx2_mbox_dev *mdev; + struct mbox_hdr *rsp_hdr; + struct mbox_msghdr *msg; + struct otx2_mbox *mbox; + int offset, i; + + cptpf = container_of(work, struct otx2_cptpf_dev, afpf_mbox_up_work); + mbox = &cptpf->afpf_mbox_up; + mdev = &mbox->dev[0]; + /* Sync mbox data into memory */ + smp_wmb(); + + rsp_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start); + offset = mbox->rx_start + ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN); + + for (i = 0; i < rsp_hdr->num_msgs; i++) { + msg = (struct mbox_msghdr *)(mdev->mbase + offset); + + process_afpf_mbox_up_msg(cptpf, msg); + + offset = mbox->rx_start + msg->next_msgoff; + } + otx2_mbox_msg_send(mbox, 0); +} diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c b/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c index 1577986677f6..1958b797a421 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c @@ -1504,11 +1504,9 @@ int otx2_cpt_discover_eng_capabilities(struct otx2_cptpf_dev *cptpf) if (ret) goto delete_grps; - lfs->pdev = pdev; - lfs->reg_base = cptpf->reg_base; - lfs->mbox = &cptpf->afpf_mbox; - lfs->blkaddr = BLKADDR_CPT0; - ret = otx2_cptlf_init(&cptpf->lfs, OTX2_CPT_ALL_ENG_GRPS_MASK, + otx2_cptlf_set_dev_info(lfs, cptpf->pdev, cptpf->reg_base, + &cptpf->afpf_mbox, BLKADDR_CPT0); + ret = otx2_cptlf_init(lfs, OTX2_CPT_ALL_ENG_GRPS_MASK, OTX2_CPT_QUEUE_HI_PRIO, 1); if (ret) goto delete_grps; @@ -1562,7 +1560,7 @@ int otx2_cpt_discover_eng_capabilities(struct otx2_cptpf_dev *cptpf) free_result: kfree(result); lf_cleanup: - otx2_cptlf_shutdown(&cptpf->lfs); + otx2_cptlf_shutdown(lfs); delete_grps: delete_engine_grps(pdev, &cptpf->eng_grps); diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptvf.h b/drivers/crypto/marvell/octeontx2/otx2_cptvf.h index 4207e2236903..994291e90da1 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptvf.h +++ b/drivers/crypto/marvell/octeontx2/otx2_cptvf.h @@ -19,6 +19,7 @@ struct otx2_cptvf_dev { struct otx2_mbox pfvf_mbox; struct work_struct pfvf_mbox_work; struct workqueue_struct *pfvf_mbox_wq; + int blkaddr; void *bbuf_base; unsigned long cap_flag; }; diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c b/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c index 6023a7adb70c..bac729c885f9 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c @@ -277,12 +277,11 @@ static int cptvf_lf_init(struct otx2_cptvf_dev *cptvf) if (ret) return ret; - lfs->reg_base = cptvf->reg_base; - lfs->pdev = cptvf->pdev; - lfs->mbox = &cptvf->pfvf_mbox; - lfs_num = cptvf->lfs.kvf_limits ? cptvf->lfs.kvf_limits : num_online_cpus(); + + otx2_cptlf_set_dev_info(lfs, cptvf->pdev, cptvf->reg_base, + &cptvf->pfvf_mbox, cptvf->blkaddr); ret = otx2_cptlf_init(lfs, eng_grp_msk, OTX2_CPT_QUEUE_HI_PRIO, lfs_num); if (ret) @@ -380,6 +379,7 @@ static int otx2_cptvf_probe(struct pci_dev *pdev, if (ret) goto destroy_pfvf_mbox; + cptvf->blkaddr = BLKADDR_CPT0; /* Initialize CPT LFs */ ret = cptvf_lf_init(cptvf); if (ret) diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c index 20d0dcd50344..4f6ca229ee5e 100644 --- a/drivers/crypto/n2_core.c +++ b/drivers/crypto/n2_core.c @@ -9,6 +9,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/of_address.h> #include <linux/of_device.h> #include <linux/cpumask.h> #include <linux/slab.h> @@ -1795,11 +1796,9 @@ static int grab_mdesc_irq_props(struct mdesc_handle *mdesc, struct spu_mdesc_info *ip, const char *node_name) { - const unsigned int *reg; - u64 node; + u64 node, reg; - reg = of_get_property(dev->dev.of_node, "reg", NULL); - if (!reg) + if (of_property_read_reg(dev->dev.of_node, 0, ®, NULL) < 0) return -ENODEV; mdesc_for_each_node_by_name(mdesc, node, "virtual-device") { @@ -1810,7 +1809,7 @@ static int grab_mdesc_irq_props(struct mdesc_handle *mdesc, if (!name || strcmp(name, node_name)) continue; chdl = mdesc_get_property(mdesc, node, "cfg-handle", NULL); - if (!chdl || (*chdl != *reg)) + if (!chdl || (*chdl != reg)) continue; ip->cfg_handle = *chdl; return get_irq_props(mdesc, node, ip); diff --git a/drivers/crypto/nx/Makefile b/drivers/crypto/nx/Makefile index d00181a26dd6..483cef62acee 100644 --- a/drivers/crypto/nx/Makefile +++ b/drivers/crypto/nx/Makefile @@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_CRYPTO_DEV_NX_ENCRYPT) += nx-crypto.o nx-crypto-objs := nx.o \ - nx_debugfs.o \ nx-aes-cbc.o \ nx-aes-ecb.o \ nx-aes-gcm.o \ @@ -11,6 +10,7 @@ nx-crypto-objs := nx.o \ nx-sha256.o \ nx-sha512.o +nx-crypto-$(CONFIG_DEBUG_FS) += nx_debugfs.o obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_PSERIES) += nx-compress-pseries.o nx-compress.o obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_POWERNV) += nx-compress-powernv.o nx-compress.o nx-compress-objs := nx-842.o diff --git a/drivers/crypto/nx/nx.h b/drivers/crypto/nx/nx.h index c6233173c612..2697baebb6a3 100644 --- a/drivers/crypto/nx/nx.h +++ b/drivers/crypto/nx/nx.h @@ -170,8 +170,8 @@ struct nx_sg *nx_walk_and_build(struct nx_sg *, unsigned int, void nx_debugfs_init(struct nx_crypto_driver *); void nx_debugfs_fini(struct nx_crypto_driver *); #else -#define NX_DEBUGFS_INIT(drv) (0) -#define NX_DEBUGFS_FINI(drv) (0) +#define NX_DEBUGFS_INIT(drv) do {} while (0) +#define NX_DEBUGFS_FINI(drv) do {} while (0) #endif #define NX_PAGE_NUM(x) ((u64)(x) & 0xfffffffffffff000ULL) diff --git a/drivers/crypto/sa2ul.h b/drivers/crypto/sa2ul.h index 92bf97232a29..12c17a68d350 100644 --- a/drivers/crypto/sa2ul.h +++ b/drivers/crypto/sa2ul.h @@ -170,7 +170,7 @@ struct sa_tfm_ctx; * the following range, so avoid using it. */ #define SA_UNSAFE_DATA_SZ_MIN 240 -#define SA_UNSAFE_DATA_SZ_MAX 256 +#define SA_UNSAFE_DATA_SZ_MAX 255 struct sa_match_data; diff --git a/drivers/crypto/starfive/Kconfig b/drivers/crypto/starfive/Kconfig new file mode 100644 index 000000000000..df745fcb09df --- /dev/null +++ b/drivers/crypto/starfive/Kconfig @@ -0,0 +1,20 @@ +# +# StarFive crypto drivers configuration +# + +config CRYPTO_DEV_JH7110 + tristate "StarFive JH7110 cryptographic engine driver" + depends on SOC_STARFIVE || AMBA_PL08X || COMPILE_TEST + depends on HAS_DMA + select CRYPTO_ENGINE + select CRYPTO_HMAC + select CRYPTO_SHA256 + select CRYPTO_SHA512 + select CRYPTO_SM3_GENERIC + select CRYPTO_RSA + help + Support for StarFive JH7110 crypto hardware acceleration engine. + This module provides acceleration for public key algo, + skciphers, AEAD and hash functions. + + If you choose 'M' here, this module will be called jh7110-crypto. diff --git a/drivers/crypto/starfive/Makefile b/drivers/crypto/starfive/Makefile new file mode 100644 index 000000000000..98b01d2f1ccf --- /dev/null +++ b/drivers/crypto/starfive/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_CRYPTO_DEV_JH7110) += jh7110-crypto.o +jh7110-crypto-objs := jh7110-cryp.o jh7110-hash.o jh7110-rsa.o diff --git a/drivers/crypto/starfive/jh7110-cryp.c b/drivers/crypto/starfive/jh7110-cryp.c new file mode 100644 index 000000000000..cc43556b6c80 --- /dev/null +++ b/drivers/crypto/starfive/jh7110-cryp.c @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Cryptographic API. + * + * Support for StarFive hardware cryptographic engine. + * Copyright (c) 2022 StarFive Technology + * + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/iopoll.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/reset.h> + +#include "jh7110-cryp.h" + +#define DRIVER_NAME "jh7110-crypto" + +struct starfive_dev_list { + struct list_head dev_list; + spinlock_t lock; /* protect dev_list */ +}; + +static struct starfive_dev_list dev_list = { + .dev_list = LIST_HEAD_INIT(dev_list.dev_list), + .lock = __SPIN_LOCK_UNLOCKED(dev_list.lock), +}; + +struct starfive_cryp_dev *starfive_cryp_find_dev(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_dev *cryp = NULL, *tmp; + + spin_lock_bh(&dev_list.lock); + if (!ctx->cryp) { + list_for_each_entry(tmp, &dev_list.dev_list, list) { + cryp = tmp; + break; + } + ctx->cryp = cryp; + } else { + cryp = ctx->cryp; + } + + spin_unlock_bh(&dev_list.lock); + + return cryp; +} + +static int starfive_dma_init(struct starfive_cryp_dev *cryp) +{ + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + cryp->tx = dma_request_chan(cryp->dev, "tx"); + if (IS_ERR(cryp->tx)) + return dev_err_probe(cryp->dev, PTR_ERR(cryp->tx), + "Error requesting tx dma channel.\n"); + + cryp->rx = dma_request_chan(cryp->dev, "rx"); + if (IS_ERR(cryp->rx)) { + dma_release_channel(cryp->tx); + return dev_err_probe(cryp->dev, PTR_ERR(cryp->rx), + "Error requesting rx dma channel.\n"); + } + + return 0; +} + +static void starfive_dma_cleanup(struct starfive_cryp_dev *cryp) +{ + dma_release_channel(cryp->tx); + dma_release_channel(cryp->rx); +} + +static irqreturn_t starfive_cryp_irq(int irq, void *priv) +{ + u32 status; + struct starfive_cryp_dev *cryp = (struct starfive_cryp_dev *)priv; + + status = readl(cryp->base + STARFIVE_IE_FLAG_OFFSET); + if (status & STARFIVE_IE_FLAG_HASH_DONE) { + status = readl(cryp->base + STARFIVE_IE_MASK_OFFSET); + status |= STARFIVE_IE_MASK_HASH_DONE; + writel(status, cryp->base + STARFIVE_IE_MASK_OFFSET); + tasklet_schedule(&cryp->hash_done); + } + + if (status & STARFIVE_IE_FLAG_PKA_DONE) { + status = readl(cryp->base + STARFIVE_IE_MASK_OFFSET); + status |= STARFIVE_IE_MASK_PKA_DONE; + writel(status, cryp->base + STARFIVE_IE_MASK_OFFSET); + complete(&cryp->pka_done); + } + + return IRQ_HANDLED; +} + +static int starfive_cryp_probe(struct platform_device *pdev) +{ + struct starfive_cryp_dev *cryp; + struct resource *res; + int irq; + int ret; + + cryp = devm_kzalloc(&pdev->dev, sizeof(*cryp), GFP_KERNEL); + if (!cryp) + return -ENOMEM; + + platform_set_drvdata(pdev, cryp); + cryp->dev = &pdev->dev; + + cryp->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(cryp->base)) + return dev_err_probe(&pdev->dev, PTR_ERR(cryp->base), + "Error remapping memory for platform device\n"); + + tasklet_init(&cryp->hash_done, starfive_hash_done_task, (unsigned long)cryp); + + cryp->phys_base = res->start; + cryp->dma_maxburst = 32; + + cryp->hclk = devm_clk_get(&pdev->dev, "hclk"); + if (IS_ERR(cryp->hclk)) + return dev_err_probe(&pdev->dev, PTR_ERR(cryp->hclk), + "Error getting hardware reference clock\n"); + + cryp->ahb = devm_clk_get(&pdev->dev, "ahb"); + if (IS_ERR(cryp->ahb)) + return dev_err_probe(&pdev->dev, PTR_ERR(cryp->ahb), + "Error getting ahb reference clock\n"); + + cryp->rst = devm_reset_control_get_shared(cryp->dev, NULL); + if (IS_ERR(cryp->rst)) + return dev_err_probe(&pdev->dev, PTR_ERR(cryp->rst), + "Error getting hardware reset line\n"); + + init_completion(&cryp->pka_done); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + ret = devm_request_irq(&pdev->dev, irq, starfive_cryp_irq, 0, pdev->name, + (void *)cryp); + if (ret) + return dev_err_probe(&pdev->dev, irq, + "Failed to register interrupt handler\n"); + + clk_prepare_enable(cryp->hclk); + clk_prepare_enable(cryp->ahb); + reset_control_deassert(cryp->rst); + + spin_lock(&dev_list.lock); + list_add(&cryp->list, &dev_list.dev_list); + spin_unlock(&dev_list.lock); + + ret = starfive_dma_init(cryp); + if (ret) { + if (ret == -EPROBE_DEFER) + goto err_probe_defer; + else + goto err_dma_init; + } + + /* Initialize crypto engine */ + cryp->engine = crypto_engine_alloc_init(&pdev->dev, 1); + if (!cryp->engine) { + ret = -ENOMEM; + goto err_engine; + } + + ret = crypto_engine_start(cryp->engine); + if (ret) + goto err_engine_start; + + ret = starfive_hash_register_algs(); + if (ret) + goto err_algs_hash; + + ret = starfive_rsa_register_algs(); + if (ret) + goto err_algs_rsa; + + return 0; + +err_algs_rsa: + starfive_hash_unregister_algs(); +err_algs_hash: + crypto_engine_stop(cryp->engine); +err_engine_start: + crypto_engine_exit(cryp->engine); +err_engine: + starfive_dma_cleanup(cryp); +err_dma_init: + spin_lock(&dev_list.lock); + list_del(&cryp->list); + spin_unlock(&dev_list.lock); + + clk_disable_unprepare(cryp->hclk); + clk_disable_unprepare(cryp->ahb); + reset_control_assert(cryp->rst); + + tasklet_kill(&cryp->hash_done); +err_probe_defer: + return ret; +} + +static int starfive_cryp_remove(struct platform_device *pdev) +{ + struct starfive_cryp_dev *cryp = platform_get_drvdata(pdev); + + starfive_hash_unregister_algs(); + starfive_rsa_unregister_algs(); + + tasklet_kill(&cryp->hash_done); + + crypto_engine_stop(cryp->engine); + crypto_engine_exit(cryp->engine); + + starfive_dma_cleanup(cryp); + + spin_lock(&dev_list.lock); + list_del(&cryp->list); + spin_unlock(&dev_list.lock); + + clk_disable_unprepare(cryp->hclk); + clk_disable_unprepare(cryp->ahb); + reset_control_assert(cryp->rst); + + return 0; +} + +static const struct of_device_id starfive_dt_ids[] __maybe_unused = { + { .compatible = "starfive,jh7110-crypto", .data = NULL}, + {}, +}; +MODULE_DEVICE_TABLE(of, starfive_dt_ids); + +static struct platform_driver starfive_cryp_driver = { + .probe = starfive_cryp_probe, + .remove = starfive_cryp_remove, + .driver = { + .name = DRIVER_NAME, + .of_match_table = starfive_dt_ids, + }, +}; + +module_platform_driver(starfive_cryp_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("StarFive JH7110 Cryptographic Module"); diff --git a/drivers/crypto/starfive/jh7110-cryp.h b/drivers/crypto/starfive/jh7110-cryp.h new file mode 100644 index 000000000000..0cdcffc0d7d4 --- /dev/null +++ b/drivers/crypto/starfive/jh7110-cryp.h @@ -0,0 +1,172 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __STARFIVE_STR_H__ +#define __STARFIVE_STR_H__ + +#include <linux/delay.h> +#include <linux/dma-mapping.h> +#include <linux/dmaengine.h> + +#include <crypto/engine.h> +#include <crypto/sha2.h> +#include <crypto/sm3.h> + +#define STARFIVE_ALG_CR_OFFSET 0x0 +#define STARFIVE_ALG_FIFO_OFFSET 0x4 +#define STARFIVE_IE_MASK_OFFSET 0x8 +#define STARFIVE_IE_FLAG_OFFSET 0xc +#define STARFIVE_DMA_IN_LEN_OFFSET 0x10 +#define STARFIVE_DMA_OUT_LEN_OFFSET 0x14 + +#define STARFIVE_IE_MASK_HASH_DONE 0x4 +#define STARFIVE_IE_MASK_PKA_DONE 0x8 +#define STARFIVE_IE_FLAG_HASH_DONE 0x4 +#define STARFIVE_IE_FLAG_PKA_DONE 0x8 + +#define STARFIVE_MSG_BUFFER_SIZE SZ_16K +#define MAX_KEY_SIZE SHA512_BLOCK_SIZE + +union starfive_hash_csr { + u32 v; + struct { + u32 start :1; + u32 reset :1; + u32 ie :1; + u32 firstb :1; +#define STARFIVE_HASH_SM3 0x0 +#define STARFIVE_HASH_SHA224 0x3 +#define STARFIVE_HASH_SHA256 0x4 +#define STARFIVE_HASH_SHA384 0x5 +#define STARFIVE_HASH_SHA512 0x6 +#define STARFIVE_HASH_MODE_MASK 0x7 + u32 mode :3; + u32 rsvd_1 :1; + u32 final :1; + u32 rsvd_2 :2; +#define STARFIVE_HASH_HMAC_FLAGS 0x800 + u32 hmac :1; + u32 rsvd_3 :1; +#define STARFIVE_HASH_KEY_DONE BIT(13) + u32 key_done :1; + u32 key_flag :1; + u32 hmac_done :1; +#define STARFIVE_HASH_BUSY BIT(16) + u32 busy :1; + u32 hashdone :1; + u32 rsvd_4 :14; + }; +}; + +union starfive_pka_cacr { + u32 v; + struct { + u32 start :1; + u32 reset :1; + u32 ie :1; + u32 rsvd_0 :1; + u32 fifo_mode :1; + u32 not_r2 :1; + u32 ecc_sub :1; + u32 pre_expf :1; + u32 cmd :4; + u32 rsvd_1 :1; + u32 ctrl_dummy :1; + u32 ctrl_false :1; + u32 cln_done :1; + u32 opsize :6; + u32 rsvd_2 :2; + u32 exposize :6; + u32 rsvd_3 :1; + u32 bigendian :1; + }; +}; + +struct starfive_rsa_key { + u8 *n; + u8 *e; + u8 *d; + int e_bitlen; + int d_bitlen; + int bitlen; + size_t key_sz; +}; + +union starfive_alg_cr { + u32 v; + struct { + u32 start :1; + u32 aes_dma_en :1; + u32 rsvd_0 :1; + u32 hash_dma_en :1; + u32 alg_done :1; + u32 rsvd_1 :3; + u32 clear :1; + u32 rsvd_2 :23; + }; +}; + +struct starfive_cryp_ctx { + struct crypto_engine_ctx enginectx; + struct starfive_cryp_dev *cryp; + struct starfive_cryp_request_ctx *rctx; + + unsigned int hash_mode; + u8 key[MAX_KEY_SIZE]; + int keylen; + bool is_hmac; + struct starfive_rsa_key rsa_key; + struct crypto_akcipher *akcipher_fbk; + struct crypto_ahash *ahash_fbk; +}; + +struct starfive_cryp_dev { + struct list_head list; + struct device *dev; + struct clk *hclk; + struct clk *ahb; + struct reset_control *rst; + + void __iomem *base; + phys_addr_t phys_base; + + u32 dma_maxburst; + struct dma_chan *tx; + struct dma_chan *rx; + struct dma_slave_config cfg_in; + struct dma_slave_config cfg_out; + struct crypto_engine *engine; + struct tasklet_struct hash_done; + struct completion pka_done; + int err; + union starfive_alg_cr alg_cr; + union { + struct ahash_request *hreq; + } req; +}; + +struct starfive_cryp_request_ctx { + union { + union starfive_hash_csr hash; + union starfive_pka_cacr pka; + } csr; + + struct scatterlist *in_sg; + struct scatterlist *out_sg; + struct ahash_request ahash_fbk_req; + size_t total; + size_t nents; + unsigned int blksize; + unsigned int digsize; + unsigned long in_sg_len; + u8 rsa_data[] __aligned(sizeof(u32)); +}; + +struct starfive_cryp_dev *starfive_cryp_find_dev(struct starfive_cryp_ctx *ctx); + +int starfive_hash_register_algs(void); +void starfive_hash_unregister_algs(void); + +int starfive_rsa_register_algs(void); +void starfive_rsa_unregister_algs(void); + +void starfive_hash_done_task(unsigned long param); +#endif diff --git a/drivers/crypto/starfive/jh7110-hash.c b/drivers/crypto/starfive/jh7110-hash.c new file mode 100644 index 000000000000..5064150b8a1c --- /dev/null +++ b/drivers/crypto/starfive/jh7110-hash.c @@ -0,0 +1,899 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Hash function and HMAC support for StarFive driver + * + * Copyright (c) 2022 StarFive Technology + * + */ + +#include <linux/clk.h> +#include <linux/crypto.h> +#include <linux/dma-direct.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/reset.h> +#include <linux/amba/pl080.h> + +#include <crypto/hash.h> +#include <crypto/scatterwalk.h> +#include <crypto/internal/hash.h> + +#include "jh7110-cryp.h" + +#define STARFIVE_HASH_REGS_OFFSET 0x300 +#define STARFIVE_HASH_SHACSR (STARFIVE_HASH_REGS_OFFSET + 0x0) +#define STARFIVE_HASH_SHAWDR (STARFIVE_HASH_REGS_OFFSET + 0x4) +#define STARFIVE_HASH_SHARDR (STARFIVE_HASH_REGS_OFFSET + 0x8) +#define STARFIVE_HASH_SHAWSR (STARFIVE_HASH_REGS_OFFSET + 0xC) +#define STARFIVE_HASH_SHAWLEN3 (STARFIVE_HASH_REGS_OFFSET + 0x10) +#define STARFIVE_HASH_SHAWLEN2 (STARFIVE_HASH_REGS_OFFSET + 0x14) +#define STARFIVE_HASH_SHAWLEN1 (STARFIVE_HASH_REGS_OFFSET + 0x18) +#define STARFIVE_HASH_SHAWLEN0 (STARFIVE_HASH_REGS_OFFSET + 0x1C) +#define STARFIVE_HASH_SHAWKR (STARFIVE_HASH_REGS_OFFSET + 0x20) +#define STARFIVE_HASH_SHAWKLEN (STARFIVE_HASH_REGS_OFFSET + 0x24) + +#define STARFIVE_HASH_BUFLEN SHA512_BLOCK_SIZE +#define STARFIVE_HASH_RESET 0x2 + +static inline int starfive_hash_wait_busy(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + u32 status; + + return readl_relaxed_poll_timeout(cryp->base + STARFIVE_HASH_SHACSR, status, + !(status & STARFIVE_HASH_BUSY), 10, 100000); +} + +static inline int starfive_hash_wait_key_done(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + u32 status; + + return readl_relaxed_poll_timeout(cryp->base + STARFIVE_HASH_SHACSR, status, + (status & STARFIVE_HASH_KEY_DONE), 10, 100000); +} + +static int starfive_hash_hmac_key(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_request_ctx *rctx = ctx->rctx; + struct starfive_cryp_dev *cryp = ctx->cryp; + int klen = ctx->keylen, loop; + unsigned int *key = (unsigned int *)ctx->key; + unsigned char *cl; + + writel(ctx->keylen, cryp->base + STARFIVE_HASH_SHAWKLEN); + + rctx->csr.hash.hmac = 1; + rctx->csr.hash.key_flag = 1; + + writel(rctx->csr.hash.v, cryp->base + STARFIVE_HASH_SHACSR); + + for (loop = 0; loop < klen / sizeof(unsigned int); loop++, key++) + writel(*key, cryp->base + STARFIVE_HASH_SHAWKR); + + if (klen & 0x3) { + cl = (unsigned char *)key; + for (loop = 0; loop < (klen & 0x3); loop++, cl++) + writeb(*cl, cryp->base + STARFIVE_HASH_SHAWKR); + } + + if (starfive_hash_wait_key_done(ctx)) + return dev_err_probe(cryp->dev, -ETIMEDOUT, "starfive_hash_wait_key_done error\n"); + + return 0; +} + +static void starfive_hash_start(void *param) +{ + struct starfive_cryp_ctx *ctx = param; + struct starfive_cryp_request_ctx *rctx = ctx->rctx; + struct starfive_cryp_dev *cryp = ctx->cryp; + union starfive_alg_cr alg_cr; + union starfive_hash_csr csr; + u32 stat; + + dma_unmap_sg(cryp->dev, rctx->in_sg, rctx->in_sg_len, DMA_TO_DEVICE); + + alg_cr.v = 0; + alg_cr.clear = 1; + + writel(alg_cr.v, cryp->base + STARFIVE_ALG_CR_OFFSET); + + csr.v = readl(cryp->base + STARFIVE_HASH_SHACSR); + csr.firstb = 0; + csr.final = 1; + + stat = readl(cryp->base + STARFIVE_IE_MASK_OFFSET); + stat &= ~STARFIVE_IE_MASK_HASH_DONE; + writel(stat, cryp->base + STARFIVE_IE_MASK_OFFSET); + writel(csr.v, cryp->base + STARFIVE_HASH_SHACSR); +} + +static int starfive_hash_xmit_dma(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_request_ctx *rctx = ctx->rctx; + struct starfive_cryp_dev *cryp = ctx->cryp; + struct dma_async_tx_descriptor *in_desc; + union starfive_alg_cr alg_cr; + int total_len; + int ret; + + if (!rctx->total) { + starfive_hash_start(ctx); + return 0; + } + + writel(rctx->total, cryp->base + STARFIVE_DMA_IN_LEN_OFFSET); + + total_len = rctx->total; + total_len = (total_len & 0x3) ? (((total_len >> 2) + 1) << 2) : total_len; + sg_dma_len(rctx->in_sg) = total_len; + + alg_cr.v = 0; + alg_cr.start = 1; + alg_cr.hash_dma_en = 1; + + writel(alg_cr.v, cryp->base + STARFIVE_ALG_CR_OFFSET); + + ret = dma_map_sg(cryp->dev, rctx->in_sg, rctx->in_sg_len, DMA_TO_DEVICE); + if (!ret) + return dev_err_probe(cryp->dev, -EINVAL, "dma_map_sg() error\n"); + + cryp->cfg_in.direction = DMA_MEM_TO_DEV; + cryp->cfg_in.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + cryp->cfg_in.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + cryp->cfg_in.src_maxburst = cryp->dma_maxburst; + cryp->cfg_in.dst_maxburst = cryp->dma_maxburst; + cryp->cfg_in.dst_addr = cryp->phys_base + STARFIVE_ALG_FIFO_OFFSET; + + dmaengine_slave_config(cryp->tx, &cryp->cfg_in); + + in_desc = dmaengine_prep_slave_sg(cryp->tx, rctx->in_sg, + ret, DMA_MEM_TO_DEV, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + + if (!in_desc) + return -EINVAL; + + in_desc->callback = starfive_hash_start; + in_desc->callback_param = ctx; + + dmaengine_submit(in_desc); + dma_async_issue_pending(cryp->tx); + + return 0; +} + +static int starfive_hash_xmit(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_request_ctx *rctx = ctx->rctx; + struct starfive_cryp_dev *cryp = ctx->cryp; + int ret = 0; + + rctx->csr.hash.v = 0; + rctx->csr.hash.reset = 1; + writel(rctx->csr.hash.v, cryp->base + STARFIVE_HASH_SHACSR); + + if (starfive_hash_wait_busy(ctx)) + return dev_err_probe(cryp->dev, -ETIMEDOUT, "Error resetting engine.\n"); + + rctx->csr.hash.v = 0; + rctx->csr.hash.mode = ctx->hash_mode; + rctx->csr.hash.ie = 1; + + if (ctx->is_hmac) { + ret = starfive_hash_hmac_key(ctx); + if (ret) + return ret; + } else { + rctx->csr.hash.start = 1; + rctx->csr.hash.firstb = 1; + writel(rctx->csr.hash.v, cryp->base + STARFIVE_HASH_SHACSR); + } + + return starfive_hash_xmit_dma(ctx); +} + +static int starfive_hash_copy_hash(struct ahash_request *req) +{ + struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req); + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); + int count, *data; + int mlen; + + if (!req->result) + return 0; + + mlen = rctx->digsize / sizeof(u32); + data = (u32 *)req->result; + + for (count = 0; count < mlen; count++) + data[count] = readl(ctx->cryp->base + STARFIVE_HASH_SHARDR); + + return 0; +} + +void starfive_hash_done_task(unsigned long param) +{ + struct starfive_cryp_dev *cryp = (struct starfive_cryp_dev *)param; + int err = cryp->err; + + if (!err) + err = starfive_hash_copy_hash(cryp->req.hreq); + + /* Reset to clear hash_done in irq register*/ + writel(STARFIVE_HASH_RESET, cryp->base + STARFIVE_HASH_SHACSR); + + crypto_finalize_hash_request(cryp->engine, cryp->req.hreq, err); +} + +static int starfive_hash_check_aligned(struct scatterlist *sg, size_t total, size_t align) +{ + int len = 0; + + if (!total) + return 0; + + if (!IS_ALIGNED(total, align)) + return -EINVAL; + + while (sg) { + if (!IS_ALIGNED(sg->offset, sizeof(u32))) + return -EINVAL; + + if (!IS_ALIGNED(sg->length, align)) + return -EINVAL; + + len += sg->length; + sg = sg_next(sg); + } + + if (len != total) + return -EINVAL; + + return 0; +} + +static int starfive_hash_one_request(struct crypto_engine *engine, void *areq) +{ + struct ahash_request *req = container_of(areq, struct ahash_request, + base); + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); + struct starfive_cryp_dev *cryp = ctx->cryp; + + if (!cryp) + return -ENODEV; + + return starfive_hash_xmit(ctx); +} + +static int starfive_hash_init(struct ahash_request *req) +{ + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req); + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm); + + ahash_request_set_tfm(&rctx->ahash_fbk_req, ctx->ahash_fbk); + ahash_request_set_callback(&rctx->ahash_fbk_req, + req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP, + req->base.complete, req->base.data); + + ahash_request_set_crypt(&rctx->ahash_fbk_req, req->src, + req->result, req->nbytes); + + return crypto_ahash_init(&rctx->ahash_fbk_req); +} + +static int starfive_hash_update(struct ahash_request *req) +{ + struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req); + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm); + + ahash_request_set_tfm(&rctx->ahash_fbk_req, ctx->ahash_fbk); + ahash_request_set_callback(&rctx->ahash_fbk_req, + req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP, + req->base.complete, req->base.data); + + ahash_request_set_crypt(&rctx->ahash_fbk_req, req->src, + req->result, req->nbytes); + + return crypto_ahash_update(&rctx->ahash_fbk_req); +} + +static int starfive_hash_final(struct ahash_request *req) +{ + struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req); + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm); + + ahash_request_set_tfm(&rctx->ahash_fbk_req, ctx->ahash_fbk); + ahash_request_set_callback(&rctx->ahash_fbk_req, + req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP, + req->base.complete, req->base.data); + + ahash_request_set_crypt(&rctx->ahash_fbk_req, req->src, + req->result, req->nbytes); + + return crypto_ahash_final(&rctx->ahash_fbk_req); +} + +static int starfive_hash_finup(struct ahash_request *req) +{ + struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req); + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm); + + ahash_request_set_tfm(&rctx->ahash_fbk_req, ctx->ahash_fbk); + ahash_request_set_callback(&rctx->ahash_fbk_req, + req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP, + req->base.complete, req->base.data); + + ahash_request_set_crypt(&rctx->ahash_fbk_req, req->src, + req->result, req->nbytes); + + return crypto_ahash_finup(&rctx->ahash_fbk_req); +} + +static int starfive_hash_digest_fb(struct ahash_request *req) +{ + struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req); + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm); + + ahash_request_set_tfm(&rctx->ahash_fbk_req, ctx->ahash_fbk); + ahash_request_set_callback(&rctx->ahash_fbk_req, req->base.flags, + req->base.complete, req->base.data); + + ahash_request_set_crypt(&rctx->ahash_fbk_req, req->src, + req->result, req->nbytes); + + return crypto_ahash_digest(&rctx->ahash_fbk_req); +} + +static int starfive_hash_digest(struct ahash_request *req) +{ + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm); + struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req); + struct starfive_cryp_dev *cryp = ctx->cryp; + + memset(rctx, 0, sizeof(struct starfive_cryp_request_ctx)); + + cryp->req.hreq = req; + rctx->total = req->nbytes; + rctx->in_sg = req->src; + rctx->blksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); + rctx->digsize = crypto_ahash_digestsize(tfm); + rctx->in_sg_len = sg_nents_for_len(rctx->in_sg, rctx->total); + ctx->rctx = rctx; + + if (starfive_hash_check_aligned(rctx->in_sg, rctx->total, rctx->blksize)) + return starfive_hash_digest_fb(req); + + return crypto_transfer_hash_request_to_engine(cryp->engine, req); +} + +static int starfive_hash_export(struct ahash_request *req, void *out) +{ + struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req); + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm); + + ahash_request_set_tfm(&rctx->ahash_fbk_req, ctx->ahash_fbk); + ahash_request_set_callback(&rctx->ahash_fbk_req, + req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP, + req->base.complete, req->base.data); + + return crypto_ahash_export(&rctx->ahash_fbk_req, out); +} + +static int starfive_hash_import(struct ahash_request *req, const void *in) +{ + struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req); + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm); + + ahash_request_set_tfm(&rctx->ahash_fbk_req, ctx->ahash_fbk); + ahash_request_set_callback(&rctx->ahash_fbk_req, + req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP, + req->base.complete, req->base.data); + + return crypto_ahash_import(&rctx->ahash_fbk_req, in); +} + +static int starfive_hash_init_tfm(struct crypto_ahash *hash, + const char *alg_name, + unsigned int mode) +{ + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash); + + ctx->cryp = starfive_cryp_find_dev(ctx); + + if (!ctx->cryp) + return -ENODEV; + + ctx->ahash_fbk = crypto_alloc_ahash(alg_name, 0, + CRYPTO_ALG_NEED_FALLBACK); + + if (IS_ERR(ctx->ahash_fbk)) + return dev_err_probe(ctx->cryp->dev, PTR_ERR(ctx->ahash_fbk), + "starfive_hash: Could not load fallback driver.\n"); + + crypto_ahash_set_statesize(hash, crypto_ahash_statesize(ctx->ahash_fbk)); + crypto_ahash_set_reqsize(hash, sizeof(struct starfive_cryp_request_ctx) + + crypto_ahash_reqsize(ctx->ahash_fbk)); + + ctx->keylen = 0; + ctx->hash_mode = mode; + + ctx->enginectx.op.do_one_request = starfive_hash_one_request; + ctx->enginectx.op.prepare_request = NULL; + ctx->enginectx.op.unprepare_request = NULL; + + return 0; +} + +static void starfive_hash_exit_tfm(struct crypto_ahash *hash) +{ + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash); + + crypto_free_ahash(ctx->ahash_fbk); + + ctx->ahash_fbk = NULL; + ctx->enginectx.op.do_one_request = NULL; + ctx->enginectx.op.prepare_request = NULL; + ctx->enginectx.op.unprepare_request = NULL; +} + +static int starfive_hash_long_setkey(struct starfive_cryp_ctx *ctx, + const u8 *key, unsigned int keylen, + const char *alg_name) +{ + struct crypto_wait wait; + struct ahash_request *req; + struct scatterlist sg; + struct crypto_ahash *ahash_tfm; + u8 *buf; + int ret; + + ahash_tfm = crypto_alloc_ahash(alg_name, 0, 0); + if (IS_ERR(ahash_tfm)) + return PTR_ERR(ahash_tfm); + + req = ahash_request_alloc(ahash_tfm, GFP_KERNEL); + if (!req) { + ret = -ENOMEM; + goto err_free_ahash; + } + + crypto_init_wait(&wait); + ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, + crypto_req_done, &wait); + crypto_ahash_clear_flags(ahash_tfm, ~0); + + buf = kzalloc(keylen + STARFIVE_HASH_BUFLEN, GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto err_free_req; + } + + memcpy(buf, key, keylen); + sg_init_one(&sg, buf, keylen); + ahash_request_set_crypt(req, &sg, ctx->key, keylen); + + ret = crypto_wait_req(crypto_ahash_digest(req), &wait); + + kfree(buf); +err_free_req: + ahash_request_free(req); +err_free_ahash: + crypto_free_ahash(ahash_tfm); + return ret; +} + +static int starfive_hash_setkey(struct crypto_ahash *hash, + const u8 *key, unsigned int keylen) +{ + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash); + unsigned int digestsize = crypto_ahash_digestsize(hash); + unsigned int blocksize = crypto_ahash_blocksize(hash); + const char *alg_name; + + crypto_ahash_setkey(ctx->ahash_fbk, key, keylen); + + if (keylen <= blocksize) { + memcpy(ctx->key, key, keylen); + ctx->keylen = keylen; + return 0; + } + + ctx->keylen = digestsize; + + switch (digestsize) { + case SHA224_DIGEST_SIZE: + alg_name = "sha224-starfive"; + break; + case SHA256_DIGEST_SIZE: + if (ctx->hash_mode == STARFIVE_HASH_SM3) + alg_name = "sm3-starfive"; + else + alg_name = "sha256-starfive"; + break; + case SHA384_DIGEST_SIZE: + alg_name = "sha384-starfive"; + break; + case SHA512_DIGEST_SIZE: + alg_name = "sha512-starfive"; + break; + default: + return -EINVAL; + } + + return starfive_hash_long_setkey(ctx, key, keylen, alg_name); +} + +static int starfive_sha224_init_tfm(struct crypto_ahash *hash) +{ + return starfive_hash_init_tfm(hash, "sha224-generic", + STARFIVE_HASH_SHA224); +} + +static int starfive_sha256_init_tfm(struct crypto_ahash *hash) +{ + return starfive_hash_init_tfm(hash, "sha256-generic", + STARFIVE_HASH_SHA256); +} + +static int starfive_sha384_init_tfm(struct crypto_ahash *hash) +{ + return starfive_hash_init_tfm(hash, "sha384-generic", + STARFIVE_HASH_SHA384); +} + +static int starfive_sha512_init_tfm(struct crypto_ahash *hash) +{ + return starfive_hash_init_tfm(hash, "sha512-generic", + STARFIVE_HASH_SHA512); +} + +static int starfive_sm3_init_tfm(struct crypto_ahash *hash) +{ + return starfive_hash_init_tfm(hash, "sm3-generic", + STARFIVE_HASH_SM3); +} + +static int starfive_hmac_sha224_init_tfm(struct crypto_ahash *hash) +{ + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash); + + ctx->is_hmac = true; + + return starfive_hash_init_tfm(hash, "hmac(sha224-generic)", + STARFIVE_HASH_SHA224); +} + +static int starfive_hmac_sha256_init_tfm(struct crypto_ahash *hash) +{ + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash); + + ctx->is_hmac = true; + + return starfive_hash_init_tfm(hash, "hmac(sha256-generic)", + STARFIVE_HASH_SHA256); +} + +static int starfive_hmac_sha384_init_tfm(struct crypto_ahash *hash) +{ + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash); + + ctx->is_hmac = true; + + return starfive_hash_init_tfm(hash, "hmac(sha384-generic)", + STARFIVE_HASH_SHA384); +} + +static int starfive_hmac_sha512_init_tfm(struct crypto_ahash *hash) +{ + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash); + + ctx->is_hmac = true; + + return starfive_hash_init_tfm(hash, "hmac(sha512-generic)", + STARFIVE_HASH_SHA512); +} + +static int starfive_hmac_sm3_init_tfm(struct crypto_ahash *hash) +{ + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash); + + ctx->is_hmac = true; + + return starfive_hash_init_tfm(hash, "hmac(sm3-generic)", + STARFIVE_HASH_SM3); +} + +static struct ahash_alg algs_sha2_sm3[] = { +{ + .init = starfive_hash_init, + .update = starfive_hash_update, + .final = starfive_hash_final, + .finup = starfive_hash_finup, + .digest = starfive_hash_digest, + .export = starfive_hash_export, + .import = starfive_hash_import, + .init_tfm = starfive_sha224_init_tfm, + .exit_tfm = starfive_hash_exit_tfm, + .halg = { + .digestsize = SHA224_DIGEST_SIZE, + .statesize = sizeof(struct sha256_state), + .base = { + .cra_name = "sha224", + .cra_driver_name = "sha224-starfive", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SHA224_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 3, + .cra_module = THIS_MODULE, + } + } +}, { + .init = starfive_hash_init, + .update = starfive_hash_update, + .final = starfive_hash_final, + .finup = starfive_hash_finup, + .digest = starfive_hash_digest, + .export = starfive_hash_export, + .import = starfive_hash_import, + .init_tfm = starfive_hmac_sha224_init_tfm, + .exit_tfm = starfive_hash_exit_tfm, + .setkey = starfive_hash_setkey, + .halg = { + .digestsize = SHA224_DIGEST_SIZE, + .statesize = sizeof(struct sha256_state), + .base = { + .cra_name = "hmac(sha224)", + .cra_driver_name = "sha224-hmac-starfive", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SHA224_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 3, + .cra_module = THIS_MODULE, + } + } +}, { + .init = starfive_hash_init, + .update = starfive_hash_update, + .final = starfive_hash_final, + .finup = starfive_hash_finup, + .digest = starfive_hash_digest, + .export = starfive_hash_export, + .import = starfive_hash_import, + .init_tfm = starfive_sha256_init_tfm, + .exit_tfm = starfive_hash_exit_tfm, + .halg = { + .digestsize = SHA256_DIGEST_SIZE, + .statesize = sizeof(struct sha256_state), + .base = { + .cra_name = "sha256", + .cra_driver_name = "sha256-starfive", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SHA256_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 3, + .cra_module = THIS_MODULE, + } + } +}, { + .init = starfive_hash_init, + .update = starfive_hash_update, + .final = starfive_hash_final, + .finup = starfive_hash_finup, + .digest = starfive_hash_digest, + .export = starfive_hash_export, + .import = starfive_hash_import, + .init_tfm = starfive_hmac_sha256_init_tfm, + .exit_tfm = starfive_hash_exit_tfm, + .setkey = starfive_hash_setkey, + .halg = { + .digestsize = SHA256_DIGEST_SIZE, + .statesize = sizeof(struct sha256_state), + .base = { + .cra_name = "hmac(sha256)", + .cra_driver_name = "sha256-hmac-starfive", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SHA256_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 3, + .cra_module = THIS_MODULE, + } + } +}, { + .init = starfive_hash_init, + .update = starfive_hash_update, + .final = starfive_hash_final, + .finup = starfive_hash_finup, + .digest = starfive_hash_digest, + .export = starfive_hash_export, + .import = starfive_hash_import, + .init_tfm = starfive_sha384_init_tfm, + .exit_tfm = starfive_hash_exit_tfm, + .halg = { + .digestsize = SHA384_DIGEST_SIZE, + .statesize = sizeof(struct sha512_state), + .base = { + .cra_name = "sha384", + .cra_driver_name = "sha384-starfive", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SHA384_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 3, + .cra_module = THIS_MODULE, + } + } +}, { + .init = starfive_hash_init, + .update = starfive_hash_update, + .final = starfive_hash_final, + .finup = starfive_hash_finup, + .digest = starfive_hash_digest, + .export = starfive_hash_export, + .import = starfive_hash_import, + .init_tfm = starfive_hmac_sha384_init_tfm, + .exit_tfm = starfive_hash_exit_tfm, + .setkey = starfive_hash_setkey, + .halg = { + .digestsize = SHA384_DIGEST_SIZE, + .statesize = sizeof(struct sha512_state), + .base = { + .cra_name = "hmac(sha384)", + .cra_driver_name = "sha384-hmac-starfive", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SHA384_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 3, + .cra_module = THIS_MODULE, + } + } +}, { + .init = starfive_hash_init, + .update = starfive_hash_update, + .final = starfive_hash_final, + .finup = starfive_hash_finup, + .digest = starfive_hash_digest, + .export = starfive_hash_export, + .import = starfive_hash_import, + .init_tfm = starfive_sha512_init_tfm, + .exit_tfm = starfive_hash_exit_tfm, + .halg = { + .digestsize = SHA512_DIGEST_SIZE, + .statesize = sizeof(struct sha512_state), + .base = { + .cra_name = "sha512", + .cra_driver_name = "sha512-starfive", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SHA512_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 3, + .cra_module = THIS_MODULE, + } + } +}, { + .init = starfive_hash_init, + .update = starfive_hash_update, + .final = starfive_hash_final, + .finup = starfive_hash_finup, + .digest = starfive_hash_digest, + .export = starfive_hash_export, + .import = starfive_hash_import, + .init_tfm = starfive_hmac_sha512_init_tfm, + .exit_tfm = starfive_hash_exit_tfm, + .setkey = starfive_hash_setkey, + .halg = { + .digestsize = SHA512_DIGEST_SIZE, + .statesize = sizeof(struct sha512_state), + .base = { + .cra_name = "hmac(sha512)", + .cra_driver_name = "sha512-hmac-starfive", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SHA512_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 3, + .cra_module = THIS_MODULE, + } + } +}, { + .init = starfive_hash_init, + .update = starfive_hash_update, + .final = starfive_hash_final, + .finup = starfive_hash_finup, + .digest = starfive_hash_digest, + .export = starfive_hash_export, + .import = starfive_hash_import, + .init_tfm = starfive_sm3_init_tfm, + .exit_tfm = starfive_hash_exit_tfm, + .halg = { + .digestsize = SM3_DIGEST_SIZE, + .statesize = sizeof(struct sm3_state), + .base = { + .cra_name = "sm3", + .cra_driver_name = "sm3-starfive", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SM3_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 3, + .cra_module = THIS_MODULE, + } + } +}, { + .init = starfive_hash_init, + .update = starfive_hash_update, + .final = starfive_hash_final, + .finup = starfive_hash_finup, + .digest = starfive_hash_digest, + .export = starfive_hash_export, + .import = starfive_hash_import, + .init_tfm = starfive_hmac_sm3_init_tfm, + .exit_tfm = starfive_hash_exit_tfm, + .setkey = starfive_hash_setkey, + .halg = { + .digestsize = SM3_DIGEST_SIZE, + .statesize = sizeof(struct sm3_state), + .base = { + .cra_name = "hmac(sm3)", + .cra_driver_name = "sm3-hmac-starfive", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SM3_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 3, + .cra_module = THIS_MODULE, + } + } +}, +}; + +int starfive_hash_register_algs(void) +{ + return crypto_register_ahashes(algs_sha2_sm3, ARRAY_SIZE(algs_sha2_sm3)); +} + +void starfive_hash_unregister_algs(void) +{ + crypto_unregister_ahashes(algs_sha2_sm3, ARRAY_SIZE(algs_sha2_sm3)); +} diff --git a/drivers/crypto/starfive/jh7110-rsa.c b/drivers/crypto/starfive/jh7110-rsa.c new file mode 100644 index 000000000000..f31bbd825f88 --- /dev/null +++ b/drivers/crypto/starfive/jh7110-rsa.c @@ -0,0 +1,617 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * StarFive Public Key Algo acceleration driver + * + * Copyright (c) 2022 StarFive Technology + */ + +#include <linux/crypto.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/dma-direct.h> +#include <linux/interrupt.h> +#include <linux/iopoll.h> +#include <linux/io.h> +#include <linux/mod_devicetable.h> +#include <crypto/akcipher.h> +#include <crypto/algapi.h> +#include <crypto/internal/akcipher.h> +#include <crypto/internal/rsa.h> +#include <crypto/scatterwalk.h> + +#include "jh7110-cryp.h" + +#define STARFIVE_PKA_REGS_OFFSET 0x400 +#define STARFIVE_PKA_CACR_OFFSET (STARFIVE_PKA_REGS_OFFSET + 0x0) +#define STARFIVE_PKA_CASR_OFFSET (STARFIVE_PKA_REGS_OFFSET + 0x4) +#define STARFIVE_PKA_CAAR_OFFSET (STARFIVE_PKA_REGS_OFFSET + 0x8) +#define STARFIVE_PKA_CAER_OFFSET (STARFIVE_PKA_REGS_OFFSET + 0x108) +#define STARFIVE_PKA_CANR_OFFSET (STARFIVE_PKA_REGS_OFFSET + 0x208) + +// R^2 mod N and N0' +#define CRYPTO_CMD_PRE 0x0 +// A * R mod N ==> A +#define CRYPTO_CMD_ARN 0x5 +// A * E * R mod N ==> A +#define CRYPTO_CMD_AERN 0x6 +// A * A * R mod N ==> A +#define CRYPTO_CMD_AARN 0x7 + +#define STARFIVE_RSA_MAX_KEYSZ 256 +#define STARFIVE_RSA_RESET 0x2 + +static inline int starfive_pka_wait_done(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + + return wait_for_completion_timeout(&cryp->pka_done, + usecs_to_jiffies(100000)); +} + +static inline void starfive_pka_irq_mask_clear(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + u32 stat; + + stat = readl(cryp->base + STARFIVE_IE_MASK_OFFSET); + stat &= ~STARFIVE_IE_MASK_PKA_DONE; + writel(stat, cryp->base + STARFIVE_IE_MASK_OFFSET); + + reinit_completion(&cryp->pka_done); +} + +static void starfive_rsa_free_key(struct starfive_rsa_key *key) +{ + if (key->d) + kfree_sensitive(key->d); + if (key->e) + kfree_sensitive(key->e); + if (key->n) + kfree_sensitive(key->n); + memset(key, 0, sizeof(*key)); +} + +static unsigned int starfive_rsa_get_nbit(u8 *pa, u32 snum, int key_sz) +{ + u32 i; + u8 value; + + i = snum >> 3; + + value = pa[key_sz - i - 1]; + value >>= snum & 0x7; + value &= 0x1; + + return value; +} + +static int starfive_rsa_montgomery_form(struct starfive_cryp_ctx *ctx, + u32 *out, u32 *in, u8 mont, + u32 *mod, int bit_len) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + struct starfive_cryp_request_ctx *rctx = ctx->rctx; + int count = rctx->total / sizeof(u32) - 1; + int loop; + u32 temp; + u8 opsize; + + opsize = (bit_len - 1) >> 5; + rctx->csr.pka.v = 0; + + writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET); + + for (loop = 0; loop <= opsize; loop++) + writel(mod[opsize - loop], cryp->base + STARFIVE_PKA_CANR_OFFSET + loop * 4); + + if (mont) { + rctx->csr.pka.v = 0; + rctx->csr.pka.cln_done = 1; + rctx->csr.pka.opsize = opsize; + rctx->csr.pka.exposize = opsize; + rctx->csr.pka.cmd = CRYPTO_CMD_PRE; + rctx->csr.pka.start = 1; + rctx->csr.pka.not_r2 = 1; + rctx->csr.pka.ie = 1; + + starfive_pka_irq_mask_clear(ctx); + writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET); + + if (!starfive_pka_wait_done(ctx)) + return -ETIMEDOUT; + + for (loop = 0; loop <= opsize; loop++) + writel(in[opsize - loop], cryp->base + STARFIVE_PKA_CAAR_OFFSET + loop * 4); + + writel(0x1000000, cryp->base + STARFIVE_PKA_CAER_OFFSET); + + for (loop = 1; loop <= opsize; loop++) + writel(0, cryp->base + STARFIVE_PKA_CAER_OFFSET + loop * 4); + + rctx->csr.pka.v = 0; + rctx->csr.pka.cln_done = 1; + rctx->csr.pka.opsize = opsize; + rctx->csr.pka.exposize = opsize; + rctx->csr.pka.cmd = CRYPTO_CMD_AERN; + rctx->csr.pka.start = 1; + rctx->csr.pka.ie = 1; + + starfive_pka_irq_mask_clear(ctx); + writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET); + + if (!starfive_pka_wait_done(ctx)) + return -ETIMEDOUT; + } else { + rctx->csr.pka.v = 0; + rctx->csr.pka.cln_done = 1; + rctx->csr.pka.opsize = opsize; + rctx->csr.pka.exposize = opsize; + rctx->csr.pka.cmd = CRYPTO_CMD_PRE; + rctx->csr.pka.start = 1; + rctx->csr.pka.pre_expf = 1; + rctx->csr.pka.ie = 1; + + starfive_pka_irq_mask_clear(ctx); + writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET); + + if (!starfive_pka_wait_done(ctx)) + return -ETIMEDOUT; + + for (loop = 0; loop <= count; loop++) + writel(in[count - loop], cryp->base + STARFIVE_PKA_CAER_OFFSET + loop * 4); + + /*pad with 0 up to opsize*/ + for (loop = count + 1; loop <= opsize; loop++) + writel(0, cryp->base + STARFIVE_PKA_CAER_OFFSET + loop * 4); + + rctx->csr.pka.v = 0; + rctx->csr.pka.cln_done = 1; + rctx->csr.pka.opsize = opsize; + rctx->csr.pka.exposize = opsize; + rctx->csr.pka.cmd = CRYPTO_CMD_ARN; + rctx->csr.pka.start = 1; + rctx->csr.pka.ie = 1; + + starfive_pka_irq_mask_clear(ctx); + writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET); + + if (!starfive_pka_wait_done(ctx)) + return -ETIMEDOUT; + } + + for (loop = 0; loop <= opsize; loop++) { + temp = readl(cryp->base + STARFIVE_PKA_CAAR_OFFSET + 0x4 * loop); + out[opsize - loop] = temp; + } + + return 0; +} + +static int starfive_rsa_cpu_start(struct starfive_cryp_ctx *ctx, u32 *result, + u8 *de, u32 *n, int key_sz) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + struct starfive_cryp_request_ctx *rctx = ctx->rctx; + struct starfive_rsa_key *key = &ctx->rsa_key; + u32 temp; + int ret = 0; + int opsize, mlen, loop; + unsigned int *mta; + + opsize = (key_sz - 1) >> 2; + + mta = kmalloc(key_sz, GFP_KERNEL); + if (!mta) + return -ENOMEM; + + ret = starfive_rsa_montgomery_form(ctx, mta, (u32 *)rctx->rsa_data, + 0, n, key_sz << 3); + if (ret) { + dev_err_probe(cryp->dev, ret, "Conversion to Montgomery failed"); + goto rsa_err; + } + + for (loop = 0; loop <= opsize; loop++) + writel(mta[opsize - loop], + cryp->base + STARFIVE_PKA_CAER_OFFSET + loop * 4); + + for (loop = key->bitlen - 1; loop > 0; loop--) { + mlen = starfive_rsa_get_nbit(de, loop - 1, key_sz); + + rctx->csr.pka.v = 0; + rctx->csr.pka.cln_done = 1; + rctx->csr.pka.opsize = opsize; + rctx->csr.pka.exposize = opsize; + rctx->csr.pka.cmd = CRYPTO_CMD_AARN; + rctx->csr.pka.start = 1; + rctx->csr.pka.ie = 1; + + starfive_pka_irq_mask_clear(ctx); + writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET); + + ret = -ETIMEDOUT; + if (!starfive_pka_wait_done(ctx)) + goto rsa_err; + + if (mlen) { + rctx->csr.pka.v = 0; + rctx->csr.pka.cln_done = 1; + rctx->csr.pka.opsize = opsize; + rctx->csr.pka.exposize = opsize; + rctx->csr.pka.cmd = CRYPTO_CMD_AERN; + rctx->csr.pka.start = 1; + rctx->csr.pka.ie = 1; + + starfive_pka_irq_mask_clear(ctx); + writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET); + + if (!starfive_pka_wait_done(ctx)) + goto rsa_err; + } + } + + for (loop = 0; loop <= opsize; loop++) { + temp = readl(cryp->base + STARFIVE_PKA_CAAR_OFFSET + 0x4 * loop); + result[opsize - loop] = temp; + } + + ret = starfive_rsa_montgomery_form(ctx, result, result, 1, n, key_sz << 3); + if (ret) + dev_err_probe(cryp->dev, ret, "Conversion from Montgomery failed"); +rsa_err: + kfree(mta); + return ret; +} + +static int starfive_rsa_start(struct starfive_cryp_ctx *ctx, u8 *result, + u8 *de, u8 *n, int key_sz) +{ + return starfive_rsa_cpu_start(ctx, (u32 *)result, de, (u32 *)n, key_sz); +} + +static int starfive_rsa_enc_core(struct starfive_cryp_ctx *ctx, int enc) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + struct starfive_cryp_request_ctx *rctx = ctx->rctx; + struct starfive_rsa_key *key = &ctx->rsa_key; + int ret = 0; + + writel(STARFIVE_RSA_RESET, cryp->base + STARFIVE_PKA_CACR_OFFSET); + + rctx->total = sg_copy_to_buffer(rctx->in_sg, rctx->nents, + rctx->rsa_data, rctx->total); + + if (enc) { + key->bitlen = key->e_bitlen; + ret = starfive_rsa_start(ctx, rctx->rsa_data, key->e, + key->n, key->key_sz); + } else { + key->bitlen = key->d_bitlen; + ret = starfive_rsa_start(ctx, rctx->rsa_data, key->d, + key->n, key->key_sz); + } + + if (ret) + goto err_rsa_crypt; + + sg_copy_buffer(rctx->out_sg, sg_nents(rctx->out_sg), + rctx->rsa_data, key->key_sz, 0, 0); + +err_rsa_crypt: + writel(STARFIVE_RSA_RESET, cryp->base + STARFIVE_PKA_CACR_OFFSET); + kfree(rctx->rsa_data); + return ret; +} + +static int starfive_rsa_enc(struct akcipher_request *req) +{ + struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); + struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm); + struct starfive_cryp_dev *cryp = ctx->cryp; + struct starfive_rsa_key *key = &ctx->rsa_key; + struct starfive_cryp_request_ctx *rctx = akcipher_request_ctx(req); + int ret; + + if (!key->key_sz) { + akcipher_request_set_tfm(req, ctx->akcipher_fbk); + ret = crypto_akcipher_encrypt(req); + akcipher_request_set_tfm(req, tfm); + return ret; + } + + if (unlikely(!key->n || !key->e)) + return -EINVAL; + + if (req->dst_len < key->key_sz) + return dev_err_probe(cryp->dev, -EOVERFLOW, + "Output buffer length less than parameter n\n"); + + rctx->in_sg = req->src; + rctx->out_sg = req->dst; + rctx->total = req->src_len; + rctx->nents = sg_nents(rctx->in_sg); + ctx->rctx = rctx; + + return starfive_rsa_enc_core(ctx, 1); +} + +static int starfive_rsa_dec(struct akcipher_request *req) +{ + struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); + struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm); + struct starfive_cryp_dev *cryp = ctx->cryp; + struct starfive_rsa_key *key = &ctx->rsa_key; + struct starfive_cryp_request_ctx *rctx = akcipher_request_ctx(req); + int ret; + + if (!key->key_sz) { + akcipher_request_set_tfm(req, ctx->akcipher_fbk); + ret = crypto_akcipher_decrypt(req); + akcipher_request_set_tfm(req, tfm); + return ret; + } + + if (unlikely(!key->n || !key->d)) + return -EINVAL; + + if (req->dst_len < key->key_sz) + return dev_err_probe(cryp->dev, -EOVERFLOW, + "Output buffer length less than parameter n\n"); + + rctx->in_sg = req->src; + rctx->out_sg = req->dst; + ctx->rctx = rctx; + rctx->total = req->src_len; + + return starfive_rsa_enc_core(ctx, 0); +} + +static int starfive_rsa_set_n(struct starfive_rsa_key *rsa_key, + const char *value, size_t vlen) +{ + const char *ptr = value; + unsigned int bitslen; + int ret; + + while (!*ptr && vlen) { + ptr++; + vlen--; + } + rsa_key->key_sz = vlen; + bitslen = rsa_key->key_sz << 3; + + /* check valid key size */ + if (bitslen & 0x1f) + return -EINVAL; + + ret = -ENOMEM; + rsa_key->n = kmemdup(ptr, rsa_key->key_sz, GFP_KERNEL); + if (!rsa_key->n) + goto err; + + return 0; + err: + rsa_key->key_sz = 0; + rsa_key->n = NULL; + starfive_rsa_free_key(rsa_key); + return ret; +} + +static int starfive_rsa_set_e(struct starfive_rsa_key *rsa_key, + const char *value, size_t vlen) +{ + const char *ptr = value; + unsigned char pt; + int loop; + + while (!*ptr && vlen) { + ptr++; + vlen--; + } + pt = *ptr; + + if (!rsa_key->key_sz || !vlen || vlen > rsa_key->key_sz) { + rsa_key->e = NULL; + return -EINVAL; + } + + rsa_key->e = kzalloc(rsa_key->key_sz, GFP_KERNEL); + if (!rsa_key->e) + return -ENOMEM; + + for (loop = 8; loop > 0; loop--) { + if (pt >> (loop - 1)) + break; + } + + rsa_key->e_bitlen = (vlen - 1) * 8 + loop; + + memcpy(rsa_key->e + (rsa_key->key_sz - vlen), ptr, vlen); + + return 0; +} + +static int starfive_rsa_set_d(struct starfive_rsa_key *rsa_key, + const char *value, size_t vlen) +{ + const char *ptr = value; + unsigned char pt; + int loop; + int ret; + + while (!*ptr && vlen) { + ptr++; + vlen--; + } + pt = *ptr; + + ret = -EINVAL; + if (!rsa_key->key_sz || !vlen || vlen > rsa_key->key_sz) + goto err; + + ret = -ENOMEM; + rsa_key->d = kzalloc(rsa_key->key_sz, GFP_KERNEL); + if (!rsa_key->d) + goto err; + + for (loop = 8; loop > 0; loop--) { + if (pt >> (loop - 1)) + break; + } + + rsa_key->d_bitlen = (vlen - 1) * 8 + loop; + + memcpy(rsa_key->d + (rsa_key->key_sz - vlen), ptr, vlen); + + return 0; + err: + rsa_key->d = NULL; + return ret; +} + +static int starfive_rsa_setkey(struct crypto_akcipher *tfm, const void *key, + unsigned int keylen, bool private) +{ + struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm); + struct rsa_key raw_key = {NULL}; + struct starfive_rsa_key *rsa_key = &ctx->rsa_key; + int ret; + + if (private) + ret = rsa_parse_priv_key(&raw_key, key, keylen); + else + ret = rsa_parse_pub_key(&raw_key, key, keylen); + if (ret < 0) + goto err; + + starfive_rsa_free_key(rsa_key); + + /* Use fallback for mod > 256 + 1 byte prefix */ + if (raw_key.n_sz > STARFIVE_RSA_MAX_KEYSZ + 1) + return 0; + + ret = starfive_rsa_set_n(rsa_key, raw_key.n, raw_key.n_sz); + if (ret) + return ret; + + ret = starfive_rsa_set_e(rsa_key, raw_key.e, raw_key.e_sz); + if (ret) + goto err; + + if (private) { + ret = starfive_rsa_set_d(rsa_key, raw_key.d, raw_key.d_sz); + if (ret) + goto err; + } + + if (!rsa_key->n || !rsa_key->e) { + ret = -EINVAL; + goto err; + } + + if (private && !rsa_key->d) { + ret = -EINVAL; + goto err; + } + + return 0; + err: + starfive_rsa_free_key(rsa_key); + return ret; +} + +static int starfive_rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, + unsigned int keylen) +{ + struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm); + int ret; + + ret = crypto_akcipher_set_pub_key(ctx->akcipher_fbk, key, keylen); + if (ret) + return ret; + + return starfive_rsa_setkey(tfm, key, keylen, false); +} + +static int starfive_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key, + unsigned int keylen) +{ + struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm); + int ret; + + ret = crypto_akcipher_set_priv_key(ctx->akcipher_fbk, key, keylen); + if (ret) + return ret; + + return starfive_rsa_setkey(tfm, key, keylen, true); +} + +static unsigned int starfive_rsa_max_size(struct crypto_akcipher *tfm) +{ + struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm); + + if (ctx->rsa_key.key_sz) + return ctx->rsa_key.key_sz; + + return crypto_akcipher_maxsize(ctx->akcipher_fbk); +} + +static int starfive_rsa_init_tfm(struct crypto_akcipher *tfm) +{ + struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm); + + ctx->akcipher_fbk = crypto_alloc_akcipher("rsa-generic", 0, 0); + if (IS_ERR(ctx->akcipher_fbk)) + return PTR_ERR(ctx->akcipher_fbk); + + ctx->cryp = starfive_cryp_find_dev(ctx); + if (!ctx->cryp) { + crypto_free_akcipher(ctx->akcipher_fbk); + return -ENODEV; + } + + akcipher_set_reqsize(tfm, sizeof(struct starfive_cryp_request_ctx) + + sizeof(struct crypto_akcipher) + 32); + + return 0; +} + +static void starfive_rsa_exit_tfm(struct crypto_akcipher *tfm) +{ + struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm); + struct starfive_rsa_key *key = (struct starfive_rsa_key *)&ctx->rsa_key; + + crypto_free_akcipher(ctx->akcipher_fbk); + starfive_rsa_free_key(key); +} + +static struct akcipher_alg starfive_rsa = { + .encrypt = starfive_rsa_enc, + .decrypt = starfive_rsa_dec, + .sign = starfive_rsa_dec, + .verify = starfive_rsa_enc, + .set_pub_key = starfive_rsa_set_pub_key, + .set_priv_key = starfive_rsa_set_priv_key, + .max_size = starfive_rsa_max_size, + .init = starfive_rsa_init_tfm, + .exit = starfive_rsa_exit_tfm, + .base = { + .cra_name = "rsa", + .cra_driver_name = "starfive-rsa", + .cra_flags = CRYPTO_ALG_TYPE_AKCIPHER | + CRYPTO_ALG_NEED_FALLBACK, + .cra_priority = 3000, + .cra_module = THIS_MODULE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + }, +}; + +int starfive_rsa_register_algs(void) +{ + return crypto_register_akcipher(&starfive_rsa); +} + +void starfive_rsa_unregister_algs(void) +{ + crypto_unregister_akcipher(&starfive_rsa); +} diff --git a/drivers/cxl/Kconfig b/drivers/cxl/Kconfig index ff4e78117b31..fcbf8295fde3 100644 --- a/drivers/cxl/Kconfig +++ b/drivers/cxl/Kconfig @@ -82,6 +82,7 @@ config CXL_PMEM config CXL_MEM tristate "CXL: Memory Expansion" depends on CXL_PCI + select FW_UPLOAD default CXL_BUS help The CXL.mem protocol allows a device to act as a provider of "System @@ -139,4 +140,17 @@ config CXL_REGION_INVALIDATION_TEST If unsure, or if this kernel is meant for production environments, say N. +config CXL_PMU + tristate "CXL Performance Monitoring Unit" + default CXL_BUS + depends on PERF_EVENTS + help + Support performance monitoring as defined in CXL rev 3.0 + section 13.2: Performance Monitoring. CXL components may have + one or more CXL Performance Monitoring Units (CPMUs). + + Say 'y/m' to enable a driver that will attach to performance + monitoring units and provide standard perf based interfaces. + + If unsure say 'm'. endif diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c index 7e1765b09e04..658e6b84a769 100644 --- a/drivers/cxl/acpi.c +++ b/drivers/cxl/acpi.c @@ -258,7 +258,7 @@ static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg, cxld = &cxlrd->cxlsd.cxld; cxld->flags = cfmws_to_decoder_flags(cfmws->restrictions); - cxld->target_type = CXL_DECODER_EXPANDER; + cxld->target_type = CXL_DECODER_HOSTONLYMEM; cxld->hpa_range = (struct range) { .start = res->start, .end = res->end, @@ -327,66 +327,21 @@ __mock struct acpi_device *to_cxl_host_bridge(struct device *host, return NULL; } -/* - * A host bridge is a dport to a CFMWS decode and it is a uport to the - * dport (PCIe Root Ports) in the host bridge. - */ -static int add_host_bridge_uport(struct device *match, void *arg) -{ - struct cxl_port *root_port = arg; - struct device *host = root_port->dev.parent; - struct acpi_device *hb = to_cxl_host_bridge(host, match); - struct acpi_pci_root *pci_root; - struct cxl_dport *dport; - struct cxl_port *port; - struct device *bridge; - int rc; - - if (!hb) - return 0; - - pci_root = acpi_pci_find_root(hb->handle); - bridge = pci_root->bus->bridge; - dport = cxl_find_dport_by_dev(root_port, bridge); - if (!dport) { - dev_dbg(host, "host bridge expected and not found\n"); - return 0; - } - - if (dport->rch) { - dev_info(bridge, "host supports CXL (restricted)\n"); - return 0; - } - - rc = devm_cxl_register_pci_bus(host, bridge, pci_root->bus); - if (rc) - return rc; - - port = devm_cxl_add_port(host, bridge, dport->component_reg_phys, - dport); - if (IS_ERR(port)) - return PTR_ERR(port); - - dev_info(bridge, "host supports CXL\n"); - - return 0; -} - +/* Note, @dev is used by mock_acpi_table_parse_cedt() */ struct cxl_chbs_context { struct device *dev; unsigned long long uid; - resource_size_t rcrb; - resource_size_t chbcr; + resource_size_t base; u32 cxl_version; }; -static int cxl_get_chbcr(union acpi_subtable_headers *header, void *arg, - const unsigned long end) +static int cxl_get_chbs_iter(union acpi_subtable_headers *header, void *arg, + const unsigned long end) { struct cxl_chbs_context *ctx = arg; struct acpi_cedt_chbs *chbs; - if (ctx->chbcr) + if (ctx->base != CXL_RESOURCE_NONE) return 0; chbs = (struct acpi_cedt_chbs *) header; @@ -395,23 +350,39 @@ static int cxl_get_chbcr(union acpi_subtable_headers *header, void *arg, return 0; ctx->cxl_version = chbs->cxl_version; - ctx->rcrb = CXL_RESOURCE_NONE; - ctx->chbcr = CXL_RESOURCE_NONE; - if (!chbs->base) return 0; - if (chbs->cxl_version != ACPI_CEDT_CHBS_VERSION_CXL11) { - ctx->chbcr = chbs->base; + if (chbs->cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11 && + chbs->length != CXL_RCRB_SIZE) return 0; + + ctx->base = chbs->base; + + return 0; +} + +static int cxl_get_chbs(struct device *dev, struct acpi_device *hb, + struct cxl_chbs_context *ctx) +{ + unsigned long long uid; + int rc; + + rc = acpi_evaluate_integer(hb->handle, METHOD_NAME__UID, NULL, &uid); + if (rc != AE_OK) { + dev_err(dev, "unable to retrieve _UID\n"); + return -ENOENT; } - if (chbs->length != CXL_RCRB_SIZE) - return 0; + dev_dbg(dev, "UID found: %lld\n", uid); + *ctx = (struct cxl_chbs_context) { + .dev = dev, + .uid = uid, + .base = CXL_RESOURCE_NONE, + .cxl_version = UINT_MAX, + }; - ctx->rcrb = chbs->base; - ctx->chbcr = cxl_rcrb_to_component(ctx->dev, chbs->base, - CXL_RCRB_DOWNSTREAM); + acpi_table_parse_cedt(ACPI_CEDT_TYPE_CHBS, cxl_get_chbs_iter, ctx); return 0; } @@ -420,7 +391,6 @@ static int add_host_bridge_dport(struct device *match, void *arg) { acpi_status rc; struct device *bridge; - unsigned long long uid; struct cxl_dport *dport; struct cxl_chbs_context ctx; struct acpi_pci_root *pci_root; @@ -431,51 +401,107 @@ static int add_host_bridge_dport(struct device *match, void *arg) if (!hb) return 0; - rc = acpi_evaluate_integer(hb->handle, METHOD_NAME__UID, NULL, &uid); - if (rc != AE_OK) { - dev_err(match, "unable to retrieve _UID\n"); - return -ENODEV; - } - - dev_dbg(match, "UID found: %lld\n", uid); - - ctx = (struct cxl_chbs_context) { - .dev = match, - .uid = uid, - }; - acpi_table_parse_cedt(ACPI_CEDT_TYPE_CHBS, cxl_get_chbcr, &ctx); + rc = cxl_get_chbs(match, hb, &ctx); + if (rc) + return rc; - if (!ctx.chbcr) { + if (ctx.cxl_version == UINT_MAX) { dev_warn(match, "No CHBS found for Host Bridge (UID %lld)\n", - uid); + ctx.uid); return 0; } - if (ctx.rcrb != CXL_RESOURCE_NONE) - dev_dbg(match, "RCRB found for UID %lld: %pa\n", uid, &ctx.rcrb); - - if (ctx.chbcr == CXL_RESOURCE_NONE) { - dev_warn(match, "CHBCR invalid for Host Bridge (UID %lld)\n", - uid); + if (ctx.base == CXL_RESOURCE_NONE) { + dev_warn(match, "CHBS invalid for Host Bridge (UID %lld)\n", + ctx.uid); return 0; } - dev_dbg(match, "CHBCR found: %pa\n", &ctx.chbcr); - pci_root = acpi_pci_find_root(hb->handle); bridge = pci_root->bus->bridge; - if (ctx.cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11) - dport = devm_cxl_add_rch_dport(root_port, bridge, uid, - ctx.chbcr, ctx.rcrb); - else - dport = devm_cxl_add_dport(root_port, bridge, uid, - ctx.chbcr); + + /* + * In RCH mode, bind the component regs base to the dport. In + * VH mode it will be bound to the CXL host bridge's port + * object later in add_host_bridge_uport(). + */ + if (ctx.cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11) { + dev_dbg(match, "RCRB found for UID %lld: %pa\n", ctx.uid, + &ctx.base); + dport = devm_cxl_add_rch_dport(root_port, bridge, ctx.uid, + ctx.base); + } else { + dport = devm_cxl_add_dport(root_port, bridge, ctx.uid, + CXL_RESOURCE_NONE); + } + if (IS_ERR(dport)) return PTR_ERR(dport); return 0; } +/* + * A host bridge is a dport to a CFMWS decode and it is a uport to the + * dport (PCIe Root Ports) in the host bridge. + */ +static int add_host_bridge_uport(struct device *match, void *arg) +{ + struct cxl_port *root_port = arg; + struct device *host = root_port->dev.parent; + struct acpi_device *hb = to_cxl_host_bridge(host, match); + struct acpi_pci_root *pci_root; + struct cxl_dport *dport; + struct cxl_port *port; + struct device *bridge; + struct cxl_chbs_context ctx; + resource_size_t component_reg_phys; + int rc; + + if (!hb) + return 0; + + pci_root = acpi_pci_find_root(hb->handle); + bridge = pci_root->bus->bridge; + dport = cxl_find_dport_by_dev(root_port, bridge); + if (!dport) { + dev_dbg(host, "host bridge expected and not found\n"); + return 0; + } + + if (dport->rch) { + dev_info(bridge, "host supports CXL (restricted)\n"); + return 0; + } + + rc = cxl_get_chbs(match, hb, &ctx); + if (rc) + return rc; + + if (ctx.cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11) { + dev_warn(bridge, + "CXL CHBS version mismatch, skip port registration\n"); + return 0; + } + + component_reg_phys = ctx.base; + if (component_reg_phys != CXL_RESOURCE_NONE) + dev_dbg(match, "CHBCR found for UID %lld: %pa\n", + ctx.uid, &component_reg_phys); + + rc = devm_cxl_register_pci_bus(host, bridge, pci_root->bus); + if (rc) + return rc; + + port = devm_cxl_add_port(host, bridge, component_reg_phys, dport); + if (IS_ERR(port)) + return PTR_ERR(port); + + dev_info(bridge, "host supports CXL\n"); + + return 0; +} + static int add_root_nvdimm_bridge(struct device *match, void *data) { struct cxl_decoder *cxld; diff --git a/drivers/cxl/core/Makefile b/drivers/cxl/core/Makefile index ca4ae31d8f57..1f66b5d4d935 100644 --- a/drivers/cxl/core/Makefile +++ b/drivers/cxl/core/Makefile @@ -12,5 +12,6 @@ cxl_core-y += memdev.o cxl_core-y += mbox.o cxl_core-y += pci.o cxl_core-y += hdm.o +cxl_core-y += pmu.o cxl_core-$(CONFIG_TRACING) += trace.o cxl_core-$(CONFIG_CXL_REGION) += region.o diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h index 27f0968449de..45e7e044cf4a 100644 --- a/drivers/cxl/core/core.h +++ b/drivers/cxl/core/core.h @@ -6,6 +6,7 @@ extern const struct device_type cxl_nvdimm_bridge_type; extern const struct device_type cxl_nvdimm_type; +extern const struct device_type cxl_pmu_type; extern struct attribute_group cxl_base_attribute_group; @@ -63,6 +64,16 @@ int cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, unsigned long long size); int cxl_dpa_free(struct cxl_endpoint_decoder *cxled); resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled); resource_size_t cxl_dpa_resource_start(struct cxl_endpoint_decoder *cxled); + +enum cxl_rcrb { + CXL_RCRB_DOWNSTREAM, + CXL_RCRB_UPSTREAM, +}; +struct cxl_rcrb_info; +resource_size_t __rcrb_to_component(struct device *dev, + struct cxl_rcrb_info *ri, + enum cxl_rcrb which); + extern struct rw_semaphore cxl_dpa_rwsem; int cxl_memdev_init(void); diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c index 7889ff203a34..4449b34a80cc 100644 --- a/drivers/cxl/core/hdm.c +++ b/drivers/cxl/core/hdm.c @@ -85,6 +85,7 @@ static int map_hdm_decoder_regs(struct cxl_port *port, void __iomem *crb, struct cxl_component_regs *regs) { struct cxl_register_map map = { + .dev = &port->dev, .resource = port->component_reg_phys, .base = crb, .max_size = CXL_COMPONENT_REG_BLOCK_SIZE, @@ -97,8 +98,7 @@ static int map_hdm_decoder_regs(struct cxl_port *port, void __iomem *crb, return -ENODEV; } - return cxl_map_component_regs(&port->dev, regs, &map, - BIT(CXL_CM_CAP_CAP_ID_HDM)); + return cxl_map_component_regs(&map, regs, BIT(CXL_CM_CAP_CAP_ID_HDM)); } static bool should_emulate_decoders(struct cxl_endpoint_dvsec_info *info) @@ -570,8 +570,9 @@ static void cxld_set_interleave(struct cxl_decoder *cxld, u32 *ctrl) static void cxld_set_type(struct cxl_decoder *cxld, u32 *ctrl) { - u32p_replace_bits(ctrl, !!(cxld->target_type == 3), - CXL_HDM_DECODER0_CTRL_TYPE); + u32p_replace_bits(ctrl, + !!(cxld->target_type == CXL_DECODER_HOSTONLYMEM), + CXL_HDM_DECODER0_CTRL_HOSTONLY); } static int cxlsd_set_targets(struct cxl_switch_decoder *cxlsd, u64 *tgt) @@ -764,7 +765,7 @@ static int cxl_setup_hdm_decoder_from_dvsec( if (!len) return -ENOENT; - cxld->target_type = CXL_DECODER_EXPANDER; + cxld->target_type = CXL_DECODER_HOSTONLYMEM; cxld->commit = NULL; cxld->reset = NULL; cxld->hpa_range = info->dvsec_range[which]; @@ -793,8 +794,8 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, int *target_map, void __iomem *hdm, int which, u64 *dpa_base, struct cxl_endpoint_dvsec_info *info) { + struct cxl_endpoint_decoder *cxled = NULL; u64 size, base, skip, dpa_size, lo, hi; - struct cxl_endpoint_decoder *cxled; bool committed; u32 remainder; int i, rc; @@ -827,6 +828,8 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, return -ENXIO; } + if (info) + cxled = to_cxl_endpoint_decoder(&cxld->dev); cxld->hpa_range = (struct range) { .start = base, .end = base + size - 1, @@ -837,10 +840,10 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, cxld->flags |= CXL_DECODER_F_ENABLE; if (ctrl & CXL_HDM_DECODER0_CTRL_LOCK) cxld->flags |= CXL_DECODER_F_LOCK; - if (FIELD_GET(CXL_HDM_DECODER0_CTRL_TYPE, ctrl)) - cxld->target_type = CXL_DECODER_EXPANDER; + if (FIELD_GET(CXL_HDM_DECODER0_CTRL_HOSTONLY, ctrl)) + cxld->target_type = CXL_DECODER_HOSTONLYMEM; else - cxld->target_type = CXL_DECODER_ACCELERATOR; + cxld->target_type = CXL_DECODER_DEVMEM; if (cxld->id != port->commit_end + 1) { dev_warn(&port->dev, "decoder%d.%d: Committed out of order\n", @@ -856,12 +859,28 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, } port->commit_end = cxld->id; } else { - /* unless / until type-2 drivers arrive, assume type-3 */ - if (FIELD_GET(CXL_HDM_DECODER0_CTRL_TYPE, ctrl) == 0) { - ctrl |= CXL_HDM_DECODER0_CTRL_TYPE; + if (cxled) { + struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); + struct cxl_dev_state *cxlds = cxlmd->cxlds; + + /* + * Default by devtype until a device arrives that needs + * more precision. + */ + if (cxlds->type == CXL_DEVTYPE_CLASSMEM) + cxld->target_type = CXL_DECODER_HOSTONLYMEM; + else + cxld->target_type = CXL_DECODER_DEVMEM; + } else { + /* To be overridden by region type at commit time */ + cxld->target_type = CXL_DECODER_HOSTONLYMEM; + } + + if (!FIELD_GET(CXL_HDM_DECODER0_CTRL_HOSTONLY, ctrl) && + cxld->target_type == CXL_DECODER_HOSTONLYMEM) { + ctrl |= CXL_HDM_DECODER0_CTRL_HOSTONLY; writel(ctrl, hdm + CXL_HDM_DECODER0_CTRL_OFFSET(which)); } - cxld->target_type = CXL_DECODER_EXPANDER; } rc = eiw_to_ways(FIELD_GET(CXL_HDM_DECODER0_CTRL_IW_MASK, ctrl), &cxld->interleave_ways); @@ -880,7 +899,7 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, port->id, cxld->id, cxld->hpa_range.start, cxld->hpa_range.end, cxld->interleave_ways, cxld->interleave_granularity); - if (!info) { + if (!cxled) { lo = readl(hdm + CXL_HDM_DECODER0_TL_LOW(which)); hi = readl(hdm + CXL_HDM_DECODER0_TL_HIGH(which)); target_list.value = (hi << 32) + lo; @@ -903,7 +922,6 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, lo = readl(hdm + CXL_HDM_DECODER0_SKIP_LOW(which)); hi = readl(hdm + CXL_HDM_DECODER0_SKIP_HIGH(which)); skip = (hi << 32) + lo; - cxled = to_cxl_endpoint_decoder(&cxld->dev); rc = devm_cxl_dpa_reserve(cxled, *dpa_base + skip, dpa_size, skip); if (rc) { dev_err(&port->dev, diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c index bea9cf31a12d..d6d067fbee97 100644 --- a/drivers/cxl/core/mbox.c +++ b/drivers/cxl/core/mbox.c @@ -182,7 +182,7 @@ static const char *cxl_mem_opcode_to_name(u16 opcode) /** * cxl_internal_send_cmd() - Kernel internal interface to send a mailbox command - * @cxlds: The device data for the operation + * @mds: The driver data for the operation * @mbox_cmd: initialized command to execute * * Context: Any context. @@ -198,19 +198,19 @@ static const char *cxl_mem_opcode_to_name(u16 opcode) * error. While this distinction can be useful for commands from userspace, the * kernel will only be able to use results when both are successful. */ -int cxl_internal_send_cmd(struct cxl_dev_state *cxlds, +int cxl_internal_send_cmd(struct cxl_memdev_state *mds, struct cxl_mbox_cmd *mbox_cmd) { size_t out_size, min_out; int rc; - if (mbox_cmd->size_in > cxlds->payload_size || - mbox_cmd->size_out > cxlds->payload_size) + if (mbox_cmd->size_in > mds->payload_size || + mbox_cmd->size_out > mds->payload_size) return -E2BIG; out_size = mbox_cmd->size_out; min_out = mbox_cmd->min_out; - rc = cxlds->mbox_send(cxlds, mbox_cmd); + rc = mds->mbox_send(mds, mbox_cmd); /* * EIO is reserved for a payload size mismatch and mbox_send() * may not return this error. @@ -220,7 +220,8 @@ int cxl_internal_send_cmd(struct cxl_dev_state *cxlds, if (rc) return rc; - if (mbox_cmd->return_code != CXL_MBOX_CMD_RC_SUCCESS) + if (mbox_cmd->return_code != CXL_MBOX_CMD_RC_SUCCESS && + mbox_cmd->return_code != CXL_MBOX_CMD_RC_BACKGROUND) return cxl_mbox_cmd_rc2errno(mbox_cmd); if (!out_size) @@ -297,7 +298,7 @@ static bool cxl_payload_from_user_allowed(u16 opcode, void *payload_in) } static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox, - struct cxl_dev_state *cxlds, u16 opcode, + struct cxl_memdev_state *mds, u16 opcode, size_t in_size, size_t out_size, u64 in_payload) { *mbox = (struct cxl_mbox_cmd) { @@ -312,7 +313,7 @@ static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox, return PTR_ERR(mbox->payload_in); if (!cxl_payload_from_user_allowed(opcode, mbox->payload_in)) { - dev_dbg(cxlds->dev, "%s: input payload not allowed\n", + dev_dbg(mds->cxlds.dev, "%s: input payload not allowed\n", cxl_mem_opcode_to_name(opcode)); kvfree(mbox->payload_in); return -EBUSY; @@ -321,7 +322,7 @@ static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox, /* Prepare to handle a full payload for variable sized output */ if (out_size == CXL_VARIABLE_PAYLOAD) - mbox->size_out = cxlds->payload_size; + mbox->size_out = mds->payload_size; else mbox->size_out = out_size; @@ -343,7 +344,7 @@ static void cxl_mbox_cmd_dtor(struct cxl_mbox_cmd *mbox) static int cxl_to_mem_cmd_raw(struct cxl_mem_command *mem_cmd, const struct cxl_send_command *send_cmd, - struct cxl_dev_state *cxlds) + struct cxl_memdev_state *mds) { if (send_cmd->raw.rsvd) return -EINVAL; @@ -353,13 +354,13 @@ static int cxl_to_mem_cmd_raw(struct cxl_mem_command *mem_cmd, * gets passed along without further checking, so it must be * validated here. */ - if (send_cmd->out.size > cxlds->payload_size) + if (send_cmd->out.size > mds->payload_size) return -EINVAL; if (!cxl_mem_raw_command_allowed(send_cmd->raw.opcode)) return -EPERM; - dev_WARN_ONCE(cxlds->dev, true, "raw command path used\n"); + dev_WARN_ONCE(mds->cxlds.dev, true, "raw command path used\n"); *mem_cmd = (struct cxl_mem_command) { .info = { @@ -375,7 +376,7 @@ static int cxl_to_mem_cmd_raw(struct cxl_mem_command *mem_cmd, static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd, const struct cxl_send_command *send_cmd, - struct cxl_dev_state *cxlds) + struct cxl_memdev_state *mds) { struct cxl_mem_command *c = &cxl_mem_commands[send_cmd->id]; const struct cxl_command_info *info = &c->info; @@ -390,11 +391,11 @@ static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd, return -EINVAL; /* Check that the command is enabled for hardware */ - if (!test_bit(info->id, cxlds->enabled_cmds)) + if (!test_bit(info->id, mds->enabled_cmds)) return -ENOTTY; /* Check that the command is not claimed for exclusive kernel use */ - if (test_bit(info->id, cxlds->exclusive_cmds)) + if (test_bit(info->id, mds->exclusive_cmds)) return -EBUSY; /* Check the input buffer is the expected size */ @@ -423,7 +424,7 @@ static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd, /** * cxl_validate_cmd_from_user() - Check fields for CXL_MEM_SEND_COMMAND. * @mbox_cmd: Sanitized and populated &struct cxl_mbox_cmd. - * @cxlds: The device data for the operation + * @mds: The driver data for the operation * @send_cmd: &struct cxl_send_command copied in from userspace. * * Return: @@ -438,7 +439,7 @@ static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd, * safe to send to the hardware. */ static int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd, - struct cxl_dev_state *cxlds, + struct cxl_memdev_state *mds, const struct cxl_send_command *send_cmd) { struct cxl_mem_command mem_cmd; @@ -452,20 +453,20 @@ static int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd, * supports, but output can be arbitrarily large (simply write out as * much data as the hardware provides). */ - if (send_cmd->in.size > cxlds->payload_size) + if (send_cmd->in.size > mds->payload_size) return -EINVAL; /* Sanitize and construct a cxl_mem_command */ if (send_cmd->id == CXL_MEM_COMMAND_ID_RAW) - rc = cxl_to_mem_cmd_raw(&mem_cmd, send_cmd, cxlds); + rc = cxl_to_mem_cmd_raw(&mem_cmd, send_cmd, mds); else - rc = cxl_to_mem_cmd(&mem_cmd, send_cmd, cxlds); + rc = cxl_to_mem_cmd(&mem_cmd, send_cmd, mds); if (rc) return rc; /* Sanitize and construct a cxl_mbox_cmd */ - return cxl_mbox_cmd_ctor(mbox_cmd, cxlds, mem_cmd.opcode, + return cxl_mbox_cmd_ctor(mbox_cmd, mds, mem_cmd.opcode, mem_cmd.info.size_in, mem_cmd.info.size_out, send_cmd->in.payload); } @@ -473,6 +474,7 @@ static int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd, int cxl_query_cmd(struct cxl_memdev *cxlmd, struct cxl_mem_query_commands __user *q) { + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct device *dev = &cxlmd->dev; struct cxl_mem_command *cmd; u32 n_commands; @@ -494,9 +496,9 @@ int cxl_query_cmd(struct cxl_memdev *cxlmd, cxl_for_each_cmd(cmd) { struct cxl_command_info info = cmd->info; - if (test_bit(info.id, cxlmd->cxlds->enabled_cmds)) + if (test_bit(info.id, mds->enabled_cmds)) info.flags |= CXL_MEM_COMMAND_FLAG_ENABLED; - if (test_bit(info.id, cxlmd->cxlds->exclusive_cmds)) + if (test_bit(info.id, mds->exclusive_cmds)) info.flags |= CXL_MEM_COMMAND_FLAG_EXCLUSIVE; if (copy_to_user(&q->commands[j++], &info, sizeof(info))) @@ -511,7 +513,7 @@ int cxl_query_cmd(struct cxl_memdev *cxlmd, /** * handle_mailbox_cmd_from_user() - Dispatch a mailbox command for userspace. - * @cxlds: The device data for the operation + * @mds: The driver data for the operation * @mbox_cmd: The validated mailbox command. * @out_payload: Pointer to userspace's output payload. * @size_out: (Input) Max payload size to copy out. @@ -532,12 +534,12 @@ int cxl_query_cmd(struct cxl_memdev *cxlmd, * * See cxl_send_cmd(). */ -static int handle_mailbox_cmd_from_user(struct cxl_dev_state *cxlds, +static int handle_mailbox_cmd_from_user(struct cxl_memdev_state *mds, struct cxl_mbox_cmd *mbox_cmd, u64 out_payload, s32 *size_out, u32 *retval) { - struct device *dev = cxlds->dev; + struct device *dev = mds->cxlds.dev; int rc; dev_dbg(dev, @@ -547,7 +549,7 @@ static int handle_mailbox_cmd_from_user(struct cxl_dev_state *cxlds, cxl_mem_opcode_to_name(mbox_cmd->opcode), mbox_cmd->opcode, mbox_cmd->size_in); - rc = cxlds->mbox_send(cxlds, mbox_cmd); + rc = mds->mbox_send(mds, mbox_cmd); if (rc) goto out; @@ -576,7 +578,7 @@ out: int cxl_send_cmd(struct cxl_memdev *cxlmd, struct cxl_send_command __user *s) { - struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct device *dev = &cxlmd->dev; struct cxl_send_command send; struct cxl_mbox_cmd mbox_cmd; @@ -587,11 +589,11 @@ int cxl_send_cmd(struct cxl_memdev *cxlmd, struct cxl_send_command __user *s) if (copy_from_user(&send, s, sizeof(send))) return -EFAULT; - rc = cxl_validate_cmd_from_user(&mbox_cmd, cxlmd->cxlds, &send); + rc = cxl_validate_cmd_from_user(&mbox_cmd, mds, &send); if (rc) return rc; - rc = handle_mailbox_cmd_from_user(cxlds, &mbox_cmd, send.out.payload, + rc = handle_mailbox_cmd_from_user(mds, &mbox_cmd, send.out.payload, &send.out.size, &send.retval); if (rc) return rc; @@ -602,13 +604,14 @@ int cxl_send_cmd(struct cxl_memdev *cxlmd, struct cxl_send_command __user *s) return 0; } -static int cxl_xfer_log(struct cxl_dev_state *cxlds, uuid_t *uuid, u32 *size, u8 *out) +static int cxl_xfer_log(struct cxl_memdev_state *mds, uuid_t *uuid, + u32 *size, u8 *out) { u32 remaining = *size; u32 offset = 0; while (remaining) { - u32 xfer_size = min_t(u32, remaining, cxlds->payload_size); + u32 xfer_size = min_t(u32, remaining, mds->payload_size); struct cxl_mbox_cmd mbox_cmd; struct cxl_mbox_get_log log; int rc; @@ -627,7 +630,7 @@ static int cxl_xfer_log(struct cxl_dev_state *cxlds, uuid_t *uuid, u32 *size, u8 .payload_out = out, }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); /* * The output payload length that indicates the number @@ -654,17 +657,18 @@ static int cxl_xfer_log(struct cxl_dev_state *cxlds, uuid_t *uuid, u32 *size, u8 /** * cxl_walk_cel() - Walk through the Command Effects Log. - * @cxlds: The device data for the operation + * @mds: The driver data for the operation * @size: Length of the Command Effects Log. * @cel: CEL * * Iterate over each entry in the CEL and determine if the driver supports the * command. If so, the command is enabled for the device and can be used later. */ -static void cxl_walk_cel(struct cxl_dev_state *cxlds, size_t size, u8 *cel) +static void cxl_walk_cel(struct cxl_memdev_state *mds, size_t size, u8 *cel) { struct cxl_cel_entry *cel_entry; const int cel_entries = size / sizeof(*cel_entry); + struct device *dev = mds->cxlds.dev; int i; cel_entry = (struct cxl_cel_entry *) cel; @@ -674,39 +678,39 @@ static void cxl_walk_cel(struct cxl_dev_state *cxlds, size_t size, u8 *cel) struct cxl_mem_command *cmd = cxl_mem_find_command(opcode); if (!cmd && !cxl_is_poison_command(opcode)) { - dev_dbg(cxlds->dev, + dev_dbg(dev, "Opcode 0x%04x unsupported by driver\n", opcode); continue; } if (cmd) - set_bit(cmd->info.id, cxlds->enabled_cmds); + set_bit(cmd->info.id, mds->enabled_cmds); if (cxl_is_poison_command(opcode)) - cxl_set_poison_cmd_enabled(&cxlds->poison, opcode); + cxl_set_poison_cmd_enabled(&mds->poison, opcode); - dev_dbg(cxlds->dev, "Opcode 0x%04x enabled\n", opcode); + dev_dbg(dev, "Opcode 0x%04x enabled\n", opcode); } } -static struct cxl_mbox_get_supported_logs *cxl_get_gsl(struct cxl_dev_state *cxlds) +static struct cxl_mbox_get_supported_logs *cxl_get_gsl(struct cxl_memdev_state *mds) { struct cxl_mbox_get_supported_logs *ret; struct cxl_mbox_cmd mbox_cmd; int rc; - ret = kvmalloc(cxlds->payload_size, GFP_KERNEL); + ret = kvmalloc(mds->payload_size, GFP_KERNEL); if (!ret) return ERR_PTR(-ENOMEM); mbox_cmd = (struct cxl_mbox_cmd) { .opcode = CXL_MBOX_OP_GET_SUPPORTED_LOGS, - .size_out = cxlds->payload_size, + .size_out = mds->payload_size, .payload_out = ret, /* At least the record number field must be valid */ .min_out = 2, }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc < 0) { kvfree(ret); return ERR_PTR(rc); @@ -729,22 +733,22 @@ static const uuid_t log_uuid[] = { /** * cxl_enumerate_cmds() - Enumerate commands for a device. - * @cxlds: The device data for the operation + * @mds: The driver data for the operation * * Returns 0 if enumerate completed successfully. * * CXL devices have optional support for certain commands. This function will * determine the set of supported commands for the hardware and update the - * enabled_cmds bitmap in the @cxlds. + * enabled_cmds bitmap in the @mds. */ -int cxl_enumerate_cmds(struct cxl_dev_state *cxlds) +int cxl_enumerate_cmds(struct cxl_memdev_state *mds) { struct cxl_mbox_get_supported_logs *gsl; - struct device *dev = cxlds->dev; + struct device *dev = mds->cxlds.dev; struct cxl_mem_command *cmd; int i, rc; - gsl = cxl_get_gsl(cxlds); + gsl = cxl_get_gsl(mds); if (IS_ERR(gsl)) return PTR_ERR(gsl); @@ -765,19 +769,19 @@ int cxl_enumerate_cmds(struct cxl_dev_state *cxlds) goto out; } - rc = cxl_xfer_log(cxlds, &uuid, &size, log); + rc = cxl_xfer_log(mds, &uuid, &size, log); if (rc) { kvfree(log); goto out; } - cxl_walk_cel(cxlds, size, log); + cxl_walk_cel(mds, size, log); kvfree(log); /* In case CEL was bogus, enable some default commands. */ cxl_for_each_cmd(cmd) if (cmd->flags & CXL_CMD_FLAG_FORCE_ENABLE) - set_bit(cmd->info.id, cxlds->enabled_cmds); + set_bit(cmd->info.id, mds->enabled_cmds); /* Found the required CEL */ rc = 0; @@ -838,7 +842,7 @@ static void cxl_event_trace_record(const struct cxl_memdev *cxlmd, } } -static int cxl_clear_event_record(struct cxl_dev_state *cxlds, +static int cxl_clear_event_record(struct cxl_memdev_state *mds, enum cxl_event_log_type log, struct cxl_get_event_payload *get_pl) { @@ -852,9 +856,9 @@ static int cxl_clear_event_record(struct cxl_dev_state *cxlds, int i; /* Payload size may limit the max handles */ - if (pl_size > cxlds->payload_size) { - max_handles = (cxlds->payload_size - sizeof(*payload)) / - sizeof(__le16); + if (pl_size > mds->payload_size) { + max_handles = (mds->payload_size - sizeof(*payload)) / + sizeof(__le16); pl_size = struct_size(payload, handles, max_handles); } @@ -879,12 +883,12 @@ static int cxl_clear_event_record(struct cxl_dev_state *cxlds, i = 0; for (cnt = 0; cnt < total; cnt++) { payload->handles[i++] = get_pl->records[cnt].hdr.handle; - dev_dbg(cxlds->dev, "Event log '%d': Clearing %u\n", - log, le16_to_cpu(payload->handles[i])); + dev_dbg(mds->cxlds.dev, "Event log '%d': Clearing %u\n", log, + le16_to_cpu(payload->handles[i])); if (i == max_handles) { payload->nr_recs = i; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc) goto free_pl; i = 0; @@ -895,7 +899,7 @@ static int cxl_clear_event_record(struct cxl_dev_state *cxlds, if (i) { payload->nr_recs = i; mbox_cmd.size_in = struct_size(payload, handles, i); - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc) goto free_pl; } @@ -905,32 +909,34 @@ free_pl: return rc; } -static void cxl_mem_get_records_log(struct cxl_dev_state *cxlds, +static void cxl_mem_get_records_log(struct cxl_memdev_state *mds, enum cxl_event_log_type type) { + struct cxl_memdev *cxlmd = mds->cxlds.cxlmd; + struct device *dev = mds->cxlds.dev; struct cxl_get_event_payload *payload; struct cxl_mbox_cmd mbox_cmd; u8 log_type = type; u16 nr_rec; - mutex_lock(&cxlds->event.log_lock); - payload = cxlds->event.buf; + mutex_lock(&mds->event.log_lock); + payload = mds->event.buf; mbox_cmd = (struct cxl_mbox_cmd) { .opcode = CXL_MBOX_OP_GET_EVENT_RECORD, .payload_in = &log_type, .size_in = sizeof(log_type), .payload_out = payload, - .size_out = cxlds->payload_size, + .size_out = mds->payload_size, .min_out = struct_size(payload, records, 0), }; do { int rc, i; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc) { - dev_err_ratelimited(cxlds->dev, + dev_err_ratelimited(dev, "Event log '%d': Failed to query event records : %d", type, rc); break; @@ -941,27 +947,27 @@ static void cxl_mem_get_records_log(struct cxl_dev_state *cxlds, break; for (i = 0; i < nr_rec; i++) - cxl_event_trace_record(cxlds->cxlmd, type, + cxl_event_trace_record(cxlmd, type, &payload->records[i]); if (payload->flags & CXL_GET_EVENT_FLAG_OVERFLOW) - trace_cxl_overflow(cxlds->cxlmd, type, payload); + trace_cxl_overflow(cxlmd, type, payload); - rc = cxl_clear_event_record(cxlds, type, payload); + rc = cxl_clear_event_record(mds, type, payload); if (rc) { - dev_err_ratelimited(cxlds->dev, + dev_err_ratelimited(dev, "Event log '%d': Failed to clear events : %d", type, rc); break; } } while (nr_rec); - mutex_unlock(&cxlds->event.log_lock); + mutex_unlock(&mds->event.log_lock); } /** * cxl_mem_get_event_records - Get Event Records from the device - * @cxlds: The device data for the operation + * @mds: The driver data for the operation * @status: Event Status register value identifying which events are available. * * Retrieve all event records available on the device, report them as trace @@ -970,24 +976,24 @@ static void cxl_mem_get_records_log(struct cxl_dev_state *cxlds, * See CXL rev 3.0 @8.2.9.2.2 Get Event Records * See CXL rev 3.0 @8.2.9.2.3 Clear Event Records */ -void cxl_mem_get_event_records(struct cxl_dev_state *cxlds, u32 status) +void cxl_mem_get_event_records(struct cxl_memdev_state *mds, u32 status) { - dev_dbg(cxlds->dev, "Reading event logs: %x\n", status); + dev_dbg(mds->cxlds.dev, "Reading event logs: %x\n", status); if (status & CXLDEV_EVENT_STATUS_FATAL) - cxl_mem_get_records_log(cxlds, CXL_EVENT_TYPE_FATAL); + cxl_mem_get_records_log(mds, CXL_EVENT_TYPE_FATAL); if (status & CXLDEV_EVENT_STATUS_FAIL) - cxl_mem_get_records_log(cxlds, CXL_EVENT_TYPE_FAIL); + cxl_mem_get_records_log(mds, CXL_EVENT_TYPE_FAIL); if (status & CXLDEV_EVENT_STATUS_WARN) - cxl_mem_get_records_log(cxlds, CXL_EVENT_TYPE_WARN); + cxl_mem_get_records_log(mds, CXL_EVENT_TYPE_WARN); if (status & CXLDEV_EVENT_STATUS_INFO) - cxl_mem_get_records_log(cxlds, CXL_EVENT_TYPE_INFO); + cxl_mem_get_records_log(mds, CXL_EVENT_TYPE_INFO); } EXPORT_SYMBOL_NS_GPL(cxl_mem_get_event_records, CXL); /** * cxl_mem_get_partition_info - Get partition info - * @cxlds: The device data for the operation + * @mds: The driver data for the operation * * Retrieve the current partition info for the device specified. The active * values are the current capacity in bytes. If not 0, the 'next' values are @@ -997,7 +1003,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_mem_get_event_records, CXL); * * See CXL @8.2.9.5.2.1 Get Partition Info */ -static int cxl_mem_get_partition_info(struct cxl_dev_state *cxlds) +static int cxl_mem_get_partition_info(struct cxl_memdev_state *mds) { struct cxl_mbox_get_partition_info pi; struct cxl_mbox_cmd mbox_cmd; @@ -1008,17 +1014,17 @@ static int cxl_mem_get_partition_info(struct cxl_dev_state *cxlds) .size_out = sizeof(pi), .payload_out = &pi, }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc) return rc; - cxlds->active_volatile_bytes = + mds->active_volatile_bytes = le64_to_cpu(pi.active_volatile_cap) * CXL_CAPACITY_MULTIPLIER; - cxlds->active_persistent_bytes = + mds->active_persistent_bytes = le64_to_cpu(pi.active_persistent_cap) * CXL_CAPACITY_MULTIPLIER; - cxlds->next_volatile_bytes = + mds->next_volatile_bytes = le64_to_cpu(pi.next_volatile_cap) * CXL_CAPACITY_MULTIPLIER; - cxlds->next_persistent_bytes = + mds->next_persistent_bytes = le64_to_cpu(pi.next_volatile_cap) * CXL_CAPACITY_MULTIPLIER; return 0; @@ -1026,14 +1032,14 @@ static int cxl_mem_get_partition_info(struct cxl_dev_state *cxlds) /** * cxl_dev_state_identify() - Send the IDENTIFY command to the device. - * @cxlds: The device data for the operation + * @mds: The driver data for the operation * * Return: 0 if identify was executed successfully or media not ready. * * This will dispatch the identify command to the device and on success populate * structures to be exported to sysfs. */ -int cxl_dev_state_identify(struct cxl_dev_state *cxlds) +int cxl_dev_state_identify(struct cxl_memdev_state *mds) { /* See CXL 2.0 Table 175 Identify Memory Device Output Payload */ struct cxl_mbox_identify id; @@ -1041,7 +1047,7 @@ int cxl_dev_state_identify(struct cxl_dev_state *cxlds) u32 val; int rc; - if (!cxlds->media_ready) + if (!mds->cxlds.media_ready) return 0; mbox_cmd = (struct cxl_mbox_cmd) { @@ -1049,31 +1055,92 @@ int cxl_dev_state_identify(struct cxl_dev_state *cxlds) .size_out = sizeof(id), .payload_out = &id, }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc < 0) return rc; - cxlds->total_bytes = + mds->total_bytes = le64_to_cpu(id.total_capacity) * CXL_CAPACITY_MULTIPLIER; - cxlds->volatile_only_bytes = + mds->volatile_only_bytes = le64_to_cpu(id.volatile_capacity) * CXL_CAPACITY_MULTIPLIER; - cxlds->persistent_only_bytes = + mds->persistent_only_bytes = le64_to_cpu(id.persistent_capacity) * CXL_CAPACITY_MULTIPLIER; - cxlds->partition_align_bytes = + mds->partition_align_bytes = le64_to_cpu(id.partition_align) * CXL_CAPACITY_MULTIPLIER; - cxlds->lsa_size = le32_to_cpu(id.lsa_size); - memcpy(cxlds->firmware_version, id.fw_revision, sizeof(id.fw_revision)); + mds->lsa_size = le32_to_cpu(id.lsa_size); + memcpy(mds->firmware_version, id.fw_revision, + sizeof(id.fw_revision)); - if (test_bit(CXL_POISON_ENABLED_LIST, cxlds->poison.enabled_cmds)) { + if (test_bit(CXL_POISON_ENABLED_LIST, mds->poison.enabled_cmds)) { val = get_unaligned_le24(id.poison_list_max_mer); - cxlds->poison.max_errors = min_t(u32, val, CXL_POISON_LIST_MAX); + mds->poison.max_errors = min_t(u32, val, CXL_POISON_LIST_MAX); } return 0; } EXPORT_SYMBOL_NS_GPL(cxl_dev_state_identify, CXL); +/** + * cxl_mem_sanitize() - Send a sanitization command to the device. + * @mds: The device data for the operation + * @cmd: The specific sanitization command opcode + * + * Return: 0 if the command was executed successfully, regardless of + * whether or not the actual security operation is done in the background, + * such as for the Sanitize case. + * Error return values can be the result of the mailbox command, -EINVAL + * when security requirements are not met or invalid contexts. + * + * See CXL 3.0 @8.2.9.8.5.1 Sanitize and @8.2.9.8.5.2 Secure Erase. + */ +int cxl_mem_sanitize(struct cxl_memdev_state *mds, u16 cmd) +{ + int rc; + u32 sec_out = 0; + struct cxl_get_security_output { + __le32 flags; + } out; + struct cxl_mbox_cmd sec_cmd = { + .opcode = CXL_MBOX_OP_GET_SECURITY_STATE, + .payload_out = &out, + .size_out = sizeof(out), + }; + struct cxl_mbox_cmd mbox_cmd = { .opcode = cmd }; + struct cxl_dev_state *cxlds = &mds->cxlds; + + if (cmd != CXL_MBOX_OP_SANITIZE && cmd != CXL_MBOX_OP_SECURE_ERASE) + return -EINVAL; + + rc = cxl_internal_send_cmd(mds, &sec_cmd); + if (rc < 0) { + dev_err(cxlds->dev, "Failed to get security state : %d", rc); + return rc; + } + + /* + * Prior to using these commands, any security applied to + * the user data areas of the device shall be DISABLED (or + * UNLOCKED for secure erase case). + */ + sec_out = le32_to_cpu(out.flags); + if (sec_out & CXL_PMEM_SEC_STATE_USER_PASS_SET) + return -EINVAL; + + if (cmd == CXL_MBOX_OP_SECURE_ERASE && + sec_out & CXL_PMEM_SEC_STATE_LOCKED) + return -EINVAL; + + rc = cxl_internal_send_cmd(mds, &mbox_cmd); + if (rc < 0) { + dev_err(cxlds->dev, "Failed to sanitize device : %d", rc); + return rc; + } + + return 0; +} +EXPORT_SYMBOL_NS_GPL(cxl_mem_sanitize, CXL); + static int add_dpa_res(struct device *dev, struct resource *parent, struct resource *res, resource_size_t start, resource_size_t size, const char *type) @@ -1100,8 +1167,9 @@ static int add_dpa_res(struct device *dev, struct resource *parent, return 0; } -int cxl_mem_create_range_info(struct cxl_dev_state *cxlds) +int cxl_mem_create_range_info(struct cxl_memdev_state *mds) { + struct cxl_dev_state *cxlds = &mds->cxlds; struct device *dev = cxlds->dev; int rc; @@ -1113,35 +1181,35 @@ int cxl_mem_create_range_info(struct cxl_dev_state *cxlds) } cxlds->dpa_res = - (struct resource)DEFINE_RES_MEM(0, cxlds->total_bytes); + (struct resource)DEFINE_RES_MEM(0, mds->total_bytes); - if (cxlds->partition_align_bytes == 0) { + if (mds->partition_align_bytes == 0) { rc = add_dpa_res(dev, &cxlds->dpa_res, &cxlds->ram_res, 0, - cxlds->volatile_only_bytes, "ram"); + mds->volatile_only_bytes, "ram"); if (rc) return rc; return add_dpa_res(dev, &cxlds->dpa_res, &cxlds->pmem_res, - cxlds->volatile_only_bytes, - cxlds->persistent_only_bytes, "pmem"); + mds->volatile_only_bytes, + mds->persistent_only_bytes, "pmem"); } - rc = cxl_mem_get_partition_info(cxlds); + rc = cxl_mem_get_partition_info(mds); if (rc) { dev_err(dev, "Failed to query partition information\n"); return rc; } rc = add_dpa_res(dev, &cxlds->dpa_res, &cxlds->ram_res, 0, - cxlds->active_volatile_bytes, "ram"); + mds->active_volatile_bytes, "ram"); if (rc) return rc; return add_dpa_res(dev, &cxlds->dpa_res, &cxlds->pmem_res, - cxlds->active_volatile_bytes, - cxlds->active_persistent_bytes, "pmem"); + mds->active_volatile_bytes, + mds->active_persistent_bytes, "pmem"); } EXPORT_SYMBOL_NS_GPL(cxl_mem_create_range_info, CXL); -int cxl_set_timestamp(struct cxl_dev_state *cxlds) +int cxl_set_timestamp(struct cxl_memdev_state *mds) { struct cxl_mbox_cmd mbox_cmd; struct cxl_mbox_set_timestamp_in pi; @@ -1154,7 +1222,7 @@ int cxl_set_timestamp(struct cxl_dev_state *cxlds) .payload_in = &pi, }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); /* * Command is optional. Devices may have another way of providing * a timestamp, or may return all 0s in timestamp fields. @@ -1170,18 +1238,18 @@ EXPORT_SYMBOL_NS_GPL(cxl_set_timestamp, CXL); int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len, struct cxl_region *cxlr) { - struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct cxl_mbox_poison_out *po; struct cxl_mbox_poison_in pi; struct cxl_mbox_cmd mbox_cmd; int nr_records = 0; int rc; - rc = mutex_lock_interruptible(&cxlds->poison.lock); + rc = mutex_lock_interruptible(&mds->poison.lock); if (rc) return rc; - po = cxlds->poison.list_out; + po = mds->poison.list_out; pi.offset = cpu_to_le64(offset); pi.length = cpu_to_le64(len / CXL_POISON_LEN_MULT); @@ -1189,13 +1257,13 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len, .opcode = CXL_MBOX_OP_GET_POISON, .size_in = sizeof(pi), .payload_in = &pi, - .size_out = cxlds->payload_size, + .size_out = mds->payload_size, .payload_out = po, .min_out = struct_size(po, record, 0), }; do { - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc) break; @@ -1206,14 +1274,14 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len, /* Protect against an uncleared _FLAG_MORE */ nr_records = nr_records + le16_to_cpu(po->count); - if (nr_records >= cxlds->poison.max_errors) { + if (nr_records >= mds->poison.max_errors) { dev_dbg(&cxlmd->dev, "Max Error Records reached: %d\n", nr_records); break; } } while (po->flags & CXL_POISON_FLAG_MORE); - mutex_unlock(&cxlds->poison.lock); + mutex_unlock(&mds->poison.lock); return rc; } EXPORT_SYMBOL_NS_GPL(cxl_mem_get_poison, CXL); @@ -1223,52 +1291,53 @@ static void free_poison_buf(void *buf) kvfree(buf); } -/* Get Poison List output buffer is protected by cxlds->poison.lock */ -static int cxl_poison_alloc_buf(struct cxl_dev_state *cxlds) +/* Get Poison List output buffer is protected by mds->poison.lock */ +static int cxl_poison_alloc_buf(struct cxl_memdev_state *mds) { - cxlds->poison.list_out = kvmalloc(cxlds->payload_size, GFP_KERNEL); - if (!cxlds->poison.list_out) + mds->poison.list_out = kvmalloc(mds->payload_size, GFP_KERNEL); + if (!mds->poison.list_out) return -ENOMEM; - return devm_add_action_or_reset(cxlds->dev, free_poison_buf, - cxlds->poison.list_out); + return devm_add_action_or_reset(mds->cxlds.dev, free_poison_buf, + mds->poison.list_out); } -int cxl_poison_state_init(struct cxl_dev_state *cxlds) +int cxl_poison_state_init(struct cxl_memdev_state *mds) { int rc; - if (!test_bit(CXL_POISON_ENABLED_LIST, cxlds->poison.enabled_cmds)) + if (!test_bit(CXL_POISON_ENABLED_LIST, mds->poison.enabled_cmds)) return 0; - rc = cxl_poison_alloc_buf(cxlds); + rc = cxl_poison_alloc_buf(mds); if (rc) { - clear_bit(CXL_POISON_ENABLED_LIST, cxlds->poison.enabled_cmds); + clear_bit(CXL_POISON_ENABLED_LIST, mds->poison.enabled_cmds); return rc; } - mutex_init(&cxlds->poison.lock); + mutex_init(&mds->poison.lock); return 0; } EXPORT_SYMBOL_NS_GPL(cxl_poison_state_init, CXL); -struct cxl_dev_state *cxl_dev_state_create(struct device *dev) +struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev) { - struct cxl_dev_state *cxlds; + struct cxl_memdev_state *mds; - cxlds = devm_kzalloc(dev, sizeof(*cxlds), GFP_KERNEL); - if (!cxlds) { + mds = devm_kzalloc(dev, sizeof(*mds), GFP_KERNEL); + if (!mds) { dev_err(dev, "No memory available\n"); return ERR_PTR(-ENOMEM); } - mutex_init(&cxlds->mbox_mutex); - mutex_init(&cxlds->event.log_lock); - cxlds->dev = dev; + mutex_init(&mds->mbox_mutex); + mutex_init(&mds->event.log_lock); + mds->cxlds.dev = dev; + mds->cxlds.type = CXL_DEVTYPE_CLASSMEM; - return cxlds; + return mds; } -EXPORT_SYMBOL_NS_GPL(cxl_dev_state_create, CXL); +EXPORT_SYMBOL_NS_GPL(cxl_memdev_state_create, CXL); void __init cxl_mbox_init(void) { diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c index 057a43267290..f99e7ec3cc40 100644 --- a/drivers/cxl/core/memdev.c +++ b/drivers/cxl/core/memdev.c @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright(c) 2020 Intel Corporation. */ +#include <linux/io-64-nonatomic-lo-hi.h> +#include <linux/firmware.h> #include <linux/device.h> #include <linux/slab.h> #include <linux/idr.h> @@ -39,8 +41,11 @@ static ssize_t firmware_version_show(struct device *dev, { struct cxl_memdev *cxlmd = to_cxl_memdev(dev); struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); - return sysfs_emit(buf, "%.16s\n", cxlds->firmware_version); + if (!mds) + return sysfs_emit(buf, "\n"); + return sysfs_emit(buf, "%.16s\n", mds->firmware_version); } static DEVICE_ATTR_RO(firmware_version); @@ -49,8 +54,11 @@ static ssize_t payload_max_show(struct device *dev, { struct cxl_memdev *cxlmd = to_cxl_memdev(dev); struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); - return sysfs_emit(buf, "%zu\n", cxlds->payload_size); + if (!mds) + return sysfs_emit(buf, "\n"); + return sysfs_emit(buf, "%zu\n", mds->payload_size); } static DEVICE_ATTR_RO(payload_max); @@ -59,8 +67,11 @@ static ssize_t label_storage_size_show(struct device *dev, { struct cxl_memdev *cxlmd = to_cxl_memdev(dev); struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); - return sysfs_emit(buf, "%zu\n", cxlds->lsa_size); + if (!mds) + return sysfs_emit(buf, "\n"); + return sysfs_emit(buf, "%zu\n", mds->lsa_size); } static DEVICE_ATTR_RO(label_storage_size); @@ -107,6 +118,89 @@ static ssize_t numa_node_show(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RO(numa_node); +static ssize_t security_state_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cxl_memdev *cxlmd = to_cxl_memdev(dev); + struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); + u64 reg = readq(cxlds->regs.mbox + CXLDEV_MBOX_BG_CMD_STATUS_OFFSET); + u32 pct = FIELD_GET(CXLDEV_MBOX_BG_CMD_COMMAND_PCT_MASK, reg); + u16 cmd = FIELD_GET(CXLDEV_MBOX_BG_CMD_COMMAND_OPCODE_MASK, reg); + unsigned long state = mds->security.state; + + if (cmd == CXL_MBOX_OP_SANITIZE && pct != 100) + return sysfs_emit(buf, "sanitize\n"); + + if (!(state & CXL_PMEM_SEC_STATE_USER_PASS_SET)) + return sysfs_emit(buf, "disabled\n"); + if (state & CXL_PMEM_SEC_STATE_FROZEN || + state & CXL_PMEM_SEC_STATE_MASTER_PLIMIT || + state & CXL_PMEM_SEC_STATE_USER_PLIMIT) + return sysfs_emit(buf, "frozen\n"); + if (state & CXL_PMEM_SEC_STATE_LOCKED) + return sysfs_emit(buf, "locked\n"); + else + return sysfs_emit(buf, "unlocked\n"); +} +static struct device_attribute dev_attr_security_state = + __ATTR(state, 0444, security_state_show, NULL); + +static ssize_t security_sanitize_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct cxl_memdev *cxlmd = to_cxl_memdev(dev); + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); + struct cxl_port *port = cxlmd->endpoint; + bool sanitize; + ssize_t rc; + + if (kstrtobool(buf, &sanitize) || !sanitize) + return -EINVAL; + + if (!port || !is_cxl_endpoint(port)) + return -EINVAL; + + /* ensure no regions are mapped to this memdev */ + if (port->commit_end != -1) + return -EBUSY; + + rc = cxl_mem_sanitize(mds, CXL_MBOX_OP_SANITIZE); + + return rc ? rc : len; +} +static struct device_attribute dev_attr_security_sanitize = + __ATTR(sanitize, 0200, NULL, security_sanitize_store); + +static ssize_t security_erase_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct cxl_memdev *cxlmd = to_cxl_memdev(dev); + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); + struct cxl_port *port = cxlmd->endpoint; + ssize_t rc; + bool erase; + + if (kstrtobool(buf, &erase) || !erase) + return -EINVAL; + + if (!port || !is_cxl_endpoint(port)) + return -EINVAL; + + /* ensure no regions are mapped to this memdev */ + if (port->commit_end != -1) + return -EBUSY; + + rc = cxl_mem_sanitize(mds, CXL_MBOX_OP_SECURE_ERASE); + + return rc ? rc : len; +} +static struct device_attribute dev_attr_security_erase = + __ATTR(erase, 0200, NULL, security_erase_store); + static int cxl_get_poison_by_memdev(struct cxl_memdev *cxlmd) { struct cxl_dev_state *cxlds = cxlmd->cxlds; @@ -140,7 +234,7 @@ int cxl_trigger_poison_list(struct cxl_memdev *cxlmd) struct cxl_port *port; int rc; - port = dev_get_drvdata(&cxlmd->dev); + port = cxlmd->endpoint; if (!port || !is_cxl_endpoint(port)) return -EINVAL; @@ -198,7 +292,7 @@ static struct cxl_region *cxl_dpa_to_region(struct cxl_memdev *cxlmd, u64 dpa) ctx = (struct cxl_dpa_to_region_context) { .dpa = dpa, }; - port = dev_get_drvdata(&cxlmd->dev); + port = cxlmd->endpoint; if (port && is_cxl_endpoint(port) && port->commit_end != -1) device_for_each_child(&port->dev, &ctx, __cxl_dpa_to_region); @@ -231,7 +325,7 @@ static int cxl_validate_poison_dpa(struct cxl_memdev *cxlmd, u64 dpa) int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa) { - struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct cxl_mbox_inject_poison inject; struct cxl_poison_record record; struct cxl_mbox_cmd mbox_cmd; @@ -255,13 +349,13 @@ int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa) .size_in = sizeof(inject), .payload_in = &inject, }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc) goto out; cxlr = cxl_dpa_to_region(cxlmd, dpa); if (cxlr) - dev_warn_once(cxlds->dev, + dev_warn_once(mds->cxlds.dev, "poison inject dpa:%#llx region: %s\n", dpa, dev_name(&cxlr->dev)); @@ -279,7 +373,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_inject_poison, CXL); int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa) { - struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct cxl_mbox_clear_poison clear; struct cxl_poison_record record; struct cxl_mbox_cmd mbox_cmd; @@ -312,14 +406,15 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa) .payload_in = &clear, }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc) goto out; cxlr = cxl_dpa_to_region(cxlmd, dpa); if (cxlr) - dev_warn_once(cxlds->dev, "poison clear dpa:%#llx region: %s\n", - dpa, dev_name(&cxlr->dev)); + dev_warn_once(mds->cxlds.dev, + "poison clear dpa:%#llx region: %s\n", dpa, + dev_name(&cxlr->dev)); record = (struct cxl_poison_record) { .address = cpu_to_le64(dpa), @@ -352,6 +447,13 @@ static struct attribute *cxl_memdev_ram_attributes[] = { NULL, }; +static struct attribute *cxl_memdev_security_attributes[] = { + &dev_attr_security_state.attr, + &dev_attr_security_sanitize.attr, + &dev_attr_security_erase.attr, + NULL, +}; + static umode_t cxl_memdev_visible(struct kobject *kobj, struct attribute *a, int n) { @@ -375,10 +477,16 @@ static struct attribute_group cxl_memdev_pmem_attribute_group = { .attrs = cxl_memdev_pmem_attributes, }; +static struct attribute_group cxl_memdev_security_attribute_group = { + .name = "security", + .attrs = cxl_memdev_security_attributes, +}; + static const struct attribute_group *cxl_memdev_attribute_groups[] = { &cxl_memdev_attribute_group, &cxl_memdev_ram_attribute_group, &cxl_memdev_pmem_attribute_group, + &cxl_memdev_security_attribute_group, NULL, }; @@ -397,17 +505,18 @@ EXPORT_SYMBOL_NS_GPL(is_cxl_memdev, CXL); /** * set_exclusive_cxl_commands() - atomically disable user cxl commands - * @cxlds: The device state to operate on + * @mds: The device state to operate on * @cmds: bitmap of commands to mark exclusive * * Grab the cxl_memdev_rwsem in write mode to flush in-flight * invocations of the ioctl path and then disable future execution of * commands with the command ids set in @cmds. */ -void set_exclusive_cxl_commands(struct cxl_dev_state *cxlds, unsigned long *cmds) +void set_exclusive_cxl_commands(struct cxl_memdev_state *mds, + unsigned long *cmds) { down_write(&cxl_memdev_rwsem); - bitmap_or(cxlds->exclusive_cmds, cxlds->exclusive_cmds, cmds, + bitmap_or(mds->exclusive_cmds, mds->exclusive_cmds, cmds, CXL_MEM_COMMAND_ID_MAX); up_write(&cxl_memdev_rwsem); } @@ -415,23 +524,34 @@ EXPORT_SYMBOL_NS_GPL(set_exclusive_cxl_commands, CXL); /** * clear_exclusive_cxl_commands() - atomically enable user cxl commands - * @cxlds: The device state to modify + * @mds: The device state to modify * @cmds: bitmap of commands to mark available for userspace */ -void clear_exclusive_cxl_commands(struct cxl_dev_state *cxlds, unsigned long *cmds) +void clear_exclusive_cxl_commands(struct cxl_memdev_state *mds, + unsigned long *cmds) { down_write(&cxl_memdev_rwsem); - bitmap_andnot(cxlds->exclusive_cmds, cxlds->exclusive_cmds, cmds, + bitmap_andnot(mds->exclusive_cmds, mds->exclusive_cmds, cmds, CXL_MEM_COMMAND_ID_MAX); up_write(&cxl_memdev_rwsem); } EXPORT_SYMBOL_NS_GPL(clear_exclusive_cxl_commands, CXL); +static void cxl_memdev_security_shutdown(struct device *dev) +{ + struct cxl_memdev *cxlmd = to_cxl_memdev(dev); + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); + + if (mds->security.poll) + cancel_delayed_work_sync(&mds->security.poll_dwork); +} + static void cxl_memdev_shutdown(struct device *dev) { struct cxl_memdev *cxlmd = to_cxl_memdev(dev); down_write(&cxl_memdev_rwsem); + cxl_memdev_security_shutdown(dev); cxlmd->cxlds = NULL; up_write(&cxl_memdev_rwsem); } @@ -511,10 +631,12 @@ static long cxl_memdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct cxl_memdev *cxlmd = file->private_data; + struct cxl_dev_state *cxlds; int rc = -ENXIO; down_read(&cxl_memdev_rwsem); - if (cxlmd->cxlds) + cxlds = cxlmd->cxlds; + if (cxlds && cxlds->type == CXL_DEVTYPE_CLASSMEM) rc = __cxl_memdev_ioctl(cxlmd, cmd, arg); up_read(&cxl_memdev_rwsem); @@ -542,6 +664,316 @@ static int cxl_memdev_release_file(struct inode *inode, struct file *file) return 0; } +/** + * cxl_mem_get_fw_info - Get Firmware info + * @mds: The device data for the operation + * + * Retrieve firmware info for the device specified. + * + * Return: 0 if no error: or the result of the mailbox command. + * + * See CXL-3.0 8.2.9.3.1 Get FW Info + */ +static int cxl_mem_get_fw_info(struct cxl_memdev_state *mds) +{ + struct cxl_mbox_get_fw_info info; + struct cxl_mbox_cmd mbox_cmd; + int rc; + + mbox_cmd = (struct cxl_mbox_cmd) { + .opcode = CXL_MBOX_OP_GET_FW_INFO, + .size_out = sizeof(info), + .payload_out = &info, + }; + + rc = cxl_internal_send_cmd(mds, &mbox_cmd); + if (rc < 0) + return rc; + + mds->fw.num_slots = info.num_slots; + mds->fw.cur_slot = FIELD_GET(CXL_FW_INFO_SLOT_INFO_CUR_MASK, + info.slot_info); + + return 0; +} + +/** + * cxl_mem_activate_fw - Activate Firmware + * @mds: The device data for the operation + * @slot: slot number to activate + * + * Activate firmware in a given slot for the device specified. + * + * Return: 0 if no error: or the result of the mailbox command. + * + * See CXL-3.0 8.2.9.3.3 Activate FW + */ +static int cxl_mem_activate_fw(struct cxl_memdev_state *mds, int slot) +{ + struct cxl_mbox_activate_fw activate; + struct cxl_mbox_cmd mbox_cmd; + + if (slot == 0 || slot > mds->fw.num_slots) + return -EINVAL; + + mbox_cmd = (struct cxl_mbox_cmd) { + .opcode = CXL_MBOX_OP_ACTIVATE_FW, + .size_in = sizeof(activate), + .payload_in = &activate, + }; + + /* Only offline activation supported for now */ + activate.action = CXL_FW_ACTIVATE_OFFLINE; + activate.slot = slot; + + return cxl_internal_send_cmd(mds, &mbox_cmd); +} + +/** + * cxl_mem_abort_fw_xfer - Abort an in-progress FW transfer + * @mds: The device data for the operation + * + * Abort an in-progress firmware transfer for the device specified. + * + * Return: 0 if no error: or the result of the mailbox command. + * + * See CXL-3.0 8.2.9.3.2 Transfer FW + */ +static int cxl_mem_abort_fw_xfer(struct cxl_memdev_state *mds) +{ + struct cxl_mbox_transfer_fw *transfer; + struct cxl_mbox_cmd mbox_cmd; + int rc; + + transfer = kzalloc(struct_size(transfer, data, 0), GFP_KERNEL); + if (!transfer) + return -ENOMEM; + + /* Set a 1s poll interval and a total wait time of 30s */ + mbox_cmd = (struct cxl_mbox_cmd) { + .opcode = CXL_MBOX_OP_TRANSFER_FW, + .size_in = sizeof(*transfer), + .payload_in = transfer, + .poll_interval_ms = 1000, + .poll_count = 30, + }; + + transfer->action = CXL_FW_TRANSFER_ACTION_ABORT; + + rc = cxl_internal_send_cmd(mds, &mbox_cmd); + kfree(transfer); + return rc; +} + +static void cxl_fw_cleanup(struct fw_upload *fwl) +{ + struct cxl_memdev_state *mds = fwl->dd_handle; + + mds->fw.next_slot = 0; +} + +static int cxl_fw_do_cancel(struct fw_upload *fwl) +{ + struct cxl_memdev_state *mds = fwl->dd_handle; + struct cxl_dev_state *cxlds = &mds->cxlds; + struct cxl_memdev *cxlmd = cxlds->cxlmd; + int rc; + + rc = cxl_mem_abort_fw_xfer(mds); + if (rc < 0) + dev_err(&cxlmd->dev, "Error aborting FW transfer: %d\n", rc); + + return FW_UPLOAD_ERR_CANCELED; +} + +static enum fw_upload_err cxl_fw_prepare(struct fw_upload *fwl, const u8 *data, + u32 size) +{ + struct cxl_memdev_state *mds = fwl->dd_handle; + struct cxl_mbox_transfer_fw *transfer; + + if (!size) + return FW_UPLOAD_ERR_INVALID_SIZE; + + mds->fw.oneshot = struct_size(transfer, data, size) < + mds->payload_size; + + if (cxl_mem_get_fw_info(mds)) + return FW_UPLOAD_ERR_HW_ERROR; + + /* + * So far no state has been changed, hence no other cleanup is + * necessary. Simply return the cancelled status. + */ + if (test_and_clear_bit(CXL_FW_CANCEL, mds->fw.state)) + return FW_UPLOAD_ERR_CANCELED; + + return FW_UPLOAD_ERR_NONE; +} + +static enum fw_upload_err cxl_fw_write(struct fw_upload *fwl, const u8 *data, + u32 offset, u32 size, u32 *written) +{ + struct cxl_memdev_state *mds = fwl->dd_handle; + struct cxl_dev_state *cxlds = &mds->cxlds; + struct cxl_memdev *cxlmd = cxlds->cxlmd; + struct cxl_mbox_transfer_fw *transfer; + struct cxl_mbox_cmd mbox_cmd; + u32 cur_size, remaining; + size_t size_in; + int rc; + + *written = 0; + + /* Offset has to be aligned to 128B (CXL-3.0 8.2.9.3.2 Table 8-57) */ + if (!IS_ALIGNED(offset, CXL_FW_TRANSFER_ALIGNMENT)) { + dev_err(&cxlmd->dev, + "misaligned offset for FW transfer slice (%u)\n", + offset); + return FW_UPLOAD_ERR_RW_ERROR; + } + + /* + * Pick transfer size based on mds->payload_size @size must bw 128-byte + * aligned, ->payload_size is a power of 2 starting at 256 bytes, and + * sizeof(*transfer) is 128. These constraints imply that @cur_size + * will always be 128b aligned. + */ + cur_size = min_t(size_t, size, mds->payload_size - sizeof(*transfer)); + + remaining = size - cur_size; + size_in = struct_size(transfer, data, cur_size); + + if (test_and_clear_bit(CXL_FW_CANCEL, mds->fw.state)) + return cxl_fw_do_cancel(fwl); + + /* + * Slot numbers are 1-indexed + * cur_slot is the 0-indexed next_slot (i.e. 'cur_slot - 1 + 1') + * Check for rollover using modulo, and 1-index it by adding 1 + */ + mds->fw.next_slot = (mds->fw.cur_slot % mds->fw.num_slots) + 1; + + /* Do the transfer via mailbox cmd */ + transfer = kzalloc(size_in, GFP_KERNEL); + if (!transfer) + return FW_UPLOAD_ERR_RW_ERROR; + + transfer->offset = cpu_to_le32(offset / CXL_FW_TRANSFER_ALIGNMENT); + memcpy(transfer->data, data + offset, cur_size); + if (mds->fw.oneshot) { + transfer->action = CXL_FW_TRANSFER_ACTION_FULL; + transfer->slot = mds->fw.next_slot; + } else { + if (offset == 0) { + transfer->action = CXL_FW_TRANSFER_ACTION_INITIATE; + } else if (remaining == 0) { + transfer->action = CXL_FW_TRANSFER_ACTION_END; + transfer->slot = mds->fw.next_slot; + } else { + transfer->action = CXL_FW_TRANSFER_ACTION_CONTINUE; + } + } + + mbox_cmd = (struct cxl_mbox_cmd) { + .opcode = CXL_MBOX_OP_TRANSFER_FW, + .size_in = size_in, + .payload_in = transfer, + .poll_interval_ms = 1000, + .poll_count = 30, + }; + + rc = cxl_internal_send_cmd(mds, &mbox_cmd); + if (rc < 0) { + rc = FW_UPLOAD_ERR_RW_ERROR; + goto out_free; + } + + *written = cur_size; + + /* Activate FW if oneshot or if the last slice was written */ + if (mds->fw.oneshot || remaining == 0) { + dev_dbg(&cxlmd->dev, "Activating firmware slot: %d\n", + mds->fw.next_slot); + rc = cxl_mem_activate_fw(mds, mds->fw.next_slot); + if (rc < 0) { + dev_err(&cxlmd->dev, "Error activating firmware: %d\n", + rc); + rc = FW_UPLOAD_ERR_HW_ERROR; + goto out_free; + } + } + + rc = FW_UPLOAD_ERR_NONE; + +out_free: + kfree(transfer); + return rc; +} + +static enum fw_upload_err cxl_fw_poll_complete(struct fw_upload *fwl) +{ + struct cxl_memdev_state *mds = fwl->dd_handle; + + /* + * cxl_internal_send_cmd() handles background operations synchronously. + * No need to wait for completions here - any errors would've been + * reported and handled during the ->write() call(s). + * Just check if a cancel request was received, and return success. + */ + if (test_and_clear_bit(CXL_FW_CANCEL, mds->fw.state)) + return cxl_fw_do_cancel(fwl); + + return FW_UPLOAD_ERR_NONE; +} + +static void cxl_fw_cancel(struct fw_upload *fwl) +{ + struct cxl_memdev_state *mds = fwl->dd_handle; + + set_bit(CXL_FW_CANCEL, mds->fw.state); +} + +static const struct fw_upload_ops cxl_memdev_fw_ops = { + .prepare = cxl_fw_prepare, + .write = cxl_fw_write, + .poll_complete = cxl_fw_poll_complete, + .cancel = cxl_fw_cancel, + .cleanup = cxl_fw_cleanup, +}; + +static void devm_cxl_remove_fw_upload(void *fwl) +{ + firmware_upload_unregister(fwl); +} + +int cxl_memdev_setup_fw_upload(struct cxl_memdev_state *mds) +{ + struct cxl_dev_state *cxlds = &mds->cxlds; + struct device *dev = &cxlds->cxlmd->dev; + struct fw_upload *fwl; + int rc; + + if (!test_bit(CXL_MEM_COMMAND_ID_GET_FW_INFO, mds->enabled_cmds)) + return 0; + + fwl = firmware_upload_register(THIS_MODULE, dev, dev_name(dev), + &cxl_memdev_fw_ops, mds); + if (IS_ERR(fwl)) + return dev_err_probe(dev, PTR_ERR(fwl), + "Failed to register firmware loader\n"); + + rc = devm_add_action_or_reset(cxlds->dev, devm_cxl_remove_fw_upload, + fwl); + if (rc) + dev_err(dev, + "Failed to add firmware loader remove action: %d\n", + rc); + + return rc; +} +EXPORT_SYMBOL_NS_GPL(cxl_memdev_setup_fw_upload, CXL); + static const struct file_operations cxl_memdev_fops = { .owner = THIS_MODULE, .unlocked_ioctl = cxl_memdev_ioctl, @@ -551,6 +983,35 @@ static const struct file_operations cxl_memdev_fops = { .llseek = noop_llseek, }; +static void put_sanitize(void *data) +{ + struct cxl_memdev_state *mds = data; + + sysfs_put(mds->security.sanitize_node); +} + +static int cxl_memdev_security_init(struct cxl_memdev *cxlmd) +{ + struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); + struct device *dev = &cxlmd->dev; + struct kernfs_node *sec; + + sec = sysfs_get_dirent(dev->kobj.sd, "security"); + if (!sec) { + dev_err(dev, "sysfs_get_dirent 'security' failed\n"); + return -ENODEV; + } + mds->security.sanitize_node = sysfs_get_dirent(sec, "state"); + sysfs_put(sec); + if (!mds->security.sanitize_node) { + dev_err(dev, "sysfs_get_dirent 'state' failed\n"); + return -ENODEV; + } + + return devm_add_action_or_reset(cxlds->dev, put_sanitize, mds); + } + struct cxl_memdev *devm_cxl_add_memdev(struct cxl_dev_state *cxlds) { struct cxl_memdev *cxlmd; @@ -579,6 +1040,10 @@ struct cxl_memdev *devm_cxl_add_memdev(struct cxl_dev_state *cxlds) if (rc) goto err; + rc = cxl_memdev_security_init(cxlmd); + if (rc) + goto err; + rc = devm_add_action_or_reset(cxlds->dev, cxl_memdev_unregister, cxlmd); if (rc) return ERR_PTR(rc); diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c index 67f4ab6daa34..c7a7887ebdcf 100644 --- a/drivers/cxl/core/pci.c +++ b/drivers/cxl/core/pci.c @@ -67,7 +67,7 @@ static int match_add_dports(struct pci_dev *pdev, void *data) /** * devm_cxl_port_enumerate_dports - enumerate downstream ports of the upstream port - * @port: cxl_port whose ->uport is the upstream of dports to be enumerated + * @port: cxl_port whose ->uport_dev is the upstream of dports to be enumerated * * Returns a positive number of dports enumerated or a negative error * code. @@ -308,36 +308,17 @@ static void disable_hdm(void *_cxlhdm) hdm + CXL_HDM_DECODER_CTRL_OFFSET); } -int devm_cxl_enable_hdm(struct cxl_port *port, struct cxl_hdm *cxlhdm) +static int devm_cxl_enable_hdm(struct device *host, struct cxl_hdm *cxlhdm) { - void __iomem *hdm; + void __iomem *hdm = cxlhdm->regs.hdm_decoder; u32 global_ctrl; - /* - * If the hdm capability was not mapped there is nothing to enable and - * the caller is responsible for what happens next. For example, - * emulate a passthrough decoder. - */ - if (IS_ERR(cxlhdm)) - return 0; - - hdm = cxlhdm->regs.hdm_decoder; global_ctrl = readl(hdm + CXL_HDM_DECODER_CTRL_OFFSET); - - /* - * If the HDM decoder capability was enabled on entry, skip - * registering disable_hdm() since this decode capability may be - * owned by platform firmware. - */ - if (global_ctrl & CXL_HDM_DECODER_ENABLE) - return 0; - writel(global_ctrl | CXL_HDM_DECODER_ENABLE, hdm + CXL_HDM_DECODER_CTRL_OFFSET); - return devm_add_action_or_reset(&port->dev, disable_hdm, cxlhdm); + return devm_add_action_or_reset(host, disable_hdm, cxlhdm); } -EXPORT_SYMBOL_NS_GPL(devm_cxl_enable_hdm, CXL); int cxl_dvsec_rr_decode(struct device *dev, int d, struct cxl_endpoint_dvsec_info *info) @@ -511,7 +492,7 @@ int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm, if (info->mem_enabled) return 0; - rc = devm_cxl_enable_hdm(port, cxlhdm); + rc = devm_cxl_enable_hdm(&port->dev, cxlhdm); if (rc) return rc; @@ -622,7 +603,7 @@ static int cxl_cdat_read_table(struct device *dev, */ void read_cdat_data(struct cxl_port *port) { - struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport); + struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev); struct device *host = cxlmd->dev.parent; struct device *dev = &port->dev; struct pci_doe_mb *cdat_doe; diff --git a/drivers/cxl/core/pmem.c b/drivers/cxl/core/pmem.c index f8c38d997252..fc94f5240327 100644 --- a/drivers/cxl/core/pmem.c +++ b/drivers/cxl/core/pmem.c @@ -64,7 +64,7 @@ static int match_nvdimm_bridge(struct device *dev, void *data) struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_memdev *cxlmd) { - struct cxl_port *port = find_cxl_root(dev_get_drvdata(&cxlmd->dev)); + struct cxl_port *port = find_cxl_root(cxlmd->endpoint); struct device *dev; if (!port) diff --git a/drivers/cxl/core/pmu.c b/drivers/cxl/core/pmu.c new file mode 100644 index 000000000000..7684c843e5a5 --- /dev/null +++ b/drivers/cxl/core/pmu.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2023 Huawei. All rights reserved. */ + +#include <linux/device.h> +#include <linux/slab.h> +#include <linux/idr.h> +#include <cxlmem.h> +#include <pmu.h> +#include <cxl.h> +#include "core.h" + +static void cxl_pmu_release(struct device *dev) +{ + struct cxl_pmu *pmu = to_cxl_pmu(dev); + + kfree(pmu); +} + +const struct device_type cxl_pmu_type = { + .name = "cxl_pmu", + .release = cxl_pmu_release, +}; + +static void remove_dev(void *dev) +{ + device_del(dev); +} + +int devm_cxl_pmu_add(struct device *parent, struct cxl_pmu_regs *regs, + int assoc_id, int index, enum cxl_pmu_type type) +{ + struct cxl_pmu *pmu; + struct device *dev; + int rc; + + pmu = kzalloc(sizeof(*pmu), GFP_KERNEL); + if (!pmu) + return -ENOMEM; + + pmu->assoc_id = assoc_id; + pmu->index = index; + pmu->type = type; + pmu->base = regs->pmu; + dev = &pmu->dev; + device_initialize(dev); + device_set_pm_not_required(dev); + dev->parent = parent; + dev->bus = &cxl_bus_type; + dev->type = &cxl_pmu_type; + switch (pmu->type) { + case CXL_PMU_MEMDEV: + rc = dev_set_name(dev, "pmu_mem%d.%d", assoc_id, index); + break; + } + if (rc) + goto err; + + rc = device_add(dev); + if (rc) + goto err; + + return devm_add_action_or_reset(parent, remove_dev, dev); + +err: + put_device(&pmu->dev); + return rc; +} +EXPORT_SYMBOL_NS_GPL(devm_cxl_pmu_add, CXL); diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c index e7c284c890bc..724be8448eb4 100644 --- a/drivers/cxl/core/port.c +++ b/drivers/cxl/core/port.c @@ -56,6 +56,8 @@ static int cxl_device_id(const struct device *dev) return CXL_DEVICE_MEMORY_EXPANDER; if (dev->type == CXL_REGION_TYPE()) return CXL_DEVICE_REGION; + if (dev->type == &cxl_pmu_type) + return CXL_DEVICE_PMU; return 0; } @@ -117,9 +119,9 @@ static ssize_t target_type_show(struct device *dev, struct cxl_decoder *cxld = to_cxl_decoder(dev); switch (cxld->target_type) { - case CXL_DECODER_ACCELERATOR: + case CXL_DECODER_DEVMEM: return sysfs_emit(buf, "accelerator\n"); - case CXL_DECODER_EXPANDER: + case CXL_DECODER_HOSTONLYMEM: return sysfs_emit(buf, "expander\n"); } return -ENXIO; @@ -561,9 +563,9 @@ static void unregister_port(void *_port) * unregistered while holding their parent port lock. */ if (!parent) - lock_dev = port->uport; + lock_dev = port->uport_dev; else if (is_cxl_root(parent)) - lock_dev = parent->uport; + lock_dev = parent->uport_dev; else lock_dev = &parent->dev; @@ -583,7 +585,8 @@ static int devm_cxl_link_uport(struct device *host, struct cxl_port *port) { int rc; - rc = sysfs_create_link(&port->dev.kobj, &port->uport->kobj, "uport"); + rc = sysfs_create_link(&port->dev.kobj, &port->uport_dev->kobj, + "uport"); if (rc) return rc; return devm_add_action_or_reset(host, cxl_unlink_uport, port); @@ -605,7 +608,7 @@ static int devm_cxl_link_parent_dport(struct device *host, if (!parent_dport) return 0; - rc = sysfs_create_link(&port->dev.kobj, &parent_dport->dport->kobj, + rc = sysfs_create_link(&port->dev.kobj, &parent_dport->dport_dev->kobj, "parent_dport"); if (rc) return rc; @@ -614,7 +617,7 @@ static int devm_cxl_link_parent_dport(struct device *host, static struct lock_class_key cxl_port_key; -static struct cxl_port *cxl_port_alloc(struct device *uport, +static struct cxl_port *cxl_port_alloc(struct device *uport_dev, resource_size_t component_reg_phys, struct cxl_dport *parent_dport) { @@ -630,7 +633,7 @@ static struct cxl_port *cxl_port_alloc(struct device *uport, if (rc < 0) goto err; port->id = rc; - port->uport = uport; + port->uport_dev = uport_dev; /* * The top-level cxl_port "cxl_root" does not have a cxl_port as @@ -658,12 +661,13 @@ static struct cxl_port *cxl_port_alloc(struct device *uport, if (iter->host_bridge) port->host_bridge = iter->host_bridge; else if (parent_dport->rch) - port->host_bridge = parent_dport->dport; + port->host_bridge = parent_dport->dport_dev; else - port->host_bridge = iter->uport; - dev_dbg(uport, "host-bridge: %s\n", dev_name(port->host_bridge)); + port->host_bridge = iter->uport_dev; + dev_dbg(uport_dev, "host-bridge: %s\n", + dev_name(port->host_bridge)); } else - dev->parent = uport; + dev->parent = uport_dev; port->component_reg_phys = component_reg_phys; ida_init(&port->decoder_ida); @@ -686,8 +690,38 @@ err: return ERR_PTR(rc); } +static int cxl_setup_comp_regs(struct device *dev, struct cxl_register_map *map, + resource_size_t component_reg_phys) +{ + if (component_reg_phys == CXL_RESOURCE_NONE) + return 0; + + *map = (struct cxl_register_map) { + .dev = dev, + .reg_type = CXL_REGLOC_RBI_COMPONENT, + .resource = component_reg_phys, + .max_size = CXL_COMPONENT_REG_BLOCK_SIZE, + }; + + return cxl_setup_regs(map); +} + +static inline int cxl_port_setup_regs(struct cxl_port *port, + resource_size_t component_reg_phys) +{ + return cxl_setup_comp_regs(&port->dev, &port->comp_map, + component_reg_phys); +} + +static inline int cxl_dport_setup_regs(struct cxl_dport *dport, + resource_size_t component_reg_phys) +{ + return cxl_setup_comp_regs(dport->dport_dev, &dport->comp_map, + component_reg_phys); +} + static struct cxl_port *__devm_cxl_add_port(struct device *host, - struct device *uport, + struct device *uport_dev, resource_size_t component_reg_phys, struct cxl_dport *parent_dport) { @@ -695,12 +729,12 @@ static struct cxl_port *__devm_cxl_add_port(struct device *host, struct device *dev; int rc; - port = cxl_port_alloc(uport, component_reg_phys, parent_dport); + port = cxl_port_alloc(uport_dev, component_reg_phys, parent_dport); if (IS_ERR(port)) return port; dev = &port->dev; - if (is_cxl_memdev(uport)) + if (is_cxl_memdev(uport_dev)) rc = dev_set_name(dev, "endpoint%d", port->id); else if (parent_dport) rc = dev_set_name(dev, "port%d", port->id); @@ -709,6 +743,10 @@ static struct cxl_port *__devm_cxl_add_port(struct device *host, if (rc) goto err; + rc = cxl_port_setup_regs(port, component_reg_phys); + if (rc) + goto err; + rc = device_add(dev); if (rc) goto err; @@ -735,28 +773,29 @@ err: /** * devm_cxl_add_port - register a cxl_port in CXL memory decode hierarchy * @host: host device for devm operations - * @uport: "physical" device implementing this upstream port + * @uport_dev: "physical" device implementing this upstream port * @component_reg_phys: (optional) for configurable cxl_port instances * @parent_dport: next hop up in the CXL memory decode hierarchy */ -struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport, +struct cxl_port *devm_cxl_add_port(struct device *host, + struct device *uport_dev, resource_size_t component_reg_phys, struct cxl_dport *parent_dport) { struct cxl_port *port, *parent_port; - port = __devm_cxl_add_port(host, uport, component_reg_phys, + port = __devm_cxl_add_port(host, uport_dev, component_reg_phys, parent_dport); parent_port = parent_dport ? parent_dport->port : NULL; if (IS_ERR(port)) { - dev_dbg(uport, "Failed to add%s%s%s: %ld\n", + dev_dbg(uport_dev, "Failed to add%s%s%s: %ld\n", parent_port ? " port to " : "", parent_port ? dev_name(&parent_port->dev) : "", parent_port ? "" : " root port", PTR_ERR(port)); } else { - dev_dbg(uport, "%s added%s%s%s\n", + dev_dbg(uport_dev, "%s added%s%s%s\n", dev_name(&port->dev), parent_port ? " to " : "", parent_port ? dev_name(&parent_port->dev) : "", @@ -773,33 +812,34 @@ struct pci_bus *cxl_port_to_pci_bus(struct cxl_port *port) if (is_cxl_root(port)) return NULL; - if (dev_is_pci(port->uport)) { - struct pci_dev *pdev = to_pci_dev(port->uport); + if (dev_is_pci(port->uport_dev)) { + struct pci_dev *pdev = to_pci_dev(port->uport_dev); return pdev->subordinate; } - return xa_load(&cxl_root_buses, (unsigned long)port->uport); + return xa_load(&cxl_root_buses, (unsigned long)port->uport_dev); } EXPORT_SYMBOL_NS_GPL(cxl_port_to_pci_bus, CXL); -static void unregister_pci_bus(void *uport) +static void unregister_pci_bus(void *uport_dev) { - xa_erase(&cxl_root_buses, (unsigned long)uport); + xa_erase(&cxl_root_buses, (unsigned long)uport_dev); } -int devm_cxl_register_pci_bus(struct device *host, struct device *uport, +int devm_cxl_register_pci_bus(struct device *host, struct device *uport_dev, struct pci_bus *bus) { int rc; - if (dev_is_pci(uport)) + if (dev_is_pci(uport_dev)) return -EINVAL; - rc = xa_insert(&cxl_root_buses, (unsigned long)uport, bus, GFP_KERNEL); + rc = xa_insert(&cxl_root_buses, (unsigned long)uport_dev, bus, + GFP_KERNEL); if (rc) return rc; - return devm_add_action_or_reset(host, unregister_pci_bus, uport); + return devm_add_action_or_reset(host, unregister_pci_bus, uport_dev); } EXPORT_SYMBOL_NS_GPL(devm_cxl_register_pci_bus, CXL); @@ -847,22 +887,22 @@ static struct cxl_dport *find_dport(struct cxl_port *port, int id) return NULL; } -static int add_dport(struct cxl_port *port, struct cxl_dport *new) +static int add_dport(struct cxl_port *port, struct cxl_dport *dport) { struct cxl_dport *dup; int rc; device_lock_assert(&port->dev); - dup = find_dport(port, new->port_id); + dup = find_dport(port, dport->port_id); if (dup) { dev_err(&port->dev, "unable to add dport%d-%s non-unique port id (%s)\n", - new->port_id, dev_name(new->dport), - dev_name(dup->dport)); + dport->port_id, dev_name(dport->dport_dev), + dev_name(dup->dport_dev)); return -EBUSY; } - rc = xa_insert(&port->dports, (unsigned long)new->dport, new, + rc = xa_insert(&port->dports, (unsigned long)dport->dport_dev, dport, GFP_KERNEL); if (rc) return rc; @@ -895,8 +935,8 @@ static void cxl_dport_remove(void *data) struct cxl_dport *dport = data; struct cxl_port *port = dport->port; - xa_erase(&port->dports, (unsigned long) dport->dport); - put_device(dport->dport); + xa_erase(&port->dports, (unsigned long) dport->dport_dev); + put_device(dport->dport_dev); } static void cxl_dport_unlink(void *data) @@ -920,7 +960,7 @@ __devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev, int rc; if (is_cxl_root(port)) - host = port->uport; + host = port->uport_dev; else host = &port->dev; @@ -938,13 +978,29 @@ __devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev, if (!dport) return ERR_PTR(-ENOMEM); - dport->dport = dport_dev; + if (rcrb != CXL_RESOURCE_NONE) { + dport->rcrb.base = rcrb; + component_reg_phys = __rcrb_to_component(dport_dev, &dport->rcrb, + CXL_RCRB_DOWNSTREAM); + if (component_reg_phys == CXL_RESOURCE_NONE) { + dev_warn(dport_dev, "Invalid Component Registers in RCRB"); + return ERR_PTR(-ENXIO); + } + + dport->rch = true; + } + + if (component_reg_phys != CXL_RESOURCE_NONE) + dev_dbg(dport_dev, "Component Registers found for dport: %pa\n", + &component_reg_phys); + + dport->dport_dev = dport_dev; dport->port_id = port_id; - dport->component_reg_phys = component_reg_phys; dport->port = port; - if (rcrb != CXL_RESOURCE_NONE) - dport->rch = true; - dport->rcrb = rcrb; + + rc = cxl_dport_setup_regs(dport, component_reg_phys); + if (rc) + return ERR_PTR(rc); cond_cxl_root_lock(port); rc = add_dport(port, dport); @@ -1004,14 +1060,12 @@ EXPORT_SYMBOL_NS_GPL(devm_cxl_add_dport, CXL); * @port: the cxl_port that references this dport * @dport_dev: firmware or PCI device representing the dport * @port_id: identifier for this dport in a decoder's target list - * @component_reg_phys: optional location of CXL component registers * @rcrb: mandatory location of a Root Complex Register Block * * See CXL 3.0 9.11.8 CXL Devices Attached to an RCH */ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port, struct device *dport_dev, int port_id, - resource_size_t component_reg_phys, resource_size_t rcrb) { struct cxl_dport *dport; @@ -1022,7 +1076,7 @@ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port, } dport = __devm_cxl_add_dport(port, dport_dev, port_id, - component_reg_phys, rcrb); + CXL_RESOURCE_NONE, rcrb); if (IS_ERR(dport)) { dev_dbg(dport_dev, "failed to add RCH dport to %s: %ld\n", dev_name(&port->dev), PTR_ERR(dport)); @@ -1161,7 +1215,7 @@ static struct device *grandparent(struct device *dev) static void delete_endpoint(void *data) { struct cxl_memdev *cxlmd = data; - struct cxl_port *endpoint = dev_get_drvdata(&cxlmd->dev); + struct cxl_port *endpoint = cxlmd->endpoint; struct cxl_port *parent_port; struct device *parent; @@ -1176,6 +1230,7 @@ static void delete_endpoint(void *data) devm_release_action(parent, cxl_unlink_uport, endpoint); devm_release_action(parent, unregister_port, endpoint); } + cxlmd->endpoint = NULL; device_unlock(parent); put_device(parent); out: @@ -1187,7 +1242,7 @@ int cxl_endpoint_autoremove(struct cxl_memdev *cxlmd, struct cxl_port *endpoint) struct device *dev = &cxlmd->dev; get_device(&endpoint->dev); - dev_set_drvdata(dev, endpoint); + cxlmd->endpoint = endpoint; cxlmd->depth = endpoint->depth; return devm_add_action_or_reset(dev, delete_endpoint, cxlmd); } @@ -1363,7 +1418,7 @@ out: rc = PTR_ERR(port); else { dev_dbg(&cxlmd->dev, "add to new port %s:%s\n", - dev_name(&port->dev), dev_name(port->uport)); + dev_name(&port->dev), dev_name(port->uport_dev)); rc = cxl_add_ep(dport, &cxlmd->dev); if (rc == -EBUSY) { /* @@ -1425,7 +1480,8 @@ retry: if (port) { dev_dbg(&cxlmd->dev, "found already registered port %s:%s\n", - dev_name(&port->dev), dev_name(port->uport)); + dev_name(&port->dev), + dev_name(port->uport_dev)); rc = cxl_add_ep(dport, &cxlmd->dev); /* @@ -1465,6 +1521,13 @@ retry: } EXPORT_SYMBOL_NS_GPL(devm_cxl_enumerate_ports, CXL); +struct cxl_port *cxl_pci_find_port(struct pci_dev *pdev, + struct cxl_dport **dport) +{ + return find_cxl_port(pdev->dev.parent, dport); +} +EXPORT_SYMBOL_NS_GPL(cxl_pci_find_port, CXL); + struct cxl_port *cxl_mem_find_port(struct cxl_memdev *cxlmd, struct cxl_dport **dport) { @@ -1550,7 +1613,7 @@ static int cxl_decoder_init(struct cxl_port *port, struct cxl_decoder *cxld) /* Pre initialize an "empty" decoder */ cxld->interleave_ways = 1; cxld->interleave_granularity = PAGE_SIZE; - cxld->target_type = CXL_DECODER_EXPANDER; + cxld->target_type = CXL_DECODER_HOSTONLYMEM; cxld->hpa_range = (struct range) { .start = 0, .end = -1, diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c index f822de44bee0..e115ba382e04 100644 --- a/drivers/cxl/core/region.c +++ b/drivers/cxl/core/region.c @@ -125,10 +125,38 @@ static struct cxl_region_ref *cxl_rr_load(struct cxl_port *port, return xa_load(&port->regions, (unsigned long)cxlr); } +static int cxl_region_invalidate_memregion(struct cxl_region *cxlr) +{ + if (!cpu_cache_has_invalidate_memregion()) { + if (IS_ENABLED(CONFIG_CXL_REGION_INVALIDATION_TEST)) { + dev_warn_once( + &cxlr->dev, + "Bypassing cpu_cache_invalidate_memregion() for testing!\n"); + return 0; + } else { + dev_err(&cxlr->dev, + "Failed to synchronize CPU cache state\n"); + return -ENXIO; + } + } + + cpu_cache_invalidate_memregion(IORES_DESC_CXL); + return 0; +} + static int cxl_region_decode_reset(struct cxl_region *cxlr, int count) { struct cxl_region_params *p = &cxlr->params; - int i; + int i, rc = 0; + + /* + * Before region teardown attempt to flush, and if the flush + * fails cancel the region teardown for data consistency + * concerns + */ + rc = cxl_region_invalidate_memregion(cxlr); + if (rc) + return rc; for (i = count - 1; i >= 0; i--) { struct cxl_endpoint_decoder *cxled = p->targets[i]; @@ -136,7 +164,6 @@ static int cxl_region_decode_reset(struct cxl_region *cxlr, int count) struct cxl_port *iter = cxled_to_port(cxled); struct cxl_dev_state *cxlds = cxlmd->cxlds; struct cxl_ep *ep; - int rc = 0; if (cxlds->rcd) goto endpoint_reset; @@ -155,14 +182,19 @@ static int cxl_region_decode_reset(struct cxl_region *cxlr, int count) rc = cxld->reset(cxld); if (rc) return rc; + set_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags); } endpoint_reset: rc = cxled->cxld.reset(&cxled->cxld); if (rc) return rc; + set_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags); } + /* all decoders associated with this region have been torn down */ + clear_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags); + return 0; } @@ -256,9 +288,19 @@ static ssize_t commit_store(struct device *dev, struct device_attribute *attr, goto out; } - if (commit) + /* + * Invalidate caches before region setup to drop any speculative + * consumption of this address space + */ + rc = cxl_region_invalidate_memregion(cxlr); + if (rc) + return rc; + + if (commit) { rc = cxl_region_decode_commit(cxlr); - else { + if (rc == 0) + p->state = CXL_CONFIG_COMMIT; + } else { p->state = CXL_CONFIG_RESET_PENDING; up_write(&cxl_region_rwsem); device_release_driver(&cxlr->dev); @@ -268,18 +310,20 @@ static ssize_t commit_store(struct device *dev, struct device_attribute *attr, * The lock was dropped, so need to revalidate that the reset is * still pending. */ - if (p->state == CXL_CONFIG_RESET_PENDING) + if (p->state == CXL_CONFIG_RESET_PENDING) { rc = cxl_region_decode_reset(cxlr, p->interleave_ways); + /* + * Revert to committed since there may still be active + * decoders associated with this region, or move forward + * to active to mark the reset successful + */ + if (rc) + p->state = CXL_CONFIG_COMMIT; + else + p->state = CXL_CONFIG_ACTIVE; + } } - if (rc) - goto out; - - if (commit) - p->state = CXL_CONFIG_COMMIT; - else if (p->state == CXL_CONFIG_RESET_PENDING) - p->state = CXL_CONFIG_ACTIVE; - out: up_write(&cxl_region_rwsem); @@ -809,6 +853,18 @@ static int cxl_rr_alloc_decoder(struct cxl_port *port, struct cxl_region *cxlr, return -EBUSY; } + /* + * Endpoints should already match the region type, but backstop that + * assumption with an assertion. Switch-decoders change mapping-type + * based on what is mapped when they are assigned to a region. + */ + dev_WARN_ONCE(&cxlr->dev, + port == cxled_to_port(cxled) && + cxld->target_type != cxlr->type, + "%s:%s mismatch decoder type %d -> %d\n", + dev_name(&cxled_to_memdev(cxled)->dev), + dev_name(&cxld->dev), cxld->target_type, cxlr->type); + cxld->target_type = cxlr->type; cxl_rr->decoder = cxld; return 0; } @@ -906,10 +962,10 @@ static int cxl_port_attach_region(struct cxl_port *port, dev_dbg(&cxlr->dev, "%s:%s %s add: %s:%s @ %d next: %s nr_eps: %d nr_targets: %d\n", - dev_name(port->uport), dev_name(&port->dev), + dev_name(port->uport_dev), dev_name(&port->dev), dev_name(&cxld->dev), dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), pos, - ep ? ep->next ? dev_name(ep->next->uport) : + ep ? ep->next ? dev_name(ep->next->uport_dev) : dev_name(&cxlmd->dev) : "none", cxl_rr->nr_eps, cxl_rr->nr_targets); @@ -984,7 +1040,7 @@ static int check_last_peer(struct cxl_endpoint_decoder *cxled, */ if (pos < distance) { dev_dbg(&cxlr->dev, "%s:%s: cannot host %s:%s at %d\n", - dev_name(port->uport), dev_name(&port->dev), + dev_name(port->uport_dev), dev_name(&port->dev), dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), pos); return -ENXIO; } @@ -994,7 +1050,7 @@ static int check_last_peer(struct cxl_endpoint_decoder *cxled, if (ep->dport != ep_peer->dport) { dev_dbg(&cxlr->dev, "%s:%s: %s:%s pos %d mismatched peer %s:%s\n", - dev_name(port->uport), dev_name(&port->dev), + dev_name(port->uport_dev), dev_name(&port->dev), dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), pos, dev_name(&cxlmd_peer->dev), dev_name(&cxled_peer->cxld.dev)); @@ -1026,7 +1082,7 @@ static int cxl_port_setup_targets(struct cxl_port *port, */ if (!is_power_of_2(cxl_rr->nr_targets)) { dev_dbg(&cxlr->dev, "%s:%s: invalid target count %d\n", - dev_name(port->uport), dev_name(&port->dev), + dev_name(port->uport_dev), dev_name(&port->dev), cxl_rr->nr_targets); return -EINVAL; } @@ -1076,7 +1132,7 @@ static int cxl_port_setup_targets(struct cxl_port *port, rc = granularity_to_eig(parent_ig, &peig); if (rc) { dev_dbg(&cxlr->dev, "%s:%s: invalid parent granularity: %d\n", - dev_name(parent_port->uport), + dev_name(parent_port->uport_dev), dev_name(&parent_port->dev), parent_ig); return rc; } @@ -1084,7 +1140,7 @@ static int cxl_port_setup_targets(struct cxl_port *port, rc = ways_to_eiw(parent_iw, &peiw); if (rc) { dev_dbg(&cxlr->dev, "%s:%s: invalid parent interleave: %d\n", - dev_name(parent_port->uport), + dev_name(parent_port->uport_dev), dev_name(&parent_port->dev), parent_iw); return rc; } @@ -1093,7 +1149,7 @@ static int cxl_port_setup_targets(struct cxl_port *port, rc = ways_to_eiw(iw, &eiw); if (rc) { dev_dbg(&cxlr->dev, "%s:%s: invalid port interleave: %d\n", - dev_name(port->uport), dev_name(&port->dev), iw); + dev_name(port->uport_dev), dev_name(&port->dev), iw); return rc; } @@ -1113,7 +1169,7 @@ static int cxl_port_setup_targets(struct cxl_port *port, rc = eig_to_granularity(eig, &ig); if (rc) { dev_dbg(&cxlr->dev, "%s:%s: invalid interleave: %d\n", - dev_name(port->uport), dev_name(&port->dev), + dev_name(port->uport_dev), dev_name(&port->dev), 256 << eig); return rc; } @@ -1126,11 +1182,11 @@ static int cxl_port_setup_targets(struct cxl_port *port, ((cxld->flags & CXL_DECODER_F_ENABLE) == 0)) { dev_err(&cxlr->dev, "%s:%s %s expected iw: %d ig: %d %pr\n", - dev_name(port->uport), dev_name(&port->dev), + dev_name(port->uport_dev), dev_name(&port->dev), __func__, iw, ig, p->res); dev_err(&cxlr->dev, "%s:%s %s got iw: %d ig: %d state: %s %#llx:%#llx\n", - dev_name(port->uport), dev_name(&port->dev), + dev_name(port->uport_dev), dev_name(&port->dev), __func__, cxld->interleave_ways, cxld->interleave_granularity, (cxld->flags & CXL_DECODER_F_ENABLE) ? @@ -1147,22 +1203,22 @@ static int cxl_port_setup_targets(struct cxl_port *port, .end = p->res->end, }; } - dev_dbg(&cxlr->dev, "%s:%s iw: %d ig: %d\n", dev_name(port->uport), + dev_dbg(&cxlr->dev, "%s:%s iw: %d ig: %d\n", dev_name(port->uport_dev), dev_name(&port->dev), iw, ig); add_target: if (cxl_rr->nr_targets_set == cxl_rr->nr_targets) { dev_dbg(&cxlr->dev, "%s:%s: targets full trying to add %s:%s at %d\n", - dev_name(port->uport), dev_name(&port->dev), + dev_name(port->uport_dev), dev_name(&port->dev), dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), pos); return -ENXIO; } if (test_bit(CXL_REGION_F_AUTO, &cxlr->flags)) { if (cxlsd->target[cxl_rr->nr_targets_set] != ep->dport) { dev_dbg(&cxlr->dev, "%s:%s: %s expected %s at %d\n", - dev_name(port->uport), dev_name(&port->dev), + dev_name(port->uport_dev), dev_name(&port->dev), dev_name(&cxlsd->cxld.dev), - dev_name(ep->dport->dport), + dev_name(ep->dport->dport_dev), cxl_rr->nr_targets_set); return -ENXIO; } @@ -1172,8 +1228,8 @@ add_target: out_target_set: cxl_rr->nr_targets_set += inc; dev_dbg(&cxlr->dev, "%s:%s target[%d] = %s for %s:%s @ %d\n", - dev_name(port->uport), dev_name(&port->dev), - cxl_rr->nr_targets_set - 1, dev_name(ep->dport->dport), + dev_name(port->uport_dev), dev_name(&port->dev), + cxl_rr->nr_targets_set - 1, dev_name(ep->dport->dport_dev), dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), pos); return 0; @@ -1492,7 +1548,7 @@ static int cmp_decode_pos(const void *a, const void *b) if (!dev) { struct range *range = &cxled_a->cxld.hpa_range; - dev_err(port->uport, + dev_err(port->uport_dev, "failed to find decoder that maps %#llx-%#llx\n", range->start, range->end); goto err; @@ -1507,14 +1563,15 @@ static int cmp_decode_pos(const void *a, const void *b) put_device(dev); if (a_pos < 0 || b_pos < 0) { - dev_err(port->uport, + dev_err(port->uport_dev, "failed to find shared decoder for %s and %s\n", dev_name(cxlmd_a->dev.parent), dev_name(cxlmd_b->dev.parent)); goto err; } - dev_dbg(port->uport, "%s comes %s %s\n", dev_name(cxlmd_a->dev.parent), + dev_dbg(port->uport_dev, "%s comes %s %s\n", + dev_name(cxlmd_a->dev.parent), a_pos - b_pos < 0 ? "before" : "after", dev_name(cxlmd_b->dev.parent)); @@ -1674,7 +1731,6 @@ static int cxl_region_attach(struct cxl_region *cxlr, if (rc) goto err_decrement; p->state = CXL_CONFIG_ACTIVE; - set_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags); } cxled->cxld.interleave_ways = p->interleave_ways; @@ -2059,11 +2115,11 @@ static struct cxl_region *devm_cxl_add_region(struct cxl_root_decoder *cxlrd, if (rc) goto err; - rc = devm_add_action_or_reset(port->uport, unregister_region, cxlr); + rc = devm_add_action_or_reset(port->uport_dev, unregister_region, cxlr); if (rc) return ERR_PTR(rc); - dev_dbg(port->uport, "%s: created %s\n", + dev_dbg(port->uport_dev, "%s: created %s\n", dev_name(&cxlrd->cxlsd.cxld.dev), dev_name(dev)); return cxlr; @@ -2103,7 +2159,7 @@ static struct cxl_region *__create_region(struct cxl_root_decoder *cxlrd, return ERR_PTR(-EBUSY); } - return devm_cxl_add_region(cxlrd, id, mode, CXL_DECODER_EXPANDER); + return devm_cxl_add_region(cxlrd, id, mode, CXL_DECODER_HOSTONLYMEM); } static ssize_t create_pmem_region_store(struct device *dev, @@ -2191,7 +2247,7 @@ static ssize_t delete_region_store(struct device *dev, if (IS_ERR(cxlr)) return PTR_ERR(cxlr); - devm_release_action(port->uport, unregister_region, cxlr); + devm_release_action(port->uport_dev, unregister_region, cxlr); put_device(&cxlr->dev); return len; @@ -2356,7 +2412,8 @@ int cxl_get_poison_by_endpoint(struct cxl_port *port) rc = device_for_each_child(&port->dev, &ctx, poison_by_decoder); if (rc == 1) - rc = cxl_get_poison_unmapped(to_cxl_memdev(port->uport), &ctx); + rc = cxl_get_poison_unmapped(to_cxl_memdev(port->uport_dev), + &ctx); up_read(&cxl_region_rwsem); return rc; @@ -2732,7 +2789,7 @@ static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd, err: up_write(&cxl_region_rwsem); - devm_release_action(port->uport, unregister_region, cxlr); + devm_release_action(port->uport_dev, unregister_region, cxlr); return ERR_PTR(rc); } @@ -2803,30 +2860,6 @@ out: } EXPORT_SYMBOL_NS_GPL(cxl_add_to_region, CXL); -static int cxl_region_invalidate_memregion(struct cxl_region *cxlr) -{ - if (!test_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags)) - return 0; - - if (!cpu_cache_has_invalidate_memregion()) { - if (IS_ENABLED(CONFIG_CXL_REGION_INVALIDATION_TEST)) { - dev_warn_once( - &cxlr->dev, - "Bypassing cpu_cache_invalidate_memregion() for testing!\n"); - clear_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags); - return 0; - } else { - dev_err(&cxlr->dev, - "Failed to synchronize CPU cache state\n"); - return -ENXIO; - } - } - - cpu_cache_invalidate_memregion(IORES_DESC_CXL); - clear_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags); - return 0; -} - static int is_system_ram(struct resource *res, void *arg) { struct cxl_region *cxlr = arg; @@ -2854,7 +2887,12 @@ static int cxl_region_probe(struct device *dev) goto out; } - rc = cxl_region_invalidate_memregion(cxlr); + if (test_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags)) { + dev_err(&cxlr->dev, + "failed to activate, re-commit region and retry\n"); + rc = -ENXIO; + goto out; + } /* * From this point on any path that changes the region's state away from diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c index 1476a0299c9b..6281127b3e9d 100644 --- a/drivers/cxl/core/regs.c +++ b/drivers/cxl/core/regs.c @@ -6,6 +6,7 @@ #include <linux/pci.h> #include <cxlmem.h> #include <cxlpci.h> +#include <pmu.h> #include "core.h" @@ -199,11 +200,13 @@ void __iomem *devm_cxl_iomap_block(struct device *dev, resource_size_t addr, return ret_val; } -int cxl_map_component_regs(struct device *dev, struct cxl_component_regs *regs, - struct cxl_register_map *map, unsigned long map_mask) +int cxl_map_component_regs(const struct cxl_register_map *map, + struct cxl_component_regs *regs, + unsigned long map_mask) { + struct device *dev = map->dev; struct mapinfo { - struct cxl_reg_map *rmap; + const struct cxl_reg_map *rmap; void __iomem **addr; } mapinfo[] = { { &map->component_map.hdm_decoder, ®s->hdm_decoder }, @@ -231,13 +234,13 @@ int cxl_map_component_regs(struct device *dev, struct cxl_component_regs *regs, } EXPORT_SYMBOL_NS_GPL(cxl_map_component_regs, CXL); -int cxl_map_device_regs(struct device *dev, - struct cxl_device_regs *regs, - struct cxl_register_map *map) +int cxl_map_device_regs(const struct cxl_register_map *map, + struct cxl_device_regs *regs) { + struct device *dev = map->dev; resource_size_t phys_addr = map->resource; struct mapinfo { - struct cxl_reg_map *rmap; + const struct cxl_reg_map *rmap; void __iomem **addr; } mapinfo[] = { { &map->device_map.status, ®s->status, }, @@ -286,23 +289,30 @@ static bool cxl_decode_regblock(struct pci_dev *pdev, u32 reg_lo, u32 reg_hi, } /** - * cxl_find_regblock() - Locate register blocks by type + * cxl_find_regblock_instance() - Locate a register block by type / index * @pdev: The CXL PCI device to enumerate. * @type: Register Block Indicator id * @map: Enumeration output, clobbered on error + * @index: Index into which particular instance of a regblock wanted in the + * order found in register locator DVSEC. * * Return: 0 if register block enumerated, negative error code otherwise * * A CXL DVSEC may point to one or more register blocks, search for them - * by @type. + * by @type and @index. */ -int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type, - struct cxl_register_map *map) +int cxl_find_regblock_instance(struct pci_dev *pdev, enum cxl_regloc_type type, + struct cxl_register_map *map, int index) { u32 regloc_size, regblocks; + int instance = 0; int regloc, i; - map->resource = CXL_RESOURCE_NONE; + *map = (struct cxl_register_map) { + .dev = &pdev->dev, + .resource = CXL_RESOURCE_NONE, + }; + regloc = pci_find_dvsec_capability(pdev, PCI_DVSEC_VENDOR_ID_CXL, CXL_DVSEC_REG_LOCATOR); if (!regloc) @@ -323,20 +333,148 @@ int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type, if (!cxl_decode_regblock(pdev, reg_lo, reg_hi, map)) continue; - if (map->reg_type == type) - return 0; + if (map->reg_type == type) { + if (index == instance) + return 0; + instance++; + } } map->resource = CXL_RESOURCE_NONE; return -ENODEV; } +EXPORT_SYMBOL_NS_GPL(cxl_find_regblock_instance, CXL); + +/** + * cxl_find_regblock() - Locate register blocks by type + * @pdev: The CXL PCI device to enumerate. + * @type: Register Block Indicator id + * @map: Enumeration output, clobbered on error + * + * Return: 0 if register block enumerated, negative error code otherwise + * + * A CXL DVSEC may point to one or more register blocks, search for them + * by @type. + */ +int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type, + struct cxl_register_map *map) +{ + return cxl_find_regblock_instance(pdev, type, map, 0); +} EXPORT_SYMBOL_NS_GPL(cxl_find_regblock, CXL); -resource_size_t cxl_rcrb_to_component(struct device *dev, - resource_size_t rcrb, - enum cxl_rcrb which) +/** + * cxl_count_regblock() - Count instances of a given regblock type. + * @pdev: The CXL PCI device to enumerate. + * @type: Register Block Indicator id + * + * Some regblocks may be repeated. Count how many instances. + * + * Return: count of matching regblocks. + */ +int cxl_count_regblock(struct pci_dev *pdev, enum cxl_regloc_type type) +{ + struct cxl_register_map map; + int rc, count = 0; + + while (1) { + rc = cxl_find_regblock_instance(pdev, type, &map, count); + if (rc) + return count; + count++; + } +} +EXPORT_SYMBOL_NS_GPL(cxl_count_regblock, CXL); + +int cxl_map_pmu_regs(struct pci_dev *pdev, struct cxl_pmu_regs *regs, + struct cxl_register_map *map) +{ + struct device *dev = &pdev->dev; + resource_size_t phys_addr; + + phys_addr = map->resource; + regs->pmu = devm_cxl_iomap_block(dev, phys_addr, CXL_PMU_REGMAP_SIZE); + if (!regs->pmu) + return -ENOMEM; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(cxl_map_pmu_regs, CXL); + +static int cxl_map_regblock(struct cxl_register_map *map) +{ + struct device *dev = map->dev; + + map->base = ioremap(map->resource, map->max_size); + if (!map->base) { + dev_err(dev, "failed to map registers\n"); + return -ENOMEM; + } + + dev_dbg(dev, "Mapped CXL Memory Device resource %pa\n", &map->resource); + return 0; +} + +static void cxl_unmap_regblock(struct cxl_register_map *map) +{ + iounmap(map->base); + map->base = NULL; +} + +static int cxl_probe_regs(struct cxl_register_map *map) +{ + struct cxl_component_reg_map *comp_map; + struct cxl_device_reg_map *dev_map; + struct device *dev = map->dev; + void __iomem *base = map->base; + + switch (map->reg_type) { + case CXL_REGLOC_RBI_COMPONENT: + comp_map = &map->component_map; + cxl_probe_component_regs(dev, base, comp_map); + dev_dbg(dev, "Set up component registers\n"); + break; + case CXL_REGLOC_RBI_MEMDEV: + dev_map = &map->device_map; + cxl_probe_device_regs(dev, base, dev_map); + if (!dev_map->status.valid || !dev_map->mbox.valid || + !dev_map->memdev.valid) { + dev_err(dev, "registers not found: %s%s%s\n", + !dev_map->status.valid ? "status " : "", + !dev_map->mbox.valid ? "mbox " : "", + !dev_map->memdev.valid ? "memdev " : ""); + return -ENXIO; + } + + dev_dbg(dev, "Probing device registers...\n"); + break; + default: + break; + } + + return 0; +} + +int cxl_setup_regs(struct cxl_register_map *map) +{ + int rc; + + rc = cxl_map_regblock(map); + if (rc) + return rc; + + rc = cxl_probe_regs(map); + cxl_unmap_regblock(map); + + return rc; +} +EXPORT_SYMBOL_NS_GPL(cxl_setup_regs, CXL); + +resource_size_t __rcrb_to_component(struct device *dev, struct cxl_rcrb_info *ri, + enum cxl_rcrb which) { resource_size_t component_reg_phys; + resource_size_t rcrb = ri->base; void __iomem *addr; u32 bar0, bar1; u16 cmd; @@ -395,4 +533,12 @@ resource_size_t cxl_rcrb_to_component(struct device *dev, return component_reg_phys; } -EXPORT_SYMBOL_NS_GPL(cxl_rcrb_to_component, CXL); + +resource_size_t cxl_rcd_component_reg_phys(struct device *dev, + struct cxl_dport *dport) +{ + if (!dport->rch) + return CXL_RESOURCE_NONE; + return __rcrb_to_component(dev, &dport->rcrb, CXL_RCRB_UPSTREAM); +} +EXPORT_SYMBOL_NS_GPL(cxl_rcd_component_reg_phys, CXL); diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index f93a28538962..76d92561af29 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h @@ -56,7 +56,7 @@ #define CXL_HDM_DECODER0_CTRL_COMMIT BIT(9) #define CXL_HDM_DECODER0_CTRL_COMMITTED BIT(10) #define CXL_HDM_DECODER0_CTRL_COMMIT_ERROR BIT(11) -#define CXL_HDM_DECODER0_CTRL_TYPE BIT(12) +#define CXL_HDM_DECODER0_CTRL_HOSTONLY BIT(12) #define CXL_HDM_DECODER0_TL_LOW(i) (0x20 * (i) + 0x24) #define CXL_HDM_DECODER0_TL_HIGH(i) (0x20 * (i) + 0x28) #define CXL_HDM_DECODER0_SKIP_LOW(i) CXL_HDM_DECODER0_TL_LOW(i) @@ -176,14 +176,22 @@ static inline int ways_to_eiw(unsigned int ways, u8 *eiw) /* CXL 2.0 8.2.8.4 Mailbox Registers */ #define CXLDEV_MBOX_CAPS_OFFSET 0x00 #define CXLDEV_MBOX_CAP_PAYLOAD_SIZE_MASK GENMASK(4, 0) +#define CXLDEV_MBOX_CAP_BG_CMD_IRQ BIT(6) +#define CXLDEV_MBOX_CAP_IRQ_MSGNUM_MASK GENMASK(10, 7) #define CXLDEV_MBOX_CTRL_OFFSET 0x04 #define CXLDEV_MBOX_CTRL_DOORBELL BIT(0) +#define CXLDEV_MBOX_CTRL_BG_CMD_IRQ BIT(2) #define CXLDEV_MBOX_CMD_OFFSET 0x08 #define CXLDEV_MBOX_CMD_COMMAND_OPCODE_MASK GENMASK_ULL(15, 0) #define CXLDEV_MBOX_CMD_PAYLOAD_LENGTH_MASK GENMASK_ULL(36, 16) #define CXLDEV_MBOX_STATUS_OFFSET 0x10 +#define CXLDEV_MBOX_STATUS_BG_CMD BIT(0) #define CXLDEV_MBOX_STATUS_RET_CODE_MASK GENMASK_ULL(47, 32) #define CXLDEV_MBOX_BG_CMD_STATUS_OFFSET 0x18 +#define CXLDEV_MBOX_BG_CMD_COMMAND_OPCODE_MASK GENMASK_ULL(15, 0) +#define CXLDEV_MBOX_BG_CMD_COMMAND_PCT_MASK GENMASK_ULL(22, 16) +#define CXLDEV_MBOX_BG_CMD_COMMAND_RC_MASK GENMASK_ULL(47, 32) +#define CXLDEV_MBOX_BG_CMD_COMMAND_VENDOR_MASK GENMASK_ULL(63, 48) #define CXLDEV_MBOX_PAYLOAD_OFFSET 0x20 /* @@ -209,6 +217,10 @@ struct cxl_regs { struct_group_tagged(cxl_device_regs, device_regs, void __iomem *status, *mbox, *memdev; ); + + struct_group_tagged(cxl_pmu_regs, pmu_regs, + void __iomem *pmu; + ); }; struct cxl_reg_map { @@ -229,16 +241,23 @@ struct cxl_device_reg_map { struct cxl_reg_map memdev; }; +struct cxl_pmu_reg_map { + struct cxl_reg_map pmu; +}; + /** * struct cxl_register_map - DVSEC harvested register block mapping parameters + * @dev: device for devm operations and logging * @base: virtual base of the register-block-BAR + @block_offset * @resource: physical resource base of the register block * @max_size: maximum mapping size to perform register search * @reg_type: see enum cxl_regloc_type * @component_map: cxl_reg_map for component registers * @device_map: cxl_reg_maps for device registers + * @pmu_map: cxl_reg_maps for CXL Performance Monitoring Units */ struct cxl_register_map { + struct device *dev; void __iomem *base; resource_size_t resource; resource_size_t max_size; @@ -246,6 +265,7 @@ struct cxl_register_map { union { struct cxl_component_reg_map component_map; struct cxl_device_reg_map device_map; + struct cxl_pmu_reg_map pmu_map; }; }; @@ -253,23 +273,24 @@ void cxl_probe_component_regs(struct device *dev, void __iomem *base, struct cxl_component_reg_map *map); void cxl_probe_device_regs(struct device *dev, void __iomem *base, struct cxl_device_reg_map *map); -int cxl_map_component_regs(struct device *dev, struct cxl_component_regs *regs, - struct cxl_register_map *map, +int cxl_map_component_regs(const struct cxl_register_map *map, + struct cxl_component_regs *regs, unsigned long map_mask); -int cxl_map_device_regs(struct device *dev, struct cxl_device_regs *regs, - struct cxl_register_map *map); +int cxl_map_device_regs(const struct cxl_register_map *map, + struct cxl_device_regs *regs); +int cxl_map_pmu_regs(struct pci_dev *pdev, struct cxl_pmu_regs *regs, + struct cxl_register_map *map); enum cxl_regloc_type; +int cxl_count_regblock(struct pci_dev *pdev, enum cxl_regloc_type type); +int cxl_find_regblock_instance(struct pci_dev *pdev, enum cxl_regloc_type type, + struct cxl_register_map *map, int index); int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type, struct cxl_register_map *map); - -enum cxl_rcrb { - CXL_RCRB_DOWNSTREAM, - CXL_RCRB_UPSTREAM, -}; -resource_size_t cxl_rcrb_to_component(struct device *dev, - resource_size_t rcrb, - enum cxl_rcrb which); +int cxl_setup_regs(struct cxl_register_map *map); +struct cxl_dport; +resource_size_t cxl_rcd_component_reg_phys(struct device *dev, + struct cxl_dport *dport); #define CXL_RESOURCE_NONE ((resource_size_t) -1) #define CXL_TARGET_STRLEN 20 @@ -290,8 +311,8 @@ resource_size_t cxl_rcrb_to_component(struct device *dev, #define CXL_DECODER_F_MASK GENMASK(5, 0) enum cxl_decoder_type { - CXL_DECODER_ACCELERATOR = 2, - CXL_DECODER_EXPANDER = 3, + CXL_DECODER_DEVMEM = 2, + CXL_DECODER_HOSTONLYMEM = 3, }; /* @@ -463,17 +484,19 @@ struct cxl_region_params { }; /* - * Flag whether this region needs to have its HPA span synchronized with - * CPU cache state at region activation time. - */ -#define CXL_REGION_F_INCOHERENT 0 - -/* * Indicate whether this region has been assembled by autodetection or * userspace assembly. Prevent endpoint decoders outside of automatic * detection from being added to the region. */ -#define CXL_REGION_F_AUTO 1 +#define CXL_REGION_F_AUTO 0 + +/* + * Require that a committed region successfully complete a teardown once + * any of its associated decoders have been torn down. This maintains + * the commit state for the region since there are committed decoders, + * but blocks cxl_region_probe(). + */ +#define CXL_REGION_F_NEEDS_RESET 1 /** * struct cxl_region - CXL region @@ -541,7 +564,7 @@ struct cxl_dax_region { * downstream port devices to construct a CXL memory * decode hierarchy. * @dev: this port's device - * @uport: PCI or platform device implementing the upstream port capability + * @uport_dev: PCI or platform device implementing the upstream port capability * @host_bridge: Shortcut to the platform attach point for this port * @id: id for port device-name * @dports: cxl_dport instances referenced by decoders @@ -549,6 +572,7 @@ struct cxl_dax_region { * @regions: cxl_region_ref instances, regions mapped by this port * @parent_dport: dport that points to this port in the parent * @decoder_ida: allocator for decoder ids + * @comp_map: component register capability mappings * @nr_dports: number of entries in @dports * @hdm_end: track last allocated HDM decoder instance for allocation ordering * @commit_end: cursor to track highest committed decoder for commit ordering @@ -560,7 +584,7 @@ struct cxl_dax_region { */ struct cxl_port { struct device dev; - struct device *uport; + struct device *uport_dev; struct device *host_bridge; int id; struct xarray dports; @@ -568,6 +592,7 @@ struct cxl_port { struct xarray regions; struct cxl_dport *parent_dport; struct ida decoder_ida; + struct cxl_register_map comp_map; int nr_dports; int hdm_end; int commit_end; @@ -587,20 +612,25 @@ cxl_find_dport_by_dev(struct cxl_port *port, const struct device *dport_dev) return xa_load(&port->dports, (unsigned long)dport_dev); } +struct cxl_rcrb_info { + resource_size_t base; + u16 aer_cap; +}; + /** * struct cxl_dport - CXL downstream port - * @dport: PCI bridge or firmware device representing the downstream link + * @dport_dev: PCI bridge or firmware device representing the downstream link + * @comp_map: component register capability mappings * @port_id: unique hardware identifier for dport in decoder target list - * @component_reg_phys: downstream port component registers - * @rcrb: base address for the Root Complex Register Block + * @rcrb: Data about the Root Complex Register Block layout * @rch: Indicate whether this dport was enumerated in RCH or VH mode * @port: reference to cxl_port that contains this downstream port */ struct cxl_dport { - struct device *dport; + struct device *dport_dev; + struct cxl_register_map comp_map; int port_id; - resource_size_t component_reg_phys; - resource_size_t rcrb; + struct cxl_rcrb_info rcrb; bool rch; struct cxl_port *port; }; @@ -641,27 +671,30 @@ struct cxl_region_ref { /* * The platform firmware device hosting the root is also the top of the * CXL port topology. All other CXL ports have another CXL port as their - * parent and their ->uport / host device is out-of-line of the port + * parent and their ->uport_dev / host device is out-of-line of the port * ancestry. */ static inline bool is_cxl_root(struct cxl_port *port) { - return port->uport == port->dev.parent; + return port->uport_dev == port->dev.parent; } bool is_cxl_port(const struct device *dev); struct cxl_port *to_cxl_port(const struct device *dev); struct pci_bus; -int devm_cxl_register_pci_bus(struct device *host, struct device *uport, +int devm_cxl_register_pci_bus(struct device *host, struct device *uport_dev, struct pci_bus *bus); struct pci_bus *cxl_port_to_pci_bus(struct cxl_port *port); -struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport, +struct cxl_port *devm_cxl_add_port(struct device *host, + struct device *uport_dev, resource_size_t component_reg_phys, struct cxl_dport *parent_dport); struct cxl_port *find_cxl_root(struct cxl_port *port); int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd); void cxl_bus_rescan(void); void cxl_bus_drain(void); +struct cxl_port *cxl_pci_find_port(struct pci_dev *pdev, + struct cxl_dport **dport); struct cxl_port *cxl_mem_find_port(struct cxl_memdev *cxlmd, struct cxl_dport **dport); bool schedule_cxl_memdev_detach(struct cxl_memdev *cxlmd); @@ -671,7 +704,6 @@ struct cxl_dport *devm_cxl_add_dport(struct cxl_port *port, resource_size_t component_reg_phys); struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port, struct device *dport_dev, int port_id, - resource_size_t component_reg_phys, resource_size_t rcrb); struct cxl_decoder *to_cxl_decoder(struct device *dev); @@ -710,7 +742,6 @@ struct cxl_endpoint_dvsec_info { struct cxl_hdm; struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port, struct cxl_endpoint_dvsec_info *info); -int devm_cxl_enable_hdm(struct cxl_port *port, struct cxl_hdm *cxlhdm); int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm, struct cxl_endpoint_dvsec_info *info); int devm_cxl_add_passthrough_decoder(struct cxl_port *port); @@ -750,6 +781,7 @@ void cxl_driver_unregister(struct cxl_driver *cxl_drv); #define CXL_DEVICE_REGION 6 #define CXL_DEVICE_PMEM_REGION 7 #define CXL_DEVICE_DAX_REGION 8 +#define CXL_DEVICE_PMU 9 #define MODULE_ALIAS_CXL(type) MODULE_ALIAS("cxl:t" __stringify(type) "*") #define CXL_MODALIAS_FMT "cxl:t%d" diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h index a2845a7a69d8..79e99c873ca2 100644 --- a/drivers/cxl/cxlmem.h +++ b/drivers/cxl/cxlmem.h @@ -5,6 +5,7 @@ #include <uapi/linux/cxl_mem.h> #include <linux/cdev.h> #include <linux/uuid.h> +#include <linux/rcuwait.h> #include "cxl.h" /* CXL 2.0 8.2.8.5.1.1 Memory Device Status Register */ @@ -38,6 +39,7 @@ * @detach_work: active memdev lost a port in its ancestry * @cxl_nvb: coordinate removal of @cxl_nvd if present * @cxl_nvd: optional bridge to an nvdimm if the device supports pmem + * @endpoint: connection to the CXL port topology for this memory device * @id: id number of this memdev instance. * @depth: endpoint port depth */ @@ -48,6 +50,7 @@ struct cxl_memdev { struct work_struct detach_work; struct cxl_nvdimm_bridge *cxl_nvb; struct cxl_nvdimm *cxl_nvd; + struct cxl_port *endpoint; int id; int depth; }; @@ -72,16 +75,18 @@ cxled_to_memdev(struct cxl_endpoint_decoder *cxled) { struct cxl_port *port = to_cxl_port(cxled->cxld.dev.parent); - return to_cxl_memdev(port->uport); + return to_cxl_memdev(port->uport_dev); } bool is_cxl_memdev(const struct device *dev); static inline bool is_cxl_endpoint(struct cxl_port *port) { - return is_cxl_memdev(port->uport); + return is_cxl_memdev(port->uport_dev); } struct cxl_memdev *devm_cxl_add_memdev(struct cxl_dev_state *cxlds); +struct cxl_memdev_state; +int cxl_memdev_setup_fw_upload(struct cxl_memdev_state *mds); int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled, resource_size_t base, resource_size_t len, resource_size_t skipped); @@ -108,6 +113,9 @@ static inline struct cxl_ep *cxl_ep_load(struct cxl_port *port, * variable sized output commands, it tells the exact number of bytes * written. * @min_out: (input) internal command output payload size validation + * @poll_count: (input) Number of timeouts to attempt. + * @poll_interval_ms: (input) Time between mailbox background command polling + * interval timeouts. * @return_code: (output) Error code returned from hardware. * * This is the primary mechanism used to send commands to the hardware. @@ -123,6 +131,8 @@ struct cxl_mbox_cmd { size_t size_in; size_t size_out; size_t min_out; + int poll_count; + int poll_interval_ms; u16 return_code; }; @@ -195,7 +205,7 @@ static inline int cxl_mbox_cmd_rc2errno(struct cxl_mbox_cmd *mbox_cmd) */ #define CXL_CAPACITY_MULTIPLIER SZ_256M -/** +/* * Event Interrupt Policy * * CXL rev 3.0 section 8.2.9.2.4; Table 8-52 @@ -215,8 +225,8 @@ struct cxl_event_interrupt_policy { /** * struct cxl_event_state - Event log driver state * - * @event_buf: Buffer to receive event data - * @event_log_lock: Serialize event_buf and log use + * @buf: Buffer to receive event data + * @log_lock: Serialize event_buf and log use */ struct cxl_event_state { struct cxl_get_event_payload *buf; @@ -254,6 +264,115 @@ struct cxl_poison_state { struct mutex lock; /* Protect reads of poison list */ }; +/* + * Get FW Info + * CXL rev 3.0 section 8.2.9.3.1; Table 8-56 + */ +struct cxl_mbox_get_fw_info { + u8 num_slots; + u8 slot_info; + u8 activation_cap; + u8 reserved[13]; + char slot_1_revision[16]; + char slot_2_revision[16]; + char slot_3_revision[16]; + char slot_4_revision[16]; +} __packed; + +#define CXL_FW_INFO_SLOT_INFO_CUR_MASK GENMASK(2, 0) +#define CXL_FW_INFO_SLOT_INFO_NEXT_MASK GENMASK(5, 3) +#define CXL_FW_INFO_SLOT_INFO_NEXT_SHIFT 3 +#define CXL_FW_INFO_ACTIVATION_CAP_HAS_LIVE_ACTIVATE BIT(0) + +/* + * Transfer FW Input Payload + * CXL rev 3.0 section 8.2.9.3.2; Table 8-57 + */ +struct cxl_mbox_transfer_fw { + u8 action; + u8 slot; + u8 reserved[2]; + __le32 offset; + u8 reserved2[0x78]; + u8 data[]; +} __packed; + +#define CXL_FW_TRANSFER_ACTION_FULL 0x0 +#define CXL_FW_TRANSFER_ACTION_INITIATE 0x1 +#define CXL_FW_TRANSFER_ACTION_CONTINUE 0x2 +#define CXL_FW_TRANSFER_ACTION_END 0x3 +#define CXL_FW_TRANSFER_ACTION_ABORT 0x4 + +/* + * CXL rev 3.0 section 8.2.9.3.2 mandates 128-byte alignment for FW packages + * and for each part transferred in a Transfer FW command. + */ +#define CXL_FW_TRANSFER_ALIGNMENT 128 + +/* + * Activate FW Input Payload + * CXL rev 3.0 section 8.2.9.3.3; Table 8-58 + */ +struct cxl_mbox_activate_fw { + u8 action; + u8 slot; +} __packed; + +#define CXL_FW_ACTIVATE_ONLINE 0x0 +#define CXL_FW_ACTIVATE_OFFLINE 0x1 + +/* FW state bits */ +#define CXL_FW_STATE_BITS 32 +#define CXL_FW_CANCEL BIT(0) + +/** + * struct cxl_fw_state - Firmware upload / activation state + * + * @state: fw_uploader state bitmask + * @oneshot: whether the fw upload fits in a single transfer + * @num_slots: Number of FW slots available + * @cur_slot: Slot number currently active + * @next_slot: Slot number for the new firmware + */ +struct cxl_fw_state { + DECLARE_BITMAP(state, CXL_FW_STATE_BITS); + bool oneshot; + int num_slots; + int cur_slot; + int next_slot; +}; + +/** + * struct cxl_security_state - Device security state + * + * @state: state of last security operation + * @poll: polling for sanitization is enabled, device has no mbox irq support + * @poll_tmo_secs: polling timeout + * @poll_dwork: polling work item + * @sanitize_node: sanitation sysfs file to notify + */ +struct cxl_security_state { + unsigned long state; + bool poll; + int poll_tmo_secs; + struct delayed_work poll_dwork; + struct kernfs_node *sanitize_node; +}; + +/* + * enum cxl_devtype - delineate type-2 from a generic type-3 device + * @CXL_DEVTYPE_DEVMEM - Vendor specific CXL Type-2 device implementing HDM-D or + * HDM-DB, no requirement that this device implements a + * mailbox, or other memory-device-standard manageability + * flows. + * @CXL_DEVTYPE_CLASSMEM - Common class definition of a CXL Type-3 device with + * HDM-H and class-mandatory memory device registers + */ +enum cxl_devtype { + CXL_DEVTYPE_DEVMEM, + CXL_DEVTYPE_CLASSMEM, +}; + /** * struct cxl_dev_state - The driver device state * @@ -267,6 +386,36 @@ struct cxl_poison_state { * @cxl_dvsec: Offset to the PCIe device DVSEC * @rcd: operating in RCD mode (CXL 3.0 9.11.8 CXL Devices Attached to an RCH) * @media_ready: Indicate whether the device media is usable + * @dpa_res: Overall DPA resource tree for the device + * @pmem_res: Active Persistent memory capacity configuration + * @ram_res: Active Volatile memory capacity configuration + * @component_reg_phys: register base of component registers + * @serial: PCIe Device Serial Number + * @type: Generic Memory Class device or Vendor Specific Memory device + */ +struct cxl_dev_state { + struct device *dev; + struct cxl_memdev *cxlmd; + struct cxl_regs regs; + int cxl_dvsec; + bool rcd; + bool media_ready; + struct resource dpa_res; + struct resource pmem_res; + struct resource ram_res; + resource_size_t component_reg_phys; + u64 serial; + enum cxl_devtype type; +}; + +/** + * struct cxl_memdev_state - Generic Type-3 Memory Device Class driver data + * + * CXL 8.1.12.1 PCI Header - Class Code Register Memory Device defines + * common memory device functionality like the presence of a mailbox and + * the functionality related to that like Identify Memory Device and Get + * Partition Info + * @cxlds: Core driver state common across Type-2 and Type-3 devices * @payload_size: Size of space for payload * (CXL 2.0 8.2.8.4.3 Mailbox Capabilities Register) * @lsa_size: Size of Label Storage Area @@ -275,9 +424,6 @@ struct cxl_poison_state { * @firmware_version: Firmware version for the memory device. * @enabled_cmds: Hardware commands found enabled in CEL. * @exclusive_cmds: Commands that are kernel-internal only - * @dpa_res: Overall DPA resource tree for the device - * @pmem_res: Active Persistent memory capacity configuration - * @ram_res: Active Volatile memory capacity configuration * @total_bytes: sum of all possible capacities * @volatile_only_bytes: hard volatile capacity * @persistent_only_bytes: hard persistent capacity @@ -286,54 +432,48 @@ struct cxl_poison_state { * @active_persistent_bytes: sum of hard + soft persistent * @next_volatile_bytes: volatile capacity change pending device reset * @next_persistent_bytes: persistent capacity change pending device reset - * @component_reg_phys: register base of component registers - * @info: Cached DVSEC information about the device. - * @serial: PCIe Device Serial Number * @event: event log driver state * @poison: poison driver state info + * @fw: firmware upload / activation state * @mbox_send: @dev specific transport for transmitting mailbox commands * - * See section 8.2.9.5.2 Capacity Configuration and Label Storage for + * See CXL 3.0 8.2.9.8.2 Capacity Configuration and Label Storage for * details on capacity parameters. */ -struct cxl_dev_state { - struct device *dev; - struct cxl_memdev *cxlmd; - - struct cxl_regs regs; - int cxl_dvsec; - - bool rcd; - bool media_ready; +struct cxl_memdev_state { + struct cxl_dev_state cxlds; size_t payload_size; size_t lsa_size; struct mutex mbox_mutex; /* Protects device mailbox and firmware */ char firmware_version[0x10]; DECLARE_BITMAP(enabled_cmds, CXL_MEM_COMMAND_ID_MAX); DECLARE_BITMAP(exclusive_cmds, CXL_MEM_COMMAND_ID_MAX); - - struct resource dpa_res; - struct resource pmem_res; - struct resource ram_res; u64 total_bytes; u64 volatile_only_bytes; u64 persistent_only_bytes; u64 partition_align_bytes; - u64 active_volatile_bytes; u64 active_persistent_bytes; u64 next_volatile_bytes; u64 next_persistent_bytes; - - resource_size_t component_reg_phys; - u64 serial; - struct cxl_event_state event; struct cxl_poison_state poison; + struct cxl_security_state security; + struct cxl_fw_state fw; - int (*mbox_send)(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd); + struct rcuwait mbox_wait; + int (*mbox_send)(struct cxl_memdev_state *mds, + struct cxl_mbox_cmd *cmd); }; +static inline struct cxl_memdev_state * +to_cxl_memdev_state(struct cxl_dev_state *cxlds) +{ + if (cxlds->type != CXL_DEVTYPE_CLASSMEM) + return NULL; + return container_of(cxlds, struct cxl_memdev_state, cxlds); +} + enum cxl_opcode { CXL_MBOX_OP_INVALID = 0x0000, CXL_MBOX_OP_RAW = CXL_MBOX_OP_INVALID, @@ -342,6 +482,7 @@ enum cxl_opcode { CXL_MBOX_OP_GET_EVT_INT_POLICY = 0x0102, CXL_MBOX_OP_SET_EVT_INT_POLICY = 0x0103, CXL_MBOX_OP_GET_FW_INFO = 0x0200, + CXL_MBOX_OP_TRANSFER_FW = 0x0201, CXL_MBOX_OP_ACTIVATE_FW = 0x0202, CXL_MBOX_OP_SET_TIMESTAMP = 0x0301, CXL_MBOX_OP_GET_SUPPORTED_LOGS = 0x0400, @@ -362,6 +503,8 @@ enum cxl_opcode { CXL_MBOX_OP_GET_SCAN_MEDIA_CAPS = 0x4303, CXL_MBOX_OP_SCAN_MEDIA = 0x4304, CXL_MBOX_OP_GET_SCAN_MEDIA = 0x4305, + CXL_MBOX_OP_SANITIZE = 0x4400, + CXL_MBOX_OP_SECURE_ERASE = 0x4401, CXL_MBOX_OP_GET_SECURITY_STATE = 0x4500, CXL_MBOX_OP_SET_PASSPHRASE = 0x4501, CXL_MBOX_OP_DISABLE_PASSPHRASE = 0x4502, @@ -692,18 +835,20 @@ enum { CXL_PMEM_SEC_PASS_USER, }; -int cxl_internal_send_cmd(struct cxl_dev_state *cxlds, +int cxl_internal_send_cmd(struct cxl_memdev_state *mds, struct cxl_mbox_cmd *cmd); -int cxl_dev_state_identify(struct cxl_dev_state *cxlds); +int cxl_dev_state_identify(struct cxl_memdev_state *mds); int cxl_await_media_ready(struct cxl_dev_state *cxlds); -int cxl_enumerate_cmds(struct cxl_dev_state *cxlds); -int cxl_mem_create_range_info(struct cxl_dev_state *cxlds); -struct cxl_dev_state *cxl_dev_state_create(struct device *dev); -void set_exclusive_cxl_commands(struct cxl_dev_state *cxlds, unsigned long *cmds); -void clear_exclusive_cxl_commands(struct cxl_dev_state *cxlds, unsigned long *cmds); -void cxl_mem_get_event_records(struct cxl_dev_state *cxlds, u32 status); -int cxl_set_timestamp(struct cxl_dev_state *cxlds); -int cxl_poison_state_init(struct cxl_dev_state *cxlds); +int cxl_enumerate_cmds(struct cxl_memdev_state *mds); +int cxl_mem_create_range_info(struct cxl_memdev_state *mds); +struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev); +void set_exclusive_cxl_commands(struct cxl_memdev_state *mds, + unsigned long *cmds); +void clear_exclusive_cxl_commands(struct cxl_memdev_state *mds, + unsigned long *cmds); +void cxl_mem_get_event_records(struct cxl_memdev_state *mds, u32 status); +int cxl_set_timestamp(struct cxl_memdev_state *mds); +int cxl_poison_state_init(struct cxl_memdev_state *mds); int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len, struct cxl_region *cxlr); int cxl_trigger_poison_list(struct cxl_memdev *cxlmd); @@ -722,6 +867,8 @@ static inline void cxl_mem_active_dec(void) } #endif +int cxl_mem_sanitize(struct cxl_memdev_state *mds, u16 cmd); + struct cxl_hdm { struct cxl_component_regs regs; unsigned int decoder_count; diff --git a/drivers/cxl/cxlpci.h b/drivers/cxl/cxlpci.h index 7c02e55b8042..0fa4799ea316 100644 --- a/drivers/cxl/cxlpci.h +++ b/drivers/cxl/cxlpci.h @@ -67,6 +67,7 @@ enum cxl_regloc_type { CXL_REGLOC_RBI_COMPONENT, CXL_REGLOC_RBI_VIRT, CXL_REGLOC_RBI_MEMDEV, + CXL_REGLOC_RBI_PMU, CXL_REGLOC_RBI_TYPES }; diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c index 519edd0eb196..317c7548e4e9 100644 --- a/drivers/cxl/mem.c +++ b/drivers/cxl/mem.c @@ -51,7 +51,6 @@ static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd, struct cxl_port *parent_port = parent_dport->port; struct cxl_dev_state *cxlds = cxlmd->cxlds; struct cxl_port *endpoint, *iter, *down; - resource_size_t component_reg_phys; int rc; /* @@ -66,17 +65,8 @@ static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd, ep->next = down; } - /* - * The component registers for an RCD might come from the - * host-bridge RCRB if they are not already mapped via the - * typical register locator mechanism. - */ - if (parent_dport->rch && cxlds->component_reg_phys == CXL_RESOURCE_NONE) - component_reg_phys = cxl_rcrb_to_component( - &cxlmd->dev, parent_dport->rcrb, CXL_RCRB_UPSTREAM); - else - component_reg_phys = cxlds->component_reg_phys; - endpoint = devm_cxl_add_port(host, &cxlmd->dev, component_reg_phys, + endpoint = devm_cxl_add_port(host, &cxlmd->dev, + cxlds->component_reg_phys, parent_dport); if (IS_ERR(endpoint)) return PTR_ERR(endpoint); @@ -117,6 +107,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(cxl_poison_clear_fops, NULL, static int cxl_mem_probe(struct device *dev) { struct cxl_memdev *cxlmd = to_cxl_memdev(dev); + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct cxl_dev_state *cxlds = cxlmd->cxlds; struct device *endpoint_parent; struct cxl_port *parent_port; @@ -141,10 +132,10 @@ static int cxl_mem_probe(struct device *dev) dentry = cxl_debugfs_create_dir(dev_name(dev)); debugfs_create_devm_seqfile(dev, "dpamem", dentry, cxl_mem_dpa_show); - if (test_bit(CXL_POISON_ENABLED_INJECT, cxlds->poison.enabled_cmds)) + if (test_bit(CXL_POISON_ENABLED_INJECT, mds->poison.enabled_cmds)) debugfs_create_file("inject_poison", 0200, dentry, cxlmd, &cxl_poison_inject_fops); - if (test_bit(CXL_POISON_ENABLED_CLEAR, cxlds->poison.enabled_cmds)) + if (test_bit(CXL_POISON_ENABLED_CLEAR, mds->poison.enabled_cmds)) debugfs_create_file("clear_poison", 0200, dentry, cxlmd, &cxl_poison_clear_fops); @@ -163,7 +154,7 @@ static int cxl_mem_probe(struct device *dev) } if (dport->rch) - endpoint_parent = parent_port->uport; + endpoint_parent = parent_port->uport_dev; else endpoint_parent = &parent_port->dev; @@ -227,9 +218,12 @@ static umode_t cxl_mem_visible(struct kobject *kobj, struct attribute *a, int n) { if (a == &dev_attr_trigger_poison_list.attr) { struct device *dev = kobj_to_dev(kobj); + struct cxl_memdev *cxlmd = to_cxl_memdev(dev); + struct cxl_memdev_state *mds = + to_cxl_memdev_state(cxlmd->cxlds); if (!test_bit(CXL_POISON_ENABLED_LIST, - to_cxl_memdev(dev)->cxlds->poison.enabled_cmds)) + mds->poison.enabled_cmds)) return 0; } return a->mode; diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c index 0872f2233ed0..1cb1494c28fe 100644 --- a/drivers/cxl/pci.c +++ b/drivers/cxl/pci.c @@ -13,6 +13,7 @@ #include "cxlmem.h" #include "cxlpci.h" #include "cxl.h" +#include "pmu.h" /** * DOC: cxl pci @@ -84,9 +85,92 @@ static int cxl_pci_mbox_wait_for_doorbell(struct cxl_dev_state *cxlds) status & CXLMDEV_DEV_FATAL ? " fatal" : "", \ status & CXLMDEV_FW_HALT ? " firmware-halt" : "") +struct cxl_dev_id { + struct cxl_dev_state *cxlds; +}; + +static int cxl_request_irq(struct cxl_dev_state *cxlds, int irq, + irq_handler_t handler, irq_handler_t thread_fn) +{ + struct device *dev = cxlds->dev; + struct cxl_dev_id *dev_id; + + /* dev_id must be globally unique and must contain the cxlds */ + dev_id = devm_kzalloc(dev, sizeof(*dev_id), GFP_KERNEL); + if (!dev_id) + return -ENOMEM; + dev_id->cxlds = cxlds; + + return devm_request_threaded_irq(dev, irq, handler, thread_fn, + IRQF_SHARED | IRQF_ONESHOT, + NULL, dev_id); +} + +static bool cxl_mbox_background_complete(struct cxl_dev_state *cxlds) +{ + u64 reg; + + reg = readq(cxlds->regs.mbox + CXLDEV_MBOX_BG_CMD_STATUS_OFFSET); + return FIELD_GET(CXLDEV_MBOX_BG_CMD_COMMAND_PCT_MASK, reg) == 100; +} + +static irqreturn_t cxl_pci_mbox_irq(int irq, void *id) +{ + u64 reg; + u16 opcode; + struct cxl_dev_id *dev_id = id; + struct cxl_dev_state *cxlds = dev_id->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); + + if (!cxl_mbox_background_complete(cxlds)) + return IRQ_NONE; + + reg = readq(cxlds->regs.mbox + CXLDEV_MBOX_BG_CMD_STATUS_OFFSET); + opcode = FIELD_GET(CXLDEV_MBOX_BG_CMD_COMMAND_OPCODE_MASK, reg); + if (opcode == CXL_MBOX_OP_SANITIZE) { + if (mds->security.sanitize_node) + sysfs_notify_dirent(mds->security.sanitize_node); + + dev_dbg(cxlds->dev, "Sanitization operation ended\n"); + } else { + /* short-circuit the wait in __cxl_pci_mbox_send_cmd() */ + rcuwait_wake_up(&mds->mbox_wait); + } + + return IRQ_HANDLED; +} + +/* + * Sanitization operation polling mode. + */ +static void cxl_mbox_sanitize_work(struct work_struct *work) +{ + struct cxl_memdev_state *mds = + container_of(work, typeof(*mds), security.poll_dwork.work); + struct cxl_dev_state *cxlds = &mds->cxlds; + + mutex_lock(&mds->mbox_mutex); + if (cxl_mbox_background_complete(cxlds)) { + mds->security.poll_tmo_secs = 0; + put_device(cxlds->dev); + + if (mds->security.sanitize_node) + sysfs_notify_dirent(mds->security.sanitize_node); + + dev_dbg(cxlds->dev, "Sanitization operation ended\n"); + } else { + int timeout = mds->security.poll_tmo_secs + 10; + + mds->security.poll_tmo_secs = min(15 * 60, timeout); + queue_delayed_work(system_wq, &mds->security.poll_dwork, + timeout * HZ); + } + mutex_unlock(&mds->mbox_mutex); +} + /** * __cxl_pci_mbox_send_cmd() - Execute a mailbox command - * @cxlds: The device state to communicate with. + * @mds: The memory device driver data * @mbox_cmd: Command to send to the memory device. * * Context: Any context. Expects mbox_mutex to be held. @@ -106,16 +190,17 @@ static int cxl_pci_mbox_wait_for_doorbell(struct cxl_dev_state *cxlds) * not need to coordinate with each other. The driver only uses the primary * mailbox. */ -static int __cxl_pci_mbox_send_cmd(struct cxl_dev_state *cxlds, +static int __cxl_pci_mbox_send_cmd(struct cxl_memdev_state *mds, struct cxl_mbox_cmd *mbox_cmd) { + struct cxl_dev_state *cxlds = &mds->cxlds; void __iomem *payload = cxlds->regs.mbox + CXLDEV_MBOX_PAYLOAD_OFFSET; struct device *dev = cxlds->dev; u64 cmd_reg, status_reg; size_t out_len; int rc; - lockdep_assert_held(&cxlds->mbox_mutex); + lockdep_assert_held(&mds->mbox_mutex); /* * Here are the steps from 8.2.8.4 of the CXL 2.0 spec. @@ -144,6 +229,16 @@ static int __cxl_pci_mbox_send_cmd(struct cxl_dev_state *cxlds, return -EBUSY; } + /* + * With sanitize polling, hardware might be done and the poller still + * not be in sync. Ensure no new command comes in until so. Keep the + * hardware semantics and only allow device health status. + */ + if (mds->security.poll_tmo_secs > 0) { + if (mbox_cmd->opcode != CXL_MBOX_OP_GET_HEALTH_INFO) + return -EBUSY; + } + cmd_reg = FIELD_PREP(CXLDEV_MBOX_CMD_COMMAND_OPCODE_MASK, mbox_cmd->opcode); if (mbox_cmd->size_in) { @@ -177,12 +272,80 @@ static int __cxl_pci_mbox_send_cmd(struct cxl_dev_state *cxlds, mbox_cmd->return_code = FIELD_GET(CXLDEV_MBOX_STATUS_RET_CODE_MASK, status_reg); + /* + * Handle the background command in a synchronous manner. + * + * All other mailbox commands will serialize/queue on the mbox_mutex, + * which we currently hold. Furthermore this also guarantees that + * cxl_mbox_background_complete() checks are safe amongst each other, + * in that no new bg operation can occur in between. + * + * Background operations are timesliced in accordance with the nature + * of the command. In the event of timeout, the mailbox state is + * indeterminate until the next successful command submission and the + * driver can get back in sync with the hardware state. + */ + if (mbox_cmd->return_code == CXL_MBOX_CMD_RC_BACKGROUND) { + u64 bg_status_reg; + int i, timeout; + + /* + * Sanitization is a special case which monopolizes the device + * and cannot be timesliced. Handle asynchronously instead, + * and allow userspace to poll(2) for completion. + */ + if (mbox_cmd->opcode == CXL_MBOX_OP_SANITIZE) { + if (mds->security.poll) { + /* hold the device throughout */ + get_device(cxlds->dev); + + /* give first timeout a second */ + timeout = 1; + mds->security.poll_tmo_secs = timeout; + queue_delayed_work(system_wq, + &mds->security.poll_dwork, + timeout * HZ); + } + + dev_dbg(dev, "Sanitization operation started\n"); + goto success; + } + + dev_dbg(dev, "Mailbox background operation (0x%04x) started\n", + mbox_cmd->opcode); + + timeout = mbox_cmd->poll_interval_ms; + for (i = 0; i < mbox_cmd->poll_count; i++) { + if (rcuwait_wait_event_timeout(&mds->mbox_wait, + cxl_mbox_background_complete(cxlds), + TASK_UNINTERRUPTIBLE, + msecs_to_jiffies(timeout)) > 0) + break; + } + + if (!cxl_mbox_background_complete(cxlds)) { + dev_err(dev, "timeout waiting for background (%d ms)\n", + timeout * mbox_cmd->poll_count); + return -ETIMEDOUT; + } + + bg_status_reg = readq(cxlds->regs.mbox + + CXLDEV_MBOX_BG_CMD_STATUS_OFFSET); + mbox_cmd->return_code = + FIELD_GET(CXLDEV_MBOX_BG_CMD_COMMAND_RC_MASK, + bg_status_reg); + dev_dbg(dev, + "Mailbox background operation (0x%04x) completed\n", + mbox_cmd->opcode); + } + if (mbox_cmd->return_code != CXL_MBOX_CMD_RC_SUCCESS) { dev_dbg(dev, "Mailbox operation had an error: %s\n", cxl_mbox_cmd_rc2str(mbox_cmd)); return 0; /* completed but caller must check return_code */ } +success: /* #7 */ cmd_reg = readq(cxlds->regs.mbox + CXLDEV_MBOX_CMD_OFFSET); out_len = FIELD_GET(CXLDEV_MBOX_CMD_PAYLOAD_LENGTH_MASK, cmd_reg); @@ -196,8 +359,9 @@ static int __cxl_pci_mbox_send_cmd(struct cxl_dev_state *cxlds, * have requested less data than the hardware supplied even * within spec. */ - size_t n = min3(mbox_cmd->size_out, cxlds->payload_size, out_len); + size_t n; + n = min3(mbox_cmd->size_out, mds->payload_size, out_len); memcpy_fromio(mbox_cmd->payload_out, payload, n); mbox_cmd->size_out = n; } else { @@ -207,20 +371,23 @@ static int __cxl_pci_mbox_send_cmd(struct cxl_dev_state *cxlds, return 0; } -static int cxl_pci_mbox_send(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd) +static int cxl_pci_mbox_send(struct cxl_memdev_state *mds, + struct cxl_mbox_cmd *cmd) { int rc; - mutex_lock_io(&cxlds->mbox_mutex); - rc = __cxl_pci_mbox_send_cmd(cxlds, cmd); - mutex_unlock(&cxlds->mbox_mutex); + mutex_lock_io(&mds->mbox_mutex); + rc = __cxl_pci_mbox_send_cmd(mds, cmd); + mutex_unlock(&mds->mbox_mutex); return rc; } -static int cxl_pci_setup_mailbox(struct cxl_dev_state *cxlds) +static int cxl_pci_setup_mailbox(struct cxl_memdev_state *mds) { + struct cxl_dev_state *cxlds = &mds->cxlds; const int cap = readl(cxlds->regs.mbox + CXLDEV_MBOX_CAPS_OFFSET); + struct device *dev = cxlds->dev; unsigned long timeout; u64 md_status; @@ -234,8 +401,7 @@ static int cxl_pci_setup_mailbox(struct cxl_dev_state *cxlds) } while (!time_after(jiffies, timeout)); if (!(md_status & CXLMDEV_MBOX_IF_READY)) { - cxl_err(cxlds->dev, md_status, - "timeout awaiting mailbox ready"); + cxl_err(dev, md_status, "timeout awaiting mailbox ready"); return -ETIMEDOUT; } @@ -246,12 +412,12 @@ static int cxl_pci_setup_mailbox(struct cxl_dev_state *cxlds) * source for future doorbell busy events. */ if (cxl_pci_mbox_wait_for_doorbell(cxlds) != 0) { - cxl_err(cxlds->dev, md_status, "timeout awaiting mailbox idle"); + cxl_err(dev, md_status, "timeout awaiting mailbox idle"); return -ETIMEDOUT; } - cxlds->mbox_send = cxl_pci_mbox_send; - cxlds->payload_size = + mds->mbox_send = cxl_pci_mbox_send; + mds->payload_size = 1 << FIELD_GET(CXLDEV_MBOX_CAP_PAYLOAD_SIZE_MASK, cap); /* @@ -261,121 +427,104 @@ static int cxl_pci_setup_mailbox(struct cxl_dev_state *cxlds) * there's no point in going forward. If the size is too large, there's * no harm is soft limiting it. */ - cxlds->payload_size = min_t(size_t, cxlds->payload_size, SZ_1M); - if (cxlds->payload_size < 256) { - dev_err(cxlds->dev, "Mailbox is too small (%zub)", - cxlds->payload_size); + mds->payload_size = min_t(size_t, mds->payload_size, SZ_1M); + if (mds->payload_size < 256) { + dev_err(dev, "Mailbox is too small (%zub)", + mds->payload_size); return -ENXIO; } - dev_dbg(cxlds->dev, "Mailbox payload sized %zu", - cxlds->payload_size); + dev_dbg(dev, "Mailbox payload sized %zu", mds->payload_size); - return 0; -} + rcuwait_init(&mds->mbox_wait); -static int cxl_map_regblock(struct pci_dev *pdev, struct cxl_register_map *map) -{ - struct device *dev = &pdev->dev; + if (cap & CXLDEV_MBOX_CAP_BG_CMD_IRQ) { + u32 ctrl; + int irq, msgnum; + struct pci_dev *pdev = to_pci_dev(cxlds->dev); - map->base = ioremap(map->resource, map->max_size); - if (!map->base) { - dev_err(dev, "failed to map registers\n"); - return -ENOMEM; + msgnum = FIELD_GET(CXLDEV_MBOX_CAP_IRQ_MSGNUM_MASK, cap); + irq = pci_irq_vector(pdev, msgnum); + if (irq < 0) + goto mbox_poll; + + if (cxl_request_irq(cxlds, irq, cxl_pci_mbox_irq, NULL)) + goto mbox_poll; + + /* enable background command mbox irq support */ + ctrl = readl(cxlds->regs.mbox + CXLDEV_MBOX_CTRL_OFFSET); + ctrl |= CXLDEV_MBOX_CTRL_BG_CMD_IRQ; + writel(ctrl, cxlds->regs.mbox + CXLDEV_MBOX_CTRL_OFFSET); + + return 0; } - dev_dbg(dev, "Mapped CXL Memory Device resource %pa\n", &map->resource); +mbox_poll: + mds->security.poll = true; + INIT_DELAYED_WORK(&mds->security.poll_dwork, cxl_mbox_sanitize_work); + + dev_dbg(cxlds->dev, "Mailbox interrupts are unsupported"); return 0; } -static void cxl_unmap_regblock(struct pci_dev *pdev, - struct cxl_register_map *map) +/* + * Assume that any RCIEP that emits the CXL memory expander class code + * is an RCD + */ +static bool is_cxl_restricted(struct pci_dev *pdev) { - iounmap(map->base); - map->base = NULL; + return pci_pcie_type(pdev) == PCI_EXP_TYPE_RC_END; } -static int cxl_probe_regs(struct pci_dev *pdev, struct cxl_register_map *map) +static int cxl_rcrb_get_comp_regs(struct pci_dev *pdev, + struct cxl_register_map *map) { - struct cxl_component_reg_map *comp_map; - struct cxl_device_reg_map *dev_map; - struct device *dev = &pdev->dev; - void __iomem *base = map->base; - - switch (map->reg_type) { - case CXL_REGLOC_RBI_COMPONENT: - comp_map = &map->component_map; - cxl_probe_component_regs(dev, base, comp_map); - if (!comp_map->hdm_decoder.valid) { - dev_err(dev, "HDM decoder registers not found\n"); - return -ENXIO; - } + struct cxl_port *port; + struct cxl_dport *dport; + resource_size_t component_reg_phys; - if (!comp_map->ras.valid) - dev_dbg(dev, "RAS registers not found\n"); - - dev_dbg(dev, "Set up component registers\n"); - break; - case CXL_REGLOC_RBI_MEMDEV: - dev_map = &map->device_map; - cxl_probe_device_regs(dev, base, dev_map); - if (!dev_map->status.valid || !dev_map->mbox.valid || - !dev_map->memdev.valid) { - dev_err(dev, "registers not found: %s%s%s\n", - !dev_map->status.valid ? "status " : "", - !dev_map->mbox.valid ? "mbox " : "", - !dev_map->memdev.valid ? "memdev " : ""); - return -ENXIO; - } + *map = (struct cxl_register_map) { + .dev = &pdev->dev, + .resource = CXL_RESOURCE_NONE, + }; - dev_dbg(dev, "Probing device registers...\n"); - break; - default: - break; - } + port = cxl_pci_find_port(pdev, &dport); + if (!port) + return -EPROBE_DEFER; + + component_reg_phys = cxl_rcd_component_reg_phys(&pdev->dev, dport); + + put_device(&port->dev); + + if (component_reg_phys == CXL_RESOURCE_NONE) + return -ENXIO; + + map->resource = component_reg_phys; + map->reg_type = CXL_REGLOC_RBI_COMPONENT; + map->max_size = CXL_COMPONENT_REG_BLOCK_SIZE; return 0; } -static int cxl_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type, - struct cxl_register_map *map) +static int cxl_pci_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type, + struct cxl_register_map *map) { int rc; rc = cxl_find_regblock(pdev, type, map); - if (rc) - return rc; - rc = cxl_map_regblock(pdev, map); + /* + * If the Register Locator DVSEC does not exist, check if it + * is an RCH and try to extract the Component Registers from + * an RCRB. + */ + if (rc && type == CXL_REGLOC_RBI_COMPONENT && is_cxl_restricted(pdev)) + rc = cxl_rcrb_get_comp_regs(pdev, map); + if (rc) return rc; - rc = cxl_probe_regs(pdev, map); - cxl_unmap_regblock(pdev, map); - - return rc; -} - -/* - * Assume that any RCIEP that emits the CXL memory expander class code - * is an RCD - */ -static bool is_cxl_restricted(struct pci_dev *pdev) -{ - return pci_pcie_type(pdev) == PCI_EXP_TYPE_RC_END; -} - -/* - * CXL v3.0 6.2.3 Table 6-4 - * The table indicates that if PCIe Flit Mode is set, then CXL is in 256B flits - * mode, otherwise it's 68B flits mode. - */ -static bool cxl_pci_flit_256(struct pci_dev *pdev) -{ - u16 lnksta2; - - pcie_capability_read_word(pdev, PCI_EXP_LNKSTA2, &lnksta2); - return lnksta2 & PCI_EXP_LNKSTA2_FLIT; + return cxl_setup_regs(map); } static int cxl_pci_ras_unmask(struct pci_dev *pdev) @@ -404,9 +553,8 @@ static int cxl_pci_ras_unmask(struct pci_dev *pdev) addr = cxlds->regs.ras + CXL_RAS_UNCORRECTABLE_MASK_OFFSET; orig_val = readl(addr); - mask = CXL_RAS_UNCORRECTABLE_MASK_MASK; - if (!cxl_pci_flit_256(pdev)) - mask &= ~CXL_RAS_UNCORRECTABLE_MASK_F256B_MASK; + mask = CXL_RAS_UNCORRECTABLE_MASK_MASK | + CXL_RAS_UNCORRECTABLE_MASK_F256B_MASK; val = orig_val & ~mask; writel(val, addr); dev_dbg(&pdev->dev, @@ -433,18 +581,18 @@ static void free_event_buf(void *buf) /* * There is a single buffer for reading event logs from the mailbox. All logs - * share this buffer protected by the cxlds->event_log_lock. + * share this buffer protected by the mds->event_log_lock. */ -static int cxl_mem_alloc_event_buf(struct cxl_dev_state *cxlds) +static int cxl_mem_alloc_event_buf(struct cxl_memdev_state *mds) { struct cxl_get_event_payload *buf; - buf = kvmalloc(cxlds->payload_size, GFP_KERNEL); + buf = kvmalloc(mds->payload_size, GFP_KERNEL); if (!buf) return -ENOMEM; - cxlds->event.buf = buf; + mds->event.buf = buf; - return devm_add_action_or_reset(cxlds->dev, free_event_buf, buf); + return devm_add_action_or_reset(mds->cxlds.dev, free_event_buf, buf); } static int cxl_alloc_irq_vectors(struct pci_dev *pdev) @@ -469,14 +617,11 @@ static int cxl_alloc_irq_vectors(struct pci_dev *pdev) return 0; } -struct cxl_dev_id { - struct cxl_dev_state *cxlds; -}; - static irqreturn_t cxl_event_thread(int irq, void *id) { struct cxl_dev_id *dev_id = id; struct cxl_dev_state *cxlds = dev_id->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); u32 status; do { @@ -489,7 +634,7 @@ static irqreturn_t cxl_event_thread(int irq, void *id) status &= CXLDEV_EVENT_STATUS_ALL; if (!status) break; - cxl_mem_get_event_records(cxlds, status); + cxl_mem_get_event_records(mds, status); cond_resched(); } while (status); @@ -498,31 +643,21 @@ static irqreturn_t cxl_event_thread(int irq, void *id) static int cxl_event_req_irq(struct cxl_dev_state *cxlds, u8 setting) { - struct device *dev = cxlds->dev; - struct pci_dev *pdev = to_pci_dev(dev); - struct cxl_dev_id *dev_id; + struct pci_dev *pdev = to_pci_dev(cxlds->dev); int irq; if (FIELD_GET(CXLDEV_EVENT_INT_MODE_MASK, setting) != CXL_INT_MSI_MSIX) return -ENXIO; - /* dev_id must be globally unique and must contain the cxlds */ - dev_id = devm_kzalloc(dev, sizeof(*dev_id), GFP_KERNEL); - if (!dev_id) - return -ENOMEM; - dev_id->cxlds = cxlds; - irq = pci_irq_vector(pdev, FIELD_GET(CXLDEV_EVENT_INT_MSGNUM_MASK, setting)); if (irq < 0) return irq; - return devm_request_threaded_irq(dev, irq, NULL, cxl_event_thread, - IRQF_SHARED | IRQF_ONESHOT, NULL, - dev_id); + return cxl_request_irq(cxlds, irq, NULL, cxl_event_thread); } -static int cxl_event_get_int_policy(struct cxl_dev_state *cxlds, +static int cxl_event_get_int_policy(struct cxl_memdev_state *mds, struct cxl_event_interrupt_policy *policy) { struct cxl_mbox_cmd mbox_cmd = { @@ -532,15 +667,15 @@ static int cxl_event_get_int_policy(struct cxl_dev_state *cxlds, }; int rc; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc < 0) - dev_err(cxlds->dev, "Failed to get event interrupt policy : %d", - rc); + dev_err(mds->cxlds.dev, + "Failed to get event interrupt policy : %d", rc); return rc; } -static int cxl_event_config_msgnums(struct cxl_dev_state *cxlds, +static int cxl_event_config_msgnums(struct cxl_memdev_state *mds, struct cxl_event_interrupt_policy *policy) { struct cxl_mbox_cmd mbox_cmd; @@ -559,23 +694,24 @@ static int cxl_event_config_msgnums(struct cxl_dev_state *cxlds, .size_in = sizeof(*policy), }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc < 0) { - dev_err(cxlds->dev, "Failed to set event interrupt policy : %d", + dev_err(mds->cxlds.dev, "Failed to set event interrupt policy : %d", rc); return rc; } /* Retrieve final interrupt settings */ - return cxl_event_get_int_policy(cxlds, policy); + return cxl_event_get_int_policy(mds, policy); } -static int cxl_event_irqsetup(struct cxl_dev_state *cxlds) +static int cxl_event_irqsetup(struct cxl_memdev_state *mds) { + struct cxl_dev_state *cxlds = &mds->cxlds; struct cxl_event_interrupt_policy policy; int rc; - rc = cxl_event_config_msgnums(cxlds, &policy); + rc = cxl_event_config_msgnums(mds, &policy); if (rc) return rc; @@ -614,7 +750,7 @@ static bool cxl_event_int_is_fw(u8 setting) } static int cxl_event_config(struct pci_host_bridge *host_bridge, - struct cxl_dev_state *cxlds) + struct cxl_memdev_state *mds) { struct cxl_event_interrupt_policy policy; int rc; @@ -626,11 +762,11 @@ static int cxl_event_config(struct pci_host_bridge *host_bridge, if (!host_bridge->native_cxl_error) return 0; - rc = cxl_mem_alloc_event_buf(cxlds); + rc = cxl_mem_alloc_event_buf(mds); if (rc) return rc; - rc = cxl_event_get_int_policy(cxlds, &policy); + rc = cxl_event_get_int_policy(mds, &policy); if (rc) return rc; @@ -638,15 +774,16 @@ static int cxl_event_config(struct pci_host_bridge *host_bridge, cxl_event_int_is_fw(policy.warn_settings) || cxl_event_int_is_fw(policy.failure_settings) || cxl_event_int_is_fw(policy.fatal_settings)) { - dev_err(cxlds->dev, "FW still in control of Event Logs despite _OSC settings\n"); + dev_err(mds->cxlds.dev, + "FW still in control of Event Logs despite _OSC settings\n"); return -EBUSY; } - rc = cxl_event_irqsetup(cxlds); + rc = cxl_event_irqsetup(mds); if (rc) return rc; - cxl_mem_get_event_records(cxlds, CXLDEV_EVENT_STATUS_ALL); + cxl_mem_get_event_records(mds, CXLDEV_EVENT_STATUS_ALL); return 0; } @@ -654,10 +791,11 @@ static int cxl_event_config(struct pci_host_bridge *host_bridge, static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct pci_host_bridge *host_bridge = pci_find_host_bridge(pdev->bus); + struct cxl_memdev_state *mds; + struct cxl_dev_state *cxlds; struct cxl_register_map map; struct cxl_memdev *cxlmd; - struct cxl_dev_state *cxlds; - int rc; + int i, rc, pmu_count; /* * Double check the anonymous union trickery in struct cxl_regs @@ -671,9 +809,10 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) return rc; pci_set_master(pdev); - cxlds = cxl_dev_state_create(&pdev->dev); - if (IS_ERR(cxlds)) - return PTR_ERR(cxlds); + mds = cxl_memdev_state_create(&pdev->dev); + if (IS_ERR(mds)) + return PTR_ERR(mds); + cxlds = &mds->cxlds; pci_set_drvdata(pdev, cxlds); cxlds->rcd = is_cxl_restricted(pdev); @@ -684,11 +823,11 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) dev_warn(&pdev->dev, "Device DVSEC not present, skip CXL.mem init\n"); - rc = cxl_setup_regs(pdev, CXL_REGLOC_RBI_MEMDEV, &map); + rc = cxl_pci_setup_regs(pdev, CXL_REGLOC_RBI_MEMDEV, &map); if (rc) return rc; - rc = cxl_map_device_regs(&pdev->dev, &cxlds->regs.device_regs, &map); + rc = cxl_map_device_regs(&map, &cxlds->regs.device_regs); if (rc) return rc; @@ -697,14 +836,16 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) * still be useful for management functions so don't return an error. */ cxlds->component_reg_phys = CXL_RESOURCE_NONE; - rc = cxl_setup_regs(pdev, CXL_REGLOC_RBI_COMPONENT, &map); + rc = cxl_pci_setup_regs(pdev, CXL_REGLOC_RBI_COMPONENT, &map); if (rc) dev_warn(&pdev->dev, "No component registers (%d)\n", rc); + else if (!map.component_map.ras.valid) + dev_dbg(&pdev->dev, "RAS registers not found\n"); cxlds->component_reg_phys = map.resource; - rc = cxl_map_component_regs(&pdev->dev, &cxlds->regs.component, - &map, BIT(CXL_CM_CAP_CAP_ID_RAS)); + rc = cxl_map_component_regs(&map, &cxlds->regs.component, + BIT(CXL_CM_CAP_CAP_ID_RAS)); if (rc) dev_dbg(&pdev->dev, "Failed to map RAS capability.\n"); @@ -714,31 +855,31 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) else dev_warn(&pdev->dev, "Media not active (%d)\n", rc); - rc = cxl_pci_setup_mailbox(cxlds); + rc = cxl_alloc_irq_vectors(pdev); if (rc) return rc; - rc = cxl_enumerate_cmds(cxlds); + rc = cxl_pci_setup_mailbox(mds); if (rc) return rc; - rc = cxl_set_timestamp(cxlds); + rc = cxl_enumerate_cmds(mds); if (rc) return rc; - rc = cxl_poison_state_init(cxlds); + rc = cxl_set_timestamp(mds); if (rc) return rc; - rc = cxl_dev_state_identify(cxlds); + rc = cxl_poison_state_init(mds); if (rc) return rc; - rc = cxl_mem_create_range_info(cxlds); + rc = cxl_dev_state_identify(mds); if (rc) return rc; - rc = cxl_alloc_irq_vectors(pdev); + rc = cxl_mem_create_range_info(mds); if (rc) return rc; @@ -746,7 +887,34 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (IS_ERR(cxlmd)) return PTR_ERR(cxlmd); - rc = cxl_event_config(host_bridge, cxlds); + rc = cxl_memdev_setup_fw_upload(mds); + if (rc) + return rc; + + pmu_count = cxl_count_regblock(pdev, CXL_REGLOC_RBI_PMU); + for (i = 0; i < pmu_count; i++) { + struct cxl_pmu_regs pmu_regs; + + rc = cxl_find_regblock_instance(pdev, CXL_REGLOC_RBI_PMU, &map, i); + if (rc) { + dev_dbg(&pdev->dev, "Could not find PMU regblock\n"); + break; + } + + rc = cxl_map_pmu_regs(pdev, &pmu_regs, &map); + if (rc) { + dev_dbg(&pdev->dev, "Could not map PMU regs\n"); + break; + } + + rc = devm_cxl_pmu_add(cxlds->dev, &pmu_regs, cxlmd->id, i, CXL_PMU_MEMDEV); + if (rc) { + dev_dbg(&pdev->dev, "Could not add PMU instance\n"); + break; + } + } + + rc = cxl_event_config(host_bridge, mds); if (rc) return rc; diff --git a/drivers/cxl/pmem.c b/drivers/cxl/pmem.c index 71cfa1fdf902..7cb8994f8809 100644 --- a/drivers/cxl/pmem.c +++ b/drivers/cxl/pmem.c @@ -15,9 +15,9 @@ extern const struct nvdimm_security_ops *cxl_security_ops; static __read_mostly DECLARE_BITMAP(exclusive_cmds, CXL_MEM_COMMAND_ID_MAX); -static void clear_exclusive(void *cxlds) +static void clear_exclusive(void *mds) { - clear_exclusive_cxl_commands(cxlds, exclusive_cmds); + clear_exclusive_cxl_commands(mds, exclusive_cmds); } static void unregister_nvdimm(void *nvdimm) @@ -65,13 +65,13 @@ static int cxl_nvdimm_probe(struct device *dev) struct cxl_nvdimm *cxl_nvd = to_cxl_nvdimm(dev); struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; struct cxl_nvdimm_bridge *cxl_nvb = cxlmd->cxl_nvb; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); unsigned long flags = 0, cmd_mask = 0; - struct cxl_dev_state *cxlds = cxlmd->cxlds; struct nvdimm *nvdimm; int rc; - set_exclusive_cxl_commands(cxlds, exclusive_cmds); - rc = devm_add_action_or_reset(dev, clear_exclusive, cxlds); + set_exclusive_cxl_commands(mds, exclusive_cmds); + rc = devm_add_action_or_reset(dev, clear_exclusive, mds); if (rc) return rc; @@ -100,22 +100,23 @@ static struct cxl_driver cxl_nvdimm_driver = { }, }; -static int cxl_pmem_get_config_size(struct cxl_dev_state *cxlds, +static int cxl_pmem_get_config_size(struct cxl_memdev_state *mds, struct nd_cmd_get_config_size *cmd, unsigned int buf_len) { if (sizeof(*cmd) > buf_len) return -EINVAL; - *cmd = (struct nd_cmd_get_config_size) { - .config_size = cxlds->lsa_size, - .max_xfer = cxlds->payload_size - sizeof(struct cxl_mbox_set_lsa), + *cmd = (struct nd_cmd_get_config_size){ + .config_size = mds->lsa_size, + .max_xfer = + mds->payload_size - sizeof(struct cxl_mbox_set_lsa), }; return 0; } -static int cxl_pmem_get_config_data(struct cxl_dev_state *cxlds, +static int cxl_pmem_get_config_data(struct cxl_memdev_state *mds, struct nd_cmd_get_config_data_hdr *cmd, unsigned int buf_len) { @@ -140,13 +141,13 @@ static int cxl_pmem_get_config_data(struct cxl_dev_state *cxlds, .payload_out = cmd->out_buf, }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); cmd->status = 0; return rc; } -static int cxl_pmem_set_config_data(struct cxl_dev_state *cxlds, +static int cxl_pmem_set_config_data(struct cxl_memdev_state *mds, struct nd_cmd_set_config_hdr *cmd, unsigned int buf_len) { @@ -176,7 +177,7 @@ static int cxl_pmem_set_config_data(struct cxl_dev_state *cxlds, .size_in = struct_size(set_lsa, data, cmd->in_length), }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); /* * Set "firmware" status (4-packed bytes at the end of the input @@ -194,18 +195,18 @@ static int cxl_pmem_nvdimm_ctl(struct nvdimm *nvdimm, unsigned int cmd, struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); unsigned long cmd_mask = nvdimm_cmd_mask(nvdimm); struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; - struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); if (!test_bit(cmd, &cmd_mask)) return -ENOTTY; switch (cmd) { case ND_CMD_GET_CONFIG_SIZE: - return cxl_pmem_get_config_size(cxlds, buf, buf_len); + return cxl_pmem_get_config_size(mds, buf, buf_len); case ND_CMD_GET_CONFIG_DATA: - return cxl_pmem_get_config_data(cxlds, buf, buf_len); + return cxl_pmem_get_config_data(mds, buf, buf_len); case ND_CMD_SET_CONFIG_DATA: - return cxl_pmem_set_config_data(cxlds, buf, buf_len); + return cxl_pmem_set_config_data(mds, buf, buf_len); default: return -ENOTTY; } diff --git a/drivers/cxl/pmu.h b/drivers/cxl/pmu.h new file mode 100644 index 000000000000..b1e9bcd9f28c --- /dev/null +++ b/drivers/cxl/pmu.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright(c) 2023 Huawei + * CXL Specification rev 3.0 Setion 8.2.7 (CPMU Register Interface) + */ +#ifndef CXL_PMU_H +#define CXL_PMU_H +#include <linux/device.h> + +enum cxl_pmu_type { + CXL_PMU_MEMDEV, +}; + +#define CXL_PMU_REGMAP_SIZE 0xe00 /* Table 8-32 CXL 3.0 specification */ +struct cxl_pmu { + struct device dev; + void __iomem *base; + int assoc_id; + int index; + enum cxl_pmu_type type; +}; + +#define to_cxl_pmu(dev) container_of(dev, struct cxl_pmu, dev) +struct cxl_pmu_regs; +int devm_cxl_pmu_add(struct device *parent, struct cxl_pmu_regs *regs, + int assoc_id, int idx, enum cxl_pmu_type type); + +#endif diff --git a/drivers/cxl/port.c b/drivers/cxl/port.c index c23b6164e1c0..6240e05b9542 100644 --- a/drivers/cxl/port.c +++ b/drivers/cxl/port.c @@ -60,17 +60,13 @@ static int discover_region(struct device *dev, void *root) static int cxl_switch_port_probe(struct cxl_port *port) { struct cxl_hdm *cxlhdm; - int rc, nr_dports; - - nr_dports = devm_cxl_port_enumerate_dports(port); - if (nr_dports < 0) - return nr_dports; + int rc; - cxlhdm = devm_cxl_setup_hdm(port, NULL); - rc = devm_cxl_enable_hdm(port, cxlhdm); - if (rc) + rc = devm_cxl_port_enumerate_dports(port); + if (rc < 0) return rc; + cxlhdm = devm_cxl_setup_hdm(port, NULL); if (!IS_ERR(cxlhdm)) return devm_cxl_enumerate_decoders(cxlhdm, NULL); @@ -79,7 +75,7 @@ static int cxl_switch_port_probe(struct cxl_port *port) return PTR_ERR(cxlhdm); } - if (nr_dports == 1) { + if (rc == 1) { dev_dbg(&port->dev, "Fallback to passthrough decoder\n"); return devm_cxl_add_passthrough_decoder(port); } @@ -91,7 +87,7 @@ static int cxl_switch_port_probe(struct cxl_port *port) static int cxl_endpoint_port_probe(struct cxl_port *port) { struct cxl_endpoint_dvsec_info info = { .port = port }; - struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport); + struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev); struct cxl_dev_state *cxlds = cxlmd->cxlds; struct cxl_hdm *cxlhdm; struct cxl_port *root; @@ -102,8 +98,11 @@ static int cxl_endpoint_port_probe(struct cxl_port *port) return rc; cxlhdm = devm_cxl_setup_hdm(port, &info); - if (IS_ERR(cxlhdm)) + if (IS_ERR(cxlhdm)) { + if (PTR_ERR(cxlhdm) == -ENODEV) + dev_err(&port->dev, "HDM decoder registers not found\n"); return PTR_ERR(cxlhdm); + } /* Cache the data early to ensure is_visible() works */ read_cdat_data(port); diff --git a/drivers/cxl/security.c b/drivers/cxl/security.c index 4ad4bda2d18e..21856a3f408e 100644 --- a/drivers/cxl/security.c +++ b/drivers/cxl/security.c @@ -14,7 +14,7 @@ static unsigned long cxl_pmem_get_security_flags(struct nvdimm *nvdimm, { struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; - struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); unsigned long security_flags = 0; struct cxl_get_security_output { __le32 flags; @@ -29,11 +29,14 @@ static unsigned long cxl_pmem_get_security_flags(struct nvdimm *nvdimm, .payload_out = &out, }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc < 0) return 0; sec_out = le32_to_cpu(out.flags); + /* cache security state */ + mds->security.state = sec_out; + if (ptype == NVDIMM_MASTER) { if (sec_out & CXL_PMEM_SEC_STATE_MASTER_PASS_SET) set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags); @@ -67,7 +70,7 @@ static int cxl_pmem_security_change_key(struct nvdimm *nvdimm, { struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; - struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct cxl_mbox_cmd mbox_cmd; struct cxl_set_pass set_pass; @@ -84,7 +87,7 @@ static int cxl_pmem_security_change_key(struct nvdimm *nvdimm, .payload_in = &set_pass, }; - return cxl_internal_send_cmd(cxlds, &mbox_cmd); + return cxl_internal_send_cmd(mds, &mbox_cmd); } static int __cxl_pmem_security_disable(struct nvdimm *nvdimm, @@ -93,7 +96,7 @@ static int __cxl_pmem_security_disable(struct nvdimm *nvdimm, { struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; - struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct cxl_disable_pass dis_pass; struct cxl_mbox_cmd mbox_cmd; @@ -109,7 +112,7 @@ static int __cxl_pmem_security_disable(struct nvdimm *nvdimm, .payload_in = &dis_pass, }; - return cxl_internal_send_cmd(cxlds, &mbox_cmd); + return cxl_internal_send_cmd(mds, &mbox_cmd); } static int cxl_pmem_security_disable(struct nvdimm *nvdimm, @@ -128,12 +131,12 @@ static int cxl_pmem_security_freeze(struct nvdimm *nvdimm) { struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; - struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct cxl_mbox_cmd mbox_cmd = { .opcode = CXL_MBOX_OP_FREEZE_SECURITY, }; - return cxl_internal_send_cmd(cxlds, &mbox_cmd); + return cxl_internal_send_cmd(mds, &mbox_cmd); } static int cxl_pmem_security_unlock(struct nvdimm *nvdimm, @@ -141,7 +144,7 @@ static int cxl_pmem_security_unlock(struct nvdimm *nvdimm, { struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; - struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); u8 pass[NVDIMM_PASSPHRASE_LEN]; struct cxl_mbox_cmd mbox_cmd; int rc; @@ -153,7 +156,7 @@ static int cxl_pmem_security_unlock(struct nvdimm *nvdimm, .payload_in = pass, }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc < 0) return rc; @@ -166,7 +169,7 @@ static int cxl_pmem_security_passphrase_erase(struct nvdimm *nvdimm, { struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; - struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct cxl_mbox_cmd mbox_cmd; struct cxl_pass_erase erase; int rc; @@ -182,7 +185,7 @@ static int cxl_pmem_security_passphrase_erase(struct nvdimm *nvdimm, .payload_in = &erase, }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc < 0) return rc; diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c index 227800053309..0ee96e6fc426 100644 --- a/drivers/dax/bus.c +++ b/drivers/dax/bus.c @@ -446,18 +446,33 @@ static void unregister_dev_dax(void *dev) put_device(dev); } +static void dax_region_free(struct kref *kref) +{ + struct dax_region *dax_region; + + dax_region = container_of(kref, struct dax_region, kref); + kfree(dax_region); +} + +static void dax_region_put(struct dax_region *dax_region) +{ + kref_put(&dax_region->kref, dax_region_free); +} + /* a return value >= 0 indicates this invocation invalidated the id */ static int __free_dev_dax_id(struct dev_dax *dev_dax) { - struct dax_region *dax_region = dev_dax->region; struct device *dev = &dev_dax->dev; + struct dax_region *dax_region; int rc = dev_dax->id; device_lock_assert(dev); - if (is_static(dax_region) || dev_dax->id < 0) + if (!dev_dax->dyn_id || dev_dax->id < 0) return -1; + dax_region = dev_dax->region; ida_free(&dax_region->ida, dev_dax->id); + dax_region_put(dax_region); dev_dax->id = -1; return rc; } @@ -473,6 +488,20 @@ static int free_dev_dax_id(struct dev_dax *dev_dax) return rc; } +static int alloc_dev_dax_id(struct dev_dax *dev_dax) +{ + struct dax_region *dax_region = dev_dax->region; + int id; + + id = ida_alloc(&dax_region->ida, GFP_KERNEL); + if (id < 0) + return id; + kref_get(&dax_region->kref); + dev_dax->dyn_id = true; + dev_dax->id = id; + return id; +} + static ssize_t delete_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { @@ -560,20 +589,6 @@ static const struct attribute_group *dax_region_attribute_groups[] = { NULL, }; -static void dax_region_free(struct kref *kref) -{ - struct dax_region *dax_region; - - dax_region = container_of(kref, struct dax_region, kref); - kfree(dax_region); -} - -void dax_region_put(struct dax_region *dax_region) -{ - kref_put(&dax_region->kref, dax_region_free); -} -EXPORT_SYMBOL_GPL(dax_region_put); - static void dax_region_unregister(void *region) { struct dax_region *dax_region = region; @@ -625,7 +640,6 @@ struct dax_region *alloc_dax_region(struct device *parent, int region_id, return NULL; } - kref_get(&dax_region->kref); if (devm_add_action_or_reset(parent, dax_region_unregister, dax_region)) return NULL; return dax_region; @@ -635,10 +649,12 @@ EXPORT_SYMBOL_GPL(alloc_dax_region); static void dax_mapping_release(struct device *dev) { struct dax_mapping *mapping = to_dax_mapping(dev); - struct dev_dax *dev_dax = to_dev_dax(dev->parent); + struct device *parent = dev->parent; + struct dev_dax *dev_dax = to_dev_dax(parent); ida_free(&dev_dax->ida, mapping->id); kfree(mapping); + put_device(parent); } static void unregister_dax_mapping(void *data) @@ -655,8 +671,7 @@ static void unregister_dax_mapping(void *data) dev_dax->ranges[mapping->range_id].mapping = NULL; mapping->range_id = -1; - device_del(dev); - put_device(dev); + device_unregister(dev); } static struct dev_dax_range *get_dax_range(struct device *dev) @@ -778,6 +793,7 @@ static int devm_register_dax_mapping(struct dev_dax *dev_dax, int range_id) dev = &mapping->dev; device_initialize(dev); dev->parent = &dev_dax->dev; + get_device(dev->parent); dev->type = &dax_mapping_type; dev_set_name(dev, "mapping%d", mapping->id); rc = device_add(dev); @@ -1295,12 +1311,10 @@ static const struct attribute_group *dax_attribute_groups[] = { static void dev_dax_release(struct device *dev) { struct dev_dax *dev_dax = to_dev_dax(dev); - struct dax_region *dax_region = dev_dax->region; struct dax_device *dax_dev = dev_dax->dax_dev; put_dax(dax_dev); free_dev_dax_id(dev_dax); - dax_region_put(dax_region); kfree(dev_dax->pgmap); kfree(dev_dax); } @@ -1324,6 +1338,7 @@ struct dev_dax *devm_create_dev_dax(struct dev_dax_data *data) if (!dev_dax) return ERR_PTR(-ENOMEM); + dev_dax->region = dax_region; if (is_static(dax_region)) { if (dev_WARN_ONCE(parent, data->id < 0, "dynamic id specified to static region\n")) { @@ -1339,13 +1354,11 @@ struct dev_dax *devm_create_dev_dax(struct dev_dax_data *data) goto err_id; } - rc = ida_alloc(&dax_region->ida, GFP_KERNEL); + rc = alloc_dev_dax_id(dev_dax); if (rc < 0) goto err_id; - dev_dax->id = rc; } - dev_dax->region = dax_region; dev = &dev_dax->dev; device_initialize(dev); dev_set_name(dev, "dax%d.%d", dax_region->id, dev_dax->id); @@ -1386,7 +1399,6 @@ struct dev_dax *devm_create_dev_dax(struct dev_dax_data *data) dev_dax->target_node = dax_region->target_node; dev_dax->align = dax_region->align; ida_init(&dev_dax->ida); - kref_get(&dax_region->kref); inode = dax_inode(dax_dev); dev->devt = inode->i_rdev; diff --git a/drivers/dax/bus.h b/drivers/dax/bus.h index 8cd79ab34292..1ccd23360124 100644 --- a/drivers/dax/bus.h +++ b/drivers/dax/bus.h @@ -9,7 +9,6 @@ struct dev_dax; struct resource; struct dax_device; struct dax_region; -void dax_region_put(struct dax_region *dax_region); /* dax bus specific ioresource flags */ #define IORESOURCE_DAX_STATIC BIT(0) @@ -49,13 +48,6 @@ void dax_driver_unregister(struct dax_device_driver *dax_drv); void kill_dev_dax(struct dev_dax *dev_dax); bool static_dev_dax(struct dev_dax *dev_dax); -/* - * While run_dax() is potentially a generic operation that could be - * defined in include/linux/dax.h we don't want to grow any users - * outside of drivers/dax/ - */ -void run_dax(struct dax_device *dax_dev); - #define MODULE_ALIAS_DAX_DEVICE(type) \ MODULE_ALIAS("dax:t" __stringify(type) "*") #define DAX_DEVICE_MODALIAS_FMT "dax:t%d" diff --git a/drivers/dax/cxl.c b/drivers/dax/cxl.c index ccdf8de85bd5..8bc9d04034d6 100644 --- a/drivers/dax/cxl.c +++ b/drivers/dax/cxl.c @@ -13,7 +13,6 @@ static int cxl_dax_region_probe(struct device *dev) struct cxl_region *cxlr = cxlr_dax->cxlr; struct dax_region *dax_region; struct dev_dax_data data; - struct dev_dax *dev_dax; if (nid == NUMA_NO_NODE) nid = memory_add_physaddr_to_nid(cxlr_dax->hpa_range.start); @@ -28,13 +27,8 @@ static int cxl_dax_region_probe(struct device *dev) .id = -1, .size = range_len(&cxlr_dax->hpa_range), }; - dev_dax = devm_create_dev_dax(&data); - if (IS_ERR(dev_dax)) - return PTR_ERR(dev_dax); - /* child dev_dax instances now own the lifetime of the dax_region */ - dax_region_put(dax_region); - return 0; + return PTR_ERR_OR_ZERO(devm_create_dev_dax(&data)); } static struct cxl_driver cxl_dax_region_driver = { diff --git a/drivers/dax/dax-private.h b/drivers/dax/dax-private.h index 1c974b7caae6..27cf2daaaa79 100644 --- a/drivers/dax/dax-private.h +++ b/drivers/dax/dax-private.h @@ -52,7 +52,8 @@ struct dax_mapping { * @region - parent region * @dax_dev - core dax functionality * @target_node: effective numa node if dev_dax memory range is onlined - * @id: ida allocated id + * @dyn_id: is this a dynamic or statically created instance + * @id: ida allocated id when the dax_region is not static * @ida: mapping id allocator * @dev - device core * @pgmap - pgmap for memmap setup / lifetime (driver owned) @@ -64,6 +65,7 @@ struct dev_dax { struct dax_device *dax_dev; unsigned int align; int target_node; + bool dyn_id; int id; struct ida ida; struct device dev; @@ -76,6 +78,13 @@ struct dev_dax { } *ranges; }; +/* + * While run_dax() is potentially a generic operation that could be + * defined in include/linux/dax.h we don't want to grow any users + * outside of drivers/dax/ + */ +void run_dax(struct dax_device *dax_dev); + static inline struct dev_dax *to_dev_dax(struct device *dev) { return container_of(dev, struct dev_dax, dev); diff --git a/drivers/dax/device.c b/drivers/dax/device.c index af9930c03c9c..30665a3ff6ea 100644 --- a/drivers/dax/device.c +++ b/drivers/dax/device.c @@ -396,7 +396,7 @@ static void dev_dax_kill(void *dev_dax) kill_dev_dax(dev_dax); } -int dev_dax_probe(struct dev_dax *dev_dax) +static int dev_dax_probe(struct dev_dax *dev_dax) { struct dax_device *dax_dev = dev_dax->dax_dev; struct device *dev = &dev_dax->dev; @@ -471,7 +471,6 @@ int dev_dax_probe(struct dev_dax *dev_dax) run_dax(dax_dev); return devm_add_action_or_reset(dev, dev_dax_kill, dev_dax); } -EXPORT_SYMBOL_GPL(dev_dax_probe); static struct dax_device_driver device_dax_driver = { .probe = dev_dax_probe, diff --git a/drivers/dax/hmem/hmem.c b/drivers/dax/hmem/hmem.c index e5fe8b39fb94..5d2ddef0f8f5 100644 --- a/drivers/dax/hmem/hmem.c +++ b/drivers/dax/hmem/hmem.c @@ -16,7 +16,6 @@ static int dax_hmem_probe(struct platform_device *pdev) struct dax_region *dax_region; struct memregion_info *mri; struct dev_dax_data data; - struct dev_dax *dev_dax; /* * @region_idle == true indicates that an administrative agent @@ -38,13 +37,8 @@ static int dax_hmem_probe(struct platform_device *pdev) .id = -1, .size = region_idle ? 0 : range_len(&mri->range), }; - dev_dax = devm_create_dev_dax(&data); - if (IS_ERR(dev_dax)) - return PTR_ERR(dev_dax); - /* child dev_dax instances now own the lifetime of the dax_region */ - dax_region_put(dax_region); - return 0; + return PTR_ERR_OR_ZERO(devm_create_dev_dax(&data)); } static struct platform_driver dax_hmem_driver = { diff --git a/drivers/dax/kmem.c b/drivers/dax/kmem.c index 7b36db6f1cbd..898ca9505754 100644 --- a/drivers/dax/kmem.c +++ b/drivers/dax/kmem.c @@ -99,7 +99,7 @@ static int dev_dax_kmem_probe(struct dev_dax *dev_dax) if (!data->res_name) goto err_res_name; - rc = memory_group_register_static(numa_node, total_len); + rc = memory_group_register_static(numa_node, PFN_UP(total_len)); if (rc < 0) goto err_reg_mgid; data->mgid = rc; diff --git a/drivers/dax/pmem.c b/drivers/dax/pmem.c index f050ea78bb83..ae0cb113a5d3 100644 --- a/drivers/dax/pmem.c +++ b/drivers/dax/pmem.c @@ -13,7 +13,6 @@ static struct dev_dax *__dax_pmem_probe(struct device *dev) int rc, id, region_id; resource_size_t offset; struct nd_pfn_sb *pfn_sb; - struct dev_dax *dev_dax; struct dev_dax_data data; struct nd_namespace_io *nsio; struct dax_region *dax_region; @@ -65,12 +64,8 @@ static struct dev_dax *__dax_pmem_probe(struct device *dev) .pgmap = &pgmap, .size = range_len(&range), }; - dev_dax = devm_create_dev_dax(&data); - /* child dev_dax instances now own the lifetime of the dax_region */ - dax_region_put(dax_region); - - return dev_dax; + return devm_create_dev_dax(&data); } static int dax_pmem_probe(struct device *dev) diff --git a/drivers/dax/super.c b/drivers/dax/super.c index c4c4728a36e4..0da9232ea175 100644 --- a/drivers/dax/super.c +++ b/drivers/dax/super.c @@ -203,6 +203,8 @@ size_t dax_copy_to_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr, int dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff, size_t nr_pages) { + int ret; + if (!dax_alive(dax_dev)) return -ENXIO; /* @@ -213,7 +215,8 @@ int dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff, if (nr_pages != 1) return -EIO; - return dax_dev->ops->zero_page_range(dax_dev, pgoff, nr_pages); + ret = dax_dev->ops->zero_page_range(dax_dev, pgoff, nr_pages); + return dax_mem2blk_err(ret); } EXPORT_SYMBOL_GPL(dax_zero_page_range); diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 3a6ee7bb06f1..1599f1176842 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -214,6 +214,7 @@ static int generic_ops_register(void) generic_ops.get_variable = efi.get_variable; generic_ops.get_next_variable = efi.get_next_variable; generic_ops.query_variable_store = efi_query_variable_store; + generic_ops.query_variable_info = efi.query_variable_info; if (efi_rt_services_supported(EFI_RT_SUPPORTED_SET_VARIABLE)) { generic_ops.set_variable = efi.set_variable; diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c index 87729c365be1..7a81c0ce4780 100644 --- a/drivers/firmware/efi/esrt.c +++ b/drivers/firmware/efi/esrt.c @@ -95,10 +95,6 @@ static ssize_t esre_attr_show(struct kobject *kobj, struct esre_entry *entry = to_entry(kobj); struct esre_attribute *attr = to_attr(_attr); - /* Don't tell normal users what firmware versions we've got... */ - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - return attr->show(entry, buf); } @@ -156,7 +152,7 @@ static void esre_release(struct kobject *kobj) kfree(entry); } -static struct kobj_type esre1_ktype = { +static const struct kobj_type esre1_ktype = { .release = esre_release, .sysfs_ops = &esre_attr_ops, .default_groups = esre1_groups, diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index 1e0203d74691..732984295295 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -378,6 +378,9 @@ efi_status_t efi_exit_boot_services(void *handle, void *priv, struct efi_boot_memmap *map; efi_status_t status; + if (efi_disable_pci_dma) + efi_pci_disable_bridge_busmaster(); + status = efi_get_memory_map(&map, true); if (status != EFI_SUCCESS) return status; @@ -388,9 +391,6 @@ efi_status_t efi_exit_boot_services(void *handle, void *priv, return status; } - if (efi_disable_pci_dma) - efi_pci_disable_bridge_busmaster(); - status = efi_bs_call(exit_boot_services, handle, map->map_key); if (status == EFI_INVALID_PARAMETER) { diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c index bfc5fa6aa47b..e9dc7116daf1 100644 --- a/drivers/firmware/efi/vars.c +++ b/drivers/firmware/efi/vars.c @@ -245,3 +245,15 @@ efi_status_t efivar_set_variable(efi_char16_t *name, efi_guid_t *vendor, return status; } EXPORT_SYMBOL_NS_GPL(efivar_set_variable, EFIVAR); + +efi_status_t efivar_query_variable_info(u32 attr, + u64 *storage_space, + u64 *remaining_space, + u64 *max_variable_size) +{ + if (!__efivars->ops->query_variable_info) + return EFI_UNSUPPORTED; + return __efivars->ops->query_variable_info(attr, storage_space, + remaining_space, max_variable_size); +} +EXPORT_SYMBOL_NS_GPL(efivar_query_variable_info, EFIVAR); diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c index 464b0ea3b6f1..80d08ddde40e 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c @@ -964,11 +964,15 @@ static int tegra186_gpio_probe(struct platform_device *pdev) np = of_find_matching_node(NULL, tegra186_pmc_of_match); if (np) { - irq->parent_domain = irq_find_host(np); - of_node_put(np); - - if (!irq->parent_domain) - return -EPROBE_DEFER; + if (of_device_is_available(np)) { + irq->parent_domain = irq_find_host(np); + of_node_put(np); + + if (!irq->parent_domain) + return -EPROBE_DEFER; + } else { + of_node_put(np); + } } irq->map = devm_kcalloc(&pdev->dev, gpio->gpio.ngpio, diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 87600b4aacb3..9cfe8fc509d7 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -157,7 +157,7 @@ config I2C_I801 Emmitsburg (PCH) Alder Lake (PCH) Raptor Lake (PCH) - Meteor Lake (SOC) + Meteor Lake (SOC and PCH) This driver can also be built as a module. If so, the module will be called i2c-i801. @@ -1025,7 +1025,7 @@ config I2C_RZV2M depends on ARCH_RENESAS || COMPILE_TEST help If you say yes to this option, support will be included for the - Renesas RZ/V2M I2C interface. + Renesas RZ/V2M I2C interface. This driver can also be built as a module. If so, the module will be called i2c-rzv2m. diff --git a/drivers/i2c/busses/i2c-altera.c b/drivers/i2c/busses/i2c-altera.c index 50e7f3f670b6..252fbd175fb1 100644 --- a/drivers/i2c/busses/i2c-altera.c +++ b/drivers/i2c/busses/i2c-altera.c @@ -465,14 +465,12 @@ static int altr_i2c_probe(struct platform_device *pdev) return 0; } -static int altr_i2c_remove(struct platform_device *pdev) +static void altr_i2c_remove(struct platform_device *pdev) { struct altr_i2c_dev *idev = platform_get_drvdata(pdev); clk_disable_unprepare(idev->i2c_clk); i2c_del_adapter(&idev->adapter); - - return 0; } /* Match table for of_platform binding */ @@ -484,7 +482,7 @@ MODULE_DEVICE_TABLE(of, altr_i2c_of_match); static struct platform_driver altr_i2c_driver = { .probe = altr_i2c_probe, - .remove = altr_i2c_remove, + .remove_new = altr_i2c_remove, .driver = { .name = "altera-i2c", .of_match_table = altr_i2c_of_match, diff --git a/drivers/i2c/busses/i2c-amd-mp2-plat.c b/drivers/i2c/busses/i2c-amd-mp2-plat.c index 423fe0c8a471..112fe2bc5662 100644 --- a/drivers/i2c/busses/i2c-amd-mp2-plat.c +++ b/drivers/i2c/busses/i2c-amd-mp2-plat.c @@ -322,7 +322,7 @@ static int i2c_amd_probe(struct platform_device *pdev) return ret; } -static int i2c_amd_remove(struct platform_device *pdev) +static void i2c_amd_remove(struct platform_device *pdev) { struct amd_i2c_dev *i2c_dev = platform_get_drvdata(pdev); struct amd_i2c_common *i2c_common = &i2c_dev->common; @@ -336,7 +336,6 @@ static int i2c_amd_remove(struct platform_device *pdev) i2c_unlock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER); i2c_del_adapter(&i2c_dev->adap); - return 0; } static const struct acpi_device_id i2c_amd_acpi_match[] = { @@ -347,7 +346,7 @@ MODULE_DEVICE_TABLE(acpi, i2c_amd_acpi_match); static struct platform_driver i2c_amd_plat_driver = { .probe = i2c_amd_probe, - .remove = i2c_amd_remove, + .remove_new = i2c_amd_remove, .driver = { .name = "i2c_amd_mp2", .acpi_match_table = ACPI_PTR(i2c_amd_acpi_match), diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c index d3c99c5b3247..2e5acfeb76c8 100644 --- a/drivers/i2c/busses/i2c-aspeed.c +++ b/drivers/i2c/busses/i2c-aspeed.c @@ -1061,7 +1061,7 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) return 0; } -static int aspeed_i2c_remove_bus(struct platform_device *pdev) +static void aspeed_i2c_remove_bus(struct platform_device *pdev) { struct aspeed_i2c_bus *bus = platform_get_drvdata(pdev); unsigned long flags; @@ -1077,13 +1077,11 @@ static int aspeed_i2c_remove_bus(struct platform_device *pdev) reset_control_assert(bus->rst); i2c_del_adapter(&bus->adap); - - return 0; } static struct platform_driver aspeed_i2c_bus_driver = { .probe = aspeed_i2c_probe_bus, - .remove = aspeed_i2c_remove_bus, + .remove_new = aspeed_i2c_remove_bus, .driver = { .name = "aspeed-i2c-bus", .of_match_table = aspeed_i2c_bus_of_table, diff --git a/drivers/i2c/busses/i2c-at91-core.c b/drivers/i2c/busses/i2c-at91-core.c index 2df9df585131..05ad3bc3578a 100644 --- a/drivers/i2c/busses/i2c-at91-core.c +++ b/drivers/i2c/busses/i2c-at91-core.c @@ -273,7 +273,7 @@ static int at91_twi_probe(struct platform_device *pdev) return 0; } -static int at91_twi_remove(struct platform_device *pdev) +static void at91_twi_remove(struct platform_device *pdev) { struct at91_twi_dev *dev = platform_get_drvdata(pdev); @@ -282,8 +282,6 @@ static int at91_twi_remove(struct platform_device *pdev) pm_runtime_disable(dev->dev); pm_runtime_set_suspended(dev->dev); - - return 0; } static int __maybe_unused at91_twi_runtime_suspend(struct device *dev) @@ -342,7 +340,7 @@ static const struct dev_pm_ops __maybe_unused at91_twi_pm = { static struct platform_driver at91_twi_driver = { .probe = at91_twi_probe, - .remove = at91_twi_remove, + .remove_new = at91_twi_remove, .id_table = at91_twi_devtypes, .driver = { .name = "at91_i2c", diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c index 7b42d35b1294..e66c12ecf270 100644 --- a/drivers/i2c/busses/i2c-au1550.c +++ b/drivers/i2c/busses/i2c-au1550.c @@ -334,13 +334,12 @@ i2c_au1550_probe(struct platform_device *pdev) return 0; } -static int i2c_au1550_remove(struct platform_device *pdev) +static void i2c_au1550_remove(struct platform_device *pdev) { struct i2c_au1550_data *priv = platform_get_drvdata(pdev); i2c_del_adapter(&priv->adap); i2c_au1550_disable(priv); - return 0; } #ifdef CONFIG_PM @@ -379,7 +378,7 @@ static struct platform_driver au1xpsc_smbus_driver = { .pm = AU1XPSC_SMBUS_PMOPS, }, .probe = i2c_au1550_probe, - .remove = i2c_au1550_remove, + .remove_new = i2c_au1550_remove, }; module_platform_driver(au1xpsc_smbus_driver); diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c index c1c74ce08407..d7f1e98777ac 100644 --- a/drivers/i2c/busses/i2c-axxia.c +++ b/drivers/i2c/busses/i2c-axxia.c @@ -804,14 +804,12 @@ error_disable_clk: return ret; } -static int axxia_i2c_remove(struct platform_device *pdev) +static void axxia_i2c_remove(struct platform_device *pdev) { struct axxia_i2c_dev *idev = platform_get_drvdata(pdev); clk_disable_unprepare(idev->i2c_clk); i2c_del_adapter(&idev->adapter); - - return 0; } /* Match table for of_platform binding */ @@ -824,7 +822,7 @@ MODULE_DEVICE_TABLE(of, axxia_i2c_of_match); static struct platform_driver axxia_i2c_driver = { .probe = axxia_i2c_probe, - .remove = axxia_i2c_remove, + .remove_new = axxia_i2c_remove, .driver = { .name = "axxia-i2c", .of_match_table = axxia_i2c_of_match, diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c index 85d8a6b04885..2d8342fdc25d 100644 --- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -1107,7 +1107,7 @@ static int bcm_iproc_i2c_probe(struct platform_device *pdev) return i2c_add_adapter(adap); } -static int bcm_iproc_i2c_remove(struct platform_device *pdev) +static void bcm_iproc_i2c_remove(struct platform_device *pdev) { struct bcm_iproc_i2c_dev *iproc_i2c = platform_get_drvdata(pdev); @@ -1123,8 +1123,6 @@ static int bcm_iproc_i2c_remove(struct platform_device *pdev) i2c_del_adapter(&iproc_i2c->adapter); bcm_iproc_i2c_enable_disable(iproc_i2c, false); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1260,7 +1258,7 @@ static struct platform_driver bcm_iproc_i2c_driver = { .pm = BCM_IPROC_I2C_PM_OPS, }, .probe = bcm_iproc_i2c_probe, - .remove = bcm_iproc_i2c_remove, + .remove_new = bcm_iproc_i2c_remove, }; module_platform_driver(bcm_iproc_i2c_driver); diff --git a/drivers/i2c/busses/i2c-bcm-kona.c b/drivers/i2c/busses/i2c-bcm-kona.c index f3e369f0fd40..a57088ec2b06 100644 --- a/drivers/i2c/busses/i2c-bcm-kona.c +++ b/drivers/i2c/busses/i2c-bcm-kona.c @@ -859,13 +859,11 @@ probe_disable_clk: return rc; } -static int bcm_kona_i2c_remove(struct platform_device *pdev) +static void bcm_kona_i2c_remove(struct platform_device *pdev) { struct bcm_kona_i2c_dev *dev = platform_get_drvdata(pdev); i2c_del_adapter(&dev->adapter); - - return 0; } static const struct of_device_id bcm_kona_i2c_of_match[] = { @@ -880,7 +878,7 @@ static struct platform_driver bcm_kona_i2c_driver = { .of_match_table = bcm_kona_i2c_of_match, }, .probe = bcm_kona_i2c_probe, - .remove = bcm_kona_i2c_remove, + .remove_new = bcm_kona_i2c_remove, }; module_platform_driver(bcm_kona_i2c_driver); diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c index 09a077b31bfe..8ce6d3f49551 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -503,7 +503,7 @@ err_put_exclusive_rate: return ret; } -static int bcm2835_i2c_remove(struct platform_device *pdev) +static void bcm2835_i2c_remove(struct platform_device *pdev) { struct bcm2835_i2c_dev *i2c_dev = platform_get_drvdata(pdev); @@ -512,8 +512,6 @@ static int bcm2835_i2c_remove(struct platform_device *pdev) free_irq(i2c_dev->irq, i2c_dev); i2c_del_adapter(&i2c_dev->adapter); - - return 0; } static const struct of_device_id bcm2835_i2c_of_match[] = { @@ -525,7 +523,7 @@ MODULE_DEVICE_TABLE(of, bcm2835_i2c_of_match); static struct platform_driver bcm2835_i2c_driver = { .probe = bcm2835_i2c_probe, - .remove = bcm2835_i2c_remove, + .remove_new = bcm2835_i2c_remove, .driver = { .name = "i2c-bcm2835", .of_match_table = bcm2835_i2c_of_match, diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c index ef942714642a..cf92cbcb8c86 100644 --- a/drivers/i2c/busses/i2c-brcmstb.c +++ b/drivers/i2c/busses/i2c-brcmstb.c @@ -690,12 +690,11 @@ probe_errorout: return rc; } -static int brcmstb_i2c_remove(struct platform_device *pdev) +static void brcmstb_i2c_remove(struct platform_device *pdev) { struct brcmstb_i2c_dev *dev = platform_get_drvdata(pdev); i2c_del_adapter(&dev->adapter); - return 0; } #ifdef CONFIG_PM_SLEEP @@ -736,7 +735,7 @@ static struct platform_driver brcmstb_i2c_driver = { .pm = &brcmstb_i2c_pm, }, .probe = brcmstb_i2c_probe, - .remove = brcmstb_i2c_remove, + .remove_new = brcmstb_i2c_remove, }; module_platform_driver(brcmstb_i2c_driver); diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index 3a4edf7e75f9..9849f4502570 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -1415,7 +1415,7 @@ err_clk_dis: * * Return: 0 always */ -static int cdns_i2c_remove(struct platform_device *pdev) +static void cdns_i2c_remove(struct platform_device *pdev) { struct cdns_i2c *id = platform_get_drvdata(pdev); @@ -1427,8 +1427,6 @@ static int cdns_i2c_remove(struct platform_device *pdev) clk_notifier_unregister(id->clk, &id->clk_rate_change_nb); reset_control_assert(id->reset); clk_disable_unprepare(id->clk); - - return 0; } static struct platform_driver cdns_i2c_drv = { @@ -1438,7 +1436,7 @@ static struct platform_driver cdns_i2c_drv = { .pm = &cdns_i2c_dev_pm_ops, }, .probe = cdns_i2c_probe, - .remove = cdns_i2c_remove, + .remove_new = cdns_i2c_remove, }; module_platform_driver(cdns_i2c_drv); diff --git a/drivers/i2c/busses/i2c-cbus-gpio.c b/drivers/i2c/busses/i2c-cbus-gpio.c index d97c61eec95c..fdc1758a3275 100644 --- a/drivers/i2c/busses/i2c-cbus-gpio.c +++ b/drivers/i2c/busses/i2c-cbus-gpio.c @@ -200,13 +200,11 @@ static const struct i2c_algorithm cbus_i2c_algo = { .functionality = cbus_i2c_func, }; -static int cbus_i2c_remove(struct platform_device *pdev) +static void cbus_i2c_remove(struct platform_device *pdev) { struct i2c_adapter *adapter = platform_get_drvdata(pdev); i2c_del_adapter(adapter); - - return 0; } static int cbus_i2c_probe(struct platform_device *pdev) @@ -266,7 +264,7 @@ MODULE_DEVICE_TABLE(of, i2c_cbus_dt_ids); static struct platform_driver cbus_i2c_driver = { .probe = cbus_i2c_probe, - .remove = cbus_i2c_remove, + .remove_new = cbus_i2c_remove, .driver = { .name = "i2c-cbus-gpio", .of_match_table = of_match_ptr(i2c_cbus_dt_ids), diff --git a/drivers/i2c/busses/i2c-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c index 2b2c3d090089..0209933b9a84 100644 --- a/drivers/i2c/busses/i2c-cht-wc.c +++ b/drivers/i2c/busses/i2c-cht-wc.c @@ -529,15 +529,13 @@ remove_irq_domain: return ret; } -static int cht_wc_i2c_adap_i2c_remove(struct platform_device *pdev) +static void cht_wc_i2c_adap_i2c_remove(struct platform_device *pdev) { struct cht_wc_i2c_adap *adap = platform_get_drvdata(pdev); i2c_unregister_device(adap->client); i2c_del_adapter(&adap->adapter); irq_domain_remove(adap->irq_domain); - - return 0; } static const struct platform_device_id cht_wc_i2c_adap_id_table[] = { @@ -548,7 +546,7 @@ MODULE_DEVICE_TABLE(platform, cht_wc_i2c_adap_id_table); static struct platform_driver cht_wc_i2c_adap_driver = { .probe = cht_wc_i2c_adap_i2c_probe, - .remove = cht_wc_i2c_adap_i2c_remove, + .remove_new = cht_wc_i2c_adap_i2c_remove, .driver = { .name = "cht_wcove_ext_chgr", }, diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index 24d584a1c9a7..732daf6a932b 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -676,7 +676,7 @@ out_free: return result; } -static int cpm_i2c_remove(struct platform_device *ofdev) +static void cpm_i2c_remove(struct platform_device *ofdev) { struct cpm_i2c *cpm = platform_get_drvdata(ofdev); @@ -685,8 +685,6 @@ static int cpm_i2c_remove(struct platform_device *ofdev) cpm_i2c_shutdown(cpm); kfree(cpm); - - return 0; } static const struct of_device_id cpm_i2c_match[] = { @@ -703,7 +701,7 @@ MODULE_DEVICE_TABLE(of, cpm_i2c_match); static struct platform_driver cpm_i2c_driver = { .probe = cpm_i2c_probe, - .remove = cpm_i2c_remove, + .remove_new = cpm_i2c_remove, .driver = { .name = "fsl-i2c-cpm", .of_match_table = cpm_i2c_match, diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c index 8b3ff5bb14d8..2737fd8abd32 100644 --- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c +++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c @@ -283,13 +283,11 @@ static int ec_i2c_probe(struct platform_device *pdev) return err; } -static int ec_i2c_remove(struct platform_device *dev) +static void ec_i2c_remove(struct platform_device *dev) { struct ec_i2c_device *bus = platform_get_drvdata(dev); i2c_del_adapter(&bus->adap); - - return 0; } static const struct of_device_id cros_ec_i2c_of_match[] __maybe_unused = { @@ -306,7 +304,7 @@ MODULE_DEVICE_TABLE(acpi, cros_ec_i2c_tunnel_acpi_id); static struct platform_driver ec_i2c_tunnel_driver = { .probe = ec_i2c_probe, - .remove = ec_i2c_remove, + .remove_new = ec_i2c_remove, .driver = { .name = "cros-ec-i2c-tunnel", .acpi_match_table = ACPI_PTR(cros_ec_i2c_tunnel_acpi_id), diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 9750310f2c96..71b60778c643 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -767,12 +767,9 @@ static int davinci_i2c_probe(struct platform_device *pdev) if (irq < 0) return dev_err_probe(&pdev->dev, irq, "can't get irq resource\n"); - dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_i2c_dev), - GFP_KERNEL); - if (!dev) { - dev_err(&pdev->dev, "Memory allocation failed\n"); + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) return -ENOMEM; - } init_completion(&dev->cmd_complete); @@ -885,7 +882,7 @@ err_pm: return r; } -static int davinci_i2c_remove(struct platform_device *pdev) +static void davinci_i2c_remove(struct platform_device *pdev) { struct davinci_i2c_dev *dev = platform_get_drvdata(pdev); int ret; @@ -894,17 +891,15 @@ static int davinci_i2c_remove(struct platform_device *pdev) i2c_del_adapter(&dev->adapter); - ret = pm_runtime_resume_and_get(&pdev->dev); + ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) - return ret; - - davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0); + dev_err(&pdev->dev, "Failed to resume device\n"); + else + davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0); pm_runtime_dont_use_autosuspend(dev->dev); pm_runtime_put_sync(dev->dev); pm_runtime_disable(dev->dev); - - return 0; } #ifdef CONFIG_PM @@ -940,12 +935,16 @@ static const struct dev_pm_ops davinci_i2c_pm = { #define davinci_i2c_pm_ops NULL #endif -/* work with hotplug and coldplug */ -MODULE_ALIAS("platform:i2c_davinci"); +static const struct platform_device_id davinci_i2c_driver_ids[] = { + { .name = "i2c_davinci", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, davinci_i2c_driver_ids); static struct platform_driver davinci_i2c_driver = { .probe = davinci_i2c_probe, - .remove = davinci_i2c_remove, + .remove_new = davinci_i2c_remove, + .id_table = davinci_i2c_driver_ids, .driver = { .name = "i2c_davinci", .pm = davinci_i2c_pm_ops, diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c index 0dc6b1ce663f..cdd8c67d9129 100644 --- a/drivers/i2c/busses/i2c-designware-common.c +++ b/drivers/i2c/busses/i2c-designware-common.c @@ -575,6 +575,14 @@ int i2c_dw_set_fifo_size(struct dw_i2c_dev *dev) unsigned int param; int ret; + /* DW_IC_COMP_PARAM_1 not implement for IP issue */ + if ((dev->flags & MODEL_MASK) == MODEL_WANGXUN_SP) { + dev->tx_fifo_depth = TXGBE_TX_FIFO_DEPTH; + dev->rx_fifo_depth = TXGBE_RX_FIFO_DEPTH; + + return 0; + } + /* * Try to detect the FIFO depth if not set by interface driver, * the depth could be from 2 to 256 from HW spec. diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index bf23bfb51aea..cf4f684f5356 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -304,6 +304,7 @@ struct dw_i2c_dev { #define MODEL_MSCC_OCELOT BIT(8) #define MODEL_BAIKAL_BT1 BIT(9) #define MODEL_AMD_NAVI_GPU BIT(10) +#define MODEL_WANGXUN_SP BIT(11) #define MODEL_MASK GENMASK(11, 8) /* @@ -313,6 +314,9 @@ struct dw_i2c_dev { #define AMD_UCSI_INTR_REG 0x474 #define AMD_UCSI_INTR_EN 0xd +#define TXGBE_TX_FIFO_DEPTH 4 +#define TXGBE_RX_FIFO_DEPTH 0 + struct i2c_dw_semaphore_callbacks { int (*probe)(struct dw_i2c_dev *dev); void (*remove)(struct dw_i2c_dev *dev); diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index 55ea91a63382..3bfd7a2232db 100644 --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c @@ -354,6 +354,68 @@ static int amd_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs, return 0; } +static int i2c_dw_poll_tx_empty(struct dw_i2c_dev *dev) +{ + u32 val; + + return regmap_read_poll_timeout(dev->map, DW_IC_RAW_INTR_STAT, val, + val & DW_IC_INTR_TX_EMPTY, + 100, 1000); +} + +static int i2c_dw_poll_rx_full(struct dw_i2c_dev *dev) +{ + u32 val; + + return regmap_read_poll_timeout(dev->map, DW_IC_RAW_INTR_STAT, val, + val & DW_IC_INTR_RX_FULL, + 100, 1000); +} + +static int txgbe_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num_msgs) +{ + struct dw_i2c_dev *dev = i2c_get_adapdata(adap); + int msg_idx, buf_len, data_idx, ret; + unsigned int val, stop = 0; + u8 *buf; + + dev->msgs = msgs; + dev->msgs_num = num_msgs; + i2c_dw_xfer_init(dev); + regmap_write(dev->map, DW_IC_INTR_MASK, 0); + + for (msg_idx = 0; msg_idx < num_msgs; msg_idx++) { + buf = msgs[msg_idx].buf; + buf_len = msgs[msg_idx].len; + + for (data_idx = 0; data_idx < buf_len; data_idx++) { + if (msg_idx == num_msgs - 1 && data_idx == buf_len - 1) + stop |= BIT(9); + + if (msgs[msg_idx].flags & I2C_M_RD) { + regmap_write(dev->map, DW_IC_DATA_CMD, 0x100 | stop); + + ret = i2c_dw_poll_rx_full(dev); + if (ret) + return ret; + + regmap_read(dev->map, DW_IC_DATA_CMD, &val); + buf[data_idx] = val; + } else { + ret = i2c_dw_poll_tx_empty(dev); + if (ret) + return ret; + + regmap_write(dev->map, DW_IC_DATA_CMD, + buf[data_idx] | stop); + } + } + } + + return num_msgs; +} + /* * Initiate (and continue) low level master read/write transaction. * This function is only called from i2c_dw_isr, and pumping i2c_msg @@ -559,13 +621,19 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) pm_runtime_get_sync(dev->dev); /* - * Initiate I2C message transfer when AMD NAVI GPU card is enabled, + * Initiate I2C message transfer when polling mode is enabled, * As it is polling based transfer mechanism, which does not support * interrupt based functionalities of existing DesignWare driver. */ - if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU) { + switch (dev->flags & MODEL_MASK) { + case MODEL_AMD_NAVI_GPU: ret = amd_i2c_dw_xfer_quirk(adap, msgs, num); goto done_nolock; + case MODEL_WANGXUN_SP: + ret = txgbe_i2c_dw_xfer_quirk(adap, msgs, num); + goto done_nolock; + default: + break; } reinit_completion(&dev->cmd_complete); @@ -848,7 +916,7 @@ static int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev) return 0; } -static int amd_i2c_adap_quirk(struct dw_i2c_dev *dev) +static int i2c_dw_poll_adap_quirk(struct dw_i2c_dev *dev) { struct i2c_adapter *adap = &dev->adapter; int ret; @@ -862,6 +930,17 @@ static int amd_i2c_adap_quirk(struct dw_i2c_dev *dev) return ret; } +static bool i2c_dw_is_model_poll(struct dw_i2c_dev *dev) +{ + switch (dev->flags & MODEL_MASK) { + case MODEL_AMD_NAVI_GPU: + case MODEL_WANGXUN_SP: + return true; + default: + return false; + } +} + int i2c_dw_probe_master(struct dw_i2c_dev *dev) { struct i2c_adapter *adap = &dev->adapter; @@ -917,8 +996,8 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev) adap->dev.parent = dev->dev; i2c_set_adapdata(adap, dev); - if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU) - return amd_i2c_adap_quirk(dev); + if (i2c_dw_is_model_poll(dev)) + return i2c_dw_poll_adap_quirk(dev); if (dev->flags & ACCESS_NO_IRQ_SUSPEND) { irq_flags = IRQF_NO_SUSPEND; diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c index 782fe1ef3ca1..61d7a27aa070 100644 --- a/drivers/i2c/busses/i2c-designware-pcidrv.c +++ b/drivers/i2c/busses/i2c-designware-pcidrv.c @@ -20,6 +20,7 @@ #include <linux/module.h> #include <linux/pci.h> #include <linux/pm_runtime.h> +#include <linux/power_supply.h> #include <linux/sched.h> #include <linux/slab.h> @@ -234,6 +235,16 @@ static const struct dev_pm_ops i2c_dw_pm_ops = { SET_RUNTIME_PM_OPS(i2c_dw_pci_runtime_suspend, i2c_dw_pci_runtime_resume, NULL) }; +static const struct property_entry dgpu_properties[] = { + /* USB-C doesn't power the system */ + PROPERTY_ENTRY_U8("scope", POWER_SUPPLY_SCOPE_DEVICE), + {} +}; + +static const struct software_node dgpu_node = { + .properties = dgpu_properties, +}; + static int i2c_dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -325,7 +336,7 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev, } if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU) { - dev->slave = i2c_new_ccgx_ucsi(&dev->adapter, dev->irq, NULL); + dev->slave = i2c_new_ccgx_ucsi(&dev->adapter, dev->irq, &dgpu_node); if (IS_ERR(dev->slave)) return dev_err_probe(dev->dev, PTR_ERR(dev->slave), "register UCSI failed\n"); diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 89ad88c54754..970c1c3b0402 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -168,6 +168,15 @@ static inline int dw_i2c_of_configure(struct platform_device *pdev) } #endif +static int txgbe_i2c_request_regs(struct dw_i2c_dev *dev) +{ + dev->map = dev_get_regmap(dev->dev->parent, NULL); + if (!dev->map) + return -ENODEV; + + return 0; +} + static void dw_i2c_plat_pm_cleanup(struct dw_i2c_dev *dev) { pm_runtime_disable(dev->dev); @@ -185,6 +194,9 @@ static int dw_i2c_plat_request_regs(struct dw_i2c_dev *dev) case MODEL_BAIKAL_BT1: ret = bt1_i2c_request_regs(dev); break; + case MODEL_WANGXUN_SP: + ret = txgbe_i2c_request_regs(dev); + break; default: dev->base = devm_platform_ioremap_resource(pdev, 0); ret = PTR_ERR_OR_ZERO(dev->base); @@ -277,6 +289,9 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) return -ENOMEM; dev->flags = (uintptr_t)device_get_match_data(&pdev->dev); + if (device_property_present(&pdev->dev, "wx,i2c-snps-model")) + dev->flags = MODEL_WANGXUN_SP; + dev->dev = &pdev->dev; dev->irq = irq; platform_set_drvdata(pdev, dev); @@ -384,7 +399,7 @@ exit_reset: return ret; } -static int dw_i2c_plat_remove(struct platform_device *pdev) +static void dw_i2c_plat_remove(struct platform_device *pdev) { struct dw_i2c_dev *dev = platform_get_drvdata(pdev); @@ -401,8 +416,6 @@ static int dw_i2c_plat_remove(struct platform_device *pdev) i2c_dw_remove_lock_support(dev); reset_control_assert(dev->rst); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -481,7 +494,7 @@ MODULE_ALIAS("platform:i2c_designware"); static struct platform_driver dw_i2c_driver = { .probe = dw_i2c_plat_probe, - .remove = dw_i2c_plat_remove, + .remove_new = dw_i2c_plat_remove, .driver = { .name = "i2c_designware", .of_match_table = of_match_ptr(dw_i2c_of_match), diff --git a/drivers/i2c/busses/i2c-digicolor.c b/drivers/i2c/busses/i2c-digicolor.c index 50925d97fa42..3462f2bc0fa8 100644 --- a/drivers/i2c/busses/i2c-digicolor.c +++ b/drivers/i2c/busses/i2c-digicolor.c @@ -347,14 +347,12 @@ static int dc_i2c_probe(struct platform_device *pdev) return 0; } -static int dc_i2c_remove(struct platform_device *pdev) +static void dc_i2c_remove(struct platform_device *pdev) { struct dc_i2c *i2c = platform_get_drvdata(pdev); i2c_del_adapter(&i2c->adap); clk_disable_unprepare(i2c->clk); - - return 0; } static const struct of_device_id dc_i2c_match[] = { @@ -365,7 +363,7 @@ MODULE_DEVICE_TABLE(of, dc_i2c_match); static struct platform_driver dc_i2c_driver = { .probe = dc_i2c_probe, - .remove = dc_i2c_remove, + .remove_new = dc_i2c_remove, .driver = { .name = "digicolor-i2c", .of_match_table = dc_i2c_match, diff --git a/drivers/i2c/busses/i2c-dln2.c b/drivers/i2c/busses/i2c-dln2.c index 2a2089db71a5..4f02cc2fb567 100644 --- a/drivers/i2c/busses/i2c-dln2.c +++ b/drivers/i2c/busses/i2c-dln2.c @@ -236,20 +236,18 @@ out_disable: return ret; } -static int dln2_i2c_remove(struct platform_device *pdev) +static void dln2_i2c_remove(struct platform_device *pdev) { struct dln2_i2c *dln2 = platform_get_drvdata(pdev); i2c_del_adapter(&dln2->adapter); dln2_i2c_enable(dln2, false); - - return 0; } static struct platform_driver dln2_i2c_driver = { .driver.name = "dln2-i2c", .probe = dln2_i2c_probe, - .remove = dln2_i2c_remove, + .remove_new = dln2_i2c_remove, }; module_platform_driver(dln2_i2c_driver); diff --git a/drivers/i2c/busses/i2c-emev2.c b/drivers/i2c/busses/i2c-emev2.c index f2e537b137b2..4ba93cd91c0f 100644 --- a/drivers/i2c/busses/i2c-emev2.c +++ b/drivers/i2c/busses/i2c-emev2.c @@ -419,14 +419,12 @@ err_clk: return ret; } -static int em_i2c_remove(struct platform_device *dev) +static void em_i2c_remove(struct platform_device *dev) { struct em_i2c_device *priv = platform_get_drvdata(dev); i2c_del_adapter(&priv->adap); clk_disable_unprepare(priv->sclk); - - return 0; } static const struct of_device_id em_i2c_ids[] = { @@ -436,7 +434,7 @@ static const struct of_device_id em_i2c_ids[] = { static struct platform_driver em_i2c_driver = { .probe = em_i2c_probe, - .remove = em_i2c_remove, + .remove_new = em_i2c_remove, .driver = { .name = "em-i2c", .of_match_table = em_i2c_ids, diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index 4a6260d04db2..f378cd479e55 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -882,7 +882,7 @@ static int exynos5_i2c_probe(struct platform_device *pdev) return ret; } -static int exynos5_i2c_remove(struct platform_device *pdev) +static void exynos5_i2c_remove(struct platform_device *pdev) { struct exynos5_i2c *i2c = platform_get_drvdata(pdev); @@ -890,8 +890,6 @@ static int exynos5_i2c_remove(struct platform_device *pdev) clk_unprepare(i2c->clk); clk_unprepare(i2c->pclk); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -945,7 +943,7 @@ static const struct dev_pm_ops exynos5_i2c_dev_pm_ops = { static struct platform_driver exynos5_i2c_driver = { .probe = exynos5_i2c_probe, - .remove = exynos5_i2c_remove, + .remove_new = exynos5_i2c_remove, .driver = { .name = "exynos5-hsi2c", .pm = &exynos5_i2c_dev_pm_ops, diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index 1794c0399f22..e5a5b9e8bf2c 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -475,7 +475,7 @@ static int i2c_gpio_probe(struct platform_device *pdev) return 0; } -static int i2c_gpio_remove(struct platform_device *pdev) +static void i2c_gpio_remove(struct platform_device *pdev) { struct i2c_gpio_private_data *priv; struct i2c_adapter *adap; @@ -486,8 +486,6 @@ static int i2c_gpio_remove(struct platform_device *pdev) adap = &priv->adap; i2c_del_adapter(adap); - - return 0; } static const struct of_device_id i2c_gpio_dt_ids[] = { @@ -510,7 +508,7 @@ static struct platform_driver i2c_gpio_driver = { .acpi_match_table = i2c_gpio_acpi_match, }, .probe = i2c_gpio_probe, - .remove = i2c_gpio_remove, + .remove_new = i2c_gpio_remove, }; static int __init i2c_gpio_init(void) diff --git a/drivers/i2c/busses/i2c-gxp.c b/drivers/i2c/busses/i2c-gxp.c index 8ea3fb5e4c7f..70b0de07ed99 100644 --- a/drivers/i2c/busses/i2c-gxp.c +++ b/drivers/i2c/busses/i2c-gxp.c @@ -577,15 +577,13 @@ static int gxp_i2c_probe(struct platform_device *pdev) return 0; } -static int gxp_i2c_remove(struct platform_device *pdev) +static void gxp_i2c_remove(struct platform_device *pdev) { struct gxp_i2c_drvdata *drvdata = platform_get_drvdata(pdev); /* Disable interrupt */ regmap_update_bits(i2cg_map, GXP_I2CINTEN, BIT(drvdata->engine), 0); i2c_del_adapter(&drvdata->adapter); - - return 0; } static const struct of_device_id gxp_i2c_of_match[] = { @@ -596,7 +594,7 @@ MODULE_DEVICE_TABLE(of, gxp_i2c_of_match); static struct platform_driver gxp_i2c_driver = { .probe = gxp_i2c_probe, - .remove = gxp_i2c_remove, + .remove_new = gxp_i2c_remove, .driver = { .name = "gxp-i2c", .of_match_table = gxp_i2c_of_match, diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c index 4374a8677271..7922bc917c33 100644 --- a/drivers/i2c/busses/i2c-highlander.c +++ b/drivers/i2c/busses/i2c-highlander.c @@ -435,7 +435,7 @@ err: return ret; } -static int highlander_i2c_remove(struct platform_device *pdev) +static void highlander_i2c_remove(struct platform_device *pdev) { struct highlander_i2c_dev *dev = platform_get_drvdata(pdev); @@ -446,8 +446,6 @@ static int highlander_i2c_remove(struct platform_device *pdev) iounmap(dev->base); kfree(dev); - - return 0; } static struct platform_driver highlander_i2c_driver = { @@ -456,7 +454,7 @@ static struct platform_driver highlander_i2c_driver = { }, .probe = highlander_i2c_probe, - .remove = highlander_i2c_remove, + .remove_new = highlander_i2c_remove, }; module_platform_driver(highlander_i2c_driver); diff --git a/drivers/i2c/busses/i2c-hix5hd2.c b/drivers/i2c/busses/i2c-hix5hd2.c index 0e34cbaca22d..784a5f56eb76 100644 --- a/drivers/i2c/busses/i2c-hix5hd2.c +++ b/drivers/i2c/busses/i2c-hix5hd2.c @@ -360,7 +360,11 @@ static int hix5hd2_i2c_xfer(struct i2c_adapter *adap, pm_runtime_get_sync(priv->dev); for (i = 0; i < num; i++, msgs++) { - stop = (i == num - 1); + if ((i == num - 1) || (msgs->flags & I2C_M_STOP)) + stop = 1; + else + stop = 0; + ret = hix5hd2_i2c_xfer_msg(priv, msgs, stop); if (ret < 0) goto out; @@ -416,12 +420,11 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev) if (irq < 0) return irq; - priv->clk = devm_clk_get(&pdev->dev, NULL); + priv->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(priv->clk)) { - dev_err(&pdev->dev, "cannot get clock\n"); + dev_err(&pdev->dev, "cannot enable clock\n"); return PTR_ERR(priv->clk); } - clk_prepare_enable(priv->clk); strscpy(priv->adap.name, "hix5hd2-i2c", sizeof(priv->adap.name)); priv->dev = &pdev->dev; @@ -442,7 +445,7 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev) IRQF_NO_SUSPEND, dev_name(&pdev->dev), priv); if (ret != 0) { dev_err(&pdev->dev, "cannot request HS-I2C IRQ %d\n", irq); - goto err_clk; + return ret; } pm_runtime_set_autosuspend_delay(priv->dev, MSEC_PER_SEC); @@ -459,21 +462,17 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev) err_runtime: pm_runtime_disable(priv->dev); pm_runtime_set_suspended(priv->dev); -err_clk: - clk_disable_unprepare(priv->clk); + return ret; } -static int hix5hd2_i2c_remove(struct platform_device *pdev) +static void hix5hd2_i2c_remove(struct platform_device *pdev) { struct hix5hd2_i2c_priv *priv = platform_get_drvdata(pdev); i2c_del_adapter(&priv->adap); pm_runtime_disable(priv->dev); pm_runtime_set_suspended(priv->dev); - clk_disable_unprepare(priv->clk); - - return 0; } #ifdef CONFIG_PM @@ -511,7 +510,7 @@ MODULE_DEVICE_TABLE(of, hix5hd2_i2c_match); static struct platform_driver hix5hd2_i2c_driver = { .probe = hix5hd2_i2c_probe, - .remove = hix5hd2_i2c_remove, + .remove_new = hix5hd2_i2c_remove, .driver = { .name = "hix5hd2-i2c", .pm = &hix5hd2_i2c_pm_ops, diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index ac5326747c51..943b8e6d026d 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -77,6 +77,8 @@ * Alder Lake-M (PCH) 0x54a3 32 hard yes yes yes * Raptor Lake-S (PCH) 0x7a23 32 hard yes yes yes * Meteor Lake-P (SOC) 0x7e22 32 hard yes yes yes + * Meteor Lake SoC-S (SOC) 0xae22 32 hard yes yes yes + * Meteor Lake PCH-S (PCH) 0x7f23 32 hard yes yes yes * * Features supported by this driver: * Software PEC no @@ -233,6 +235,7 @@ #define PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_S_SMBUS 0x7a23 #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS 0x7aa3 #define PCI_DEVICE_ID_INTEL_METEOR_LAKE_P_SMBUS 0x7e22 +#define PCI_DEVICE_ID_INTEL_METEOR_LAKE_PCH_S_SMBUS 0x7f23 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22 #define PCI_DEVICE_ID_INTEL_WILDCATPOINT_SMBUS 0x8ca2 #define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS 0x8d22 @@ -250,6 +253,7 @@ #define PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS 0xa2a3 #define PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS 0xa323 #define PCI_DEVICE_ID_INTEL_COMETLAKE_V_SMBUS 0xa3a3 +#define PCI_DEVICE_ID_INTEL_METEOR_LAKE_SOC_S_SMBUS 0xae22 struct i801_mux_config { char *gpio_chip; @@ -977,67 +981,69 @@ static const struct i2c_algorithm smbus_algorithm = { FEATURE_HOST_NOTIFY) static const struct pci_device_id i801_ids[] = { - { PCI_DEVICE_DATA(INTEL, 82801AA_3, 0) }, - { PCI_DEVICE_DATA(INTEL, 82801AB_3, 0) }, - { PCI_DEVICE_DATA(INTEL, 82801BA_2, 0) }, - { PCI_DEVICE_DATA(INTEL, 82801CA_3, FEATURE_HOST_NOTIFY) }, - { PCI_DEVICE_DATA(INTEL, 82801DB_3, FEATURES_ICH4) }, - { PCI_DEVICE_DATA(INTEL, 82801EB_3, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, ESB_4, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, ICH6_16, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, ICH7_17, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, ESB2_17, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, ICH8_5, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, ICH9_6, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, EP80579_1, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, ICH10_4, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, ICH10_5, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, 5_3400_SERIES_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, COUGARPOINT_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF0, FEATURES_ICH5 | FEATURE_IDF) }, - { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF1, FEATURES_ICH5 | FEATURE_IDF) }, - { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF2, FEATURES_ICH5 | FEATURE_IDF) }, - { PCI_DEVICE_DATA(INTEL, DH89XXCC_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, PANTHERPOINT_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, LYNXPOINT_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, LYNXPOINT_LP_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, AVOTON_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS0, FEATURES_ICH5 | FEATURE_IDF) }, - { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS1, FEATURES_ICH5 | FEATURE_IDF) }, - { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS2, FEATURES_ICH5 | FEATURE_IDF) }, - { PCI_DEVICE_DATA(INTEL, COLETOCREEK_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, GEMINILAKE_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, WILDCATPOINT_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, WILDCATPOINT_LP_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, BAYTRAIL_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, BRASWELL_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, SUNRISEPOINT_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, - { PCI_DEVICE_DATA(INTEL, SUNRISEPOINT_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, - { PCI_DEVICE_DATA(INTEL, CDF_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, DNV_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, - { PCI_DEVICE_DATA(INTEL, EBG_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, BROXTON_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, LEWISBURG_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, - { PCI_DEVICE_DATA(INTEL, LEWISBURG_SSKU_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, - { PCI_DEVICE_DATA(INTEL, KABYLAKE_PCH_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, - { PCI_DEVICE_DATA(INTEL, CANNONLAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, CANNONLAKE_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, ICELAKE_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, ICELAKE_N_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, COMETLAKE_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, COMETLAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, COMETLAKE_V_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, - { PCI_DEVICE_DATA(INTEL, ELKHART_LAKE_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, TIGERLAKE_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, TIGERLAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, JASPER_LAKE_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, ALDER_LAKE_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, ALDER_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, ALDER_LAKE_M_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, RAPTOR_LAKE_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, 82801AA_3, 0) }, + { PCI_DEVICE_DATA(INTEL, 82801AB_3, 0) }, + { PCI_DEVICE_DATA(INTEL, 82801BA_2, 0) }, + { PCI_DEVICE_DATA(INTEL, 82801CA_3, FEATURE_HOST_NOTIFY) }, + { PCI_DEVICE_DATA(INTEL, 82801DB_3, FEATURES_ICH4) }, + { PCI_DEVICE_DATA(INTEL, 82801EB_3, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, ESB_4, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, ICH6_16, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, ICH7_17, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, ESB2_17, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, ICH8_5, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, ICH9_6, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, EP80579_1, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, ICH10_4, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, ICH10_5, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, 5_3400_SERIES_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, COUGARPOINT_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF0, FEATURES_ICH5 | FEATURE_IDF) }, + { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF1, FEATURES_ICH5 | FEATURE_IDF) }, + { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF2, FEATURES_ICH5 | FEATURE_IDF) }, + { PCI_DEVICE_DATA(INTEL, DH89XXCC_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, PANTHERPOINT_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, LYNXPOINT_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, LYNXPOINT_LP_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, AVOTON_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS0, FEATURES_ICH5 | FEATURE_IDF) }, + { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS1, FEATURES_ICH5 | FEATURE_IDF) }, + { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS2, FEATURES_ICH5 | FEATURE_IDF) }, + { PCI_DEVICE_DATA(INTEL, COLETOCREEK_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, GEMINILAKE_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, WILDCATPOINT_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, WILDCATPOINT_LP_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, BAYTRAIL_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, BRASWELL_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, SUNRISEPOINT_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, + { PCI_DEVICE_DATA(INTEL, SUNRISEPOINT_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, + { PCI_DEVICE_DATA(INTEL, CDF_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, DNV_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, + { PCI_DEVICE_DATA(INTEL, EBG_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, BROXTON_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, LEWISBURG_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, + { PCI_DEVICE_DATA(INTEL, LEWISBURG_SSKU_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, + { PCI_DEVICE_DATA(INTEL, KABYLAKE_PCH_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, + { PCI_DEVICE_DATA(INTEL, CANNONLAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, CANNONLAKE_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, ICELAKE_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, ICELAKE_N_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, COMETLAKE_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, COMETLAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, COMETLAKE_V_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, + { PCI_DEVICE_DATA(INTEL, ELKHART_LAKE_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, TIGERLAKE_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, TIGERLAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, JASPER_LAKE_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, ALDER_LAKE_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, ALDER_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, ALDER_LAKE_M_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, RAPTOR_LAKE_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_SOC_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_PCH_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index eeb80e34f9ad..1ad9d3b26dd3 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -694,10 +694,8 @@ static int iic_probe(struct platform_device *ofdev) int ret; dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) { - dev_err(&ofdev->dev, "failed to allocate device data\n"); + if (!dev) return -ENOMEM; - } platform_set_drvdata(ofdev, dev); @@ -769,7 +767,7 @@ error_cleanup: /* * Cleanup initialized IIC interface */ -static int iic_remove(struct platform_device *ofdev) +static void iic_remove(struct platform_device *ofdev) { struct ibm_iic_private *dev = platform_get_drvdata(ofdev); @@ -782,8 +780,6 @@ static int iic_remove(struct platform_device *ofdev) iounmap(dev->vaddr); kfree(dev); - - return 0; } static const struct of_device_id ibm_iic_match[] = { @@ -798,7 +794,7 @@ static struct platform_driver ibm_iic_driver = { .of_match_table = ibm_iic_match, }, .probe = iic_probe, - .remove = iic_remove, + .remove_new = iic_remove, }; module_platform_driver(ibm_iic_driver); diff --git a/drivers/i2c/busses/i2c-img-scb.c b/drivers/i2c/busses/i2c-img-scb.c index 39c479f96eb5..66ba36949ab5 100644 --- a/drivers/i2c/busses/i2c-img-scb.c +++ b/drivers/i2c/busses/i2c-img-scb.c @@ -913,7 +913,7 @@ static unsigned int img_i2c_auto(struct img_i2c *i2c, static irqreturn_t img_i2c_isr(int irq, void *dev_id) { - struct img_i2c *i2c = (struct img_i2c *)dev_id; + struct img_i2c *i2c = dev_id; u32 int_status, line_status; /* We handle transaction completion AFTER accessing registers */ unsigned int hret; @@ -1413,7 +1413,7 @@ rpm_disable: return ret; } -static int img_i2c_remove(struct platform_device *dev) +static void img_i2c_remove(struct platform_device *dev) { struct img_i2c *i2c = platform_get_drvdata(dev); @@ -1421,8 +1421,6 @@ static int img_i2c_remove(struct platform_device *dev) pm_runtime_disable(&dev->dev); if (!pm_runtime_status_suspended(&dev->dev)) img_i2c_runtime_suspend(&dev->dev); - - return 0; } static int img_i2c_runtime_suspend(struct device *dev) @@ -1506,7 +1504,7 @@ static struct platform_driver img_scb_i2c_driver = { .pm = &img_i2c_pm, }, .probe = img_i2c_probe, - .remove = img_i2c_remove, + .remove_new = img_i2c_remove, }; module_platform_driver(img_scb_i2c_driver); diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c index 4d24ceb57ee7..c3287c887c6f 100644 --- a/drivers/i2c/busses/i2c-imx-lpi2c.c +++ b/drivers/i2c/busses/i2c-imx-lpi2c.c @@ -217,7 +217,7 @@ static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx) for (prescale = 0; prescale <= 7; prescale++) { clk_cycle = clk_rate / ((1 << prescale) * lpi2c_imx->bitrate) - 3 - (filt >> 1); - clkhi = (clk_cycle + I2C_CLK_RATIO) / (I2C_CLK_RATIO + 1); + clkhi = DIV_ROUND_UP(clk_cycle, I2C_CLK_RATIO + 1); clklo = clk_cycle - clkhi; if (clklo < 64) break; @@ -623,7 +623,7 @@ rpm_disable: return ret; } -static int lpi2c_imx_remove(struct platform_device *pdev) +static void lpi2c_imx_remove(struct platform_device *pdev) { struct lpi2c_imx_struct *lpi2c_imx = platform_get_drvdata(pdev); @@ -631,8 +631,6 @@ static int lpi2c_imx_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev); - - return 0; } static int __maybe_unused lpi2c_runtime_suspend(struct device *dev) @@ -669,7 +667,7 @@ static const struct dev_pm_ops lpi2c_pm_ops = { static struct platform_driver lpi2c_imx_driver = { .probe = lpi2c_imx_probe, - .remove = lpi2c_imx_remove, + .remove_new = lpi2c_imx_remove, .driver = { .name = DRIVER_NAME, .of_match_table = lpi2c_imx_of_match, diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 42189a5f2905..65128a73e8a3 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -1561,7 +1561,7 @@ rpm_disable: return ret; } -static int i2c_imx_remove(struct platform_device *pdev) +static void i2c_imx_remove(struct platform_device *pdev) { struct imx_i2c_struct *i2c_imx = platform_get_drvdata(pdev); int irq, ret; @@ -1592,8 +1592,6 @@ static int i2c_imx_remove(struct platform_device *pdev) pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); - - return 0; } static int __maybe_unused i2c_imx_runtime_suspend(struct device *dev) @@ -1624,7 +1622,7 @@ static const struct dev_pm_ops i2c_imx_pm_ops = { static struct platform_driver i2c_imx_driver = { .probe = i2c_imx_probe, - .remove = i2c_imx_remove, + .remove_new = i2c_imx_remove, .driver = { .name = DRIVER_NAME, .pm = &i2c_imx_pm_ops, diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c index 4a6ff54d87fe..f2f7ebeeaecb 100644 --- a/drivers/i2c/busses/i2c-iop3xx.c +++ b/drivers/i2c/busses/i2c-iop3xx.c @@ -388,7 +388,7 @@ static const struct i2c_algorithm iop3xx_i2c_algo = { .functionality = iop3xx_i2c_func, }; -static int +static void iop3xx_i2c_remove(struct platform_device *pdev) { struct i2c_adapter *padapter = platform_get_drvdata(pdev); @@ -408,8 +408,6 @@ iop3xx_i2c_remove(struct platform_device *pdev) release_mem_region(res->start, IOP3XX_I2C_IO_SIZE); kfree(adapter_data); kfree(padapter); - - return 0; } static int @@ -529,7 +527,7 @@ MODULE_DEVICE_TABLE(of, i2c_iop3xx_match); static struct platform_driver iop3xx_i2c_driver = { .probe = iop3xx_i2c_probe, - .remove = iop3xx_i2c_remove, + .remove_new = iop3xx_i2c_remove, .driver = { .name = "IOP3xx-I2C", .of_match_table = i2c_iop3xx_match, diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c index 2dc7ada06ac5..1dc1ceaa4443 100644 --- a/drivers/i2c/busses/i2c-isch.c +++ b/drivers/i2c/busses/i2c-isch.c @@ -286,14 +286,12 @@ static int smbus_sch_probe(struct platform_device *dev) return retval; } -static int smbus_sch_remove(struct platform_device *pdev) +static void smbus_sch_remove(struct platform_device *pdev) { if (sch_smba) { i2c_del_adapter(&sch_adapter); sch_smba = 0; } - - return 0; } static struct platform_driver smbus_sch_driver = { @@ -301,7 +299,7 @@ static struct platform_driver smbus_sch_driver = { .name = "isch_smbus", }, .probe = smbus_sch_probe, - .remove = smbus_sch_remove, + .remove_new = smbus_sch_remove, }; module_platform_driver(smbus_sch_driver); diff --git a/drivers/i2c/busses/i2c-jz4780.c b/drivers/i2c/busses/i2c-jz4780.c index baa7319eee53..0dfe60399521 100644 --- a/drivers/i2c/busses/i2c-jz4780.c +++ b/drivers/i2c/busses/i2c-jz4780.c @@ -845,18 +845,17 @@ err: return ret; } -static int jz4780_i2c_remove(struct platform_device *pdev) +static void jz4780_i2c_remove(struct platform_device *pdev) { struct jz4780_i2c *i2c = platform_get_drvdata(pdev); clk_disable_unprepare(i2c->clk); i2c_del_adapter(&i2c->adap); - return 0; } static struct platform_driver jz4780_i2c_driver = { .probe = jz4780_i2c_probe, - .remove = jz4780_i2c_remove, + .remove_new = jz4780_i2c_remove, .driver = { .name = "jz4780-i2c", .of_match_table = jz4780_i2c_of_matches, diff --git a/drivers/i2c/busses/i2c-kempld.c b/drivers/i2c/busses/i2c-kempld.c index cf857cf22507..281058e3ea46 100644 --- a/drivers/i2c/busses/i2c-kempld.c +++ b/drivers/i2c/busses/i2c-kempld.c @@ -329,7 +329,7 @@ static int kempld_i2c_probe(struct platform_device *pdev) return 0; } -static int kempld_i2c_remove(struct platform_device *pdev) +static void kempld_i2c_remove(struct platform_device *pdev) { struct kempld_i2c_data *i2c = platform_get_drvdata(pdev); struct kempld_device_data *pld = i2c->pld; @@ -348,8 +348,6 @@ static int kempld_i2c_remove(struct platform_device *pdev) kempld_release_mutex(pld); i2c_del_adapter(&i2c->adap); - - return 0; } #ifdef CONFIG_PM @@ -389,7 +387,7 @@ static struct platform_driver kempld_i2c_driver = { .name = "kempld-i2c", }, .probe = kempld_i2c_probe, - .remove = kempld_i2c_remove, + .remove_new = kempld_i2c_remove, .suspend = kempld_i2c_suspend, .resume = kempld_i2c_resume, }; diff --git a/drivers/i2c/busses/i2c-lpc2k.c b/drivers/i2c/busses/i2c-lpc2k.c index 8fff6fbb7065..5c6d96554753 100644 --- a/drivers/i2c/busses/i2c-lpc2k.c +++ b/drivers/i2c/busses/i2c-lpc2k.c @@ -365,23 +365,17 @@ static int i2c_lpc2k_probe(struct platform_device *pdev) init_waitqueue_head(&i2c->wait); - i2c->clk = devm_clk_get(&pdev->dev, NULL); + i2c->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(i2c->clk)) { - dev_err(&pdev->dev, "error getting clock\n"); + dev_err(&pdev->dev, "failed to enable clock.\n"); return PTR_ERR(i2c->clk); } - ret = clk_prepare_enable(i2c->clk); - if (ret) { - dev_err(&pdev->dev, "unable to enable clock.\n"); - return ret; - } - ret = devm_request_irq(&pdev->dev, i2c->irq, i2c_lpc2k_handler, 0, dev_name(&pdev->dev), i2c); if (ret < 0) { dev_err(&pdev->dev, "can't request interrupt.\n"); - goto fail_clk; + return ret; } disable_irq_nosync(i2c->irq); @@ -397,8 +391,7 @@ static int i2c_lpc2k_probe(struct platform_device *pdev) clkrate = clk_get_rate(i2c->clk); if (clkrate == 0) { dev_err(&pdev->dev, "can't get I2C base clock\n"); - ret = -EINVAL; - goto fail_clk; + return -EINVAL; } /* Setup I2C dividers to generate clock with proper duty cycle */ @@ -424,25 +417,18 @@ static int i2c_lpc2k_probe(struct platform_device *pdev) ret = i2c_add_adapter(&i2c->adap); if (ret < 0) - goto fail_clk; + return ret; dev_info(&pdev->dev, "LPC2K I2C adapter\n"); return 0; - -fail_clk: - clk_disable_unprepare(i2c->clk); - return ret; } -static int i2c_lpc2k_remove(struct platform_device *dev) +static void i2c_lpc2k_remove(struct platform_device *dev) { struct lpc2k_i2c *i2c = platform_get_drvdata(dev); i2c_del_adapter(&i2c->adap); - clk_disable_unprepare(i2c->clk); - - return 0; } #ifdef CONFIG_PM @@ -483,7 +469,7 @@ MODULE_DEVICE_TABLE(of, lpc2k_i2c_match); static struct platform_driver i2c_lpc2k_driver = { .probe = i2c_lpc2k_probe, - .remove = i2c_lpc2k_remove, + .remove_new = i2c_lpc2k_remove, .driver = { .name = "lpc2k-i2c", .pm = I2C_LPC2K_DEV_PM_OPS, diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c index 889eff06b78f..16026c895bb6 100644 --- a/drivers/i2c/busses/i2c-meson.c +++ b/drivers/i2c/busses/i2c-meson.c @@ -535,14 +535,12 @@ static int meson_i2c_probe(struct platform_device *pdev) return 0; } -static int meson_i2c_remove(struct platform_device *pdev) +static void meson_i2c_remove(struct platform_device *pdev) { struct meson_i2c *i2c = platform_get_drvdata(pdev); i2c_del_adapter(&i2c->adap); clk_disable_unprepare(i2c->clk); - - return 0; } static const struct meson_i2c_data i2c_meson6_data = { @@ -568,7 +566,7 @@ MODULE_DEVICE_TABLE(of, meson_i2c_match); static struct platform_driver meson_i2c_driver = { .probe = meson_i2c_probe, - .remove = meson_i2c_remove, + .remove_new = meson_i2c_remove, .driver = { .name = "meson-i2c", .of_match_table = meson_i2c_match, diff --git a/drivers/i2c/busses/i2c-microchip-corei2c.c b/drivers/i2c/busses/i2c-microchip-corei2c.c index 4d7e9b25f018..7f58f7eaabb6 100644 --- a/drivers/i2c/busses/i2c-microchip-corei2c.c +++ b/drivers/i2c/busses/i2c-microchip-corei2c.c @@ -446,14 +446,12 @@ static int mchp_corei2c_probe(struct platform_device *pdev) return 0; } -static int mchp_corei2c_remove(struct platform_device *pdev) +static void mchp_corei2c_remove(struct platform_device *pdev) { struct mchp_corei2c_dev *idev = platform_get_drvdata(pdev); clk_disable_unprepare(idev->i2c_clk); i2c_del_adapter(&idev->adapter); - - return 0; } static const struct of_device_id mchp_corei2c_of_match[] = { @@ -465,7 +463,7 @@ MODULE_DEVICE_TABLE(of, mchp_corei2c_of_match); static struct platform_driver mchp_corei2c_driver = { .probe = mchp_corei2c_probe, - .remove = mchp_corei2c_remove, + .remove_new = mchp_corei2c_remove, .driver = { .name = "microchip-corei2c", .of_match_table = mchp_corei2c_of_match, diff --git a/drivers/i2c/busses/i2c-mlxbf.c b/drivers/i2c/busses/i2c-mlxbf.c index 1810d5791b3d..ae66bdd1b737 100644 --- a/drivers/i2c/busses/i2c-mlxbf.c +++ b/drivers/i2c/busses/i2c-mlxbf.c @@ -2433,7 +2433,7 @@ static int mlxbf_i2c_probe(struct platform_device *pdev) return 0; } -static int mlxbf_i2c_remove(struct platform_device *pdev) +static void mlxbf_i2c_remove(struct platform_device *pdev) { struct mlxbf_i2c_priv *priv = platform_get_drvdata(pdev); struct device *dev = &pdev->dev; @@ -2474,13 +2474,11 @@ static int mlxbf_i2c_remove(struct platform_device *pdev) devm_free_irq(dev, priv->irq, priv); i2c_del_adapter(&priv->adap); - - return 0; } static struct platform_driver mlxbf_i2c_driver = { .probe = mlxbf_i2c_probe, - .remove = mlxbf_i2c_remove, + .remove_new = mlxbf_i2c_remove, .driver = { .name = "i2c-mlxbf", .acpi_match_table = ACPI_PTR(mlxbf_i2c_acpi_ids), diff --git a/drivers/i2c/busses/i2c-mlxcpld.c b/drivers/i2c/busses/i2c-mlxcpld.c index 081f51ef0551..c42fd4b329e4 100644 --- a/drivers/i2c/busses/i2c-mlxcpld.c +++ b/drivers/i2c/busses/i2c-mlxcpld.c @@ -571,19 +571,17 @@ mlxcpld_i2_probe_failed: return err; } -static int mlxcpld_i2c_remove(struct platform_device *pdev) +static void mlxcpld_i2c_remove(struct platform_device *pdev) { struct mlxcpld_i2c_priv *priv = platform_get_drvdata(pdev); i2c_del_adapter(&priv->adap); mutex_destroy(&priv->lock); - - return 0; } static struct platform_driver mlxcpld_i2c_driver = { .probe = mlxcpld_i2c_probe, - .remove = mlxcpld_i2c_remove, + .remove_new = mlxcpld_i2c_remove, .driver = { .name = MLXCPLD_I2C_DEVICE_NAME, }, diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index cfd074ee6d54..fb1b640f33b7 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -316,9 +316,10 @@ static void mpc_i2c_setup_512x(struct device_node *node, if (node_ctrl) { ctrl = of_iomap(node_ctrl, 0); if (ctrl) { + u64 addr; /* Interrupt enable bits for i2c-0/1/2: bit 24/26/28 */ - pval = of_get_property(node, "reg", NULL); - idx = (*pval & 0xff) / 0x20; + of_property_read_reg(node, 0, &addr, NULL); + idx = (addr & 0xff) / 0x20; setbits32(ctrl, 1 << (24 + idx * 2)); iounmap(ctrl); } @@ -890,15 +891,13 @@ static int fsl_i2c_probe(struct platform_device *op) return result; }; -static int fsl_i2c_remove(struct platform_device *op) +static void fsl_i2c_remove(struct platform_device *op) { struct mpc_i2c *i2c = platform_get_drvdata(op); i2c_del_adapter(&i2c->adap); clk_disable_unprepare(i2c->clk_per); - - return 0; }; static int __maybe_unused mpc_i2c_suspend(struct device *dev) @@ -959,7 +958,7 @@ MODULE_DEVICE_TABLE(of, mpc_i2c_of_match); /* Structure for a device driver */ static struct platform_driver mpc_i2c_driver = { .probe = fsl_i2c_probe, - .remove = fsl_i2c_remove, + .remove_new = fsl_i2c_remove, .driver = { .name = DRV_NAME, .of_match_table = mpc_i2c_of_match, diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index a43c4d77739a..7ca3f2221ba6 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -1505,15 +1505,13 @@ err_bulk_unprepare: return ret; } -static int mtk_i2c_remove(struct platform_device *pdev) +static void mtk_i2c_remove(struct platform_device *pdev) { struct mtk_i2c *i2c = platform_get_drvdata(pdev); i2c_del_adapter(&i2c->adap); clk_bulk_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1555,7 +1553,7 @@ static const struct dev_pm_ops mtk_i2c_pm = { static struct platform_driver mtk_i2c_driver = { .probe = mtk_i2c_probe, - .remove = mtk_i2c_remove, + .remove_new = mtk_i2c_remove, .driver = { .name = I2C_DRV_NAME, .pm = &mtk_i2c_pm, diff --git a/drivers/i2c/busses/i2c-mt7621.c b/drivers/i2c/busses/i2c-mt7621.c index 20eda5738ac4..104bb194e990 100644 --- a/drivers/i2c/busses/i2c-mt7621.c +++ b/drivers/i2c/busses/i2c-mt7621.c @@ -282,16 +282,11 @@ static int mtk_i2c_probe(struct platform_device *pdev) if (IS_ERR(i2c->base)) return PTR_ERR(i2c->base); - i2c->clk = devm_clk_get(&pdev->dev, NULL); + i2c->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(i2c->clk)) { - dev_err(&pdev->dev, "no clock defined\n"); + dev_err(&pdev->dev, "Failed to enable clock\n"); return PTR_ERR(i2c->clk); } - ret = clk_prepare_enable(i2c->clk); - if (ret) { - dev_err(&pdev->dev, "Unable to enable clock\n"); - return ret; - } i2c->dev = &pdev->dev; @@ -301,8 +296,7 @@ static int mtk_i2c_probe(struct platform_device *pdev) if (i2c->bus_freq == 0) { dev_warn(i2c->dev, "clock-frequency 0 not supported\n"); - ret = -EINVAL; - goto err_disable_clk; + return -EINVAL; } adap = &i2c->adap; @@ -320,31 +314,23 @@ static int mtk_i2c_probe(struct platform_device *pdev) ret = i2c_add_adapter(adap); if (ret < 0) - goto err_disable_clk; + return ret; dev_info(&pdev->dev, "clock %u kHz\n", i2c->bus_freq / 1000); return 0; - -err_disable_clk: - clk_disable_unprepare(i2c->clk); - - return ret; } -static int mtk_i2c_remove(struct platform_device *pdev) +static void mtk_i2c_remove(struct platform_device *pdev) { struct mtk_i2c *i2c = platform_get_drvdata(pdev); - clk_disable_unprepare(i2c->clk); i2c_del_adapter(&i2c->adap); - - return 0; } static struct platform_driver mtk_i2c_driver = { .probe = mtk_i2c_probe, - .remove = mtk_i2c_remove, + .remove_new = mtk_i2c_remove, .driver = { .name = "i2c-mt7621", .of_match_table = i2c_mtk_dt_ids, diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 878c076ebdc6..fd8403b07fa6 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -1084,7 +1084,7 @@ exit_disable_pm: return rc; } -static int +static void mv64xxx_i2c_remove(struct platform_device *pd) { struct mv64xxx_i2c_data *drv_data = platform_get_drvdata(pd); @@ -1094,8 +1094,6 @@ mv64xxx_i2c_remove(struct platform_device *pd) pm_runtime_disable(&pd->dev); if (!pm_runtime_status_suspended(&pd->dev)) mv64xxx_i2c_runtime_suspend(&pd->dev); - - return 0; } static const struct dev_pm_ops mv64xxx_i2c_pm_ops = { @@ -1107,7 +1105,7 @@ static const struct dev_pm_ops mv64xxx_i2c_pm_ops = { static struct platform_driver mv64xxx_i2c_driver = { .probe = mv64xxx_i2c_probe, - .remove = mv64xxx_i2c_remove, + .remove_new = mv64xxx_i2c_remove, .driver = { .name = MV64XXX_I2C_CTLR_NAME, .pm = &mv64xxx_i2c_pm_ops, diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index e0f3b3545cfe..1d76f1c4dc06 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -864,7 +864,7 @@ static int mxs_i2c_probe(struct platform_device *pdev) return 0; } -static int mxs_i2c_remove(struct platform_device *pdev) +static void mxs_i2c_remove(struct platform_device *pdev) { struct mxs_i2c_dev *i2c = platform_get_drvdata(pdev); @@ -874,8 +874,6 @@ static int mxs_i2c_remove(struct platform_device *pdev) dma_release_channel(i2c->dmach); writel(MXS_I2C_CTRL0_SFTRST, i2c->regs + MXS_I2C_CTRL0_SET); - - return 0; } static struct platform_driver mxs_i2c_driver = { @@ -884,7 +882,7 @@ static struct platform_driver mxs_i2c_driver = { .of_match_table = mxs_i2c_dt_ids, }, .probe = mxs_i2c_probe, - .remove = mxs_i2c_remove, + .remove_new = mxs_i2c_remove, }; static int __init mxs_i2c_init(void) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index a2d12a5b1c34..1e5fd23ef45c 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -970,12 +970,10 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) struct i2c_vendor_data *vendor = id->data; u32 max_fifo_threshold = (vendor->fifodepth / 2) - 1; - dev = devm_kzalloc(&adev->dev, sizeof(struct nmk_i2c_dev), GFP_KERNEL); - if (!dev) { - dev_err(&adev->dev, "cannot allocate memory\n"); - ret = -ENOMEM; - goto err_no_mem; - } + dev = devm_kzalloc(&adev->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + dev->vendor = vendor; dev->adev = adev; nmk_i2c_of_probe(np, dev); @@ -996,31 +994,20 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) dev->virtbase = devm_ioremap(&adev->dev, adev->res.start, resource_size(&adev->res)); - if (!dev->virtbase) { - ret = -ENOMEM; - goto err_no_mem; - } + if (!dev->virtbase) + return -ENOMEM; dev->irq = adev->irq[0]; ret = devm_request_irq(&adev->dev, dev->irq, i2c_irq_handler, 0, DRIVER_NAME, dev); - if (ret) { - dev_err(&adev->dev, "cannot claim the irq %d\n", dev->irq); - goto err_no_mem; - } - - dev->clk = devm_clk_get(&adev->dev, NULL); - if (IS_ERR(dev->clk)) { - dev_err(&adev->dev, "could not get i2c clock\n"); - ret = PTR_ERR(dev->clk); - goto err_no_mem; - } + if (ret) + return dev_err_probe(&adev->dev, ret, + "cannot claim the irq %d\n", dev->irq); - ret = clk_prepare_enable(dev->clk); - if (ret) { - dev_err(&adev->dev, "can't prepare_enable clock\n"); - goto err_no_mem; - } + dev->clk = devm_clk_get_enabled(&adev->dev, NULL); + if (IS_ERR(dev->clk)) + return dev_err_probe(&adev->dev, PTR_ERR(dev->clk), + "could enable i2c clock\n"); init_hw(dev); @@ -1042,17 +1029,11 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) ret = i2c_add_adapter(adap); if (ret) - goto err_no_adap; + return ret; pm_runtime_put(&adev->dev); return 0; - - err_no_adap: - clk_disable_unprepare(dev->clk); - err_no_mem: - - return ret; } static void nmk_i2c_remove(struct amba_device *adev) @@ -1066,7 +1047,6 @@ static void nmk_i2c_remove(struct amba_device *adev) clear_all_interrupts(dev); /* disable the controller */ i2c_clr_bit(dev->virtbase + I2C_CR, I2C_CR_PE); - clk_disable_unprepare(dev->clk); release_mem_region(res->start, resource_size(res)); } diff --git a/drivers/i2c/busses/i2c-npcm7xx.c b/drivers/i2c/busses/i2c-npcm7xx.c index 38d5864d0cb5..53b65ffb6a64 100644 --- a/drivers/i2c/busses/i2c-npcm7xx.c +++ b/drivers/i2c/busses/i2c-npcm7xx.c @@ -2361,7 +2361,7 @@ static int npcm_i2c_probe_bus(struct platform_device *pdev) return 0; } -static int npcm_i2c_remove_bus(struct platform_device *pdev) +static void npcm_i2c_remove_bus(struct platform_device *pdev) { unsigned long lock_flags; struct npcm_i2c *bus = platform_get_drvdata(pdev); @@ -2371,7 +2371,6 @@ static int npcm_i2c_remove_bus(struct platform_device *pdev) npcm_i2c_disable(bus); spin_unlock_irqrestore(&bus->lock, lock_flags); i2c_del_adapter(&bus->adap); - return 0; } static const struct of_device_id npcm_i2c_bus_of_table[] = { @@ -2383,7 +2382,7 @@ MODULE_DEVICE_TABLE(of, npcm_i2c_bus_of_table); static struct platform_driver npcm_i2c_bus_driver = { .probe = npcm_i2c_probe_bus, - .remove = npcm_i2c_remove_bus, + .remove_new = npcm_i2c_remove_bus, .driver = { .name = "nuvoton-i2c", .of_match_table = npcm_i2c_bus_of_table, diff --git a/drivers/i2c/busses/i2c-nvidia-gpu.c b/drivers/i2c/busses/i2c-nvidia-gpu.c index a8b99e7f6262..26622d24bb1b 100644 --- a/drivers/i2c/busses/i2c-nvidia-gpu.c +++ b/drivers/i2c/busses/i2c-nvidia-gpu.c @@ -14,6 +14,7 @@ #include <linux/platform_device.h> #include <linux/pm.h> #include <linux/pm_runtime.h> +#include <linux/power_supply.h> #include <asm/unaligned.h> @@ -261,6 +262,8 @@ MODULE_DEVICE_TABLE(pci, gpu_i2c_ids); static const struct property_entry ccgx_props[] = { /* Use FW built for NVIDIA GPU only */ PROPERTY_ENTRY_STRING("firmware-name", "nvidia,gpu"), + /* USB-C doesn't power the system */ + PROPERTY_ENTRY_U8("scope", POWER_SUPPLY_SCOPE_DEVICE), { } }; diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index 2e575856c5cd..4ac77e57bbbf 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -552,28 +552,20 @@ static int ocores_i2c_of_probe(struct platform_device *pdev, &clock_frequency); i2c->bus_clock_khz = 100; - i2c->clk = devm_clk_get(&pdev->dev, NULL); - - if (!IS_ERR(i2c->clk)) { - int ret = clk_prepare_enable(i2c->clk); - - if (ret) { - dev_err(&pdev->dev, - "clk_prepare_enable failed: %d\n", ret); - return ret; - } - i2c->ip_clock_khz = clk_get_rate(i2c->clk) / 1000; - if (clock_frequency_present) - i2c->bus_clock_khz = clock_frequency / 1000; - } - + i2c->clk = devm_clk_get_optional_enabled(&pdev->dev, NULL); + if (IS_ERR(i2c->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(i2c->clk), + "devm_clk_get_optional_enabled failed\n"); + + i2c->ip_clock_khz = clk_get_rate(i2c->clk) / 1000; + if (clock_frequency_present) + i2c->bus_clock_khz = clock_frequency / 1000; if (i2c->ip_clock_khz == 0) { if (of_property_read_u32(np, "opencores,ip-clock-frequency", &val)) { if (!clock_frequency_present) { dev_err(&pdev->dev, "Missing required parameter 'opencores,ip-clock-frequency'\n"); - clk_disable_unprepare(i2c->clk); return -ENODEV; } i2c->ip_clock_khz = clock_frequency / 1000; @@ -678,8 +670,7 @@ static int ocores_i2c_probe(struct platform_device *pdev) default: dev_err(&pdev->dev, "Unsupported I/O width (%d)\n", i2c->reg_io_width); - ret = -EINVAL; - goto err_clk; + return -EINVAL; } } @@ -710,13 +701,13 @@ static int ocores_i2c_probe(struct platform_device *pdev) pdev->name, i2c); if (ret) { dev_err(&pdev->dev, "Cannot claim IRQ\n"); - goto err_clk; + return ret; } } ret = ocores_init(&pdev->dev, i2c); if (ret) - goto err_clk; + return ret; /* hook up driver to tree */ platform_set_drvdata(pdev, i2c); @@ -728,7 +719,7 @@ static int ocores_i2c_probe(struct platform_device *pdev) /* add i2c adapter to i2c tree */ ret = i2c_add_adapter(&i2c->adap); if (ret) - goto err_clk; + return ret; /* add in known devices to the bus */ if (pdata) { @@ -737,13 +728,9 @@ static int ocores_i2c_probe(struct platform_device *pdev) } return 0; - -err_clk: - clk_disable_unprepare(i2c->clk); - return ret; } -static int ocores_i2c_remove(struct platform_device *pdev) +static void ocores_i2c_remove(struct platform_device *pdev) { struct ocores_i2c *i2c = platform_get_drvdata(pdev); u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL); @@ -754,11 +741,6 @@ static int ocores_i2c_remove(struct platform_device *pdev) /* remove adapter & data */ i2c_del_adapter(&i2c->adap); - - if (!IS_ERR(i2c->clk)) - clk_disable_unprepare(i2c->clk); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -771,28 +753,22 @@ static int ocores_i2c_suspend(struct device *dev) ctrl &= ~(OCI2C_CTRL_EN | OCI2C_CTRL_IEN); oc_setreg(i2c, OCI2C_CONTROL, ctrl); - if (!IS_ERR(i2c->clk)) - clk_disable_unprepare(i2c->clk); + clk_disable_unprepare(i2c->clk); return 0; } static int ocores_i2c_resume(struct device *dev) { struct ocores_i2c *i2c = dev_get_drvdata(dev); + unsigned long rate; + int ret; - if (!IS_ERR(i2c->clk)) { - unsigned long rate; - int ret = clk_prepare_enable(i2c->clk); - - if (ret) { - dev_err(dev, - "clk_prepare_enable failed: %d\n", ret); - return ret; - } - rate = clk_get_rate(i2c->clk) / 1000; - if (rate) - i2c->ip_clock_khz = rate; - } + ret = clk_prepare_enable(i2c->clk); + if (ret) + return dev_err_probe(dev, ret, "clk_prepare_enable failed\n"); + rate = clk_get_rate(i2c->clk) / 1000; + if (rate) + i2c->ip_clock_khz = rate; return ocores_init(dev, i2c); } @@ -804,7 +780,7 @@ static SIMPLE_DEV_PM_OPS(ocores_i2c_pm, ocores_i2c_suspend, ocores_i2c_resume); static struct platform_driver ocores_i2c_driver = { .probe = ocores_i2c_probe, - .remove = ocores_i2c_remove, + .remove_new = ocores_i2c_remove, .driver = { .name = "ocores-i2c", .of_match_table = ocores_i2c_match, diff --git a/drivers/i2c/busses/i2c-octeon-platdrv.c b/drivers/i2c/busses/i2c-octeon-platdrv.c index 0c227963c8d6..7d54b3203f71 100644 --- a/drivers/i2c/busses/i2c-octeon-platdrv.c +++ b/drivers/i2c/busses/i2c-octeon-platdrv.c @@ -253,12 +253,11 @@ out: return result; }; -static int octeon_i2c_remove(struct platform_device *pdev) +static void octeon_i2c_remove(struct platform_device *pdev) { struct octeon_i2c *i2c = platform_get_drvdata(pdev); i2c_del_adapter(&i2c->adap); - return 0; }; static const struct of_device_id octeon_i2c_match[] = { @@ -270,7 +269,7 @@ MODULE_DEVICE_TABLE(of, octeon_i2c_match); static struct platform_driver octeon_i2c_driver = { .probe = octeon_i2c_probe, - .remove = octeon_i2c_remove, + .remove_new = octeon_i2c_remove, .driver = { .name = DRV_NAME, .of_match_table = octeon_i2c_match, diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 4199f57a6bf2..58fd6fa3edf1 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1519,7 +1519,7 @@ err_disable_pm: return r; } -static int omap_i2c_remove(struct platform_device *pdev) +static void omap_i2c_remove(struct platform_device *pdev) { struct omap_i2c_dev *omap = platform_get_drvdata(pdev); int ret; @@ -1535,8 +1535,6 @@ static int omap_i2c_remove(struct platform_device *pdev) pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); - - return 0; } static int __maybe_unused omap_i2c_runtime_suspend(struct device *dev) @@ -1588,7 +1586,7 @@ static const struct dev_pm_ops omap_i2c_pm_ops = { static struct platform_driver omap_i2c_driver = { .probe = omap_i2c_probe, - .remove = omap_i2c_remove, + .remove_new = omap_i2c_remove, .driver = { .name = "omap_i2c", .pm = &omap_i2c_pm_ops, diff --git a/drivers/i2c/busses/i2c-opal.c b/drivers/i2c/busses/i2c-opal.c index 9f773b4f5ed8..17ef87d50f7c 100644 --- a/drivers/i2c/busses/i2c-opal.c +++ b/drivers/i2c/busses/i2c-opal.c @@ -232,13 +232,11 @@ static int i2c_opal_probe(struct platform_device *pdev) return rc; } -static int i2c_opal_remove(struct platform_device *pdev) +static void i2c_opal_remove(struct platform_device *pdev) { struct i2c_adapter *adapter = platform_get_drvdata(pdev); i2c_del_adapter(adapter); - - return 0; } static const struct of_device_id i2c_opal_of_match[] = { @@ -251,7 +249,7 @@ MODULE_DEVICE_TABLE(of, i2c_opal_of_match); static struct platform_driver i2c_opal_driver = { .probe = i2c_opal_probe, - .remove = i2c_opal_remove, + .remove_new = i2c_opal_remove, .driver = { .name = "i2c-opal", .of_match_table = i2c_opal_of_match, diff --git a/drivers/i2c/busses/i2c-owl.c b/drivers/i2c/busses/i2c-owl.c index 99ddd8894964..5f0ef8c35141 100644 --- a/drivers/i2c/busses/i2c-owl.c +++ b/drivers/i2c/busses/i2c-owl.c @@ -461,21 +461,16 @@ static int owl_i2c_probe(struct platform_device *pdev) return -EINVAL; } - i2c_dev->clk = devm_clk_get(dev, NULL); + i2c_dev->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(i2c_dev->clk)) { - dev_err(dev, "failed to get clock\n"); + dev_err(dev, "failed to enable clock\n"); return PTR_ERR(i2c_dev->clk); } - ret = clk_prepare_enable(i2c_dev->clk); - if (ret) - return ret; - i2c_dev->clk_rate = clk_get_rate(i2c_dev->clk); if (!i2c_dev->clk_rate) { dev_err(dev, "input clock rate should not be zero\n"); - ret = -EINVAL; - goto disable_clk; + return -EINVAL; } init_completion(&i2c_dev->msg_complete); @@ -496,15 +491,10 @@ static int owl_i2c_probe(struct platform_device *pdev) i2c_dev); if (ret) { dev_err(dev, "failed to request irq %d\n", irq); - goto disable_clk; + return ret; } return i2c_add_adapter(&i2c_dev->adap); - -disable_clk: - clk_disable_unprepare(i2c_dev->clk); - - return ret; } static const struct of_device_id owl_i2c_of_match[] = { diff --git a/drivers/i2c/busses/i2c-pasemi-platform.c b/drivers/i2c/busses/i2c-pasemi-platform.c index e35945a91dbe..5fbfb9b41744 100644 --- a/drivers/i2c/busses/i2c-pasemi-platform.c +++ b/drivers/i2c/busses/i2c-pasemi-platform.c @@ -66,22 +66,18 @@ static int pasemi_platform_i2c_probe(struct platform_device *pdev) if (of_property_read_u32(dev->of_node, "clock-frequency", &frequency)) frequency = I2C_MAX_STANDARD_MODE_FREQ; - data->clk_ref = devm_clk_get(dev, NULL); + data->clk_ref = devm_clk_get_enabled(dev, NULL); if (IS_ERR(data->clk_ref)) return PTR_ERR(data->clk_ref); - error = clk_prepare_enable(data->clk_ref); - if (error) - return error; - error = pasemi_platform_i2c_calc_clk_div(data, frequency); if (error) - goto out_clk_disable; + return error; smbus->adapter.dev.of_node = pdev->dev.of_node; error = pasemi_i2c_common_probe(smbus); if (error) - goto out_clk_disable; + return error; irq_num = platform_get_irq(pdev, 0); error = devm_request_irq(smbus->dev, irq_num, pasemi_irq_handler, 0, "pasemi_apple_i2c", (void *)smbus); @@ -91,20 +87,9 @@ static int pasemi_platform_i2c_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); return 0; - -out_clk_disable: - clk_disable_unprepare(data->clk_ref); - - return error; } -static int pasemi_platform_i2c_remove(struct platform_device *pdev) -{ - struct pasemi_platform_i2c_data *data = platform_get_drvdata(pdev); - - clk_disable_unprepare(data->clk_ref); - return 0; -} +static void pasemi_platform_i2c_remove(struct platform_device *pdev) { } static const struct of_device_id pasemi_platform_i2c_of_match[] = { { .compatible = "apple,t8103-i2c" }, @@ -119,7 +104,7 @@ static struct platform_driver pasemi_platform_i2c_driver = { .of_match_table = pasemi_platform_i2c_of_match, }, .probe = pasemi_platform_i2c_probe, - .remove = pasemi_platform_i2c_remove, + .remove_new = pasemi_platform_i2c_remove, }; module_platform_driver(pasemi_platform_i2c_driver); diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index 86d4f75ef8d3..d2a9e7b61c1a 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -221,13 +221,11 @@ static int i2c_pca_pf_probe(struct platform_device *pdev) return 0; } -static int i2c_pca_pf_remove(struct platform_device *pdev) +static void i2c_pca_pf_remove(struct platform_device *pdev) { struct i2c_pca_pf_data *i2c = platform_get_drvdata(pdev); i2c_del_adapter(&i2c->adap); - - return 0; } #ifdef CONFIG_OF @@ -241,7 +239,7 @@ MODULE_DEVICE_TABLE(of, i2c_pca_of_match_table); static struct platform_driver i2c_pca_pf_driver = { .probe = i2c_pca_pf_probe, - .remove = i2c_pca_pf_remove, + .remove_new = i2c_pca_pf_remove, .driver = { .name = "i2c-pca-platform", .of_match_table = of_match_ptr(i2c_pca_of_match_table), diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 50f21cdbe90d..82400057f810 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -743,14 +743,12 @@ out_clock: return ret; } -static int i2c_pnx_remove(struct platform_device *pdev) +static void i2c_pnx_remove(struct platform_device *pdev) { struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev); i2c_del_adapter(&alg_data->adapter); clk_disable_unprepare(alg_data->clk); - - return 0; } #ifdef CONFIG_OF @@ -768,7 +766,7 @@ static struct platform_driver i2c_pnx_driver = { .pm = PNX_I2C_PM, }, .probe = i2c_pnx_probe, - .remove = i2c_pnx_remove, + .remove_new = i2c_pnx_remove, }; static int __init i2c_adap_pnx_init(void) diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c index ec706a3aba26..4996a628fdae 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -188,14 +188,12 @@ static const struct i2c_adapter_quirks i2c_powermac_quirks = { .max_num_msgs = 1, }; -static int i2c_powermac_remove(struct platform_device *dev) +static void i2c_powermac_remove(struct platform_device *dev) { struct i2c_adapter *adapter = platform_get_drvdata(dev); i2c_del_adapter(adapter); memset(adapter, 0, sizeof(*adapter)); - - return 0; } static u32 i2c_powermac_get_addr(struct i2c_adapter *adap, @@ -439,7 +437,7 @@ static int i2c_powermac_probe(struct platform_device *dev) static struct platform_driver i2c_powermac_driver = { .probe = i2c_powermac_probe, - .remove = i2c_powermac_remove, + .remove_new = i2c_powermac_remove, .driver = { .name = "i2c-powermac", .bus = &platform_bus_type, diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index f9fa5308556b..937f7eebe906 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -1482,15 +1482,13 @@ ereqirq: return ret; } -static int i2c_pxa_remove(struct platform_device *dev) +static void i2c_pxa_remove(struct platform_device *dev) { struct pxa_i2c *i2c = platform_get_drvdata(dev); i2c_del_adapter(&i2c->adap); clk_disable_unprepare(i2c->clk); - - return 0; } #ifdef CONFIG_PM @@ -1525,7 +1523,7 @@ static const struct dev_pm_ops i2c_pxa_dev_pm_ops = { static struct platform_driver i2c_pxa_driver = { .probe = i2c_pxa_probe, - .remove = i2c_pxa_remove, + .remove_new = i2c_pxa_remove, .driver = { .name = "pxa2xx-i2c", .pm = I2C_PXA_DEV_PM_OPS, diff --git a/drivers/i2c/busses/i2c-qcom-cci.c b/drivers/i2c/busses/i2c-qcom-cci.c index 01358472680c..622dc14add9d 100644 --- a/drivers/i2c/busses/i2c-qcom-cci.c +++ b/drivers/i2c/busses/i2c-qcom-cci.c @@ -581,8 +581,7 @@ static int cci_probe(struct platform_device *pdev) /* Memory */ - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - cci->base = devm_ioremap_resource(dev, r); + cci->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r); if (IS_ERR(cci->base)) return PTR_ERR(cci->base); @@ -675,7 +674,7 @@ disable_clocks: return ret; } -static int cci_remove(struct platform_device *pdev) +static void cci_remove(struct platform_device *pdev) { struct cci *cci = platform_get_drvdata(pdev); int i; @@ -691,8 +690,6 @@ static int cci_remove(struct platform_device *pdev) disable_irq(cci->irq); pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); - - return 0; } static const struct cci_data cci_v1_data = { @@ -829,7 +826,7 @@ MODULE_DEVICE_TABLE(of, cci_dt_match); static struct platform_driver qcom_cci_driver = { .probe = cci_probe, - .remove = cci_remove, + .remove_new = cci_remove, .driver = { .name = "i2c-qcom-cci", .of_match_table = cci_dt_match, diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 83909b02a03e..b670a67c4fdd 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -936,14 +936,13 @@ err_dma: return ret; } -static int geni_i2c_remove(struct platform_device *pdev) +static void geni_i2c_remove(struct platform_device *pdev) { struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev); i2c_del_adapter(&gi2c->adap); release_gpi_dma(gi2c); pm_runtime_disable(gi2c->se.dev); - return 0; } static void geni_i2c_shutdown(struct platform_device *pdev) @@ -1041,7 +1040,7 @@ MODULE_DEVICE_TABLE(of, geni_i2c_dt_match); static struct platform_driver geni_i2c_driver = { .probe = geni_i2c_probe, - .remove = geni_i2c_remove, + .remove_new = geni_i2c_remove, .shutdown = geni_i2c_shutdown, .driver = { .name = "geni_i2c", diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index 78682388e02e..ae90170023b0 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -1911,7 +1911,7 @@ fail_dma: return ret; } -static int qup_i2c_remove(struct platform_device *pdev) +static void qup_i2c_remove(struct platform_device *pdev) { struct qup_i2c_dev *qup = platform_get_drvdata(pdev); @@ -1925,7 +1925,6 @@ static int qup_i2c_remove(struct platform_device *pdev) i2c_del_adapter(&qup->adap); pm_runtime_disable(qup->dev); pm_runtime_set_suspended(qup->dev); - return 0; } #ifdef CONFIG_PM @@ -1985,7 +1984,7 @@ MODULE_DEVICE_TABLE(of, qup_i2c_dt_match); static struct platform_driver qup_i2c_driver = { .probe = qup_i2c_probe, - .remove = qup_i2c_remove, + .remove_new = qup_i2c_remove, .driver = { .name = "i2c_qup", .pm = &qup_i2c_qup_pm_ops, diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index cef82b205c26..2d9c37410ebd 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -1155,7 +1155,7 @@ static int rcar_i2c_probe(struct platform_device *pdev) return ret; } -static int rcar_i2c_remove(struct platform_device *pdev) +static void rcar_i2c_remove(struct platform_device *pdev) { struct rcar_i2c_priv *priv = platform_get_drvdata(pdev); struct device *dev = &pdev->dev; @@ -1167,8 +1167,6 @@ static int rcar_i2c_remove(struct platform_device *pdev) if (priv->flags & ID_P_PM_BLOCKED) pm_runtime_put(dev); pm_runtime_disable(dev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1204,7 +1202,7 @@ static struct platform_driver rcar_i2c_driver = { .pm = DEV_PM_OPS, }, .probe = rcar_i2c_probe, - .remove = rcar_i2c_remove, + .remove_new = rcar_i2c_remove, }; module_platform_driver(rcar_i2c_driver); diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c index 849848ccb080..5f8c0bd508d2 100644 --- a/drivers/i2c/busses/i2c-riic.c +++ b/drivers/i2c/busses/i2c-riic.c @@ -477,7 +477,7 @@ out: return ret; } -static int riic_i2c_remove(struct platform_device *pdev) +static void riic_i2c_remove(struct platform_device *pdev) { struct riic_dev *riic = platform_get_drvdata(pdev); @@ -486,8 +486,6 @@ static int riic_i2c_remove(struct platform_device *pdev) pm_runtime_put(&pdev->dev); i2c_del_adapter(&riic->adapter); pm_runtime_disable(&pdev->dev); - - return 0; } static const struct of_device_id riic_i2c_dt_ids[] = { @@ -497,7 +495,7 @@ static const struct of_device_id riic_i2c_dt_ids[] = { static struct platform_driver riic_i2c_driver = { .probe = riic_i2c_probe, - .remove = riic_i2c_remove, + .remove_new = riic_i2c_remove, .driver = { .name = "i2c-riic", .of_match_table = riic_i2c_dt_ids, diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c index b31cf4f18f85..a044ca0c35a1 100644 --- a/drivers/i2c/busses/i2c-rk3x.c +++ b/drivers/i2c/busses/i2c-rk3x.c @@ -1372,7 +1372,7 @@ err_clk: return ret; } -static int rk3x_i2c_remove(struct platform_device *pdev) +static void rk3x_i2c_remove(struct platform_device *pdev) { struct rk3x_i2c *i2c = platform_get_drvdata(pdev); @@ -1381,15 +1381,13 @@ static int rk3x_i2c_remove(struct platform_device *pdev) clk_notifier_unregister(i2c->clk, &i2c->clk_rate_nb); clk_unprepare(i2c->pclk); clk_unprepare(i2c->clk); - - return 0; } static SIMPLE_DEV_PM_OPS(rk3x_i2c_pm_ops, NULL, rk3x_i2c_resume); static struct platform_driver rk3x_i2c_driver = { .probe = rk3x_i2c_probe, - .remove = rk3x_i2c_remove, + .remove_new = rk3x_i2c_remove, .driver = { .name = "rk3x-i2c", .of_match_table = rk3x_i2c_match, diff --git a/drivers/i2c/busses/i2c-rzv2m.c b/drivers/i2c/busses/i2c-rzv2m.c index 56d0faee5c46..b0bfc96b9ede 100644 --- a/drivers/i2c/busses/i2c-rzv2m.c +++ b/drivers/i2c/busses/i2c-rzv2m.c @@ -50,9 +50,6 @@ #define IICB0MDSC BIT(7) /* Bus Mode */ #define IICB0SLSE BIT(1) /* Start condition output */ -#define bit_setl(addr, val) writel(readl(addr) | (val), (addr)) -#define bit_clrl(addr, val) writel(readl(addr) & ~(val), (addr)) - struct rzv2m_i2c_priv { void __iomem *base; struct i2c_adapter adap; @@ -78,6 +75,16 @@ static const struct bitrate_config bitrate_configs[] = { [RZV2M_I2C_400K] = { 52, 900 }, }; +static inline void bit_setl(void __iomem *addr, u32 val) +{ + writel(readl(addr) | val, addr); +} + +static inline void bit_clrl(void __iomem *addr, u32 val) +{ + writel(readl(addr) & ~val, addr); +} + static irqreturn_t rzv2m_i2c_tia_irq_handler(int this_irq, void *dev_id) { struct rzv2m_i2c_priv *priv = dev_id; @@ -382,6 +389,20 @@ static u32 rzv2m_i2c_func(struct i2c_adapter *adap) I2C_FUNC_10BIT_ADDR; } +static int rzv2m_i2c_disable(struct device *dev, struct rzv2m_i2c_priv *priv) +{ + int ret; + + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) + return ret; + + bit_clrl(priv->base + IICB0CTL0, IICB0IICE); + pm_runtime_put(dev); + + return 0; +} + static const struct i2c_adapter_quirks rzv2m_i2c_quirks = { .flags = I2C_AQ_NO_ZERO_LEN, }; @@ -454,37 +475,29 @@ static int rzv2m_i2c_probe(struct platform_device *pdev) platform_set_drvdata(pdev, priv); ret = i2c_add_numbered_adapter(adap); - if (ret < 0) + if (ret < 0) { + rzv2m_i2c_disable(dev, priv); pm_runtime_disable(dev); + } return ret; } -static int rzv2m_i2c_remove(struct platform_device *pdev) +static void rzv2m_i2c_remove(struct platform_device *pdev) { struct rzv2m_i2c_priv *priv = platform_get_drvdata(pdev); struct device *dev = priv->adap.dev.parent; i2c_del_adapter(&priv->adap); - bit_clrl(priv->base + IICB0CTL0, IICB0IICE); + rzv2m_i2c_disable(dev, priv); pm_runtime_disable(dev); - - return 0; } static int rzv2m_i2c_suspend(struct device *dev) { struct rzv2m_i2c_priv *priv = dev_get_drvdata(dev); - int ret; - ret = pm_runtime_resume_and_get(dev); - if (ret < 0) - return ret; - - bit_clrl(priv->base + IICB0CTL0, IICB0IICE); - pm_runtime_put(dev); - - return 0; + return rzv2m_i2c_disable(dev, priv); } static int rzv2m_i2c_resume(struct device *dev) @@ -523,7 +536,7 @@ static struct platform_driver rzv2m_i2c_driver = { .pm = pm_sleep_ptr(&rzv2m_i2c_pm_ops), }, .probe = rzv2m_i2c_probe, - .remove = rzv2m_i2c_remove, + .remove_new = rzv2m_i2c_remove, }; module_platform_driver(rzv2m_i2c_driver); diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 45e9df81345a..28f0e5c64f32 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -1114,7 +1114,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) return 0; } -static int s3c24xx_i2c_remove(struct platform_device *pdev) +static void s3c24xx_i2c_remove(struct platform_device *pdev) { struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); @@ -1123,8 +1123,6 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); i2c_del_adapter(&i2c->adap); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1172,7 +1170,7 @@ static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = { static struct platform_driver s3c24xx_i2c_driver = { .probe = s3c24xx_i2c_probe, - .remove = s3c24xx_i2c_remove, + .remove_new = s3c24xx_i2c_remove, .id_table = s3c24xx_driver_ids, .driver = { .name = "s3c-i2c", diff --git a/drivers/i2c/busses/i2c-scmi.c b/drivers/i2c/busses/i2c-scmi.c index 0239e134b90f..104570292241 100644 --- a/drivers/i2c/busses/i2c-scmi.c +++ b/drivers/i2c/busses/i2c-scmi.c @@ -404,19 +404,17 @@ err: return ret; } -static int smbus_cmi_remove(struct platform_device *device) +static void smbus_cmi_remove(struct platform_device *device) { struct acpi_smbus_cmi *smbus_cmi = platform_get_drvdata(device); i2c_del_adapter(&smbus_cmi->adapter); kfree(smbus_cmi); - - return 0; } static struct platform_driver smbus_cmi_driver = { .probe = smbus_cmi_probe, - .remove = smbus_cmi_remove, + .remove_new = smbus_cmi_remove, .driver = { .name = "smbus_cmi", .acpi_match_table = acpi_smbus_cmi_ids, diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c index 319d1fa617c8..1ad2a26156d1 100644 --- a/drivers/i2c/busses/i2c-sh7760.c +++ b/drivers/i2c/busses/i2c-sh7760.c @@ -443,9 +443,8 @@ static int sh7760_i2c_probe(struct platform_device *pdev) goto out0; } - id = kzalloc(sizeof(struct cami2c), GFP_KERNEL); + id = kzalloc(sizeof(*id), GFP_KERNEL); if (!id) { - dev_err(&pdev->dev, "no mem for private data\n"); ret = -ENOMEM; goto out0; } @@ -536,7 +535,7 @@ out0: return ret; } -static int sh7760_i2c_remove(struct platform_device *pdev) +static void sh7760_i2c_remove(struct platform_device *pdev) { struct cami2c *id = platform_get_drvdata(pdev); @@ -546,8 +545,6 @@ static int sh7760_i2c_remove(struct platform_device *pdev) release_resource(id->ioarea); kfree(id->ioarea); kfree(id); - - return 0; } static struct platform_driver sh7760_i2c_drv = { @@ -555,7 +552,7 @@ static struct platform_driver sh7760_i2c_drv = { .name = SH7760_I2C_DEVNAME, }, .probe = sh7760_i2c_probe, - .remove = sh7760_i2c_remove, + .remove_new = sh7760_i2c_remove, }; module_platform_driver(sh7760_i2c_drv); diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 29330ee64c9c..21717b943a9e 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -956,14 +956,13 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) return 0; } -static int sh_mobile_i2c_remove(struct platform_device *dev) +static void sh_mobile_i2c_remove(struct platform_device *dev) { struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev); i2c_del_adapter(&pd->adap); sh_mobile_i2c_release_dma(pd); pm_runtime_disable(&dev->dev); - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1000,7 +999,7 @@ static struct platform_driver sh_mobile_i2c_driver = { .pm = DEV_PM_OPS, }, .probe = sh_mobile_i2c_probe, - .remove = sh_mobile_i2c_remove, + .remove_new = sh_mobile_i2c_remove, }; static int __init sh_mobile_i2c_adap_init(void) diff --git a/drivers/i2c/busses/i2c-simtec.c b/drivers/i2c/busses/i2c-simtec.c index 87701744752f..18516bc64e04 100644 --- a/drivers/i2c/busses/i2c-simtec.c +++ b/drivers/i2c/busses/i2c-simtec.c @@ -126,7 +126,7 @@ static int simtec_i2c_probe(struct platform_device *dev) return ret; } -static int simtec_i2c_remove(struct platform_device *dev) +static void simtec_i2c_remove(struct platform_device *dev) { struct simtec_i2c_data *pd = platform_get_drvdata(dev); @@ -135,8 +135,6 @@ static int simtec_i2c_remove(struct platform_device *dev) iounmap(pd->reg); release_mem_region(pd->ioarea->start, resource_size(pd->ioarea)); kfree(pd); - - return 0; } /* device driver */ @@ -146,7 +144,7 @@ static struct platform_driver simtec_i2c_driver = { .name = "simtec-i2c", }, .probe = simtec_i2c_probe, - .remove = simtec_i2c_remove, + .remove_new = simtec_i2c_remove, }; module_platform_driver(simtec_i2c_driver); diff --git a/drivers/i2c/busses/i2c-st.c b/drivers/i2c/busses/i2c-st.c index f823913b75a6..25c3521cae0e 100644 --- a/drivers/i2c/busses/i2c-st.c +++ b/drivers/i2c/busses/i2c-st.c @@ -876,13 +876,11 @@ static int st_i2c_probe(struct platform_device *pdev) return 0; } -static int st_i2c_remove(struct platform_device *pdev) +static void st_i2c_remove(struct platform_device *pdev) { struct st_i2c_dev *i2c_dev = platform_get_drvdata(pdev); i2c_del_adapter(&i2c_dev->adap); - - return 0; } static const struct of_device_id st_i2c_match[] = { @@ -899,7 +897,7 @@ static struct platform_driver st_i2c_driver = { .pm = pm_sleep_ptr(&st_i2c_pm), }, .probe = st_i2c_probe, - .remove = st_i2c_remove, + .remove_new = st_i2c_remove, }; module_platform_driver(st_i2c_driver); diff --git a/drivers/i2c/busses/i2c-stm32f4.c b/drivers/i2c/busses/i2c-stm32f4.c index eebce7ecef25..6ad06a5a22b4 100644 --- a/drivers/i2c/busses/i2c-stm32f4.c +++ b/drivers/i2c/busses/i2c-stm32f4.c @@ -861,15 +861,13 @@ clk_free: return ret; } -static int stm32f4_i2c_remove(struct platform_device *pdev) +static void stm32f4_i2c_remove(struct platform_device *pdev) { struct stm32f4_i2c_dev *i2c_dev = platform_get_drvdata(pdev); i2c_del_adapter(&i2c_dev->adap); clk_unprepare(i2c_dev->clk); - - return 0; } static const struct of_device_id stm32f4_i2c_match[] = { @@ -884,7 +882,7 @@ static struct platform_driver stm32f4_i2c_driver = { .of_match_table = stm32f4_i2c_match, }, .probe = stm32f4_i2c_probe, - .remove = stm32f4_i2c_remove, + .remove_new = stm32f4_i2c_remove, }; module_platform_driver(stm32f4_i2c_driver); diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index d1c59d83a65b..e897d9101434 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -2309,7 +2309,7 @@ clk_free: return ret; } -static int stm32f7_i2c_remove(struct platform_device *pdev) +static void stm32f7_i2c_remove(struct platform_device *pdev) { struct stm32f7_i2c_dev *i2c_dev = platform_get_drvdata(pdev); @@ -2341,8 +2341,6 @@ static int stm32f7_i2c_remove(struct platform_device *pdev) stm32f7_i2c_write_fm_plus_bits(i2c_dev, false); clk_disable_unprepare(i2c_dev->clk); - - return 0; } static int __maybe_unused stm32f7_i2c_runtime_suspend(struct device *dev) @@ -2486,7 +2484,7 @@ static struct platform_driver stm32f7_i2c_driver = { .pm = &stm32f7_i2c_pm_ops, }, .probe = stm32f7_i2c_probe, - .remove = stm32f7_i2c_remove, + .remove_new = stm32f7_i2c_remove, }; module_platform_driver(stm32f7_i2c_driver); diff --git a/drivers/i2c/busses/i2c-sun6i-p2wi.c b/drivers/i2c/busses/i2c-sun6i-p2wi.c index 9e3483f507ff..ad8270cdbd3e 100644 --- a/drivers/i2c/busses/i2c-sun6i-p2wi.c +++ b/drivers/i2c/busses/i2c-sun6i-p2wi.c @@ -239,15 +239,9 @@ static int p2wi_probe(struct platform_device *pdev) if (irq < 0) return irq; - p2wi->clk = devm_clk_get(dev, NULL); + p2wi->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(p2wi->clk)) { ret = PTR_ERR(p2wi->clk); - dev_err(dev, "failed to retrieve clk: %d\n", ret); - return ret; - } - - ret = clk_prepare_enable(p2wi->clk); - if (ret) { dev_err(dev, "failed to enable clk: %d\n", ret); return ret; } @@ -256,15 +250,14 @@ static int p2wi_probe(struct platform_device *pdev) p2wi->rstc = devm_reset_control_get_exclusive(dev, NULL); if (IS_ERR(p2wi->rstc)) { - ret = PTR_ERR(p2wi->rstc); dev_err(dev, "failed to retrieve reset controller: %d\n", ret); - goto err_clk_disable; + return PTR_ERR(p2wi->rstc); } ret = reset_control_deassert(p2wi->rstc); if (ret) { dev_err(dev, "failed to deassert reset line: %d\n", ret); - goto err_clk_disable; + return ret; } init_completion(&p2wi->complete); @@ -307,26 +300,20 @@ static int p2wi_probe(struct platform_device *pdev) err_reset_assert: reset_control_assert(p2wi->rstc); -err_clk_disable: - clk_disable_unprepare(p2wi->clk); - return ret; } -static int p2wi_remove(struct platform_device *dev) +static void p2wi_remove(struct platform_device *dev) { struct p2wi *p2wi = platform_get_drvdata(dev); reset_control_assert(p2wi->rstc); - clk_disable_unprepare(p2wi->clk); i2c_del_adapter(&p2wi->adapter); - - return 0; } static struct platform_driver p2wi_driver = { .probe = p2wi_probe, - .remove = p2wi_remove, + .remove_new = p2wi_remove, .driver = { .name = "i2c-sunxi-p2wi", .of_match_table = p2wi_of_match_table, diff --git a/drivers/i2c/busses/i2c-synquacer.c b/drivers/i2c/busses/i2c-synquacer.c index 50d19cf99a03..4cc196ca8f6d 100644 --- a/drivers/i2c/busses/i2c-synquacer.c +++ b/drivers/i2c/busses/i2c-synquacer.c @@ -618,15 +618,13 @@ static int synquacer_i2c_probe(struct platform_device *pdev) return 0; } -static int synquacer_i2c_remove(struct platform_device *pdev) +static void synquacer_i2c_remove(struct platform_device *pdev) { struct synquacer_i2c *i2c = platform_get_drvdata(pdev); i2c_del_adapter(&i2c->adapter); if (!IS_ERR(i2c->pclk)) clk_disable_unprepare(i2c->pclk); - - return 0; }; static const struct of_device_id synquacer_i2c_dt_ids[] __maybe_unused = { @@ -645,7 +643,7 @@ MODULE_DEVICE_TABLE(acpi, synquacer_i2c_acpi_ids); static struct platform_driver synquacer_i2c_driver = { .probe = synquacer_i2c_probe, - .remove = synquacer_i2c_remove, + .remove_new = synquacer_i2c_remove, .driver = { .name = "synquacer_i2c", .of_match_table = of_match_ptr(synquacer_i2c_dt_ids), diff --git a/drivers/i2c/busses/i2c-tegra-bpmp.c b/drivers/i2c/busses/i2c-tegra-bpmp.c index 95139985b2d5..bc3f94561746 100644 --- a/drivers/i2c/busses/i2c-tegra-bpmp.c +++ b/drivers/i2c/busses/i2c-tegra-bpmp.c @@ -316,13 +316,11 @@ static int tegra_bpmp_i2c_probe(struct platform_device *pdev) return i2c_add_adapter(&i2c->adapter); } -static int tegra_bpmp_i2c_remove(struct platform_device *pdev) +static void tegra_bpmp_i2c_remove(struct platform_device *pdev) { struct tegra_bpmp_i2c *i2c = platform_get_drvdata(pdev); i2c_del_adapter(&i2c->adapter); - - return 0; } static const struct of_device_id tegra_bpmp_i2c_of_match[] = { @@ -337,7 +335,7 @@ static struct platform_driver tegra_bpmp_i2c_driver = { .of_match_table = tegra_bpmp_i2c_of_match, }, .probe = tegra_bpmp_i2c_probe, - .remove = tegra_bpmp_i2c_remove, + .remove_new = tegra_bpmp_i2c_remove, }; module_platform_driver(tegra_bpmp_i2c_driver); diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 157066f06a32..bcbbf23aa530 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -249,8 +249,7 @@ struct tegra_i2c_hw_feature { * @msg_read: indicates that the transfer is a read access * @timings: i2c timings information like bus frequency * @multimaster_mode: indicates that I2C controller is in multi-master mode - * @tx_dma_chan: DMA transmit channel - * @rx_dma_chan: DMA receive channel + * @dma_chan: DMA channel * @dma_phys: handle to DMA resources * @dma_buf: pointer to allocated DMA buffer * @dma_buf_size: DMA buffer size @@ -283,8 +282,7 @@ struct tegra_i2c_dev { u8 *msg_buf; struct completion dma_complete; - struct dma_chan *tx_dma_chan; - struct dma_chan *rx_dma_chan; + struct dma_chan *dma_chan; unsigned int dma_buf_size; struct device *dma_dev; dma_addr_t dma_phys; @@ -298,6 +296,9 @@ struct tegra_i2c_dev { bool is_vi; }; +#define IS_DVC(dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && (dev)->is_dvc) +#define IS_VI(dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) && (dev)->is_vi) + static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned int reg) { @@ -315,9 +316,9 @@ static u32 dvc_readl(struct tegra_i2c_dev *i2c_dev, unsigned int reg) */ static u32 tegra_i2c_reg_addr(struct tegra_i2c_dev *i2c_dev, unsigned int reg) { - if (i2c_dev->is_dvc) + if (IS_DVC(i2c_dev)) reg += (reg >= I2C_TX_FIFO) ? 0x10 : 0x40; - else if (i2c_dev->is_vi) + else if (IS_VI(i2c_dev)) reg = 0xc00 + (reg << 2); return reg; @@ -330,7 +331,7 @@ static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned int reg) /* read back register to make sure that register writes completed */ if (reg != I2C_TX_FIFO) readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg)); - else if (i2c_dev->is_vi) + else if (IS_VI(i2c_dev)) readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, I2C_INT_STATUS)); } @@ -393,16 +394,14 @@ static int tegra_i2c_dma_submit(struct tegra_i2c_dev *i2c_dev, size_t len) { struct dma_async_tx_descriptor *dma_desc; enum dma_transfer_direction dir; - struct dma_chan *chan; dev_dbg(i2c_dev->dev, "starting DMA for length: %zu\n", len); reinit_completion(&i2c_dev->dma_complete); dir = i2c_dev->msg_read ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV; - chan = i2c_dev->msg_read ? i2c_dev->rx_dma_chan : i2c_dev->tx_dma_chan; - dma_desc = dmaengine_prep_slave_single(chan, i2c_dev->dma_phys, + dma_desc = dmaengine_prep_slave_single(i2c_dev->dma_chan, i2c_dev->dma_phys, len, dir, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!dma_desc) { @@ -415,7 +414,7 @@ static int tegra_i2c_dma_submit(struct tegra_i2c_dev *i2c_dev, size_t len) dma_desc->callback_param = i2c_dev; dmaengine_submit(dma_desc); - dma_async_issue_pending(chan); + dma_async_issue_pending(i2c_dev->dma_chan); return 0; } @@ -428,25 +427,19 @@ static void tegra_i2c_release_dma(struct tegra_i2c_dev *i2c_dev) i2c_dev->dma_buf = NULL; } - if (i2c_dev->tx_dma_chan) { - dma_release_channel(i2c_dev->tx_dma_chan); - i2c_dev->tx_dma_chan = NULL; - } - - if (i2c_dev->rx_dma_chan) { - dma_release_channel(i2c_dev->rx_dma_chan); - i2c_dev->rx_dma_chan = NULL; + if (i2c_dev->dma_chan) { + dma_release_channel(i2c_dev->dma_chan); + i2c_dev->dma_chan = NULL; } } static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev) { - struct dma_chan *chan; dma_addr_t dma_phys; u32 *dma_buf; int err; - if (i2c_dev->is_vi) + if (IS_VI(i2c_dev)) return 0; if (!i2c_dev->hw->has_apb_dma) { @@ -459,25 +452,18 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev) return 0; } - chan = dma_request_chan(i2c_dev->dev, "rx"); - if (IS_ERR(chan)) { - err = PTR_ERR(chan); - goto err_out; - } - - i2c_dev->rx_dma_chan = chan; - - chan = dma_request_chan(i2c_dev->dev, "tx"); - if (IS_ERR(chan)) { - err = PTR_ERR(chan); + /* + * The same channel will be used for both RX and TX. + * Keeping the name as "tx" for backward compatibility + * with existing devicetrees. + */ + i2c_dev->dma_chan = dma_request_chan(i2c_dev->dev, "tx"); + if (IS_ERR(i2c_dev->dma_chan)) { + err = PTR_ERR(i2c_dev->dma_chan); goto err_out; } - i2c_dev->tx_dma_chan = chan; - - WARN_ON(i2c_dev->tx_dma_chan->device != i2c_dev->rx_dma_chan->device); - i2c_dev->dma_dev = chan->device->dev; - + i2c_dev->dma_dev = i2c_dev->dma_chan->device->dev; i2c_dev->dma_buf_size = i2c_dev->hw->quirks->max_write_len + I2C_PACKET_HEADER_SIZE; @@ -639,7 +625,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) WARN_ON_ONCE(err); - if (i2c_dev->is_dvc) + if (IS_DVC(i2c_dev)) tegra_dvc_init(i2c_dev); val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN | @@ -651,7 +637,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) i2c_writel(i2c_dev, val, I2C_CNFG); i2c_writel(i2c_dev, 0, I2C_INT_MASK); - if (i2c_dev->is_vi) + if (IS_VI(i2c_dev)) tegra_i2c_vi_init(i2c_dev); switch (t->bus_freq_hz) { @@ -703,7 +689,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) return err; } - if (!i2c_dev->is_dvc && !i2c_dev->is_vi) { + if (!IS_DVC(i2c_dev) && !IS_VI(i2c_dev)) { u32 sl_cfg = i2c_readl(i2c_dev, I2C_SL_CNFG); sl_cfg |= I2C_SL_CNFG_NACK | I2C_SL_CNFG_NEWSL; @@ -846,7 +832,7 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev) i2c_dev->msg_buf_remaining = buf_remaining; i2c_dev->msg_buf = buf + words_to_transfer * BYTES_PER_FIFO_WORD; - if (i2c_dev->is_vi) + if (IS_VI(i2c_dev)) i2c_writesl_vi(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer); else i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer); @@ -933,7 +919,7 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) } i2c_writel(i2c_dev, status, I2C_INT_STATUS); - if (i2c_dev->is_dvc) + if (IS_DVC(i2c_dev)) dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); /* @@ -972,15 +958,11 @@ err: i2c_writel(i2c_dev, status, I2C_INT_STATUS); - if (i2c_dev->is_dvc) + if (IS_DVC(i2c_dev)) dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); if (i2c_dev->dma_mode) { - if (i2c_dev->msg_read) - dmaengine_terminate_async(i2c_dev->rx_dma_chan); - else - dmaengine_terminate_async(i2c_dev->tx_dma_chan); - + dmaengine_terminate_async(i2c_dev->dma_chan); complete(&i2c_dev->dma_complete); } @@ -994,7 +976,6 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev, { struct dma_slave_config slv_config = {0}; u32 val, reg, dma_burst, reg_offset; - struct dma_chan *chan; int err; if (i2c_dev->hw->has_mst_fifo) @@ -1011,7 +992,6 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev, dma_burst = 8; if (i2c_dev->msg_read) { - chan = i2c_dev->rx_dma_chan; reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_RX_FIFO); slv_config.src_addr = i2c_dev->base_phys + reg_offset; @@ -1023,7 +1003,6 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev, else val = I2C_FIFO_CONTROL_RX_TRIG(dma_burst); } else { - chan = i2c_dev->tx_dma_chan; reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_TX_FIFO); slv_config.dst_addr = i2c_dev->base_phys + reg_offset; @@ -1037,7 +1016,7 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev, } slv_config.device_fc = true; - err = dmaengine_slave_config(chan, &slv_config); + err = dmaengine_slave_config(i2c_dev->dma_chan, &slv_config); if (err) { dev_err(i2c_dev->dev, "DMA config failed: %d\n", err); dev_err(i2c_dev->dev, "falling back to PIO\n"); @@ -1347,13 +1326,8 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, * performs synchronization after the transfer's termination * and we want to get a completion if transfer succeeded. */ - dmaengine_synchronize(i2c_dev->msg_read ? - i2c_dev->rx_dma_chan : - i2c_dev->tx_dma_chan); - - dmaengine_terminate_sync(i2c_dev->msg_read ? - i2c_dev->rx_dma_chan : - i2c_dev->tx_dma_chan); + dmaengine_synchronize(i2c_dev->dma_chan); + dmaengine_terminate_sync(i2c_dev->dma_chan); if (!time_left && !completion_done(&i2c_dev->dma_complete)) { dev_err(i2c_dev->dev, "DMA transfer timed out\n"); @@ -1654,13 +1628,17 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = { static const struct of_device_id tegra_i2c_of_match[] = { { .compatible = "nvidia,tegra194-i2c", .data = &tegra194_i2c_hw, }, { .compatible = "nvidia,tegra186-i2c", .data = &tegra186_i2c_hw, }, +#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) { .compatible = "nvidia,tegra210-i2c-vi", .data = &tegra210_i2c_hw, }, +#endif { .compatible = "nvidia,tegra210-i2c", .data = &tegra210_i2c_hw, }, { .compatible = "nvidia,tegra124-i2c", .data = &tegra124_i2c_hw, }, { .compatible = "nvidia,tegra114-i2c", .data = &tegra114_i2c_hw, }, { .compatible = "nvidia,tegra30-i2c", .data = &tegra30_i2c_hw, }, { .compatible = "nvidia,tegra20-i2c", .data = &tegra20_i2c_hw, }, +#if IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) { .compatible = "nvidia,tegra20-i2c-dvc", .data = &tegra20_i2c_hw, }, +#endif {}, }; MODULE_DEVICE_TABLE(of, tegra_i2c_of_match); @@ -1675,10 +1653,12 @@ static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev) multi_mode = device_property_read_bool(i2c_dev->dev, "multi-master"); i2c_dev->multimaster_mode = multi_mode; - if (of_device_is_compatible(np, "nvidia,tegra20-i2c-dvc")) + if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && + of_device_is_compatible(np, "nvidia,tegra20-i2c-dvc")) i2c_dev->is_dvc = true; - if (of_device_is_compatible(np, "nvidia,tegra210-i2c-vi")) + if (IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) && + of_device_is_compatible(np, "nvidia,tegra210-i2c-vi")) i2c_dev->is_vi = true; } @@ -1707,7 +1687,7 @@ static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev) if (i2c_dev->hw == &tegra20_i2c_hw || i2c_dev->hw == &tegra30_i2c_hw) i2c_dev->clocks[i2c_dev->nclocks++].id = "fast-clk"; - if (i2c_dev->is_vi) + if (IS_VI(i2c_dev)) i2c_dev->clocks[i2c_dev->nclocks++].id = "slow"; err = devm_clk_bulk_get(i2c_dev->dev, i2c_dev->nclocks, @@ -1825,7 +1805,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) * VI I2C device shouldn't be marked as IRQ-safe because VI I2C won't * be used for atomic transfers. */ - if (!i2c_dev->is_vi) + if (!IS_VI(i2c_dev)) pm_runtime_irq_safe(i2c_dev->dev); pm_runtime_enable(i2c_dev->dev); @@ -1868,7 +1848,7 @@ release_clocks: return err; } -static int tegra_i2c_remove(struct platform_device *pdev) +static void tegra_i2c_remove(struct platform_device *pdev) { struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); @@ -1877,8 +1857,6 @@ static int tegra_i2c_remove(struct platform_device *pdev) tegra_i2c_release_dma(i2c_dev); tegra_i2c_release_clocks(i2c_dev); - - return 0; } static int __maybe_unused tegra_i2c_runtime_resume(struct device *dev) @@ -1899,7 +1877,7 @@ static int __maybe_unused tegra_i2c_runtime_resume(struct device *dev) * power ON/OFF during runtime PM resume/suspend, meaning that * controller needs to be re-initialized after power ON. */ - if (i2c_dev->is_vi) { + if (IS_VI(i2c_dev)) { err = tegra_i2c_init(i2c_dev); if (err) goto disable_clocks; @@ -1987,7 +1965,7 @@ MODULE_DEVICE_TABLE(acpi, tegra_i2c_acpi_match); static struct platform_driver tegra_i2c_driver = { .probe = tegra_i2c_probe, - .remove = tegra_i2c_remove, + .remove_new = tegra_i2c_remove, .driver = { .name = "tegra-i2c", .of_match_table = tegra_i2c_of_match, diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c index 7279ca0eaa2d..d1fa9ff5aeab 100644 --- a/drivers/i2c/busses/i2c-tiny-usb.c +++ b/drivers/i2c/busses/i2c-tiny-usb.c @@ -226,10 +226,8 @@ static int i2c_tiny_usb_probe(struct usb_interface *interface, /* allocate memory for our device state and initialize it */ dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) { - dev_err(&interface->dev, "Out of memory\n"); + if (!dev) goto error; - } dev->usb_dev = usb_get_dev(interface_to_usbdev(interface)); dev->interface = interface; diff --git a/drivers/i2c/busses/i2c-uniphier-f.c b/drivers/i2c/busses/i2c-uniphier-f.c index d7b622891e52..dbc91c7c3788 100644 --- a/drivers/i2c/busses/i2c-uniphier-f.c +++ b/drivers/i2c/busses/i2c-uniphier-f.c @@ -540,21 +540,16 @@ static int uniphier_fi2c_probe(struct platform_device *pdev) return -EINVAL; } - priv->clk = devm_clk_get(dev, NULL); + priv->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(priv->clk)) { - dev_err(dev, "failed to get clock\n"); + dev_err(dev, "failed to enable clock\n"); return PTR_ERR(priv->clk); } - ret = clk_prepare_enable(priv->clk); - if (ret) - return ret; - clk_rate = clk_get_rate(priv->clk); if (!clk_rate) { dev_err(dev, "input clock rate should not be zero\n"); - ret = -EINVAL; - goto disable_clk; + return -EINVAL; } priv->clk_cycle = clk_rate / bus_speed; @@ -575,25 +570,17 @@ static int uniphier_fi2c_probe(struct platform_device *pdev) pdev->name, priv); if (ret) { dev_err(dev, "failed to request irq %d\n", irq); - goto disable_clk; + return ret; } - ret = i2c_add_adapter(&priv->adap); -disable_clk: - if (ret) - clk_disable_unprepare(priv->clk); - - return ret; + return i2c_add_adapter(&priv->adap); } -static int uniphier_fi2c_remove(struct platform_device *pdev) +static void uniphier_fi2c_remove(struct platform_device *pdev) { struct uniphier_fi2c_priv *priv = platform_get_drvdata(pdev); i2c_del_adapter(&priv->adap); - clk_disable_unprepare(priv->clk); - - return 0; } static int __maybe_unused uniphier_fi2c_suspend(struct device *dev) @@ -631,7 +618,7 @@ MODULE_DEVICE_TABLE(of, uniphier_fi2c_match); static struct platform_driver uniphier_fi2c_drv = { .probe = uniphier_fi2c_probe, - .remove = uniphier_fi2c_remove, + .remove_new = uniphier_fi2c_remove, .driver = { .name = "uniphier-fi2c", .of_match_table = uniphier_fi2c_match, diff --git a/drivers/i2c/busses/i2c-uniphier.c b/drivers/i2c/busses/i2c-uniphier.c index e3ebae381f08..854ac25b5862 100644 --- a/drivers/i2c/busses/i2c-uniphier.c +++ b/drivers/i2c/busses/i2c-uniphier.c @@ -335,21 +335,16 @@ static int uniphier_i2c_probe(struct platform_device *pdev) return -EINVAL; } - priv->clk = devm_clk_get(dev, NULL); + priv->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(priv->clk)) { - dev_err(dev, "failed to get clock\n"); + dev_err(dev, "failed to enable clock\n"); return PTR_ERR(priv->clk); } - ret = clk_prepare_enable(priv->clk); - if (ret) - return ret; - clk_rate = clk_get_rate(priv->clk); if (!clk_rate) { dev_err(dev, "input clock rate should not be zero\n"); - ret = -EINVAL; - goto disable_clk; + return -EINVAL; } priv->clk_cycle = clk_rate / bus_speed; @@ -369,25 +364,17 @@ static int uniphier_i2c_probe(struct platform_device *pdev) priv); if (ret) { dev_err(dev, "failed to request irq %d\n", irq); - goto disable_clk; + return ret; } - ret = i2c_add_adapter(&priv->adap); -disable_clk: - if (ret) - clk_disable_unprepare(priv->clk); - - return ret; + return i2c_add_adapter(&priv->adap); } -static int uniphier_i2c_remove(struct platform_device *pdev) +static void uniphier_i2c_remove(struct platform_device *pdev) { struct uniphier_i2c_priv *priv = platform_get_drvdata(pdev); i2c_del_adapter(&priv->adap); - clk_disable_unprepare(priv->clk); - - return 0; } static int __maybe_unused uniphier_i2c_suspend(struct device *dev) @@ -425,7 +412,7 @@ MODULE_DEVICE_TABLE(of, uniphier_i2c_match); static struct platform_driver uniphier_i2c_drv = { .probe = uniphier_i2c_probe, - .remove = uniphier_i2c_remove, + .remove_new = uniphier_i2c_remove, .driver = { .name = "uniphier-i2c", .of_match_table = uniphier_i2c_match, diff --git a/drivers/i2c/busses/i2c-versatile.c b/drivers/i2c/busses/i2c-versatile.c index 1ab419f8fa52..76abfa77e200 100644 --- a/drivers/i2c/busses/i2c-versatile.c +++ b/drivers/i2c/busses/i2c-versatile.c @@ -64,15 +64,13 @@ static const struct i2c_algo_bit_data i2c_versatile_algo = { static int i2c_versatile_probe(struct platform_device *dev) { struct i2c_versatile *i2c; - struct resource *r; int ret; i2c = devm_kzalloc(&dev->dev, sizeof(struct i2c_versatile), GFP_KERNEL); if (!i2c) return -ENOMEM; - r = platform_get_resource(dev, IORESOURCE_MEM, 0); - i2c->base = devm_ioremap_resource(&dev->dev, r); + i2c->base = devm_platform_get_and_ioremap_resource(dev, 0, NULL); if (IS_ERR(i2c->base)) return PTR_ERR(i2c->base); @@ -96,12 +94,11 @@ static int i2c_versatile_probe(struct platform_device *dev) return 0; } -static int i2c_versatile_remove(struct platform_device *dev) +static void i2c_versatile_remove(struct platform_device *dev) { struct i2c_versatile *i2c = platform_get_drvdata(dev); i2c_del_adapter(&i2c->adap); - return 0; } static const struct of_device_id i2c_versatile_match[] = { @@ -112,7 +109,7 @@ MODULE_DEVICE_TABLE(of, i2c_versatile_match); static struct platform_driver i2c_versatile_driver = { .probe = i2c_versatile_probe, - .remove = i2c_versatile_remove, + .remove_new = i2c_versatile_remove, .driver = { .name = "versatile-i2c", .of_match_table = i2c_versatile_match, diff --git a/drivers/i2c/busses/i2c-viperboard.c b/drivers/i2c/busses/i2c-viperboard.c index 8b5322c3bce0..9e153b5b0e8e 100644 --- a/drivers/i2c/busses/i2c-viperboard.c +++ b/drivers/i2c/busses/i2c-viperboard.c @@ -407,20 +407,18 @@ static int vprbrd_i2c_probe(struct platform_device *pdev) return 0; } -static int vprbrd_i2c_remove(struct platform_device *pdev) +static void vprbrd_i2c_remove(struct platform_device *pdev) { struct vprbrd_i2c *vb_i2c = platform_get_drvdata(pdev); i2c_del_adapter(&vb_i2c->i2c); - - return 0; } static struct platform_driver vprbrd_i2c_driver = { .driver.name = "viperboard-i2c", .driver.owner = THIS_MODULE, .probe = vprbrd_i2c_probe, - .remove = vprbrd_i2c_remove, + .remove_new = vprbrd_i2c_remove, }; static int __init vprbrd_i2c_init(void) diff --git a/drivers/i2c/busses/i2c-wmt.c b/drivers/i2c/busses/i2c-wmt.c index 7d4bc8736079..76118abc6e10 100644 --- a/drivers/i2c/busses/i2c-wmt.c +++ b/drivers/i2c/busses/i2c-wmt.c @@ -372,7 +372,6 @@ static int wmt_i2c_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct wmt_i2c_dev *i2c_dev; struct i2c_adapter *adap; - struct resource *res; int err; u32 clk_rate; @@ -380,8 +379,7 @@ static int wmt_i2c_probe(struct platform_device *pdev) if (!i2c_dev) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2c_dev->base = devm_ioremap_resource(&pdev->dev, res); + i2c_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); if (IS_ERR(i2c_dev->base)) return PTR_ERR(i2c_dev->base); @@ -436,7 +434,7 @@ static int wmt_i2c_probe(struct platform_device *pdev) return 0; } -static int wmt_i2c_remove(struct platform_device *pdev) +static void wmt_i2c_remove(struct platform_device *pdev) { struct wmt_i2c_dev *i2c_dev = platform_get_drvdata(pdev); @@ -444,8 +442,6 @@ static int wmt_i2c_remove(struct platform_device *pdev) writew(0, i2c_dev->base + REG_IMR); clk_disable_unprepare(i2c_dev->clk); i2c_del_adapter(&i2c_dev->adapter); - - return 0; } static const struct of_device_id wmt_i2c_dt_ids[] = { @@ -455,7 +451,7 @@ static const struct of_device_id wmt_i2c_dt_ids[] = { static struct platform_driver wmt_i2c_driver = { .probe = wmt_i2c_probe, - .remove = wmt_i2c_remove, + .remove_new = wmt_i2c_remove, .driver = { .name = "wmt-i2c", .of_match_table = wmt_i2c_dt_ids, diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c index 3538d36368a9..fbc1ffbd2fa7 100644 --- a/drivers/i2c/busses/i2c-xgene-slimpro.c +++ b/drivers/i2c/busses/i2c-xgene-slimpro.c @@ -560,7 +560,7 @@ mbox_err: return rc; } -static int xgene_slimpro_i2c_remove(struct platform_device *pdev) +static void xgene_slimpro_i2c_remove(struct platform_device *pdev) { struct slimpro_i2c_dev *ctx = platform_get_drvdata(pdev); @@ -570,8 +570,6 @@ static int xgene_slimpro_i2c_remove(struct platform_device *pdev) mbox_free_channel(ctx->mbox_chan); else pcc_mbox_free_channel(ctx->pcc_chan); - - return 0; } static const struct of_device_id xgene_slimpro_i2c_dt_ids[] = { @@ -591,7 +589,7 @@ MODULE_DEVICE_TABLE(acpi, xgene_slimpro_i2c_acpi_ids); static struct platform_driver xgene_slimpro_i2c_driver = { .probe = xgene_slimpro_i2c_probe, - .remove = xgene_slimpro_i2c_remove, + .remove_new = xgene_slimpro_i2c_remove, .driver = { .name = "xgene-slimpro-i2c", .of_match_table = of_match_ptr(xgene_slimpro_i2c_dt_ids), diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 8a3d9817cb41..f879af4def5e 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -1256,16 +1256,11 @@ static int xiic_i2c_probe(struct platform_device *pdev) mutex_init(&i2c->lock); - i2c->clk = devm_clk_get(&pdev->dev, NULL); + i2c->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(i2c->clk)) return dev_err_probe(&pdev->dev, PTR_ERR(i2c->clk), - "input clock not found.\n"); + "failed to enable input clock.\n"); - ret = clk_prepare_enable(i2c->clk); - if (ret) { - dev_err(&pdev->dev, "Unable to enable clock.\n"); - return ret; - } i2c->dev = &pdev->dev; pm_runtime_set_autosuspend_delay(i2c->dev, XIIC_PM_TIMEOUT); pm_runtime_use_autosuspend(i2c->dev); @@ -1286,7 +1281,7 @@ static int xiic_i2c_probe(struct platform_device *pdev) if (ret < 0) { dev_err(&pdev->dev, "Cannot claim IRQ\n"); - goto err_clk_dis; + goto err_pm_disable; } i2c->singlemaster = @@ -1307,14 +1302,14 @@ static int xiic_i2c_probe(struct platform_device *pdev) ret = xiic_reinit(i2c); if (ret < 0) { dev_err(&pdev->dev, "Cannot xiic_reinit\n"); - goto err_clk_dis; + goto err_pm_disable; } /* add i2c adapter to i2c tree */ ret = i2c_add_adapter(&i2c->adap); if (ret) { xiic_deinit(i2c); - goto err_clk_dis; + goto err_pm_disable; } if (pdata) { @@ -1328,14 +1323,14 @@ static int xiic_i2c_probe(struct platform_device *pdev) return 0; -err_clk_dis: +err_pm_disable: pm_runtime_set_suspended(&pdev->dev); pm_runtime_disable(&pdev->dev); - clk_disable_unprepare(i2c->clk); + return ret; } -static int xiic_i2c_remove(struct platform_device *pdev) +static void xiic_i2c_remove(struct platform_device *pdev) { struct xiic_i2c *i2c = platform_get_drvdata(pdev); int ret; @@ -1352,12 +1347,9 @@ static int xiic_i2c_remove(struct platform_device *pdev) xiic_deinit(i2c); pm_runtime_put_sync(i2c->dev); - clk_disable_unprepare(i2c->clk); pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev); - - return 0; } static int __maybe_unused xiic_i2c_runtime_suspend(struct device *dev) @@ -1390,7 +1382,7 @@ static const struct dev_pm_ops xiic_dev_pm_ops = { static struct platform_driver xiic_i2c_driver = { .probe = xiic_i2c_probe, - .remove = xiic_i2c_remove, + .remove_new = xiic_i2c_remove, .driver = { .name = DRIVER_NAME, .of_match_table = of_match_ptr(xiic_of_match), diff --git a/drivers/i2c/busses/i2c-xlp9xx.c b/drivers/i2c/busses/i2c-xlp9xx.c index 4e3b11c0f732..f59e8c544f36 100644 --- a/drivers/i2c/busses/i2c-xlp9xx.c +++ b/drivers/i2c/busses/i2c-xlp9xx.c @@ -559,7 +559,7 @@ static int xlp9xx_i2c_probe(struct platform_device *pdev) return 0; } -static int xlp9xx_i2c_remove(struct platform_device *pdev) +static void xlp9xx_i2c_remove(struct platform_device *pdev) { struct xlp9xx_i2c_dev *priv; @@ -568,8 +568,6 @@ static int xlp9xx_i2c_remove(struct platform_device *pdev) synchronize_irq(priv->irq); i2c_del_adapter(&priv->adapter); xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, 0); - - return 0; } #ifdef CONFIG_ACPI @@ -583,7 +581,7 @@ MODULE_DEVICE_TABLE(acpi, xlp9xx_i2c_acpi_ids); static struct platform_driver xlp9xx_i2c_driver = { .probe = xlp9xx_i2c_probe, - .remove = xlp9xx_i2c_remove, + .remove_new = xlp9xx_i2c_remove, .driver = { .name = "xlp9xx-i2c", .acpi_match_table = ACPI_PTR(xlp9xx_i2c_acpi_ids), diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index 7b42a18bd05c..83c1db610f54 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -523,14 +523,12 @@ static void scx200_cleanup_iface(struct scx200_acb_iface *iface) kfree(iface); } -static int scx200_remove(struct platform_device *pdev) +static void scx200_remove(struct platform_device *pdev) { struct scx200_acb_iface *iface; iface = platform_get_drvdata(pdev); scx200_cleanup_iface(iface); - - return 0; } static struct platform_driver scx200_pci_driver = { @@ -538,7 +536,7 @@ static struct platform_driver scx200_pci_driver = { .name = "cs5535-smb", }, .probe = scx200_probe, - .remove = scx200_remove, + .remove_new = scx200_remove, }; static const struct pci_device_id scx200_isa[] = { diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index ae3af738b03f..60746652fd52 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -114,6 +114,25 @@ const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id, } EXPORT_SYMBOL_GPL(i2c_match_id); +const void *i2c_get_match_data(const struct i2c_client *client) +{ + struct i2c_driver *driver = to_i2c_driver(client->dev.driver); + const struct i2c_device_id *match; + const void *data; + + data = device_get_match_data(&client->dev); + if (!data) { + match = i2c_match_id(driver->id_table, client); + if (!match) + return NULL; + + data = (const void *)match->driver_data; + } + + return data; +} +EXPORT_SYMBOL(i2c_get_match_data); + static int i2c_device_match(struct device *dev, struct device_driver *drv) { struct i2c_client *client = i2c_verify_client(dev); diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c index 1c78657631f4..24168e9f7df4 100644 --- a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c +++ b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c @@ -174,13 +174,12 @@ static int i2c_arbitrator_probe(struct platform_device *pdev) return ret; } -static int i2c_arbitrator_remove(struct platform_device *pdev) +static void i2c_arbitrator_remove(struct platform_device *pdev) { struct i2c_mux_core *muxc = platform_get_drvdata(pdev); i2c_mux_del_adapters(muxc); i2c_put_adapter(muxc->parent); - return 0; } static const struct of_device_id i2c_arbitrator_of_match[] = { @@ -191,7 +190,7 @@ MODULE_DEVICE_TABLE(of, i2c_arbitrator_of_match); static struct platform_driver i2c_arbitrator_driver = { .probe = i2c_arbitrator_probe, - .remove = i2c_arbitrator_remove, + .remove_new = i2c_arbitrator_remove, .driver = { .name = "i2c-arb-gpio-challenge", .of_match_table = i2c_arbitrator_of_match, diff --git a/drivers/i2c/muxes/i2c-demux-pinctrl.c b/drivers/i2c/muxes/i2c-demux-pinctrl.c index f7a7405d4350..a3a122fae71e 100644 --- a/drivers/i2c/muxes/i2c-demux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-demux-pinctrl.c @@ -282,7 +282,7 @@ err_rollback: return err; } -static int i2c_demux_pinctrl_remove(struct platform_device *pdev) +static void i2c_demux_pinctrl_remove(struct platform_device *pdev) { struct i2c_demux_pinctrl_priv *priv = platform_get_drvdata(pdev); int i; @@ -296,8 +296,6 @@ static int i2c_demux_pinctrl_remove(struct platform_device *pdev) of_node_put(priv->chan[i].parent_np); of_changeset_destroy(&priv->chan[i].chgset); } - - return 0; } static const struct of_device_id i2c_demux_pinctrl_of_match[] = { @@ -312,7 +310,7 @@ static struct platform_driver i2c_demux_pinctrl_driver = { .of_match_table = i2c_demux_pinctrl_of_match, }, .probe = i2c_demux_pinctrl_probe, - .remove = i2c_demux_pinctrl_remove, + .remove_new = i2c_demux_pinctrl_remove, }; module_platform_driver(i2c_demux_pinctrl_driver); diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c index 73a23e117ebe..5d5cbe0130cd 100644 --- a/drivers/i2c/muxes/i2c-mux-gpio.c +++ b/drivers/i2c/muxes/i2c-mux-gpio.c @@ -225,14 +225,12 @@ alloc_failed: return ret; } -static int i2c_mux_gpio_remove(struct platform_device *pdev) +static void i2c_mux_gpio_remove(struct platform_device *pdev) { struct i2c_mux_core *muxc = platform_get_drvdata(pdev); i2c_mux_del_adapters(muxc); i2c_put_adapter(muxc->parent); - - return 0; } static const struct of_device_id i2c_mux_gpio_of_match[] = { @@ -243,7 +241,7 @@ MODULE_DEVICE_TABLE(of, i2c_mux_gpio_of_match); static struct platform_driver i2c_mux_gpio_driver = { .probe = i2c_mux_gpio_probe, - .remove = i2c_mux_gpio_remove, + .remove_new = i2c_mux_gpio_remove, .driver = { .name = "i2c-mux-gpio", .of_match_table = i2c_mux_gpio_of_match, diff --git a/drivers/i2c/muxes/i2c-mux-gpmux.c b/drivers/i2c/muxes/i2c-mux-gpmux.c index 33024acaac02..0405af0e1510 100644 --- a/drivers/i2c/muxes/i2c-mux-gpmux.c +++ b/drivers/i2c/muxes/i2c-mux-gpmux.c @@ -142,19 +142,17 @@ err_parent: return ret; } -static int i2c_mux_remove(struct platform_device *pdev) +static void i2c_mux_remove(struct platform_device *pdev) { struct i2c_mux_core *muxc = platform_get_drvdata(pdev); i2c_mux_del_adapters(muxc); i2c_put_adapter(muxc->parent); - - return 0; } static struct platform_driver i2c_mux_driver = { .probe = i2c_mux_probe, - .remove = i2c_mux_remove, + .remove_new = i2c_mux_remove, .driver = { .name = "i2c-mux-gpmux", .of_match_table = i2c_mux_of_match, diff --git a/drivers/i2c/muxes/i2c-mux-mlxcpld.c b/drivers/i2c/muxes/i2c-mux-mlxcpld.c index 1a879f6a31ef..3dda00f1df78 100644 --- a/drivers/i2c/muxes/i2c-mux-mlxcpld.c +++ b/drivers/i2c/muxes/i2c-mux-mlxcpld.c @@ -170,12 +170,11 @@ virt_reg_failed: return err; } -static int mlxcpld_mux_remove(struct platform_device *pdev) +static void mlxcpld_mux_remove(struct platform_device *pdev) { struct i2c_mux_core *muxc = platform_get_drvdata(pdev); i2c_mux_del_adapters(muxc); - return 0; } static struct platform_driver mlxcpld_mux_driver = { @@ -183,7 +182,7 @@ static struct platform_driver mlxcpld_mux_driver = { .name = "i2c-mux-mlxcpld", }, .probe = mlxcpld_mux_probe, - .remove = mlxcpld_mux_remove, + .remove_new = mlxcpld_mux_remove, }; module_platform_driver(mlxcpld_mux_driver); diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c index d5ad904756fd..18236b9fa14a 100644 --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c @@ -166,14 +166,12 @@ err_put_parent: return ret; } -static int i2c_mux_pinctrl_remove(struct platform_device *pdev) +static void i2c_mux_pinctrl_remove(struct platform_device *pdev) { struct i2c_mux_core *muxc = platform_get_drvdata(pdev); i2c_mux_del_adapters(muxc); i2c_put_adapter(muxc->parent); - - return 0; } static const struct of_device_id i2c_mux_pinctrl_of_match[] = { @@ -188,7 +186,7 @@ static struct platform_driver i2c_mux_pinctrl_driver = { .of_match_table = i2c_mux_pinctrl_of_match, }, .probe = i2c_mux_pinctrl_probe, - .remove = i2c_mux_pinctrl_remove, + .remove_new = i2c_mux_pinctrl_remove, }; module_platform_driver(i2c_mux_pinctrl_driver); diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c index 30a6de1694e0..9efc1ed01577 100644 --- a/drivers/i2c/muxes/i2c-mux-reg.c +++ b/drivers/i2c/muxes/i2c-mux-reg.c @@ -233,14 +233,12 @@ err_put_parent: return ret; } -static int i2c_mux_reg_remove(struct platform_device *pdev) +static void i2c_mux_reg_remove(struct platform_device *pdev) { struct i2c_mux_core *muxc = platform_get_drvdata(pdev); i2c_mux_del_adapters(muxc); i2c_put_adapter(muxc->parent); - - return 0; } static const struct of_device_id i2c_mux_reg_of_match[] = { @@ -251,7 +249,7 @@ MODULE_DEVICE_TABLE(of, i2c_mux_reg_of_match); static struct platform_driver i2c_mux_reg_driver = { .probe = i2c_mux_reg_probe, - .remove = i2c_mux_reg_remove, + .remove_new = i2c_mux_reg_remove, .driver = { .name = "i2c-mux-reg", .of_match_table = of_match_ptr(i2c_mux_reg_of_match), diff --git a/drivers/irqchip/irq-riscv-intc.c b/drivers/irqchip/irq-riscv-intc.c index f229e3e66387..4adeee1bc391 100644 --- a/drivers/irqchip/irq-riscv-intc.c +++ b/drivers/irqchip/irq-riscv-intc.c @@ -6,6 +6,7 @@ */ #define pr_fmt(fmt) "riscv-intc: " fmt +#include <linux/acpi.h> #include <linux/atomic.h> #include <linux/bits.h> #include <linux/cpu.h> @@ -112,6 +113,30 @@ static struct fwnode_handle *riscv_intc_hwnode(void) return intc_domain->fwnode; } +static int __init riscv_intc_init_common(struct fwnode_handle *fn) +{ + int rc; + + intc_domain = irq_domain_create_linear(fn, BITS_PER_LONG, + &riscv_intc_domain_ops, NULL); + if (!intc_domain) { + pr_err("unable to add IRQ domain\n"); + return -ENXIO; + } + + rc = set_handle_irq(&riscv_intc_irq); + if (rc) { + pr_err("failed to set irq handler\n"); + return rc; + } + + riscv_set_intc_hwnode_fn(riscv_intc_hwnode); + + pr_info("%d local interrupts mapped\n", BITS_PER_LONG); + + return 0; +} + static int __init riscv_intc_init(struct device_node *node, struct device_node *parent) { @@ -133,24 +158,39 @@ static int __init riscv_intc_init(struct device_node *node, if (riscv_hartid_to_cpuid(hartid) != smp_processor_id()) return 0; - intc_domain = irq_domain_add_linear(node, BITS_PER_LONG, - &riscv_intc_domain_ops, NULL); - if (!intc_domain) { - pr_err("unable to add IRQ domain\n"); - return -ENXIO; - } + return riscv_intc_init_common(of_node_to_fwnode(node)); +} - rc = set_handle_irq(&riscv_intc_irq); - if (rc) { - pr_err("failed to set irq handler\n"); - return rc; - } +IRQCHIP_DECLARE(riscv, "riscv,cpu-intc", riscv_intc_init); - riscv_set_intc_hwnode_fn(riscv_intc_hwnode); +#ifdef CONFIG_ACPI - pr_info("%d local interrupts mapped\n", BITS_PER_LONG); +static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header, + const unsigned long end) +{ + struct fwnode_handle *fn; + struct acpi_madt_rintc *rintc; - return 0; + rintc = (struct acpi_madt_rintc *)header; + + /* + * The ACPI MADT will have one INTC for each CPU (or HART) + * so riscv_intc_acpi_init() function will be called once + * for each INTC. We only do INTC initialization + * for the INTC belonging to the boot CPU (or boot HART). + */ + if (riscv_hartid_to_cpuid(rintc->hart_id) != smp_processor_id()) + return 0; + + fn = irq_domain_alloc_named_fwnode("RISCV-INTC"); + if (!fn) { + pr_err("unable to allocate INTC FW node\n"); + return -ENOMEM; + } + + return riscv_intc_init_common(fn); } -IRQCHIP_DECLARE(riscv, "riscv,cpu-intc", riscv_intc_init); +IRQCHIP_ACPI_DECLARE(riscv_intc, ACPI_MADT_TYPE_RINTC, NULL, + ACPI_MADT_RINTC_VERSION_V1, riscv_intc_acpi_init); +#endif diff --git a/drivers/macintosh/ams/ams-i2c.c b/drivers/macintosh/ams/ams-i2c.c index a4a1035eb412..f9bfe84b1c73 100644 --- a/drivers/macintosh/ams/ams-i2c.c +++ b/drivers/macintosh/ams/ams-i2c.c @@ -69,7 +69,7 @@ static struct i2c_driver ams_i2c_driver = { .driver = { .name = "ams", }, - .probe_new = ams_i2c_probe, + .probe = ams_i2c_probe, .remove = ams_i2c_remove, .id_table = ams_id, }; diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index b495bfa77896..5183a00529f5 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -33,7 +33,8 @@ #include <linux/delay.h> #include <linux/poll.h> #include <linux/mutex.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/of_address.h> #include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/slab.h> @@ -470,7 +471,7 @@ EXPORT_SYMBOL(smu_present); int __init smu_init (void) { struct device_node *np; - const u32 *data; + u64 data; int ret = 0; np = of_find_node_by_type(NULL, "smu"); @@ -514,8 +515,7 @@ int __init smu_init (void) ret = -ENXIO; goto fail_bootmem; } - data = of_get_property(smu->db_node, "reg", NULL); - if (data == NULL) { + if (of_property_read_reg(smu->db_node, 0, &data, NULL)) { printk(KERN_ERR "SMU: Can't find doorbell GPIO address !\n"); ret = -ENXIO; goto fail_db_node; @@ -525,7 +525,7 @@ int __init smu_init (void) * and ack. GPIOs are at 0x50, best would be to find that out * in the device-tree though. */ - smu->doorbell = *data; + smu->doorbell = data; if (smu->doorbell < 0x50) smu->doorbell += 0x50; @@ -534,13 +534,12 @@ int __init smu_init (void) smu->msg_node = of_find_node_by_name(NULL, "smu-interrupt"); if (smu->msg_node == NULL) break; - data = of_get_property(smu->msg_node, "reg", NULL); - if (data == NULL) { + if (of_property_read_reg(smu->msg_node, 0, &data, NULL)) { of_node_put(smu->msg_node); smu->msg_node = NULL; break; } - smu->msg = *data; + smu->msg = data; if (smu->msg < 0x50) smu->msg += 0x50; } while(0); diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index 384b87d661e1..53ea56b286f9 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c @@ -598,7 +598,7 @@ static struct i2c_driver thermostat_driver = { .driver = { .name = "therm_adt746x", }, - .probe_new = probe_thermostat, + .probe = probe_thermostat, .remove = remove_thermostat, .id_table = therm_adt746x_id, }; diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c index 22b15efcc025..18a982454321 100644 --- a/drivers/macintosh/therm_windtunnel.c +++ b/drivers/macintosh/therm_windtunnel.c @@ -442,7 +442,7 @@ static struct i2c_driver g4fan_driver = { .driver = { .name = "therm_windtunnel", }, - .probe_new = do_probe, + .probe = do_probe, .remove = do_remove, .id_table = therm_windtunnel_id, }; diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c index 5071289063f0..f8dd1e831530 100644 --- a/drivers/macintosh/via-cuda.c +++ b/drivers/macintosh/via-cuda.c @@ -235,8 +235,7 @@ int __init find_via_cuda(void) int __init find_via_cuda(void) { struct adb_request req; - phys_addr_t taddr; - const u32 *reg; + struct resource res; int err; if (vias) @@ -245,17 +244,12 @@ int __init find_via_cuda(void) if (!vias) return 0; - reg = of_get_property(vias, "reg", NULL); - if (reg == NULL) { - printk(KERN_ERR "via-cuda: No \"reg\" property !\n"); - goto fail; - } - taddr = of_translate_address(vias, reg); - if (taddr == 0) { - printk(KERN_ERR "via-cuda: Can't translate address !\n"); + err = of_address_to_resource(vias, 0, &res); + if (err) { + printk(KERN_ERR "via-cuda: Error getting \"reg\" property !\n"); goto fail; } - via = ioremap(taddr, 0x2000); + via = ioremap(res.start, 0x2000); if (via == NULL) { printk(KERN_ERR "via-cuda: Can't map address !\n"); goto fail; diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index e0cb8daf4f08..9d5703b60937 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -286,8 +286,9 @@ static char *pbook_type[] = { int __init find_via_pmu(void) { #ifdef CONFIG_PPC_PMAC + int err; u64 taddr; - const u32 *reg; + struct resource res; if (pmu_state != uninitialized) return 1; @@ -295,16 +296,12 @@ int __init find_via_pmu(void) if (vias == NULL) return 0; - reg = of_get_property(vias, "reg", NULL); - if (reg == NULL) { - printk(KERN_ERR "via-pmu: No \"reg\" property !\n"); - goto fail; - } - taddr = of_translate_address(vias, reg); - if (taddr == OF_BAD_ADDR) { - printk(KERN_ERR "via-pmu: Can't translate address !\n"); + err = of_address_to_resource(vias, 0, &res); + if (err) { + printk(KERN_ERR "via-pmu: Error getting \"reg\" property !\n"); goto fail; } + taddr = res.start; pmu_has_adb = 1; @@ -324,7 +321,6 @@ int __init find_via_pmu(void) || of_device_is_compatible(vias->parent, "K2-Keylargo")) { struct device_node *gpiop; struct device_node *adbp; - u64 gaddr = OF_BAD_ADDR; pmu_kind = PMU_KEYLARGO_BASED; adbp = of_find_node_by_type(NULL, "adb"); @@ -338,11 +334,8 @@ int __init find_via_pmu(void) gpiop = of_find_node_by_name(NULL, "gpio"); if (gpiop) { - reg = of_get_property(gpiop, "reg", NULL); - if (reg) - gaddr = of_translate_address(gpiop, reg); - if (gaddr != OF_BAD_ADDR) - gpio_reg = ioremap(gaddr, 0x10); + if (!of_address_to_resource(gpiop, 0, &res)) + gpio_reg = ioremap(res.start, 0x10); of_node_put(gpiop); } if (gpio_reg == NULL) { diff --git a/drivers/macintosh/windfarm_ad7417_sensor.c b/drivers/macintosh/windfarm_ad7417_sensor.c index 33b4723d235e..49ce37fde930 100644 --- a/drivers/macintosh/windfarm_ad7417_sensor.c +++ b/drivers/macintosh/windfarm_ad7417_sensor.c @@ -320,7 +320,7 @@ static struct i2c_driver wf_ad7417_driver = { .name = "wf_ad7417", .of_match_table = wf_ad7417_of_id, }, - .probe_new = wf_ad7417_probe, + .probe = wf_ad7417_probe, .remove = wf_ad7417_remove, .id_table = wf_ad7417_id, }; diff --git a/drivers/macintosh/windfarm_fcu_controls.c b/drivers/macintosh/windfarm_fcu_controls.c index e027d889d7e8..603ef6c600ba 100644 --- a/drivers/macintosh/windfarm_fcu_controls.c +++ b/drivers/macintosh/windfarm_fcu_controls.c @@ -589,7 +589,7 @@ static struct i2c_driver wf_fcu_driver = { .name = "wf_fcu", .of_match_table = wf_fcu_of_id, }, - .probe_new = wf_fcu_probe, + .probe = wf_fcu_probe, .remove = wf_fcu_remove, .id_table = wf_fcu_id, }; diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c index 9c6febce2376..48dbdb2bda15 100644 --- a/drivers/macintosh/windfarm_lm75_sensor.c +++ b/drivers/macintosh/windfarm_lm75_sensor.c @@ -177,7 +177,7 @@ static struct i2c_driver wf_lm75_driver = { .name = "wf_lm75", .of_match_table = wf_lm75_of_id, }, - .probe_new = wf_lm75_probe, + .probe = wf_lm75_probe, .remove = wf_lm75_remove, .id_table = wf_lm75_id, }; diff --git a/drivers/macintosh/windfarm_lm87_sensor.c b/drivers/macintosh/windfarm_lm87_sensor.c index f37a32c2070c..975361c23a93 100644 --- a/drivers/macintosh/windfarm_lm87_sensor.c +++ b/drivers/macintosh/windfarm_lm87_sensor.c @@ -172,7 +172,7 @@ static struct i2c_driver wf_lm87_driver = { .name = "wf_lm87", .of_match_table = wf_lm87_of_id, }, - .probe_new = wf_lm87_probe, + .probe = wf_lm87_probe, .remove = wf_lm87_remove, .id_table = wf_lm87_id, }; diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c index 6c5ab657b6b3..02856d1f0313 100644 --- a/drivers/macintosh/windfarm_max6690_sensor.c +++ b/drivers/macintosh/windfarm_max6690_sensor.c @@ -128,7 +128,7 @@ static struct i2c_driver wf_max6690_driver = { .name = "wf_max6690", .of_match_table = wf_max6690_of_id, }, - .probe_new = wf_max6690_probe, + .probe = wf_max6690_probe, .remove = wf_max6690_remove, .id_table = wf_max6690_id, }; diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c index 089f2743a070..50baa062c9df 100644 --- a/drivers/macintosh/windfarm_smu_sat.c +++ b/drivers/macintosh/windfarm_smu_sat.c @@ -349,7 +349,7 @@ static struct i2c_driver wf_sat_driver = { .name = "wf_smu_sat", .of_match_table = wf_sat_of_id, }, - .probe_new = wf_sat_probe, + .probe = wf_sat_probe, .remove = wf_sat_remove, .id_table = wf_sat_id, }; diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index eea977662e81..bc309e41d074 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c @@ -1157,23 +1157,6 @@ static void *alloc_buffer_data(struct dm_bufio_client *c, gfp_t gfp_mask, *data_mode = DATA_MODE_VMALLOC; - /* - * __vmalloc allocates the data pages and auxiliary structures with - * gfp_flags that were specified, but pagetables are always allocated - * with GFP_KERNEL, no matter what was specified as gfp_mask. - * - * Consequently, we must set per-process flag PF_MEMALLOC_NOIO so that - * all allocations done by this process (including pagetables) are done - * as if GFP_NOIO was specified. - */ - if (gfp_mask & __GFP_NORETRY) { - unsigned int noio_flag = memalloc_noio_save(); - void *ptr = __vmalloc(c->block_size, gfp_mask); - - memalloc_noio_restore(noio_flag); - return ptr; - } - return __vmalloc(c->block_size, gfp_mask); } @@ -2592,6 +2575,13 @@ void dm_bufio_client_destroy(struct dm_bufio_client *c) } EXPORT_SYMBOL_GPL(dm_bufio_client_destroy); +void dm_bufio_client_reset(struct dm_bufio_client *c) +{ + drop_buffers(c); + flush_work(&c->shrink_work); +} +EXPORT_SYMBOL_GPL(dm_bufio_client_reset); + void dm_bufio_set_sector_offset(struct dm_bufio_client *c, sector_t start) { c->start = start; diff --git a/drivers/md/dm-core.h b/drivers/md/dm-core.h index ce913ad91a52..0d93661f88d3 100644 --- a/drivers/md/dm-core.h +++ b/drivers/md/dm-core.h @@ -306,7 +306,8 @@ struct dm_io { */ enum { DM_IO_ACCOUNTED, - DM_IO_WAS_SPLIT + DM_IO_WAS_SPLIT, + DM_IO_BLK_STAT }; static inline bool dm_io_flagged(struct dm_io *io, unsigned int bit) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 15424bfea7ee..1dc6227d353e 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -31,10 +31,10 @@ #include <asm/unaligned.h> #include <crypto/hash.h> #include <crypto/md5.h> -#include <crypto/algapi.h> #include <crypto/skcipher.h> #include <crypto/aead.h> #include <crypto/authenc.h> +#include <crypto/utils.h> #include <linux/rtnetlink.h> /* for struct rtattr and RTA macros only */ #include <linux/key-type.h> #include <keys/user-type.h> @@ -745,16 +745,23 @@ static int crypt_iv_eboiv_ctr(struct crypt_config *cc, struct dm_target *ti, static int crypt_iv_eboiv_gen(struct crypt_config *cc, u8 *iv, struct dm_crypt_request *dmreq) { - u8 buf[MAX_CIPHER_BLOCKSIZE] __aligned(__alignof__(__le64)); + struct crypto_skcipher *tfm = any_tfm(cc); struct skcipher_request *req; struct scatterlist src, dst; DECLARE_CRYPTO_WAIT(wait); + unsigned int reqsize; int err; + u8 *buf; - req = skcipher_request_alloc(any_tfm(cc), GFP_NOIO); + reqsize = ALIGN(crypto_skcipher_reqsize(tfm), __alignof__(__le64)); + + req = kmalloc(reqsize + cc->iv_size, GFP_NOIO); if (!req) return -ENOMEM; + skcipher_request_set_tfm(req, tfm); + + buf = (u8 *)req + reqsize; memset(buf, 0, cc->iv_size); *(__le64 *)buf = cpu_to_le64(dmreq->iv_sector * cc->sector_size); @@ -763,7 +770,7 @@ static int crypt_iv_eboiv_gen(struct crypt_config *cc, u8 *iv, skcipher_request_set_crypt(req, &src, &dst, cc->iv_size, buf); skcipher_request_set_callback(req, 0, crypto_req_done, &wait); err = crypto_wait_req(crypto_skcipher_encrypt(req), &wait); - skcipher_request_free(req); + kfree_sensitive(req); return err; } @@ -1661,6 +1668,9 @@ static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone); * In order to not degrade performance with excessive locking, we try * non-blocking allocations without a mutex first but on failure we fallback * to blocking allocations with a mutex. + * + * In order to reduce allocation overhead, we try to allocate compound pages in + * the first pass. If they are not available, we fall back to the mempool. */ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned int size) { @@ -1668,8 +1678,8 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned int size) struct bio *clone; unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; gfp_t gfp_mask = GFP_NOWAIT | __GFP_HIGHMEM; - unsigned int i, len, remaining_size; - struct page *page; + unsigned int remaining_size; + unsigned int order = MAX_ORDER - 1; retry: if (unlikely(gfp_mask & __GFP_DIRECT_RECLAIM)) @@ -1682,19 +1692,34 @@ retry: remaining_size = size; - for (i = 0; i < nr_iovecs; i++) { - page = mempool_alloc(&cc->page_pool, gfp_mask); - if (!page) { + while (remaining_size) { + struct page *pages; + unsigned size_to_add; + unsigned remaining_order = __fls((remaining_size + PAGE_SIZE - 1) >> PAGE_SHIFT); + order = min(order, remaining_order); + + while (order > 0) { + pages = alloc_pages(gfp_mask + | __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN | __GFP_COMP, + order); + if (likely(pages != NULL)) + goto have_pages; + order--; + } + + pages = mempool_alloc(&cc->page_pool, gfp_mask); + if (!pages) { crypt_free_buffer_pages(cc, clone); bio_put(clone); gfp_mask |= __GFP_DIRECT_RECLAIM; + order = 0; goto retry; } - len = (remaining_size > PAGE_SIZE) ? PAGE_SIZE : remaining_size; - - __bio_add_page(clone, page, len, 0); - remaining_size -= len; +have_pages: + size_to_add = min((unsigned)PAGE_SIZE << order, remaining_size); + __bio_add_page(clone, pages, size_to_add, 0); + remaining_size -= size_to_add; } /* Allocate space for integrity tags */ @@ -1712,12 +1737,15 @@ retry: static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone) { - struct bio_vec *bv; - struct bvec_iter_all iter_all; + struct folio_iter fi; - bio_for_each_segment_all(bv, clone, iter_all) { - BUG_ON(!bv->bv_page); - mempool_free(bv->bv_page, &cc->page_pool); + if (clone->bi_vcnt > 0) { /* bio_for_each_folio_all crashes with an empty bio */ + bio_for_each_folio_all(fi, clone) { + if (folio_test_large(fi.folio)) + folio_put(fi.folio); + else + mempool_free(&fi.folio->page, &cc->page_pool); + } } } @@ -2887,7 +2915,7 @@ static int crypt_ctr_cipher_new(struct dm_target *ti, char *cipher_in, char *key ret = crypt_ctr_auth_cipher(cc, cipher_api); if (ret < 0) { ti->error = "Invalid AEAD cipher spec"; - return -ENOMEM; + return ret; } } diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c index bd80bcafbe50..120153e44ae0 100644 --- a/drivers/md/dm-flakey.c +++ b/drivers/md/dm-flakey.c @@ -16,6 +16,8 @@ #define DM_MSG_PREFIX "flakey" +#define PROBABILITY_BASE 1000000000 + #define all_corrupt_bio_flags_match(bio, fc) \ (((bio)->bi_opf & (fc)->corrupt_bio_flags) == (fc)->corrupt_bio_flags) @@ -34,6 +36,8 @@ struct flakey_c { unsigned int corrupt_bio_rw; unsigned int corrupt_bio_value; blk_opf_t corrupt_bio_flags; + unsigned int random_read_corrupt; + unsigned int random_write_corrupt; }; enum feature_flag_bits { @@ -54,10 +58,11 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc, const char *arg_name; static const struct dm_arg _args[] = { - {0, 7, "Invalid number of feature args"}, + {0, 11, "Invalid number of feature args"}, {1, UINT_MAX, "Invalid corrupt bio byte"}, {0, 255, "Invalid corrupt value to write into bio byte (0-255)"}, {0, UINT_MAX, "Invalid corrupt bio flags mask"}, + {0, PROBABILITY_BASE, "Invalid random corrupt argument"}, }; /* No feature arguments supplied. */ @@ -170,6 +175,32 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc, continue; } + if (!strcasecmp(arg_name, "random_read_corrupt")) { + if (!argc) { + ti->error = "Feature random_read_corrupt requires a parameter"; + return -EINVAL; + } + r = dm_read_arg(_args + 4, as, &fc->random_read_corrupt, &ti->error); + if (r) + return r; + argc--; + + continue; + } + + if (!strcasecmp(arg_name, "random_write_corrupt")) { + if (!argc) { + ti->error = "Feature random_write_corrupt requires a parameter"; + return -EINVAL; + } + r = dm_read_arg(_args + 4, as, &fc->random_write_corrupt, &ti->error); + if (r) + return r; + argc--; + + continue; + } + ti->error = "Unrecognised flakey feature requested"; return -EINVAL; } @@ -184,7 +215,8 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc, } if (!fc->corrupt_bio_byte && !test_bit(ERROR_READS, &fc->flags) && - !test_bit(DROP_WRITES, &fc->flags) && !test_bit(ERROR_WRITES, &fc->flags)) { + !test_bit(DROP_WRITES, &fc->flags) && !test_bit(ERROR_WRITES, &fc->flags) && + !fc->random_read_corrupt && !fc->random_write_corrupt) { set_bit(ERROR_WRITES, &fc->flags); set_bit(ERROR_READS, &fc->flags); } @@ -306,40 +338,143 @@ static void flakey_map_bio(struct dm_target *ti, struct bio *bio) bio->bi_iter.bi_sector = flakey_map_sector(ti, bio->bi_iter.bi_sector); } -static void corrupt_bio_data(struct bio *bio, struct flakey_c *fc) +static void corrupt_bio_common(struct bio *bio, unsigned int corrupt_bio_byte, + unsigned char corrupt_bio_value) { - unsigned int corrupt_bio_byte = fc->corrupt_bio_byte - 1; - struct bvec_iter iter; struct bio_vec bvec; - if (!bio_has_data(bio)) - return; - /* * Overwrite the Nth byte of the bio's data, on whichever page * it falls. */ bio_for_each_segment(bvec, bio, iter) { if (bio_iter_len(bio, iter) > corrupt_bio_byte) { - char *segment; - struct page *page = bio_iter_page(bio, iter); - if (unlikely(page == ZERO_PAGE(0))) - break; - segment = bvec_kmap_local(&bvec); - segment[corrupt_bio_byte] = fc->corrupt_bio_value; + unsigned char *segment = bvec_kmap_local(&bvec); + segment[corrupt_bio_byte] = corrupt_bio_value; kunmap_local(segment); DMDEBUG("Corrupting data bio=%p by writing %u to byte %u " "(rw=%c bi_opf=%u bi_sector=%llu size=%u)\n", - bio, fc->corrupt_bio_value, fc->corrupt_bio_byte, + bio, corrupt_bio_value, corrupt_bio_byte, (bio_data_dir(bio) == WRITE) ? 'w' : 'r', bio->bi_opf, - (unsigned long long)bio->bi_iter.bi_sector, bio->bi_iter.bi_size); + (unsigned long long)bio->bi_iter.bi_sector, + bio->bi_iter.bi_size); break; } corrupt_bio_byte -= bio_iter_len(bio, iter); } } +static void corrupt_bio_data(struct bio *bio, struct flakey_c *fc) +{ + unsigned int corrupt_bio_byte = fc->corrupt_bio_byte - 1; + + if (!bio_has_data(bio)) + return; + + corrupt_bio_common(bio, corrupt_bio_byte, fc->corrupt_bio_value); +} + +static void corrupt_bio_random(struct bio *bio) +{ + unsigned int corrupt_byte; + unsigned char corrupt_value; + + if (!bio_has_data(bio)) + return; + + corrupt_byte = get_random_u32() % bio->bi_iter.bi_size; + corrupt_value = get_random_u8(); + + corrupt_bio_common(bio, corrupt_byte, corrupt_value); +} + +static void clone_free(struct bio *clone) +{ + struct folio_iter fi; + + if (clone->bi_vcnt > 0) { /* bio_for_each_folio_all crashes with an empty bio */ + bio_for_each_folio_all(fi, clone) + folio_put(fi.folio); + } + + bio_uninit(clone); + kfree(clone); +} + +static void clone_endio(struct bio *clone) +{ + struct bio *bio = clone->bi_private; + bio->bi_status = clone->bi_status; + clone_free(clone); + bio_endio(bio); +} + +static struct bio *clone_bio(struct dm_target *ti, struct flakey_c *fc, struct bio *bio) +{ + struct bio *clone; + unsigned size, remaining_size, nr_iovecs, order; + struct bvec_iter iter = bio->bi_iter; + + if (unlikely(bio->bi_iter.bi_size > UIO_MAXIOV << PAGE_SHIFT)) + dm_accept_partial_bio(bio, UIO_MAXIOV << PAGE_SHIFT >> SECTOR_SHIFT); + + size = bio->bi_iter.bi_size; + nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; + + clone = bio_kmalloc(nr_iovecs, GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN); + if (!clone) + return NULL; + + bio_init(clone, fc->dev->bdev, bio->bi_inline_vecs, nr_iovecs, bio->bi_opf); + + clone->bi_iter.bi_sector = flakey_map_sector(ti, bio->bi_iter.bi_sector); + clone->bi_private = bio; + clone->bi_end_io = clone_endio; + + remaining_size = size; + + order = MAX_ORDER - 1; + while (remaining_size) { + struct page *pages; + unsigned size_to_add, to_copy; + unsigned char *virt; + unsigned remaining_order = __fls((remaining_size + PAGE_SIZE - 1) >> PAGE_SHIFT); + order = min(order, remaining_order); + +retry_alloc_pages: + pages = alloc_pages(GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN | __GFP_COMP, order); + if (unlikely(!pages)) { + if (order) { + order--; + goto retry_alloc_pages; + } + clone_free(clone); + return NULL; + } + size_to_add = min((unsigned)PAGE_SIZE << order, remaining_size); + + virt = page_to_virt(pages); + to_copy = size_to_add; + do { + struct bio_vec bvec = bvec_iter_bvec(bio->bi_io_vec, iter); + unsigned this_step = min(bvec.bv_len, to_copy); + void *map = bvec_kmap_local(&bvec); + memcpy(virt, map, this_step); + kunmap_local(map); + + bvec_iter_advance(bio->bi_io_vec, &iter, this_step); + to_copy -= this_step; + virt += this_step; + } while (to_copy); + + __bio_add_page(clone, pages, size_to_add, 0); + remaining_size -= size_to_add; + } + + return clone; +} + static int flakey_map(struct dm_target *ti, struct bio *bio) { struct flakey_c *fc = ti->private; @@ -354,6 +489,7 @@ static int flakey_map(struct dm_target *ti, struct bio *bio) /* Are we alive ? */ elapsed = (jiffies - fc->start_time) / HZ; if (elapsed % (fc->up_interval + fc->down_interval) >= fc->up_interval) { + bool corrupt_fixed, corrupt_random; /* * Flag this bio as submitted while down. */ @@ -383,12 +519,28 @@ static int flakey_map(struct dm_target *ti, struct bio *bio) /* * Corrupt matching writes. */ - if (fc->corrupt_bio_byte) { - if (fc->corrupt_bio_rw == WRITE) { - if (all_corrupt_bio_flags_match(bio, fc)) - corrupt_bio_data(bio, fc); + corrupt_fixed = false; + corrupt_random = false; + if (fc->corrupt_bio_byte && fc->corrupt_bio_rw == WRITE) { + if (all_corrupt_bio_flags_match(bio, fc)) + corrupt_fixed = true; + } + if (fc->random_write_corrupt) { + u64 rnd = get_random_u64(); + u32 rem = do_div(rnd, PROBABILITY_BASE); + if (rem < fc->random_write_corrupt) + corrupt_random = true; + } + if (corrupt_fixed || corrupt_random) { + struct bio *clone = clone_bio(ti, fc, bio); + if (clone) { + if (corrupt_fixed) + corrupt_bio_data(clone, fc); + if (corrupt_random) + corrupt_bio_random(clone); + submit_bio(clone); + return DM_MAPIO_SUBMITTED; } - goto map_bio; } } @@ -417,6 +569,12 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio, corrupt_bio_data(bio, fc); } } + if (fc->random_read_corrupt) { + u64 rnd = get_random_u64(); + u32 rem = do_div(rnd, PROBABILITY_BASE); + if (rem < fc->random_read_corrupt) + corrupt_bio_random(bio); + } if (test_bit(ERROR_READS, &fc->flags)) { /* * Error read during the down_interval if drop_writes @@ -449,7 +607,10 @@ static void flakey_status(struct dm_target *ti, status_type_t type, error_reads = test_bit(ERROR_READS, &fc->flags); drop_writes = test_bit(DROP_WRITES, &fc->flags); error_writes = test_bit(ERROR_WRITES, &fc->flags); - DMEMIT(" %u", error_reads + drop_writes + error_writes + (fc->corrupt_bio_byte > 0) * 5); + DMEMIT(" %u", error_reads + drop_writes + error_writes + + (fc->corrupt_bio_byte > 0) * 5 + + (fc->random_read_corrupt > 0) * 2 + + (fc->random_write_corrupt > 0) * 2); if (error_reads) DMEMIT(" error_reads"); @@ -464,6 +625,11 @@ static void flakey_status(struct dm_target *ti, status_type_t type, (fc->corrupt_bio_rw == WRITE) ? 'w' : 'r', fc->corrupt_bio_value, fc->corrupt_bio_flags); + if (fc->random_read_corrupt > 0) + DMEMIT(" random_read_corrupt %u", fc->random_read_corrupt); + if (fc->random_write_corrupt > 0) + DMEMIT(" random_write_corrupt %u", fc->random_write_corrupt); + break; case STATUSTYPE_IMA: diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c index 63ec502fcb12..3d5c56e0a062 100644 --- a/drivers/md/dm-integrity.c +++ b/drivers/md/dm-integrity.c @@ -34,11 +34,11 @@ #define DEFAULT_BUFFER_SECTORS 128 #define DEFAULT_JOURNAL_WATERMARK 50 #define DEFAULT_SYNC_MSEC 10000 -#define DEFAULT_MAX_JOURNAL_SECTORS 131072 +#define DEFAULT_MAX_JOURNAL_SECTORS (IS_ENABLED(CONFIG_64BIT) ? 131072 : 8192) #define MIN_LOG2_INTERLEAVE_SECTORS 3 #define MAX_LOG2_INTERLEAVE_SECTORS 31 #define METADATA_WORKQUEUE_MAX_ACTIVE 16 -#define RECALC_SECTORS 32768 +#define RECALC_SECTORS (IS_ENABLED(CONFIG_64BIT) ? 32768 : 2048) #define RECALC_WRITE_SUPER 16 #define BITMAP_BLOCK_SIZE 4096 /* don't change it */ #define BITMAP_FLUSH_INTERVAL (10 * HZ) @@ -251,8 +251,6 @@ struct dm_integrity_c { struct workqueue_struct *recalc_wq; struct work_struct recalc_work; - u8 *recalc_buffer; - u8 *recalc_tags; struct bio_list flush_bio_list; @@ -342,24 +340,9 @@ static struct kmem_cache *journal_io_cache; #define JOURNAL_IO_MEMPOOL 32 #ifdef DEBUG_PRINT -#define DEBUG_print(x, ...) printk(KERN_DEBUG x, ##__VA_ARGS__) -static void __DEBUG_bytes(__u8 *bytes, size_t len, const char *msg, ...) -{ - va_list args; - - va_start(args, msg); - vprintk(msg, args); - va_end(args); - if (len) - pr_cont(":"); - while (len) { - pr_cont(" %02x", *bytes); - bytes++; - len--; - } - pr_cont("\n"); -} -#define DEBUG_bytes(bytes, len, msg, ...) __DEBUG_bytes(bytes, len, KERN_DEBUG msg, ##__VA_ARGS__) +#define DEBUG_print(x, ...) printk(KERN_DEBUG x, ##__VA_ARGS__) +#define DEBUG_bytes(bytes, len, msg, ...) printk(KERN_DEBUG msg "%s%*ph\n", ##__VA_ARGS__, \ + len ? ": " : "", len, bytes) #else #define DEBUG_print(x, ...) do { } while (0) #define DEBUG_bytes(bytes, len, msg, ...) do { } while (0) @@ -2661,6 +2644,9 @@ static void recalc_write_super(struct dm_integrity_c *ic) static void integrity_recalc(struct work_struct *w) { struct dm_integrity_c *ic = container_of(w, struct dm_integrity_c, recalc_work); + size_t recalc_tags_size; + u8 *recalc_buffer = NULL; + u8 *recalc_tags = NULL; struct dm_integrity_range range; struct dm_io_request io_req; struct dm_io_region io_loc; @@ -2672,6 +2658,26 @@ static void integrity_recalc(struct work_struct *w) unsigned int i; int r; unsigned int super_counter = 0; + unsigned recalc_sectors = RECALC_SECTORS; + +retry: + recalc_buffer = __vmalloc(recalc_sectors << SECTOR_SHIFT, GFP_NOIO); + if (!recalc_buffer) { +oom: + recalc_sectors >>= 1; + if (recalc_sectors >= 1U << ic->sb->log2_sectors_per_block) + goto retry; + DMCRIT("out of memory for recalculate buffer - recalculation disabled"); + goto free_ret; + } + recalc_tags_size = (recalc_sectors >> ic->sb->log2_sectors_per_block) * ic->tag_size; + if (crypto_shash_digestsize(ic->internal_hash) > ic->tag_size) + recalc_tags_size += crypto_shash_digestsize(ic->internal_hash) - ic->tag_size; + recalc_tags = kvmalloc(recalc_tags_size, GFP_NOIO); + if (!recalc_tags) { + vfree(recalc_buffer); + goto oom; + } DEBUG_print("start recalculation... (position %llx)\n", le64_to_cpu(ic->sb->recalc_sector)); @@ -2693,7 +2699,7 @@ next_chunk: } get_area_and_offset(ic, range.logical_sector, &area, &offset); - range.n_sectors = min((sector_t)RECALC_SECTORS, ic->provided_data_sectors - range.logical_sector); + range.n_sectors = min((sector_t)recalc_sectors, ic->provided_data_sectors - range.logical_sector); if (!ic->meta_dev) range.n_sectors = min(range.n_sectors, ((sector_t)1U << ic->sb->log2_interleave_sectors) - (unsigned int)offset); @@ -2735,7 +2741,7 @@ next_chunk: io_req.bi_opf = REQ_OP_READ; io_req.mem.type = DM_IO_VMA; - io_req.mem.ptr.addr = ic->recalc_buffer; + io_req.mem.ptr.addr = recalc_buffer; io_req.notify.fn = NULL; io_req.client = ic->io; io_loc.bdev = ic->dev->bdev; @@ -2748,15 +2754,15 @@ next_chunk: goto err; } - t = ic->recalc_tags; + t = recalc_tags; for (i = 0; i < n_sectors; i += ic->sectors_per_block) { - integrity_sector_checksum(ic, logical_sector + i, ic->recalc_buffer + (i << SECTOR_SHIFT), t); + integrity_sector_checksum(ic, logical_sector + i, recalc_buffer + (i << SECTOR_SHIFT), t); t += ic->tag_size; } metadata_block = get_metadata_sector_and_offset(ic, area, offset, &metadata_offset); - r = dm_integrity_rw_tag(ic, ic->recalc_tags, &metadata_block, &metadata_offset, t - ic->recalc_tags, TAG_WRITE); + r = dm_integrity_rw_tag(ic, recalc_tags, &metadata_block, &metadata_offset, t - recalc_tags, TAG_WRITE); if (unlikely(r)) { dm_integrity_io_error(ic, "writing tags", r); goto err; @@ -2784,12 +2790,16 @@ advance_and_next: err: remove_range(ic, &range); - return; + goto free_ret; unlock_ret: spin_unlock_irq(&ic->endio_wait.lock); recalc_write_super(ic); + +free_ret: + vfree(recalc_buffer); + kvfree(recalc_tags); } static void bitmap_block_work(struct work_struct *w) @@ -4454,8 +4464,6 @@ try_smaller_buffer: } if (ic->internal_hash) { - size_t recalc_tags_size; - ic->recalc_wq = alloc_workqueue("dm-integrity-recalc", WQ_MEM_RECLAIM, 1); if (!ic->recalc_wq) { ti->error = "Cannot allocate workqueue"; @@ -4463,21 +4471,6 @@ try_smaller_buffer: goto bad; } INIT_WORK(&ic->recalc_work, integrity_recalc); - ic->recalc_buffer = vmalloc(RECALC_SECTORS << SECTOR_SHIFT); - if (!ic->recalc_buffer) { - ti->error = "Cannot allocate buffer for recalculating"; - r = -ENOMEM; - goto bad; - } - recalc_tags_size = (RECALC_SECTORS >> ic->sb->log2_sectors_per_block) * ic->tag_size; - if (crypto_shash_digestsize(ic->internal_hash) > ic->tag_size) - recalc_tags_size += crypto_shash_digestsize(ic->internal_hash) - ic->tag_size; - ic->recalc_tags = kvmalloc(recalc_tags_size, GFP_KERNEL); - if (!ic->recalc_tags) { - ti->error = "Cannot allocate tags for recalculating"; - r = -ENOMEM; - goto bad; - } } else { if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING)) { ti->error = "Recalculate can only be specified with internal_hash"; @@ -4621,8 +4614,6 @@ static void dm_integrity_dtr(struct dm_target *ti) destroy_workqueue(ic->writer_wq); if (ic->recalc_wq) destroy_workqueue(ic->recalc_wq); - vfree(ic->recalc_buffer); - kvfree(ic->recalc_tags); kvfree(ic->bbs); if (ic->bufio) dm_bufio_client_destroy(ic->bufio); diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 6d301019e5e3..f5ed729a8e0c 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -767,7 +767,14 @@ static int get_target_version(struct file *filp, struct dm_ioctl *param, size_t static int check_name(const char *name) { if (strchr(name, '/')) { - DMERR("invalid device name"); + DMERR("device name cannot contain '/'"); + return -EINVAL; + } + + if (strcmp(name, DM_CONTROL_NODE) == 0 || + strcmp(name, ".") == 0 || + strcmp(name, "..") == 0) { + DMERR("device name cannot be \"%s\", \".\", or \"..\"", DM_CONTROL_NODE); return -EINVAL; } @@ -1388,16 +1395,38 @@ static inline blk_mode_t get_mode(struct dm_ioctl *param) return mode; } -static int next_target(struct dm_target_spec *last, uint32_t next, void *end, +static int next_target(struct dm_target_spec *last, uint32_t next, const char *end, struct dm_target_spec **spec, char **target_params) { - *spec = (struct dm_target_spec *) ((unsigned char *) last + next); - *target_params = (char *) (*spec + 1); + static_assert(__alignof__(struct dm_target_spec) <= 8, + "struct dm_target_spec must not require more than 8-byte alignment"); + + /* + * Number of bytes remaining, starting with last. This is always + * sizeof(struct dm_target_spec) or more, as otherwise *last was + * out of bounds already. + */ + size_t remaining = end - (char *)last; + + /* + * There must be room for both the next target spec and the + * NUL-terminator of the target itself. + */ + if (remaining - sizeof(struct dm_target_spec) <= next) { + DMERR("Target spec extends beyond end of parameters"); + return -EINVAL; + } - if (*spec < (last + 1)) + if (next % __alignof__(struct dm_target_spec)) { + DMERR("Next dm_target_spec (offset %u) is not %zu-byte aligned", + next, __alignof__(struct dm_target_spec)); return -EINVAL; + } + + *spec = (struct dm_target_spec *) ((unsigned char *) last + next); + *target_params = (char *) (*spec + 1); - return invalid_str(*target_params, end); + return 0; } static int populate_table(struct dm_table *table, @@ -1407,8 +1436,9 @@ static int populate_table(struct dm_table *table, unsigned int i = 0; struct dm_target_spec *spec = (struct dm_target_spec *) param; uint32_t next = param->data_start; - void *end = (void *) param + param_size; + const char *const end = (const char *) param + param_size; char *target_params; + size_t min_size = sizeof(struct dm_ioctl); if (!param->target_count) { DMERR("%s: no targets specified", __func__); @@ -1416,6 +1446,13 @@ static int populate_table(struct dm_table *table, } for (i = 0; i < param->target_count; i++) { + const char *nul_terminator; + + if (next < min_size) { + DMERR("%s: next target spec (offset %u) overlaps %s", + __func__, next, i ? "previous target" : "'struct dm_ioctl'"); + return -EINVAL; + } r = next_target(spec, next, end, &spec, &target_params); if (r) { @@ -1423,6 +1460,15 @@ static int populate_table(struct dm_table *table, return r; } + nul_terminator = memchr(target_params, 0, (size_t)(end - target_params)); + if (nul_terminator == NULL) { + DMERR("%s: target parameters not NUL-terminated", __func__); + return -EINVAL; + } + + /* Add 1 for NUL terminator */ + min_size = (size_t)(nul_terminator - (const char *)spec) + 1; + r = dm_table_add_target(table, spec->target_type, (sector_t) spec->sector_start, (sector_t) spec->length, @@ -1830,30 +1876,36 @@ static ioctl_fn lookup_ioctl(unsigned int cmd, int *ioctl_flags) * As well as checking the version compatibility this always * copies the kernel interface version out. */ -static int check_version(unsigned int cmd, struct dm_ioctl __user *user) +static int check_version(unsigned int cmd, struct dm_ioctl __user *user, + struct dm_ioctl *kernel_params) { - uint32_t version[3]; int r = 0; - if (copy_from_user(version, user->version, sizeof(version))) + /* Make certain version is first member of dm_ioctl struct */ + BUILD_BUG_ON(offsetof(struct dm_ioctl, version) != 0); + + if (copy_from_user(kernel_params->version, user->version, sizeof(kernel_params->version))) return -EFAULT; - if ((version[0] != DM_VERSION_MAJOR) || - (version[1] > DM_VERSION_MINOR)) { + if ((kernel_params->version[0] != DM_VERSION_MAJOR) || + (kernel_params->version[1] > DM_VERSION_MINOR)) { DMERR("ioctl interface mismatch: kernel(%u.%u.%u), user(%u.%u.%u), cmd(%d)", DM_VERSION_MAJOR, DM_VERSION_MINOR, DM_VERSION_PATCHLEVEL, - version[0], version[1], version[2], cmd); + kernel_params->version[0], + kernel_params->version[1], + kernel_params->version[2], + cmd); r = -EINVAL; } /* * Fill in the kernel version. */ - version[0] = DM_VERSION_MAJOR; - version[1] = DM_VERSION_MINOR; - version[2] = DM_VERSION_PATCHLEVEL; - if (copy_to_user(user->version, version, sizeof(version))) + kernel_params->version[0] = DM_VERSION_MAJOR; + kernel_params->version[1] = DM_VERSION_MINOR; + kernel_params->version[2] = DM_VERSION_PATCHLEVEL; + if (copy_to_user(user->version, kernel_params->version, sizeof(kernel_params->version))) return -EFAULT; return r; @@ -1877,9 +1929,11 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern struct dm_ioctl *dmi; int secure_data; const size_t minimum_data_size = offsetof(struct dm_ioctl, data); - unsigned int noio_flag; - if (copy_from_user(param_kernel, user, minimum_data_size)) + /* check_version() already copied version from userspace, avoid TOCTOU */ + if (copy_from_user((char *)param_kernel + sizeof(param_kernel->version), + (char __user *)user + sizeof(param_kernel->version), + minimum_data_size - sizeof(param_kernel->version))) return -EFAULT; if (param_kernel->data_size < minimum_data_size) { @@ -1904,9 +1958,7 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern * Use kmalloc() rather than vmalloc() when we can. */ dmi = NULL; - noio_flag = memalloc_noio_save(); - dmi = kvmalloc(param_kernel->data_size, GFP_KERNEL | __GFP_HIGH); - memalloc_noio_restore(noio_flag); + dmi = kvmalloc(param_kernel->data_size, GFP_NOIO | __GFP_HIGH); if (!dmi) { if (secure_data && clear_user(user, param_kernel->data_size)) @@ -1991,7 +2043,7 @@ static int ctl_ioctl(struct file *file, uint command, struct dm_ioctl __user *us * Check the interface version passed in. This also * writes out the kernel's interface version. */ - r = check_version(cmd, user); + r = check_version(cmd, user, ¶m_kernel); if (r) return r; diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index 9dd0409848ab..6022189c1388 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c @@ -603,6 +603,8 @@ static int __format_metadata(struct dm_pool_metadata *pmd) r = dm_tm_create_with_sm(pmd->bm, THIN_SUPERBLOCK_LOCATION, &pmd->tm, &pmd->metadata_sm); if (r < 0) { + pmd->tm = NULL; + pmd->metadata_sm = NULL; DMERR("tm_create_with_sm failed"); return r; } @@ -611,6 +613,7 @@ static int __format_metadata(struct dm_pool_metadata *pmd) if (IS_ERR(pmd->data_sm)) { DMERR("sm_disk_create failed"); r = PTR_ERR(pmd->data_sm); + pmd->data_sm = NULL; goto bad_cleanup_tm; } @@ -641,11 +644,15 @@ static int __format_metadata(struct dm_pool_metadata *pmd) bad_cleanup_nb_tm: dm_tm_destroy(pmd->nb_tm); + pmd->nb_tm = NULL; bad_cleanup_data_sm: dm_sm_destroy(pmd->data_sm); + pmd->data_sm = NULL; bad_cleanup_tm: dm_tm_destroy(pmd->tm); + pmd->tm = NULL; dm_sm_destroy(pmd->metadata_sm); + pmd->metadata_sm = NULL; return r; } @@ -711,6 +718,8 @@ static int __open_metadata(struct dm_pool_metadata *pmd) sizeof(disk_super->metadata_space_map_root), &pmd->tm, &pmd->metadata_sm); if (r < 0) { + pmd->tm = NULL; + pmd->metadata_sm = NULL; DMERR("tm_open_with_sm failed"); goto bad_unlock_sblock; } @@ -720,6 +729,7 @@ static int __open_metadata(struct dm_pool_metadata *pmd) if (IS_ERR(pmd->data_sm)) { DMERR("sm_disk_open failed"); r = PTR_ERR(pmd->data_sm); + pmd->data_sm = NULL; goto bad_cleanup_tm; } @@ -746,9 +756,12 @@ static int __open_metadata(struct dm_pool_metadata *pmd) bad_cleanup_data_sm: dm_sm_destroy(pmd->data_sm); + pmd->data_sm = NULL; bad_cleanup_tm: dm_tm_destroy(pmd->tm); + pmd->tm = NULL; dm_sm_destroy(pmd->metadata_sm); + pmd->metadata_sm = NULL; bad_unlock_sblock: dm_bm_unlock(sblock); @@ -795,9 +808,13 @@ static void __destroy_persistent_data_objects(struct dm_pool_metadata *pmd, bool destroy_bm) { dm_sm_destroy(pmd->data_sm); + pmd->data_sm = NULL; dm_sm_destroy(pmd->metadata_sm); + pmd->metadata_sm = NULL; dm_tm_destroy(pmd->nb_tm); + pmd->nb_tm = NULL; dm_tm_destroy(pmd->tm); + pmd->tm = NULL; if (destroy_bm) dm_block_manager_destroy(pmd->bm); } @@ -1005,8 +1022,7 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd) __func__, r); } pmd_write_unlock(pmd); - if (!pmd->fail_io) - __destroy_persistent_data_objects(pmd, true); + __destroy_persistent_data_objects(pmd, true); kfree(pmd); return 0; @@ -1881,53 +1897,29 @@ static void __set_abort_with_changes_flags(struct dm_pool_metadata *pmd) int dm_pool_abort_metadata(struct dm_pool_metadata *pmd) { int r = -EINVAL; - struct dm_block_manager *old_bm = NULL, *new_bm = NULL; /* fail_io is double-checked with pmd->root_lock held below */ if (unlikely(pmd->fail_io)) return r; - /* - * Replacement block manager (new_bm) is created and old_bm destroyed outside of - * pmd root_lock to avoid ABBA deadlock that would result (due to life-cycle of - * shrinker associated with the block manager's bufio client vs pmd root_lock). - * - must take shrinker_rwsem without holding pmd->root_lock - */ - new_bm = dm_block_manager_create(pmd->bdev, THIN_METADATA_BLOCK_SIZE << SECTOR_SHIFT, - THIN_MAX_CONCURRENT_LOCKS); - pmd_write_lock(pmd); if (pmd->fail_io) { pmd_write_unlock(pmd); - goto out; + return r; } - __set_abort_with_changes_flags(pmd); + + /* destroy data_sm/metadata_sm/nb_tm/tm */ __destroy_persistent_data_objects(pmd, false); - old_bm = pmd->bm; - if (IS_ERR(new_bm)) { - DMERR("could not create block manager during abort"); - pmd->bm = NULL; - r = PTR_ERR(new_bm); - goto out_unlock; - } - pmd->bm = new_bm; + /* reset bm */ + dm_block_manager_reset(pmd->bm); + + /* rebuild data_sm/metadata_sm/nb_tm/tm */ r = __open_or_format_metadata(pmd, false); - if (r) { - pmd->bm = NULL; - goto out_unlock; - } - new_bm = NULL; -out_unlock: if (r) pmd->fail_io = true; pmd_write_unlock(pmd); - dm_block_manager_destroy(old_bm); -out: - if (new_bm && !IS_ERR(new_bm)) - dm_block_manager_destroy(new_bm); - return r; } diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index f1d0dcb9db22..07c7f9795b10 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -2527,16 +2527,11 @@ static void noflush_work(struct thin_c *tc, void (*fn)(struct work_struct *)) /*----------------------------------------------------------------*/ -static bool passdown_enabled(struct pool_c *pt) -{ - return pt->adjusted_pf.discard_passdown; -} - static void set_discard_callbacks(struct pool *pool) { struct pool_c *pt = pool->ti->private; - if (passdown_enabled(pt)) { + if (pt->adjusted_pf.discard_passdown) { pool->process_discard_cell = process_discard_cell_passdown; pool->process_prepared_discard = process_prepared_discard_passdown_pt1; pool->process_prepared_discard_pt2 = process_prepared_discard_passdown_pt2; @@ -2845,7 +2840,7 @@ static bool is_factor(sector_t block_size, uint32_t n) * If discard_passdown was enabled verify that the data device * supports discards. Disable discard_passdown if not. */ -static void disable_passdown_if_not_supported(struct pool_c *pt) +static void disable_discard_passdown_if_not_supported(struct pool_c *pt) { struct pool *pool = pt->pool; struct block_device *data_bdev = pt->data_dev->bdev; @@ -3446,7 +3441,6 @@ out_unlock: static int pool_map(struct dm_target *ti, struct bio *bio) { - int r; struct pool_c *pt = ti->private; struct pool *pool = pt->pool; @@ -3455,10 +3449,9 @@ static int pool_map(struct dm_target *ti, struct bio *bio) */ spin_lock_irq(&pool->lock); bio_set_dev(bio, pt->data_dev->bdev); - r = DM_MAPIO_REMAPPED; spin_unlock_irq(&pool->lock); - return r; + return DM_MAPIO_REMAPPED; } static int maybe_resize_data_dev(struct dm_target *ti, bool *need_commit) @@ -4099,21 +4092,22 @@ static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits) * They get transferred to the live pool in bind_control_target() * called from pool_preresume(). */ - if (!pt->adjusted_pf.discard_enabled) { + + if (pt->adjusted_pf.discard_enabled) { + disable_discard_passdown_if_not_supported(pt); + if (!pt->adjusted_pf.discard_passdown) + limits->max_discard_sectors = 0; + /* + * The pool uses the same discard limits as the underlying data + * device. DM core has already set this up. + */ + } else { /* * Must explicitly disallow stacking discard limits otherwise the * block layer will stack them if pool's data device has support. */ limits->discard_granularity = 0; - return; } - - disable_passdown_if_not_supported(pt); - - /* - * The pool uses the same discard limits as the underlying data - * device. DM core has already set this up. - */ } static struct target_type pool_target = { @@ -4497,11 +4491,10 @@ static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits) struct thin_c *tc = ti->private; struct pool *pool = tc->pool; - if (!pool->pf.discard_enabled) - return; - - limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT; - limits->max_discard_sectors = pool->sectors_per_block * BIO_PRISON_MAX_RANGE; + if (pool->pf.discard_enabled) { + limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT; + limits->max_discard_sectors = pool->sectors_per_block * BIO_PRISON_MAX_RANGE; + } } static struct target_type thin_target = { diff --git a/drivers/md/dm-zone.c b/drivers/md/dm-zone.c index 4b82b7798ce4..eb9832b22b14 100644 --- a/drivers/md/dm-zone.c +++ b/drivers/md/dm-zone.c @@ -7,6 +7,7 @@ #include <linux/mm.h> #include <linux/sched/mm.h> #include <linux/slab.h> +#include <linux/bitmap.h> #include "dm-core.h" @@ -140,9 +141,9 @@ bool dm_is_zone_write(struct mapped_device *md, struct bio *bio) void dm_cleanup_zoned_dev(struct mapped_device *md) { if (md->disk) { - kfree(md->disk->conv_zones_bitmap); + bitmap_free(md->disk->conv_zones_bitmap); md->disk->conv_zones_bitmap = NULL; - kfree(md->disk->seq_zones_wlock); + bitmap_free(md->disk->seq_zones_wlock); md->disk->seq_zones_wlock = NULL; } @@ -182,9 +183,8 @@ static int dm_zone_revalidate_cb(struct blk_zone *zone, unsigned int idx, switch (zone->type) { case BLK_ZONE_TYPE_CONVENTIONAL: if (!disk->conv_zones_bitmap) { - disk->conv_zones_bitmap = - kcalloc(BITS_TO_LONGS(disk->nr_zones), - sizeof(unsigned long), GFP_NOIO); + disk->conv_zones_bitmap = bitmap_zalloc(disk->nr_zones, + GFP_NOIO); if (!disk->conv_zones_bitmap) return -ENOMEM; } @@ -193,9 +193,8 @@ static int dm_zone_revalidate_cb(struct blk_zone *zone, unsigned int idx, case BLK_ZONE_TYPE_SEQWRITE_REQ: case BLK_ZONE_TYPE_SEQWRITE_PREF: if (!disk->seq_zones_wlock) { - disk->seq_zones_wlock = - kcalloc(BITS_TO_LONGS(disk->nr_zones), - sizeof(unsigned long), GFP_NOIO); + disk->seq_zones_wlock = bitmap_zalloc(disk->nr_zones, + GFP_NOIO); if (!disk->seq_zones_wlock) return -ENOMEM; } diff --git a/drivers/md/dm.c b/drivers/md/dm.c index fe2d4750d9c7..f0f118ab20fa 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -487,48 +487,50 @@ u64 dm_start_time_ns_from_clone(struct bio *bio) } EXPORT_SYMBOL_GPL(dm_start_time_ns_from_clone); -static bool bio_is_flush_with_data(struct bio *bio) +static inline bool bio_is_flush_with_data(struct bio *bio) { return ((bio->bi_opf & REQ_PREFLUSH) && bio->bi_iter.bi_size); } -static void dm_io_acct(struct dm_io *io, bool end) +static inline unsigned int dm_io_sectors(struct dm_io *io, struct bio *bio) { - struct dm_stats_aux *stats_aux = &io->stats_aux; - unsigned long start_time = io->start_time; - struct mapped_device *md = io->md; - struct bio *bio = io->orig_bio; - unsigned int sectors; - /* * If REQ_PREFLUSH set, don't account payload, it will be * submitted (and accounted) after this flush completes. */ if (bio_is_flush_with_data(bio)) - sectors = 0; - else if (likely(!(dm_io_flagged(io, DM_IO_WAS_SPLIT)))) - sectors = bio_sectors(bio); - else - sectors = io->sectors; + return 0; + if (unlikely(dm_io_flagged(io, DM_IO_WAS_SPLIT))) + return io->sectors; + return bio_sectors(bio); +} - if (!end) - bdev_start_io_acct(bio->bi_bdev, bio_op(bio), start_time); - else - bdev_end_io_acct(bio->bi_bdev, bio_op(bio), sectors, - start_time); +static void dm_io_acct(struct dm_io *io, bool end) +{ + struct bio *bio = io->orig_bio; + + if (dm_io_flagged(io, DM_IO_BLK_STAT)) { + if (!end) + bdev_start_io_acct(bio->bi_bdev, bio_op(bio), + io->start_time); + else + bdev_end_io_acct(bio->bi_bdev, bio_op(bio), + dm_io_sectors(io, bio), + io->start_time); + } if (static_branch_unlikely(&stats_enabled) && - unlikely(dm_stats_used(&md->stats))) { + unlikely(dm_stats_used(&io->md->stats))) { sector_t sector; - if (likely(!dm_io_flagged(io, DM_IO_WAS_SPLIT))) - sector = bio->bi_iter.bi_sector; - else + if (unlikely(dm_io_flagged(io, DM_IO_WAS_SPLIT))) sector = bio_end_sector(bio) - io->sector_offset; + else + sector = bio->bi_iter.bi_sector; - dm_stats_account_io(&md->stats, bio_data_dir(bio), - sector, sectors, - end, start_time, stats_aux); + dm_stats_account_io(&io->md->stats, bio_data_dir(bio), + sector, dm_io_sectors(io, bio), + end, io->start_time, &io->stats_aux); } } @@ -592,8 +594,11 @@ static struct dm_io *alloc_io(struct mapped_device *md, struct bio *bio) spin_lock_init(&io->lock); io->start_time = jiffies; io->flags = 0; + if (blk_queue_io_stat(md->queue)) + dm_io_set_flag(io, DM_IO_BLK_STAT); - if (static_branch_unlikely(&stats_enabled)) + if (static_branch_unlikely(&stats_enabled) && + unlikely(dm_stats_used(&md->stats))) dm_stats_record_start(&md->stats, &io->stats_aux); return io; @@ -2348,6 +2353,7 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t) break; case DM_TYPE_BIO_BASED: case DM_TYPE_DAX_BIO_BASED: + blk_queue_flag_set(QUEUE_FLAG_IO_STAT, md->queue); break; case DM_TYPE_NONE: WARN_ON_ONCE(true); @@ -3143,6 +3149,8 @@ struct dm_pr { bool fail_early; int ret; enum pr_type type; + struct pr_keys *read_keys; + struct pr_held_reservation *rsv; }; static int dm_call_pr(struct block_device *bdev, iterate_devices_callout_fn fn, @@ -3375,12 +3383,79 @@ out: return r; } +static int __dm_pr_read_keys(struct dm_target *ti, struct dm_dev *dev, + sector_t start, sector_t len, void *data) +{ + struct dm_pr *pr = data; + const struct pr_ops *ops = dev->bdev->bd_disk->fops->pr_ops; + + if (!ops || !ops->pr_read_keys) { + pr->ret = -EOPNOTSUPP; + return -1; + } + + pr->ret = ops->pr_read_keys(dev->bdev, pr->read_keys); + if (!pr->ret) + return -1; + + return 0; +} + +static int dm_pr_read_keys(struct block_device *bdev, struct pr_keys *keys) +{ + struct dm_pr pr = { + .read_keys = keys, + }; + int ret; + + ret = dm_call_pr(bdev, __dm_pr_read_keys, &pr); + if (ret) + return ret; + + return pr.ret; +} + +static int __dm_pr_read_reservation(struct dm_target *ti, struct dm_dev *dev, + sector_t start, sector_t len, void *data) +{ + struct dm_pr *pr = data; + const struct pr_ops *ops = dev->bdev->bd_disk->fops->pr_ops; + + if (!ops || !ops->pr_read_reservation) { + pr->ret = -EOPNOTSUPP; + return -1; + } + + pr->ret = ops->pr_read_reservation(dev->bdev, pr->rsv); + if (!pr->ret) + return -1; + + return 0; +} + +static int dm_pr_read_reservation(struct block_device *bdev, + struct pr_held_reservation *rsv) +{ + struct dm_pr pr = { + .rsv = rsv, + }; + int ret; + + ret = dm_call_pr(bdev, __dm_pr_read_reservation, &pr); + if (ret) + return ret; + + return pr.ret; +} + static const struct pr_ops dm_pr_ops = { .pr_register = dm_pr_register, .pr_reserve = dm_pr_reserve, .pr_release = dm_pr_release, .pr_preempt = dm_pr_preempt, .pr_clear = dm_pr_clear, + .pr_read_keys = dm_pr_read_keys, + .pr_read_reservation = dm_pr_read_reservation, }; static const struct block_device_operations dm_blk_dops = { diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 63d9010d8e61..f682295af91f 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -210,9 +210,6 @@ void dm_put_table_device(struct mapped_device *md, struct dm_dev *d); int dm_kobject_uevent(struct mapped_device *md, enum kobject_action action, unsigned int cookie, bool need_resize_uevent); -void dm_internal_suspend(struct mapped_device *md); -void dm_internal_resume(struct mapped_device *md); - int dm_io_init(void); void dm_io_exit(void); diff --git a/drivers/md/persistent-data/dm-block-manager.c b/drivers/md/persistent-data/dm-block-manager.c index 7bdfc23f758a..0e010e1204aa 100644 --- a/drivers/md/persistent-data/dm-block-manager.c +++ b/drivers/md/persistent-data/dm-block-manager.c @@ -421,6 +421,12 @@ void dm_block_manager_destroy(struct dm_block_manager *bm) } EXPORT_SYMBOL_GPL(dm_block_manager_destroy); +void dm_block_manager_reset(struct dm_block_manager *bm) +{ + dm_bufio_client_reset(bm->bufio); +} +EXPORT_SYMBOL_GPL(dm_block_manager_reset); + unsigned int dm_bm_block_size(struct dm_block_manager *bm) { return dm_bufio_get_block_size(bm->bufio); diff --git a/drivers/md/persistent-data/dm-block-manager.h b/drivers/md/persistent-data/dm-block-manager.h index 5746b0f82a03..f706d3de8d5a 100644 --- a/drivers/md/persistent-data/dm-block-manager.h +++ b/drivers/md/persistent-data/dm-block-manager.h @@ -36,6 +36,7 @@ struct dm_block_manager *dm_block_manager_create( struct block_device *bdev, unsigned int block_size, unsigned int max_held_per_thread); void dm_block_manager_destroy(struct dm_block_manager *bm); +void dm_block_manager_reset(struct dm_block_manager *bm); unsigned int dm_bm_block_size(struct dm_block_manager *bm); dm_block_t dm_bm_nr_blocks(struct dm_block_manager *bm); diff --git a/drivers/md/persistent-data/dm-space-map.h b/drivers/md/persistent-data/dm-space-map.h index dab490353781..6bf69922b5ad 100644 --- a/drivers/md/persistent-data/dm-space-map.h +++ b/drivers/md/persistent-data/dm-space-map.h @@ -77,7 +77,8 @@ struct dm_space_map { static inline void dm_sm_destroy(struct dm_space_map *sm) { - sm->destroy(sm); + if (sm) + sm->destroy(sm); } static inline int dm_sm_extend(struct dm_space_map *sm, dm_block_t extra_blocks) diff --git a/drivers/md/persistent-data/dm-transaction-manager.c b/drivers/md/persistent-data/dm-transaction-manager.c index 6dc016248baf..c88fa6266203 100644 --- a/drivers/md/persistent-data/dm-transaction-manager.c +++ b/drivers/md/persistent-data/dm-transaction-manager.c @@ -199,6 +199,9 @@ EXPORT_SYMBOL_GPL(dm_tm_create_non_blocking_clone); void dm_tm_destroy(struct dm_transaction_manager *tm) { + if (!tm) + return; + if (!tm->is_clone) wipe_shadow_table(tm); diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig index a3d0288fd0e2..88a6e506a942 100644 --- a/drivers/message/fusion/Kconfig +++ b/drivers/message/fusion/Kconfig @@ -2,7 +2,7 @@ menuconfig FUSION bool "Fusion MPT device support" - depends on PCI + depends on PCI && HAS_IOPORT help Say Y here to get to see options for Fusion Message Passing Technology (MPT) drivers. diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 4f0afce8428d..4bf669c55649 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -712,7 +712,7 @@ mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass, char *func_name) MptDriverClass[cb_idx] = dclass; MptEvHandlers[cb_idx] = NULL; last_drv_idx = cb_idx; - strlcpy(MptCallbacksName[cb_idx], func_name, + strscpy(MptCallbacksName[cb_idx], func_name, MPT_MAX_CALLBACKNAME_LEN+1); break; } @@ -7666,7 +7666,7 @@ mpt_display_event_info(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply) break; } if (ds) - strlcpy(evStr, ds, EVENT_DESCR_STR_SZ); + strscpy(evStr, ds, EVENT_DESCR_STR_SZ); devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 1decd09a08d8..dd028df4b283 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -2408,7 +2408,7 @@ mptctl_hp_hostinfo(MPT_ADAPTER *ioc, unsigned long arg, unsigned int data_size) if (mpt_config(ioc, &cfg) == 0) { ManufacturingPage0_t *pdata = (ManufacturingPage0_t *) pbuf; if (strlen(pdata->BoardTracerNumber) > 1) { - strlcpy(karg.serial_number, + strscpy(karg.serial_number, pdata->BoardTracerNumber, 24); } } diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index 938c4f41b98c..5aae2f9bdd51 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -761,7 +761,8 @@ static int at24_probe(struct i2c_client *client) pm_runtime_disable(dev); if (!pm_runtime_status_suspended(dev)) regulator_disable(at24->vcc_reg); - return PTR_ERR(at24->nvmem); + return dev_err_probe(dev, PTR_ERR(at24->nvmem), + "failed to register nvmem\n"); } /* diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index a7244de081ec..ed4d0ef5e5c3 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -159,10 +159,7 @@ static irqreturn_t pci_endpoint_test_irqhandler(int irq, void *dev_id) if (reg & STATUS_IRQ_RAISED) { test->last_irq = irq; complete(&test->irq_raised); - reg &= ~STATUS_IRQ_RAISED; } - pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_STATUS, - reg); return IRQ_HANDLED; } @@ -316,21 +313,17 @@ static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test, struct pci_dev *pdev = test->pdev; pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, - msix == false ? IRQ_TYPE_MSI : - IRQ_TYPE_MSIX); + msix ? IRQ_TYPE_MSIX : IRQ_TYPE_MSI); pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, msi_num); pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, - msix == false ? COMMAND_RAISE_MSI_IRQ : - COMMAND_RAISE_MSIX_IRQ); + msix ? COMMAND_RAISE_MSIX_IRQ : + COMMAND_RAISE_MSI_IRQ); val = wait_for_completion_timeout(&test->irq_raised, msecs_to_jiffies(1000)); if (!val) return false; - if (pci_irq_vector(pdev, msi_num - 1) == test->last_irq) - return true; - - return false; + return pci_irq_vector(pdev, msi_num - 1) == test->last_irq; } static int pci_endpoint_test_validate_xfer_params(struct device *dev, @@ -729,6 +722,10 @@ static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd, struct pci_dev *pdev = test->pdev; mutex_lock(&test->mutex); + + reinit_completion(&test->irq_raised); + test->last_irq = -ENODATA; + switch (cmd) { case PCITEST_BAR: bar = arg; @@ -938,6 +935,9 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev) if (id < 0) return; + pci_endpoint_test_release_irq(test); + pci_endpoint_test_free_irq_vectors(test); + misc_deregister(&test->miscdev); kfree(misc_device->name); kfree(test->name); @@ -947,9 +947,6 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev) pci_iounmap(pdev, test->bar[bar]); } - pci_endpoint_test_release_irq(test); - pci_endpoint_test_free_irq_vectors(test); - pci_release_regions(pdev); pci_disable_device(pdev); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c index fb7874da3caa..4804990b7f22 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c @@ -368,7 +368,6 @@ static int mlx5_pci_link_toggle(struct mlx5_core_dev *dev) struct pci_dev *sdev; u16 reg16, dev_id; int cap, err; - u32 reg32; err = pci_read_config_word(dev->pdev, PCI_DEVICE_ID, &dev_id); if (err) @@ -399,11 +398,8 @@ static int mlx5_pci_link_toggle(struct mlx5_core_dev *dev) return err; /* Check link */ - err = pci_read_config_dword(bridge, cap + PCI_EXP_LNKCAP, ®32); - if (err) - return err; - if (!(reg32 & PCI_EXP_LNKCAP_DLLLARC)) { - mlx5_core_warn(dev, "No PCI link reporting capability (0x%08x)\n", reg32); + if (!bridge->link_active_reporting) { + mlx5_core_warn(dev, "No PCI link reporting capability\n"); msleep(1000); goto restore; } diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index 954dbc105fc8..5852fe290523 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -25,7 +25,7 @@ int nvdimm_major; static int nvdimm_bus_major; -struct class *nd_class; +static struct class *nd_class; static DEFINE_IDA(nd_ida); static int to_nd_device_type(const struct device *dev) diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c index 957f7c3d17ba..1273873582be 100644 --- a/drivers/nvdimm/dimm_devs.c +++ b/drivers/nvdimm/dimm_devs.c @@ -349,8 +349,8 @@ static ssize_t available_slots_show(struct device *dev, } static DEVICE_ATTR_RO(available_slots); -ssize_t security_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t security_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct nvdimm *nvdimm = to_nvdimm(dev); diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index ceea55f621cc..46e094e56159 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -260,7 +260,7 @@ __weak long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff, long actual_nr; if (mode != DAX_RECOVERY_WRITE) - return -EIO; + return -EHWPOISON; /* * Set the recovery stride is set to kernel page size because diff --git a/drivers/nvme/host/Makefile b/drivers/nvme/host/Makefile index d3fc5063e4be..c7c3cf202d12 100644 --- a/drivers/nvme/host/Makefile +++ b/drivers/nvme/host/Makefile @@ -10,7 +10,7 @@ obj-$(CONFIG_NVME_FC) += nvme-fc.o obj-$(CONFIG_NVME_TCP) += nvme-tcp.o obj-$(CONFIG_NVME_APPLE) += nvme-apple.o -nvme-core-y += core.o ioctl.o sysfs.o +nvme-core-y += core.o ioctl.o sysfs.o pr.o nvme-core-$(CONFIG_NVME_VERBOSE_ERRORS) += constants.o nvme-core-$(CONFIG_TRACING) += trace.o nvme-core-$(CONFIG_NVME_MULTIPATH) += multipath.o diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index fdfcf2781c85..98bfb3d9c22a 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -279,7 +279,7 @@ static blk_status_t nvme_error_status(u16 status) case NVME_SC_INVALID_PI: return BLK_STS_PROTECTION; case NVME_SC_RESERVATION_CONFLICT: - return BLK_STS_NEXUS; + return BLK_STS_RESV_CONFLICT; case NVME_SC_HOST_PATH_ERROR: return BLK_STS_TRANSPORT; case NVME_SC_ZONE_TOO_MANY_ACTIVE: @@ -2105,153 +2105,6 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_ns_info *info) } } -static char nvme_pr_type(enum pr_type type) -{ - switch (type) { - case PR_WRITE_EXCLUSIVE: - return 1; - case PR_EXCLUSIVE_ACCESS: - return 2; - case PR_WRITE_EXCLUSIVE_REG_ONLY: - return 3; - case PR_EXCLUSIVE_ACCESS_REG_ONLY: - return 4; - case PR_WRITE_EXCLUSIVE_ALL_REGS: - return 5; - case PR_EXCLUSIVE_ACCESS_ALL_REGS: - return 6; - default: - return 0; - } -} - -static int nvme_send_ns_head_pr_command(struct block_device *bdev, - struct nvme_command *c, u8 data[16]) -{ - struct nvme_ns_head *head = bdev->bd_disk->private_data; - int srcu_idx = srcu_read_lock(&head->srcu); - struct nvme_ns *ns = nvme_find_path(head); - int ret = -EWOULDBLOCK; - - if (ns) { - c->common.nsid = cpu_to_le32(ns->head->ns_id); - ret = nvme_submit_sync_cmd(ns->queue, c, data, 16); - } - srcu_read_unlock(&head->srcu, srcu_idx); - return ret; -} - -static int nvme_send_ns_pr_command(struct nvme_ns *ns, struct nvme_command *c, - u8 data[16]) -{ - c->common.nsid = cpu_to_le32(ns->head->ns_id); - return nvme_submit_sync_cmd(ns->queue, c, data, 16); -} - -static int nvme_sc_to_pr_err(int nvme_sc) -{ - if (nvme_is_path_error(nvme_sc)) - return PR_STS_PATH_FAILED; - - switch (nvme_sc) { - case NVME_SC_SUCCESS: - return PR_STS_SUCCESS; - case NVME_SC_RESERVATION_CONFLICT: - return PR_STS_RESERVATION_CONFLICT; - case NVME_SC_ONCS_NOT_SUPPORTED: - return -EOPNOTSUPP; - case NVME_SC_BAD_ATTRIBUTES: - case NVME_SC_INVALID_OPCODE: - case NVME_SC_INVALID_FIELD: - case NVME_SC_INVALID_NS: - return -EINVAL; - default: - return PR_STS_IOERR; - } -} - -static int nvme_pr_command(struct block_device *bdev, u32 cdw10, - u64 key, u64 sa_key, u8 op) -{ - struct nvme_command c = { }; - u8 data[16] = { 0, }; - int ret; - - put_unaligned_le64(key, &data[0]); - put_unaligned_le64(sa_key, &data[8]); - - c.common.opcode = op; - c.common.cdw10 = cpu_to_le32(cdw10); - - if (IS_ENABLED(CONFIG_NVME_MULTIPATH) && - bdev->bd_disk->fops == &nvme_ns_head_ops) - ret = nvme_send_ns_head_pr_command(bdev, &c, data); - else - ret = nvme_send_ns_pr_command(bdev->bd_disk->private_data, &c, - data); - if (ret < 0) - return ret; - - return nvme_sc_to_pr_err(ret); -} - -static int nvme_pr_register(struct block_device *bdev, u64 old, - u64 new, unsigned flags) -{ - u32 cdw10; - - if (flags & ~PR_FL_IGNORE_KEY) - return -EOPNOTSUPP; - - cdw10 = old ? 2 : 0; - cdw10 |= (flags & PR_FL_IGNORE_KEY) ? 1 << 3 : 0; - cdw10 |= (1 << 30) | (1 << 31); /* PTPL=1 */ - return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_register); -} - -static int nvme_pr_reserve(struct block_device *bdev, u64 key, - enum pr_type type, unsigned flags) -{ - u32 cdw10; - - if (flags & ~PR_FL_IGNORE_KEY) - return -EOPNOTSUPP; - - cdw10 = nvme_pr_type(type) << 8; - cdw10 |= ((flags & PR_FL_IGNORE_KEY) ? 1 << 3 : 0); - return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_acquire); -} - -static int nvme_pr_preempt(struct block_device *bdev, u64 old, u64 new, - enum pr_type type, bool abort) -{ - u32 cdw10 = nvme_pr_type(type) << 8 | (abort ? 2 : 1); - - return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_acquire); -} - -static int nvme_pr_clear(struct block_device *bdev, u64 key) -{ - u32 cdw10 = 1 | (key ? 0 : 1 << 3); - - return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release); -} - -static int nvme_pr_release(struct block_device *bdev, u64 key, enum pr_type type) -{ - u32 cdw10 = nvme_pr_type(type) << 8 | (key ? 0 : 1 << 3); - - return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release); -} - -const struct pr_ops nvme_pr_ops = { - .pr_register = nvme_pr_register, - .pr_reserve = nvme_pr_reserve, - .pr_release = nvme_pr_release, - .pr_preempt = nvme_pr_preempt, - .pr_clear = nvme_pr_clear, -}; - #ifdef CONFIG_BLK_SED_OPAL static int nvme_sec_submit(void *data, u16 spsp, u8 secp, void *buffer, size_t len, bool send) diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 9a98c14c552a..a69e1efb3299 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -19,6 +19,8 @@ #include <trace/events/block.h> +extern const struct pr_ops nvme_pr_ops; + extern unsigned int nvme_io_timeout; #define NVME_IO_TIMEOUT (nvme_io_timeout * HZ) diff --git a/drivers/nvme/host/pr.c b/drivers/nvme/host/pr.c new file mode 100644 index 000000000000..391b1465ebfd --- /dev/null +++ b/drivers/nvme/host/pr.c @@ -0,0 +1,315 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015 Intel Corporation + * Keith Busch <kbusch@kernel.org> + */ +#include <linux/blkdev.h> +#include <linux/pr.h> +#include <asm/unaligned.h> + +#include "nvme.h" + +static enum nvme_pr_type nvme_pr_type_from_blk(enum pr_type type) +{ + switch (type) { + case PR_WRITE_EXCLUSIVE: + return NVME_PR_WRITE_EXCLUSIVE; + case PR_EXCLUSIVE_ACCESS: + return NVME_PR_EXCLUSIVE_ACCESS; + case PR_WRITE_EXCLUSIVE_REG_ONLY: + return NVME_PR_WRITE_EXCLUSIVE_REG_ONLY; + case PR_EXCLUSIVE_ACCESS_REG_ONLY: + return NVME_PR_EXCLUSIVE_ACCESS_REG_ONLY; + case PR_WRITE_EXCLUSIVE_ALL_REGS: + return NVME_PR_WRITE_EXCLUSIVE_ALL_REGS; + case PR_EXCLUSIVE_ACCESS_ALL_REGS: + return NVME_PR_EXCLUSIVE_ACCESS_ALL_REGS; + } + + return 0; +} + +static enum pr_type block_pr_type_from_nvme(enum nvme_pr_type type) +{ + switch (type) { + case NVME_PR_WRITE_EXCLUSIVE: + return PR_WRITE_EXCLUSIVE; + case NVME_PR_EXCLUSIVE_ACCESS: + return PR_EXCLUSIVE_ACCESS; + case NVME_PR_WRITE_EXCLUSIVE_REG_ONLY: + return PR_WRITE_EXCLUSIVE_REG_ONLY; + case NVME_PR_EXCLUSIVE_ACCESS_REG_ONLY: + return PR_EXCLUSIVE_ACCESS_REG_ONLY; + case NVME_PR_WRITE_EXCLUSIVE_ALL_REGS: + return PR_WRITE_EXCLUSIVE_ALL_REGS; + case NVME_PR_EXCLUSIVE_ACCESS_ALL_REGS: + return PR_EXCLUSIVE_ACCESS_ALL_REGS; + } + + return 0; +} + +static int nvme_send_ns_head_pr_command(struct block_device *bdev, + struct nvme_command *c, void *data, unsigned int data_len) +{ + struct nvme_ns_head *head = bdev->bd_disk->private_data; + int srcu_idx = srcu_read_lock(&head->srcu); + struct nvme_ns *ns = nvme_find_path(head); + int ret = -EWOULDBLOCK; + + if (ns) { + c->common.nsid = cpu_to_le32(ns->head->ns_id); + ret = nvme_submit_sync_cmd(ns->queue, c, data, data_len); + } + srcu_read_unlock(&head->srcu, srcu_idx); + return ret; +} + +static int nvme_send_ns_pr_command(struct nvme_ns *ns, struct nvme_command *c, + void *data, unsigned int data_len) +{ + c->common.nsid = cpu_to_le32(ns->head->ns_id); + return nvme_submit_sync_cmd(ns->queue, c, data, data_len); +} + +static int nvme_sc_to_pr_err(int nvme_sc) +{ + if (nvme_is_path_error(nvme_sc)) + return PR_STS_PATH_FAILED; + + switch (nvme_sc) { + case NVME_SC_SUCCESS: + return PR_STS_SUCCESS; + case NVME_SC_RESERVATION_CONFLICT: + return PR_STS_RESERVATION_CONFLICT; + case NVME_SC_ONCS_NOT_SUPPORTED: + return -EOPNOTSUPP; + case NVME_SC_BAD_ATTRIBUTES: + case NVME_SC_INVALID_OPCODE: + case NVME_SC_INVALID_FIELD: + case NVME_SC_INVALID_NS: + return -EINVAL; + default: + return PR_STS_IOERR; + } +} + +static int nvme_send_pr_command(struct block_device *bdev, + struct nvme_command *c, void *data, unsigned int data_len) +{ + if (IS_ENABLED(CONFIG_NVME_MULTIPATH) && + bdev->bd_disk->fops == &nvme_ns_head_ops) + return nvme_send_ns_head_pr_command(bdev, c, data, data_len); + + return nvme_send_ns_pr_command(bdev->bd_disk->private_data, c, data, + data_len); +} + +static int nvme_pr_command(struct block_device *bdev, u32 cdw10, + u64 key, u64 sa_key, u8 op) +{ + struct nvme_command c = { }; + u8 data[16] = { 0, }; + int ret; + + put_unaligned_le64(key, &data[0]); + put_unaligned_le64(sa_key, &data[8]); + + c.common.opcode = op; + c.common.cdw10 = cpu_to_le32(cdw10); + + ret = nvme_send_pr_command(bdev, &c, data, sizeof(data)); + if (ret < 0) + return ret; + + return nvme_sc_to_pr_err(ret); +} + +static int nvme_pr_register(struct block_device *bdev, u64 old, + u64 new, unsigned flags) +{ + u32 cdw10; + + if (flags & ~PR_FL_IGNORE_KEY) + return -EOPNOTSUPP; + + cdw10 = old ? 2 : 0; + cdw10 |= (flags & PR_FL_IGNORE_KEY) ? 1 << 3 : 0; + cdw10 |= (1 << 30) | (1 << 31); /* PTPL=1 */ + return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_register); +} + +static int nvme_pr_reserve(struct block_device *bdev, u64 key, + enum pr_type type, unsigned flags) +{ + u32 cdw10; + + if (flags & ~PR_FL_IGNORE_KEY) + return -EOPNOTSUPP; + + cdw10 = nvme_pr_type_from_blk(type) << 8; + cdw10 |= ((flags & PR_FL_IGNORE_KEY) ? 1 << 3 : 0); + return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_acquire); +} + +static int nvme_pr_preempt(struct block_device *bdev, u64 old, u64 new, + enum pr_type type, bool abort) +{ + u32 cdw10 = nvme_pr_type_from_blk(type) << 8 | (abort ? 2 : 1); + + return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_acquire); +} + +static int nvme_pr_clear(struct block_device *bdev, u64 key) +{ + u32 cdw10 = 1 | (key ? 0 : 1 << 3); + + return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release); +} + +static int nvme_pr_release(struct block_device *bdev, u64 key, enum pr_type type) +{ + u32 cdw10 = nvme_pr_type_from_blk(type) << 8 | (key ? 0 : 1 << 3); + + return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release); +} + +static int nvme_pr_resv_report(struct block_device *bdev, void *data, + u32 data_len, bool *eds) +{ + struct nvme_command c = { }; + int ret; + + c.common.opcode = nvme_cmd_resv_report; + c.common.cdw10 = cpu_to_le32(nvme_bytes_to_numd(data_len)); + c.common.cdw11 = cpu_to_le32(NVME_EXTENDED_DATA_STRUCT); + *eds = true; + +retry: + ret = nvme_send_pr_command(bdev, &c, data, data_len); + if (ret == NVME_SC_HOST_ID_INCONSIST && + c.common.cdw11 == cpu_to_le32(NVME_EXTENDED_DATA_STRUCT)) { + c.common.cdw11 = 0; + *eds = false; + goto retry; + } + + if (ret < 0) + return ret; + + return nvme_sc_to_pr_err(ret); +} + +static int nvme_pr_read_keys(struct block_device *bdev, + struct pr_keys *keys_info) +{ + u32 rse_len, num_keys = keys_info->num_keys; + struct nvme_reservation_status_ext *rse; + int ret, i; + bool eds; + + /* + * Assume we are using 128-bit host IDs and allocate a buffer large + * enough to get enough keys to fill the return keys buffer. + */ + rse_len = struct_size(rse, regctl_eds, num_keys); + rse = kzalloc(rse_len, GFP_KERNEL); + if (!rse) + return -ENOMEM; + + ret = nvme_pr_resv_report(bdev, rse, rse_len, &eds); + if (ret) + goto free_rse; + + keys_info->generation = le32_to_cpu(rse->gen); + keys_info->num_keys = get_unaligned_le16(&rse->regctl); + + num_keys = min(num_keys, keys_info->num_keys); + for (i = 0; i < num_keys; i++) { + if (eds) { + keys_info->keys[i] = + le64_to_cpu(rse->regctl_eds[i].rkey); + } else { + struct nvme_reservation_status *rs; + + rs = (struct nvme_reservation_status *)rse; + keys_info->keys[i] = le64_to_cpu(rs->regctl_ds[i].rkey); + } + } + +free_rse: + kfree(rse); + return ret; +} + +static int nvme_pr_read_reservation(struct block_device *bdev, + struct pr_held_reservation *resv) +{ + struct nvme_reservation_status_ext tmp_rse, *rse; + int ret, i, num_regs; + u32 rse_len; + bool eds; + +get_num_regs: + /* + * Get the number of registrations so we know how big to allocate + * the response buffer. + */ + ret = nvme_pr_resv_report(bdev, &tmp_rse, sizeof(tmp_rse), &eds); + if (ret) + return ret; + + num_regs = get_unaligned_le16(&tmp_rse.regctl); + if (!num_regs) { + resv->generation = le32_to_cpu(tmp_rse.gen); + return 0; + } + + rse_len = struct_size(rse, regctl_eds, num_regs); + rse = kzalloc(rse_len, GFP_KERNEL); + if (!rse) + return -ENOMEM; + + ret = nvme_pr_resv_report(bdev, rse, rse_len, &eds); + if (ret) + goto free_rse; + + if (num_regs != get_unaligned_le16(&rse->regctl)) { + kfree(rse); + goto get_num_regs; + } + + resv->generation = le32_to_cpu(rse->gen); + resv->type = block_pr_type_from_nvme(rse->rtype); + + for (i = 0; i < num_regs; i++) { + if (eds) { + if (rse->regctl_eds[i].rcsts) { + resv->key = le64_to_cpu(rse->regctl_eds[i].rkey); + break; + } + } else { + struct nvme_reservation_status *rs; + + rs = (struct nvme_reservation_status *)rse; + if (rs->regctl_ds[i].rcsts) { + resv->key = le64_to_cpu(rs->regctl_ds[i].rkey); + break; + } + } + } + +free_rse: + kfree(rse); + return ret; +} + +const struct pr_ops nvme_pr_ops = { + .pr_register = nvme_pr_register, + .pr_reserve = nvme_pr_reserve, + .pr_release = nvme_pr_release, + .pr_preempt = nvme_pr_preempt, + .pr_clear = nvme_pr_clear, + .pr_read_keys = nvme_pr_read_keys, + .pr_read_reservation = nvme_pr_read_reservation, +}; diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index a66386043aa6..9bf652bd002c 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -97,7 +97,6 @@ #define DBG_RUN_SG(x...) #endif -#define CCIO_INLINE inline #define WRITE_U32(value, addr) __raw_writel(value, addr) #define READ_U32(addr) __raw_readl(addr) @@ -330,7 +329,8 @@ static int ioc_count; /** * ccio_alloc_range - Allocate pages in the ioc's resource map. * @ioc: The I/O Controller. - * @pages_needed: The requested number of pages to be mapped into the + * @dev: The PCI device. + * @size: The requested number of bytes to be mapped into the * I/O Pdir... * * This function searches the resource map of the ioc to locate a range @@ -552,7 +552,7 @@ static u32 hint_lookup[] = { * (Load Coherence Index) instruction. The 8 bits used for the virtual * index are bits 12:19 of the value returned by LCI. */ -static void CCIO_INLINE +static void ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba, unsigned long hints) { @@ -623,7 +623,7 @@ ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba, * * FIXME: Can we change the byte_cnt to pages_mapped? */ -static CCIO_INLINE void +static void ccio_clear_io_tlb(struct ioc *ioc, dma_addr_t iovp, size_t byte_cnt) { u32 chain_size = 1 << ioc->chainid_shift; @@ -656,7 +656,7 @@ ccio_clear_io_tlb(struct ioc *ioc, dma_addr_t iovp, size_t byte_cnt) * * FIXME: Can we change byte_cnt to pages_mapped? */ -static CCIO_INLINE void +static void ccio_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt) { u32 iovp = (u32)CCIO_IOVP(iova); @@ -795,9 +795,10 @@ ccio_map_page(struct device *dev, struct page *page, unsigned long offset, /** * ccio_unmap_page - Unmap an address range from the IOMMU. * @dev: The PCI device. - * @addr: The start address of the DMA region. + * @iova: The start address of the DMA region. * @size: The length of the DMA region. * @direction: The direction of the DMA transaction (to/from device). + * @attrs: attributes */ static void ccio_unmap_page(struct device *dev, dma_addr_t iova, size_t size, @@ -838,6 +839,8 @@ ccio_unmap_page(struct device *dev, dma_addr_t iova, size_t size, * @dev: The PCI device. * @size: The length of the DMA region. * @dma_handle: The DMA address handed back to the device (not the cpu). + * @flag: allocation flags + * @attrs: attributes * * This function implements the pci_alloc_consistent function. */ @@ -872,6 +875,7 @@ ccio_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag, * @size: The length of the DMA region. * @cpu_addr: The cpu address returned from the ccio_alloc_consistent. * @dma_handle: The device address returned from the ccio_alloc_consistent. + * @attrs: attributes * * This function implements the pci_free_consistent function. */ @@ -901,6 +905,7 @@ ccio_free(struct device *dev, size_t size, void *cpu_addr, * @sglist: The scatter/gather list to be mapped in the IOMMU. * @nents: The number of entries in the scatter/gather list. * @direction: The direction of the DMA transaction (to/from device). + * @attrs: attributes * * This function implements the pci_map_sg function. */ @@ -980,6 +985,7 @@ ccio_map_sg(struct device *dev, struct scatterlist *sglist, int nents, * @sglist: The scatter/gather list to be unmapped from the IOMMU. * @nents: The number of entries in the scatter/gather list. * @direction: The direction of the DMA transaction (to/from device). + * @attrs: attributes * * This function implements the pci_unmap_sg function. */ diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index e33036281327..f89f9fb4c84b 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -924,8 +924,6 @@ static const char cujo_vers[][4] = { "2.0" }; -void ccio_cujo20_fixup(struct parisc_device *dev, u32 iovp); - /* ** Determine if dino should claim this chip (return 0) or not (return 1). ** If so, initialize the chip appropriately (card-mode vs bridge mode). @@ -1086,9 +1084,8 @@ static struct parisc_driver dino_driver __refdata = { * This is the only routine which is NOT static. * Must be called exactly once before pci_init(). */ -int __init dino_init(void) +void __init dino_init(void) { register_parisc_driver(&dino_driver); - return 0; } diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c index f96e5eaee87e..45e487388c6e 100644 --- a/drivers/parisc/eisa.c +++ b/drivers/parisc/eisa.c @@ -400,7 +400,7 @@ static struct parisc_driver eisa_driver __refdata = { .probe = eisa_probe, }; -void __init eisa_init(void) +void __init parisc_eisa_init(void) { register_parisc_driver(&eisa_driver); } diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index afc6e66ddc31..702bfd64e6e1 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -404,7 +404,7 @@ static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int static void lba_wr_cfg(struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size) { - int error = 0; + int error __maybe_unused = 0; u32 arb_mask = 0; u32 error_config = 0; u32 status_control = 0; @@ -1018,7 +1018,7 @@ static void lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) { unsigned long bytecnt; - long io_count; + long io_count __maybe_unused; long status; /* PDC return status */ long pa_count; pdc_pat_cell_mod_maddr_block_t *pa_pdc_cell; /* PA_VIEW */ @@ -1164,10 +1164,6 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) #endif /* CONFIG_64BIT */ -extern void sba_distributed_lmmio(struct parisc_device *, struct resource *); -extern void sba_directed_lmmio(struct parisc_device *, struct resource *); - - static void lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) { diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c index 2a18f7ba2398..633266447e2f 100644 --- a/drivers/parisc/pdc_stable.c +++ b/drivers/parisc/pdc_stable.c @@ -509,6 +509,8 @@ static struct pdcspath_entry *pdcspath_entries[] = { /** * pdcs_size_read - Stable Storage size output. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The output buffer to write to. */ static ssize_t pdcs_size_read(struct kobject *kobj, @@ -528,6 +530,8 @@ static ssize_t pdcs_size_read(struct kobject *kobj, /** * pdcs_auto_read - Stable Storage autoboot/search flag output. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The output buffer to write to. * @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag */ @@ -554,6 +558,8 @@ static ssize_t pdcs_auto_read(struct kobject *kobj, /** * pdcs_autoboot_read - Stable Storage autoboot flag output. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The output buffer to write to. */ static ssize_t pdcs_autoboot_read(struct kobject *kobj, @@ -564,6 +570,8 @@ static ssize_t pdcs_autoboot_read(struct kobject *kobj, /** * pdcs_autosearch_read - Stable Storage autoboot flag output. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The output buffer to write to. */ static ssize_t pdcs_autosearch_read(struct kobject *kobj, @@ -574,6 +582,8 @@ static ssize_t pdcs_autosearch_read(struct kobject *kobj, /** * pdcs_timer_read - Stable Storage timer count output (in seconds). + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The output buffer to write to. * * The value of the timer field correponds to a number of seconds in powers of 2. @@ -601,6 +611,8 @@ static ssize_t pdcs_timer_read(struct kobject *kobj, /** * pdcs_osid_read - Stable Storage OS ID register output. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The output buffer to write to. */ static ssize_t pdcs_osid_read(struct kobject *kobj, @@ -619,6 +631,8 @@ static ssize_t pdcs_osid_read(struct kobject *kobj, /** * pdcs_osdep1_read - Stable Storage OS-Dependent data area 1 output. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The output buffer to write to. * * This can hold 16 bytes of OS-Dependent data. @@ -645,6 +659,8 @@ static ssize_t pdcs_osdep1_read(struct kobject *kobj, /** * pdcs_diagnostic_read - Stable Storage Diagnostic register output. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The output buffer to write to. * * I have NFC how to interpret the content of that register ;-). @@ -669,6 +685,8 @@ static ssize_t pdcs_diagnostic_read(struct kobject *kobj, /** * pdcs_fastsize_read - Stable Storage FastSize register output. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The output buffer to write to. * * This register holds the amount of system RAM to be tested during boot sequence. @@ -697,6 +715,8 @@ static ssize_t pdcs_fastsize_read(struct kobject *kobj, /** * pdcs_osdep2_read - Stable Storage OS-Dependent data area 2 output. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The output buffer to write to. * * This can hold pdcs_size - 224 bytes of OS-Dependent data, when available. @@ -729,6 +749,8 @@ static ssize_t pdcs_osdep2_read(struct kobject *kobj, /** * pdcs_auto_write - This function handles autoboot/search flag modifying. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The input buffer to read from. * @count: The number of bytes to be read. * @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag @@ -801,6 +823,8 @@ parse_error: /** * pdcs_autoboot_write - This function handles autoboot flag modifying. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The input buffer to read from. * @count: The number of bytes to be read. * @@ -817,6 +841,8 @@ static ssize_t pdcs_autoboot_write(struct kobject *kobj, /** * pdcs_autosearch_write - This function handles autosearch flag modifying. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The input buffer to read from. * @count: The number of bytes to be read. * @@ -833,6 +859,8 @@ static ssize_t pdcs_autosearch_write(struct kobject *kobj, /** * pdcs_osdep1_write - Stable Storage OS-Dependent data area 1 input. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The input buffer to read from. * @count: The number of bytes to be read. * @@ -870,6 +898,8 @@ static ssize_t pdcs_osdep1_write(struct kobject *kobj, /** * pdcs_osdep2_write - Stable Storage OS-Dependent data area 2 input. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The input buffer to read from. * @count: The number of bytes to be read. * @@ -1023,7 +1053,7 @@ pdcs_unregister_pathentries(void) static int __init pdc_stable_init(void) { - int rc = 0, error = 0; + int rc = 0, error; u32 result; /* find the size of the stable storage */ @@ -1052,6 +1082,10 @@ pdc_stable_init(void) /* Don't forget the root entries */ error = sysfs_create_group(stable_kobj, &pdcs_attr_group); + if (error) { + rc = -ENOMEM; + goto fail_ksetreg; + } /* register the paths kset as a child of the stable kset */ paths_kset = kset_create_and_add("paths", NULL, stable_kobj); diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index ecd870087a3d..bf3405f4289e 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -95,8 +95,6 @@ #define DBG_RES(x...) #endif -#define SBA_INLINE __inline__ - #define DEFAULT_DMA_HINT_REG 0 struct sba_device *sba_list; @@ -332,13 +330,14 @@ static unsigned long ptr_to_pide(struct ioc *ioc, unsigned long *res_ptr, /** * sba_search_bitmap - find free space in IO PDIR resource bitmap * @ioc: IO MMU structure which owns the pdir we are interested in. + * @dev: device to query the bitmap for * @bits_wanted: number of entries we need. * * Find consecutive free bits in resource bitmap. * Each bit represents one entry in the IO Pdir. * Cool perf optimization: search for log2(size) bits at a time. */ -static SBA_INLINE unsigned long +static unsigned long sba_search_bitmap(struct ioc *ioc, struct device *dev, unsigned long bits_wanted) { @@ -431,6 +430,7 @@ sba_search_bitmap(struct ioc *ioc, struct device *dev, /** * sba_alloc_range - find free bits and mark them in IO PDIR resource bitmap * @ioc: IO MMU structure which owns the pdir we are interested in. + * @dev: device for which pages should be alloced * @size: number of bytes to create a mapping for * * Given a size, find consecutive unmarked and then mark those bits in the @@ -490,7 +490,7 @@ sba_alloc_range(struct ioc *ioc, struct device *dev, size_t size) * * clear bits in the ioc's resource map */ -static SBA_INLINE void +static void sba_free_range(struct ioc *ioc, dma_addr_t iova, size_t size) { unsigned long iovp = SBA_IOVP(ioc, iova); @@ -568,7 +568,7 @@ typedef unsigned long space_t; * IOMMU uses little endian for the pdir. */ -static void SBA_INLINE +static void sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba, unsigned long hint) { @@ -609,7 +609,7 @@ sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba, * must be a power of 2. The "Cool perf optimization" in the * allocation routine helps keep that true. */ -static SBA_INLINE void +static void sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt) { u32 iovp = (u32) SBA_IOVP(ioc,iova); @@ -793,6 +793,7 @@ sba_map_page(struct device *dev, struct page *page, unsigned long offset, * @iova: IOVA of driver buffer previously mapped. * @size: number of bytes mapped in driver buffer. * @direction: R/W or both. + * @attrs: attributes * * See Documentation/core-api/dma-api-howto.rst */ @@ -872,6 +873,8 @@ sba_unmap_page(struct device *dev, dma_addr_t iova, size_t size, * @hwdev: instance of PCI owned by the driver that's asking. * @size: number of bytes mapped in driver buffer. * @dma_handle: IOVA of new buffer. + * @gfp: allocation flags + * @attrs: attributes * * See Documentation/core-api/dma-api-howto.rst */ @@ -902,7 +905,8 @@ static void *sba_alloc(struct device *hwdev, size_t size, dma_addr_t *dma_handle * @hwdev: instance of PCI owned by the driver that's asking. * @size: number of bytes mapped in driver buffer. * @vaddr: virtual address IOVA of "consistent" buffer. - * @dma_handler: IO virtual address of "consistent" buffer. + * @dma_handle: IO virtual address of "consistent" buffer. + * @attrs: attributes * * See Documentation/core-api/dma-api-howto.rst */ @@ -938,6 +942,7 @@ int dump_run_sg = 0; * @sglist: array of buffer/length pairs * @nents: number of entries in list * @direction: R/W or both. + * @attrs: attributes * * See Documentation/core-api/dma-api-howto.rst */ @@ -946,7 +951,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, enum dma_data_direction direction, unsigned long attrs) { struct ioc *ioc; - int coalesced, filled = 0; + int filled = 0; unsigned long flags; DBG_RUN_SG("%s() START %d entries\n", __func__, nents); @@ -985,7 +990,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, ** w/o this association, we wouldn't have coherent DMA! ** Access to the virtual address is what forces a two pass algorithm. */ - coalesced = iommu_coalesce_chunks(ioc, dev, sglist, nents, sba_alloc_range); + iommu_coalesce_chunks(ioc, dev, sglist, nents, sba_alloc_range); /* ** Program the I/O Pdir @@ -1022,6 +1027,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, * @sglist: array of buffer/length pairs * @nents: number of entries in list * @direction: R/W or both. + * @attrs: attributes * * See Documentation/core-api/dma-api-howto.rst */ @@ -1229,8 +1235,6 @@ struct ibase_data_struct { static int setup_ibase_imask_callback(struct device *dev, void *data) { - /* lba_set_iregs() is in drivers/parisc/lba_pci.c */ - extern void lba_set_iregs(struct parisc_device *, u32, u32); struct parisc_device *lba = to_parisc_device(dev); struct ibase_data_struct *ibd = data; int rope_num = (lba->hpa.start >> 13) & 0xf; @@ -1992,7 +1996,7 @@ void __init sba_init(void) /** * sba_get_iommu - Assign the iommu pointer for the pci bus controller. - * @dev: The parisc device. + * @pci_hba: The parisc device. * * Returns the appropriate IOMMU data for the given parisc PCI controller. * This is cached and used later for PCI DMA Mapping. @@ -2012,7 +2016,7 @@ void * sba_get_iommu(struct parisc_device *pci_hba) /** * sba_directed_lmmio - return first directed LMMIO range routed to rope - * @pa_dev: The parisc device. + * @pci_hba: The parisc device. * @r: resource PCI host controller wants start/end fields assigned. * * For the given parisc PCI controller, determine if any direct ranges @@ -2054,7 +2058,7 @@ void sba_directed_lmmio(struct parisc_device *pci_hba, struct resource *r) /** * sba_distributed_lmmio - return portion of distributed LMMIO range - * @pa_dev: The parisc device. + * @pci_hba: The parisc device. * @r: resource PCI host controller wants start/end fields assigned. * * For the given parisc PCI controller, return portion of distributed LMMIO diff --git a/drivers/pci/controller/cadence/pci-j721e.c b/drivers/pci/controller/cadence/pci-j721e.c index cc83a8925ce0..e70213c9060a 100644 --- a/drivers/pci/controller/cadence/pci-j721e.c +++ b/drivers/pci/controller/cadence/pci-j721e.c @@ -542,7 +542,7 @@ err_get_sync: return ret; } -static int j721e_pcie_remove(struct platform_device *pdev) +static void j721e_pcie_remove(struct platform_device *pdev) { struct j721e_pcie *pcie = platform_get_drvdata(pdev); struct cdns_pcie *cdns_pcie = pcie->cdns_pcie; @@ -552,13 +552,11 @@ static int j721e_pcie_remove(struct platform_device *pdev) cdns_pcie_disable_phy(cdns_pcie); pm_runtime_put(dev); pm_runtime_disable(dev); - - return 0; } static struct platform_driver j721e_pcie_driver = { .probe = j721e_pcie_probe, - .remove = j721e_pcie_remove, + .remove_new = j721e_pcie_remove, .driver = { .name = "j721e-pcie", .of_match_table = of_j721e_pcie_match, diff --git a/drivers/pci/controller/cadence/pcie-cadence-host.c b/drivers/pci/controller/cadence/pcie-cadence-host.c index 940c7dd701d6..5b14f7ee3c79 100644 --- a/drivers/pci/controller/cadence/pcie-cadence-host.c +++ b/drivers/pci/controller/cadence/pcie-cadence-host.c @@ -12,6 +12,8 @@ #include "pcie-cadence.h" +#define LINK_RETRAIN_TIMEOUT HZ + static u64 bar_max_size[] = { [RP_BAR0] = _ULL(128 * SZ_2G), [RP_BAR1] = SZ_2G, @@ -77,6 +79,27 @@ static struct pci_ops cdns_pcie_host_ops = { .write = pci_generic_config_write, }; +static int cdns_pcie_host_training_complete(struct cdns_pcie *pcie) +{ + u32 pcie_cap_off = CDNS_PCIE_RP_CAP_OFFSET; + unsigned long end_jiffies; + u16 lnk_stat; + + /* Wait for link training to complete. Exit after timeout. */ + end_jiffies = jiffies + LINK_RETRAIN_TIMEOUT; + do { + lnk_stat = cdns_pcie_rp_readw(pcie, pcie_cap_off + PCI_EXP_LNKSTA); + if (!(lnk_stat & PCI_EXP_LNKSTA_LT)) + break; + usleep_range(0, 1000); + } while (time_before(jiffies, end_jiffies)); + + if (!(lnk_stat & PCI_EXP_LNKSTA_LT)) + return 0; + + return -ETIMEDOUT; +} + static int cdns_pcie_host_wait_for_link(struct cdns_pcie *pcie) { struct device *dev = pcie->dev; @@ -118,6 +141,10 @@ static int cdns_pcie_retrain(struct cdns_pcie *pcie) cdns_pcie_rp_writew(pcie, pcie_cap_off + PCI_EXP_LNKCTL, lnk_ctl); + ret = cdns_pcie_host_training_complete(pcie); + if (ret) + return ret; + ret = cdns_pcie_host_wait_for_link(pcie); } return ret; diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index 52906f999f2b..27aaa2a6bf39 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -80,6 +80,7 @@ struct imx6_pcie { struct clk *pcie; struct clk *pcie_aux; struct regmap *iomuxc_gpr; + u16 msi_ctrl; u32 controller_id; struct reset_control *pciephy_reset; struct reset_control *apps_reset; @@ -1178,6 +1179,26 @@ pm_turnoff_sleep: usleep_range(1000, 10000); } +static void imx6_pcie_msi_save_restore(struct imx6_pcie *imx6_pcie, bool save) +{ + u8 offset; + u16 val; + struct dw_pcie *pci = imx6_pcie->pci; + + if (pci_msi_enabled()) { + offset = dw_pcie_find_capability(pci, PCI_CAP_ID_MSI); + if (save) { + val = dw_pcie_readw_dbi(pci, offset + PCI_MSI_FLAGS); + imx6_pcie->msi_ctrl = val; + } else { + dw_pcie_dbi_ro_wr_en(pci); + val = imx6_pcie->msi_ctrl; + dw_pcie_writew_dbi(pci, offset + PCI_MSI_FLAGS, val); + dw_pcie_dbi_ro_wr_dis(pci); + } + } +} + static int imx6_pcie_suspend_noirq(struct device *dev) { struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev); @@ -1186,6 +1207,7 @@ static int imx6_pcie_suspend_noirq(struct device *dev) if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_SUPPORTS_SUSPEND)) return 0; + imx6_pcie_msi_save_restore(imx6_pcie, true); imx6_pcie_pm_turnoff(imx6_pcie); imx6_pcie_stop_link(imx6_pcie->pci); imx6_pcie_host_exit(pp); @@ -1205,6 +1227,7 @@ static int imx6_pcie_resume_noirq(struct device *dev) ret = imx6_pcie_host_init(pp); if (ret) return ret; + imx6_pcie_msi_save_restore(imx6_pcie, false); dw_pcie_setup_rc(pp); if (imx6_pcie->link_is_up) diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c b/drivers/pci/controller/dwc/pci-layerscape-ep.c index c640db60edc6..de4c1758a6c3 100644 --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c @@ -18,6 +18,20 @@ #include "pcie-designware.h" +#define PEX_PF0_CONFIG 0xC0014 +#define PEX_PF0_CFG_READY BIT(0) + +/* PEX PFa PCIE PME and message interrupt registers*/ +#define PEX_PF0_PME_MES_DR 0xC0020 +#define PEX_PF0_PME_MES_DR_LUD BIT(7) +#define PEX_PF0_PME_MES_DR_LDD BIT(9) +#define PEX_PF0_PME_MES_DR_HRD BIT(10) + +#define PEX_PF0_PME_MES_IER 0xC0028 +#define PEX_PF0_PME_MES_IER_LUDIE BIT(7) +#define PEX_PF0_PME_MES_IER_LDDIE BIT(9) +#define PEX_PF0_PME_MES_IER_HRDIE BIT(10) + #define to_ls_pcie_ep(x) dev_get_drvdata((x)->dev) struct ls_pcie_ep_drvdata { @@ -30,8 +44,84 @@ struct ls_pcie_ep { struct dw_pcie *pci; struct pci_epc_features *ls_epc; const struct ls_pcie_ep_drvdata *drvdata; + int irq; + bool big_endian; }; +static u32 ls_lut_readl(struct ls_pcie_ep *pcie, u32 offset) +{ + struct dw_pcie *pci = pcie->pci; + + if (pcie->big_endian) + return ioread32be(pci->dbi_base + offset); + else + return ioread32(pci->dbi_base + offset); +} + +static void ls_lut_writel(struct ls_pcie_ep *pcie, u32 offset, u32 value) +{ + struct dw_pcie *pci = pcie->pci; + + if (pcie->big_endian) + iowrite32be(value, pci->dbi_base + offset); + else + iowrite32(value, pci->dbi_base + offset); +} + +static irqreturn_t ls_pcie_ep_event_handler(int irq, void *dev_id) +{ + struct ls_pcie_ep *pcie = dev_id; + struct dw_pcie *pci = pcie->pci; + u32 val, cfg; + + val = ls_lut_readl(pcie, PEX_PF0_PME_MES_DR); + ls_lut_writel(pcie, PEX_PF0_PME_MES_DR, val); + + if (!val) + return IRQ_NONE; + + if (val & PEX_PF0_PME_MES_DR_LUD) { + cfg = ls_lut_readl(pcie, PEX_PF0_CONFIG); + cfg |= PEX_PF0_CFG_READY; + ls_lut_writel(pcie, PEX_PF0_CONFIG, cfg); + dw_pcie_ep_linkup(&pci->ep); + + dev_dbg(pci->dev, "Link up\n"); + } else if (val & PEX_PF0_PME_MES_DR_LDD) { + dev_dbg(pci->dev, "Link down\n"); + } else if (val & PEX_PF0_PME_MES_DR_HRD) { + dev_dbg(pci->dev, "Hot reset\n"); + } + + return IRQ_HANDLED; +} + +static int ls_pcie_ep_interrupt_init(struct ls_pcie_ep *pcie, + struct platform_device *pdev) +{ + u32 val; + int ret; + + pcie->irq = platform_get_irq_byname(pdev, "pme"); + if (pcie->irq < 0) + return pcie->irq; + + ret = devm_request_irq(&pdev->dev, pcie->irq, ls_pcie_ep_event_handler, + IRQF_SHARED, pdev->name, pcie); + if (ret) { + dev_err(&pdev->dev, "Can't register PCIe IRQ\n"); + return ret; + } + + /* Enable interrupts */ + val = ls_lut_readl(pcie, PEX_PF0_PME_MES_IER); + val |= PEX_PF0_PME_MES_IER_LDDIE | PEX_PF0_PME_MES_IER_HRDIE | + PEX_PF0_PME_MES_IER_LUDIE; + ls_lut_writel(pcie, PEX_PF0_PME_MES_IER, val); + + return 0; +} + static const struct pci_epc_features* ls_pcie_ep_get_features(struct dw_pcie_ep *ep) { @@ -125,6 +215,7 @@ static int __init ls_pcie_ep_probe(struct platform_device *pdev) struct ls_pcie_ep *pcie; struct pci_epc_features *ls_epc; struct resource *dbi_base; + int ret; pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); if (!pcie) @@ -144,6 +235,7 @@ static int __init ls_pcie_ep_probe(struct platform_device *pdev) pci->ops = pcie->drvdata->dw_pcie_ops; ls_epc->bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4); + ls_epc->linkup_notifier = true; pcie->pci = pci; pcie->ls_epc = ls_epc; @@ -155,9 +247,15 @@ static int __init ls_pcie_ep_probe(struct platform_device *pdev) pci->ep.ops = &ls_pcie_ep_ops; + pcie->big_endian = of_property_read_bool(dev->of_node, "big-endian"); + platform_set_drvdata(pdev, pcie); - return dw_pcie_ep_init(&pci->ep); + ret = dw_pcie_ep_init(&pci->ep); + if (ret) + return ret; + + return ls_pcie_ep_interrupt_init(pcie, pdev); } static struct platform_driver ls_pcie_ep_driver = { diff --git a/drivers/pci/controller/dwc/pcie-bt1.c b/drivers/pci/controller/dwc/pcie-bt1.c index 95a723a6fd46..17e696797ff5 100644 --- a/drivers/pci/controller/dwc/pcie-bt1.c +++ b/drivers/pci/controller/dwc/pcie-bt1.c @@ -617,13 +617,11 @@ static int bt1_pcie_probe(struct platform_device *pdev) return bt1_pcie_add_port(btpci); } -static int bt1_pcie_remove(struct platform_device *pdev) +static void bt1_pcie_remove(struct platform_device *pdev) { struct bt1_pcie *btpci = platform_get_drvdata(pdev); bt1_pcie_del_port(btpci); - - return 0; } static const struct of_device_id bt1_pcie_of_match[] = { @@ -634,7 +632,7 @@ MODULE_DEVICE_TABLE(of, bt1_pcie_of_match); static struct platform_driver bt1_pcie_driver = { .probe = bt1_pcie_probe, - .remove = bt1_pcie_remove, + .remove_new = bt1_pcie_remove, .driver = { .name = "bt1-pcie", .of_match_table = bt1_pcie_of_match, diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 9952057c8819..cf61733bf78d 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -485,14 +485,19 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp) if (ret) goto err_remove_edma; - if (!dw_pcie_link_up(pci)) { + if (dw_pcie_link_up(pci)) { + dw_pcie_print_link_status(pci); + } else { ret = dw_pcie_start_link(pci); if (ret) goto err_remove_edma; - } - /* Ignore errors, the link may come up later */ - dw_pcie_wait_for_link(pci); + if (pci->ops && pci->ops->start_link) { + ret = dw_pcie_wait_for_link(pci); + if (ret) + goto err_stop_link; + } + } bridge->sysdata = pp; diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c index 8e33e6e59e68..df092229e97d 100644 --- a/drivers/pci/controller/dwc/pcie-designware.c +++ b/drivers/pci/controller/dwc/pcie-designware.c @@ -644,9 +644,20 @@ void dw_pcie_disable_atu(struct dw_pcie *pci, u32 dir, int index) dw_pcie_writel_atu(pci, dir, index, PCIE_ATU_REGION_CTRL2, 0); } -int dw_pcie_wait_for_link(struct dw_pcie *pci) +void dw_pcie_print_link_status(struct dw_pcie *pci) { u32 offset, val; + + offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); + val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA); + + dev_info(pci->dev, "PCIe Gen.%u x%u link up\n", + FIELD_GET(PCI_EXP_LNKSTA_CLS, val), + FIELD_GET(PCI_EXP_LNKSTA_NLW, val)); +} + +int dw_pcie_wait_for_link(struct dw_pcie *pci) +{ int retries; /* Check if the link is up or not */ @@ -662,12 +673,7 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci) return -ETIMEDOUT; } - offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); - val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA); - - dev_info(pci->dev, "PCIe Gen.%u x%u link up\n", - FIELD_GET(PCI_EXP_LNKSTA_CLS, val), - FIELD_GET(PCI_EXP_LNKSTA_NLW, val)); + dw_pcie_print_link_status(pci); return 0; } diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 79713ce075cc..615660640801 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -429,6 +429,7 @@ void dw_pcie_setup(struct dw_pcie *pci); void dw_pcie_iatu_detect(struct dw_pcie *pci); int dw_pcie_edma_detect(struct dw_pcie *pci); void dw_pcie_edma_remove(struct dw_pcie *pci); +void dw_pcie_print_link_status(struct dw_pcie *pci); static inline void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val) { diff --git a/drivers/pci/controller/dwc/pcie-histb.c b/drivers/pci/controller/dwc/pcie-histb.c index 927ae05dc920..fd484cc7c481 100644 --- a/drivers/pci/controller/dwc/pcie-histb.c +++ b/drivers/pci/controller/dwc/pcie-histb.c @@ -421,7 +421,7 @@ static int histb_pcie_probe(struct platform_device *pdev) return 0; } -static int histb_pcie_remove(struct platform_device *pdev) +static void histb_pcie_remove(struct platform_device *pdev) { struct histb_pcie *hipcie = platform_get_drvdata(pdev); @@ -429,8 +429,6 @@ static int histb_pcie_remove(struct platform_device *pdev) if (hipcie->phy) phy_exit(hipcie->phy); - - return 0; } static const struct of_device_id histb_pcie_of_match[] = { @@ -441,7 +439,7 @@ MODULE_DEVICE_TABLE(of, histb_pcie_of_match); static struct platform_driver histb_pcie_platform_driver = { .probe = histb_pcie_probe, - .remove = histb_pcie_remove, + .remove_new = histb_pcie_remove, .driver = { .name = "histb-pcie", .of_match_table = histb_pcie_of_match, diff --git a/drivers/pci/controller/dwc/pcie-intel-gw.c b/drivers/pci/controller/dwc/pcie-intel-gw.c index 333c33d98a70..9c7caed9e706 100644 --- a/drivers/pci/controller/dwc/pcie-intel-gw.c +++ b/drivers/pci/controller/dwc/pcie-intel-gw.c @@ -340,15 +340,13 @@ static void __intel_pcie_remove(struct intel_pcie *pcie) phy_exit(pcie->phy); } -static int intel_pcie_remove(struct platform_device *pdev) +static void intel_pcie_remove(struct platform_device *pdev) { struct intel_pcie *pcie = platform_get_drvdata(pdev); struct dw_pcie_rp *pp = &pcie->pci.pp; dw_pcie_host_deinit(pp); __intel_pcie_remove(pcie); - - return 0; } static int intel_pcie_suspend_noirq(struct device *dev) @@ -443,7 +441,7 @@ static const struct of_device_id of_intel_pcie_match[] = { static struct platform_driver intel_pcie_driver = { .probe = intel_pcie_probe, - .remove = intel_pcie_remove, + .remove_new = intel_pcie_remove, .driver = { .name = "intel-gw-pcie", .of_match_table = of_intel_pcie_match, diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c b/drivers/pci/controller/dwc/pcie-qcom-ep.c index 19b32839ea26..0fe7f06f2102 100644 --- a/drivers/pci/controller/dwc/pcie-qcom-ep.c +++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c @@ -569,9 +569,11 @@ static irqreturn_t qcom_pcie_ep_global_irq_thread(int irq, void *data) if (FIELD_GET(PARF_INT_ALL_LINK_DOWN, status)) { dev_dbg(dev, "Received Linkdown event\n"); pcie_ep->link_status = QCOM_PCIE_EP_LINK_DOWN; + pci_epc_linkdown(pci->ep.epc); } else if (FIELD_GET(PARF_INT_ALL_BME, status)) { dev_dbg(dev, "Received BME event. Link is enabled!\n"); pcie_ep->link_status = QCOM_PCIE_EP_LINK_ENABLED; + pci_epc_bme_notify(pci->ep.epc); } else if (FIELD_GET(PARF_INT_ALL_PM_TURNOFF, status)) { dev_dbg(dev, "Received PM Turn-off event! Entering L23\n"); val = readl_relaxed(pcie_ep->parf + PARF_PM_CTRL); @@ -784,7 +786,7 @@ err_disable_resources: return ret; } -static int qcom_pcie_ep_remove(struct platform_device *pdev) +static void qcom_pcie_ep_remove(struct platform_device *pdev) { struct qcom_pcie_ep *pcie_ep = platform_get_drvdata(pdev); @@ -794,11 +796,9 @@ static int qcom_pcie_ep_remove(struct platform_device *pdev) debugfs_remove_recursive(pcie_ep->debugfs); if (pcie_ep->link_status == QCOM_PCIE_EP_LINK_DISABLED) - return 0; + return; qcom_pcie_disable_resources(pcie_ep); - - return 0; } static const struct of_device_id qcom_pcie_ep_match[] = { @@ -810,7 +810,7 @@ MODULE_DEVICE_TABLE(of, qcom_pcie_ep_match); static struct platform_driver qcom_pcie_ep_driver = { .probe = qcom_pcie_ep_probe, - .remove = qcom_pcie_ep_remove, + .remove_new = qcom_pcie_ep_remove, .driver = { .name = "qcom-pcie-ep", .of_match_table = qcom_pcie_ep_match, diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 4ab30892f6ef..7a87a47eb7ed 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -61,7 +61,6 @@ /* DBI registers */ #define AXI_MSTR_RESP_COMP_CTRL0 0x818 #define AXI_MSTR_RESP_COMP_CTRL1 0x81c -#define MISC_CONTROL_1_REG 0x8bc /* MHI registers */ #define PARF_DEBUG_CNT_PM_LINKST_IN_L2 0xc04 @@ -132,9 +131,6 @@ /* AXI_MSTR_RESP_COMP_CTRL1 register fields */ #define CFG_BRIDGE_SB_INIT BIT(0) -/* MISC_CONTROL_1_REG register fields */ -#define DBI_RO_WR_EN 1 - /* PCI_EXP_SLTCAP register fields */ #define PCIE_CAP_SLOT_POWER_LIMIT_VAL FIELD_PREP(PCI_EXP_SLTCAP_SPLV, 250) #define PCIE_CAP_SLOT_POWER_LIMIT_SCALE FIELD_PREP(PCI_EXP_SLTCAP_SPLS, 1) @@ -144,7 +140,6 @@ PCI_EXP_SLTCAP_AIP | \ PCI_EXP_SLTCAP_PIP | \ PCI_EXP_SLTCAP_HPS | \ - PCI_EXP_SLTCAP_HPC | \ PCI_EXP_SLTCAP_EIP | \ PCIE_CAP_SLOT_POWER_LIMIT_VAL | \ PCIE_CAP_SLOT_POWER_LIMIT_SCALE) @@ -274,6 +269,20 @@ static int qcom_pcie_start_link(struct dw_pcie *pci) return 0; } +static void qcom_pcie_clear_hpc(struct dw_pcie *pci) +{ + u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); + u32 val; + + dw_pcie_dbi_ro_wr_en(pci); + + val = readl(pci->dbi_base + offset + PCI_EXP_SLTCAP); + val &= ~PCI_EXP_SLTCAP_HPC; + writel(val, pci->dbi_base + offset + PCI_EXP_SLTCAP); + + dw_pcie_dbi_ro_wr_dis(pci); +} + static void qcom_pcie_2_1_0_ltssm_enable(struct qcom_pcie *pcie) { u32 val; @@ -429,6 +438,8 @@ static int qcom_pcie_post_init_2_1_0(struct qcom_pcie *pcie) writel(CFG_BRIDGE_SB_INIT, pci->dbi_base + AXI_MSTR_RESP_COMP_CTRL1); + qcom_pcie_clear_hpc(pcie->pci); + return 0; } @@ -512,6 +523,8 @@ static int qcom_pcie_post_init_1_0_0(struct qcom_pcie *pcie) writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT); } + qcom_pcie_clear_hpc(pcie->pci); + return 0; } @@ -607,6 +620,8 @@ static int qcom_pcie_post_init_2_3_2(struct qcom_pcie *pcie) val |= EN; writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); + qcom_pcie_clear_hpc(pcie->pci); + return 0; } @@ -692,34 +707,6 @@ static int qcom_pcie_init_2_4_0(struct qcom_pcie *pcie) return 0; } -static int qcom_pcie_post_init_2_4_0(struct qcom_pcie *pcie) -{ - u32 val; - - /* enable PCIe clocks and resets */ - val = readl(pcie->parf + PARF_PHY_CTRL); - val &= ~PHY_TEST_PWR_DOWN; - writel(val, pcie->parf + PARF_PHY_CTRL); - - /* change DBI base address */ - writel(0, pcie->parf + PARF_DBI_BASE_ADDR); - - /* MAC PHY_POWERDOWN MUX DISABLE */ - val = readl(pcie->parf + PARF_SYS_CTRL); - val &= ~MAC_PHY_POWERDOWN_IN_P2_D_MUX_EN; - writel(val, pcie->parf + PARF_SYS_CTRL); - - val = readl(pcie->parf + PARF_MHI_CLOCK_RESET_CTRL); - val |= BYPASS; - writel(val, pcie->parf + PARF_MHI_CLOCK_RESET_CTRL); - - val = readl(pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); - val |= EN; - writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); - - return 0; -} - static int qcom_pcie_get_resources_2_3_3(struct qcom_pcie *pcie) { struct qcom_pcie_resources_2_3_3 *res = &pcie->res.v2_3_3; @@ -826,7 +813,9 @@ static int qcom_pcie_post_init_2_3_3(struct qcom_pcie *pcie) writel(0, pcie->parf + PARF_Q2A_FLUSH); writel(PCI_COMMAND_MASTER, pci->dbi_base + PCI_COMMAND); - writel(DBI_RO_WR_EN, pci->dbi_base + MISC_CONTROL_1_REG); + + dw_pcie_dbi_ro_wr_en(pci); + writel(PCIE_CAP_SLOT_VAL, pci->dbi_base + offset + PCI_EXP_SLTCAP); val = readl(pci->dbi_base + offset + PCI_EXP_LNKCAP); @@ -836,6 +825,8 @@ static int qcom_pcie_post_init_2_3_3(struct qcom_pcie *pcie) writel(PCI_EXP_DEVCTL2_COMP_TMOUT_DIS, pci->dbi_base + offset + PCI_EXP_DEVCTL2); + dw_pcie_dbi_ro_wr_dis(pci); + return 0; } @@ -966,6 +957,13 @@ err_disable_regulators: return ret; } +static int qcom_pcie_post_init_2_7_0(struct qcom_pcie *pcie) +{ + qcom_pcie_clear_hpc(pcie->pci); + + return 0; +} + static void qcom_pcie_deinit_2_7_0(struct qcom_pcie *pcie) { struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0; @@ -1136,6 +1134,7 @@ static int qcom_pcie_post_init_2_9_0(struct qcom_pcie *pcie) writel(0, pcie->parf + PARF_Q2A_FLUSH); dw_pcie_dbi_ro_wr_en(pci); + writel(PCIE_CAP_SLOT_VAL, pci->dbi_base + offset + PCI_EXP_SLTCAP); val = readl(pci->dbi_base + offset + PCI_EXP_LNKCAP); @@ -1145,6 +1144,8 @@ static int qcom_pcie_post_init_2_9_0(struct qcom_pcie *pcie) writel(PCI_EXP_DEVCTL2_COMP_TMOUT_DIS, pci->dbi_base + offset + PCI_EXP_DEVCTL2); + dw_pcie_dbi_ro_wr_dis(pci); + for (i = 0; i < 256; i++) writel(0, pcie->parf + PARF_BDF_TO_SID_TABLE_N + (4 * i)); @@ -1251,7 +1252,7 @@ static const struct qcom_pcie_ops ops_2_3_2 = { static const struct qcom_pcie_ops ops_2_4_0 = { .get_resources = qcom_pcie_get_resources_2_4_0, .init = qcom_pcie_init_2_4_0, - .post_init = qcom_pcie_post_init_2_4_0, + .post_init = qcom_pcie_post_init_2_3_2, .deinit = qcom_pcie_deinit_2_4_0, .ltssm_enable = qcom_pcie_2_3_2_ltssm_enable, }; @@ -1269,6 +1270,7 @@ static const struct qcom_pcie_ops ops_2_3_3 = { static const struct qcom_pcie_ops ops_2_7_0 = { .get_resources = qcom_pcie_get_resources_2_7_0, .init = qcom_pcie_init_2_7_0, + .post_init = qcom_pcie_post_init_2_7_0, .deinit = qcom_pcie_deinit_2_7_0, .ltssm_enable = qcom_pcie_2_3_2_ltssm_enable, }; @@ -1277,6 +1279,7 @@ static const struct qcom_pcie_ops ops_2_7_0 = { static const struct qcom_pcie_ops ops_1_9_0 = { .get_resources = qcom_pcie_get_resources_2_7_0, .init = qcom_pcie_init_2_7_0, + .post_init = qcom_pcie_post_init_2_7_0, .deinit = qcom_pcie_deinit_2_7_0, .ltssm_enable = qcom_pcie_2_3_2_ltssm_enable, .config_sid = qcom_pcie_config_sid_1_9_0, diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c index 4fdadc7b045f..e1db909f53ec 100644 --- a/drivers/pci/controller/dwc/pcie-tegra194.c +++ b/drivers/pci/controller/dwc/pcie-tegra194.c @@ -2296,13 +2296,13 @@ fail: return ret; } -static int tegra_pcie_dw_remove(struct platform_device *pdev) +static void tegra_pcie_dw_remove(struct platform_device *pdev) { struct tegra_pcie_dw *pcie = platform_get_drvdata(pdev); if (pcie->of_data->mode == DW_PCIE_RC_TYPE) { if (!pcie->link_state) - return 0; + return; debugfs_remove_recursive(pcie->debugfs); tegra_pcie_deinit_controller(pcie); @@ -2316,8 +2316,6 @@ static int tegra_pcie_dw_remove(struct platform_device *pdev) tegra_bpmp_put(pcie->bpmp); if (pcie->pex_refclk_sel_gpiod) gpiod_set_value(pcie->pex_refclk_sel_gpiod, 0); - - return 0; } static int tegra_pcie_dw_suspend_late(struct device *dev) @@ -2511,7 +2509,7 @@ static const struct dev_pm_ops tegra_pcie_dw_pm_ops = { static struct platform_driver tegra_pcie_dw_driver = { .probe = tegra_pcie_dw_probe, - .remove = tegra_pcie_dw_remove, + .remove_new = tegra_pcie_dw_remove, .shutdown = tegra_pcie_dw_shutdown, .driver = { .name = "tegra194-pcie", diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c index 513d8edf3a5c..71ecd7ddcc8a 100644 --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c @@ -1927,7 +1927,7 @@ static int advk_pcie_probe(struct platform_device *pdev) return 0; } -static int advk_pcie_remove(struct platform_device *pdev) +static void advk_pcie_remove(struct platform_device *pdev) { struct advk_pcie *pcie = platform_get_drvdata(pdev); struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); @@ -1989,8 +1989,6 @@ static int advk_pcie_remove(struct platform_device *pdev) /* Disable phy */ advk_pcie_disable_phy(pcie); - - return 0; } static const struct of_device_id advk_pcie_of_match_table[] = { @@ -2005,7 +2003,7 @@ static struct platform_driver advk_pcie_driver = { .of_match_table = advk_pcie_of_match_table, }, .probe = advk_pcie_probe, - .remove = advk_pcie_remove, + .remove_new = advk_pcie_remove, }; module_platform_driver(advk_pcie_driver); diff --git a/drivers/pci/controller/pci-ftpci100.c b/drivers/pci/controller/pci-ftpci100.c index ecd3009df586..6e7981d2ed5e 100644 --- a/drivers/pci/controller/pci-ftpci100.c +++ b/drivers/pci/controller/pci-ftpci100.c @@ -429,22 +429,12 @@ static int faraday_pci_probe(struct platform_device *pdev) p->dev = dev; /* Retrieve and enable optional clocks */ - clk = devm_clk_get(dev, "PCLK"); + clk = devm_clk_get_enabled(dev, "PCLK"); if (IS_ERR(clk)) return PTR_ERR(clk); - ret = clk_prepare_enable(clk); - if (ret) { - dev_err(dev, "could not prepare PCLK\n"); - return ret; - } - p->bus_clk = devm_clk_get(dev, "PCICLK"); + p->bus_clk = devm_clk_get_enabled(dev, "PCICLK"); if (IS_ERR(p->bus_clk)) return PTR_ERR(p->bus_clk); - ret = clk_prepare_enable(p->bus_clk); - if (ret) { - dev_err(dev, "could not prepare PCICLK\n"); - return ret; - } p->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(p->base)) diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c index 1dc209f6f53a..c931b1b07b1d 100644 --- a/drivers/pci/controller/pci-mvebu.c +++ b/drivers/pci/controller/pci-mvebu.c @@ -1649,7 +1649,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev) return pci_host_probe(bridge); } -static int mvebu_pcie_remove(struct platform_device *pdev) +static void mvebu_pcie_remove(struct platform_device *pdev) { struct mvebu_pcie *pcie = platform_get_drvdata(pdev); struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); @@ -1707,8 +1707,6 @@ static int mvebu_pcie_remove(struct platform_device *pdev) /* Power down card and disable clocks. Must be the last step. */ mvebu_pcie_powerdown(port); } - - return 0; } static const struct of_device_id mvebu_pcie_of_match_table[] = { @@ -1730,7 +1728,7 @@ static struct platform_driver mvebu_pcie_driver = { .pm = &mvebu_pcie_pm_ops, }, .probe = mvebu_pcie_probe, - .remove = mvebu_pcie_remove, + .remove_new = mvebu_pcie_remove, }; module_platform_driver(mvebu_pcie_driver); diff --git a/drivers/pci/controller/pci-tegra.c b/drivers/pci/controller/pci-tegra.c index 79630885b9c8..038d974a318e 100644 --- a/drivers/pci/controller/pci-tegra.c +++ b/drivers/pci/controller/pci-tegra.c @@ -2680,7 +2680,7 @@ put_resources: return err; } -static int tegra_pcie_remove(struct platform_device *pdev) +static void tegra_pcie_remove(struct platform_device *pdev) { struct tegra_pcie *pcie = platform_get_drvdata(pdev); struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); @@ -2701,8 +2701,6 @@ static int tegra_pcie_remove(struct platform_device *pdev) list_for_each_entry_safe(port, tmp, &pcie->ports, list) tegra_pcie_port_free(port); - - return 0; } static int tegra_pcie_pm_suspend(struct device *dev) @@ -2808,6 +2806,6 @@ static struct platform_driver tegra_pcie_driver = { .pm = &tegra_pcie_pm_ops, }, .probe = tegra_pcie_probe, - .remove = tegra_pcie_remove, + .remove_new = tegra_pcie_remove, }; module_platform_driver(tegra_pcie_driver); diff --git a/drivers/pci/controller/pci-xgene-msi.c b/drivers/pci/controller/pci-xgene-msi.c index d7987b281f79..0234e528b9a5 100644 --- a/drivers/pci/controller/pci-xgene-msi.c +++ b/drivers/pci/controller/pci-xgene-msi.c @@ -348,7 +348,7 @@ static void xgene_msi_isr(struct irq_desc *desc) static enum cpuhp_state pci_xgene_online; -static int xgene_msi_remove(struct platform_device *pdev) +static void xgene_msi_remove(struct platform_device *pdev) { struct xgene_msi *msi = platform_get_drvdata(pdev); @@ -362,8 +362,6 @@ static int xgene_msi_remove(struct platform_device *pdev) msi->bitmap = NULL; xgene_free_domains(msi); - - return 0; } static int xgene_msi_hwirq_alloc(unsigned int cpu) @@ -521,7 +519,7 @@ static struct platform_driver xgene_msi_driver = { .of_match_table = xgene_msi_match_table, }, .probe = xgene_msi_probe, - .remove = xgene_msi_remove, + .remove_new = xgene_msi_remove, }; static int __init xgene_pcie_msi_init(void) diff --git a/drivers/pci/controller/pcie-altera-msi.c b/drivers/pci/controller/pcie-altera-msi.c index 65e8a20cc442..6ad5427490b5 100644 --- a/drivers/pci/controller/pcie-altera-msi.c +++ b/drivers/pci/controller/pcie-altera-msi.c @@ -197,7 +197,7 @@ static void altera_free_domains(struct altera_msi *msi) irq_domain_remove(msi->inner_domain); } -static int altera_msi_remove(struct platform_device *pdev) +static void altera_msi_remove(struct platform_device *pdev) { struct altera_msi *msi = platform_get_drvdata(pdev); @@ -207,7 +207,6 @@ static int altera_msi_remove(struct platform_device *pdev) altera_free_domains(msi); platform_set_drvdata(pdev, NULL); - return 0; } static int altera_msi_probe(struct platform_device *pdev) @@ -275,7 +274,7 @@ static struct platform_driver altera_msi_driver = { .of_match_table = altera_msi_of_match, }, .probe = altera_msi_probe, - .remove = altera_msi_remove, + .remove_new = altera_msi_remove, }; static int __init altera_msi_init(void) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index 18b2361d6462..c95a29fff8bf 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -806,7 +806,7 @@ static int altera_pcie_probe(struct platform_device *pdev) return pci_host_probe(bridge); } -static int altera_pcie_remove(struct platform_device *pdev) +static void altera_pcie_remove(struct platform_device *pdev) { struct altera_pcie *pcie = platform_get_drvdata(pdev); struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); @@ -814,13 +814,11 @@ static int altera_pcie_remove(struct platform_device *pdev) pci_stop_root_bus(bridge->bus); pci_remove_root_bus(bridge->bus); altera_pcie_irq_teardown(pcie); - - return 0; } static struct platform_driver altera_pcie_driver = { .probe = altera_pcie_probe, - .remove = altera_pcie_remove, + .remove_new = altera_pcie_remove, .driver = { .name = "altera-pcie", .of_match_table = altera_pcie_of_match, diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c index edf283e2b5dd..f593a422bd63 100644 --- a/drivers/pci/controller/pcie-brcmstb.c +++ b/drivers/pci/controller/pcie-brcmstb.c @@ -1396,7 +1396,7 @@ static void __brcm_pcie_remove(struct brcm_pcie *pcie) clk_disable_unprepare(pcie->clk); } -static int brcm_pcie_remove(struct platform_device *pdev) +static void brcm_pcie_remove(struct platform_device *pdev) { struct brcm_pcie *pcie = platform_get_drvdata(pdev); struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); @@ -1404,8 +1404,6 @@ static int brcm_pcie_remove(struct platform_device *pdev) pci_stop_root_bus(bridge->bus); pci_remove_root_bus(bridge->bus); __brcm_pcie_remove(pcie); - - return 0; } static const int pcie_offsets[] = { @@ -1612,7 +1610,7 @@ static const struct dev_pm_ops brcm_pcie_pm_ops = { static struct platform_driver brcm_pcie_driver = { .probe = brcm_pcie_probe, - .remove = brcm_pcie_remove, + .remove_new = brcm_pcie_remove, .driver = { .name = "brcm-pcie", .of_match_table = brcm_pcie_match, diff --git a/drivers/pci/controller/pcie-hisi-error.c b/drivers/pci/controller/pcie-hisi-error.c index 7d88eb696b06..ad9d5ffcd9e3 100644 --- a/drivers/pci/controller/pcie-hisi-error.c +++ b/drivers/pci/controller/pcie-hisi-error.c @@ -299,13 +299,11 @@ static int hisi_pcie_error_handler_probe(struct platform_device *pdev) return 0; } -static int hisi_pcie_error_handler_remove(struct platform_device *pdev) +static void hisi_pcie_error_handler_remove(struct platform_device *pdev) { struct hisi_pcie_error_private *priv = platform_get_drvdata(pdev); ghes_unregister_vendor_record_notifier(&priv->nb); - - return 0; } static const struct acpi_device_id hisi_pcie_acpi_match[] = { @@ -319,7 +317,7 @@ static struct platform_driver hisi_pcie_error_handler_driver = { .acpi_match_table = hisi_pcie_acpi_match, }, .probe = hisi_pcie_error_handler_probe, - .remove = hisi_pcie_error_handler_remove, + .remove_new = hisi_pcie_error_handler_remove, }; module_platform_driver(hisi_pcie_error_handler_driver); diff --git a/drivers/pci/controller/pcie-iproc-platform.c b/drivers/pci/controller/pcie-iproc-platform.c index 4142a73e611d..acdc583d2980 100644 --- a/drivers/pci/controller/pcie-iproc-platform.c +++ b/drivers/pci/controller/pcie-iproc-platform.c @@ -114,11 +114,11 @@ static int iproc_pltfm_pcie_probe(struct platform_device *pdev) return 0; } -static int iproc_pltfm_pcie_remove(struct platform_device *pdev) +static void iproc_pltfm_pcie_remove(struct platform_device *pdev) { struct iproc_pcie *pcie = platform_get_drvdata(pdev); - return iproc_pcie_remove(pcie); + iproc_pcie_remove(pcie); } static void iproc_pltfm_pcie_shutdown(struct platform_device *pdev) @@ -134,7 +134,7 @@ static struct platform_driver iproc_pltfm_pcie_driver = { .of_match_table = of_match_ptr(iproc_pcie_of_match_table), }, .probe = iproc_pltfm_pcie_probe, - .remove = iproc_pltfm_pcie_remove, + .remove_new = iproc_pltfm_pcie_remove, .shutdown = iproc_pltfm_pcie_shutdown, }; module_platform_driver(iproc_pltfm_pcie_driver); diff --git a/drivers/pci/controller/pcie-iproc.c b/drivers/pci/controller/pcie-iproc.c index 83029bdfd884..bd1c98b68851 100644 --- a/drivers/pci/controller/pcie-iproc.c +++ b/drivers/pci/controller/pcie-iproc.c @@ -1537,7 +1537,7 @@ err_exit_phy: } EXPORT_SYMBOL(iproc_pcie_setup); -int iproc_pcie_remove(struct iproc_pcie *pcie) +void iproc_pcie_remove(struct iproc_pcie *pcie) { struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); @@ -1548,8 +1548,6 @@ int iproc_pcie_remove(struct iproc_pcie *pcie) phy_power_off(pcie->phy); phy_exit(pcie->phy); - - return 0; } EXPORT_SYMBOL(iproc_pcie_remove); diff --git a/drivers/pci/controller/pcie-iproc.h b/drivers/pci/controller/pcie-iproc.h index dcca315897c8..969ded03b8c2 100644 --- a/drivers/pci/controller/pcie-iproc.h +++ b/drivers/pci/controller/pcie-iproc.h @@ -111,7 +111,7 @@ struct iproc_pcie { }; int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res); -int iproc_pcie_remove(struct iproc_pcie *pcie); +void iproc_pcie_remove(struct iproc_pcie *pcie); int iproc_pcie_shutdown(struct iproc_pcie *pcie); #ifdef CONFIG_PCIE_IPROC_MSI diff --git a/drivers/pci/controller/pcie-mediatek-gen3.c b/drivers/pci/controller/pcie-mediatek-gen3.c index b8612ce5f4d0..e0e27645fdf4 100644 --- a/drivers/pci/controller/pcie-mediatek-gen3.c +++ b/drivers/pci/controller/pcie-mediatek-gen3.c @@ -943,7 +943,7 @@ static int mtk_pcie_probe(struct platform_device *pdev) return 0; } -static int mtk_pcie_remove(struct platform_device *pdev) +static void mtk_pcie_remove(struct platform_device *pdev) { struct mtk_gen3_pcie *pcie = platform_get_drvdata(pdev); struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); @@ -955,8 +955,6 @@ static int mtk_pcie_remove(struct platform_device *pdev) mtk_pcie_irq_teardown(pcie); mtk_pcie_power_down(pcie); - - return 0; } static void mtk_pcie_irq_save(struct mtk_gen3_pcie *pcie) @@ -1069,7 +1067,7 @@ MODULE_DEVICE_TABLE(of, mtk_pcie_of_match); static struct platform_driver mtk_pcie_driver = { .probe = mtk_pcie_probe, - .remove = mtk_pcie_remove, + .remove_new = mtk_pcie_remove, .driver = { .name = "mtk-pcie-gen3", .of_match_table = mtk_pcie_of_match, diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c index 31de7a29192c..66a8f73296fc 100644 --- a/drivers/pci/controller/pcie-mediatek.c +++ b/drivers/pci/controller/pcie-mediatek.c @@ -1134,7 +1134,7 @@ static void mtk_pcie_free_resources(struct mtk_pcie *pcie) pci_free_resource_list(windows); } -static int mtk_pcie_remove(struct platform_device *pdev) +static void mtk_pcie_remove(struct platform_device *pdev) { struct mtk_pcie *pcie = platform_get_drvdata(pdev); struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); @@ -1146,8 +1146,6 @@ static int mtk_pcie_remove(struct platform_device *pdev) mtk_pcie_irq_teardown(pcie); mtk_pcie_put_resources(pcie); - - return 0; } static int mtk_pcie_suspend_noirq(struct device *dev) @@ -1239,7 +1237,7 @@ MODULE_DEVICE_TABLE(of, mtk_pcie_ids); static struct platform_driver mtk_pcie_driver = { .probe = mtk_pcie_probe, - .remove = mtk_pcie_remove, + .remove_new = mtk_pcie_remove, .driver = { .name = "mtk-pcie", .of_match_table = mtk_pcie_ids, diff --git a/drivers/pci/controller/pcie-mt7621.c b/drivers/pci/controller/pcie-mt7621.c index a445ec314375..79e225edb42a 100644 --- a/drivers/pci/controller/pcie-mt7621.c +++ b/drivers/pci/controller/pcie-mt7621.c @@ -524,15 +524,13 @@ remove_resets: return err; } -static int mt7621_pcie_remove(struct platform_device *pdev) +static void mt7621_pcie_remove(struct platform_device *pdev) { struct mt7621_pcie *pcie = platform_get_drvdata(pdev); struct mt7621_pcie_port *port; list_for_each_entry(port, &pcie->ports, list) reset_control_put(port->pcie_rst); - - return 0; } static const struct of_device_id mt7621_pcie_ids[] = { @@ -543,7 +541,7 @@ MODULE_DEVICE_TABLE(of, mt7621_pcie_ids); static struct platform_driver mt7621_pcie_driver = { .probe = mt7621_pcie_probe, - .remove = mt7621_pcie_remove, + .remove_new = mt7621_pcie_remove, .driver = { .name = "mt7621-pci", .of_match_table = mt7621_pcie_ids, diff --git a/drivers/pci/controller/pcie-rcar-host.c b/drivers/pci/controller/pcie-rcar-host.c index e80e56b2a842..88975e40ee2f 100644 --- a/drivers/pci/controller/pcie-rcar-host.c +++ b/drivers/pci/controller/pcie-rcar-host.c @@ -41,21 +41,6 @@ struct rcar_msi { int irq2; }; -#ifdef CONFIG_ARM -/* - * Here we keep a static copy of the remapped PCIe controller address. - * This is only used on aarch32 systems, all of which have one single - * PCIe controller, to provide quick access to the PCIe controller in - * the L1 link state fixup function, called from the ARM fault handler. - */ -static void __iomem *pcie_base; -/* - * Static copy of PCIe device pointer, so we can check whether the - * device is runtime suspended or not. - */ -static struct device *pcie_dev; -#endif - /* Structure representing the PCIe interface */ struct rcar_pcie_host { struct rcar_pcie pcie; @@ -684,7 +669,7 @@ static void rcar_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) } static struct irq_chip rcar_msi_bottom_chip = { - .name = "Rcar MSI", + .name = "R-Car MSI", .irq_ack = rcar_msi_irq_ack, .irq_mask = rcar_msi_irq_mask, .irq_unmask = rcar_msi_irq_unmask, @@ -813,7 +798,7 @@ static int rcar_pcie_enable_msi(struct rcar_pcie_host *host) /* * Setup MSI data target using RC base address address, which - * is guaranteed to be in the low 32bit range on any RCar HW. + * is guaranteed to be in the low 32bit range on any R-Car HW. */ rcar_pci_write_reg(pcie, lower_32_bits(res.start) | MSIFE, PCIEMSIALR); rcar_pci_write_reg(pcie, upper_32_bits(res.start), PCIEMSIAUR); @@ -879,12 +864,6 @@ static int rcar_pcie_get_resources(struct rcar_pcie_host *host) } host->msi.irq2 = i; -#ifdef CONFIG_ARM - /* Cache static copy for L1 link state fixup hook on aarch32 */ - pcie_base = pcie->base; - pcie_dev = pcie->dev; -#endif - return 0; err_irq2: diff --git a/drivers/pci/controller/pcie-rockchip-ep.c b/drivers/pci/controller/pcie-rockchip-ep.c index d1a200b93b2b..0af0e965fb57 100644 --- a/drivers/pci/controller/pcie-rockchip-ep.c +++ b/drivers/pci/controller/pcie-rockchip-ep.c @@ -61,70 +61,38 @@ static void rockchip_pcie_clear_ep_ob_atu(struct rockchip_pcie *rockchip, ROCKCHIP_PCIE_AT_OB_REGION_DESC0(region)); rockchip_pcie_write(rockchip, 0, ROCKCHIP_PCIE_AT_OB_REGION_DESC1(region)); - rockchip_pcie_write(rockchip, 0, - ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR0(region)); - rockchip_pcie_write(rockchip, 0, - ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR1(region)); } static void rockchip_pcie_prog_ep_ob_atu(struct rockchip_pcie *rockchip, u8 fn, - u32 r, u32 type, u64 cpu_addr, - u64 pci_addr, size_t size) + u32 r, u64 cpu_addr, u64 pci_addr, + size_t size) { - u64 sz = 1ULL << fls64(size - 1); - int num_pass_bits = ilog2(sz); - u32 addr0, addr1, desc0, desc1; - bool is_nor_msg = (type == AXI_WRAPPER_NOR_MSG); + int num_pass_bits = fls64(size - 1); + u32 addr0, addr1, desc0; - /* The minimal region size is 1MB */ if (num_pass_bits < 8) num_pass_bits = 8; - cpu_addr -= rockchip->mem_res->start; - addr0 = ((is_nor_msg ? 0x10 : (num_pass_bits - 1)) & - PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) | - (lower_32_bits(cpu_addr) & PCIE_CORE_OB_REGION_ADDR0_LO_ADDR); - addr1 = upper_32_bits(is_nor_msg ? cpu_addr : pci_addr); - desc0 = ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN(fn) | type; - desc1 = 0; - - if (is_nor_msg) { - rockchip_pcie_write(rockchip, 0, - ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r)); - rockchip_pcie_write(rockchip, 0, - ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r)); - rockchip_pcie_write(rockchip, desc0, - ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r)); - rockchip_pcie_write(rockchip, desc1, - ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r)); - } else { - /* PCI bus address region */ - rockchip_pcie_write(rockchip, addr0, - ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r)); - rockchip_pcie_write(rockchip, addr1, - ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r)); - rockchip_pcie_write(rockchip, desc0, - ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r)); - rockchip_pcie_write(rockchip, desc1, - ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r)); - - addr0 = - ((num_pass_bits - 1) & PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) | - (lower_32_bits(cpu_addr) & - PCIE_CORE_OB_REGION_ADDR0_LO_ADDR); - addr1 = upper_32_bits(cpu_addr); - } + addr0 = ((num_pass_bits - 1) & PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) | + (lower_32_bits(pci_addr) & PCIE_CORE_OB_REGION_ADDR0_LO_ADDR); + addr1 = upper_32_bits(pci_addr); + desc0 = ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN(fn) | AXI_WRAPPER_MEM_WRITE; - /* CPU bus address region */ + /* PCI bus address region */ rockchip_pcie_write(rockchip, addr0, - ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR0(r)); + ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r)); rockchip_pcie_write(rockchip, addr1, - ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR1(r)); + ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r)); + rockchip_pcie_write(rockchip, desc0, + ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r)); + rockchip_pcie_write(rockchip, 0, + ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r)); } static int rockchip_pcie_ep_write_header(struct pci_epc *epc, u8 fn, u8 vfn, struct pci_epf_header *hdr) { + u32 reg; struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); struct rockchip_pcie *rockchip = &ep->rockchip; @@ -137,8 +105,9 @@ static int rockchip_pcie_ep_write_header(struct pci_epc *epc, u8 fn, u8 vfn, PCIE_CORE_CONFIG_VENDOR); } - rockchip_pcie_write(rockchip, hdr->deviceid << 16, - ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + PCI_VENDOR_ID); + reg = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_DID_VID); + reg = (reg & 0xFFFF) | (hdr->deviceid << 16); + rockchip_pcie_write(rockchip, reg, PCIE_EP_CONFIG_DID_VID); rockchip_pcie_write(rockchip, hdr->revid | @@ -256,26 +225,20 @@ static void rockchip_pcie_ep_clear_bar(struct pci_epc *epc, u8 fn, u8 vfn, ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar)); } +static inline u32 rockchip_ob_region(phys_addr_t addr) +{ + return (addr >> ilog2(SZ_1M)) & 0x1f; +} + static int rockchip_pcie_ep_map_addr(struct pci_epc *epc, u8 fn, u8 vfn, phys_addr_t addr, u64 pci_addr, size_t size) { struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); struct rockchip_pcie *pcie = &ep->rockchip; - u32 r; - - r = find_first_zero_bit(&ep->ob_region_map, BITS_PER_LONG); - /* - * Region 0 is reserved for configuration space and shouldn't - * be used elsewhere per TRM, so leave it out. - */ - if (r >= ep->max_regions - 1) { - dev_err(&epc->dev, "no free outbound region\n"); - return -EINVAL; - } + u32 r = rockchip_ob_region(addr); - rockchip_pcie_prog_ep_ob_atu(pcie, fn, r, AXI_WRAPPER_MEM_WRITE, addr, - pci_addr, size); + rockchip_pcie_prog_ep_ob_atu(pcie, fn, r, addr, pci_addr, size); set_bit(r, &ep->ob_region_map); ep->ob_addr[r] = addr; @@ -290,15 +253,11 @@ static void rockchip_pcie_ep_unmap_addr(struct pci_epc *epc, u8 fn, u8 vfn, struct rockchip_pcie *rockchip = &ep->rockchip; u32 r; - for (r = 0; r < ep->max_regions - 1; r++) + for (r = 0; r < ep->max_regions; r++) if (ep->ob_addr[r] == addr) break; - /* - * Region 0 is reserved for configuration space and shouldn't - * be used elsewhere per TRM, so leave it out. - */ - if (r == ep->max_regions - 1) + if (r == ep->max_regions) return; rockchip_pcie_clear_ep_ob_atu(rockchip, r); @@ -312,15 +271,15 @@ static int rockchip_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, u8 vfn, { struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); struct rockchip_pcie *rockchip = &ep->rockchip; - u16 flags; + u32 flags; flags = rockchip_pcie_read(rockchip, ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + ROCKCHIP_PCIE_EP_MSI_CTRL_REG); flags &= ~ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_MASK; flags |= - ((multi_msg_cap << 1) << ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET) | - PCI_MSI_FLAGS_64BIT; + (multi_msg_cap << ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET) | + (PCI_MSI_FLAGS_64BIT << ROCKCHIP_PCIE_EP_MSI_FLAGS_OFFSET); flags &= ~ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP; rockchip_pcie_write(rockchip, flags, ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + @@ -332,7 +291,7 @@ static int rockchip_pcie_ep_get_msi(struct pci_epc *epc, u8 fn, u8 vfn) { struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); struct rockchip_pcie *rockchip = &ep->rockchip; - u16 flags; + u32 flags; flags = rockchip_pcie_read(rockchip, ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + @@ -345,48 +304,25 @@ static int rockchip_pcie_ep_get_msi(struct pci_epc *epc, u8 fn, u8 vfn) } static void rockchip_pcie_ep_assert_intx(struct rockchip_pcie_ep *ep, u8 fn, - u8 intx, bool is_asserted) + u8 intx, bool do_assert) { struct rockchip_pcie *rockchip = &ep->rockchip; - u32 r = ep->max_regions - 1; - u32 offset; - u32 status; - u8 msg_code; - - if (unlikely(ep->irq_pci_addr != ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR || - ep->irq_pci_fn != fn)) { - rockchip_pcie_prog_ep_ob_atu(rockchip, fn, r, - AXI_WRAPPER_NOR_MSG, - ep->irq_phys_addr, 0, 0); - ep->irq_pci_addr = ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR; - ep->irq_pci_fn = fn; - } intx &= 3; - if (is_asserted) { + + if (do_assert) { ep->irq_pending |= BIT(intx); - msg_code = ROCKCHIP_PCIE_MSG_CODE_ASSERT_INTA + intx; + rockchip_pcie_write(rockchip, + PCIE_CLIENT_INT_IN_ASSERT | + PCIE_CLIENT_INT_PEND_ST_PEND, + PCIE_CLIENT_LEGACY_INT_CTRL); } else { ep->irq_pending &= ~BIT(intx); - msg_code = ROCKCHIP_PCIE_MSG_CODE_DEASSERT_INTA + intx; + rockchip_pcie_write(rockchip, + PCIE_CLIENT_INT_IN_DEASSERT | + PCIE_CLIENT_INT_PEND_ST_NORMAL, + PCIE_CLIENT_LEGACY_INT_CTRL); } - - status = rockchip_pcie_read(rockchip, - ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + - ROCKCHIP_PCIE_EP_CMD_STATUS); - status &= ROCKCHIP_PCIE_EP_CMD_STATUS_IS; - - if ((status != 0) ^ (ep->irq_pending != 0)) { - status ^= ROCKCHIP_PCIE_EP_CMD_STATUS_IS; - rockchip_pcie_write(rockchip, status, - ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + - ROCKCHIP_PCIE_EP_CMD_STATUS); - } - - offset = - ROCKCHIP_PCIE_MSG_ROUTING(ROCKCHIP_PCIE_MSG_ROUTING_LOCAL_INTX) | - ROCKCHIP_PCIE_MSG_CODE(msg_code) | ROCKCHIP_PCIE_MSG_NO_DATA; - writel(0, ep->irq_cpu_addr + offset); } static int rockchip_pcie_ep_send_legacy_irq(struct rockchip_pcie_ep *ep, u8 fn, @@ -416,9 +352,10 @@ static int rockchip_pcie_ep_send_msi_irq(struct rockchip_pcie_ep *ep, u8 fn, u8 interrupt_num) { struct rockchip_pcie *rockchip = &ep->rockchip; - u16 flags, mme, data, data_mask; + u32 flags, mme, data, data_mask; u8 msi_count; - u64 pci_addr, pci_addr_mask = 0xff; + u64 pci_addr; + u32 r; /* Check MSI enable bit */ flags = rockchip_pcie_read(&ep->rockchip, @@ -452,21 +389,20 @@ static int rockchip_pcie_ep_send_msi_irq(struct rockchip_pcie_ep *ep, u8 fn, ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + ROCKCHIP_PCIE_EP_MSI_CTRL_REG + PCI_MSI_ADDRESS_LO); - pci_addr &= GENMASK_ULL(63, 2); /* Set the outbound region if needed. */ - if (unlikely(ep->irq_pci_addr != (pci_addr & ~pci_addr_mask) || + if (unlikely(ep->irq_pci_addr != (pci_addr & PCIE_ADDR_MASK) || ep->irq_pci_fn != fn)) { - rockchip_pcie_prog_ep_ob_atu(rockchip, fn, ep->max_regions - 1, - AXI_WRAPPER_MEM_WRITE, + r = rockchip_ob_region(ep->irq_phys_addr); + rockchip_pcie_prog_ep_ob_atu(rockchip, fn, r, ep->irq_phys_addr, - pci_addr & ~pci_addr_mask, - pci_addr_mask + 1); - ep->irq_pci_addr = (pci_addr & ~pci_addr_mask); + pci_addr & PCIE_ADDR_MASK, + ~PCIE_ADDR_MASK + 1); + ep->irq_pci_addr = (pci_addr & PCIE_ADDR_MASK); ep->irq_pci_fn = fn; } - writew(data, ep->irq_cpu_addr + (pci_addr & pci_addr_mask)); + writew(data, ep->irq_cpu_addr + (pci_addr & ~PCIE_ADDR_MASK)); return 0; } @@ -506,6 +442,7 @@ static const struct pci_epc_features rockchip_pcie_epc_features = { .linkup_notifier = false, .msi_capable = true, .msix_capable = false, + .align = 256, }; static const struct pci_epc_features* @@ -547,6 +484,8 @@ static int rockchip_pcie_parse_ep_dt(struct rockchip_pcie *rockchip, if (err < 0 || ep->max_regions > MAX_REGION_LIMIT) ep->max_regions = MAX_REGION_LIMIT; + ep->ob_region_map = 0; + err = of_property_read_u8(dev->of_node, "max-functions", &ep->epc->max_functions); if (err < 0) @@ -567,7 +506,9 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev) struct rockchip_pcie *rockchip; struct pci_epc *epc; size_t max_regions; - int err; + struct pci_epc_mem_window *windows = NULL; + int err, i; + u32 cfg_msi, cfg_msix_cp; ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL); if (!ep) @@ -614,15 +555,27 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev) /* Only enable function 0 by default */ rockchip_pcie_write(rockchip, BIT(0), PCIE_CORE_PHY_FUNC_CFG); - err = pci_epc_mem_init(epc, rockchip->mem_res->start, - resource_size(rockchip->mem_res), PAGE_SIZE); + windows = devm_kcalloc(dev, ep->max_regions, + sizeof(struct pci_epc_mem_window), GFP_KERNEL); + if (!windows) { + err = -ENOMEM; + goto err_uninit_port; + } + for (i = 0; i < ep->max_regions; i++) { + windows[i].phys_base = rockchip->mem_res->start + (SZ_1M * i); + windows[i].size = SZ_1M; + windows[i].page_size = SZ_1M; + } + err = pci_epc_multi_mem_init(epc, windows, ep->max_regions); + devm_kfree(dev, windows); + if (err < 0) { dev_err(dev, "failed to initialize the memory space\n"); goto err_uninit_port; } ep->irq_cpu_addr = pci_epc_mem_alloc_addr(epc, &ep->irq_phys_addr, - SZ_128K); + SZ_1M); if (!ep->irq_cpu_addr) { dev_err(dev, "failed to reserve memory space for MSI\n"); err = -ENOMEM; @@ -631,6 +584,32 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev) ep->irq_pci_addr = ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR; + /* + * MSI-X is not supported but the controller still advertises the MSI-X + * capability by default, which can lead to the Root Complex side + * allocating MSI-X vectors which cannot be used. Avoid this by skipping + * the MSI-X capability entry in the PCIe capabilities linked-list: get + * the next pointer from the MSI-X entry and set that in the MSI + * capability entry (which is the previous entry). This way the MSI-X + * entry is skipped (left out of the linked-list) and not advertised. + */ + cfg_msi = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_BASE + + ROCKCHIP_PCIE_EP_MSI_CTRL_REG); + + cfg_msi &= ~ROCKCHIP_PCIE_EP_MSI_CP1_MASK; + + cfg_msix_cp = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_BASE + + ROCKCHIP_PCIE_EP_MSIX_CAP_REG) & + ROCKCHIP_PCIE_EP_MSIX_CAP_CP_MASK; + + cfg_msi |= cfg_msix_cp; + + rockchip_pcie_write(rockchip, cfg_msi, + PCIE_EP_CONFIG_BASE + ROCKCHIP_PCIE_EP_MSI_CTRL_REG); + + rockchip_pcie_write(rockchip, PCIE_CLIENT_CONF_ENABLE, + PCIE_CLIENT_CONFIG); + return 0; err_epc_mem_exit: pci_epc_mem_exit(epc); diff --git a/drivers/pci/controller/pcie-rockchip-host.c b/drivers/pci/controller/pcie-rockchip-host.c index c96c0f454570..2438bc9b3a1a 100644 --- a/drivers/pci/controller/pcie-rockchip-host.c +++ b/drivers/pci/controller/pcie-rockchip-host.c @@ -1009,7 +1009,7 @@ err_set_vpcie: return err; } -static int rockchip_pcie_remove(struct platform_device *pdev) +static void rockchip_pcie_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct rockchip_pcie *rockchip = dev_get_drvdata(dev); @@ -1029,8 +1029,6 @@ static int rockchip_pcie_remove(struct platform_device *pdev) regulator_disable(rockchip->vpcie3v3); regulator_disable(rockchip->vpcie1v8); regulator_disable(rockchip->vpcie0v9); - - return 0; } static const struct dev_pm_ops rockchip_pcie_pm_ops = { @@ -1051,7 +1049,7 @@ static struct platform_driver rockchip_pcie_driver = { .pm = &rockchip_pcie_pm_ops, }, .probe = rockchip_pcie_probe, - .remove = rockchip_pcie_remove, + .remove_new = rockchip_pcie_remove, }; module_platform_driver(rockchip_pcie_driver); diff --git a/drivers/pci/controller/pcie-rockchip.c b/drivers/pci/controller/pcie-rockchip.c index 990a00e08bc5..1aa84035a8bc 100644 --- a/drivers/pci/controller/pcie-rockchip.c +++ b/drivers/pci/controller/pcie-rockchip.c @@ -14,6 +14,7 @@ #include <linux/clk.h> #include <linux/delay.h> #include <linux/gpio/consumer.h> +#include <linux/iopoll.h> #include <linux/of_pci.h> #include <linux/phy/phy.h> #include <linux/platform_device.h> @@ -153,6 +154,12 @@ int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip) } EXPORT_SYMBOL_GPL(rockchip_pcie_parse_dt); +#define rockchip_pcie_read_addr(addr) rockchip_pcie_read(rockchip, addr) +/* 100 ms max wait time for PHY PLLs to lock */ +#define RK_PHY_PLL_LOCK_TIMEOUT_US 100000 +/* Sleep should be less than 20ms */ +#define RK_PHY_PLL_LOCK_SLEEP_US 1000 + int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) { struct device *dev = rockchip->dev; @@ -254,6 +261,16 @@ int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) } } + err = readx_poll_timeout(rockchip_pcie_read_addr, + PCIE_CLIENT_SIDE_BAND_STATUS, + regs, !(regs & PCIE_CLIENT_PHY_ST), + RK_PHY_PLL_LOCK_SLEEP_US, + RK_PHY_PLL_LOCK_TIMEOUT_US); + if (err) { + dev_err(dev, "PHY PLLs could not lock, %d\n", err); + goto err_power_off_phy; + } + /* * Please don't reorder the deassert sequence of the following * four reset pins. diff --git a/drivers/pci/controller/pcie-rockchip.h b/drivers/pci/controller/pcie-rockchip.h index 32c3a859c26b..fe0333778fd9 100644 --- a/drivers/pci/controller/pcie-rockchip.h +++ b/drivers/pci/controller/pcie-rockchip.h @@ -38,6 +38,13 @@ #define PCIE_CLIENT_MODE_EP HIWORD_UPDATE(0x0040, 0) #define PCIE_CLIENT_GEN_SEL_1 HIWORD_UPDATE(0x0080, 0) #define PCIE_CLIENT_GEN_SEL_2 HIWORD_UPDATE_BIT(0x0080) +#define PCIE_CLIENT_LEGACY_INT_CTRL (PCIE_CLIENT_BASE + 0x0c) +#define PCIE_CLIENT_INT_IN_ASSERT HIWORD_UPDATE_BIT(0x0002) +#define PCIE_CLIENT_INT_IN_DEASSERT HIWORD_UPDATE(0x0002, 0) +#define PCIE_CLIENT_INT_PEND_ST_PEND HIWORD_UPDATE_BIT(0x0001) +#define PCIE_CLIENT_INT_PEND_ST_NORMAL HIWORD_UPDATE(0x0001, 0) +#define PCIE_CLIENT_SIDE_BAND_STATUS (PCIE_CLIENT_BASE + 0x20) +#define PCIE_CLIENT_PHY_ST BIT(12) #define PCIE_CLIENT_DEBUG_OUT_0 (PCIE_CLIENT_BASE + 0x3c) #define PCIE_CLIENT_DEBUG_LTSSM_MASK GENMASK(5, 0) #define PCIE_CLIENT_DEBUG_LTSSM_L1 0x18 @@ -132,7 +139,10 @@ #define PCIE_RC_RP_ATS_BASE 0x400000 #define PCIE_RC_CONFIG_NORMAL_BASE 0x800000 +#define PCIE_EP_PF_CONFIG_REGS_BASE 0x800000 #define PCIE_RC_CONFIG_BASE 0xa00000 +#define PCIE_EP_CONFIG_BASE 0xa00000 +#define PCIE_EP_CONFIG_DID_VID (PCIE_EP_CONFIG_BASE + 0x00) #define PCIE_RC_CONFIG_RID_CCR (PCIE_RC_CONFIG_BASE + 0x08) #define PCIE_RC_CONFIG_DCR (PCIE_RC_CONFIG_BASE + 0xc4) #define PCIE_RC_CONFIG_DCR_CSPL_SHIFT 18 @@ -148,10 +158,11 @@ #define PCIE_RC_CONFIG_THP_CAP (PCIE_RC_CONFIG_BASE + 0x274) #define PCIE_RC_CONFIG_THP_CAP_NEXT_MASK GENMASK(31, 20) +#define PCIE_ADDR_MASK 0xffffff00 #define PCIE_CORE_AXI_CONF_BASE 0xc00000 #define PCIE_CORE_OB_REGION_ADDR0 (PCIE_CORE_AXI_CONF_BASE + 0x0) #define PCIE_CORE_OB_REGION_ADDR0_NUM_BITS 0x3f -#define PCIE_CORE_OB_REGION_ADDR0_LO_ADDR 0xffffff00 +#define PCIE_CORE_OB_REGION_ADDR0_LO_ADDR PCIE_ADDR_MASK #define PCIE_CORE_OB_REGION_ADDR1 (PCIE_CORE_AXI_CONF_BASE + 0x4) #define PCIE_CORE_OB_REGION_DESC0 (PCIE_CORE_AXI_CONF_BASE + 0x8) #define PCIE_CORE_OB_REGION_DESC1 (PCIE_CORE_AXI_CONF_BASE + 0xc) @@ -159,7 +170,7 @@ #define PCIE_CORE_AXI_INBOUND_BASE 0xc00800 #define PCIE_RP_IB_ADDR0 (PCIE_CORE_AXI_INBOUND_BASE + 0x0) #define PCIE_CORE_IB_REGION_ADDR0_NUM_BITS 0x3f -#define PCIE_CORE_IB_REGION_ADDR0_LO_ADDR 0xffffff00 +#define PCIE_CORE_IB_REGION_ADDR0_LO_ADDR PCIE_ADDR_MASK #define PCIE_RP_IB_ADDR1 (PCIE_CORE_AXI_INBOUND_BASE + 0x4) /* Size of one AXI Region (not Region 0) */ @@ -216,21 +227,28 @@ #define ROCKCHIP_PCIE_EP_CMD_STATUS 0x4 #define ROCKCHIP_PCIE_EP_CMD_STATUS_IS BIT(19) #define ROCKCHIP_PCIE_EP_MSI_CTRL_REG 0x90 +#define ROCKCHIP_PCIE_EP_MSI_CP1_OFFSET 8 +#define ROCKCHIP_PCIE_EP_MSI_CP1_MASK GENMASK(15, 8) +#define ROCKCHIP_PCIE_EP_MSI_FLAGS_OFFSET 16 #define ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET 17 #define ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_MASK GENMASK(19, 17) #define ROCKCHIP_PCIE_EP_MSI_CTRL_MME_OFFSET 20 #define ROCKCHIP_PCIE_EP_MSI_CTRL_MME_MASK GENMASK(22, 20) #define ROCKCHIP_PCIE_EP_MSI_CTRL_ME BIT(16) #define ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP BIT(24) +#define ROCKCHIP_PCIE_EP_MSIX_CAP_REG 0xb0 +#define ROCKCHIP_PCIE_EP_MSIX_CAP_CP_OFFSET 8 +#define ROCKCHIP_PCIE_EP_MSIX_CAP_CP_MASK GENMASK(15, 8) #define ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR 0x1 #define ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR 0x3 -#define ROCKCHIP_PCIE_EP_FUNC_BASE(fn) (((fn) << 12) & GENMASK(19, 12)) +#define ROCKCHIP_PCIE_EP_FUNC_BASE(fn) \ + (PCIE_EP_PF_CONFIG_REGS_BASE + (((fn) << 12) & GENMASK(19, 12))) +#define ROCKCHIP_PCIE_EP_VIRT_FUNC_BASE(fn) \ + (PCIE_EP_PF_CONFIG_REGS_BASE + 0x10000 + (((fn) << 12) & GENMASK(19, 12))) #define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar) \ - (PCIE_RC_RP_ATS_BASE + 0x0840 + (fn) * 0x0040 + (bar) * 0x0008) + (PCIE_CORE_AXI_CONF_BASE + 0x0828 + (fn) * 0x0040 + (bar) * 0x0008) #define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar) \ - (PCIE_RC_RP_ATS_BASE + 0x0844 + (fn) * 0x0040 + (bar) * 0x0008) -#define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r) \ - (PCIE_RC_RP_ATS_BASE + 0x0000 + ((r) & 0x1f) * 0x0020) + (PCIE_CORE_AXI_CONF_BASE + 0x082c + (fn) * 0x0040 + (bar) * 0x0008) #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN_MASK GENMASK(19, 12) #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN(devfn) \ (((devfn) << 12) & \ @@ -238,20 +256,21 @@ #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_BUS_MASK GENMASK(27, 20) #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_BUS(bus) \ (((bus) << 20) & ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_BUS_MASK) +#define PCIE_RC_EP_ATR_OB_REGIONS_1_32 (PCIE_CORE_AXI_CONF_BASE + 0x0020) +#define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r) \ + (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0000 + ((r) & 0x1f) * 0x0020) #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r) \ - (PCIE_RC_RP_ATS_BASE + 0x0004 + ((r) & 0x1f) * 0x0020) + (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0004 + ((r) & 0x1f) * 0x0020) #define ROCKCHIP_PCIE_AT_OB_REGION_DESC0_HARDCODED_RID BIT(23) #define ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN_MASK GENMASK(31, 24) #define ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN(devfn) \ (((devfn) << 24) & ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN_MASK) #define ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r) \ - (PCIE_RC_RP_ATS_BASE + 0x0008 + ((r) & 0x1f) * 0x0020) -#define ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r) \ - (PCIE_RC_RP_ATS_BASE + 0x000c + ((r) & 0x1f) * 0x0020) -#define ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR0(r) \ - (PCIE_RC_RP_ATS_BASE + 0x0018 + ((r) & 0x1f) * 0x0020) -#define ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR1(r) \ - (PCIE_RC_RP_ATS_BASE + 0x001c + ((r) & 0x1f) * 0x0020) + (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0008 + ((r) & 0x1f) * 0x0020) +#define ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r) \ + (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x000c + ((r) & 0x1f) * 0x0020) +#define ROCKCHIP_PCIE_AT_OB_REGION_DESC2(r) \ + (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0010 + ((r) & 0x1f) * 0x0020) #define ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG0(fn) \ (PCIE_CORE_CTRL_MGMT_BASE + 0x0240 + (fn) * 0x0008) diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c index 990630ec57c6..e718a816d481 100644 --- a/drivers/pci/controller/vmd.c +++ b/drivers/pci/controller/vmd.c @@ -927,7 +927,8 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features) if (!list_empty(&child->devices)) { dev = list_first_entry(&child->devices, struct pci_dev, bus_list); - if (pci_reset_bus(dev)) + ret = pci_reset_bus(dev); + if (ret) pci_warn(dev, "can't reset device: %d\n", ret); break; @@ -1036,6 +1037,13 @@ static void vmd_remove(struct pci_dev *dev) ida_simple_remove(&vmd_instance_ida, vmd->instance); } +static void vmd_shutdown(struct pci_dev *dev) +{ + struct vmd_dev *vmd = pci_get_drvdata(dev); + + vmd_remove_irq_domain(vmd); +} + #ifdef CONFIG_PM_SLEEP static int vmd_suspend(struct device *dev) { @@ -1101,6 +1109,7 @@ static struct pci_driver vmd_drv = { .id_table = vmd_ids, .probe = vmd_probe, .remove = vmd_remove, + .shutdown = vmd_shutdown, .driver = { .pm = &vmd_dev_pm_ops, }, diff --git a/drivers/pci/endpoint/functions/Kconfig b/drivers/pci/endpoint/functions/Kconfig index 9fd560886871..0c9cea0698d7 100644 --- a/drivers/pci/endpoint/functions/Kconfig +++ b/drivers/pci/endpoint/functions/Kconfig @@ -27,7 +27,7 @@ config PCI_EPF_NTB If in doubt, say "N" to disable Endpoint NTB driver. config PCI_EPF_VNTB - tristate "PCI Endpoint NTB driver" + tristate "PCI Endpoint Virtual NTB driver" depends on PCI_ENDPOINT depends on NTB select CONFIGFS_FS @@ -37,3 +37,13 @@ config PCI_EPF_VNTB between PCI Root Port and PCIe Endpoint. If in doubt, say "N" to disable Endpoint NTB driver. + +config PCI_EPF_MHI + tristate "PCI Endpoint driver for MHI bus" + depends on PCI_ENDPOINT && MHI_BUS_EP + help + Enable this configuration option to enable the PCI Endpoint + driver for Modem Host Interface (MHI) bus in Qualcomm Endpoint + devices such as SDX55. + + If in doubt, say "N" to disable Endpoint driver for MHI bus. diff --git a/drivers/pci/endpoint/functions/Makefile b/drivers/pci/endpoint/functions/Makefile index 5c13001deaba..696473fce50e 100644 --- a/drivers/pci/endpoint/functions/Makefile +++ b/drivers/pci/endpoint/functions/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_PCI_EPF_TEST) += pci-epf-test.o obj-$(CONFIG_PCI_EPF_NTB) += pci-epf-ntb.o obj-$(CONFIG_PCI_EPF_VNTB) += pci-epf-vntb.o +obj-$(CONFIG_PCI_EPF_MHI) += pci-epf-mhi.o diff --git a/drivers/pci/endpoint/functions/pci-epf-mhi.c b/drivers/pci/endpoint/functions/pci-epf-mhi.c new file mode 100644 index 000000000000..9c1f5a154fbd --- /dev/null +++ b/drivers/pci/endpoint/functions/pci-epf-mhi.c @@ -0,0 +1,458 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PCI EPF driver for MHI Endpoint devices + * + * Copyright (C) 2023 Linaro Ltd. + * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> + */ + +#include <linux/mhi_ep.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/pci-epc.h> +#include <linux/pci-epf.h> + +#define MHI_VERSION_1_0 0x01000000 + +#define to_epf_mhi(cntrl) container_of(cntrl, struct pci_epf_mhi, cntrl) + +struct pci_epf_mhi_ep_info { + const struct mhi_ep_cntrl_config *config; + struct pci_epf_header *epf_header; + enum pci_barno bar_num; + u32 epf_flags; + u32 msi_count; + u32 mru; +}; + +#define MHI_EP_CHANNEL_CONFIG(ch_num, ch_name, direction) \ + { \ + .num = ch_num, \ + .name = ch_name, \ + .dir = direction, \ + } + +#define MHI_EP_CHANNEL_CONFIG_UL(ch_num, ch_name) \ + MHI_EP_CHANNEL_CONFIG(ch_num, ch_name, DMA_TO_DEVICE) + +#define MHI_EP_CHANNEL_CONFIG_DL(ch_num, ch_name) \ + MHI_EP_CHANNEL_CONFIG(ch_num, ch_name, DMA_FROM_DEVICE) + +static const struct mhi_ep_channel_config mhi_v1_channels[] = { + MHI_EP_CHANNEL_CONFIG_UL(0, "LOOPBACK"), + MHI_EP_CHANNEL_CONFIG_DL(1, "LOOPBACK"), + MHI_EP_CHANNEL_CONFIG_UL(2, "SAHARA"), + MHI_EP_CHANNEL_CONFIG_DL(3, "SAHARA"), + MHI_EP_CHANNEL_CONFIG_UL(4, "DIAG"), + MHI_EP_CHANNEL_CONFIG_DL(5, "DIAG"), + MHI_EP_CHANNEL_CONFIG_UL(6, "SSR"), + MHI_EP_CHANNEL_CONFIG_DL(7, "SSR"), + MHI_EP_CHANNEL_CONFIG_UL(8, "QDSS"), + MHI_EP_CHANNEL_CONFIG_DL(9, "QDSS"), + MHI_EP_CHANNEL_CONFIG_UL(10, "EFS"), + MHI_EP_CHANNEL_CONFIG_DL(11, "EFS"), + MHI_EP_CHANNEL_CONFIG_UL(12, "MBIM"), + MHI_EP_CHANNEL_CONFIG_DL(13, "MBIM"), + MHI_EP_CHANNEL_CONFIG_UL(14, "QMI"), + MHI_EP_CHANNEL_CONFIG_DL(15, "QMI"), + MHI_EP_CHANNEL_CONFIG_UL(16, "QMI"), + MHI_EP_CHANNEL_CONFIG_DL(17, "QMI"), + MHI_EP_CHANNEL_CONFIG_UL(18, "IP-CTRL-1"), + MHI_EP_CHANNEL_CONFIG_DL(19, "IP-CTRL-1"), + MHI_EP_CHANNEL_CONFIG_UL(20, "IPCR"), + MHI_EP_CHANNEL_CONFIG_DL(21, "IPCR"), + MHI_EP_CHANNEL_CONFIG_UL(32, "DUN"), + MHI_EP_CHANNEL_CONFIG_DL(33, "DUN"), + MHI_EP_CHANNEL_CONFIG_UL(46, "IP_SW0"), + MHI_EP_CHANNEL_CONFIG_DL(47, "IP_SW0"), +}; + +static const struct mhi_ep_cntrl_config mhi_v1_config = { + .max_channels = 128, + .num_channels = ARRAY_SIZE(mhi_v1_channels), + .ch_cfg = mhi_v1_channels, + .mhi_version = MHI_VERSION_1_0, +}; + +static struct pci_epf_header sdx55_header = { + .vendorid = PCI_VENDOR_ID_QCOM, + .deviceid = 0x0306, + .baseclass_code = PCI_BASE_CLASS_COMMUNICATION, + .subclass_code = PCI_CLASS_COMMUNICATION_MODEM & 0xff, + .interrupt_pin = PCI_INTERRUPT_INTA, +}; + +static const struct pci_epf_mhi_ep_info sdx55_info = { + .config = &mhi_v1_config, + .epf_header = &sdx55_header, + .bar_num = BAR_0, + .epf_flags = PCI_BASE_ADDRESS_MEM_TYPE_32, + .msi_count = 32, + .mru = 0x8000, +}; + +struct pci_epf_mhi { + const struct pci_epf_mhi_ep_info *info; + struct mhi_ep_cntrl mhi_cntrl; + struct pci_epf *epf; + struct mutex lock; + void __iomem *mmio; + resource_size_t mmio_phys; + u32 mmio_size; + int irq; +}; + +static int __pci_epf_mhi_alloc_map(struct mhi_ep_cntrl *mhi_cntrl, u64 pci_addr, + phys_addr_t *paddr, void __iomem **vaddr, + size_t offset, size_t size) +{ + struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl); + struct pci_epf *epf = epf_mhi->epf; + struct pci_epc *epc = epf->epc; + int ret; + + *vaddr = pci_epc_mem_alloc_addr(epc, paddr, size + offset); + if (!*vaddr) + return -ENOMEM; + + ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, *paddr, + pci_addr - offset, size + offset); + if (ret) { + pci_epc_mem_free_addr(epc, *paddr, *vaddr, size + offset); + return ret; + } + + *paddr = *paddr + offset; + *vaddr = *vaddr + offset; + + return 0; +} + +static int pci_epf_mhi_alloc_map(struct mhi_ep_cntrl *mhi_cntrl, u64 pci_addr, + phys_addr_t *paddr, void __iomem **vaddr, + size_t size) +{ + struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl); + struct pci_epc *epc = epf_mhi->epf->epc; + size_t offset = pci_addr & (epc->mem->window.page_size - 1); + + return __pci_epf_mhi_alloc_map(mhi_cntrl, pci_addr, paddr, vaddr, + offset, size); +} + +static void __pci_epf_mhi_unmap_free(struct mhi_ep_cntrl *mhi_cntrl, + u64 pci_addr, phys_addr_t paddr, + void __iomem *vaddr, size_t offset, + size_t size) +{ + struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl); + struct pci_epf *epf = epf_mhi->epf; + struct pci_epc *epc = epf->epc; + + pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, paddr - offset); + pci_epc_mem_free_addr(epc, paddr - offset, vaddr - offset, + size + offset); +} + +static void pci_epf_mhi_unmap_free(struct mhi_ep_cntrl *mhi_cntrl, u64 pci_addr, + phys_addr_t paddr, void __iomem *vaddr, + size_t size) +{ + struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl); + struct pci_epf *epf = epf_mhi->epf; + struct pci_epc *epc = epf->epc; + size_t offset = pci_addr & (epc->mem->window.page_size - 1); + + __pci_epf_mhi_unmap_free(mhi_cntrl, pci_addr, paddr, vaddr, offset, + size); +} + +static void pci_epf_mhi_raise_irq(struct mhi_ep_cntrl *mhi_cntrl, u32 vector) +{ + struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl); + struct pci_epf *epf = epf_mhi->epf; + struct pci_epc *epc = epf->epc; + + /* + * MHI supplies 0 based MSI vectors but the API expects the vector + * number to start from 1, so we need to increment the vector by 1. + */ + pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no, PCI_EPC_IRQ_MSI, + vector + 1); +} + +static int pci_epf_mhi_read_from_host(struct mhi_ep_cntrl *mhi_cntrl, u64 from, + void *to, size_t size) +{ + struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl); + size_t offset = from % SZ_4K; + void __iomem *tre_buf; + phys_addr_t tre_phys; + int ret; + + mutex_lock(&epf_mhi->lock); + + ret = __pci_epf_mhi_alloc_map(mhi_cntrl, from, &tre_phys, &tre_buf, + offset, size); + if (ret) { + mutex_unlock(&epf_mhi->lock); + return ret; + } + + memcpy_fromio(to, tre_buf, size); + + __pci_epf_mhi_unmap_free(mhi_cntrl, from, tre_phys, tre_buf, offset, + size); + + mutex_unlock(&epf_mhi->lock); + + return 0; +} + +static int pci_epf_mhi_write_to_host(struct mhi_ep_cntrl *mhi_cntrl, + void *from, u64 to, size_t size) +{ + struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl); + size_t offset = to % SZ_4K; + void __iomem *tre_buf; + phys_addr_t tre_phys; + int ret; + + mutex_lock(&epf_mhi->lock); + + ret = __pci_epf_mhi_alloc_map(mhi_cntrl, to, &tre_phys, &tre_buf, + offset, size); + if (ret) { + mutex_unlock(&epf_mhi->lock); + return ret; + } + + memcpy_toio(tre_buf, from, size); + + __pci_epf_mhi_unmap_free(mhi_cntrl, to, tre_phys, tre_buf, offset, + size); + + mutex_unlock(&epf_mhi->lock); + + return 0; +} + +static int pci_epf_mhi_core_init(struct pci_epf *epf) +{ + struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf); + const struct pci_epf_mhi_ep_info *info = epf_mhi->info; + struct pci_epf_bar *epf_bar = &epf->bar[info->bar_num]; + struct pci_epc *epc = epf->epc; + struct device *dev = &epf->dev; + int ret; + + epf_bar->phys_addr = epf_mhi->mmio_phys; + epf_bar->size = epf_mhi->mmio_size; + epf_bar->barno = info->bar_num; + epf_bar->flags = info->epf_flags; + ret = pci_epc_set_bar(epc, epf->func_no, epf->vfunc_no, epf_bar); + if (ret) { + dev_err(dev, "Failed to set BAR: %d\n", ret); + return ret; + } + + ret = pci_epc_set_msi(epc, epf->func_no, epf->vfunc_no, + order_base_2(info->msi_count)); + if (ret) { + dev_err(dev, "Failed to set MSI configuration: %d\n", ret); + return ret; + } + + ret = pci_epc_write_header(epc, epf->func_no, epf->vfunc_no, + epf->header); + if (ret) { + dev_err(dev, "Failed to set Configuration header: %d\n", ret); + return ret; + } + + return 0; +} + +static int pci_epf_mhi_link_up(struct pci_epf *epf) +{ + struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf); + const struct pci_epf_mhi_ep_info *info = epf_mhi->info; + struct mhi_ep_cntrl *mhi_cntrl = &epf_mhi->mhi_cntrl; + struct pci_epc *epc = epf->epc; + struct device *dev = &epf->dev; + int ret; + + mhi_cntrl->mmio = epf_mhi->mmio; + mhi_cntrl->irq = epf_mhi->irq; + mhi_cntrl->mru = info->mru; + + /* Assign the struct dev of PCI EP as MHI controller device */ + mhi_cntrl->cntrl_dev = epc->dev.parent; + mhi_cntrl->raise_irq = pci_epf_mhi_raise_irq; + mhi_cntrl->alloc_map = pci_epf_mhi_alloc_map; + mhi_cntrl->unmap_free = pci_epf_mhi_unmap_free; + mhi_cntrl->read_from_host = pci_epf_mhi_read_from_host; + mhi_cntrl->write_to_host = pci_epf_mhi_write_to_host; + + /* Register the MHI EP controller */ + ret = mhi_ep_register_controller(mhi_cntrl, info->config); + if (ret) { + dev_err(dev, "Failed to register MHI EP controller: %d\n", ret); + return ret; + } + + return 0; +} + +static int pci_epf_mhi_link_down(struct pci_epf *epf) +{ + struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf); + struct mhi_ep_cntrl *mhi_cntrl = &epf_mhi->mhi_cntrl; + + if (mhi_cntrl->mhi_dev) { + mhi_ep_power_down(mhi_cntrl); + mhi_ep_unregister_controller(mhi_cntrl); + } + + return 0; +} + +static int pci_epf_mhi_bme(struct pci_epf *epf) +{ + struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf); + struct mhi_ep_cntrl *mhi_cntrl = &epf_mhi->mhi_cntrl; + struct device *dev = &epf->dev; + int ret; + + /* + * Power up the MHI EP stack if link is up and stack is in power down + * state. + */ + if (!mhi_cntrl->enabled && mhi_cntrl->mhi_dev) { + ret = mhi_ep_power_up(mhi_cntrl); + if (ret) { + dev_err(dev, "Failed to power up MHI EP: %d\n", ret); + mhi_ep_unregister_controller(mhi_cntrl); + } + } + + return 0; +} + +static int pci_epf_mhi_bind(struct pci_epf *epf) +{ + struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf); + struct pci_epc *epc = epf->epc; + struct platform_device *pdev = to_platform_device(epc->dev.parent); + struct resource *res; + int ret; + + /* Get MMIO base address from Endpoint controller */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mmio"); + epf_mhi->mmio_phys = res->start; + epf_mhi->mmio_size = resource_size(res); + + epf_mhi->mmio = ioremap(epf_mhi->mmio_phys, epf_mhi->mmio_size); + if (!epf_mhi->mmio) + return -ENOMEM; + + ret = platform_get_irq_byname(pdev, "doorbell"); + if (ret < 0) { + iounmap(epf_mhi->mmio); + return ret; + } + + epf_mhi->irq = ret; + + return 0; +} + +static void pci_epf_mhi_unbind(struct pci_epf *epf) +{ + struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf); + const struct pci_epf_mhi_ep_info *info = epf_mhi->info; + struct pci_epf_bar *epf_bar = &epf->bar[info->bar_num]; + struct mhi_ep_cntrl *mhi_cntrl = &epf_mhi->mhi_cntrl; + struct pci_epc *epc = epf->epc; + + /* + * Forcefully power down the MHI EP stack. Only way to bring the MHI EP + * stack back to working state after successive bind is by getting BME + * from host. + */ + if (mhi_cntrl->mhi_dev) { + mhi_ep_power_down(mhi_cntrl); + mhi_ep_unregister_controller(mhi_cntrl); + } + + iounmap(epf_mhi->mmio); + pci_epc_clear_bar(epc, epf->func_no, epf->vfunc_no, epf_bar); +} + +static struct pci_epc_event_ops pci_epf_mhi_event_ops = { + .core_init = pci_epf_mhi_core_init, + .link_up = pci_epf_mhi_link_up, + .link_down = pci_epf_mhi_link_down, + .bme = pci_epf_mhi_bme, +}; + +static int pci_epf_mhi_probe(struct pci_epf *epf, + const struct pci_epf_device_id *id) +{ + struct pci_epf_mhi_ep_info *info = + (struct pci_epf_mhi_ep_info *)id->driver_data; + struct pci_epf_mhi *epf_mhi; + struct device *dev = &epf->dev; + + epf_mhi = devm_kzalloc(dev, sizeof(*epf_mhi), GFP_KERNEL); + if (!epf_mhi) + return -ENOMEM; + + epf->header = info->epf_header; + epf_mhi->info = info; + epf_mhi->epf = epf; + + epf->event_ops = &pci_epf_mhi_event_ops; + + mutex_init(&epf_mhi->lock); + + epf_set_drvdata(epf, epf_mhi); + + return 0; +} + +static const struct pci_epf_device_id pci_epf_mhi_ids[] = { + { + .name = "sdx55", .driver_data = (kernel_ulong_t)&sdx55_info, + }, + {}, +}; + +static struct pci_epf_ops pci_epf_mhi_ops = { + .unbind = pci_epf_mhi_unbind, + .bind = pci_epf_mhi_bind, +}; + +static struct pci_epf_driver pci_epf_mhi_driver = { + .driver.name = "pci_epf_mhi", + .probe = pci_epf_mhi_probe, + .id_table = pci_epf_mhi_ids, + .ops = &pci_epf_mhi_ops, + .owner = THIS_MODULE, +}; + +static int __init pci_epf_mhi_init(void) +{ + return pci_epf_register_driver(&pci_epf_mhi_driver); +} +module_init(pci_epf_mhi_init); + +static void __exit pci_epf_mhi_exit(void) +{ + pci_epf_unregister_driver(&pci_epf_mhi_driver); +} +module_exit(pci_epf_mhi_exit); + +MODULE_DESCRIPTION("PCI EPF driver for MHI Endpoint devices"); +MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pci/endpoint/functions/pci-epf-ntb.c b/drivers/pci/endpoint/functions/pci-epf-ntb.c index 9a00448c7e61..9aac2c6f3bb9 100644 --- a/drivers/pci/endpoint/functions/pci-epf-ntb.c +++ b/drivers/pci/endpoint/functions/pci-epf-ntb.c @@ -2075,11 +2075,13 @@ static struct config_group *epf_ntb_add_cfs(struct pci_epf *epf, /** * epf_ntb_probe() - Probe NTB function driver * @epf: NTB endpoint function device + * @id: NTB endpoint function device ID * * Probe NTB function driver when endpoint function bus detects a NTB * endpoint function. */ -static int epf_ntb_probe(struct pci_epf *epf) +static int epf_ntb_probe(struct pci_epf *epf, + const struct pci_epf_device_id *id) { struct epf_ntb *ntb; struct device *dev; diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c index 0f9d2ec822ac..1f0d2b84296a 100644 --- a/drivers/pci/endpoint/functions/pci-epf-test.c +++ b/drivers/pci/endpoint/functions/pci-epf-test.c @@ -54,6 +54,9 @@ struct pci_epf_test { struct delayed_work cmd_handler; struct dma_chan *dma_chan_tx; struct dma_chan *dma_chan_rx; + struct dma_chan *transfer_chan; + dma_cookie_t transfer_cookie; + enum dma_status transfer_status; struct completion transfer_complete; bool dma_supported; bool dma_private; @@ -85,8 +88,14 @@ static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 }; static void pci_epf_test_dma_callback(void *param) { struct pci_epf_test *epf_test = param; - - complete(&epf_test->transfer_complete); + struct dma_tx_state state; + + epf_test->transfer_status = + dmaengine_tx_status(epf_test->transfer_chan, + epf_test->transfer_cookie, &state); + if (epf_test->transfer_status == DMA_COMPLETE || + epf_test->transfer_status == DMA_ERROR) + complete(&epf_test->transfer_complete); } /** @@ -112,7 +121,7 @@ static int pci_epf_test_data_transfer(struct pci_epf_test *epf_test, size_t len, dma_addr_t dma_remote, enum dma_transfer_direction dir) { - struct dma_chan *chan = (dir == DMA_DEV_TO_MEM) ? + struct dma_chan *chan = (dir == DMA_MEM_TO_DEV) ? epf_test->dma_chan_tx : epf_test->dma_chan_rx; dma_addr_t dma_local = (dir == DMA_MEM_TO_DEV) ? dma_src : dma_dst; enum dma_ctrl_flags flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT; @@ -120,7 +129,6 @@ static int pci_epf_test_data_transfer(struct pci_epf_test *epf_test, struct dma_async_tx_descriptor *tx; struct dma_slave_config sconf = {}; struct device *dev = &epf->dev; - dma_cookie_t cookie; int ret; if (IS_ERR_OR_NULL(chan)) { @@ -151,26 +159,34 @@ static int pci_epf_test_data_transfer(struct pci_epf_test *epf_test, return -EIO; } + reinit_completion(&epf_test->transfer_complete); + epf_test->transfer_chan = chan; tx->callback = pci_epf_test_dma_callback; tx->callback_param = epf_test; - cookie = tx->tx_submit(tx); - reinit_completion(&epf_test->transfer_complete); + epf_test->transfer_cookie = dmaengine_submit(tx); - ret = dma_submit_error(cookie); + ret = dma_submit_error(epf_test->transfer_cookie); if (ret) { - dev_err(dev, "Failed to do DMA tx_submit %d\n", cookie); - return -EIO; + dev_err(dev, "Failed to do DMA tx_submit %d\n", ret); + goto terminate; } dma_async_issue_pending(chan); ret = wait_for_completion_interruptible(&epf_test->transfer_complete); if (ret < 0) { - dmaengine_terminate_sync(chan); - dev_err(dev, "DMA wait_for_completion_timeout\n"); - return -ETIMEDOUT; + dev_err(dev, "DMA wait_for_completion interrupted\n"); + goto terminate; } - return 0; + if (epf_test->transfer_status == DMA_ERROR) { + dev_err(dev, "DMA transfer failed\n"); + ret = -EIO; + } + +terminate: + dmaengine_terminate_sync(chan); + + return ret; } struct epf_dma_filter { @@ -279,40 +295,29 @@ static void pci_epf_test_clean_dma_chan(struct pci_epf_test *epf_test) return; } -static void pci_epf_test_print_rate(const char *ops, u64 size, +static void pci_epf_test_print_rate(struct pci_epf_test *epf_test, + const char *op, u64 size, struct timespec64 *start, struct timespec64 *end, bool dma) { - struct timespec64 ts; - u64 rate, ns; - - ts = timespec64_sub(*end, *start); - - /* convert both size (stored in 'rate') and time in terms of 'ns' */ - ns = timespec64_to_ns(&ts); - rate = size * NSEC_PER_SEC; - - /* Divide both size (stored in 'rate') and ns by a common factor */ - while (ns > UINT_MAX) { - rate >>= 1; - ns >>= 1; - } - - if (!ns) - return; + struct timespec64 ts = timespec64_sub(*end, *start); + u64 rate = 0, ns; /* calculate the rate */ - do_div(rate, (uint32_t)ns); + ns = timespec64_to_ns(&ts); + if (ns) + rate = div64_u64(size * NSEC_PER_SEC, ns * 1000); - pr_info("\n%s => Size: %llu bytes\t DMA: %s\t Time: %llu.%09u seconds\t" - "Rate: %llu KB/s\n", ops, size, dma ? "YES" : "NO", - (u64)ts.tv_sec, (u32)ts.tv_nsec, rate / 1024); + dev_info(&epf_test->epf->dev, + "%s => Size: %llu B, DMA: %s, Time: %llu.%09u s, Rate: %llu KB/s\n", + op, size, dma ? "YES" : "NO", + (u64)ts.tv_sec, (u32)ts.tv_nsec, rate); } -static int pci_epf_test_copy(struct pci_epf_test *epf_test) +static void pci_epf_test_copy(struct pci_epf_test *epf_test, + struct pci_epf_test_reg *reg) { int ret; - bool use_dma; void __iomem *src_addr; void __iomem *dst_addr; phys_addr_t src_phys_addr; @@ -321,8 +326,6 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test) struct pci_epf *epf = epf_test->epf; struct device *dev = &epf->dev; struct pci_epc *epc = epf->epc; - enum pci_barno test_reg_bar = epf_test->test_reg_bar; - struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; src_addr = pci_epc_mem_alloc_addr(epc, &src_phys_addr, reg->size); if (!src_addr) { @@ -357,14 +360,7 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test) } ktime_get_ts64(&start); - use_dma = !!(reg->flags & FLAG_USE_DMA); - if (use_dma) { - if (!epf_test->dma_supported) { - dev_err(dev, "Cannot transfer data using DMA\n"); - ret = -EINVAL; - goto err_map_addr; - } - + if (reg->flags & FLAG_USE_DMA) { if (epf_test->dma_private) { dev_err(dev, "Cannot transfer data using DMA\n"); ret = -EINVAL; @@ -390,7 +386,8 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test) kfree(buf); } ktime_get_ts64(&end); - pci_epf_test_print_rate("COPY", reg->size, &start, &end, use_dma); + pci_epf_test_print_rate(epf_test, "COPY", reg->size, &start, &end, + reg->flags & FLAG_USE_DMA); err_map_addr: pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, dst_phys_addr); @@ -405,16 +402,19 @@ err_src_addr: pci_epc_mem_free_addr(epc, src_phys_addr, src_addr, reg->size); err: - return ret; + if (!ret) + reg->status |= STATUS_COPY_SUCCESS; + else + reg->status |= STATUS_COPY_FAIL; } -static int pci_epf_test_read(struct pci_epf_test *epf_test) +static void pci_epf_test_read(struct pci_epf_test *epf_test, + struct pci_epf_test_reg *reg) { int ret; void __iomem *src_addr; void *buf; u32 crc32; - bool use_dma; phys_addr_t phys_addr; phys_addr_t dst_phys_addr; struct timespec64 start, end; @@ -422,8 +422,6 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test) struct device *dev = &epf->dev; struct pci_epc *epc = epf->epc; struct device *dma_dev = epf->epc->dev.parent; - enum pci_barno test_reg_bar = epf_test->test_reg_bar; - struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; src_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size); if (!src_addr) { @@ -447,14 +445,7 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test) goto err_map_addr; } - use_dma = !!(reg->flags & FLAG_USE_DMA); - if (use_dma) { - if (!epf_test->dma_supported) { - dev_err(dev, "Cannot transfer data using DMA\n"); - ret = -EINVAL; - goto err_dma_map; - } - + if (reg->flags & FLAG_USE_DMA) { dst_phys_addr = dma_map_single(dma_dev, buf, reg->size, DMA_FROM_DEVICE); if (dma_mapping_error(dma_dev, dst_phys_addr)) { @@ -479,7 +470,8 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test) ktime_get_ts64(&end); } - pci_epf_test_print_rate("READ", reg->size, &start, &end, use_dma); + pci_epf_test_print_rate(epf_test, "READ", reg->size, &start, &end, + reg->flags & FLAG_USE_DMA); crc32 = crc32_le(~0, buf, reg->size); if (crc32 != reg->checksum) @@ -495,15 +487,18 @@ err_addr: pci_epc_mem_free_addr(epc, phys_addr, src_addr, reg->size); err: - return ret; + if (!ret) + reg->status |= STATUS_READ_SUCCESS; + else + reg->status |= STATUS_READ_FAIL; } -static int pci_epf_test_write(struct pci_epf_test *epf_test) +static void pci_epf_test_write(struct pci_epf_test *epf_test, + struct pci_epf_test_reg *reg) { int ret; void __iomem *dst_addr; void *buf; - bool use_dma; phys_addr_t phys_addr; phys_addr_t src_phys_addr; struct timespec64 start, end; @@ -511,8 +506,6 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test) struct device *dev = &epf->dev; struct pci_epc *epc = epf->epc; struct device *dma_dev = epf->epc->dev.parent; - enum pci_barno test_reg_bar = epf_test->test_reg_bar; - struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; dst_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size); if (!dst_addr) { @@ -539,14 +532,7 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test) get_random_bytes(buf, reg->size); reg->checksum = crc32_le(~0, buf, reg->size); - use_dma = !!(reg->flags & FLAG_USE_DMA); - if (use_dma) { - if (!epf_test->dma_supported) { - dev_err(dev, "Cannot transfer data using DMA\n"); - ret = -EINVAL; - goto err_dma_map; - } - + if (reg->flags & FLAG_USE_DMA) { src_phys_addr = dma_map_single(dma_dev, buf, reg->size, DMA_TO_DEVICE); if (dma_mapping_error(dma_dev, src_phys_addr)) { @@ -573,7 +559,8 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test) ktime_get_ts64(&end); } - pci_epf_test_print_rate("WRITE", reg->size, &start, &end, use_dma); + pci_epf_test_print_rate(epf_test, "WRITE", reg->size, &start, &end, + reg->flags & FLAG_USE_DMA); /* * wait 1ms inorder for the write to complete. Without this delay L3 @@ -591,32 +578,51 @@ err_addr: pci_epc_mem_free_addr(epc, phys_addr, dst_addr, reg->size); err: - return ret; + if (!ret) + reg->status |= STATUS_WRITE_SUCCESS; + else + reg->status |= STATUS_WRITE_FAIL; } -static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test, u8 irq_type, - u16 irq) +static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test, + struct pci_epf_test_reg *reg) { struct pci_epf *epf = epf_test->epf; struct device *dev = &epf->dev; struct pci_epc *epc = epf->epc; - enum pci_barno test_reg_bar = epf_test->test_reg_bar; - struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; + u32 status = reg->status | STATUS_IRQ_RAISED; + int count; - reg->status |= STATUS_IRQ_RAISED; + /* + * Set the status before raising the IRQ to ensure that the host sees + * the updated value when it gets the IRQ. + */ + WRITE_ONCE(reg->status, status); - switch (irq_type) { + switch (reg->irq_type) { case IRQ_TYPE_LEGACY: pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no, PCI_EPC_IRQ_LEGACY, 0); break; case IRQ_TYPE_MSI: + count = pci_epc_get_msi(epc, epf->func_no, epf->vfunc_no); + if (reg->irq_number > count || count <= 0) { + dev_err(dev, "Invalid MSI IRQ number %d / %d\n", + reg->irq_number, count); + return; + } pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no, - PCI_EPC_IRQ_MSI, irq); + PCI_EPC_IRQ_MSI, reg->irq_number); break; case IRQ_TYPE_MSIX: + count = pci_epc_get_msix(epc, epf->func_no, epf->vfunc_no); + if (reg->irq_number > count || count <= 0) { + dev_err(dev, "Invalid MSIX IRQ number %d / %d\n", + reg->irq_number, count); + return; + } pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no, - PCI_EPC_IRQ_MSIX, irq); + PCI_EPC_IRQ_MSIX, reg->irq_number); break; default: dev_err(dev, "Failed to raise IRQ, unknown type\n"); @@ -626,87 +632,53 @@ static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test, u8 irq_type, static void pci_epf_test_cmd_handler(struct work_struct *work) { - int ret; - int count; u32 command; struct pci_epf_test *epf_test = container_of(work, struct pci_epf_test, cmd_handler.work); struct pci_epf *epf = epf_test->epf; struct device *dev = &epf->dev; - struct pci_epc *epc = epf->epc; enum pci_barno test_reg_bar = epf_test->test_reg_bar; struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; - command = reg->command; + command = READ_ONCE(reg->command); if (!command) goto reset_handler; - reg->command = 0; - reg->status = 0; + WRITE_ONCE(reg->command, 0); + WRITE_ONCE(reg->status, 0); - if (reg->irq_type > IRQ_TYPE_MSIX) { - dev_err(dev, "Failed to detect IRQ type\n"); + if ((READ_ONCE(reg->flags) & FLAG_USE_DMA) && + !epf_test->dma_supported) { + dev_err(dev, "Cannot transfer data using DMA\n"); goto reset_handler; } - if (command & COMMAND_RAISE_LEGACY_IRQ) { - reg->status = STATUS_IRQ_RAISED; - pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no, - PCI_EPC_IRQ_LEGACY, 0); - goto reset_handler; - } - - if (command & COMMAND_WRITE) { - ret = pci_epf_test_write(epf_test); - if (ret) - reg->status |= STATUS_WRITE_FAIL; - else - reg->status |= STATUS_WRITE_SUCCESS; - pci_epf_test_raise_irq(epf_test, reg->irq_type, - reg->irq_number); - goto reset_handler; - } - - if (command & COMMAND_READ) { - ret = pci_epf_test_read(epf_test); - if (!ret) - reg->status |= STATUS_READ_SUCCESS; - else - reg->status |= STATUS_READ_FAIL; - pci_epf_test_raise_irq(epf_test, reg->irq_type, - reg->irq_number); - goto reset_handler; - } - - if (command & COMMAND_COPY) { - ret = pci_epf_test_copy(epf_test); - if (!ret) - reg->status |= STATUS_COPY_SUCCESS; - else - reg->status |= STATUS_COPY_FAIL; - pci_epf_test_raise_irq(epf_test, reg->irq_type, - reg->irq_number); - goto reset_handler; - } - - if (command & COMMAND_RAISE_MSI_IRQ) { - count = pci_epc_get_msi(epc, epf->func_no, epf->vfunc_no); - if (reg->irq_number > count || count <= 0) - goto reset_handler; - reg->status = STATUS_IRQ_RAISED; - pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no, - PCI_EPC_IRQ_MSI, reg->irq_number); + if (reg->irq_type > IRQ_TYPE_MSIX) { + dev_err(dev, "Failed to detect IRQ type\n"); goto reset_handler; } - if (command & COMMAND_RAISE_MSIX_IRQ) { - count = pci_epc_get_msix(epc, epf->func_no, epf->vfunc_no); - if (reg->irq_number > count || count <= 0) - goto reset_handler; - reg->status = STATUS_IRQ_RAISED; - pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no, - PCI_EPC_IRQ_MSIX, reg->irq_number); - goto reset_handler; + switch (command) { + case COMMAND_RAISE_LEGACY_IRQ: + case COMMAND_RAISE_MSI_IRQ: + case COMMAND_RAISE_MSIX_IRQ: + pci_epf_test_raise_irq(epf_test, reg); + break; + case COMMAND_WRITE: + pci_epf_test_write(epf_test, reg); + pci_epf_test_raise_irq(epf_test, reg); + break; + case COMMAND_READ: + pci_epf_test_read(epf_test, reg); + pci_epf_test_raise_irq(epf_test, reg); + break; + case COMMAND_COPY: + pci_epf_test_copy(epf_test, reg); + pci_epf_test_raise_irq(epf_test, reg); + break; + default: + dev_err(dev, "Invalid command 0x%x\n", command); + break; } reset_handler: @@ -980,7 +952,8 @@ static const struct pci_epf_device_id pci_epf_test_ids[] = { {}, }; -static int pci_epf_test_probe(struct pci_epf *epf) +static int pci_epf_test_probe(struct pci_epf *epf, + const struct pci_epf_device_id *id) { struct pci_epf_test *epf_test; struct device *dev = &epf->dev; diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c index b7c7a8af99f4..0f5c8f8be847 100644 --- a/drivers/pci/endpoint/functions/pci-epf-vntb.c +++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c @@ -84,15 +84,15 @@ enum epf_ntb_bar { * | | * | | * | | - * +-----------------------+--------------------------+ Base+span_offset + * +-----------------------+--------------------------+ Base+spad_offset * | | | - * | Peer Span Space | Span Space | + * | Peer Spad Space | Spad Space | * | | | * | | | - * +-----------------------+--------------------------+ Base+span_offset - * | | | +span_count * 4 + * +-----------------------+--------------------------+ Base+spad_offset + * | | | +spad_count * 4 * | | | - * | Span Space | Peer Span Space | + * | Spad Space | Peer Spad Space | * | | | * +-----------------------+--------------------------+ * Virtual PCI PCIe Endpoint @@ -1395,13 +1395,15 @@ static struct pci_epf_ops epf_ntb_ops = { /** * epf_ntb_probe() - Probe NTB function driver * @epf: NTB endpoint function device + * @id: NTB endpoint function device ID * * Probe NTB function driver when endpoint function bus detects a NTB * endpoint function. * * Returns: Zero for success, or an error code in case of failure */ -static int epf_ntb_probe(struct pci_epf *epf) +static int epf_ntb_probe(struct pci_epf *epf, + const struct pci_epf_device_id *id) { struct epf_ntb *ntb; struct device *dev; diff --git a/drivers/pci/endpoint/pci-ep-cfs.c b/drivers/pci/endpoint/pci-ep-cfs.c index 4b8ac0ac84d5..0ea64e24ed61 100644 --- a/drivers/pci/endpoint/pci-ep-cfs.c +++ b/drivers/pci/endpoint/pci-ep-cfs.c @@ -23,6 +23,7 @@ struct pci_epf_group { struct config_group group; struct config_group primary_epc_group; struct config_group secondary_epc_group; + struct config_group *type_group; struct delayed_work cfs_work; struct pci_epf *epf; int index; @@ -178,6 +179,9 @@ static ssize_t pci_epc_start_store(struct config_item *item, const char *page, if (kstrtobool(page, &start) < 0) return -EINVAL; + if (start == epc_group->start) + return -EALREADY; + if (!start) { pci_epc_stop(epc); epc_group->start = 0; @@ -502,33 +506,64 @@ static struct configfs_item_operations pci_epf_ops = { .release = pci_epf_release, }; -static struct config_group *pci_epf_type_make(struct config_group *group, - const char *name) +static const struct config_item_type pci_epf_type = { + .ct_item_ops = &pci_epf_ops, + .ct_attrs = pci_epf_attrs, + .ct_owner = THIS_MODULE, +}; + +/** + * pci_epf_type_add_cfs() - Help function drivers to expose function specific + * attributes in configfs + * @epf: the EPF device that has to be configured using configfs + * @group: the parent configfs group (corresponding to entries in + * pci_epf_device_id) + * + * Invoke to expose function specific attributes in configfs. + * + * Return: A pointer to a config_group structure or NULL if the function driver + * does not have anything to expose (attributes configured by user) or if + * the function driver does not implement the add_cfs() method. + * + * Returns an error pointer if this function is called for an unbound EPF device + * or if the EPF driver add_cfs() method fails. + */ +static struct config_group *pci_epf_type_add_cfs(struct pci_epf *epf, + struct config_group *group) { - struct pci_epf_group *epf_group = to_pci_epf_group(&group->cg_item); struct config_group *epf_type_group; - epf_type_group = pci_epf_type_add_cfs(epf_group->epf, group); + if (!epf->driver) { + dev_err(&epf->dev, "epf device not bound to driver\n"); + return ERR_PTR(-ENODEV); + } + + if (!epf->driver->ops->add_cfs) + return NULL; + + mutex_lock(&epf->lock); + epf_type_group = epf->driver->ops->add_cfs(epf, group); + mutex_unlock(&epf->lock); + return epf_type_group; } -static void pci_epf_type_drop(struct config_group *group, - struct config_item *item) +static void pci_ep_cfs_add_type_group(struct pci_epf_group *epf_group) { - config_item_put(item); -} + struct config_group *group; -static struct configfs_group_operations pci_epf_type_group_ops = { - .make_group = &pci_epf_type_make, - .drop_item = &pci_epf_type_drop, -}; + group = pci_epf_type_add_cfs(epf_group->epf, &epf_group->group); + if (!group) + return; -static const struct config_item_type pci_epf_type = { - .ct_group_ops = &pci_epf_type_group_ops, - .ct_item_ops = &pci_epf_ops, - .ct_attrs = pci_epf_attrs, - .ct_owner = THIS_MODULE, -}; + if (IS_ERR(group)) { + dev_err(&epf_group->epf->dev, + "failed to create epf type specific attributes\n"); + return; + } + + configfs_register_group(&epf_group->group, group); +} static void pci_epf_cfs_work(struct work_struct *work) { @@ -547,6 +582,8 @@ static void pci_epf_cfs_work(struct work_struct *work) pr_err("failed to create 'secondary' EPC interface\n"); return; } + + pci_ep_cfs_add_type_group(epf_group); } static struct config_group *pci_epf_make(struct config_group *group, diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c index 46c9a5c3ca14..6c54fa5684d2 100644 --- a/drivers/pci/endpoint/pci-epc-core.c +++ b/drivers/pci/endpoint/pci-epc-core.c @@ -213,7 +213,7 @@ EXPORT_SYMBOL_GPL(pci_epc_start); * @func_no: the physical endpoint function number in the EPC device * @vfunc_no: the virtual endpoint function number in the physical function * @type: specify the type of interrupt; legacy, MSI or MSI-X - * @interrupt_num: the MSI or MSI-X interrupt number + * @interrupt_num: the MSI or MSI-X interrupt number with range (1-N) * * Invoke to raise an legacy, MSI or MSI-X interrupt */ @@ -246,7 +246,7 @@ EXPORT_SYMBOL_GPL(pci_epc_raise_irq); * @func_no: the physical endpoint function number in the EPC device * @vfunc_no: the virtual endpoint function number in the physical function * @phys_addr: the physical address of the outbound region - * @interrupt_num: the MSI interrupt number + * @interrupt_num: the MSI interrupt number with range (1-N) * @entry_size: Size of Outbound address region for each interrupt * @msi_data: the data that should be written in order to raise MSI interrupt * with interrupt number as 'interrupt num' @@ -707,6 +707,32 @@ void pci_epc_linkup(struct pci_epc *epc) EXPORT_SYMBOL_GPL(pci_epc_linkup); /** + * pci_epc_linkdown() - Notify the EPF device that EPC device has dropped the + * connection with the Root Complex. + * @epc: the EPC device which has dropped the link with the host + * + * Invoke to Notify the EPF device that the EPC device has dropped the + * connection with the Root Complex. + */ +void pci_epc_linkdown(struct pci_epc *epc) +{ + struct pci_epf *epf; + + if (!epc || IS_ERR(epc)) + return; + + mutex_lock(&epc->list_lock); + list_for_each_entry(epf, &epc->pci_epf, list) { + mutex_lock(&epf->lock); + if (epf->event_ops && epf->event_ops->link_down) + epf->event_ops->link_down(epf); + mutex_unlock(&epf->lock); + } + mutex_unlock(&epc->list_lock); +} +EXPORT_SYMBOL_GPL(pci_epc_linkdown); + +/** * pci_epc_init_notify() - Notify the EPF device that EPC device's core * initialization is completed. * @epc: the EPC device whose core initialization is completed @@ -733,6 +759,32 @@ void pci_epc_init_notify(struct pci_epc *epc) EXPORT_SYMBOL_GPL(pci_epc_init_notify); /** + * pci_epc_bme_notify() - Notify the EPF device that the EPC device has received + * the BME event from the Root complex + * @epc: the EPC device that received the BME event + * + * Invoke to Notify the EPF device that the EPC device has received the Bus + * Master Enable (BME) event from the Root complex + */ +void pci_epc_bme_notify(struct pci_epc *epc) +{ + struct pci_epf *epf; + + if (!epc || IS_ERR(epc)) + return; + + mutex_lock(&epc->list_lock); + list_for_each_entry(epf, &epc->pci_epf, list) { + mutex_lock(&epf->lock); + if (epf->event_ops && epf->event_ops->bme) + epf->event_ops->bme(epf); + mutex_unlock(&epf->lock); + } + mutex_unlock(&epc->list_lock); +} +EXPORT_SYMBOL_GPL(pci_epc_bme_notify); + +/** * pci_epc_destroy() - destroy the EPC device * @epc: the EPC device that has to be destroyed * diff --git a/drivers/pci/endpoint/pci-epf-core.c b/drivers/pci/endpoint/pci-epf-core.c index 2036e38be093..2c32de667937 100644 --- a/drivers/pci/endpoint/pci-epf-core.c +++ b/drivers/pci/endpoint/pci-epf-core.c @@ -21,38 +21,6 @@ static struct bus_type pci_epf_bus_type; static const struct device_type pci_epf_type; /** - * pci_epf_type_add_cfs() - Help function drivers to expose function specific - * attributes in configfs - * @epf: the EPF device that has to be configured using configfs - * @group: the parent configfs group (corresponding to entries in - * pci_epf_device_id) - * - * Invoke to expose function specific attributes in configfs. If the function - * driver does not have anything to expose (attributes configured by user), - * return NULL. - */ -struct config_group *pci_epf_type_add_cfs(struct pci_epf *epf, - struct config_group *group) -{ - struct config_group *epf_type_group; - - if (!epf->driver) { - dev_err(&epf->dev, "epf device not bound to driver\n"); - return NULL; - } - - if (!epf->driver->ops->add_cfs) - return NULL; - - mutex_lock(&epf->lock); - epf_type_group = epf->driver->ops->add_cfs(epf, group); - mutex_unlock(&epf->lock); - - return epf_type_group; -} -EXPORT_SYMBOL_GPL(pci_epf_type_add_cfs); - -/** * pci_epf_unbind() - Notify the function driver that the binding between the * EPF device and EPC device has been lost * @epf: the EPF device which has lost the binding with the EPC device @@ -493,16 +461,16 @@ static const struct device_type pci_epf_type = { .release = pci_epf_dev_release, }; -static int +static const struct pci_epf_device_id * pci_epf_match_id(const struct pci_epf_device_id *id, const struct pci_epf *epf) { while (id->name[0]) { if (strcmp(epf->name, id->name) == 0) - return true; + return id; id++; } - return false; + return NULL; } static int pci_epf_device_match(struct device *dev, struct device_driver *drv) @@ -511,7 +479,7 @@ static int pci_epf_device_match(struct device *dev, struct device_driver *drv) struct pci_epf_driver *driver = to_pci_epf_driver(drv); if (driver->id_table) - return pci_epf_match_id(driver->id_table, epf); + return !!pci_epf_match_id(driver->id_table, epf); return !strcmp(epf->name, drv->name); } @@ -526,7 +494,7 @@ static int pci_epf_device_probe(struct device *dev) epf->driver = driver; - return driver->probe(epf); + return driver->probe(epf, pci_epf_match_id(driver->id_table, epf)); } static void pci_epf_device_remove(struct device *dev) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 5b1f271c6034..328d1e416014 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -498,7 +498,6 @@ static void enable_slot(struct acpiphp_slot *slot, bool bridge) acpiphp_native_scan_bridge(dev); } } else { - LIST_HEAD(add_list); int max, pass; acpiphp_rescan_slot(slot); @@ -512,12 +511,10 @@ static void enable_slot(struct acpiphp_slot *slot, bool bridge) if (pass && dev->subordinate) { check_hotplug_bridge(slot, dev); pcibios_resource_survey_bus(dev->subordinate); - __pci_bus_size_bridges(dev->subordinate, - &add_list); } } } - __pci_bus_assign_resources(bus, &add_list, NULL); + pci_assign_unassigned_bridge_resources(bus->self); } acpiphp_sanitize_bus(bus); diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 529c34808440..dcdbfcf404dd 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -166,11 +166,11 @@ void pciehp_handle_button_press(struct controller *ctrl) case ON_STATE: if (ctrl->state == ON_STATE) { ctrl->state = BLINKINGOFF_STATE; - ctrl_info(ctrl, "Slot(%s): Powering off due to button press\n", + ctrl_info(ctrl, "Slot(%s): Button press: will power off in 5 sec\n", slot_name(ctrl)); } else { ctrl->state = BLINKINGON_STATE; - ctrl_info(ctrl, "Slot(%s) Powering on due to button press\n", + ctrl_info(ctrl, "Slot(%s): Button press: will power on in 5 sec\n", slot_name(ctrl)); } /* blink power indicator and turn off attention */ @@ -185,22 +185,23 @@ void pciehp_handle_button_press(struct controller *ctrl) * press the attention again before the 5 sec. limit * expires to cancel hot-add or hot-remove */ - ctrl_info(ctrl, "Slot(%s): Button cancel\n", slot_name(ctrl)); cancel_delayed_work(&ctrl->button_work); if (ctrl->state == BLINKINGOFF_STATE) { ctrl->state = ON_STATE; pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_ON, PCI_EXP_SLTCTL_ATTN_IND_OFF); + ctrl_info(ctrl, "Slot(%s): Button press: canceling request to power off\n", + slot_name(ctrl)); } else { ctrl->state = OFF_STATE; pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF, PCI_EXP_SLTCTL_ATTN_IND_OFF); + ctrl_info(ctrl, "Slot(%s): Button press: canceling request to power on\n", + slot_name(ctrl)); } - ctrl_info(ctrl, "Slot(%s): Action canceled due to button press\n", - slot_name(ctrl)); break; default: - ctrl_err(ctrl, "Slot(%s): Ignoring invalid state %#x\n", + ctrl_err(ctrl, "Slot(%s): Button press: ignoring invalid state %#x\n", slot_name(ctrl), ctrl->state); break; } @@ -256,6 +257,14 @@ void pciehp_handle_presence_or_link_change(struct controller *ctrl, u32 events) present = pciehp_card_present(ctrl); link_active = pciehp_check_link_active(ctrl); if (present <= 0 && link_active <= 0) { + if (ctrl->state == BLINKINGON_STATE) { + ctrl->state = OFF_STATE; + cancel_delayed_work(&ctrl->button_work); + pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF, + INDICATOR_NOOP); + ctrl_info(ctrl, "Slot(%s): Card not present\n", + slot_name(ctrl)); + } mutex_unlock(&ctrl->state_lock); return; } diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index f8c70115b691..8711325605f0 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -722,11 +722,8 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id) } /* Check Attention Button Pressed */ - if (events & PCI_EXP_SLTSTA_ABP) { - ctrl_info(ctrl, "Slot(%s): Attention button pressed\n", - slot_name(ctrl)); + if (events & PCI_EXP_SLTSTA_ABP) pciehp_handle_button_press(ctrl); - } /* Check Power Fault Detected */ if (events & PCI_EXP_SLTSTA_PFD) { @@ -984,7 +981,7 @@ static inline int pcie_hotplug_depth(struct pci_dev *dev) struct controller *pcie_init(struct pcie_device *dev) { struct controller *ctrl; - u32 slot_cap, slot_cap2, link_cap; + u32 slot_cap, slot_cap2; u8 poweron; struct pci_dev *pdev = dev->port; struct pci_bus *subordinate = pdev->subordinate; @@ -1030,9 +1027,6 @@ struct controller *pcie_init(struct pcie_device *dev) if (dmi_first_match(inband_presence_disabled_dmi_table)) ctrl->inband_presence_disabled = 1; - /* Check if Data Link Layer Link Active Reporting is implemented */ - pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &link_cap); - /* Clear all remaining event bits in Slot Status register. */ pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | @@ -1051,7 +1045,7 @@ struct controller *pcie_init(struct pcie_device *dev) FLAG(slot_cap, PCI_EXP_SLTCAP_EIP), FLAG(slot_cap, PCI_EXP_SLTCAP_NCCS), FLAG(slot_cap2, PCI_EXP_SLTCAP2_IBPD), - FLAG(link_cap, PCI_EXP_LNKCAP_DLLLARC), + FLAG(pdev->link_active_reporting, true), pdev->broken_cmd_compl ? " (with Cmd Compl erratum)" : ""); /* diff --git a/drivers/pci/of.c b/drivers/pci/of.c index 2c25f4fa0225..e51219f9f523 100644 --- a/drivers/pci/of.c +++ b/drivers/pci/of.c @@ -39,16 +39,14 @@ int pci_set_of_node(struct pci_dev *dev) return -ENODEV; } - dev->dev.of_node = node; - dev->dev.fwnode = &node->fwnode; + device_set_node(&dev->dev, of_fwnode_handle(node)); return 0; } void pci_release_of_node(struct pci_dev *dev) { of_node_put(dev->dev.of_node); - dev->dev.of_node = NULL; - dev->dev.fwnode = NULL; + device_set_node(&dev->dev, NULL); } void pci_set_bus_of_node(struct pci_bus *bus) @@ -63,17 +61,13 @@ void pci_set_bus_of_node(struct pci_bus *bus) bus->self->external_facing = true; } - bus->dev.of_node = node; - - if (bus->dev.of_node) - bus->dev.fwnode = &bus->dev.of_node->fwnode; + device_set_node(&bus->dev, of_fwnode_handle(node)); } void pci_release_bus_of_node(struct pci_bus *bus) { of_node_put(bus->dev.of_node); - bus->dev.of_node = NULL; - bus->dev.fwnode = NULL; + device_set_node(&bus->dev, NULL); } struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus) diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 052a611081ec..a05350a4e49c 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -1043,6 +1043,16 @@ bool acpi_pci_bridge_d3(struct pci_dev *dev) return false; } +static void acpi_pci_config_space_access(struct pci_dev *dev, bool enable) +{ + int val = enable ? ACPI_REG_CONNECT : ACPI_REG_DISCONNECT; + int ret = acpi_evaluate_reg(ACPI_HANDLE(&dev->dev), + ACPI_ADR_SPACE_PCI_CONFIG, val); + if (ret) + pci_dbg(dev, "ACPI _REG %s evaluation failed (%d)\n", + enable ? "connect" : "disconnect", ret); +} + int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) { struct acpi_device *adev = ACPI_COMPANION(&dev->dev); @@ -1053,32 +1063,49 @@ int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) [PCI_D3hot] = ACPI_STATE_D3_HOT, [PCI_D3cold] = ACPI_STATE_D3_COLD, }; - int error = -EINVAL; + int error; /* If the ACPI device has _EJ0, ignore the device */ if (!adev || acpi_has_method(adev->handle, "_EJ0")) return -ENODEV; switch (state) { - case PCI_D3cold: - if (dev_pm_qos_flags(&dev->dev, PM_QOS_FLAG_NO_POWER_OFF) == - PM_QOS_FLAGS_ALL) { - error = -EBUSY; - break; - } - fallthrough; case PCI_D0: case PCI_D1: case PCI_D2: case PCI_D3hot: - error = acpi_device_set_power(adev, state_conv[state]); + case PCI_D3cold: + break; + default: + return -EINVAL; + } + + if (state == PCI_D3cold) { + if (dev_pm_qos_flags(&dev->dev, PM_QOS_FLAG_NO_POWER_OFF) == + PM_QOS_FLAGS_ALL) + return -EBUSY; + + /* Notify AML lack of PCI config space availability */ + acpi_pci_config_space_access(dev, false); } - if (!error) - pci_dbg(dev, "power state changed by ACPI to %s\n", - acpi_power_state_string(adev->power.state)); + error = acpi_device_set_power(adev, state_conv[state]); + if (error) + return error; - return error; + pci_dbg(dev, "power state changed by ACPI to %s\n", + acpi_power_state_string(adev->power.state)); + + /* + * Notify AML of PCI config space availability. Config space is + * accessible in all states except D3cold; the only transitions + * that change availability are transitions to D3cold and from + * D3cold to D0. + */ + if (state == PCI_D0) + acpi_pci_config_space_access(dev, true); + + return 0; } pci_power_t acpi_pci_get_power_state(struct pci_dev *dev) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 5ede93222bc1..60230da957e0 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -65,6 +65,13 @@ struct pci_pme_device { #define PME_TIMEOUT 1000 /* How long between PME checks */ /* + * Following exit from Conventional Reset, devices must be ready within 1 sec + * (PCIe r6.0 sec 6.6.1). A D3cold to D0 transition implies a Conventional + * Reset (PCIe r6.0 sec 5.8). + */ +#define PCI_RESET_WAIT 1000 /* msec */ + +/* * Devices may extend the 1 sec period through Request Retry Status * completions (PCIe r6.0 sec 2.3.1). The spec does not provide an upper * limit, but 60 sec ought to be enough for any device to become @@ -1156,7 +1163,14 @@ void pci_resume_bus(struct pci_bus *bus) static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout) { int delay = 1; - u32 id; + bool retrain = false; + struct pci_dev *bridge; + + if (pci_is_pcie(dev)) { + bridge = pci_upstream_bridge(dev); + if (bridge) + retrain = true; + } /* * After reset, the device should not silently discard config @@ -1170,21 +1184,33 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout) * Command register instead of Vendor ID so we don't have to * contend with the CRS SV value. */ - pci_read_config_dword(dev, PCI_COMMAND, &id); - while (PCI_POSSIBLE_ERROR(id)) { + for (;;) { + u32 id; + + pci_read_config_dword(dev, PCI_COMMAND, &id); + if (!PCI_POSSIBLE_ERROR(id)) + break; + if (delay > timeout) { pci_warn(dev, "not ready %dms after %s; giving up\n", delay - 1, reset_type); return -ENOTTY; } - if (delay > PCI_RESET_WAIT) + if (delay > PCI_RESET_WAIT) { + if (retrain) { + retrain = false; + if (pcie_failed_link_retrain(bridge)) { + delay = 1; + continue; + } + } pci_info(dev, "not ready %dms after %s; waiting\n", delay - 1, reset_type); + } msleep(delay); delay *= 2; - pci_read_config_dword(dev, PCI_COMMAND, &id); } if (delay > PCI_RESET_WAIT) @@ -2949,13 +2975,13 @@ static const struct dmi_system_id bridge_d3_blacklist[] = { { /* * Downstream device is not accessible after putting a root port - * into D3cold and back into D0 on Elo i2. + * into D3cold and back into D0 on Elo Continental Z2 board */ - .ident = "Elo i2", + .ident = "Elo Continental Z2", .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Elo Touch Solutions"), - DMI_MATCH(DMI_PRODUCT_NAME, "Elo i2"), - DMI_MATCH(DMI_PRODUCT_VERSION, "RevB"), + DMI_MATCH(DMI_BOARD_VENDOR, "Elo Touch Solutions"), + DMI_MATCH(DMI_BOARD_NAME, "Geminilake"), + DMI_MATCH(DMI_BOARD_VERSION, "Continental Z2"), }, }, #endif @@ -4857,6 +4883,79 @@ static int pci_pm_reset(struct pci_dev *dev, bool probe) } /** + * pcie_wait_for_link_status - Wait for link status change + * @pdev: Device whose link to wait for. + * @use_lt: Use the LT bit if TRUE, or the DLLLA bit if FALSE. + * @active: Waiting for active or inactive? + * + * Return 0 if successful, or -ETIMEDOUT if status has not changed within + * PCIE_LINK_RETRAIN_TIMEOUT_MS milliseconds. + */ +static int pcie_wait_for_link_status(struct pci_dev *pdev, + bool use_lt, bool active) +{ + u16 lnksta_mask, lnksta_match; + unsigned long end_jiffies; + u16 lnksta; + + lnksta_mask = use_lt ? PCI_EXP_LNKSTA_LT : PCI_EXP_LNKSTA_DLLLA; + lnksta_match = active ? lnksta_mask : 0; + + end_jiffies = jiffies + msecs_to_jiffies(PCIE_LINK_RETRAIN_TIMEOUT_MS); + do { + pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnksta); + if ((lnksta & lnksta_mask) == lnksta_match) + return 0; + msleep(1); + } while (time_before(jiffies, end_jiffies)); + + return -ETIMEDOUT; +} + +/** + * pcie_retrain_link - Request a link retrain and wait for it to complete + * @pdev: Device whose link to retrain. + * @use_lt: Use the LT bit if TRUE, or the DLLLA bit if FALSE, for status. + * + * Retrain completion status is retrieved from the Link Status Register + * according to @use_lt. It is not verified whether the use of the DLLLA + * bit is valid. + * + * Return 0 if successful, or -ETIMEDOUT if training has not completed + * within PCIE_LINK_RETRAIN_TIMEOUT_MS milliseconds. + */ +int pcie_retrain_link(struct pci_dev *pdev, bool use_lt) +{ + int rc; + u16 lnkctl; + + /* + * Ensure the updated LNKCTL parameters are used during link + * training by checking that there is no ongoing link training to + * avoid LTSSM race as recommended in Implementation Note at the + * end of PCIe r6.0.1 sec 7.5.3.7. + */ + rc = pcie_wait_for_link_status(pdev, use_lt, !use_lt); + if (rc) + return rc; + + pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &lnkctl); + lnkctl |= PCI_EXP_LNKCTL_RL; + pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnkctl); + if (pdev->clear_retrain_link) { + /* + * Due to an erratum in some devices the Retrain Link bit + * needs to be cleared again manually to allow the link + * training to succeed. + */ + lnkctl &= ~PCI_EXP_LNKCTL_RL; + pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnkctl); + } + + return pcie_wait_for_link_status(pdev, use_lt, !use_lt); +} + +/** * pcie_wait_for_link_delay - Wait until link is active or inactive * @pdev: Bridge device * @active: waiting for active or inactive? @@ -4867,16 +4966,14 @@ static int pci_pm_reset(struct pci_dev *dev, bool probe) static bool pcie_wait_for_link_delay(struct pci_dev *pdev, bool active, int delay) { - int timeout = 1000; - bool ret; - u16 lnk_status; + int rc; /* * Some controllers might not implement link active reporting. In this * case, we wait for 1000 ms + any delay requested by the caller. */ if (!pdev->link_active_reporting) { - msleep(timeout + delay); + msleep(PCIE_LINK_RETRAIN_TIMEOUT_MS + delay); return true; } @@ -4891,20 +4988,21 @@ static bool pcie_wait_for_link_delay(struct pci_dev *pdev, bool active, */ if (active) msleep(20); - for (;;) { - pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status); - ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA); - if (ret == active) - break; - if (timeout <= 0) - break; - msleep(10); - timeout -= 10; - } - if (active && ret) + rc = pcie_wait_for_link_status(pdev, false, active); + if (active) { + if (rc) + rc = pcie_failed_link_retrain(pdev); + if (rc) + return false; + msleep(delay); + return true; + } + + if (rc) + return false; - return ret == active; + return true; } /** @@ -5011,11 +5109,9 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type) * * However, 100 ms is the minimum and the PCIe spec says the * software must allow at least 1s before it can determine that the - * device that did not respond is a broken device. There is - * evidence that 100 ms is not always enough, for example certain - * Titan Ridge xHCI controller does not always respond to - * configuration requests if we only wait for 100 ms (see - * https://bugzilla.kernel.org/show_bug.cgi?id=203885). + * device that did not respond is a broken device. Also device can + * take longer than that to respond if it indicates so through Request + * Retry Status completions. * * Therefore we wait for 100 ms and check for the device presence * until the timeout expires. @@ -5024,16 +5120,36 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type) return 0; if (pcie_get_speed_cap(dev) <= PCIE_SPEED_5_0GT) { + u16 status; + pci_dbg(dev, "waiting %d ms for downstream link\n", delay); msleep(delay); - } else { - pci_dbg(dev, "waiting %d ms for downstream link, after activation\n", - delay); - if (!pcie_wait_for_link_delay(dev, true, delay)) { - /* Did not train, no need to wait any further */ - pci_info(dev, "Data Link Layer Link Active not set in 1000 msec\n"); + + if (!pci_dev_wait(child, reset_type, PCI_RESET_WAIT - delay)) + return 0; + + /* + * If the port supports active link reporting we now check + * whether the link is active and if not bail out early with + * the assumption that the device is not present anymore. + */ + if (!dev->link_active_reporting) return -ENOTTY; - } + + pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &status); + if (!(status & PCI_EXP_LNKSTA_DLLLA)) + return -ENOTTY; + + return pci_dev_wait(child, reset_type, + PCIE_RESET_READY_POLL_MS - PCI_RESET_WAIT); + } + + pci_dbg(dev, "waiting %d ms for downstream link, after activation\n", + delay); + if (!pcie_wait_for_link_delay(dev, true, delay)) { + /* Did not train, no need to wait any further */ + pci_info(dev, "Data Link Layer Link Active not set in 1000 msec\n"); + return -ENOTTY; } return pci_dev_wait(child, reset_type, diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 2475098f6518..a4c397434057 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -11,6 +11,8 @@ #define PCI_VSEC_ID_INTEL_TBT 0x1234 /* Thunderbolt */ +#define PCIE_LINK_RETRAIN_TIMEOUT_MS 1000 + extern const unsigned char pcie_link_speed[]; extern bool pci_early_dump; @@ -64,13 +66,6 @@ struct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev, #define PCI_PM_D3HOT_WAIT 10 /* msec */ #define PCI_PM_D3COLD_WAIT 100 /* msec */ -/* - * Following exit from Conventional Reset, devices must be ready within 1 sec - * (PCIe r6.0 sec 6.6.1). A D3cold to D0 transition implies a Conventional - * Reset (PCIe r6.0 sec 5.8). - */ -#define PCI_RESET_WAIT 1000 /* msec */ - void pci_update_current_state(struct pci_dev *dev, pci_power_t state); void pci_refresh_power_state(struct pci_dev *dev); int pci_power_up(struct pci_dev *dev); @@ -541,6 +536,7 @@ void pci_acs_init(struct pci_dev *dev); int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags); int pci_dev_specific_enable_acs(struct pci_dev *dev); int pci_dev_specific_disable_acs_redir(struct pci_dev *dev); +bool pcie_failed_link_retrain(struct pci_dev *dev); #else static inline int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags) @@ -555,6 +551,10 @@ static inline int pci_dev_specific_disable_acs_redir(struct pci_dev *dev) { return -ENOTTY; } +static inline bool pcie_failed_link_retrain(struct pci_dev *dev) +{ + return false; +} #endif /* PCI error reporting and recovery */ @@ -563,6 +563,7 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, pci_ers_result_t (*reset_subordinates)(struct pci_dev *pdev)); bool pcie_wait_for_link(struct pci_dev *pdev, bool active); +int pcie_retrain_link(struct pci_dev *pdev, bool use_lt); #ifdef CONFIG_PCIEASPM void pcie_aspm_init_link_state(struct pci_dev *pdev); void pcie_aspm_exit_link_state(struct pci_dev *pdev); @@ -686,6 +687,8 @@ extern const struct attribute_group aer_stats_attr_group; void pci_aer_clear_fatal_status(struct pci_dev *dev); int pci_aer_clear_status(struct pci_dev *dev); int pci_aer_raw_clear_status(struct pci_dev *dev); +void pci_save_aer_state(struct pci_dev *dev); +void pci_restore_aer_state(struct pci_dev *dev); #else static inline void pci_no_aer(void) { } static inline void pci_aer_init(struct pci_dev *d) { } @@ -693,6 +696,8 @@ static inline void pci_aer_exit(struct pci_dev *d) { } static inline void pci_aer_clear_fatal_status(struct pci_dev *dev) { } static inline int pci_aer_clear_status(struct pci_dev *dev) { return -EINVAL; } static inline int pci_aer_raw_clear_status(struct pci_dev *dev) { return -EINVAL; } +static inline void pci_save_aer_state(struct pci_dev *dev) { } +static inline void pci_restore_aer_state(struct pci_dev *dev) { } #endif #ifdef CONFIG_ACPI diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 66d7514ca111..3dafba0b5f41 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -90,8 +90,6 @@ static const char *policy_str[] = { [POLICY_POWER_SUPERSAVE] = "powersupersave" }; -#define LINK_RETRAIN_TIMEOUT HZ - /* * The L1 PM substate capability is only implemented in function 0 in a * multi function device. @@ -193,36 +191,6 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) link->clkpm_disable = blacklist ? 1 : 0; } -static bool pcie_retrain_link(struct pcie_link_state *link) -{ - struct pci_dev *parent = link->pdev; - unsigned long end_jiffies; - u16 reg16; - - pcie_capability_read_word(parent, PCI_EXP_LNKCTL, ®16); - reg16 |= PCI_EXP_LNKCTL_RL; - pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); - if (parent->clear_retrain_link) { - /* - * Due to an erratum in some devices the Retrain Link bit - * needs to be cleared again manually to allow the link - * training to succeed. - */ - reg16 &= ~PCI_EXP_LNKCTL_RL; - pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); - } - - /* Wait for link training end. Break out after waiting for timeout */ - end_jiffies = jiffies + LINK_RETRAIN_TIMEOUT; - do { - pcie_capability_read_word(parent, PCI_EXP_LNKSTA, ®16); - if (!(reg16 & PCI_EXP_LNKSTA_LT)) - break; - msleep(1); - } while (time_before(jiffies, end_jiffies)); - return !(reg16 & PCI_EXP_LNKSTA_LT); -} - /* * pcie_aspm_configure_common_clock: check if the 2 ends of a link * could use common clock. If they are, configure them to use the @@ -289,15 +257,15 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) reg16 &= ~PCI_EXP_LNKCTL_CCC; pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); - if (pcie_retrain_link(link)) - return; + if (pcie_retrain_link(link->pdev, true)) { - /* Training failed. Restore common clock configurations */ - pci_err(parent, "ASPM: Could not configure common clock\n"); - list_for_each_entry(child, &linkbus->devices, bus_list) - pcie_capability_write_word(child, PCI_EXP_LNKCTL, + /* Training failed. Restore common clock configurations */ + pci_err(parent, "ASPM: Could not configure common clock\n"); + list_for_each_entry(child, &linkbus->devices, bus_list) + pcie_capability_write_word(child, PCI_EXP_LNKCTL, child_reg[PCI_FUNC(child->devfn)]); - pcie_capability_write_word(parent, PCI_EXP_LNKCTL, parent_reg); + pcie_capability_write_word(parent, PCI_EXP_LNKCTL, parent_reg); + } } /* Convert L0s latency encoding to ns */ @@ -337,7 +305,7 @@ static u32 calc_l1_acceptable(u32 encoding) } /* Convert L1SS T_pwr encoding to usec */ -static u32 calc_l1ss_pwron(struct pci_dev *pdev, u32 scale, u32 val) +static u32 calc_l12_pwron(struct pci_dev *pdev, u32 scale, u32 val) { switch (scale) { case 0: @@ -471,7 +439,7 @@ static void pci_clear_and_set_dword(struct pci_dev *pdev, int pos, } /* Calculate L1.2 PM substate timing parameters */ -static void aspm_calc_l1ss_info(struct pcie_link_state *link, +static void aspm_calc_l12_info(struct pcie_link_state *link, u32 parent_l1ss_cap, u32 child_l1ss_cap) { struct pci_dev *child = link->downstream, *parent = link->pdev; @@ -481,9 +449,6 @@ static void aspm_calc_l1ss_info(struct pcie_link_state *link, u32 pctl1, pctl2, cctl1, cctl2; u32 pl1_2_enables, cl1_2_enables; - if (!(link->aspm_support & ASPM_STATE_L1_2_MASK)) - return; - /* Choose the greater of the two Port Common_Mode_Restore_Times */ val1 = (parent_l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8; val2 = (child_l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8; @@ -495,13 +460,13 @@ static void aspm_calc_l1ss_info(struct pcie_link_state *link, val2 = (child_l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_VALUE) >> 19; scale2 = (child_l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_SCALE) >> 16; - if (calc_l1ss_pwron(parent, scale1, val1) > - calc_l1ss_pwron(child, scale2, val2)) { + if (calc_l12_pwron(parent, scale1, val1) > + calc_l12_pwron(child, scale2, val2)) { ctl2 |= scale1 | (val1 << 3); - t_power_on = calc_l1ss_pwron(parent, scale1, val1); + t_power_on = calc_l12_pwron(parent, scale1, val1); } else { ctl2 |= scale2 | (val2 << 3); - t_power_on = calc_l1ss_pwron(child, scale2, val2); + t_power_on = calc_l12_pwron(child, scale2, val2); } /* @@ -616,8 +581,8 @@ static void aspm_l1ss_init(struct pcie_link_state *link) if (parent_l1ss_ctl1 & child_l1ss_ctl1 & PCI_L1SS_CTL1_PCIPM_L1_2) link->aspm_enabled |= ASPM_STATE_L1_2_PCIPM; - if (link->aspm_support & ASPM_STATE_L1SS) - aspm_calc_l1ss_info(link, parent_l1ss_cap, child_l1ss_cap); + if (link->aspm_support & ASPM_STATE_L1_2_MASK) + aspm_calc_l12_info(link, parent_l1ss_cap, child_l1ss_cap); } static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) @@ -1010,21 +975,24 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) down_read(&pci_bus_sem); mutex_lock(&aspm_lock); - /* - * All PCIe functions are in one slot, remove one function will remove - * the whole slot, so just wait until we are the last function left. - */ - if (!list_empty(&parent->subordinate->devices)) - goto out; link = parent->link_state; root = link->root; parent_link = link->parent; - /* All functions are removed, so just disable ASPM for the link */ + /* + * link->downstream is a pointer to the pci_dev of function 0. If + * we remove that function, the pci_dev is about to be deallocated, + * so we can't use link->downstream again. Free the link state to + * avoid this. + * + * If we're removing a non-0 function, it's possible we could + * retain the link state, but PCIe r6.0, sec 7.5.3.7, recommends + * programming the same ASPM Control value for all functions of + * multi-function devices, so disable ASPM for all of them. + */ pcie_config_aspm_link(link, 0); list_del(&link->sibling); - /* Clock PM is for endpoint device */ free_link_state(link); /* Recheck latencies and configure upstream links */ @@ -1032,7 +1000,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) pcie_update_aspm_capable(root); pcie_config_aspm_path(parent_link); } -out: + mutex_unlock(&aspm_lock); up_read(&pci_bus_sem); } @@ -1095,8 +1063,7 @@ static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem) if (state & PCIE_LINK_STATE_L0S) link->aspm_disable |= ASPM_STATE_L0S; if (state & PCIE_LINK_STATE_L1) - /* L1 PM substates require L1 */ - link->aspm_disable |= ASPM_STATE_L1 | ASPM_STATE_L1SS; + link->aspm_disable |= ASPM_STATE_L1; if (state & PCIE_LINK_STATE_L1_1) link->aspm_disable |= ASPM_STATE_L1_1; if (state & PCIE_LINK_STATE_L1_2) @@ -1171,16 +1138,16 @@ int pci_enable_link_state(struct pci_dev *pdev, int state) if (state & PCIE_LINK_STATE_L0S) link->aspm_default |= ASPM_STATE_L0S; if (state & PCIE_LINK_STATE_L1) - /* L1 PM substates require L1 */ - link->aspm_default |= ASPM_STATE_L1 | ASPM_STATE_L1SS; + link->aspm_default |= ASPM_STATE_L1; + /* L1 PM substates require L1 */ if (state & PCIE_LINK_STATE_L1_1) - link->aspm_default |= ASPM_STATE_L1_1; + link->aspm_default |= ASPM_STATE_L1_1 | ASPM_STATE_L1; if (state & PCIE_LINK_STATE_L1_2) - link->aspm_default |= ASPM_STATE_L1_2; + link->aspm_default |= ASPM_STATE_L1_2 | ASPM_STATE_L1; if (state & PCIE_LINK_STATE_L1_1_PCIPM) - link->aspm_default |= ASPM_STATE_L1_1_PCIPM; + link->aspm_default |= ASPM_STATE_L1_1_PCIPM | ASPM_STATE_L1; if (state & PCIE_LINK_STATE_L1_2_PCIPM) - link->aspm_default |= ASPM_STATE_L1_2_PCIPM; + link->aspm_default |= ASPM_STATE_L1_2_PCIPM | ASPM_STATE_L1; pcie_config_aspm_link(link, policy_to_aspm_state(link)); link->clkpm_default = (state & PCIE_LINK_STATE_CLKPM) ? 1 : 0; diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 0b2826c4a832..8bac3ce02609 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -820,7 +820,6 @@ static void pci_set_bus_speed(struct pci_bus *bus) pcie_capability_read_dword(bridge, PCI_EXP_LNKCAP, &linkcap); bus->max_bus_speed = pcie_link_speed[linkcap & PCI_EXP_LNKCAP_SLS]; - bridge->link_active_reporting = !!(linkcap & PCI_EXP_LNKCAP_DLLLARC); pcie_capability_read_word(bridge, PCI_EXP_LNKSTA, &linksta); pcie_update_link_speed(bus, linksta); @@ -997,8 +996,10 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge) resource_list_for_each_entry_safe(window, n, &resources) { offset = window->offset; res = window->res; - if (!res->flags && !res->start && !res->end) + if (!res->flags && !res->start && !res->end) { + release_resource(res); continue; + } list_move_tail(&window->node, &bridge->windows); @@ -1527,6 +1528,7 @@ void set_pcie_port_type(struct pci_dev *pdev) { int pos; u16 reg16; + u32 reg32; int type; struct pci_dev *parent; @@ -1540,6 +1542,10 @@ void set_pcie_port_type(struct pci_dev *pdev) pci_read_config_dword(pdev, pos + PCI_EXP_DEVCAP, &pdev->devcap); pdev->pcie_mpss = FIELD_GET(PCI_EXP_DEVCAP_PAYLOAD, pdev->devcap); + pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, ®32); + if (reg32 & PCI_EXP_LNKCAP_DLLLARC) + pdev->link_active_reporting = 1; + parent = pci_upstream_bridge(pdev); if (!parent) return; @@ -2546,6 +2552,8 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) dma_set_max_seg_size(&dev->dev, 65536); dma_set_seg_boundary(&dev->dev, 0xffffffff); + pcie_failed_link_retrain(dev); + /* Fix up broken headers */ pci_fixup_device(pci_fixup_header, dev); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index c525867760bf..321156ca273d 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -33,6 +33,99 @@ #include <linux/switchtec.h> #include "pci.h" +/* + * Retrain the link of a downstream PCIe port by hand if necessary. + * + * This is needed at least where a downstream port of the ASMedia ASM2824 + * Gen 3 switch is wired to the upstream port of the Pericom PI7C9X2G304 + * Gen 2 switch, and observed with the Delock Riser Card PCI Express x1 > + * 2 x PCIe x1 device, P/N 41433, plugged into the SiFive HiFive Unmatched + * board. + * + * In such a configuration the switches are supposed to negotiate the link + * speed of preferably 5.0GT/s, falling back to 2.5GT/s. However the link + * continues switching between the two speeds indefinitely and the data + * link layer never reaches the active state, with link training reported + * repeatedly active ~84% of the time. Forcing the target link speed to + * 2.5GT/s with the upstream ASM2824 device makes the two switches talk to + * each other correctly however. And more interestingly retraining with a + * higher target link speed afterwards lets the two successfully negotiate + * 5.0GT/s. + * + * With the ASM2824 we can rely on the otherwise optional Data Link Layer + * Link Active status bit and in the failed link training scenario it will + * be off along with the Link Bandwidth Management Status indicating that + * hardware has changed the link speed or width in an attempt to correct + * unreliable link operation. For a port that has been left unconnected + * both bits will be clear. So use this information to detect the problem + * rather than polling the Link Training bit and watching out for flips or + * at least the active status. + * + * Since the exact nature of the problem isn't known and in principle this + * could trigger where an ASM2824 device is downstream rather upstream, + * apply this erratum workaround to any downstream ports as long as they + * support Link Active reporting and have the Link Control 2 register. + * Restrict the speed to 2.5GT/s then with the Target Link Speed field, + * request a retrain and wait 200ms for the data link to go up. + * + * If this turns out successful and we know by the Vendor:Device ID it is + * safe to do so, then lift the restriction, letting the devices negotiate + * a higher speed. Also check for a similar 2.5GT/s speed restriction the + * firmware may have already arranged and lift it with ports that already + * report their data link being up. + * + * Return TRUE if the link has been successfully retrained, otherwise FALSE. + */ +bool pcie_failed_link_retrain(struct pci_dev *dev) +{ + static const struct pci_device_id ids[] = { + { PCI_VDEVICE(ASMEDIA, 0x2824) }, /* ASMedia ASM2824 */ + {} + }; + u16 lnksta, lnkctl2; + + if (!pci_is_pcie(dev) || !pcie_downstream_port(dev) || + !pcie_cap_has_lnkctl2(dev) || !dev->link_active_reporting) + return false; + + pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &lnkctl2); + pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta); + if ((lnksta & (PCI_EXP_LNKSTA_LBMS | PCI_EXP_LNKSTA_DLLLA)) == + PCI_EXP_LNKSTA_LBMS) { + pci_info(dev, "broken device, retraining non-functional downstream link at 2.5GT/s\n"); + + lnkctl2 &= ~PCI_EXP_LNKCTL2_TLS; + lnkctl2 |= PCI_EXP_LNKCTL2_TLS_2_5GT; + pcie_capability_write_word(dev, PCI_EXP_LNKCTL2, lnkctl2); + + if (pcie_retrain_link(dev, false)) { + pci_info(dev, "retraining failed\n"); + return false; + } + + pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta); + } + + if ((lnksta & PCI_EXP_LNKSTA_DLLLA) && + (lnkctl2 & PCI_EXP_LNKCTL2_TLS) == PCI_EXP_LNKCTL2_TLS_2_5GT && + pci_match_id(ids, dev)) { + u32 lnkcap; + + pci_info(dev, "removing 2.5GT/s downstream link speed restriction\n"); + pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap); + lnkctl2 &= ~PCI_EXP_LNKCTL2_TLS; + lnkctl2 |= lnkcap & PCI_EXP_LNKCAP_SLS; + pcie_capability_write_word(dev, PCI_EXP_LNKCTL2, lnkctl2); + + if (pcie_retrain_link(dev, false)) { + pci_info(dev, "retraining failed\n"); + return false; + } + } + + return true; +} + static ktime_t fixup_debug_start(struct pci_dev *dev, void (*fn)(struct pci_dev *dev)) { @@ -2420,9 +2513,9 @@ static void quirk_enable_clear_retrain_link(struct pci_dev *dev) dev->clear_retrain_link = 1; pci_info(dev, "Enable PCIe Retrain Link quirk\n"); } -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PERICOM, 0xe110, quirk_enable_clear_retrain_link); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PERICOM, 0xe111, quirk_enable_clear_retrain_link); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PERICOM, 0xe130, quirk_enable_clear_retrain_link); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PERICOM, 0xe110, quirk_enable_clear_retrain_link); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PERICOM, 0xe111, quirk_enable_clear_retrain_link); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PERICOM, 0xe130, quirk_enable_clear_retrain_link); static void fixup_rev1_53c810(struct pci_dev *dev) { @@ -3993,10 +4086,11 @@ static int nvme_disable_and_flr(struct pci_dev *dev, bool probe) } /* - * Intel DC P3700 NVMe controller will timeout waiting for ready status - * to change after NVMe enable if the driver starts interacting with the - * device too soon after FLR. A 250ms delay after FLR has heuristically - * proven to produce reliably working results for device assignment cases. + * Some NVMe controllers such as Intel DC P3700 and Solidigm P44 Pro will + * timeout waiting for ready status to change after NVMe enable if the driver + * starts interacting with the device too soon after FLR. A 250ms delay after + * FLR has heuristically proven to produce reliably working results for device + * assignment cases. */ static int delay_250ms_after_flr(struct pci_dev *dev, bool probe) { @@ -4083,6 +4177,7 @@ static const struct pci_dev_reset_methods pci_dev_reset_methods[] = { { PCI_VENDOR_ID_SAMSUNG, 0xa804, nvme_disable_and_flr }, { PCI_VENDOR_ID_INTEL, 0x0953, delay_250ms_after_flr }, { PCI_VENDOR_ID_INTEL, 0x0a54, delay_250ms_after_flr }, + { PCI_VENDOR_ID_SOLIDIGM, 0xf1ac, delay_250ms_after_flr }, { PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID, reset_chelsio_generic_dev }, { PCI_VENDOR_ID_HUAWEI, PCI_DEVICE_ID_HINIC_VF, @@ -4174,6 +4269,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9220, /* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c49 */ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9230, quirk_dma_func1_alias); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9235, + quirk_dma_func1_alias); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TTI, 0x0642, quirk_dma_func1_alias); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TTI, 0x0645, diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig index 4c07d71cab0b..f4572a5cca72 100644 --- a/drivers/perf/Kconfig +++ b/drivers/perf/Kconfig @@ -221,4 +221,17 @@ source "drivers/perf/arm_cspmu/Kconfig" source "drivers/perf/amlogic/Kconfig" +config CXL_PMU + tristate "CXL Performance Monitoring Unit" + depends on CXL_BUS + help + Support performance monitoring as defined in CXL rev 3.0 + section 13.2: Performance Monitoring. CXL components may have + one or more CXL Performance Monitoring Units (CPMUs). + + Say 'y/m' to enable a driver that will attach to performance + monitoring units and provide standard perf based interfaces. + + If unsure say 'm'. + endmenu diff --git a/drivers/perf/Makefile b/drivers/perf/Makefile index 5cfe8954c250..16b3ec4db916 100644 --- a/drivers/perf/Makefile +++ b/drivers/perf/Makefile @@ -25,3 +25,4 @@ obj-$(CONFIG_APPLE_M1_CPU_PMU) += apple_m1_cpu_pmu.o obj-$(CONFIG_ALIBABA_UNCORE_DRW_PMU) += alibaba_uncore_drw_pmu.o obj-$(CONFIG_ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU) += arm_cspmu/ obj-$(CONFIG_MESON_DDR_PMU) += amlogic/ +obj-$(CONFIG_CXL_PMU) += cxl_pmu.o diff --git a/drivers/perf/cxl_pmu.c b/drivers/perf/cxl_pmu.c new file mode 100644 index 000000000000..0a8f597e695b --- /dev/null +++ b/drivers/perf/cxl_pmu.c @@ -0,0 +1,990 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/* + * Copyright(c) 2023 Huawei + * + * The CXL 3.0 specification includes a standard Performance Monitoring Unit, + * called the CXL PMU, or CPMU. In order to allow a high degree of + * implementation flexibility the specification provides a wide range of + * options all of which are self describing. + * + * Details in CXL rev 3.0 section 8.2.7 CPMU Register Interface + */ + +#include <linux/io-64-nonatomic-lo-hi.h> +#include <linux/perf_event.h> +#include <linux/bitops.h> +#include <linux/device.h> +#include <linux/bits.h> +#include <linux/list.h> +#include <linux/bug.h> +#include <linux/pci.h> + +#include "../cxl/cxlpci.h" +#include "../cxl/cxl.h" +#include "../cxl/pmu.h" + +#define CXL_PMU_CAP_REG 0x0 +#define CXL_PMU_CAP_NUM_COUNTERS_MSK GENMASK_ULL(4, 0) +#define CXL_PMU_CAP_COUNTER_WIDTH_MSK GENMASK_ULL(15, 8) +#define CXL_PMU_CAP_NUM_EVN_CAP_REG_SUP_MSK GENMASK_ULL(24, 20) +#define CXL_PMU_CAP_FILTERS_SUP_MSK GENMASK_ULL(39, 32) +#define CXL_PMU_FILTER_HDM BIT(0) +#define CXL_PMU_FILTER_CHAN_RANK_BANK BIT(1) +#define CXL_PMU_CAP_MSI_N_MSK GENMASK_ULL(47, 44) +#define CXL_PMU_CAP_WRITEABLE_WHEN_FROZEN BIT_ULL(48) +#define CXL_PMU_CAP_FREEZE BIT_ULL(49) +#define CXL_PMU_CAP_INT BIT_ULL(50) +#define CXL_PMU_CAP_VERSION_MSK GENMASK_ULL(63, 60) + +#define CXL_PMU_OVERFLOW_REG 0x10 +#define CXL_PMU_FREEZE_REG 0x18 +#define CXL_PMU_EVENT_CAP_REG(n) (0x100 + 8 * (n)) +#define CXL_PMU_EVENT_CAP_SUPPORTED_EVENTS_MSK GENMASK_ULL(31, 0) +#define CXL_PMU_EVENT_CAP_GROUP_ID_MSK GENMASK_ULL(47, 32) +#define CXL_PMU_EVENT_CAP_VENDOR_ID_MSK GENMASK_ULL(63, 48) + +#define CXL_PMU_COUNTER_CFG_REG(n) (0x200 + 8 * (n)) +#define CXL_PMU_COUNTER_CFG_TYPE_MSK GENMASK_ULL(1, 0) +#define CXL_PMU_COUNTER_CFG_TYPE_FREE_RUN 0 +#define CXL_PMU_COUNTER_CFG_TYPE_FIXED_FUN 1 +#define CXL_PMU_COUNTER_CFG_TYPE_CONFIGURABLE 2 +#define CXL_PMU_COUNTER_CFG_ENABLE BIT_ULL(8) +#define CXL_PMU_COUNTER_CFG_INT_ON_OVRFLW BIT_ULL(9) +#define CXL_PMU_COUNTER_CFG_FREEZE_ON_OVRFLW BIT_ULL(10) +#define CXL_PMU_COUNTER_CFG_EDGE BIT_ULL(11) +#define CXL_PMU_COUNTER_CFG_INVERT BIT_ULL(12) +#define CXL_PMU_COUNTER_CFG_THRESHOLD_MSK GENMASK_ULL(23, 16) +#define CXL_PMU_COUNTER_CFG_EVENTS_MSK GENMASK_ULL(55, 24) +#define CXL_PMU_COUNTER_CFG_EVENT_GRP_ID_IDX_MSK GENMASK_ULL(63, 59) + +#define CXL_PMU_FILTER_CFG_REG(n, f) (0x400 + 4 * ((f) + (n) * 8)) +#define CXL_PMU_FILTER_CFG_VALUE_MSK GENMASK(15, 0) + +#define CXL_PMU_COUNTER_REG(n) (0xc00 + 8 * (n)) + +/* CXL rev 3.0 Table 13-5 Events under CXL Vendor ID */ +#define CXL_PMU_GID_CLOCK_TICKS 0x00 +#define CXL_PMU_GID_D2H_REQ 0x0010 +#define CXL_PMU_GID_D2H_RSP 0x0011 +#define CXL_PMU_GID_H2D_REQ 0x0012 +#define CXL_PMU_GID_H2D_RSP 0x0013 +#define CXL_PMU_GID_CACHE_DATA 0x0014 +#define CXL_PMU_GID_M2S_REQ 0x0020 +#define CXL_PMU_GID_M2S_RWD 0x0021 +#define CXL_PMU_GID_M2S_BIRSP 0x0022 +#define CXL_PMU_GID_S2M_BISNP 0x0023 +#define CXL_PMU_GID_S2M_NDR 0x0024 +#define CXL_PMU_GID_S2M_DRS 0x0025 +#define CXL_PMU_GID_DDR 0x8000 + +static int cxl_pmu_cpuhp_state_num; + +struct cxl_pmu_ev_cap { + u16 vid; + u16 gid; + u32 msk; + union { + int counter_idx; /* fixed counters */ + int event_idx; /* configurable counters */ + }; + struct list_head node; +}; + +#define CXL_PMU_MAX_COUNTERS 64 +struct cxl_pmu_info { + struct pmu pmu; + void __iomem *base; + struct perf_event **hw_events; + struct list_head event_caps_configurable; + struct list_head event_caps_fixed; + DECLARE_BITMAP(used_counter_bm, CXL_PMU_MAX_COUNTERS); + DECLARE_BITMAP(conf_counter_bm, CXL_PMU_MAX_COUNTERS); + u16 counter_width; + u8 num_counters; + u8 num_event_capabilities; + int on_cpu; + struct hlist_node node; + bool filter_hdm; + int irq; +}; + +#define pmu_to_cxl_pmu_info(_pmu) container_of(_pmu, struct cxl_pmu_info, pmu) + +/* + * All CPMU counters are discoverable via the Event Capabilities Registers. + * Each Event Capability register contains a a VID / GroupID. + * A counter may then count any combination (by summing) of events in + * that group which are in the Supported Events Bitmask. + * However, there are some complexities to the scheme. + * - Fixed function counters refer to an Event Capabilities register. + * That event capability register is not then used for Configurable + * counters. + */ +static int cxl_pmu_parse_caps(struct device *dev, struct cxl_pmu_info *info) +{ + unsigned long fixed_counter_event_cap_bm = 0; + void __iomem *base = info->base; + bool freeze_for_enable; + u64 val, eval; + int i; + + val = readq(base + CXL_PMU_CAP_REG); + freeze_for_enable = FIELD_GET(CXL_PMU_CAP_WRITEABLE_WHEN_FROZEN, val) && + FIELD_GET(CXL_PMU_CAP_FREEZE, val); + if (!freeze_for_enable) { + dev_err(dev, "Counters not writable while frozen\n"); + return -ENODEV; + } + + info->num_counters = FIELD_GET(CXL_PMU_CAP_NUM_COUNTERS_MSK, val) + 1; + info->counter_width = FIELD_GET(CXL_PMU_CAP_COUNTER_WIDTH_MSK, val); + info->num_event_capabilities = FIELD_GET(CXL_PMU_CAP_NUM_EVN_CAP_REG_SUP_MSK, val) + 1; + + info->filter_hdm = FIELD_GET(CXL_PMU_CAP_FILTERS_SUP_MSK, val) & CXL_PMU_FILTER_HDM; + if (FIELD_GET(CXL_PMU_CAP_INT, val)) + info->irq = FIELD_GET(CXL_PMU_CAP_MSI_N_MSK, val); + else + info->irq = -1; + + /* First handle fixed function counters; note if configurable counters found */ + for (i = 0; i < info->num_counters; i++) { + struct cxl_pmu_ev_cap *pmu_ev; + u32 events_msk; + u8 group_idx; + + val = readq(base + CXL_PMU_COUNTER_CFG_REG(i)); + + if (FIELD_GET(CXL_PMU_COUNTER_CFG_TYPE_MSK, val) == + CXL_PMU_COUNTER_CFG_TYPE_CONFIGURABLE) { + set_bit(i, info->conf_counter_bm); + } + + if (FIELD_GET(CXL_PMU_COUNTER_CFG_TYPE_MSK, val) != + CXL_PMU_COUNTER_CFG_TYPE_FIXED_FUN) + continue; + + /* In this case we know which fields are const */ + group_idx = FIELD_GET(CXL_PMU_COUNTER_CFG_EVENT_GRP_ID_IDX_MSK, val); + events_msk = FIELD_GET(CXL_PMU_COUNTER_CFG_EVENTS_MSK, val); + eval = readq(base + CXL_PMU_EVENT_CAP_REG(group_idx)); + pmu_ev = devm_kzalloc(dev, sizeof(*pmu_ev), GFP_KERNEL); + if (!pmu_ev) + return -ENOMEM; + + pmu_ev->vid = FIELD_GET(CXL_PMU_EVENT_CAP_VENDOR_ID_MSK, eval); + pmu_ev->gid = FIELD_GET(CXL_PMU_EVENT_CAP_GROUP_ID_MSK, eval); + /* For a fixed purpose counter use the events mask from the counter CFG */ + pmu_ev->msk = events_msk; + pmu_ev->counter_idx = i; + /* This list add is never unwound as all entries deleted on remove */ + list_add(&pmu_ev->node, &info->event_caps_fixed); + /* + * Configurable counters must not use an Event Capability registers that + * is in use for a Fixed counter + */ + set_bit(group_idx, &fixed_counter_event_cap_bm); + } + + if (!bitmap_empty(info->conf_counter_bm, CXL_PMU_MAX_COUNTERS)) { + struct cxl_pmu_ev_cap *pmu_ev; + int j; + /* Walk event capabilities unused by fixed counters */ + for_each_clear_bit(j, &fixed_counter_event_cap_bm, + info->num_event_capabilities) { + pmu_ev = devm_kzalloc(dev, sizeof(*pmu_ev), GFP_KERNEL); + if (!pmu_ev) + return -ENOMEM; + + eval = readq(base + CXL_PMU_EVENT_CAP_REG(j)); + pmu_ev->vid = FIELD_GET(CXL_PMU_EVENT_CAP_VENDOR_ID_MSK, eval); + pmu_ev->gid = FIELD_GET(CXL_PMU_EVENT_CAP_GROUP_ID_MSK, eval); + pmu_ev->msk = FIELD_GET(CXL_PMU_EVENT_CAP_SUPPORTED_EVENTS_MSK, eval); + pmu_ev->event_idx = j; + list_add(&pmu_ev->node, &info->event_caps_configurable); + } + } + + return 0; +} + +static ssize_t cxl_pmu_format_sysfs_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct dev_ext_attribute *eattr; + + eattr = container_of(attr, struct dev_ext_attribute, attr); + + return sysfs_emit(buf, "%s\n", (char *)eattr->var); +} + +#define CXL_PMU_FORMAT_ATTR(_name, _format)\ + (&((struct dev_ext_attribute[]) { \ + { \ + .attr = __ATTR(_name, 0444, \ + cxl_pmu_format_sysfs_show, NULL), \ + .var = (void *)_format \ + } \ + })[0].attr.attr) + +enum { + cxl_pmu_mask_attr, + cxl_pmu_gid_attr, + cxl_pmu_vid_attr, + cxl_pmu_threshold_attr, + cxl_pmu_invert_attr, + cxl_pmu_edge_attr, + cxl_pmu_hdm_filter_en_attr, + cxl_pmu_hdm_attr, +}; + +static struct attribute *cxl_pmu_format_attr[] = { + [cxl_pmu_mask_attr] = CXL_PMU_FORMAT_ATTR(mask, "config:0-31"), + [cxl_pmu_gid_attr] = CXL_PMU_FORMAT_ATTR(gid, "config:32-47"), + [cxl_pmu_vid_attr] = CXL_PMU_FORMAT_ATTR(vid, "config:48-63"), + [cxl_pmu_threshold_attr] = CXL_PMU_FORMAT_ATTR(threshold, "config1:0-15"), + [cxl_pmu_invert_attr] = CXL_PMU_FORMAT_ATTR(invert, "config1:16"), + [cxl_pmu_edge_attr] = CXL_PMU_FORMAT_ATTR(edge, "config1:17"), + [cxl_pmu_hdm_filter_en_attr] = CXL_PMU_FORMAT_ATTR(hdm_filter_en, "config1:18"), + [cxl_pmu_hdm_attr] = CXL_PMU_FORMAT_ATTR(hdm, "config2:0-15"), + NULL +}; + +#define CXL_PMU_ATTR_CONFIG_MASK_MSK GENMASK_ULL(31, 0) +#define CXL_PMU_ATTR_CONFIG_GID_MSK GENMASK_ULL(47, 32) +#define CXL_PMU_ATTR_CONFIG_VID_MSK GENMASK_ULL(63, 48) +#define CXL_PMU_ATTR_CONFIG1_THRESHOLD_MSK GENMASK_ULL(15, 0) +#define CXL_PMU_ATTR_CONFIG1_INVERT_MSK BIT(16) +#define CXL_PMU_ATTR_CONFIG1_EDGE_MSK BIT(17) +#define CXL_PMU_ATTR_CONFIG1_FILTER_EN_MSK BIT(18) +#define CXL_PMU_ATTR_CONFIG2_HDM_MSK GENMASK(15, 0) + +static umode_t cxl_pmu_format_is_visible(struct kobject *kobj, + struct attribute *attr, int a) +{ + struct device *dev = kobj_to_dev(kobj); + struct cxl_pmu_info *info = dev_get_drvdata(dev); + + /* + * Filter capability at the CPMU level, so hide the attributes if the particular + * filter is not supported. + */ + if (!info->filter_hdm && + (attr == cxl_pmu_format_attr[cxl_pmu_hdm_filter_en_attr] || + attr == cxl_pmu_format_attr[cxl_pmu_hdm_attr])) + return 0; + + return attr->mode; +} + +static const struct attribute_group cxl_pmu_format_group = { + .name = "format", + .attrs = cxl_pmu_format_attr, + .is_visible = cxl_pmu_format_is_visible, +}; + +static u32 cxl_pmu_config_get_mask(struct perf_event *event) +{ + return FIELD_GET(CXL_PMU_ATTR_CONFIG_MASK_MSK, event->attr.config); +} + +static u16 cxl_pmu_config_get_gid(struct perf_event *event) +{ + return FIELD_GET(CXL_PMU_ATTR_CONFIG_GID_MSK, event->attr.config); +} + +static u16 cxl_pmu_config_get_vid(struct perf_event *event) +{ + return FIELD_GET(CXL_PMU_ATTR_CONFIG_VID_MSK, event->attr.config); +} + +static u8 cxl_pmu_config1_get_threshold(struct perf_event *event) +{ + return FIELD_GET(CXL_PMU_ATTR_CONFIG1_THRESHOLD_MSK, event->attr.config1); +} + +static bool cxl_pmu_config1_get_invert(struct perf_event *event) +{ + return FIELD_GET(CXL_PMU_ATTR_CONFIG1_INVERT_MSK, event->attr.config1); +} + +static bool cxl_pmu_config1_get_edge(struct perf_event *event) +{ + return FIELD_GET(CXL_PMU_ATTR_CONFIG1_EDGE_MSK, event->attr.config1); +} + +/* + * CPMU specification allows for 8 filters, each with a 16 bit value... + * So we need to find 8x16bits to store it in. + * As the value used for disable is 0xffff, a separate enable switch + * is needed. + */ + +static bool cxl_pmu_config1_hdm_filter_en(struct perf_event *event) +{ + return FIELD_GET(CXL_PMU_ATTR_CONFIG1_FILTER_EN_MSK, event->attr.config1); +} + +static u16 cxl_pmu_config2_get_hdm_decoder(struct perf_event *event) +{ + return FIELD_GET(CXL_PMU_ATTR_CONFIG2_HDM_MSK, event->attr.config2); +} + +static ssize_t cxl_pmu_event_sysfs_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct perf_pmu_events_attr *pmu_attr = + container_of(attr, struct perf_pmu_events_attr, attr); + + return sysfs_emit(buf, "config=%#llx\n", pmu_attr->id); +} + +#define CXL_PMU_EVENT_ATTR(_name, _vid, _gid, _msk) \ + PMU_EVENT_ATTR_ID(_name, cxl_pmu_event_sysfs_show, \ + ((u64)(_vid) << 48) | ((u64)(_gid) << 32) | (u64)(_msk)) + +/* For CXL spec defined events */ +#define CXL_PMU_EVENT_CXL_ATTR(_name, _gid, _msk) \ + CXL_PMU_EVENT_ATTR(_name, PCI_DVSEC_VENDOR_ID_CXL, _gid, _msk) + +static struct attribute *cxl_pmu_event_attrs[] = { + CXL_PMU_EVENT_CXL_ATTR(clock_ticks, CXL_PMU_GID_CLOCK_TICKS, BIT(0)), + /* CXL rev 3.0 Table 3-17 - Device to Host Requests */ + CXL_PMU_EVENT_CXL_ATTR(d2h_req_rdcurr, CXL_PMU_GID_D2H_REQ, BIT(1)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_rdown, CXL_PMU_GID_D2H_REQ, BIT(2)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_rdshared, CXL_PMU_GID_D2H_REQ, BIT(3)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_rdany, CXL_PMU_GID_D2H_REQ, BIT(4)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_rdownnodata, CXL_PMU_GID_D2H_REQ, BIT(5)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_itomwr, CXL_PMU_GID_D2H_REQ, BIT(6)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_wrcurr, CXL_PMU_GID_D2H_REQ, BIT(7)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_clflush, CXL_PMU_GID_D2H_REQ, BIT(8)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_cleanevict, CXL_PMU_GID_D2H_REQ, BIT(9)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_dirtyevict, CXL_PMU_GID_D2H_REQ, BIT(10)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_cleanevictnodata, CXL_PMU_GID_D2H_REQ, BIT(11)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_wowrinv, CXL_PMU_GID_D2H_REQ, BIT(12)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_wowrinvf, CXL_PMU_GID_D2H_REQ, BIT(13)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_wrinv, CXL_PMU_GID_D2H_REQ, BIT(14)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_cacheflushed, CXL_PMU_GID_D2H_REQ, BIT(16)), + /* CXL rev 3.0 Table 3-20 - D2H Repsonse Encodings */ + CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspihiti, CXL_PMU_GID_D2H_RSP, BIT(4)), + CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspvhitv, CXL_PMU_GID_D2H_RSP, BIT(6)), + CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspihitse, CXL_PMU_GID_D2H_RSP, BIT(5)), + CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspshitse, CXL_PMU_GID_D2H_RSP, BIT(1)), + CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspsfwdm, CXL_PMU_GID_D2H_RSP, BIT(7)), + CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspifwdm, CXL_PMU_GID_D2H_RSP, BIT(15)), + CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspvfwdv, CXL_PMU_GID_D2H_RSP, BIT(22)), + /* CXL rev 3.0 Table 3-21 - CXL.cache - Mapping of H2D Requests to D2H Responses */ + CXL_PMU_EVENT_CXL_ATTR(h2d_req_snpdata, CXL_PMU_GID_H2D_REQ, BIT(1)), + CXL_PMU_EVENT_CXL_ATTR(h2d_req_snpinv, CXL_PMU_GID_H2D_REQ, BIT(2)), + CXL_PMU_EVENT_CXL_ATTR(h2d_req_snpcur, CXL_PMU_GID_H2D_REQ, BIT(3)), + /* CXL rev 3.0 Table 3-22 - H2D Response Opcode Encodings */ + CXL_PMU_EVENT_CXL_ATTR(h2d_rsp_writepull, CXL_PMU_GID_H2D_RSP, BIT(1)), + CXL_PMU_EVENT_CXL_ATTR(h2d_rsp_go, CXL_PMU_GID_H2D_RSP, BIT(4)), + CXL_PMU_EVENT_CXL_ATTR(h2d_rsp_gowritepull, CXL_PMU_GID_H2D_RSP, BIT(5)), + CXL_PMU_EVENT_CXL_ATTR(h2d_rsp_extcmp, CXL_PMU_GID_H2D_RSP, BIT(6)), + CXL_PMU_EVENT_CXL_ATTR(h2d_rsp_gowritepulldrop, CXL_PMU_GID_H2D_RSP, BIT(8)), + CXL_PMU_EVENT_CXL_ATTR(h2d_rsp_fastgowritepull, CXL_PMU_GID_H2D_RSP, BIT(13)), + CXL_PMU_EVENT_CXL_ATTR(h2d_rsp_goerrwritepull, CXL_PMU_GID_H2D_RSP, BIT(15)), + /* CXL rev 3.0 Table 13-5 directly lists these */ + CXL_PMU_EVENT_CXL_ATTR(cachedata_d2h_data, CXL_PMU_GID_CACHE_DATA, BIT(0)), + CXL_PMU_EVENT_CXL_ATTR(cachedata_h2d_data, CXL_PMU_GID_CACHE_DATA, BIT(1)), + /* CXL rev 3.0 Table 3-29 M2S Req Memory Opcodes */ + CXL_PMU_EVENT_CXL_ATTR(m2s_req_meminv, CXL_PMU_GID_M2S_REQ, BIT(0)), + CXL_PMU_EVENT_CXL_ATTR(m2s_req_memrd, CXL_PMU_GID_M2S_REQ, BIT(1)), + CXL_PMU_EVENT_CXL_ATTR(m2s_req_memrddata, CXL_PMU_GID_M2S_REQ, BIT(2)), + CXL_PMU_EVENT_CXL_ATTR(m2s_req_memrdfwd, CXL_PMU_GID_M2S_REQ, BIT(3)), + CXL_PMU_EVENT_CXL_ATTR(m2s_req_memwrfwd, CXL_PMU_GID_M2S_REQ, BIT(4)), + CXL_PMU_EVENT_CXL_ATTR(m2s_req_memspecrd, CXL_PMU_GID_M2S_REQ, BIT(8)), + CXL_PMU_EVENT_CXL_ATTR(m2s_req_meminvnt, CXL_PMU_GID_M2S_REQ, BIT(9)), + CXL_PMU_EVENT_CXL_ATTR(m2s_req_memcleanevict, CXL_PMU_GID_M2S_REQ, BIT(10)), + /* CXL rev 3.0 Table 3-35 M2S RwD Memory Opcodes */ + CXL_PMU_EVENT_CXL_ATTR(m2s_rwd_memwr, CXL_PMU_GID_M2S_RWD, BIT(1)), + CXL_PMU_EVENT_CXL_ATTR(m2s_rwd_memwrptl, CXL_PMU_GID_M2S_RWD, BIT(2)), + CXL_PMU_EVENT_CXL_ATTR(m2s_rwd_biconflict, CXL_PMU_GID_M2S_RWD, BIT(4)), + /* CXL rev 3.0 Table 3-38 M2S BIRsp Memory Opcodes */ + CXL_PMU_EVENT_CXL_ATTR(m2s_birsp_i, CXL_PMU_GID_M2S_BIRSP, BIT(0)), + CXL_PMU_EVENT_CXL_ATTR(m2s_birsp_s, CXL_PMU_GID_M2S_BIRSP, BIT(1)), + CXL_PMU_EVENT_CXL_ATTR(m2s_birsp_e, CXL_PMU_GID_M2S_BIRSP, BIT(2)), + CXL_PMU_EVENT_CXL_ATTR(m2s_birsp_iblk, CXL_PMU_GID_M2S_BIRSP, BIT(4)), + CXL_PMU_EVENT_CXL_ATTR(m2s_birsp_sblk, CXL_PMU_GID_M2S_BIRSP, BIT(5)), + CXL_PMU_EVENT_CXL_ATTR(m2s_birsp_eblk, CXL_PMU_GID_M2S_BIRSP, BIT(6)), + /* CXL rev 3.0 Table 3-40 S2M BISnp Opcodes */ + CXL_PMU_EVENT_CXL_ATTR(s2m_bisnp_cur, CXL_PMU_GID_S2M_BISNP, BIT(0)), + CXL_PMU_EVENT_CXL_ATTR(s2m_bisnp_data, CXL_PMU_GID_S2M_BISNP, BIT(1)), + CXL_PMU_EVENT_CXL_ATTR(s2m_bisnp_inv, CXL_PMU_GID_S2M_BISNP, BIT(2)), + CXL_PMU_EVENT_CXL_ATTR(s2m_bisnp_curblk, CXL_PMU_GID_S2M_BISNP, BIT(4)), + CXL_PMU_EVENT_CXL_ATTR(s2m_bisnp_datblk, CXL_PMU_GID_S2M_BISNP, BIT(5)), + CXL_PMU_EVENT_CXL_ATTR(s2m_bisnp_invblk, CXL_PMU_GID_S2M_BISNP, BIT(6)), + /* CXL rev 3.0 Table 3-43 S2M NDR Opcopdes */ + CXL_PMU_EVENT_CXL_ATTR(s2m_ndr_cmp, CXL_PMU_GID_S2M_NDR, BIT(0)), + CXL_PMU_EVENT_CXL_ATTR(s2m_ndr_cmps, CXL_PMU_GID_S2M_NDR, BIT(1)), + CXL_PMU_EVENT_CXL_ATTR(s2m_ndr_cmpe, CXL_PMU_GID_S2M_NDR, BIT(2)), + CXL_PMU_EVENT_CXL_ATTR(s2m_ndr_biconflictack, CXL_PMU_GID_S2M_NDR, BIT(3)), + /* CXL rev 3.0 Table 3-46 S2M DRS opcodes */ + CXL_PMU_EVENT_CXL_ATTR(s2m_drs_memdata, CXL_PMU_GID_S2M_DRS, BIT(0)), + CXL_PMU_EVENT_CXL_ATTR(s2m_drs_memdatanxm, CXL_PMU_GID_S2M_DRS, BIT(1)), + /* CXL rev 3.0 Table 13-5 directly lists these */ + CXL_PMU_EVENT_CXL_ATTR(ddr_act, CXL_PMU_GID_DDR, BIT(0)), + CXL_PMU_EVENT_CXL_ATTR(ddr_pre, CXL_PMU_GID_DDR, BIT(1)), + CXL_PMU_EVENT_CXL_ATTR(ddr_casrd, CXL_PMU_GID_DDR, BIT(2)), + CXL_PMU_EVENT_CXL_ATTR(ddr_caswr, CXL_PMU_GID_DDR, BIT(3)), + CXL_PMU_EVENT_CXL_ATTR(ddr_refresh, CXL_PMU_GID_DDR, BIT(4)), + CXL_PMU_EVENT_CXL_ATTR(ddr_selfrefreshent, CXL_PMU_GID_DDR, BIT(5)), + CXL_PMU_EVENT_CXL_ATTR(ddr_rfm, CXL_PMU_GID_DDR, BIT(6)), + NULL +}; + +static struct cxl_pmu_ev_cap *cxl_pmu_find_fixed_counter_ev_cap(struct cxl_pmu_info *info, + int vid, int gid, int msk) +{ + struct cxl_pmu_ev_cap *pmu_ev; + + list_for_each_entry(pmu_ev, &info->event_caps_fixed, node) { + if (vid != pmu_ev->vid || gid != pmu_ev->gid) + continue; + + /* Precise match for fixed counter */ + if (msk == pmu_ev->msk) + return pmu_ev; + } + + return ERR_PTR(-EINVAL); +} + +static struct cxl_pmu_ev_cap *cxl_pmu_find_config_counter_ev_cap(struct cxl_pmu_info *info, + int vid, int gid, int msk) +{ + struct cxl_pmu_ev_cap *pmu_ev; + + list_for_each_entry(pmu_ev, &info->event_caps_configurable, node) { + if (vid != pmu_ev->vid || gid != pmu_ev->gid) + continue; + + /* Request mask must be subset of supported */ + if (msk & ~pmu_ev->msk) + continue; + + return pmu_ev; + } + + return ERR_PTR(-EINVAL); +} + +static umode_t cxl_pmu_event_is_visible(struct kobject *kobj, struct attribute *attr, int a) +{ + struct device_attribute *dev_attr = container_of(attr, struct device_attribute, attr); + struct perf_pmu_events_attr *pmu_attr = + container_of(dev_attr, struct perf_pmu_events_attr, attr); + struct device *dev = kobj_to_dev(kobj); + struct cxl_pmu_info *info = dev_get_drvdata(dev); + int vid = FIELD_GET(CXL_PMU_ATTR_CONFIG_VID_MSK, pmu_attr->id); + int gid = FIELD_GET(CXL_PMU_ATTR_CONFIG_GID_MSK, pmu_attr->id); + int msk = FIELD_GET(CXL_PMU_ATTR_CONFIG_MASK_MSK, pmu_attr->id); + + if (!IS_ERR(cxl_pmu_find_fixed_counter_ev_cap(info, vid, gid, msk))) + return attr->mode; + + if (!IS_ERR(cxl_pmu_find_config_counter_ev_cap(info, vid, gid, msk))) + return attr->mode; + + return 0; +} + +static const struct attribute_group cxl_pmu_events = { + .name = "events", + .attrs = cxl_pmu_event_attrs, + .is_visible = cxl_pmu_event_is_visible, +}; + +static ssize_t cpumask_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct cxl_pmu_info *info = dev_get_drvdata(dev); + + return cpumap_print_to_pagebuf(true, buf, cpumask_of(info->on_cpu)); +} +static DEVICE_ATTR_RO(cpumask); + +static struct attribute *cxl_pmu_cpumask_attrs[] = { + &dev_attr_cpumask.attr, + NULL +}; + +static const struct attribute_group cxl_pmu_cpumask_group = { + .attrs = cxl_pmu_cpumask_attrs, +}; + +static const struct attribute_group *cxl_pmu_attr_groups[] = { + &cxl_pmu_events, + &cxl_pmu_format_group, + &cxl_pmu_cpumask_group, + NULL +}; + +/* If counter_idx == NULL, don't try to allocate a counter. */ +static int cxl_pmu_get_event_idx(struct perf_event *event, int *counter_idx, + int *event_idx) +{ + struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu); + DECLARE_BITMAP(configurable_and_free, CXL_PMU_MAX_COUNTERS); + struct cxl_pmu_ev_cap *pmu_ev; + u32 mask; + u16 gid, vid; + int i; + + vid = cxl_pmu_config_get_vid(event); + gid = cxl_pmu_config_get_gid(event); + mask = cxl_pmu_config_get_mask(event); + + pmu_ev = cxl_pmu_find_fixed_counter_ev_cap(info, vid, gid, mask); + if (!IS_ERR(pmu_ev)) { + if (!counter_idx) + return 0; + if (!test_bit(pmu_ev->counter_idx, info->used_counter_bm)) { + *counter_idx = pmu_ev->counter_idx; + return 0; + } + /* Fixed counter is in use, but maybe a configurable one? */ + } + + pmu_ev = cxl_pmu_find_config_counter_ev_cap(info, vid, gid, mask); + if (!IS_ERR(pmu_ev)) { + if (!counter_idx) + return 0; + + bitmap_andnot(configurable_and_free, info->conf_counter_bm, + info->used_counter_bm, CXL_PMU_MAX_COUNTERS); + + i = find_first_bit(configurable_and_free, CXL_PMU_MAX_COUNTERS); + if (i == CXL_PMU_MAX_COUNTERS) + return -EINVAL; + + *counter_idx = i; + return 0; + } + + return -EINVAL; +} + +static int cxl_pmu_event_init(struct perf_event *event) +{ + struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu); + int rc; + + /* Top level type sanity check - is this a Hardware Event being requested */ + if (event->attr.type != event->pmu->type) + return -ENOENT; + + if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK) + return -EOPNOTSUPP; + /* TODO: Validation of any filter */ + + /* + * Verify that it is possible to count what was requested. Either must + * be a fixed counter that is a precise match or a configurable counter + * where this is a subset. + */ + rc = cxl_pmu_get_event_idx(event, NULL, NULL); + if (rc < 0) + return rc; + + event->cpu = info->on_cpu; + + return 0; +} + +static void cxl_pmu_enable(struct pmu *pmu) +{ + struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(pmu); + void __iomem *base = info->base; + + /* Can assume frozen at this stage */ + writeq(0, base + CXL_PMU_FREEZE_REG); +} + +static void cxl_pmu_disable(struct pmu *pmu) +{ + struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(pmu); + void __iomem *base = info->base; + + /* + * Whilst bits above number of counters are RsvdZ + * they are unlikely to be repurposed given + * number of counters is allowed to be 64 leaving + * no reserved bits. Hence this is only slightly + * naughty. + */ + writeq(GENMASK_ULL(63, 0), base + CXL_PMU_FREEZE_REG); +} + +static void cxl_pmu_event_start(struct perf_event *event, int flags) +{ + struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu); + struct hw_perf_event *hwc = &event->hw; + void __iomem *base = info->base; + u64 cfg; + + /* + * All paths to here should either set these flags directly or + * call cxl_pmu_event_stop() which will ensure the correct state. + */ + if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED))) + return; + + WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE)); + hwc->state = 0; + + /* + * Currently only hdm filter control is implemnted, this code will + * want generalizing when more filters are added. + */ + if (info->filter_hdm) { + if (cxl_pmu_config1_hdm_filter_en(event)) + cfg = cxl_pmu_config2_get_hdm_decoder(event); + else + cfg = GENMASK(15, 0); /* No filtering if 0xFFFF_FFFF */ + writeq(cfg, base + CXL_PMU_FILTER_CFG_REG(hwc->idx, 0)); + } + + cfg = readq(base + CXL_PMU_COUNTER_CFG_REG(hwc->idx)); + cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_INT_ON_OVRFLW, 1); + cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_FREEZE_ON_OVRFLW, 1); + cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_ENABLE, 1); + cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_EDGE, + cxl_pmu_config1_get_edge(event) ? 1 : 0); + cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_INVERT, + cxl_pmu_config1_get_invert(event) ? 1 : 0); + + /* Fixed purpose counters have next two fields RO */ + if (test_bit(hwc->idx, info->conf_counter_bm)) { + cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_EVENT_GRP_ID_IDX_MSK, + hwc->event_base); + cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_EVENTS_MSK, + cxl_pmu_config_get_mask(event)); + } + cfg &= ~CXL_PMU_COUNTER_CFG_THRESHOLD_MSK; + /* + * For events that generate only 1 count per clock the CXL 3.0 spec + * states the threshold shall be set to 1 but if set to 0 it will + * count the raw value anwyay? + * There is no definition of what events will count multiple per cycle + * and hence to which non 1 values of threshold can apply. + * (CXL 3.0 8.2.7.2.1 Counter Configuration - threshold field definition) + */ + cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_THRESHOLD_MSK, + cxl_pmu_config1_get_threshold(event)); + writeq(cfg, base + CXL_PMU_COUNTER_CFG_REG(hwc->idx)); + + local64_set(&hwc->prev_count, 0); + writeq(0, base + CXL_PMU_COUNTER_REG(hwc->idx)); + + perf_event_update_userpage(event); +} + +static u64 cxl_pmu_read_counter(struct perf_event *event) +{ + struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu); + void __iomem *base = info->base; + + return readq(base + CXL_PMU_COUNTER_REG(event->hw.idx)); +} + +static void __cxl_pmu_read(struct perf_event *event, bool overflow) +{ + struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu); + struct hw_perf_event *hwc = &event->hw; + u64 new_cnt, prev_cnt, delta; + + do { + prev_cnt = local64_read(&hwc->prev_count); + new_cnt = cxl_pmu_read_counter(event); + } while (local64_cmpxchg(&hwc->prev_count, prev_cnt, new_cnt) != prev_cnt); + + /* + * If we know an overflow occur then take that into account. + * Note counter is not reset as that would lose events + */ + delta = (new_cnt - prev_cnt) & GENMASK_ULL(info->counter_width - 1, 0); + if (overflow && delta < GENMASK_ULL(info->counter_width - 1, 0)) + delta += (1UL << info->counter_width); + + local64_add(delta, &event->count); +} + +static void cxl_pmu_read(struct perf_event *event) +{ + __cxl_pmu_read(event, false); +} + +static void cxl_pmu_event_stop(struct perf_event *event, int flags) +{ + struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu); + void __iomem *base = info->base; + struct hw_perf_event *hwc = &event->hw; + u64 cfg; + + cxl_pmu_read(event); + WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED); + hwc->state |= PERF_HES_STOPPED; + + cfg = readq(base + CXL_PMU_COUNTER_CFG_REG(hwc->idx)); + cfg &= ~(FIELD_PREP(CXL_PMU_COUNTER_CFG_INT_ON_OVRFLW, 1) | + FIELD_PREP(CXL_PMU_COUNTER_CFG_ENABLE, 1)); + writeq(cfg, base + CXL_PMU_COUNTER_CFG_REG(hwc->idx)); + + hwc->state |= PERF_HES_UPTODATE; +} + +static int cxl_pmu_event_add(struct perf_event *event, int flags) +{ + struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu); + struct hw_perf_event *hwc = &event->hw; + int idx, rc; + int event_idx = 0; + + hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE; + + rc = cxl_pmu_get_event_idx(event, &idx, &event_idx); + if (rc < 0) + return rc; + + hwc->idx = idx; + + /* Only set for configurable counters */ + hwc->event_base = event_idx; + info->hw_events[idx] = event; + set_bit(idx, info->used_counter_bm); + + if (flags & PERF_EF_START) + cxl_pmu_event_start(event, PERF_EF_RELOAD); + + return 0; +} + +static void cxl_pmu_event_del(struct perf_event *event, int flags) +{ + struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu); + struct hw_perf_event *hwc = &event->hw; + + cxl_pmu_event_stop(event, PERF_EF_UPDATE); + clear_bit(hwc->idx, info->used_counter_bm); + info->hw_events[hwc->idx] = NULL; + perf_event_update_userpage(event); +} + +static irqreturn_t cxl_pmu_irq(int irq, void *data) +{ + struct cxl_pmu_info *info = data; + void __iomem *base = info->base; + u64 overflowed; + DECLARE_BITMAP(overflowedbm, 64); + int i; + + overflowed = readq(base + CXL_PMU_OVERFLOW_REG); + + /* Interrupt may be shared, so maybe it isn't ours */ + if (!overflowed) + return IRQ_NONE; + + bitmap_from_arr64(overflowedbm, &overflowed, 64); + for_each_set_bit(i, overflowedbm, info->num_counters) { + struct perf_event *event = info->hw_events[i]; + + if (!event) { + dev_dbg(info->pmu.dev, + "overflow but on non enabled counter %d\n", i); + continue; + } + + __cxl_pmu_read(event, true); + } + + writeq(overflowed, base + CXL_PMU_OVERFLOW_REG); + + return IRQ_HANDLED; +} + +static void cxl_pmu_perf_unregister(void *_info) +{ + struct cxl_pmu_info *info = _info; + + perf_pmu_unregister(&info->pmu); +} + +static void cxl_pmu_cpuhp_remove(void *_info) +{ + struct cxl_pmu_info *info = _info; + + cpuhp_state_remove_instance_nocalls(cxl_pmu_cpuhp_state_num, &info->node); +} + +static int cxl_pmu_probe(struct device *dev) +{ + struct cxl_pmu *pmu = to_cxl_pmu(dev); + struct pci_dev *pdev = to_pci_dev(dev->parent); + struct cxl_pmu_info *info; + char *irq_name; + char *dev_name; + int rc, irq; + + info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + dev_set_drvdata(dev, info); + INIT_LIST_HEAD(&info->event_caps_fixed); + INIT_LIST_HEAD(&info->event_caps_configurable); + + info->base = pmu->base; + + info->on_cpu = -1; + rc = cxl_pmu_parse_caps(dev, info); + if (rc) + return rc; + + info->hw_events = devm_kcalloc(dev, sizeof(*info->hw_events), + info->num_counters, GFP_KERNEL); + if (!info->hw_events) + return -ENOMEM; + + switch (pmu->type) { + case CXL_PMU_MEMDEV: + dev_name = devm_kasprintf(dev, GFP_KERNEL, "cxl_pmu_mem%d.%d", + pmu->assoc_id, pmu->index); + break; + } + if (!dev_name) + return -ENOMEM; + + info->pmu = (struct pmu) { + .name = dev_name, + .parent = dev, + .module = THIS_MODULE, + .event_init = cxl_pmu_event_init, + .pmu_enable = cxl_pmu_enable, + .pmu_disable = cxl_pmu_disable, + .add = cxl_pmu_event_add, + .del = cxl_pmu_event_del, + .start = cxl_pmu_event_start, + .stop = cxl_pmu_event_stop, + .read = cxl_pmu_read, + .task_ctx_nr = perf_invalid_context, + .attr_groups = cxl_pmu_attr_groups, + .capabilities = PERF_PMU_CAP_NO_EXCLUDE, + }; + + if (info->irq <= 0) + return -EINVAL; + + rc = pci_irq_vector(pdev, info->irq); + if (rc < 0) + return rc; + irq = rc; + + irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s_overflow\n", dev_name); + if (!irq_name) + return -ENOMEM; + + rc = devm_request_irq(dev, irq, cxl_pmu_irq, IRQF_SHARED | IRQF_ONESHOT, + irq_name, info); + if (rc) + return rc; + info->irq = irq; + + rc = cpuhp_state_add_instance(cxl_pmu_cpuhp_state_num, &info->node); + if (rc) + return rc; + + rc = devm_add_action_or_reset(dev, cxl_pmu_cpuhp_remove, info); + if (rc) + return rc; + + rc = perf_pmu_register(&info->pmu, info->pmu.name, -1); + if (rc) + return rc; + + rc = devm_add_action_or_reset(dev, cxl_pmu_perf_unregister, info); + if (rc) + return rc; + + return 0; +} + +static struct cxl_driver cxl_pmu_driver = { + .name = "cxl_pmu", + .probe = cxl_pmu_probe, + .id = CXL_DEVICE_PMU, +}; + +static int cxl_pmu_online_cpu(unsigned int cpu, struct hlist_node *node) +{ + struct cxl_pmu_info *info = hlist_entry_safe(node, struct cxl_pmu_info, node); + + if (info->on_cpu != -1) + return 0; + + info->on_cpu = cpu; + /* + * CPU HP lock is held so we should be guaranteed that the CPU hasn't yet + * gone away again. + */ + WARN_ON(irq_set_affinity(info->irq, cpumask_of(cpu))); + + return 0; +} + +static int cxl_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node) +{ + struct cxl_pmu_info *info = hlist_entry_safe(node, struct cxl_pmu_info, node); + unsigned int target; + + if (info->on_cpu != cpu) + return 0; + + info->on_cpu = -1; + target = cpumask_any_but(cpu_online_mask, cpu); + if (target >= nr_cpu_ids) { + dev_err(info->pmu.dev, "Unable to find a suitable CPU\n"); + return 0; + } + + perf_pmu_migrate_context(&info->pmu, cpu, target); + info->on_cpu = target; + /* + * CPU HP lock is held so we should be guaranteed that this CPU hasn't yet + * gone away. + */ + WARN_ON(irq_set_affinity(info->irq, cpumask_of(target))); + + return 0; +} + +static __init int cxl_pmu_init(void) +{ + int rc; + + rc = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, + "AP_PERF_CXL_PMU_ONLINE", + cxl_pmu_online_cpu, cxl_pmu_offline_cpu); + if (rc < 0) + return rc; + cxl_pmu_cpuhp_state_num = rc; + + rc = cxl_driver_register(&cxl_pmu_driver); + if (rc) + cpuhp_remove_multi_state(cxl_pmu_cpuhp_state_num); + + return rc; +} + +static __exit void cxl_pmu_exit(void) +{ + cxl_driver_unregister(&cxl_pmu_driver); + cpuhp_remove_multi_state(cxl_pmu_cpuhp_state_num); +} + +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(CXL); +module_init(cxl_pmu_init); +module_exit(cxl_pmu_exit); +MODULE_ALIAS_CXL(CXL_DEVICE_PMU); diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c index 4f3ac296b3e2..4163ff517471 100644 --- a/drivers/perf/riscv_pmu_sbi.c +++ b/drivers/perf/riscv_pmu_sbi.c @@ -739,7 +739,6 @@ static int pmu_sbi_setup_irqs(struct riscv_pmu *pmu, struct platform_device *pde { int ret; struct cpu_hw_events __percpu *hw_events = pmu->hw_events; - struct device_node *cpu, *child; struct irq_domain *domain = NULL; if (riscv_isa_extension_available(NULL, SSCOFPMF)) { @@ -756,20 +755,8 @@ static int pmu_sbi_setup_irqs(struct riscv_pmu *pmu, struct platform_device *pde if (!riscv_pmu_use_irq) return -EOPNOTSUPP; - for_each_of_cpu_node(cpu) { - child = of_get_compatible_child(cpu, "riscv,cpu-intc"); - if (!child) { - pr_err("Failed to find INTC node\n"); - of_node_put(cpu); - return -ENODEV; - } - domain = irq_find_host(child); - of_node_put(child); - if (domain) { - of_node_put(cpu); - break; - } - } + domain = irq_find_matching_fwnode(riscv_get_intc_hwnode(), + DOMAIN_BUS_ANY); if (!domain) { pr_err("Failed to find INTC IRQ root domain\n"); return -ENODEV; @@ -868,6 +855,12 @@ static int pmu_sbi_device_probe(struct platform_device *pdev) goto out_free; } + /* It is possible to get from SBI more than max number of counters */ + if (num_counters > RISCV_MAX_COUNTERS) { + num_counters = RISCV_MAX_COUNTERS; + pr_info("SBI returned more than maximum number of counters. Limiting the number of counters to %d\n", num_counters); + } + /* cache all the information about counters now */ if (pmu_sbi_get_ctrinfo(num_counters, &cmask)) goto out_free; diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 77ff9a641aeb..57d57af1f624 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -510,7 +510,6 @@ config PINCTRL_MLXBF3 select PINMUX select GPIOLIB select GPIOLIB_IRQCHIP - select GPIO_MLXBF3 help Say Y to select the pinctrl driver for BlueField-3 SoCs. This pin controller allows selecting the mux function for diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index e196c6e324ad..482b391b5deb 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -66,7 +66,7 @@ obj-y += nomadik/ obj-y += nuvoton/ obj-y += nxp/ obj-$(CONFIG_PINCTRL_PXA) += pxa/ -obj-$(CONFIG_ARCH_QCOM) += qcom/ +obj-y += qcom/ obj-$(CONFIG_PINCTRL_RENESAS) += renesas/ obj-$(CONFIG_PINCTRL_SAMSUNG) += samsung/ obj-$(CONFIG_PINCTRL_SPEAR) += spear/ diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index 7435173e10f4..1489191a213f 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -376,10 +376,8 @@ static int bcm2835_add_pin_ranges_fallback(struct gpio_chip *gc) if (!pctldev) return 0; - gpiochip_add_pin_range(gc, pinctrl_dev_get_devname(pctldev), 0, 0, - gc->ngpio); - - return 0; + return gpiochip_add_pin_range(gc, pinctrl_dev_get_devname(pctldev), 0, 0, + gc->ngpio); } static const struct gpio_chip bcm2835_gpio_chip = { diff --git a/drivers/pinctrl/freescale/pinctrl-scu.c b/drivers/pinctrl/freescale/pinctrl-scu.c index ea261b6e7458..3b252d684d72 100644 --- a/drivers/pinctrl/freescale/pinctrl-scu.c +++ b/drivers/pinctrl/freescale/pinctrl-scu.c @@ -90,7 +90,7 @@ int imx_pinconf_set_scu(struct pinctrl_dev *pctldev, unsigned pin_id, struct imx_sc_msg_req_pad_set msg; struct imx_sc_rpc_msg *hdr = &msg.hdr; unsigned int mux = configs[0]; - unsigned int conf = configs[1]; + unsigned int conf; unsigned int val; int ret; @@ -115,6 +115,7 @@ int imx_pinconf_set_scu(struct pinctrl_dev *pctldev, unsigned pin_id, * Set mux and conf together in one IPC call */ WARN_ON(num_configs != 2); + conf = configs[1]; val = conf | BM_PAD_CTL_IFMUX_ENABLE | BM_PAD_CTL_GP_ENABLE; val |= mux << BP_PAD_CTL_IFMUX; diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index 770a2723ef81..27aef62fc7c0 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -18,6 +18,7 @@ #include <linux/pm_runtime.h> #include <linux/property.h> #include <linux/seq_file.h> +#include <linux/string_helpers.h> #include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinmux.h> @@ -52,10 +53,9 @@ #define BYT_PULL_STR_10K (1 << BYT_PULL_STR_SHIFT) #define BYT_PULL_STR_20K (2 << BYT_PULL_STR_SHIFT) #define BYT_PULL_STR_40K (3 << BYT_PULL_STR_SHIFT) -#define BYT_PULL_ASSIGN_SHIFT 7 #define BYT_PULL_ASSIGN_MASK GENMASK(8, 7) -#define BYT_PULL_ASSIGN_UP (1 << BYT_PULL_ASSIGN_SHIFT) -#define BYT_PULL_ASSIGN_DOWN (2 << BYT_PULL_ASSIGN_SHIFT) +#define BYT_PULL_ASSIGN_DOWN BIT(8) +#define BYT_PULL_ASSIGN_UP BIT(7) #define BYT_PIN_MUX GENMASK(2, 0) /* BYT_VAL_REG register bits */ @@ -668,8 +668,7 @@ static void byt_set_group_simple_mux(struct intel_pinctrl *vg, padcfg0 = byt_gpio_reg(vg, group.grp.pins[i], BYT_CONF0_REG); if (!padcfg0) { - dev_warn(vg->dev, - "Group %s, pin %i not muxed (no padcfg0)\n", + dev_warn(vg->dev, "Group %s, pin %i not muxed (can't retrieve CONF0)\n", group.grp.name, i); continue; } @@ -698,8 +697,7 @@ static void byt_set_group_mixed_mux(struct intel_pinctrl *vg, padcfg0 = byt_gpio_reg(vg, group.grp.pins[i], BYT_CONF0_REG); if (!padcfg0) { - dev_warn(vg->dev, - "Group %s, pin %i not muxed (no padcfg0)\n", + dev_warn(vg->dev, "Group %s, pin %i not muxed (can't retrieve CONF0)\n", group.grp.name, i); continue; } @@ -755,9 +753,7 @@ static void byt_gpio_clear_triggering(struct intel_pinctrl *vg, unsigned int off value = readl(reg); /* Do not clear direct-irq enabled IRQs (from gpio_disable_free) */ - if (value & BYT_DIRECT_IRQ_EN) - /* nothing to do */ ; - else + if (!(value & BYT_DIRECT_IRQ_EN)) value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL); writel(value, reg); @@ -791,7 +787,7 @@ static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev, value |= gpio_mux; writel(value, reg); - dev_warn(vg->dev, FW_BUG "pin %u forcibly re-configured as GPIO\n", offset); + dev_warn(vg->dev, FW_BUG "Pin %i: forcibly re-configured as GPIO\n", offset); } raw_spin_unlock_irqrestore(&byt_lock, flags); @@ -823,7 +819,9 @@ static void byt_gpio_direct_irq_check(struct intel_pinctrl *vg, * themselves in the foot. */ if (readl(conf_reg) & BYT_DIRECT_IRQ_EN) - dev_info_once(vg->dev, "Potential Error: Setting GPIO with direct_irq_en to output"); + dev_info_once(vg->dev, + "Potential Error: Pin %i: forcibly set GPIO with DIRECT_IRQ_EN to output\n", + offset); } static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev, @@ -1026,9 +1024,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev, if (val & BYT_INPUT_EN) { val &= ~BYT_INPUT_EN; writel(val, val_reg); - dev_warn(vg->dev, - "pin %u forcibly set to input mode\n", - offset); + dev_warn(vg->dev, "Pin %i: forcibly set to input mode\n", offset); } conf &= ~BYT_PULL_ASSIGN_MASK; @@ -1048,9 +1044,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev, if (val & BYT_INPUT_EN) { val &= ~BYT_INPUT_EN; writel(val, val_reg); - dev_warn(vg->dev, - "pin %u forcibly set to input mode\n", - offset); + dev_warn(vg->dev, "Pin %i: forcibly set to input mode\n", offset); } conf &= ~BYT_PULL_ASSIGN_MASK; @@ -1245,39 +1239,35 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) for (i = 0; i < vg->soc->npins; i++) { const struct intel_community *comm; + void __iomem *conf_reg, *val_reg; const char *pull_str = NULL; const char *pull = NULL; - void __iomem *reg; unsigned long flags; const char *label; unsigned int pin; - raw_spin_lock_irqsave(&byt_lock, flags); pin = vg->soc->pins[i].number; - reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG); - if (!reg) { - seq_printf(s, - "Could not retrieve pin %i conf0 reg\n", - pin); - raw_spin_unlock_irqrestore(&byt_lock, flags); + + conf_reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG); + if (!conf_reg) { + seq_printf(s, "Pin %i: can't retrieve CONF0\n", pin); continue; } - conf0 = readl(reg); - reg = byt_gpio_reg(vg, pin, BYT_VAL_REG); - if (!reg) { - seq_printf(s, - "Could not retrieve pin %i val reg\n", pin); - raw_spin_unlock_irqrestore(&byt_lock, flags); + val_reg = byt_gpio_reg(vg, pin, BYT_VAL_REG); + if (!val_reg) { + seq_printf(s, "Pin %i: can't retrieve VAL\n", pin); continue; } - val = readl(reg); + + raw_spin_lock_irqsave(&byt_lock, flags); + conf0 = readl(conf_reg); + val = readl(val_reg); raw_spin_unlock_irqrestore(&byt_lock, flags); comm = byt_get_community(vg, pin); if (!comm) { - seq_printf(s, - "Could not get community for pin %i\n", pin); + seq_printf(s, "Pin %i: can't retrieve community\n", pin); continue; } label = gpiochip_is_requested(chip, i); @@ -1314,7 +1304,7 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) label, val & BYT_INPUT_EN ? " " : "in", val & BYT_OUTPUT_EN ? " " : "out", - val & BYT_LEVEL ? "hi" : "lo", + str_hi_lo(val & BYT_LEVEL), comm->pad_map[i], comm->pad_map[i] * 16, conf0 & 0x7, conf0 & BYT_TRIG_NEG ? " fall" : " ", @@ -1429,7 +1419,7 @@ static int byt_irq_type(struct irq_data *d, unsigned int type) value = readl(reg); WARN(value & BYT_DIRECT_IRQ_EN, - "Bad pad config for io mode, force direct_irq_en bit clearing"); + "Bad pad config for IO mode, force DIRECT_IRQ_EN bit clearing"); /* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits * are used to indicate high and low level triggering @@ -1476,9 +1466,7 @@ static void byt_gpio_irq_handler(struct irq_desc *desc) reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG); if (!reg) { - dev_warn(vg->dev, - "Pin %i: could not retrieve interrupt status register\n", - base); + dev_warn(vg->dev, "Pin %i: can't retrieve INT_STAT%u\n", base / 32, base); continue; } @@ -1501,7 +1489,7 @@ static bool byt_direct_irq_sanity_check(struct intel_pinctrl *vg, int pin, u32 c sizeof(direct_irq_mux)); match = memchr(direct_irq_mux, pin, sizeof(direct_irq_mux)); if (!match) { - dev_warn(vg->dev, FW_BUG "pin %i: direct_irq_en set but no IRQ assigned, clearing\n", pin); + dev_warn(vg->dev, FW_BUG "Pin %i: DIRECT_IRQ_EN set but no IRQ assigned, clearing\n", pin); return false; } @@ -1528,7 +1516,8 @@ static bool byt_direct_irq_sanity_check(struct intel_pinctrl *vg, int pin, u32 c trig = conf0 & BYT_TRIG_MASK; if (trig != (BYT_TRIG_POS | BYT_TRIG_LVL) && trig != (BYT_TRIG_NEG | BYT_TRIG_LVL)) { - dev_warn(vg->dev, FW_BUG "pin %i: direct_irq_en set without trigger (conf0: %xh), clearing\n", + dev_warn(vg->dev, + FW_BUG "Pin %i: DIRECT_IRQ_EN set without trigger (CONF0: %#08x), clearing\n", pin, conf0); return false; } @@ -1555,9 +1544,7 @@ static void byt_init_irq_valid_mask(struct gpio_chip *chip, reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG); if (!reg) { - dev_warn(vg->dev, - "Pin %i: could not retrieve conf0 register\n", - i); + dev_warn(vg->dev, "Pin %i: could not retrieve CONF0\n", i); continue; } @@ -1588,9 +1575,7 @@ static int byt_gpio_irq_init_hw(struct gpio_chip *chip) reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG); if (!reg) { - dev_warn(vg->dev, - "Pin %i: could not retrieve irq status reg\n", - base); + dev_warn(vg->dev, "Pin %i: can't retrieve INT_STAT%u\n", base / 32, base); continue; } @@ -1600,7 +1585,7 @@ static int byt_gpio_irq_init_hw(struct gpio_chip *chip) value = readl(reg); if (value) dev_err(vg->dev, - "GPIO interrupt error, pins misconfigured. INT_STAT%u: 0x%08x\n", + "GPIO interrupt error, pins misconfigured. INT_STAT%u: %#08x\n", base / 32, value); } @@ -1764,15 +1749,17 @@ static int byt_gpio_suspend(struct device *dev) reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG); if (!reg) { - dev_warn(vg->dev, - "Pin %i: could not retrieve conf0 register\n", - i); + dev_warn(vg->dev, "Pin %i: can't retrieve CONF0\n", i); continue; } value = readl(reg) & BYT_CONF0_RESTORE_MASK; vg->context.pads[i].conf0 = value; reg = byt_gpio_reg(vg, pin, BYT_VAL_REG); + if (!reg) { + dev_warn(vg->dev, "Pin %i: can't retrieve VAL\n", i); + continue; + } value = readl(reg) & BYT_VAL_RESTORE_MASK; vg->context.pads[i].val = value; } @@ -1796,9 +1783,7 @@ static int byt_gpio_resume(struct device *dev) reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG); if (!reg) { - dev_warn(vg->dev, - "Pin %i: could not retrieve conf0 register\n", - i); + dev_warn(vg->dev, "Pin %i: can't retrieve CONF0\n", i); continue; } value = readl(reg); @@ -1807,10 +1792,14 @@ static int byt_gpio_resume(struct device *dev) value &= ~BYT_CONF0_RESTORE_MASK; value |= vg->context.pads[i].conf0; writel(value, reg); - dev_info(dev, "restored pin %d conf0 %#08x", i, value); + dev_info(dev, "restored pin %d CONF0 %#08x", i, value); } reg = byt_gpio_reg(vg, pin, BYT_VAL_REG); + if (!reg) { + dev_warn(vg->dev, "Pin %i: can't retrieve VAL\n", i); + continue; + } value = readl(reg); if ((value & BYT_VAL_RESTORE_MASK) != vg->context.pads[i].val) { @@ -1820,8 +1809,7 @@ static int byt_gpio_resume(struct device *dev) v |= vg->context.pads[i].val; if (v != value) { writel(v, reg); - dev_dbg(dev, "restored pin %d val %#08x\n", - i, v); + dev_dbg(dev, "restored pin %d VAL %#08x\n", i, v); } } } diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index 722990e27836..eee0f9bc3d32 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -75,7 +75,7 @@ struct intel_pad_context { u32 padctrl1; }; -#define CHV_INVALID_HWIRQ ((unsigned int)INVALID_HWIRQ) +#define CHV_INVALID_HWIRQ (~0U) /** * struct intel_community_context - community context for Cherryview @@ -949,11 +949,6 @@ static int chv_config_get(struct pinctrl_dev *pctldev, unsigned int pin, break; - case PIN_CONFIG_DRIVE_OPEN_DRAIN: - if (!(ctrl1 & CHV_PADCTRL1_ODEN)) - return -EINVAL; - break; - case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: { u32 cfg; @@ -963,6 +958,16 @@ static int chv_config_get(struct pinctrl_dev *pctldev, unsigned int pin, return -EINVAL; break; + + case PIN_CONFIG_DRIVE_PUSH_PULL: + if (ctrl1 & CHV_PADCTRL1_ODEN) + return -EINVAL; + break; + + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + if (!(ctrl1 & CHV_PADCTRL1_ODEN)) + return -EINVAL; + break; } default: @@ -1408,8 +1413,10 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned int type) raw_spin_lock_irqsave(&chv_lock, flags); ret = chv_gpio_set_intr_line(pctrl, hwirq); - if (ret) - goto out_unlock; + if (ret) { + raw_spin_unlock_irqrestore(&chv_lock, flags); + return ret; + } /* * Pins which can be used as shared interrupt are configured in @@ -1450,10 +1457,9 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned int type) else if (type & IRQ_TYPE_LEVEL_MASK) irq_set_handler_locked(d, handle_level_irq); -out_unlock: raw_spin_unlock_irqrestore(&chv_lock, flags); - return ret; + return 0; } static const struct irq_chip chv_gpio_irq_chip = { diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index c7a71c49df0a..64c3e62b4348 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -55,12 +55,11 @@ /* Offset from pad_regs */ #define PADCFG0 0x000 -#define PADCFG0_RXEVCFG_SHIFT 25 #define PADCFG0_RXEVCFG_MASK GENMASK(26, 25) -#define PADCFG0_RXEVCFG_LEVEL 0 -#define PADCFG0_RXEVCFG_EDGE 1 -#define PADCFG0_RXEVCFG_DISABLED 2 -#define PADCFG0_RXEVCFG_EDGE_BOTH 3 +#define PADCFG0_RXEVCFG_LEVEL (0 << 25) +#define PADCFG0_RXEVCFG_EDGE (1 << 25) +#define PADCFG0_RXEVCFG_DISABLED (2 << 25) +#define PADCFG0_RXEVCFG_EDGE_BOTH (3 << 25) #define PADCFG0_PREGFRXSEL BIT(24) #define PADCFG0_RXINV BIT(23) #define PADCFG0_GPIROUTIOXAPIC BIT(20) @@ -411,18 +410,19 @@ static int intel_pinmux_set_mux(struct pinctrl_dev *pctldev, /* Now enable the mux setting for each pin in the group */ for (i = 0; i < grp->grp.npins; i++) { void __iomem *padcfg0; - u32 value; + u32 value, pmode; padcfg0 = intel_get_padcfg(pctrl, grp->grp.pins[i], PADCFG0); - value = readl(padcfg0); + value = readl(padcfg0); value &= ~PADCFG0_PMODE_MASK; if (grp->modes) - value |= grp->modes[i] << PADCFG0_PMODE_SHIFT; + pmode = grp->modes[i]; else - value |= grp->mode << PADCFG0_PMODE_SHIFT; + pmode = grp->mode; + value |= pmode << PADCFG0_PMODE_SHIFT; writel(value, padcfg0); } @@ -1126,9 +1126,9 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned int type) struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct intel_pinctrl *pctrl = gpiochip_get_data(gc); unsigned int pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL); + u32 rxevcfg, rxinv, value; unsigned long flags; void __iomem *reg; - u32 value; reg = intel_get_padcfg(pctrl, pin, PADCFG0); if (!reg) @@ -1144,28 +1144,32 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned int type) return -EPERM; } - raw_spin_lock_irqsave(&pctrl->lock, flags); - - intel_gpio_set_gpio_mode(reg); - - value = readl(reg); - - value &= ~(PADCFG0_RXEVCFG_MASK | PADCFG0_RXINV); - if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { - value |= PADCFG0_RXEVCFG_EDGE_BOTH << PADCFG0_RXEVCFG_SHIFT; + rxevcfg = PADCFG0_RXEVCFG_EDGE_BOTH; } else if (type & IRQ_TYPE_EDGE_FALLING) { - value |= PADCFG0_RXEVCFG_EDGE << PADCFG0_RXEVCFG_SHIFT; - value |= PADCFG0_RXINV; + rxevcfg = PADCFG0_RXEVCFG_EDGE; } else if (type & IRQ_TYPE_EDGE_RISING) { - value |= PADCFG0_RXEVCFG_EDGE << PADCFG0_RXEVCFG_SHIFT; + rxevcfg = PADCFG0_RXEVCFG_EDGE; } else if (type & IRQ_TYPE_LEVEL_MASK) { - if (type & IRQ_TYPE_LEVEL_LOW) - value |= PADCFG0_RXINV; + rxevcfg = PADCFG0_RXEVCFG_LEVEL; } else { - value |= PADCFG0_RXEVCFG_DISABLED << PADCFG0_RXEVCFG_SHIFT; + rxevcfg = PADCFG0_RXEVCFG_DISABLED; } + if (type == IRQ_TYPE_EDGE_FALLING || type == IRQ_TYPE_LEVEL_LOW) + rxinv = PADCFG0_RXINV; + else + rxinv = 0; + + raw_spin_lock_irqsave(&pctrl->lock, flags); + + intel_gpio_set_gpio_mode(reg); + + value = readl(reg); + + value = (value & ~PADCFG0_RXEVCFG_MASK) | rxevcfg; + value = (value & ~PADCFG0_RXINV) | rxinv; + writel(value, reg); if (type & IRQ_TYPE_EDGE_BOTH) diff --git a/drivers/pinctrl/intel/pinctrl-merrifield.c b/drivers/pinctrl/intel/pinctrl-merrifield.c index 365c391c97a3..fb6de38b1c50 100644 --- a/drivers/pinctrl/intel/pinctrl-merrifield.c +++ b/drivers/pinctrl/intel/pinctrl-merrifield.c @@ -549,7 +549,7 @@ static void mrfld_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, } mode = (value & BUFCFG_PINMODE_MASK) >> BUFCFG_PINMODE_SHIFT; - if (!mode) + if (mode == BUFCFG_PINMODE_GPIO) seq_puts(s, "GPIO "); else seq_printf(s, "mode %d ", mode); @@ -710,6 +710,11 @@ static int mrfld_config_get(struct pinctrl_dev *pctldev, unsigned int pin, break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + if (value & BUFCFG_OD_EN) + return -EINVAL; + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: if (!(value & BUFCFG_OD_EN)) return -EINVAL; @@ -791,10 +796,14 @@ static int mrfld_config_set_pin(struct mrfld_pinctrl *mp, unsigned int pin, break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + mask |= BUFCFG_OD_EN; + bits &= ~BUFCFG_OD_EN; + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: mask |= BUFCFG_OD_EN; - if (arg) - bits |= BUFCFG_OD_EN; + bits |= BUFCFG_OD_EN; break; case PIN_CONFIG_SLEW_RATE: @@ -826,6 +835,7 @@ static int mrfld_config_set(struct pinctrl_dev *pctldev, unsigned int pin, case PIN_CONFIG_BIAS_DISABLE: case PIN_CONFIG_BIAS_PULL_UP: case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_DRIVE_PUSH_PULL: case PIN_CONFIG_DRIVE_OPEN_DRAIN: case PIN_CONFIG_SLEW_RATE: ret = mrfld_config_set_pin(mp, pin, configs[i]); diff --git a/drivers/pinctrl/intel/pinctrl-meteorlake.c b/drivers/pinctrl/intel/pinctrl-meteorlake.c index a82f6754c45b..9a11f729bec8 100644 --- a/drivers/pinctrl/intel/pinctrl-meteorlake.c +++ b/drivers/pinctrl/intel/pinctrl-meteorlake.c @@ -20,6 +20,12 @@ #define MTL_P_GPI_IS 0x200 #define MTL_P_GPI_IE 0x210 +#define MTL_S_PAD_OWN 0x0b0 +#define MTL_S_PADCFGLOCK 0x0f0 +#define MTL_S_HOSTSW_OWN 0x110 +#define MTL_S_GPI_IS 0x200 +#define MTL_S_GPI_IE 0x210 + #define MTL_GPP(r, s, e, g) \ { \ .reg_num = (r), \ @@ -28,9 +34,12 @@ .gpio_base = (g), \ } -#define MTL_COMMUNITY(b, s, e, g) \ +#define MTL_P_COMMUNITY(b, s, e, g) \ INTEL_COMMUNITY_GPPS(b, s, e, g, MTL_P) +#define MTL_S_COMMUNITY(b, s, e, g) \ + INTEL_COMMUNITY_GPPS(b, s, e, g, MTL_S) + /* Meteor Lake-P */ static const struct pinctrl_pin_desc mtlp_pins[] = { /* CPU */ @@ -369,11 +378,11 @@ static const struct intel_padgroup mtlp_community5_gpps[] = { }; static const struct intel_community mtlp_communities[] = { - MTL_COMMUNITY(0, 0, 52, mtlp_community0_gpps), - MTL_COMMUNITY(1, 53, 102, mtlp_community1_gpps), - MTL_COMMUNITY(2, 103, 183, mtlp_community3_gpps), - MTL_COMMUNITY(3, 184, 203, mtlp_community4_gpps), - MTL_COMMUNITY(4, 204, 288, mtlp_community5_gpps), + MTL_P_COMMUNITY(0, 0, 52, mtlp_community0_gpps), + MTL_P_COMMUNITY(1, 53, 102, mtlp_community1_gpps), + MTL_P_COMMUNITY(2, 103, 183, mtlp_community3_gpps), + MTL_P_COMMUNITY(3, 184, 203, mtlp_community4_gpps), + MTL_P_COMMUNITY(4, 204, 288, mtlp_community5_gpps), }; static const struct intel_pinctrl_soc_data mtlp_soc_data = { @@ -383,8 +392,199 @@ static const struct intel_pinctrl_soc_data mtlp_soc_data = { .ncommunities = ARRAY_SIZE(mtlp_communities), }; +/* Meteor Lake-S */ +static const struct pinctrl_pin_desc mtls_pins[] = { + /* GPP_A */ + PINCTRL_PIN(0, "DIR_ESPI_IO_0"), + PINCTRL_PIN(1, "DIR_ESPI_IO_1"), + PINCTRL_PIN(2, "DIR_ESPI_IO_2"), + PINCTRL_PIN(3, "DIR_ESPI_IO_3"), + PINCTRL_PIN(4, "DIR_ESPI_CS0_B"), + PINCTRL_PIN(5, "DIR_ESPI_CLK"), + PINCTRL_PIN(6, "DIR_ESPI_RCLK"), + PINCTRL_PIN(7, "DIR_ESPI_RESET_B"), + PINCTRL_PIN(8, "SLP_S0_B"), + PINCTRL_PIN(9, "DMI_PERSTB"), + PINCTRL_PIN(10, "CATERR_B"), + PINCTRL_PIN(11, "THERMTRIP_B"), + PINCTRL_PIN(12, "CPU_C10_GATE_B"), + PINCTRL_PIN(13, "PS_ONB"), + PINCTRL_PIN(14, "GPP_SA_14"), + PINCTRL_PIN(15, "GPP_SA_15"), + PINCTRL_PIN(16, "GPP_SA_16"), + PINCTRL_PIN(17, "GPP_SA_17"), + PINCTRL_PIN(18, "GPP_SA_18"), + PINCTRL_PIN(19, "GPP_SA_19"), + PINCTRL_PIN(20, "GPP_SA_20"), + PINCTRL_PIN(21, "GPP_SA_21"), + PINCTRL_PIN(22, "FUSA_DIAGTEST_EN"), + PINCTRL_PIN(23, "FUSA_DIAGTEST_MODE"), + PINCTRL_PIN(24, "RTCCLKIN"), + PINCTRL_PIN(25, "RESET_SYNC_B"), + PINCTRL_PIN(26, "PCH_PWROK"), + PINCTRL_PIN(27, "DIR_ESPI_CLK_LOOPBACK"), + /* vGPIO_0 */ + PINCTRL_PIN(28, "LPC_ME_FTPM_ENABLE"), + PINCTRL_PIN(29, "LPC_DTFUS_CORE_SPITPM_DIS"), + PINCTRL_PIN(30, "LPC_SPI_STRAP_TOS"), + PINCTRL_PIN(31, "ITSS_KU1_SHTDWN"), + PINCTRL_PIN(32, "LPC_PRR_TS_OVR"), + PINCTRL_PIN(33, "ESPI_PMC_EC_SCI"), + PINCTRL_PIN(34, "ESPI_PMC_EC_SCI1"), + PINCTRL_PIN(35, "vGPIO_SPARE0"), + PINCTRL_PIN(36, "vGPIO_SPARE1"), + PINCTRL_PIN(37, "vGPIO_SPARE2"), + PINCTRL_PIN(38, "vGPIO_SPARE3"), + PINCTRL_PIN(39, "vGPIO_SPARE8"), + PINCTRL_PIN(40, "vGPIO_SPARE9"), + PINCTRL_PIN(41, "vGPIO_SPARE10"), + PINCTRL_PIN(42, "vGPIO_SPARE11"), + PINCTRL_PIN(43, "vGPIO_SPARE12"), + PINCTRL_PIN(44, "vGPIO_SPARE13"), + PINCTRL_PIN(45, "vGPIO_SPARE14"), + PINCTRL_PIN(46, "vGPIO_SPARE15"), + /* GPP_C */ + PINCTRL_PIN(47, "GPP_SC_0"), + PINCTRL_PIN(48, "GPP_SC_1"), + PINCTRL_PIN(49, "GPP_SC_2"), + PINCTRL_PIN(50, "GPP_SC_3"), + PINCTRL_PIN(51, "GPP_SC_4"), + PINCTRL_PIN(52, "GPP_SC_5"), + PINCTRL_PIN(53, "GPP_SC_6"), + PINCTRL_PIN(54, "GPP_SC_7"), + PINCTRL_PIN(55, "GPP_SC_8"), + PINCTRL_PIN(56, "GPP_SC_9"), + PINCTRL_PIN(57, "GPP_SC_10"), + PINCTRL_PIN(58, "GPP_SC_11"), + PINCTRL_PIN(59, "GPP_SC_12"), + PINCTRL_PIN(60, "GPP_SC_13"), + PINCTRL_PIN(61, "GPP_SC_14"), + PINCTRL_PIN(62, "GPP_SC_15"), + PINCTRL_PIN(63, "GPP_SC_16"), + PINCTRL_PIN(64, "GPP_SC_17"), + PINCTRL_PIN(65, "GPP_SC_18"), + PINCTRL_PIN(66, "GPP_SC_19"), + PINCTRL_PIN(67, "GPP_SC_20"), + PINCTRL_PIN(68, "GPP_SC_21"), + PINCTRL_PIN(69, "GPP_SC_22"), + PINCTRL_PIN(70, "GPP_SC_23"), + PINCTRL_PIN(71, "GPP_SC_24"), + PINCTRL_PIN(72, "GPP_SC_25"), + PINCTRL_PIN(73, "GPP_SC_26"), + /* GPP_B */ + PINCTRL_PIN(74, "GPP_SB_0"), + PINCTRL_PIN(75, "GPP_SB_1"), + PINCTRL_PIN(76, "GPP_SB_2"), + PINCTRL_PIN(77, "GPP_SB_3"), + PINCTRL_PIN(78, "GPP_SB_4"), + PINCTRL_PIN(79, "GPP_SB_5"), + PINCTRL_PIN(80, "GPP_SB_6"), + PINCTRL_PIN(81, "GPP_SB_7"), + PINCTRL_PIN(82, "GPP_SB_8"), + PINCTRL_PIN(83, "GPP_SB_9"), + PINCTRL_PIN(84, "GPP_SB_10"), + PINCTRL_PIN(85, "GPP_SB_11"), + PINCTRL_PIN(86, "GPP_SB_12"), + PINCTRL_PIN(87, "GPP_SB_13"), + PINCTRL_PIN(88, "GPP_SB_14"), + PINCTRL_PIN(89, "GPP_SB_15"), + PINCTRL_PIN(90, "GPP_SB_16"), + PINCTRL_PIN(91, "PROCHOT_B"), + PINCTRL_PIN(92, "BPKI3C_SDA"), + PINCTRL_PIN(93, "BPKI3C_SCL"), + /* vGPIO_3 */ + PINCTRL_PIN(94, "TS0_IN_INT"), + PINCTRL_PIN(95, "TS1_IN_INT"), + /* GPP_D */ + PINCTRL_PIN(96, "TIME_SYNC_0"), + PINCTRL_PIN(97, "TIME_SYNC_1"), + PINCTRL_PIN(98, "DSI_DE_TE_2_GENLOCK_REF"), + PINCTRL_PIN(99, "DSI_DE_TE_1_DISP_UTILS"), + PINCTRL_PIN(100, "DSI_GENLOCK_2"), + PINCTRL_PIN(101, "DSI_GENLOCK_3"), + PINCTRL_PIN(102, "SRCCLKREQ2_B"), + PINCTRL_PIN(103, "SRCCLKREQ3_B"), + PINCTRL_PIN(104, "GPP_SD_8"), + PINCTRL_PIN(105, "GPP_SD_9"), + PINCTRL_PIN(106, "GPP_SD_10"), + PINCTRL_PIN(107, "GPP_SD_11"), + PINCTRL_PIN(108, "GPP_SD_12"), + PINCTRL_PIN(109, "GPP_SD_13"), + PINCTRL_PIN(110, "GPP_SD_14"), + PINCTRL_PIN(111, "GPP_SD_15"), + PINCTRL_PIN(112, "GPP_SD_16"), + PINCTRL_PIN(113, "GPP_SD_17"), + PINCTRL_PIN(114, "BOOTHALT_B"), + PINCTRL_PIN(115, "GPP_SD_19"), + PINCTRL_PIN(116, "GPP_SD_20"), + PINCTRL_PIN(117, "AUDCLK"), + PINCTRL_PIN(118, "AUDIN"), + PINCTRL_PIN(119, "AUDOUT"), + /* JTAG_CPU */ + PINCTRL_PIN(120, "PECI"), + PINCTRL_PIN(121, "VIDSOUT"), + PINCTRL_PIN(122, "VIDSCK"), + PINCTRL_PIN(123, "VIDALERT_B"), + PINCTRL_PIN(124, "JTAG_MBPB0"), + PINCTRL_PIN(125, "JTAG_MBPB1"), + PINCTRL_PIN(126, "JTAG_MBPB2"), + PINCTRL_PIN(127, "JTAG_MBPB3"), + PINCTRL_PIN(128, "JTAG_TDO"), + PINCTRL_PIN(129, "PRDY_B"), + PINCTRL_PIN(130, "PREQ_B"), + PINCTRL_PIN(131, "JTAG_TDI"), + PINCTRL_PIN(132, "JTAG_TMS"), + PINCTRL_PIN(133, "JTAG_TCK"), + PINCTRL_PIN(134, "DBG_PMODE"), + PINCTRL_PIN(135, "JTAG_TRST_B"), + /* vGPIO_4 */ + PINCTRL_PIN(136, "ISCLK_ESPI_XTAL_CLKREQ"), + PINCTRL_PIN(137, "ESPI_ISCLK_XTAL_CLKACK"), + PINCTRL_PIN(138, "vGPIO_SPARE4"), + PINCTRL_PIN(139, "vGPIO_SPARE5"), + PINCTRL_PIN(140, "vGPIO_SPARE6"), + PINCTRL_PIN(141, "vGPIO_SPARE7"), + PINCTRL_PIN(142, "vGPIO_SPARE16"), + PINCTRL_PIN(143, "vGPIO_SPARE17"), + PINCTRL_PIN(144, "vGPIO_SPARE18"), + PINCTRL_PIN(145, "vGPIO_SPARE19"), + PINCTRL_PIN(146, "vGPIO_SPARE20"), + PINCTRL_PIN(147, "vGPIO_SPARE21"), +}; + +static const struct intel_padgroup mtls_community0_gpps[] = { + MTL_GPP(0, 0, 27, 0), /* GPP_A */ + MTL_GPP(1, 28, 46, 32), /* vGPIO_0 */ + MTL_GPP(2, 47, 73, 64), /* GPP_C */ +}; + +static const struct intel_padgroup mtls_community1_gpps[] = { + MTL_GPP(0, 74, 93, 96), /* GPP_B */ + MTL_GPP(1, 94, 95, 128), /* vGPIO_3 */ + MTL_GPP(2, 96, 119, 160), /* GPP_D */ +}; + +static const struct intel_padgroup mtls_community3_gpps[] = { + MTL_GPP(0, 120, 135, 192), /* JTAG_CPU */ + MTL_GPP(1, 136, 147, 224), /* vGPIO_4 */ +}; + +static const struct intel_community mtls_communities[] = { + MTL_S_COMMUNITY(0, 0, 73, mtls_community0_gpps), + MTL_S_COMMUNITY(1, 74, 119, mtls_community1_gpps), + MTL_S_COMMUNITY(2, 120, 147, mtls_community3_gpps), +}; + +static const struct intel_pinctrl_soc_data mtls_soc_data = { + .pins = mtls_pins, + .npins = ARRAY_SIZE(mtls_pins), + .communities = mtls_communities, + .ncommunities = ARRAY_SIZE(mtls_communities), +}; + static const struct acpi_device_id mtl_pinctrl_acpi_match[] = { { "INTC1083", (kernel_ulong_t)&mtlp_soc_data }, + { "INTC1082", (kernel_ulong_t)&mtls_soc_data }, { } }; MODULE_DEVICE_TABLE(acpi, mtl_pinctrl_acpi_match); diff --git a/drivers/pinctrl/intel/pinctrl-moorefield.c b/drivers/pinctrl/intel/pinctrl-moorefield.c index 3c9a8484b442..2d38d953f360 100644 --- a/drivers/pinctrl/intel/pinctrl-moorefield.c +++ b/drivers/pinctrl/intel/pinctrl-moorefield.c @@ -504,7 +504,7 @@ static void mofld_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, } mode = (value & BUFCFG_PINMODE_MASK) >> BUFCFG_PINMODE_SHIFT; - if (!mode) + if (mode == BUFCFG_PINMODE_GPIO) seq_puts(s, "GPIO "); else seq_printf(s, "mode %d ", mode); @@ -661,6 +661,11 @@ static int mofld_config_get(struct pinctrl_dev *pctldev, unsigned int pin, break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + if (value & BUFCFG_OD_EN) + return -EINVAL; + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: if (!(value & BUFCFG_OD_EN)) return -EINVAL; @@ -734,10 +739,14 @@ static int mofld_config_set_pin(struct mofld_pinctrl *mp, unsigned int pin, break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + mask |= BUFCFG_OD_EN; + bits &= ~BUFCFG_OD_EN; + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: mask |= BUFCFG_OD_EN; - if (arg) - bits |= BUFCFG_OD_EN; + bits |= BUFCFG_OD_EN; break; case PIN_CONFIG_SLEW_RATE: @@ -769,6 +778,7 @@ static int mofld_config_set(struct pinctrl_dev *pctldev, unsigned int pin, case PIN_CONFIG_BIAS_DISABLE: case PIN_CONFIG_BIAS_PULL_UP: case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_DRIVE_PUSH_PULL: case PIN_CONFIG_DRIVE_OPEN_DRAIN: case PIN_CONFIG_SLEW_RATE: ret = mofld_config_set_pin(mp, pin, configs[i]); diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c index 21e61c2a3798..843ffcd96877 100644 --- a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c +++ b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c @@ -1884,6 +1884,8 @@ static int npcm7xx_gpio_of(struct npcm7xx_pinctrl *pctrl) } pctrl->gpio_bank[id].base = ioremap(res.start, resource_size(&res)); + if (!pctrl->gpio_bank[id].base) + return -EINVAL; ret = bgpio_init(&pctrl->gpio_bank[id].gc, dev, 4, pctrl->gpio_bank[id].base + NPCM7XX_GP_N_DIN, diff --git a/drivers/pinctrl/nxp/pinctrl-s32.h b/drivers/pinctrl/nxp/pinctrl-s32.h index 2f7aecd462e4..add3c77ddfed 100644 --- a/drivers/pinctrl/nxp/pinctrl-s32.h +++ b/drivers/pinctrl/nxp/pinctrl-s32.h @@ -34,24 +34,28 @@ struct s32_pin_range { unsigned int end; }; -struct s32_pinctrl_soc_info { - struct device *dev; +struct s32_pinctrl_soc_data { const struct pinctrl_pin_desc *pins; unsigned int npins; + const struct s32_pin_range *mem_pin_ranges; + unsigned int mem_regions; +}; + +struct s32_pinctrl_soc_info { + struct device *dev; + const struct s32_pinctrl_soc_data *soc_data; struct s32_pin_group *groups; unsigned int ngroups; struct pinfunction *functions; unsigned int nfunctions; unsigned int grp_index; - const struct s32_pin_range *mem_pin_ranges; - unsigned int mem_regions; }; #define S32_PINCTRL_PIN(pin) PINCTRL_PIN(pin, #pin) #define S32_PIN_RANGE(_start, _end) { .start = _start, .end = _end } int s32_pinctrl_probe(struct platform_device *pdev, - struct s32_pinctrl_soc_info *info); + const struct s32_pinctrl_soc_data *soc_data); int s32_pinctrl_resume(struct device *dev); int s32_pinctrl_suspend(struct device *dev); #endif /* __DRIVERS_PINCTRL_S32_H */ diff --git a/drivers/pinctrl/nxp/pinctrl-s32cc.c b/drivers/pinctrl/nxp/pinctrl-s32cc.c index 8373468719b6..3ae043b27463 100644 --- a/drivers/pinctrl/nxp/pinctrl-s32cc.c +++ b/drivers/pinctrl/nxp/pinctrl-s32cc.c @@ -106,7 +106,7 @@ s32_get_region(struct pinctrl_dev *pctldev, unsigned int pin) { struct s32_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); const struct s32_pin_range *pin_range; - unsigned int mem_regions = ipctl->info->mem_regions; + unsigned int mem_regions = ipctl->info->soc_data->mem_regions; unsigned int i; for (i = 0; i < mem_regions; i++) { @@ -279,8 +279,10 @@ static int s32_dt_node_to_map(struct pinctrl_dev *pctldev, ret = s32_dt_group_node_to_map(pctldev, np, map, &reserved_maps, num_maps, np_config->name); - if (ret < 0) + if (ret < 0) { + of_node_put(np); break; + } } if (ret) @@ -688,8 +690,8 @@ int s32_pinctrl_suspend(struct device *dev) int ret; unsigned int config; - for (i = 0; i < info->npins; i++) { - pin = &info->pins[i]; + for (i = 0; i < info->soc_data->npins; i++) { + pin = &info->soc_data->pins[i]; if (!s32_pinctrl_should_save(ipctl, pin->number)) continue; @@ -713,8 +715,8 @@ int s32_pinctrl_resume(struct device *dev) struct s32_pinctrl_context *saved_context = &ipctl->saved_context; int ret, i; - for (i = 0; i < info->npins; i++) { - pin = &info->pins[i]; + for (i = 0; i < info->soc_data->npins; i++) { + pin = &info->soc_data->pins[i]; if (!s32_pinctrl_should_save(ipctl, pin->number)) continue; @@ -812,8 +814,10 @@ static int s32_pinctrl_parse_functions(struct device_node *np, groups[i] = child->name; grp = &info->groups[info->grp_index++]; ret = s32_pinctrl_parse_groups(child, grp, info); - if (ret) + if (ret) { + of_node_put(child); return ret; + } i++; } @@ -831,7 +835,7 @@ static int s32_pinctrl_probe_dt(struct platform_device *pdev, struct resource *res; struct regmap *map; void __iomem *base; - int mem_regions = info->mem_regions; + unsigned int mem_regions = info->soc_data->mem_regions; int ret; u32 nfuncs = 0; u32 i = 0; @@ -869,7 +873,7 @@ static int s32_pinctrl_probe_dt(struct platform_device *pdev, } ipctl->regions[i].map = map; - ipctl->regions[i].pin_range = &info->mem_pin_ranges[i]; + ipctl->regions[i].pin_range = &info->soc_data->mem_pin_ranges[i]; } nfuncs = of_get_child_count(np); @@ -896,28 +900,36 @@ static int s32_pinctrl_probe_dt(struct platform_device *pdev, i = 0; for_each_child_of_node(np, child) { ret = s32_pinctrl_parse_functions(child, info, i++); - if (ret) + if (ret) { + of_node_put(child); return ret; + } } return 0; } int s32_pinctrl_probe(struct platform_device *pdev, - struct s32_pinctrl_soc_info *info) + const struct s32_pinctrl_soc_data *soc_data) { struct s32_pinctrl *ipctl; int ret; struct pinctrl_desc *s32_pinctrl_desc; + struct s32_pinctrl_soc_info *info; #ifdef CONFIG_PM_SLEEP struct s32_pinctrl_context *saved_context; #endif - if (!info || !info->pins || !info->npins) { + if (!soc_data || !soc_data->pins || !soc_data->npins) { dev_err(&pdev->dev, "wrong pinctrl info\n"); return -EINVAL; } + info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->soc_data = soc_data; info->dev = &pdev->dev; /* Create state holders etc for this driver */ @@ -938,8 +950,8 @@ int s32_pinctrl_probe(struct platform_device *pdev, return -ENOMEM; s32_pinctrl_desc->name = dev_name(&pdev->dev); - s32_pinctrl_desc->pins = info->pins; - s32_pinctrl_desc->npins = info->npins; + s32_pinctrl_desc->pins = info->soc_data->pins; + s32_pinctrl_desc->npins = info->soc_data->npins; s32_pinctrl_desc->pctlops = &s32_pctrl_ops; s32_pinctrl_desc->pmxops = &s32_pmx_ops; s32_pinctrl_desc->confops = &s32_pinconf_ops; @@ -960,7 +972,7 @@ int s32_pinctrl_probe(struct platform_device *pdev, #ifdef CONFIG_PM_SLEEP saved_context = &ipctl->saved_context; saved_context->pads = - devm_kcalloc(&pdev->dev, info->npins, + devm_kcalloc(&pdev->dev, info->soc_data->npins, sizeof(*saved_context->pads), GFP_KERNEL); if (!saved_context->pads) diff --git a/drivers/pinctrl/nxp/pinctrl-s32g2.c b/drivers/pinctrl/nxp/pinctrl-s32g2.c index d9f3ff6794ea..224a12ce70ed 100644 --- a/drivers/pinctrl/nxp/pinctrl-s32g2.c +++ b/drivers/pinctrl/nxp/pinctrl-s32g2.c @@ -721,7 +721,7 @@ static const struct s32_pin_range s32_pin_ranges_siul2[] = { S32_PIN_RANGE(942, 1007), }; -static struct s32_pinctrl_soc_info s32_pinctrl_info = { +static const struct s32_pinctrl_soc_data s32_pinctrl_data = { .pins = s32_pinctrl_pads_siul2, .npins = ARRAY_SIZE(s32_pinctrl_pads_siul2), .mem_pin_ranges = s32_pin_ranges_siul2, @@ -730,9 +730,8 @@ static struct s32_pinctrl_soc_info s32_pinctrl_info = { static const struct of_device_id s32_pinctrl_of_match[] = { { - .compatible = "nxp,s32g2-siul2-pinctrl", - .data = (void *) &s32_pinctrl_info, + .data = &s32_pinctrl_data, }, { /* sentinel */ } }; @@ -740,14 +739,11 @@ MODULE_DEVICE_TABLE(of, s32_pinctrl_of_match); static int s32g_pinctrl_probe(struct platform_device *pdev) { - const struct of_device_id *of_id = - of_match_device(s32_pinctrl_of_match, &pdev->dev); + const struct s32_pinctrl_soc_data *soc_data; - if (!of_id) - return -ENODEV; + soc_data = of_device_get_match_data(&pdev->dev); - return s32_pinctrl_probe - (pdev, (struct s32_pinctrl_soc_info *) of_id->data); + return s32_pinctrl_probe(pdev, soc_data); } static const struct dev_pm_ops s32g_pinctrl_pm_ops = { diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index 43d3530bab48..3c4220be30ec 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -126,6 +126,12 @@ static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset, struct amd_gpio *gpio_dev = gpiochip_get_data(gc); raw_spin_lock_irqsave(&gpio_dev->lock, flags); + + /* Use special handling for Pin0 debounce */ + pin_reg = readl(gpio_dev->base + WAKE_INT_MASTER_REG); + if (pin_reg & INTERNAL_GPIO0_DEBOUNCE) + debounce = 0; + pin_reg = readl(gpio_dev->base + offset * 4); if (debounce) { @@ -220,6 +226,7 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc) char *debounce_enable; char *wake_cntrlz; + seq_printf(s, "WAKE_INT_MASTER_REG: 0x%08x\n", readl(gpio_dev->base + WAKE_INT_MASTER_REG)); for (bank = 0; bank < gpio_dev->hwbank_num; bank++) { unsigned int time = 0; unsigned int unit = 0; @@ -653,21 +660,21 @@ static bool do_amd_gpio_irq_handler(int irq, void *dev_id) * We must read the pin register again, in case the * value was changed while executing * generic_handle_domain_irq() above. - * If we didn't find a mapping for the interrupt, - * disable it in order to avoid a system hang caused - * by an interrupt storm. + * If the line is not an irq, disable it in order to + * avoid a system hang caused by an interrupt storm. */ raw_spin_lock_irqsave(&gpio_dev->lock, flags); regval = readl(regs + i); - if (irq == 0) { - regval &= ~BIT(INTERRUPT_ENABLE_OFF); + if (!gpiochip_line_is_irq(gc, irqnr + i)) { + regval &= ~BIT(INTERRUPT_MASK_OFF); dev_dbg(&gpio_dev->pdev->dev, "Disabling spurious GPIO IRQ %d\n", irqnr + i); + } else { + ret = true; } writel(regval, regs + i); raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); - ret = true; } } /* did not cause wake on resume context for shared IRQ */ @@ -870,34 +877,6 @@ static const struct pinconf_ops amd_pinconf_ops = { .pin_config_group_set = amd_pinconf_group_set, }; -static void amd_gpio_irq_init(struct amd_gpio *gpio_dev) -{ - struct pinctrl_desc *desc = gpio_dev->pctrl->desc; - unsigned long flags; - u32 pin_reg, mask; - int i; - - mask = BIT(WAKE_CNTRL_OFF_S0I3) | BIT(WAKE_CNTRL_OFF_S3) | - BIT(INTERRUPT_MASK_OFF) | BIT(INTERRUPT_ENABLE_OFF) | - BIT(WAKE_CNTRL_OFF_S4); - - for (i = 0; i < desc->npins; i++) { - int pin = desc->pins[i].number; - const struct pin_desc *pd = pin_desc_get(gpio_dev->pctrl, pin); - - if (!pd) - continue; - - raw_spin_lock_irqsave(&gpio_dev->lock, flags); - - pin_reg = readl(gpio_dev->base + i * 4); - pin_reg &= ~mask; - writel(pin_reg, gpio_dev->base + i * 4); - - raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); - } -} - #ifdef CONFIG_PM_SLEEP static bool amd_gpio_should_save(struct amd_gpio *gpio_dev, unsigned int pin) { @@ -1135,9 +1114,6 @@ static int amd_gpio_probe(struct platform_device *pdev) return PTR_ERR(gpio_dev->pctrl); } - /* Disable and mask interrupts */ - amd_gpio_irq_init(gpio_dev); - girq = &gpio_dev->gc.irq; gpio_irq_chip_set_chip(girq, &amd_gpio_irqchip); /* This will let us handle the parent IRQ in the driver */ diff --git a/drivers/pinctrl/pinctrl-amd.h b/drivers/pinctrl/pinctrl-amd.h index 81ae8319a1f0..1cf2d06bbd8c 100644 --- a/drivers/pinctrl/pinctrl-amd.h +++ b/drivers/pinctrl/pinctrl-amd.h @@ -17,6 +17,7 @@ #define AMD_GPIO_PINS_BANK3 32 #define WAKE_INT_MASTER_REG 0xfc +#define INTERNAL_GPIO0_DEBOUNCE (1 << 15) #define EOI_MASK (1 << 29) #define WAKE_INT_STATUS_REG0 0x2f8 diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c index 2fe40acb6a3e..5d360ba3abc2 100644 --- a/drivers/pinctrl/pinctrl-at91-pio4.c +++ b/drivers/pinctrl/pinctrl-at91-pio4.c @@ -762,6 +762,11 @@ static int atmel_conf_pin_config_group_get(struct pinctrl_dev *pctldev, return -EINVAL; arg = 1; break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + if (res & ATMEL_PIO_OPD_MASK) + return -EINVAL; + arg = 1; + break; case PIN_CONFIG_INPUT_SCHMITT_ENABLE: if (!(res & ATMEL_PIO_SCHMITT_MASK)) return -EINVAL; @@ -827,10 +832,10 @@ static int atmel_conf_pin_config_group_set(struct pinctrl_dev *pctldev, conf &= (~ATMEL_PIO_PUEN_MASK); break; case PIN_CONFIG_DRIVE_OPEN_DRAIN: - if (arg == 0) - conf &= (~ATMEL_PIO_OPD_MASK); - else - conf |= ATMEL_PIO_OPD_MASK; + conf |= ATMEL_PIO_OPD_MASK; + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + conf &= ~ATMEL_PIO_OPD_MASK; break; case PIN_CONFIG_INPUT_SCHMITT_ENABLE: if (arg == 0) @@ -948,6 +953,8 @@ static void atmel_conf_pin_config_dbg_show(struct pinctrl_dev *pctldev, seq_printf(s, "%s ", "debounce"); if (conf & ATMEL_PIO_OPD_MASK) seq_printf(s, "%s ", "open-drain"); + else + seq_printf(s, "%s ", "push-pull"); if (conf & ATMEL_PIO_SCHMITT_MASK) seq_printf(s, "%s ", "schmitt"); if (atmel_pioctrl->slew_rate_support && (conf & ATMEL_PIO_SR_MASK)) @@ -1146,6 +1153,8 @@ static int atmel_pinctrl_probe(struct platform_device *pdev) /* Pin naming convention: P(bank_name)(bank_pin_number). */ pin_desc[i].name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "P%c%u", bank + 'A', line); + if (!pin_desc[i].name) + return -ENOMEM; group->name = group_names[i] = pin_desc[i].name; group->pin = pin_desc[i].number; diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index 871209c24153..39956d821ad7 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -1389,8 +1389,8 @@ static int at91_pinctrl_probe(struct platform_device *pdev) char **names; names = devm_kasprintf_strarray(dev, "pio", MAX_NB_GPIO_PER_BANK); - if (!names) - return -ENOMEM; + if (IS_ERR(names)) + return PTR_ERR(names); for (j = 0; j < MAX_NB_GPIO_PER_BANK; j++, k++) { char *name = names[j]; @@ -1870,8 +1870,8 @@ static int at91_gpio_probe(struct platform_device *pdev) } names = devm_kasprintf_strarray(dev, "pio", chip->ngpio); - if (!names) - return -ENOMEM; + if (IS_ERR(names)) + return PTR_ERR(names); for (i = 0; i < chip->ngpio; i++) strreplace(names[i], '-', alias_idx + 'A'); diff --git a/drivers/pinctrl/pinctrl-axp209.c b/drivers/pinctrl/pinctrl-axp209.c index 0bc1b381a2b8..b3ba25435c34 100644 --- a/drivers/pinctrl/pinctrl-axp209.c +++ b/drivers/pinctrl/pinctrl-axp209.c @@ -30,6 +30,11 @@ #define AXP20X_GPIO_FUNCTION_OUT_HIGH 1 #define AXP20X_GPIO_FUNCTION_INPUT 2 +#define AXP20X_GPIO3_FUNCTIONS GENMASK(2, 1) +#define AXP20X_GPIO3_FUNCTION_OUT_LOW 0 +#define AXP20X_GPIO3_FUNCTION_OUT_HIGH 2 +#define AXP20X_GPIO3_FUNCTION_INPUT 4 + #define AXP20X_FUNC_GPIO_OUT 0 #define AXP20X_FUNC_GPIO_IN 1 #define AXP20X_FUNC_LDO 2 @@ -73,6 +78,7 @@ static const struct pinctrl_pin_desc axp209_pins[] = { PINCTRL_PIN(0, "GPIO0"), PINCTRL_PIN(1, "GPIO1"), PINCTRL_PIN(2, "GPIO2"), + PINCTRL_PIN(3, "GPIO3"), }; static const struct pinctrl_pin_desc axp22x_pins[] = { @@ -130,6 +136,14 @@ static int axp20x_gpio_get(struct gpio_chip *chip, unsigned int offset) unsigned int val; int ret; + /* AXP209 has GPIO3 status sharing the settings register */ + if (offset == 3) { + ret = regmap_read(pctl->regmap, AXP20X_GPIO3_CTRL, &val); + if (ret) + return ret; + return !!(val & BIT(0)); + } + ret = regmap_read(pctl->regmap, AXP20X_GPIO20_SS, &val); if (ret) return ret; @@ -144,6 +158,17 @@ static int axp20x_gpio_get_direction(struct gpio_chip *chip, unsigned int val; int reg, ret; + /* AXP209 GPIO3 settings have a different layout */ + if (offset == 3) { + ret = regmap_read(pctl->regmap, AXP20X_GPIO3_CTRL, &val); + if (ret) + return ret; + if (val & AXP20X_GPIO3_FUNCTION_INPUT) + return GPIO_LINE_DIRECTION_IN; + + return GPIO_LINE_DIRECTION_OUT; + } + reg = axp20x_gpio_get_reg(offset); if (reg < 0) return reg; @@ -184,6 +209,15 @@ static void axp20x_gpio_set(struct gpio_chip *chip, unsigned int offset, struct axp20x_pctl *pctl = gpiochip_get_data(chip); int reg; + /* AXP209 has GPIO3 status sharing the settings register */ + if (offset == 3) { + regmap_update_bits(pctl->regmap, AXP20X_GPIO3_CTRL, + AXP20X_GPIO3_FUNCTIONS, + value ? AXP20X_GPIO3_FUNCTION_OUT_HIGH : + AXP20X_GPIO3_FUNCTION_OUT_LOW); + return; + } + reg = axp20x_gpio_get_reg(offset); if (reg < 0) return; @@ -200,6 +234,14 @@ static int axp20x_pmx_set(struct pinctrl_dev *pctldev, unsigned int offset, struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev); int reg; + /* AXP209 GPIO3 settings have a different layout */ + if (offset == 3) { + return regmap_update_bits(pctl->regmap, AXP20X_GPIO3_CTRL, + AXP20X_GPIO3_FUNCTIONS, + config == AXP20X_MUX_GPIO_OUT ? AXP20X_GPIO3_FUNCTION_OUT_LOW : + AXP20X_GPIO3_FUNCTION_INPUT); + } + reg = axp20x_gpio_get_reg(offset); if (reg < 0) return reg; diff --git a/drivers/pinctrl/pinctrl-cy8c95x0.c b/drivers/pinctrl/pinctrl-cy8c95x0.c index 564fbaabcdb8..2ecc96691c55 100644 --- a/drivers/pinctrl/pinctrl-cy8c95x0.c +++ b/drivers/pinctrl/pinctrl-cy8c95x0.c @@ -1442,7 +1442,7 @@ static struct i2c_driver cy8c95x0_driver = { .of_match_table = cy8c95x0_dt_ids, .acpi_match_table = cy8c95x0_acpi_ids, }, - .probe_new = cy8c95x0_probe, + .probe = cy8c95x0_probe, .remove = cy8c95x0_remove, .id_table = cy8c95x0_id, .detect = cy8c95x0_detect, diff --git a/drivers/pinctrl/pinctrl-falcon.c b/drivers/pinctrl/pinctrl-falcon.c index 2eab14f86fa3..0bf9ffbcc79f 100644 --- a/drivers/pinctrl/pinctrl-falcon.c +++ b/drivers/pinctrl/pinctrl-falcon.c @@ -14,7 +14,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_gpio.h> #include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/seq_file.h> diff --git a/drivers/pinctrl/pinctrl-mcp23s08_i2c.c b/drivers/pinctrl/pinctrl-mcp23s08_i2c.c index b635c5737e0c..3dd1bd8e73eb 100644 --- a/drivers/pinctrl/pinctrl-mcp23s08_i2c.c +++ b/drivers/pinctrl/pinctrl-mcp23s08_i2c.c @@ -101,7 +101,7 @@ static struct i2c_driver mcp230xx_driver = { .name = "mcp230xx", .of_match_table = mcp23s08_i2c_of_match, }, - .probe_new = mcp230xx_probe, + .probe = mcp230xx_probe, .id_table = mcp230xx_id, }; diff --git a/drivers/pinctrl/pinctrl-microchip-sgpio.c b/drivers/pinctrl/pinctrl-microchip-sgpio.c index 4794602316e7..a60db93b61b1 100644 --- a/drivers/pinctrl/pinctrl-microchip-sgpio.c +++ b/drivers/pinctrl/pinctrl-microchip-sgpio.c @@ -719,8 +719,6 @@ static void microchip_sgpio_irq_ack(struct irq_data *data) static int microchip_sgpio_irq_set_type(struct irq_data *data, unsigned int type) { - type &= IRQ_TYPE_SENSE_MASK; - switch (type) { case IRQ_TYPE_EDGE_BOTH: irq_set_handler_locked(data, handle_edge_irq); @@ -818,6 +816,9 @@ static int microchip_sgpio_register_bank(struct device *dev, pctl_desc->name = devm_kasprintf(dev, GFP_KERNEL, "%s-%sput", dev_name(dev), bank->is_input ? "in" : "out"); + if (!pctl_desc->name) + return -ENOMEM; + pctl_desc->pctlops = &sgpio_pctl_ops; pctl_desc->pmxops = &sgpio_pmx_ops; pctl_desc->confops = &sgpio_confops; diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index 7632ffc3946f..35faea8dfb0b 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -1262,7 +1262,7 @@ static struct i2c_driver sx150x_driver = { .name = "sx150x-pinctrl", .of_match_table = sx150x_of_match, }, - .probe_new = sx150x_probe, + .probe = sx150x_probe, .id_table = sx150x_id, }; diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c index 858abb23b337..cf0383f575d9 100644 --- a/drivers/pinctrl/pinctrl-xway.c +++ b/drivers/pinctrl/pinctrl-xway.c @@ -8,11 +8,11 @@ */ #include <linux/err.h> +#include <linux/gpio/driver.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/of_platform.h> #include <linux/of_address.h> -#include <linux/of_gpio.h> #include <linux/ioport.h> #include <linux/io.h> #include <linux/device.h> diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 021382632608..82c750a31952 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -677,7 +677,6 @@ void pinmux_show_setting(struct seq_file *s, DEFINE_SHOW_ATTRIBUTE(pinmux_functions); DEFINE_SHOW_ATTRIBUTE(pinmux_pins); -#define PINMUX_SELECT_MAX 128 static ssize_t pinmux_select(struct file *file, const char __user *user_buf, size_t len, loff_t *ppos) { @@ -689,17 +688,9 @@ static ssize_t pinmux_select(struct file *file, const char __user *user_buf, unsigned int num_groups; int fsel, gsel, ret; - if (len > PINMUX_SELECT_MAX) - return -ENOMEM; - - buf = kzalloc(PINMUX_SELECT_MAX, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - ret = strncpy_from_user(buf, user_buf, PINMUX_SELECT_MAX); - if (ret < 0) - goto exit_free_buf; - buf[len-1] = '\0'; + buf = memdup_user_nul(user_buf, len); + if (IS_ERR(buf)) + return PTR_ERR(buf); /* remove leading and trailing spaces of input buffer */ gname = strstrip(buf); diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig index e52cfab8d5ae..634c75336983 100644 --- a/drivers/pinctrl/qcom/Kconfig +++ b/drivers/pinctrl/qcom/Kconfig @@ -4,6 +4,8 @@ if (ARCH_QCOM || COMPILE_TEST) config PINCTRL_MSM tristate "Qualcomm core pin controller driver" depends on GPIOLIB + # OF for pinconf_generic_dt_node_to_map_group() from GENERIC_PINCONF + depends on OF select QCOM_SCM select PINMUX select PINCONF @@ -12,231 +14,7 @@ config PINCTRL_MSM select IRQ_DOMAIN_HIERARCHY select IRQ_FASTEOI_HIERARCHY_HANDLERS -config PINCTRL_APQ8064 - tristate "Qualcomm APQ8064 pin controller driver" - depends on OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm APQ8064 platform. - -config PINCTRL_APQ8084 - tristate "Qualcomm APQ8084 pin controller driver" - depends on OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm APQ8084 platform. - -config PINCTRL_IPQ4019 - tristate "Qualcomm IPQ4019 pin controller driver" - depends on OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm IPQ4019 platform. - -config PINCTRL_IPQ8064 - tristate "Qualcomm IPQ8064 pin controller driver" - depends on OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm IPQ8064 platform. - -config PINCTRL_IPQ5332 - tristate "Qualcomm Technologies Inc IPQ5332 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc IPQ5332 platform. - -config PINCTRL_IPQ8074 - tristate "Qualcomm Technologies, Inc. IPQ8074 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for - the Qualcomm Technologies Inc. TLMM block found on the - Qualcomm Technologies Inc. IPQ8074 platform. Select this for - IPQ8074. - -config PINCTRL_IPQ6018 - tristate "Qualcomm Technologies, Inc. IPQ6018 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for - the Qualcomm Technologies Inc. TLMM block found on the - Qualcomm Technologies Inc. IPQ6018 platform. Select this for - IPQ6018. - -config PINCTRL_IPQ9574 - tristate "Qualcomm Technologies, Inc. IPQ9574 pin controller driver" - depends on OF || COMPILE_TEST - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for - the Qualcomm Technologies Inc. TLMM block found on the - Qualcomm Technologies Inc. IPQ9574 platform. Select this for - IPQ9574. - -config PINCTRL_MSM8226 - tristate "Qualcomm 8226 pin controller driver" - depends on OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc MSM8226 platform. - -config PINCTRL_MSM8660 - tristate "Qualcomm 8660 pin controller driver" - depends on OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm 8660 platform. - -config PINCTRL_MSM8960 - tristate "Qualcomm 8960 pin controller driver" - depends on OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm 8960 platform. - -config PINCTRL_MDM9607 - tristate "Qualcomm 9607 pin controller driver" - depends on GPIOLIB && OF - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm 9607 platform. - -config PINCTRL_MDM9615 - tristate "Qualcomm 9615 pin controller driver" - depends on OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm 9615 platform. - -config PINCTRL_MSM8X74 - tristate "Qualcomm 8x74 pin controller driver" - depends on OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm 8974 platform. - -config PINCTRL_MSM8909 - tristate "Qualcomm 8909 pin controller driver" - depends on OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found on the Qualcomm MSM8909 platform. - -config PINCTRL_MSM8916 - tristate "Qualcomm 8916 pin controller driver" - depends on OF - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found on the Qualcomm 8916 platform. - -config PINCTRL_MSM8953 - tristate "Qualcomm 8953 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found on the Qualcomm MSM8953 platform. - The Qualcomm APQ8053, SDM450, SDM632 platforms are also - supported by this driver. - -config PINCTRL_MSM8976 - tristate "Qualcomm 8976 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found on the Qualcomm MSM8976 platform. - The Qualcomm MSM8956, APQ8056, APQ8076 platforms are also - supported by this driver. - -config PINCTRL_MSM8994 - tristate "Qualcomm 8994 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm 8994 platform. The - Qualcomm 8992 platform is also supported by this driver. - -config PINCTRL_MSM8996 - tristate "Qualcomm MSM8996 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm MSM8996 platform. - -config PINCTRL_MSM8998 - tristate "Qualcomm MSM8998 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm MSM8998 platform. - -config PINCTRL_QCM2290 - tristate "Qualcomm QCM2290 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - TLMM block found in the Qualcomm QCM2290 platform. - -config PINCTRL_QCS404 - tristate "Qualcomm QCS404 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - TLMM block found in the Qualcomm QCS404 platform. - -config PINCTRL_QDF2XXX - tristate "Qualcomm Technologies QDF2xxx pin controller driver" - depends on ACPI - depends on PINCTRL_MSM - help - This is the GPIO driver for the TLMM block found on the - Qualcomm Technologies QDF2xxx SOCs. +source "drivers/pinctrl/qcom/Kconfig.msm" config PINCTRL_QCOM_SPMI_PMIC tristate "Qualcomm SPMI PMIC pin controller driver" @@ -245,7 +23,7 @@ config PINCTRL_QCOM_SPMI_PMIC select PINMUX select PINCONF select GENERIC_PINCONF - select GPIOLIB + select GPIOLIB select GPIOLIB_IRQCHIP select IRQ_DOMAIN_HIERARCHY help @@ -260,7 +38,7 @@ config PINCTRL_QCOM_SSBI_PMIC select PINMUX select PINCONF select GENERIC_PINCONF - select GPIOLIB + select GPIOLIB select GPIOLIB_IRQCHIP select IRQ_DOMAIN_HIERARCHY help @@ -269,48 +47,20 @@ config PINCTRL_QCOM_SSBI_PMIC which are using SSBI for communication with SoC. Example PMIC's devices are pm8058 and pm8921. -config PINCTRL_QDU1000 - tristate "Qualcomm Tehcnologies Inc QDU1000/QRU1000 pin controller driver" - depends on GPIOLIB && OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf, and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc QDU1000 and QRU1000 platforms. - -config PINCTRL_SA8775P - tristate "Qualcomm Technologies Inc SA8775P pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux and pinconf driver for the Qualcomm - TLMM block found on the Qualcomm SA8775P platforms. - -config PINCTRL_SC7180 - tristate "Qualcomm Technologies Inc SC7180 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SC7180 platform. - -config PINCTRL_SC7280 - tristate "Qualcomm Technologies Inc SC7280 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM +config PINCTRL_LPASS_LPI + tristate "Qualcomm Technologies Inc LPASS LPI pin controller driver" + select PINMUX + select PINCONF + select GENERIC_PINCONF + select GENERIC_PINCTRL_GROUPS + depends on GPIOLIB help This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SC7280 platform. + Qualcomm Technologies Inc LPASS (Low Power Audio SubSystem) LPI + (Low Power Island) found on the Qualcomm Technologies Inc SoCs. config PINCTRL_SC7280_LPASS_LPI tristate "Qualcomm Technologies Inc SC7280 LPASS LPI pin controller driver" - depends on GPIOLIB depends on ARM64 || COMPILE_TEST depends on PINCTRL_LPASS_LPI help @@ -318,149 +68,8 @@ config PINCTRL_SC7280_LPASS_LPI Qualcomm Technologies Inc LPASS (Low Power Audio SubSystem) LPI (Low Power Island) found on the Qualcomm Technologies Inc SC7280 platform. -config PINCTRL_SC8180X - tristate "Qualcomm Technologies Inc SC8180x pin controller driver" - depends on (OF || ACPI) - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SC8180x platform. - -config PINCTRL_SC8280XP - tristate "Qualcomm Technologies Inc SC8280xp pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SC8280xp platform. - -config PINCTRL_SDM660 - tristate "Qualcomm Technologies Inc SDM660 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SDM660 platform. - -config PINCTRL_SDM670 - tristate "Qualcomm Technologies Inc SDM670 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SDM670 platform. - -config PINCTRL_SDM845 - tristate "Qualcomm Technologies Inc SDM845 pin controller driver" - depends on (OF || ACPI) - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SDM845 platform. - -config PINCTRL_SDX55 - tristate "Qualcomm Technologies Inc SDX55 pin controller driver" - depends on OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SDX55 platform. - -config PINCTRL_SM6115 - tristate "Qualcomm Technologies Inc SM6115,SM4250 pin controller driver" - depends on GPIOLIB && OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SM6115 and SM4250 platforms. - -config PINCTRL_SM6125 - tristate "Qualcomm Technologies Inc SM6125 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SM6125 platform. - -config PINCTRL_SM6350 - tristate "Qualcomm Technologies Inc SM6350 pin controller driver" - depends on GPIOLIB && OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SM6350 platform. - -config PINCTRL_SM6375 - tristate "Qualcomm Technologies Inc SM6375 pin controller driver" - depends on GPIOLIB && OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SM6375 platform. - -config PINCTRL_SDX65 - tristate "Qualcomm Technologies Inc SDX65 pin controller driver" - depends on GPIOLIB && OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SDX65 platform. - -config PINCTRL_SM7150 - tristate "Qualcomm Technologies Inc SM7150 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SM7150 platform. - -config PINCTRL_SM8150 - tristate "Qualcomm Technologies Inc SM8150 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SM8150 platform. - -config PINCTRL_SM8250 - tristate "Qualcomm Technologies Inc SM8250 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SM8250 platform. - config PINCTRL_SM8250_LPASS_LPI tristate "Qualcomm Technologies Inc SM8250 LPASS LPI pin controller driver" - depends on GPIOLIB depends on ARM64 || COMPILE_TEST depends on PINCTRL_LPASS_LPI help @@ -468,28 +77,8 @@ config PINCTRL_SM8250_LPASS_LPI Qualcomm Technologies Inc LPASS (Low Power Audio SubSystem) LPI (Low Power Island) found on the Qualcomm Technologies Inc SM8250 platform. -config PINCTRL_SM8350 - tristate "Qualcomm Technologies Inc SM8350 pin controller driver" - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SM8350 platform. - -config PINCTRL_SM8450 - tristate "Qualcomm Technologies Inc SM8450 pin controller driver" - depends on GPIOLIB && OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SM8450 platform. - config PINCTRL_SM8450_LPASS_LPI tristate "Qualcomm Technologies Inc SM8450 LPASS LPI pin controller driver" - depends on GPIOLIB depends on ARM64 || COMPILE_TEST depends on PINCTRL_LPASS_LPI help @@ -499,7 +88,6 @@ config PINCTRL_SM8450_LPASS_LPI config PINCTRL_SC8280XP_LPASS_LPI tristate "Qualcomm Technologies Inc SC8280XP LPASS LPI pin controller driver" - depends on GPIOLIB depends on ARM64 || COMPILE_TEST depends on PINCTRL_LPASS_LPI help @@ -507,19 +95,8 @@ config PINCTRL_SC8280XP_LPASS_LPI Qualcomm Technologies Inc LPASS (Low Power Audio SubSystem) LPI (Low Power Island) found on the Qualcomm Technologies Inc SC8280XP platform. -config PINCTRL_SM8550 - tristate "Qualcomm Technologies Inc SM8550 pin controller driver" - depends on GPIOLIB - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SM8550 platform. - config PINCTRL_SM8550_LPASS_LPI tristate "Qualcomm Technologies Inc SM8550 LPASS LPI pin controller driver" - depends on GPIOLIB depends on ARM64 || COMPILE_TEST depends on PINCTRL_LPASS_LPI help @@ -528,16 +105,4 @@ config PINCTRL_SM8550_LPASS_LPI (Low Power Island) found on the Qualcomm Technologies Inc SM8550 platform. -config PINCTRL_LPASS_LPI - tristate "Qualcomm Technologies Inc LPASS LPI pin controller driver" - select PINMUX - select PINCONF - select GENERIC_PINCONF - select GENERIC_PINCTRL_GROUPS - depends on GPIOLIB - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc LPASS (Low Power Audio SubSystem) LPI - (Low Power Island) found on the Qualcomm Technologies Inc SoCs. - endif diff --git a/drivers/pinctrl/qcom/Kconfig.msm b/drivers/pinctrl/qcom/Kconfig.msm new file mode 100644 index 000000000000..01dd7b134354 --- /dev/null +++ b/drivers/pinctrl/qcom/Kconfig.msm @@ -0,0 +1,369 @@ +# SPDX-License-Identifier: GPL-2.0-only +if PINCTRL_MSM + +config PINCTRL_APQ8064 + tristate "Qualcomm APQ8064 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm APQ8064 platform. + +config PINCTRL_APQ8084 + tristate "Qualcomm APQ8084 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm APQ8084 platform. + +config PINCTRL_IPQ4019 + tristate "Qualcomm IPQ4019 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm IPQ4019 platform. + +config PINCTRL_IPQ5018 + tristate "Qualcomm Technologies, Inc. IPQ5018 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for + the Qualcomm Technologies Inc. TLMM block found on the + Qualcomm Technologies Inc. IPQ5018 platform. Select this for + IPQ5018. + +config PINCTRL_IPQ8064 + tristate "Qualcomm IPQ8064 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm IPQ8064 platform. + +config PINCTRL_IPQ5332 + tristate "Qualcomm Technologies Inc IPQ5332 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc IPQ5332 platform. + +config PINCTRL_IPQ8074 + tristate "Qualcomm Technologies, Inc. IPQ8074 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for + the Qualcomm Technologies Inc. TLMM block found on the + Qualcomm Technologies Inc. IPQ8074 platform. Select this for + IPQ8074. + +config PINCTRL_IPQ6018 + tristate "Qualcomm Technologies, Inc. IPQ6018 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for + the Qualcomm Technologies Inc. TLMM block found on the + Qualcomm Technologies Inc. IPQ6018 platform. Select this for + IPQ6018. + +config PINCTRL_IPQ9574 + tristate "Qualcomm Technologies, Inc. IPQ9574 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for + the Qualcomm Technologies Inc. TLMM block found on the + Qualcomm Technologies Inc. IPQ9574 platform. Select this for + IPQ9574. + +config PINCTRL_MSM8226 + tristate "Qualcomm 8226 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc MSM8226 platform. + +config PINCTRL_MSM8660 + tristate "Qualcomm 8660 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm 8660 platform. + +config PINCTRL_MSM8960 + tristate "Qualcomm 8960 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm 8960 platform. + +config PINCTRL_MDM9607 + tristate "Qualcomm 9607 pin controller driver" + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm 9607 platform. + +config PINCTRL_MDM9615 + tristate "Qualcomm 9615 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm 9615 platform. + +config PINCTRL_MSM8X74 + tristate "Qualcomm 8x74 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm 8974 platform. + +config PINCTRL_MSM8909 + tristate "Qualcomm 8909 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found on the Qualcomm MSM8909 platform. + +config PINCTRL_MSM8916 + tristate "Qualcomm 8916 pin controller driver" + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found on the Qualcomm 8916 platform. + +config PINCTRL_MSM8953 + tristate "Qualcomm 8953 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found on the Qualcomm MSM8953 platform. + The Qualcomm APQ8053, SDM450, SDM632 platforms are also + supported by this driver. + +config PINCTRL_MSM8976 + tristate "Qualcomm 8976 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found on the Qualcomm MSM8976 platform. + The Qualcomm MSM8956, APQ8056, APQ8076 platforms are also + supported by this driver. + +config PINCTRL_MSM8994 + tristate "Qualcomm 8994 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm 8994 platform. The + Qualcomm 8992 platform is also supported by this driver. + +config PINCTRL_MSM8996 + tristate "Qualcomm MSM8996 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm MSM8996 platform. + +config PINCTRL_MSM8998 + tristate "Qualcomm MSM8998 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm MSM8998 platform. + +config PINCTRL_QCM2290 + tristate "Qualcomm QCM2290 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + TLMM block found in the Qualcomm QCM2290 platform. + +config PINCTRL_QCS404 + tristate "Qualcomm QCS404 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + TLMM block found in the Qualcomm QCS404 platform. + +config PINCTRL_QDF2XXX + tristate "Qualcomm Technologies QDF2xxx pin controller driver" + depends on ACPI + help + This is the GPIO driver for the TLMM block found on the + Qualcomm Technologies QDF2xxx SOCs. + +config PINCTRL_QDU1000 + tristate "Qualcomm Technologies Inc QDU1000/QRU1000 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf, and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc QDU1000 and QRU1000 platforms. + +config PINCTRL_SA8775P + tristate "Qualcomm Technologies Inc SA8775P pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux and pinconf driver for the Qualcomm + TLMM block found on the Qualcomm SA8775P platforms. + +config PINCTRL_SC7180 + tristate "Qualcomm Technologies Inc SC7180 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SC7180 platform. + +config PINCTRL_SC7280 + tristate "Qualcomm Technologies Inc SC7280 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SC7280 platform. + +config PINCTRL_SC8180X + tristate "Qualcomm Technologies Inc SC8180x pin controller driver" + depends on (OF || ACPI) + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SC8180x platform. + +config PINCTRL_SC8280XP + tristate "Qualcomm Technologies Inc SC8280xp pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SC8280xp platform. + +config PINCTRL_SDM660 + tristate "Qualcomm Technologies Inc SDM660 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SDM660 platform. + +config PINCTRL_SDM670 + tristate "Qualcomm Technologies Inc SDM670 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SDM670 platform. + +config PINCTRL_SDM845 + tristate "Qualcomm Technologies Inc SDM845 pin controller driver" + depends on (OF || ACPI) + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SDM845 platform. + +config PINCTRL_SDX55 + tristate "Qualcomm Technologies Inc SDX55 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SDX55 platform. + +config PINCTRL_SDX65 + tristate "Qualcomm Technologies Inc SDX65 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SDX65 platform. + +config PINCTRL_SDX75 + tristate "Qualcomm Technologies Inc SDX75 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SDX75 platform. + +config PINCTRL_SM6115 + tristate "Qualcomm Technologies Inc SM6115,SM4250 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SM6115 and SM4250 platforms. + +config PINCTRL_SM6125 + tristate "Qualcomm Technologies Inc SM6125 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SM6125 platform. + +config PINCTRL_SM6350 + tristate "Qualcomm Technologies Inc SM6350 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SM6350 platform. + +config PINCTRL_SM6375 + tristate "Qualcomm Technologies Inc SM6375 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SM6375 platform. + +config PINCTRL_SM7150 + tristate "Qualcomm Technologies Inc SM7150 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SM7150 platform. + +config PINCTRL_SM8150 + tristate "Qualcomm Technologies Inc SM8150 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SM8150 platform. + +config PINCTRL_SM8250 + tristate "Qualcomm Technologies Inc SM8250 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SM8250 platform. + +config PINCTRL_SM8350 + tristate "Qualcomm Technologies Inc SM8350 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SM8350 platform. + +config PINCTRL_SM8450 + tristate "Qualcomm Technologies Inc SM8450 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SM8450 platform. + +config PINCTRL_SM8550 + tristate "Qualcomm Technologies Inc SM8550 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SM8550 platform. + +endif diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile index 521b021b74ba..426ddbf35f32 100644 --- a/drivers/pinctrl/qcom/Makefile +++ b/drivers/pinctrl/qcom/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_PINCTRL_MSM) += pinctrl-msm.o obj-$(CONFIG_PINCTRL_APQ8064) += pinctrl-apq8064.o obj-$(CONFIG_PINCTRL_APQ8084) += pinctrl-apq8084.o obj-$(CONFIG_PINCTRL_IPQ4019) += pinctrl-ipq4019.o +obj-$(CONFIG_PINCTRL_IPQ5018) += pinctrl-ipq5018.o obj-$(CONFIG_PINCTRL_IPQ8064) += pinctrl-ipq8064.o obj-$(CONFIG_PINCTRL_IPQ5332) += pinctrl-ipq5332.o obj-$(CONFIG_PINCTRL_IPQ8074) += pinctrl-ipq8074.o @@ -40,11 +41,12 @@ obj-$(CONFIG_PINCTRL_SDM660) += pinctrl-sdm660.o obj-$(CONFIG_PINCTRL_SDM670) += pinctrl-sdm670.o obj-$(CONFIG_PINCTRL_SDM845) += pinctrl-sdm845.o obj-$(CONFIG_PINCTRL_SDX55) += pinctrl-sdx55.o +obj-$(CONFIG_PINCTRL_SDX65) += pinctrl-sdx65.o +obj-$(CONFIG_PINCTRL_SDX75) += pinctrl-sdx75.o obj-$(CONFIG_PINCTRL_SM6115) += pinctrl-sm6115.o obj-$(CONFIG_PINCTRL_SM6125) += pinctrl-sm6125.o obj-$(CONFIG_PINCTRL_SM6350) += pinctrl-sm6350.o obj-$(CONFIG_PINCTRL_SM6375) += pinctrl-sm6375.o -obj-$(CONFIG_PINCTRL_SDX65) += pinctrl-sdx65.o obj-$(CONFIG_PINCTRL_SM7150) += pinctrl-sm7150.o obj-$(CONFIG_PINCTRL_SM8150) += pinctrl-sm8150.o obj-$(CONFIG_PINCTRL_SM8250) += pinctrl-sm8250.o diff --git a/drivers/pinctrl/qcom/pinctrl-apq8064.c b/drivers/pinctrl/qcom/pinctrl-apq8064.c index d40ad4ea3819..20c3b9025044 100644 --- a/drivers/pinctrl/qcom/pinctrl-apq8064.c +++ b/drivers/pinctrl/qcom/pinctrl-apq8064.c @@ -6,7 +6,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" @@ -209,18 +208,11 @@ static const unsigned int sdc3_clk_pins[] = { 93 }; static const unsigned int sdc3_cmd_pins[] = { 94 }; static const unsigned int sdc3_data_pins[] = { 95 }; -#define FUNCTION(fname) \ - [APQ_MUX_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ APQ_MUX_gpio, \ APQ_MUX_##f1, \ @@ -259,9 +251,9 @@ static const unsigned int sdc3_data_pins[] = { 95 }; #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -464,48 +456,48 @@ static const char * const usb2_hsic_groups[] = { "gpio88", "gpio89" }; -static const struct msm_function apq8064_functions[] = { - FUNCTION(cam_mclk), - FUNCTION(codec_mic_i2s), - FUNCTION(codec_spkr_i2s), - FUNCTION(gp_clk_0a), - FUNCTION(gp_clk_0b), - FUNCTION(gp_clk_1a), - FUNCTION(gp_clk_1b), - FUNCTION(gp_clk_2a), - FUNCTION(gp_clk_2b), - FUNCTION(gpio), - FUNCTION(gsbi1), - FUNCTION(gsbi2), - FUNCTION(gsbi3), - FUNCTION(gsbi4), - FUNCTION(gsbi4_cam_i2c), - FUNCTION(gsbi5), - FUNCTION(gsbi5_spi_cs1), - FUNCTION(gsbi5_spi_cs2), - FUNCTION(gsbi5_spi_cs3), - FUNCTION(gsbi6), - FUNCTION(gsbi6_spi_cs1), - FUNCTION(gsbi6_spi_cs2), - FUNCTION(gsbi6_spi_cs3), - FUNCTION(gsbi7), - FUNCTION(gsbi7_spi_cs1), - FUNCTION(gsbi7_spi_cs2), - FUNCTION(gsbi7_spi_cs3), - FUNCTION(gsbi_cam_i2c), - FUNCTION(hdmi), - FUNCTION(mi2s), - FUNCTION(riva_bt), - FUNCTION(riva_fm), - FUNCTION(riva_wlan), - FUNCTION(sdc2), - FUNCTION(sdc4), - FUNCTION(slimbus), - FUNCTION(spkr_i2s), - FUNCTION(tsif1), - FUNCTION(tsif2), - FUNCTION(usb2_hsic), - FUNCTION(ps_hold), +static const struct pinfunction apq8064_functions[] = { + APQ_PIN_FUNCTION(cam_mclk), + APQ_PIN_FUNCTION(codec_mic_i2s), + APQ_PIN_FUNCTION(codec_spkr_i2s), + APQ_PIN_FUNCTION(gp_clk_0a), + APQ_PIN_FUNCTION(gp_clk_0b), + APQ_PIN_FUNCTION(gp_clk_1a), + APQ_PIN_FUNCTION(gp_clk_1b), + APQ_PIN_FUNCTION(gp_clk_2a), + APQ_PIN_FUNCTION(gp_clk_2b), + APQ_PIN_FUNCTION(gpio), + APQ_PIN_FUNCTION(gsbi1), + APQ_PIN_FUNCTION(gsbi2), + APQ_PIN_FUNCTION(gsbi3), + APQ_PIN_FUNCTION(gsbi4), + APQ_PIN_FUNCTION(gsbi4_cam_i2c), + APQ_PIN_FUNCTION(gsbi5), + APQ_PIN_FUNCTION(gsbi5_spi_cs1), + APQ_PIN_FUNCTION(gsbi5_spi_cs2), + APQ_PIN_FUNCTION(gsbi5_spi_cs3), + APQ_PIN_FUNCTION(gsbi6), + APQ_PIN_FUNCTION(gsbi6_spi_cs1), + APQ_PIN_FUNCTION(gsbi6_spi_cs2), + APQ_PIN_FUNCTION(gsbi6_spi_cs3), + APQ_PIN_FUNCTION(gsbi7), + APQ_PIN_FUNCTION(gsbi7_spi_cs1), + APQ_PIN_FUNCTION(gsbi7_spi_cs2), + APQ_PIN_FUNCTION(gsbi7_spi_cs3), + APQ_PIN_FUNCTION(gsbi_cam_i2c), + APQ_PIN_FUNCTION(hdmi), + APQ_PIN_FUNCTION(mi2s), + APQ_PIN_FUNCTION(riva_bt), + APQ_PIN_FUNCTION(riva_fm), + APQ_PIN_FUNCTION(riva_wlan), + APQ_PIN_FUNCTION(sdc2), + APQ_PIN_FUNCTION(sdc4), + APQ_PIN_FUNCTION(slimbus), + APQ_PIN_FUNCTION(spkr_i2s), + APQ_PIN_FUNCTION(tsif1), + APQ_PIN_FUNCTION(tsif2), + APQ_PIN_FUNCTION(usb2_hsic), + APQ_PIN_FUNCTION(ps_hold), }; static const struct msm_pingroup apq8064_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-apq8084.c b/drivers/pinctrl/qcom/pinctrl-apq8084.c index f83153a1d622..3fc0a40762b6 100644 --- a/drivers/pinctrl/qcom/pinctrl-apq8084.c +++ b/drivers/pinctrl/qcom/pinctrl-apq8084.c @@ -6,7 +6,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" @@ -324,18 +323,11 @@ static const unsigned int sdc2_clk_pins[] = { 150 }; static const unsigned int sdc2_cmd_pins[] = { 151 }; static const unsigned int sdc2_data_pins[] = { 152 }; -#define FUNCTION(fname) \ - [APQ_MUX_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ APQ_MUX_gpio, \ APQ_MUX_##f1, \ @@ -371,9 +363,9 @@ static const unsigned int sdc2_data_pins[] = { 152 }; #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -906,128 +898,128 @@ static const char * const uim_groups[] = { static const char * const uim_batt_alarm_groups[] = { "gpio102" }; -static const struct msm_function apq8084_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(audio_ref), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_i2c5), - FUNCTION(blsp_i2c6), - FUNCTION(blsp_i2c7), - FUNCTION(blsp_i2c8), - FUNCTION(blsp_i2c9), - FUNCTION(blsp_i2c10), - FUNCTION(blsp_i2c11), - FUNCTION(blsp_i2c12), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi1_cs1), - FUNCTION(blsp_spi1_cs2), - FUNCTION(blsp_spi1_cs3), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi3_cs1), - FUNCTION(blsp_spi3_cs2), - FUNCTION(blsp_spi3_cs3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_spi6), - FUNCTION(blsp_spi7), - FUNCTION(blsp_spi8), - FUNCTION(blsp_spi9), - FUNCTION(blsp_spi10), - FUNCTION(blsp_spi10_cs1), - FUNCTION(blsp_spi10_cs2), - FUNCTION(blsp_spi10_cs3), - FUNCTION(blsp_spi11), - FUNCTION(blsp_spi12), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uart3), - FUNCTION(blsp_uart4), - FUNCTION(blsp_uart5), - FUNCTION(blsp_uart6), - FUNCTION(blsp_uart7), - FUNCTION(blsp_uart8), - FUNCTION(blsp_uart9), - FUNCTION(blsp_uart10), - FUNCTION(blsp_uart11), - FUNCTION(blsp_uart12), - FUNCTION(blsp_uim1), - FUNCTION(blsp_uim2), - FUNCTION(blsp_uim3), - FUNCTION(blsp_uim4), - FUNCTION(blsp_uim5), - FUNCTION(blsp_uim6), - FUNCTION(blsp_uim7), - FUNCTION(blsp_uim8), - FUNCTION(blsp_uim9), - FUNCTION(blsp_uim10), - FUNCTION(blsp_uim11), - FUNCTION(blsp_uim12), - FUNCTION(cam_mclk0), - FUNCTION(cam_mclk1), - FUNCTION(cam_mclk2), - FUNCTION(cam_mclk3), - FUNCTION(cci_async), - FUNCTION(cci_async_in0), - FUNCTION(cci_i2c0), - FUNCTION(cci_i2c1), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(edp_hpd), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gcc_obt), - FUNCTION(gcc_vtt), - FUNCTION(gp_mn), - FUNCTION(gp_pdm0), - FUNCTION(gp_pdm1), - FUNCTION(gp_pdm2), - FUNCTION(gp0_clk), - FUNCTION(gp1_clk), - FUNCTION(gpio), - FUNCTION(hdmi_cec), - FUNCTION(hdmi_ddc), - FUNCTION(hdmi_dtest), - FUNCTION(hdmi_hpd), - FUNCTION(hdmi_rcv), - FUNCTION(hsic), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(mdp_vsync), - FUNCTION(pci_e0), - FUNCTION(pci_e0_n), - FUNCTION(pci_e0_rst), - FUNCTION(pci_e1), - FUNCTION(pci_e1_rst), - FUNCTION(pci_e1_rst_n), - FUNCTION(pci_e1_clkreq_n), - FUNCTION(pri_mi2s), - FUNCTION(qua_mi2s), - FUNCTION(sata_act), - FUNCTION(sata_devsleep), - FUNCTION(sata_devsleep_n), - FUNCTION(sd_write), - FUNCTION(sdc_emmc_mode), - FUNCTION(sdc3), - FUNCTION(sdc4), - FUNCTION(sec_mi2s), - FUNCTION(slimbus), - FUNCTION(spdif_tx), - FUNCTION(spkr_i2s), - FUNCTION(spkr_i2s_ws), - FUNCTION(spss_geni), - FUNCTION(ter_mi2s), - FUNCTION(tsif1), - FUNCTION(tsif2), - FUNCTION(uim), - FUNCTION(uim_batt_alarm), +static const struct pinfunction apq8084_functions[] = { + APQ_PIN_FUNCTION(adsp_ext), + APQ_PIN_FUNCTION(audio_ref), + APQ_PIN_FUNCTION(blsp_i2c1), + APQ_PIN_FUNCTION(blsp_i2c2), + APQ_PIN_FUNCTION(blsp_i2c3), + APQ_PIN_FUNCTION(blsp_i2c4), + APQ_PIN_FUNCTION(blsp_i2c5), + APQ_PIN_FUNCTION(blsp_i2c6), + APQ_PIN_FUNCTION(blsp_i2c7), + APQ_PIN_FUNCTION(blsp_i2c8), + APQ_PIN_FUNCTION(blsp_i2c9), + APQ_PIN_FUNCTION(blsp_i2c10), + APQ_PIN_FUNCTION(blsp_i2c11), + APQ_PIN_FUNCTION(blsp_i2c12), + APQ_PIN_FUNCTION(blsp_spi1), + APQ_PIN_FUNCTION(blsp_spi1_cs1), + APQ_PIN_FUNCTION(blsp_spi1_cs2), + APQ_PIN_FUNCTION(blsp_spi1_cs3), + APQ_PIN_FUNCTION(blsp_spi2), + APQ_PIN_FUNCTION(blsp_spi3), + APQ_PIN_FUNCTION(blsp_spi3_cs1), + APQ_PIN_FUNCTION(blsp_spi3_cs2), + APQ_PIN_FUNCTION(blsp_spi3_cs3), + APQ_PIN_FUNCTION(blsp_spi4), + APQ_PIN_FUNCTION(blsp_spi5), + APQ_PIN_FUNCTION(blsp_spi6), + APQ_PIN_FUNCTION(blsp_spi7), + APQ_PIN_FUNCTION(blsp_spi8), + APQ_PIN_FUNCTION(blsp_spi9), + APQ_PIN_FUNCTION(blsp_spi10), + APQ_PIN_FUNCTION(blsp_spi10_cs1), + APQ_PIN_FUNCTION(blsp_spi10_cs2), + APQ_PIN_FUNCTION(blsp_spi10_cs3), + APQ_PIN_FUNCTION(blsp_spi11), + APQ_PIN_FUNCTION(blsp_spi12), + APQ_PIN_FUNCTION(blsp_uart1), + APQ_PIN_FUNCTION(blsp_uart2), + APQ_PIN_FUNCTION(blsp_uart3), + APQ_PIN_FUNCTION(blsp_uart4), + APQ_PIN_FUNCTION(blsp_uart5), + APQ_PIN_FUNCTION(blsp_uart6), + APQ_PIN_FUNCTION(blsp_uart7), + APQ_PIN_FUNCTION(blsp_uart8), + APQ_PIN_FUNCTION(blsp_uart9), + APQ_PIN_FUNCTION(blsp_uart10), + APQ_PIN_FUNCTION(blsp_uart11), + APQ_PIN_FUNCTION(blsp_uart12), + APQ_PIN_FUNCTION(blsp_uim1), + APQ_PIN_FUNCTION(blsp_uim2), + APQ_PIN_FUNCTION(blsp_uim3), + APQ_PIN_FUNCTION(blsp_uim4), + APQ_PIN_FUNCTION(blsp_uim5), + APQ_PIN_FUNCTION(blsp_uim6), + APQ_PIN_FUNCTION(blsp_uim7), + APQ_PIN_FUNCTION(blsp_uim8), + APQ_PIN_FUNCTION(blsp_uim9), + APQ_PIN_FUNCTION(blsp_uim10), + APQ_PIN_FUNCTION(blsp_uim11), + APQ_PIN_FUNCTION(blsp_uim12), + APQ_PIN_FUNCTION(cam_mclk0), + APQ_PIN_FUNCTION(cam_mclk1), + APQ_PIN_FUNCTION(cam_mclk2), + APQ_PIN_FUNCTION(cam_mclk3), + APQ_PIN_FUNCTION(cci_async), + APQ_PIN_FUNCTION(cci_async_in0), + APQ_PIN_FUNCTION(cci_i2c0), + APQ_PIN_FUNCTION(cci_i2c1), + APQ_PIN_FUNCTION(cci_timer0), + APQ_PIN_FUNCTION(cci_timer1), + APQ_PIN_FUNCTION(cci_timer2), + APQ_PIN_FUNCTION(cci_timer3), + APQ_PIN_FUNCTION(cci_timer4), + APQ_PIN_FUNCTION(edp_hpd), + APQ_PIN_FUNCTION(gcc_gp1), + APQ_PIN_FUNCTION(gcc_gp2), + APQ_PIN_FUNCTION(gcc_gp3), + APQ_PIN_FUNCTION(gcc_obt), + APQ_PIN_FUNCTION(gcc_vtt), + APQ_PIN_FUNCTION(gp_mn), + APQ_PIN_FUNCTION(gp_pdm0), + APQ_PIN_FUNCTION(gp_pdm1), + APQ_PIN_FUNCTION(gp_pdm2), + APQ_PIN_FUNCTION(gp0_clk), + APQ_PIN_FUNCTION(gp1_clk), + APQ_PIN_FUNCTION(gpio), + APQ_PIN_FUNCTION(hdmi_cec), + APQ_PIN_FUNCTION(hdmi_ddc), + APQ_PIN_FUNCTION(hdmi_dtest), + APQ_PIN_FUNCTION(hdmi_hpd), + APQ_PIN_FUNCTION(hdmi_rcv), + APQ_PIN_FUNCTION(hsic), + APQ_PIN_FUNCTION(ldo_en), + APQ_PIN_FUNCTION(ldo_update), + APQ_PIN_FUNCTION(mdp_vsync), + APQ_PIN_FUNCTION(pci_e0), + APQ_PIN_FUNCTION(pci_e0_n), + APQ_PIN_FUNCTION(pci_e0_rst), + APQ_PIN_FUNCTION(pci_e1), + APQ_PIN_FUNCTION(pci_e1_rst), + APQ_PIN_FUNCTION(pci_e1_rst_n), + APQ_PIN_FUNCTION(pci_e1_clkreq_n), + APQ_PIN_FUNCTION(pri_mi2s), + APQ_PIN_FUNCTION(qua_mi2s), + APQ_PIN_FUNCTION(sata_act), + APQ_PIN_FUNCTION(sata_devsleep), + APQ_PIN_FUNCTION(sata_devsleep_n), + APQ_PIN_FUNCTION(sd_write), + APQ_PIN_FUNCTION(sdc_emmc_mode), + APQ_PIN_FUNCTION(sdc3), + APQ_PIN_FUNCTION(sdc4), + APQ_PIN_FUNCTION(sec_mi2s), + APQ_PIN_FUNCTION(slimbus), + APQ_PIN_FUNCTION(spdif_tx), + APQ_PIN_FUNCTION(spkr_i2s), + APQ_PIN_FUNCTION(spkr_i2s_ws), + APQ_PIN_FUNCTION(spss_geni), + APQ_PIN_FUNCTION(ter_mi2s), + APQ_PIN_FUNCTION(tsif1), + APQ_PIN_FUNCTION(tsif2), + APQ_PIN_FUNCTION(uim), + APQ_PIN_FUNCTION(uim_batt_alarm), }; static const struct msm_pingroup apq8084_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-ipq4019.c b/drivers/pinctrl/qcom/pinctrl-ipq4019.c index 63915cb210ff..1f7944dd829d 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq4019.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq4019.c @@ -6,7 +6,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" @@ -216,18 +215,11 @@ DECLARE_QCA_GPIO_PINS(97); DECLARE_QCA_GPIO_PINS(98); DECLARE_QCA_GPIO_PINS(99); -#define FUNCTION(fname) \ - [qca_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ qca_mux_gpio, /* gpio mode */ \ qca_mux_##f1, \ @@ -478,51 +470,51 @@ static const char * const wifi1_groups[] = { "gpio53", "gpio56", "gpio57", "gpio58", "gpio98", }; -static const struct msm_function ipq4019_functions[] = { - FUNCTION(aud_pin), - FUNCTION(audio_pwm), - FUNCTION(blsp_i2c0), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_spi0), - FUNCTION(blsp_spi1), - FUNCTION(blsp_uart0), - FUNCTION(blsp_uart1), - FUNCTION(chip_rst), - FUNCTION(gpio), - FUNCTION(i2s_rx), - FUNCTION(i2s_spdif_in), - FUNCTION(i2s_spdif_out), - FUNCTION(i2s_td), - FUNCTION(i2s_tx), - FUNCTION(jtag), - FUNCTION(led0), - FUNCTION(led1), - FUNCTION(led2), - FUNCTION(led3), - FUNCTION(led4), - FUNCTION(led5), - FUNCTION(led6), - FUNCTION(led7), - FUNCTION(led8), - FUNCTION(led9), - FUNCTION(led10), - FUNCTION(led11), - FUNCTION(mdc), - FUNCTION(mdio), - FUNCTION(pcie), - FUNCTION(pmu), - FUNCTION(prng_rosc), - FUNCTION(qpic), - FUNCTION(rgmii), - FUNCTION(rmii), - FUNCTION(sdio), - FUNCTION(smart0), - FUNCTION(smart1), - FUNCTION(smart2), - FUNCTION(smart3), - FUNCTION(tm), - FUNCTION(wifi0), - FUNCTION(wifi1), +static const struct pinfunction ipq4019_functions[] = { + QCA_PIN_FUNCTION(aud_pin), + QCA_PIN_FUNCTION(audio_pwm), + QCA_PIN_FUNCTION(blsp_i2c0), + QCA_PIN_FUNCTION(blsp_i2c1), + QCA_PIN_FUNCTION(blsp_spi0), + QCA_PIN_FUNCTION(blsp_spi1), + QCA_PIN_FUNCTION(blsp_uart0), + QCA_PIN_FUNCTION(blsp_uart1), + QCA_PIN_FUNCTION(chip_rst), + QCA_PIN_FUNCTION(gpio), + QCA_PIN_FUNCTION(i2s_rx), + QCA_PIN_FUNCTION(i2s_spdif_in), + QCA_PIN_FUNCTION(i2s_spdif_out), + QCA_PIN_FUNCTION(i2s_td), + QCA_PIN_FUNCTION(i2s_tx), + QCA_PIN_FUNCTION(jtag), + QCA_PIN_FUNCTION(led0), + QCA_PIN_FUNCTION(led1), + QCA_PIN_FUNCTION(led2), + QCA_PIN_FUNCTION(led3), + QCA_PIN_FUNCTION(led4), + QCA_PIN_FUNCTION(led5), + QCA_PIN_FUNCTION(led6), + QCA_PIN_FUNCTION(led7), + QCA_PIN_FUNCTION(led8), + QCA_PIN_FUNCTION(led9), + QCA_PIN_FUNCTION(led10), + QCA_PIN_FUNCTION(led11), + QCA_PIN_FUNCTION(mdc), + QCA_PIN_FUNCTION(mdio), + QCA_PIN_FUNCTION(pcie), + QCA_PIN_FUNCTION(pmu), + QCA_PIN_FUNCTION(prng_rosc), + QCA_PIN_FUNCTION(qpic), + QCA_PIN_FUNCTION(rgmii), + QCA_PIN_FUNCTION(rmii), + QCA_PIN_FUNCTION(sdio), + QCA_PIN_FUNCTION(smart0), + QCA_PIN_FUNCTION(smart1), + QCA_PIN_FUNCTION(smart2), + QCA_PIN_FUNCTION(smart3), + QCA_PIN_FUNCTION(tm), + QCA_PIN_FUNCTION(wifi0), + QCA_PIN_FUNCTION(wifi1), }; static const struct msm_pingroup ipq4019_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-ipq5018.c b/drivers/pinctrl/qcom/pinctrl-ipq5018.c new file mode 100644 index 000000000000..ed58f750f1eb --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-ipq5018.c @@ -0,0 +1,783 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2021, 2023 The Linux Foundation. All rights reserved. + */ + +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/platform_device.h> + +#include "pinctrl-msm.h" + +#define REG_SIZE 0x1000 +#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ + { \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ + .funcs = (int[]){ \ + msm_mux_gpio, /* gpio mode */ \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7, \ + msm_mux_##f8, \ + msm_mux_##f9 \ + }, \ + .nfuncs = 10, \ + .ctl_reg = REG_SIZE * id, \ + .io_reg = 0x4 + REG_SIZE * id, \ + .intr_cfg_reg = 0x8 + REG_SIZE * id, \ + .intr_status_reg = 0xc + REG_SIZE * id, \ + .intr_target_reg = 0x8 + REG_SIZE * id, \ + .mux_bit = 2, \ + .pull_bit = 0, \ + .drv_bit = 6, \ + .oe_bit = 9, \ + .in_bit = 0, \ + .out_bit = 1, \ + .intr_enable_bit = 0, \ + .intr_status_bit = 0, \ + .intr_target_bit = 5, \ + .intr_target_kpss_val = 3, \ + .intr_raw_status_bit = 4, \ + .intr_polarity_bit = 1, \ + .intr_detection_bit = 2, \ + .intr_detection_width = 2, \ + } + +static const struct pinctrl_pin_desc ipq5018_pins[] = { + PINCTRL_PIN(0, "GPIO_0"), + PINCTRL_PIN(1, "GPIO_1"), + PINCTRL_PIN(2, "GPIO_2"), + PINCTRL_PIN(3, "GPIO_3"), + PINCTRL_PIN(4, "GPIO_4"), + PINCTRL_PIN(5, "GPIO_5"), + PINCTRL_PIN(6, "GPIO_6"), + PINCTRL_PIN(7, "GPIO_7"), + PINCTRL_PIN(8, "GPIO_8"), + PINCTRL_PIN(9, "GPIO_9"), + PINCTRL_PIN(10, "GPIO_10"), + PINCTRL_PIN(11, "GPIO_11"), + PINCTRL_PIN(12, "GPIO_12"), + PINCTRL_PIN(13, "GPIO_13"), + PINCTRL_PIN(14, "GPIO_14"), + PINCTRL_PIN(15, "GPIO_15"), + PINCTRL_PIN(16, "GPIO_16"), + PINCTRL_PIN(17, "GPIO_17"), + PINCTRL_PIN(18, "GPIO_18"), + PINCTRL_PIN(19, "GPIO_19"), + PINCTRL_PIN(20, "GPIO_20"), + PINCTRL_PIN(21, "GPIO_21"), + PINCTRL_PIN(22, "GPIO_22"), + PINCTRL_PIN(23, "GPIO_23"), + PINCTRL_PIN(24, "GPIO_24"), + PINCTRL_PIN(25, "GPIO_25"), + PINCTRL_PIN(26, "GPIO_26"), + PINCTRL_PIN(27, "GPIO_27"), + PINCTRL_PIN(28, "GPIO_28"), + PINCTRL_PIN(29, "GPIO_29"), + PINCTRL_PIN(30, "GPIO_30"), + PINCTRL_PIN(31, "GPIO_31"), + PINCTRL_PIN(32, "GPIO_32"), + PINCTRL_PIN(33, "GPIO_33"), + PINCTRL_PIN(34, "GPIO_34"), + PINCTRL_PIN(35, "GPIO_35"), + PINCTRL_PIN(36, "GPIO_36"), + PINCTRL_PIN(37, "GPIO_37"), + PINCTRL_PIN(38, "GPIO_38"), + PINCTRL_PIN(39, "GPIO_39"), + PINCTRL_PIN(40, "GPIO_40"), + PINCTRL_PIN(41, "GPIO_41"), + PINCTRL_PIN(42, "GPIO_42"), + PINCTRL_PIN(43, "GPIO_43"), + PINCTRL_PIN(44, "GPIO_44"), + PINCTRL_PIN(45, "GPIO_45"), + PINCTRL_PIN(46, "GPIO_46"), +}; + +#define DECLARE_MSM_GPIO_PINS(pin) \ + static const unsigned int gpio##pin##_pins[] = { pin } +DECLARE_MSM_GPIO_PINS(0); +DECLARE_MSM_GPIO_PINS(1); +DECLARE_MSM_GPIO_PINS(2); +DECLARE_MSM_GPIO_PINS(3); +DECLARE_MSM_GPIO_PINS(4); +DECLARE_MSM_GPIO_PINS(5); +DECLARE_MSM_GPIO_PINS(6); +DECLARE_MSM_GPIO_PINS(7); +DECLARE_MSM_GPIO_PINS(8); +DECLARE_MSM_GPIO_PINS(9); +DECLARE_MSM_GPIO_PINS(10); +DECLARE_MSM_GPIO_PINS(11); +DECLARE_MSM_GPIO_PINS(12); +DECLARE_MSM_GPIO_PINS(13); +DECLARE_MSM_GPIO_PINS(14); +DECLARE_MSM_GPIO_PINS(15); +DECLARE_MSM_GPIO_PINS(16); +DECLARE_MSM_GPIO_PINS(17); +DECLARE_MSM_GPIO_PINS(18); +DECLARE_MSM_GPIO_PINS(19); +DECLARE_MSM_GPIO_PINS(20); +DECLARE_MSM_GPIO_PINS(21); +DECLARE_MSM_GPIO_PINS(22); +DECLARE_MSM_GPIO_PINS(23); +DECLARE_MSM_GPIO_PINS(24); +DECLARE_MSM_GPIO_PINS(25); +DECLARE_MSM_GPIO_PINS(26); +DECLARE_MSM_GPIO_PINS(27); +DECLARE_MSM_GPIO_PINS(28); +DECLARE_MSM_GPIO_PINS(29); +DECLARE_MSM_GPIO_PINS(30); +DECLARE_MSM_GPIO_PINS(31); +DECLARE_MSM_GPIO_PINS(32); +DECLARE_MSM_GPIO_PINS(33); +DECLARE_MSM_GPIO_PINS(34); +DECLARE_MSM_GPIO_PINS(35); +DECLARE_MSM_GPIO_PINS(36); +DECLARE_MSM_GPIO_PINS(37); +DECLARE_MSM_GPIO_PINS(38); +DECLARE_MSM_GPIO_PINS(39); +DECLARE_MSM_GPIO_PINS(40); +DECLARE_MSM_GPIO_PINS(41); +DECLARE_MSM_GPIO_PINS(42); +DECLARE_MSM_GPIO_PINS(43); +DECLARE_MSM_GPIO_PINS(44); +DECLARE_MSM_GPIO_PINS(45); +DECLARE_MSM_GPIO_PINS(46); + +enum ipq5018_functions { + msm_mux_atest_char, + msm_mux_audio_pdm0, + msm_mux_audio_pdm1, + msm_mux_audio_rxbclk, + msm_mux_audio_rxd, + msm_mux_audio_rxfsync, + msm_mux_audio_rxmclk, + msm_mux_audio_txbclk, + msm_mux_audio_txd, + msm_mux_audio_txfsync, + msm_mux_audio_txmclk, + msm_mux_blsp0_i2c, + msm_mux_blsp0_spi, + msm_mux_blsp0_uart0, + msm_mux_blsp0_uart1, + msm_mux_blsp1_i2c0, + msm_mux_blsp1_i2c1, + msm_mux_blsp1_spi0, + msm_mux_blsp1_spi1, + msm_mux_blsp1_uart0, + msm_mux_blsp1_uart1, + msm_mux_blsp1_uart2, + msm_mux_blsp2_i2c0, + msm_mux_blsp2_i2c1, + msm_mux_blsp2_spi, + msm_mux_blsp2_spi0, + msm_mux_blsp2_spi1, + msm_mux_btss, + msm_mux_burn0, + msm_mux_burn1, + msm_mux_cri_trng, + msm_mux_cri_trng0, + msm_mux_cri_trng1, + msm_mux_cxc_clk, + msm_mux_cxc_data, + msm_mux_dbg_out, + msm_mux_eud_gpio, + msm_mux_gcc_plltest, + msm_mux_gcc_tlmm, + msm_mux_gpio, + msm_mux_led0, + msm_mux_led2, + msm_mux_mac0, + msm_mux_mac1, + msm_mux_mdc, + msm_mux_mdio, + msm_mux_pcie0_clk, + msm_mux_pcie0_wake, + msm_mux_pcie1_clk, + msm_mux_pcie1_wake, + msm_mux_pll_test, + msm_mux_prng_rosc, + msm_mux_pwm0, + msm_mux_pwm1, + msm_mux_pwm2, + msm_mux_pwm3, + msm_mux_qdss_cti_trig_in_a0, + msm_mux_qdss_cti_trig_in_a1, + msm_mux_qdss_cti_trig_in_b0, + msm_mux_qdss_cti_trig_in_b1, + msm_mux_qdss_cti_trig_out_a0, + msm_mux_qdss_cti_trig_out_a1, + msm_mux_qdss_cti_trig_out_b0, + msm_mux_qdss_cti_trig_out_b1, + msm_mux_qdss_traceclk_a, + msm_mux_qdss_traceclk_b, + msm_mux_qdss_tracectl_a, + msm_mux_qdss_tracectl_b, + msm_mux_qdss_tracedata_a, + msm_mux_qdss_tracedata_b, + msm_mux_qspi_clk, + msm_mux_qspi_cs, + msm_mux_qspi_data, + msm_mux_reset_out, + msm_mux_sdc1_clk, + msm_mux_sdc1_cmd, + msm_mux_sdc1_data, + msm_mux_wci_txd, + msm_mux_wci_rxd, + msm_mux_wsa_swrm, + msm_mux_wsi_clk3, + msm_mux_wsi_data3, + msm_mux_wsis_reset, + msm_mux_xfem, + msm_mux__, +}; + +static const char * const atest_char_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", "gpio37", +}; + +static const char * const _groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", + "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", + "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21", + "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", + "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", + "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", + "gpio43", "gpio44", "gpio45", "gpio46", +}; + +static const char * const wci_txd_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", + "gpio42", "gpio43", "gpio44", "gpio45", +}; + +static const char * const wci_rxd_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", + "gpio42", "gpio43", "gpio44", "gpio45", +}; + +static const char * const xfem_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", + "gpio42", "gpio43", "gpio44", "gpio45", +}; + +static const char * const qdss_cti_trig_out_a0_groups[] = { + "gpio0", +}; + +static const char * const qdss_cti_trig_in_a0_groups[] = { + "gpio1", +}; + +static const char * const qdss_cti_trig_out_a1_groups[] = { + "gpio2", +}; + +static const char * const qdss_cti_trig_in_a1_groups[] = { + "gpio3", +}; + +static const char * const sdc1_data_groups[] = { + "gpio4", "gpio5", "gpio6", "gpio7", +}; + +static const char * const qspi_data_groups[] = { + "gpio4", + "gpio5", + "gpio6", + "gpio7", +}; + +static const char * const blsp1_spi1_groups[] = { + "gpio4", "gpio5", "gpio6", "gpio7", +}; + +static const char * const btss_groups[] = { + "gpio4", "gpio5", "gpio6", "gpio7", "gpio8", "gpio17", "gpio18", + "gpio19", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", +}; + +static const char * const dbg_out_groups[] = { + "gpio4", +}; + +static const char * const qdss_traceclk_a_groups[] = { + "gpio4", +}; + +static const char * const burn0_groups[] = { + "gpio4", +}; + +static const char * const cxc_clk_groups[] = { + "gpio5", +}; + +static const char * const blsp1_i2c1_groups[] = { + "gpio5", "gpio6", +}; + +static const char * const qdss_tracectl_a_groups[] = { + "gpio5", +}; + +static const char * const burn1_groups[] = { + "gpio5", +}; + +static const char * const cxc_data_groups[] = { + "gpio6", +}; + +static const char * const qdss_tracedata_a_groups[] = { + "gpio6", "gpio7", "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", + "gpio13", "gpio14", "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", + "gpio20", "gpio21", +}; + +static const char * const mac0_groups[] = { + "gpio7", +}; + +static const char * const sdc1_cmd_groups[] = { + "gpio8", +}; + +static const char * const qspi_cs_groups[] = { + "gpio8", +}; + +static const char * const mac1_groups[] = { + "gpio8", +}; + +static const char * const sdc1_clk_groups[] = { + "gpio9", +}; + +static const char * const qspi_clk_groups[] = { + "gpio9", +}; + +static const char * const blsp0_spi_groups[] = { + "gpio10", "gpio11", "gpio12", "gpio13", +}; + +static const char * const blsp1_uart0_groups[] = { + "gpio10", "gpio11", "gpio12", "gpio13", +}; + +static const char * const gcc_plltest_groups[] = { + "gpio10", "gpio12", +}; + +static const char * const gcc_tlmm_groups[] = { + "gpio11", +}; + +static const char * const blsp0_i2c_groups[] = { + "gpio12", "gpio13", +}; + +static const char * const pcie0_clk_groups[] = { + "gpio14", +}; + +static const char * const cri_trng0_groups[] = { + "gpio14", +}; + +static const char * const cri_trng1_groups[] = { + "gpio15", +}; + +static const char * const pcie0_wake_groups[] = { + "gpio16", +}; + +static const char * const cri_trng_groups[] = { + "gpio16", +}; + +static const char * const pcie1_clk_groups[] = { + "gpio17", +}; + +static const char * const prng_rosc_groups[] = { + "gpio17", +}; + +static const char * const blsp1_spi0_groups[] = { + "gpio18", "gpio19", "gpio20", "gpio21", +}; + +static const char * const pcie1_wake_groups[] = { + "gpio19", +}; + +static const char * const blsp1_i2c0_groups[] = { + "gpio19", "gpio20", +}; + +static const char * const blsp0_uart0_groups[] = { + "gpio20", "gpio21", +}; + +static const char * const pll_test_groups[] = { + "gpio22", +}; + +static const char * const eud_gpio_groups[] = { + "gpio22", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", +}; + +static const char * const audio_rxmclk_groups[] = { + "gpio23", "gpio23", +}; + +static const char * const audio_pdm0_groups[] = { + "gpio23", "gpio24", +}; + +static const char * const blsp2_spi1_groups[] = { + "gpio23", "gpio24", "gpio25", "gpio26", +}; + +static const char * const blsp1_uart2_groups[] = { + "gpio23", "gpio24", "gpio25", "gpio26", +}; + +static const char * const qdss_tracedata_b_groups[] = { + "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", "gpio29", + "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", "gpio36", + "gpio37", "gpio38", +}; + +static const char * const audio_rxbclk_groups[] = { + "gpio24", +}; + +static const char * const audio_rxfsync_groups[] = { + "gpio25", +}; + +static const char * const audio_pdm1_groups[] = { + "gpio25", "gpio26", +}; + +static const char * const blsp2_i2c1_groups[] = { + "gpio25", "gpio26", +}; + +static const char * const audio_rxd_groups[] = { + "gpio26", +}; + +static const char * const audio_txmclk_groups[] = { + "gpio27", "gpio27", +}; + +static const char * const wsa_swrm_groups[] = { + "gpio27", "gpio28", +}; + +static const char * const blsp2_spi_groups[] = { + "gpio27", +}; + +static const char * const audio_txbclk_groups[] = { + "gpio28", +}; + +static const char * const blsp0_uart1_groups[] = { + "gpio28", "gpio29", +}; + +static const char * const audio_txfsync_groups[] = { + "gpio29", +}; + +static const char * const audio_txd_groups[] = { + "gpio30", +}; + +static const char * const wsis_reset_groups[] = { + "gpio30", +}; + +static const char * const blsp2_spi0_groups[] = { + "gpio31", "gpio32", "gpio33", "gpio34", +}; + +static const char * const blsp1_uart1_groups[] = { + "gpio31", "gpio32", "gpio33", "gpio34", +}; + +static const char * const blsp2_i2c0_groups[] = { + "gpio33", "gpio34", +}; + +static const char * const mdc_groups[] = { + "gpio36", +}; + +static const char * const wsi_clk3_groups[] = { + "gpio36", +}; + +static const char * const mdio_groups[] = { + "gpio37", +}; + +static const char * const wsi_data3_groups[] = { + "gpio37", +}; + +static const char * const qdss_traceclk_b_groups[] = { + "gpio39", +}; + +static const char * const reset_out_groups[] = { + "gpio40", +}; + +static const char * const qdss_tracectl_b_groups[] = { + "gpio40", +}; + +static const char * const pwm0_groups[] = { + "gpio42", +}; + +static const char * const qdss_cti_trig_out_b0_groups[] = { + "gpio42", +}; + +static const char * const pwm1_groups[] = { + "gpio43", +}; + +static const char * const qdss_cti_trig_in_b0_groups[] = { + "gpio43", +}; + +static const char * const pwm2_groups[] = { + "gpio44", +}; + +static const char * const qdss_cti_trig_out_b1_groups[] = { + "gpio44", +}; + +static const char * const pwm3_groups[] = { + "gpio45", +}; + +static const char * const qdss_cti_trig_in_b1_groups[] = { + "gpio45", +}; + +static const char * const led0_groups[] = { + "gpio46", "gpio30", "gpio10", +}; + +static const char * const led2_groups[] = { + "gpio30", +}; + +static const char * const gpio_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", + "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", + "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21", + "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", + "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", + "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", + "gpio43", "gpio44", "gpio45", "gpio46", +}; + +static const struct pinfunction ipq5018_functions[] = { + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(audio_pdm0), + MSM_PIN_FUNCTION(audio_pdm1), + MSM_PIN_FUNCTION(audio_rxbclk), + MSM_PIN_FUNCTION(audio_rxd), + MSM_PIN_FUNCTION(audio_rxfsync), + MSM_PIN_FUNCTION(audio_rxmclk), + MSM_PIN_FUNCTION(audio_txbclk), + MSM_PIN_FUNCTION(audio_txd), + MSM_PIN_FUNCTION(audio_txfsync), + MSM_PIN_FUNCTION(audio_txmclk), + MSM_PIN_FUNCTION(blsp0_i2c), + MSM_PIN_FUNCTION(blsp0_spi), + MSM_PIN_FUNCTION(blsp0_uart0), + MSM_PIN_FUNCTION(blsp0_uart1), + MSM_PIN_FUNCTION(blsp1_i2c0), + MSM_PIN_FUNCTION(blsp1_i2c1), + MSM_PIN_FUNCTION(blsp1_spi0), + MSM_PIN_FUNCTION(blsp1_spi1), + MSM_PIN_FUNCTION(blsp1_uart0), + MSM_PIN_FUNCTION(blsp1_uart1), + MSM_PIN_FUNCTION(blsp1_uart2), + MSM_PIN_FUNCTION(blsp2_i2c0), + MSM_PIN_FUNCTION(blsp2_i2c1), + MSM_PIN_FUNCTION(blsp2_spi), + MSM_PIN_FUNCTION(blsp2_spi0), + MSM_PIN_FUNCTION(blsp2_spi1), + MSM_PIN_FUNCTION(btss), + MSM_PIN_FUNCTION(burn0), + MSM_PIN_FUNCTION(burn1), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(cxc_clk), + MSM_PIN_FUNCTION(cxc_data), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(eud_gpio), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(gcc_tlmm), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(led0), + MSM_PIN_FUNCTION(led2), + MSM_PIN_FUNCTION(mac0), + MSM_PIN_FUNCTION(mac1), + MSM_PIN_FUNCTION(mdc), + MSM_PIN_FUNCTION(mdio), + MSM_PIN_FUNCTION(pcie0_clk), + MSM_PIN_FUNCTION(pcie0_wake), + MSM_PIN_FUNCTION(pcie1_clk), + MSM_PIN_FUNCTION(pcie1_wake), + MSM_PIN_FUNCTION(pll_test), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(pwm0), + MSM_PIN_FUNCTION(pwm1), + MSM_PIN_FUNCTION(pwm2), + MSM_PIN_FUNCTION(pwm3), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b1), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qspi_data), + MSM_PIN_FUNCTION(reset_out), + MSM_PIN_FUNCTION(sdc1_clk), + MSM_PIN_FUNCTION(sdc1_cmd), + MSM_PIN_FUNCTION(sdc1_data), + MSM_PIN_FUNCTION(wci_txd), + MSM_PIN_FUNCTION(wci_rxd), + MSM_PIN_FUNCTION(wsa_swrm), + MSM_PIN_FUNCTION(wsi_clk3), + MSM_PIN_FUNCTION(wsi_data3), + MSM_PIN_FUNCTION(wsis_reset), + MSM_PIN_FUNCTION(xfem), +}; + +static const struct msm_pingroup ipq5018_groups[] = { + PINGROUP(0, atest_char, _, qdss_cti_trig_out_a0, wci_txd, wci_rxd, xfem, _, _, _), + PINGROUP(1, atest_char, _, qdss_cti_trig_in_a0, wci_txd, wci_rxd, xfem, _, _, _), + PINGROUP(2, atest_char, _, qdss_cti_trig_out_a1, wci_txd, wci_rxd, xfem, _, _, _), + PINGROUP(3, atest_char, _, qdss_cti_trig_in_a1, wci_txd, wci_rxd, xfem, _, _, _), + PINGROUP(4, sdc1_data, qspi_data, blsp1_spi1, btss, dbg_out, qdss_traceclk_a, _, burn0, _), + PINGROUP(5, sdc1_data, qspi_data, cxc_clk, blsp1_spi1, blsp1_i2c1, btss, _, qdss_tracectl_a, _), + PINGROUP(6, sdc1_data, qspi_data, cxc_data, blsp1_spi1, blsp1_i2c1, btss, _, qdss_tracedata_a, _), + PINGROUP(7, sdc1_data, qspi_data, mac0, blsp1_spi1, btss, _, qdss_tracedata_a, _, _), + PINGROUP(8, sdc1_cmd, qspi_cs, mac1, btss, _, qdss_tracedata_a, _, _, _), + PINGROUP(9, sdc1_clk, qspi_clk, _, qdss_tracedata_a, _, _, _, _, _), + PINGROUP(10, blsp0_spi, blsp1_uart0, led0, gcc_plltest, qdss_tracedata_a, _, _, _, _), + PINGROUP(11, blsp0_spi, blsp1_uart0, _, gcc_tlmm, qdss_tracedata_a, _, _, _, _), + PINGROUP(12, blsp0_spi, blsp0_i2c, blsp1_uart0, _, gcc_plltest, qdss_tracedata_a, _, _, _), + PINGROUP(13, blsp0_spi, blsp0_i2c, blsp1_uart0, _, qdss_tracedata_a, _, _, _, _), + PINGROUP(14, pcie0_clk, _, _, cri_trng0, qdss_tracedata_a, _, _, _, _), + PINGROUP(15, _, _, cri_trng1, qdss_tracedata_a, _, _, _, _, _), + PINGROUP(16, pcie0_wake, _, _, cri_trng, qdss_tracedata_a, _, _, _, _), + PINGROUP(17, pcie1_clk, btss, _, prng_rosc, qdss_tracedata_a, _, _, _, _), + PINGROUP(18, blsp1_spi0, btss, _, qdss_tracedata_a, _, _, _, _, _), + PINGROUP(19, pcie1_wake, blsp1_spi0, blsp1_i2c0, btss, _, qdss_tracedata_a, _, _, _), + PINGROUP(20, blsp0_uart0, blsp1_spi0, blsp1_i2c0, _, qdss_tracedata_a, _, _, _, _), + PINGROUP(21, blsp0_uart0, blsp1_spi0, _, qdss_tracedata_a, _, _, _, _, _), + PINGROUP(22, _, pll_test, eud_gpio, _, _, _, _, _, _), + PINGROUP(23, audio_rxmclk, audio_pdm0, audio_rxmclk, blsp2_spi1, blsp1_uart2, btss, _, qdss_tracedata_b, _), + PINGROUP(24, audio_rxbclk, audio_pdm0, blsp2_spi1, blsp1_uart2, btss, _, qdss_tracedata_b, _, _), + PINGROUP(25, audio_rxfsync, audio_pdm1, blsp2_i2c1, blsp2_spi1, blsp1_uart2, btss, _, qdss_tracedata_b, _), + PINGROUP(26, audio_rxd, audio_pdm1, blsp2_i2c1, blsp2_spi1, blsp1_uart2, btss, _, qdss_tracedata_b, _), + PINGROUP(27, audio_txmclk, wsa_swrm, audio_txmclk, blsp2_spi, btss, _, qdss_tracedata_b, _, _), + PINGROUP(28, audio_txbclk, wsa_swrm, blsp0_uart1, btss, qdss_tracedata_b, _, _, _, _), + PINGROUP(29, audio_txfsync, _, blsp0_uart1, _, qdss_tracedata_b, _, _, _, _), + PINGROUP(30, audio_txd, led2, led0, _, _, _, _, _, _), + PINGROUP(31, blsp2_spi0, blsp1_uart1, _, qdss_tracedata_b, eud_gpio, _, _, _, _), + PINGROUP(32, blsp2_spi0, blsp1_uart1, _, qdss_tracedata_b, eud_gpio, _, _, _, _), + PINGROUP(33, blsp2_i2c0, blsp2_spi0, blsp1_uart1, _, qdss_tracedata_b, eud_gpio, _, _, _), + PINGROUP(34, blsp2_i2c0, blsp2_spi0, blsp1_uart1, _, qdss_tracedata_b, eud_gpio, _, _, _), + PINGROUP(35, _, qdss_tracedata_b, eud_gpio, _, _, _, _, _, _), + PINGROUP(36, mdc, qdss_tracedata_b, _, wsi_clk3, _, _, _, _, _), + PINGROUP(37, mdio, atest_char, qdss_tracedata_b, _, wsi_data3, _, _, _, _), + PINGROUP(38, qdss_tracedata_b, _, _, _, _, _, _, _, _), + PINGROUP(39, qdss_traceclk_b, _, _, _, _, _, _, _, _), + PINGROUP(40, reset_out, qdss_tracectl_b, _, _, _, _, _, _, _), + PINGROUP(41, _, _, _, _, _, _, _, _, _), + PINGROUP(42, pwm0, qdss_cti_trig_out_b0, wci_txd, wci_rxd, xfem, _, _, _, _), + PINGROUP(43, pwm1, qdss_cti_trig_in_b0, wci_txd, wci_rxd, xfem, _, _, _, _), + PINGROUP(44, pwm2, qdss_cti_trig_out_b1, wci_txd, wci_rxd, xfem, _, _, _, _), + PINGROUP(45, pwm3, qdss_cti_trig_in_b1, wci_txd, wci_rxd, xfem, _, _, _, _), + PINGROUP(46, led0, _, _, _, _, _, _, _, _), +}; + +static const struct msm_pinctrl_soc_data ipq5018_pinctrl = { + .pins = ipq5018_pins, + .npins = ARRAY_SIZE(ipq5018_pins), + .functions = ipq5018_functions, + .nfunctions = ARRAY_SIZE(ipq5018_functions), + .groups = ipq5018_groups, + .ngroups = ARRAY_SIZE(ipq5018_groups), + .ngpios = 47, +}; + +static int ipq5018_pinctrl_probe(struct platform_device *pdev) +{ + return msm_pinctrl_probe(pdev, &ipq5018_pinctrl); +} + +static const struct of_device_id ipq5018_pinctrl_of_match[] = { + { .compatible = "qcom,ipq5018-tlmm", }, + { } +}; +MODULE_DEVICE_TABLE(of, ipq5018_pinctrl_of_match); + +static struct platform_driver ipq5018_pinctrl_driver = { + .driver = { + .name = "ipq5018-tlmm", + .of_match_table = ipq5018_pinctrl_of_match, + }, + .probe = ipq5018_pinctrl_probe, + .remove = msm_pinctrl_remove, +}; + +static int __init ipq5018_pinctrl_init(void) +{ + return platform_driver_register(&ipq5018_pinctrl_driver); +} +arch_initcall(ipq5018_pinctrl_init); + +static void __exit ipq5018_pinctrl_exit(void) +{ + platform_driver_unregister(&ipq5018_pinctrl_driver); +} +module_exit(ipq5018_pinctrl_exit); + +MODULE_DESCRIPTION("Qualcomm Technologies Inc ipq5018 pinctrl driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/qcom/pinctrl-ipq5332.c b/drivers/pinctrl/qcom/pinctrl-ipq5332.c index e78d11292f42..625f8014051f 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq5332.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq5332.c @@ -6,23 +6,15 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -661,102 +653,102 @@ static const char * const xfem_groups[] = { "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", }; -static const struct msm_function ipq5332_functions[] = { - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(atest_tic), - FUNCTION(audio_pri), - FUNCTION(audio_pri0), - FUNCTION(audio_pri1), - FUNCTION(audio_sec), - FUNCTION(audio_sec0), - FUNCTION(audio_sec1), - FUNCTION(blsp0_i2c), - FUNCTION(blsp0_spi), - FUNCTION(blsp0_uart0), - FUNCTION(blsp0_uart1), - FUNCTION(blsp1_i2c0), - FUNCTION(blsp1_i2c1), - FUNCTION(blsp1_spi0), - FUNCTION(blsp1_spi1), - FUNCTION(blsp1_uart0), - FUNCTION(blsp1_uart1), - FUNCTION(blsp1_uart2), - FUNCTION(blsp2_i2c0), - FUNCTION(blsp2_i2c1), - FUNCTION(blsp2_spi), - FUNCTION(blsp2_spi0), - FUNCTION(blsp2_spi1), - FUNCTION(core_voltage), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(cri_trng2), - FUNCTION(cri_trng3), - FUNCTION(cxc_clk), - FUNCTION(cxc_data), - FUNCTION(dbg_out), - FUNCTION(gcc_plltest), - FUNCTION(gcc_tlmm), - FUNCTION(gpio), - FUNCTION(lock_det), - FUNCTION(mac0), - FUNCTION(mac1), - FUNCTION(mdc0), - FUNCTION(mdc1), - FUNCTION(mdio0), - FUNCTION(mdio1), - FUNCTION(pc), - FUNCTION(pcie0_clk), - FUNCTION(pcie0_wake), - FUNCTION(pcie1_clk), - FUNCTION(pcie1_wake), - FUNCTION(pcie2_clk), - FUNCTION(pcie2_wake), - FUNCTION(pll_test), - FUNCTION(prng_rosc0), - FUNCTION(prng_rosc1), - FUNCTION(prng_rosc2), - FUNCTION(prng_rosc3), - FUNCTION(pta), - FUNCTION(pwm0), - FUNCTION(pwm1), - FUNCTION(pwm2), - FUNCTION(pwm3), - FUNCTION(qdss_cti_trig_in_a0), - FUNCTION(qdss_cti_trig_in_a1), - FUNCTION(qdss_cti_trig_in_b0), - FUNCTION(qdss_cti_trig_in_b1), - FUNCTION(qdss_cti_trig_out_a0), - FUNCTION(qdss_cti_trig_out_a1), - FUNCTION(qdss_cti_trig_out_b0), - FUNCTION(qdss_cti_trig_out_b1), - FUNCTION(qdss_traceclk_a), - FUNCTION(qdss_traceclk_b), - FUNCTION(qdss_tracectl_a), - FUNCTION(qdss_tracectl_b), - FUNCTION(qdss_tracedata_a), - FUNCTION(qdss_tracedata_b), - FUNCTION(qspi_data), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(resout), - FUNCTION(rx0), - FUNCTION(rx1), - FUNCTION(sdc_data), - FUNCTION(sdc_clk), - FUNCTION(sdc_cmd), - FUNCTION(tsens_max), - FUNCTION(wci_txd), - FUNCTION(wci_rxd), - FUNCTION(wsi_clk), - FUNCTION(wsi_clk3), - FUNCTION(wsi_data), - FUNCTION(wsi_data3), - FUNCTION(wsis_reset), - FUNCTION(xfem), +static const struct pinfunction ipq5332_functions[] = { + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(atest_tic), + MSM_PIN_FUNCTION(audio_pri), + MSM_PIN_FUNCTION(audio_pri0), + MSM_PIN_FUNCTION(audio_pri1), + MSM_PIN_FUNCTION(audio_sec), + MSM_PIN_FUNCTION(audio_sec0), + MSM_PIN_FUNCTION(audio_sec1), + MSM_PIN_FUNCTION(blsp0_i2c), + MSM_PIN_FUNCTION(blsp0_spi), + MSM_PIN_FUNCTION(blsp0_uart0), + MSM_PIN_FUNCTION(blsp0_uart1), + MSM_PIN_FUNCTION(blsp1_i2c0), + MSM_PIN_FUNCTION(blsp1_i2c1), + MSM_PIN_FUNCTION(blsp1_spi0), + MSM_PIN_FUNCTION(blsp1_spi1), + MSM_PIN_FUNCTION(blsp1_uart0), + MSM_PIN_FUNCTION(blsp1_uart1), + MSM_PIN_FUNCTION(blsp1_uart2), + MSM_PIN_FUNCTION(blsp2_i2c0), + MSM_PIN_FUNCTION(blsp2_i2c1), + MSM_PIN_FUNCTION(blsp2_spi), + MSM_PIN_FUNCTION(blsp2_spi0), + MSM_PIN_FUNCTION(blsp2_spi1), + MSM_PIN_FUNCTION(core_voltage), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(cri_trng2), + MSM_PIN_FUNCTION(cri_trng3), + MSM_PIN_FUNCTION(cxc_clk), + MSM_PIN_FUNCTION(cxc_data), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(gcc_tlmm), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(lock_det), + MSM_PIN_FUNCTION(mac0), + MSM_PIN_FUNCTION(mac1), + MSM_PIN_FUNCTION(mdc0), + MSM_PIN_FUNCTION(mdc1), + MSM_PIN_FUNCTION(mdio0), + MSM_PIN_FUNCTION(mdio1), + MSM_PIN_FUNCTION(pc), + MSM_PIN_FUNCTION(pcie0_clk), + MSM_PIN_FUNCTION(pcie0_wake), + MSM_PIN_FUNCTION(pcie1_clk), + MSM_PIN_FUNCTION(pcie1_wake), + MSM_PIN_FUNCTION(pcie2_clk), + MSM_PIN_FUNCTION(pcie2_wake), + MSM_PIN_FUNCTION(pll_test), + MSM_PIN_FUNCTION(prng_rosc0), + MSM_PIN_FUNCTION(prng_rosc1), + MSM_PIN_FUNCTION(prng_rosc2), + MSM_PIN_FUNCTION(prng_rosc3), + MSM_PIN_FUNCTION(pta), + MSM_PIN_FUNCTION(pwm0), + MSM_PIN_FUNCTION(pwm1), + MSM_PIN_FUNCTION(pwm2), + MSM_PIN_FUNCTION(pwm3), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b1), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(qspi_data), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(resout), + MSM_PIN_FUNCTION(rx0), + MSM_PIN_FUNCTION(rx1), + MSM_PIN_FUNCTION(sdc_data), + MSM_PIN_FUNCTION(sdc_clk), + MSM_PIN_FUNCTION(sdc_cmd), + MSM_PIN_FUNCTION(tsens_max), + MSM_PIN_FUNCTION(wci_txd), + MSM_PIN_FUNCTION(wci_rxd), + MSM_PIN_FUNCTION(wsi_clk), + MSM_PIN_FUNCTION(wsi_clk3), + MSM_PIN_FUNCTION(wsi_data), + MSM_PIN_FUNCTION(wsi_data3), + MSM_PIN_FUNCTION(wsis_reset), + MSM_PIN_FUNCTION(xfem), }; static const struct msm_pingroup ipq5332_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-ipq6018.c b/drivers/pinctrl/qcom/pinctrl-ipq6018.c index ec50a3b4bd16..0ad08647dbcd 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq6018.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq6018.c @@ -6,23 +6,15 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -854,129 +846,129 @@ static const char * const gpio_groups[] = { "gpio78", "gpio79", }; -static const struct msm_function ipq6018_functions[] = { - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(audio0), - FUNCTION(audio1), - FUNCTION(audio2), - FUNCTION(audio3), - FUNCTION(audio_rxbclk), - FUNCTION(audio_rxfsync), - FUNCTION(audio_rxmclk), - FUNCTION(audio_rxmclkin), - FUNCTION(audio_txbclk), - FUNCTION(audio_txfsync), - FUNCTION(audio_txmclk), - FUNCTION(audio_txmclkin), - FUNCTION(blsp0_i2c), - FUNCTION(blsp0_spi), - FUNCTION(blsp0_uart), - FUNCTION(blsp1_i2c), - FUNCTION(blsp1_spi), - FUNCTION(blsp1_uart), - FUNCTION(blsp2_i2c), - FUNCTION(blsp2_spi), - FUNCTION(blsp2_uart), - FUNCTION(blsp3_i2c), - FUNCTION(blsp3_spi), - FUNCTION(blsp3_uart), - FUNCTION(blsp4_i2c), - FUNCTION(blsp4_spi), - FUNCTION(blsp4_uart), - FUNCTION(blsp5_i2c), - FUNCTION(blsp5_uart), - FUNCTION(burn0), - FUNCTION(burn1), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(cxc0), - FUNCTION(cxc1), - FUNCTION(dbg_out), - FUNCTION(gcc_plltest), - FUNCTION(gcc_tlmm), - FUNCTION(gpio), - FUNCTION(lpass_aud), - FUNCTION(lpass_aud0), - FUNCTION(lpass_aud1), - FUNCTION(lpass_aud2), - FUNCTION(lpass_pcm), - FUNCTION(lpass_pdm), - FUNCTION(mac00), - FUNCTION(mac01), - FUNCTION(mac10), - FUNCTION(mac11), - FUNCTION(mac12), - FUNCTION(mac13), - FUNCTION(mac20), - FUNCTION(mac21), - FUNCTION(mdc), - FUNCTION(mdio), - FUNCTION(pcie0_clk), - FUNCTION(pcie0_rst), - FUNCTION(pcie0_wake), - FUNCTION(prng_rosc), - FUNCTION(pta1_0), - FUNCTION(pta1_1), - FUNCTION(pta1_2), - FUNCTION(pta2_0), - FUNCTION(pta2_1), - FUNCTION(pta2_2), - FUNCTION(pwm00), - FUNCTION(pwm01), - FUNCTION(pwm02), - FUNCTION(pwm03), - FUNCTION(pwm04), - FUNCTION(pwm10), - FUNCTION(pwm11), - FUNCTION(pwm12), - FUNCTION(pwm13), - FUNCTION(pwm14), - FUNCTION(pwm20), - FUNCTION(pwm21), - FUNCTION(pwm22), - FUNCTION(pwm23), - FUNCTION(pwm24), - FUNCTION(pwm30), - FUNCTION(pwm31), - FUNCTION(pwm32), - FUNCTION(pwm33), - FUNCTION(qdss_cti_trig_in_a0), - FUNCTION(qdss_cti_trig_in_a1), - FUNCTION(qdss_cti_trig_out_a0), - FUNCTION(qdss_cti_trig_out_a1), - FUNCTION(qdss_cti_trig_in_b0), - FUNCTION(qdss_cti_trig_in_b1), - FUNCTION(qdss_cti_trig_out_b0), - FUNCTION(qdss_cti_trig_out_b1), - FUNCTION(qdss_traceclk_a), - FUNCTION(qdss_tracectl_a), - FUNCTION(qdss_tracedata_a), - FUNCTION(qdss_traceclk_b), - FUNCTION(qdss_tracectl_b), - FUNCTION(qdss_tracedata_b), - FUNCTION(qpic_pad), - FUNCTION(rx0), - FUNCTION(rx1), - FUNCTION(rx_swrm), - FUNCTION(rx_swrm0), - FUNCTION(rx_swrm1), - FUNCTION(sd_card), - FUNCTION(sd_write), - FUNCTION(tsens_max), - FUNCTION(tx_swrm), - FUNCTION(tx_swrm0), - FUNCTION(tx_swrm1), - FUNCTION(tx_swrm2), - FUNCTION(wci20), - FUNCTION(wci21), - FUNCTION(wci22), - FUNCTION(wci23), - FUNCTION(wsa_swrm), +static const struct pinfunction ipq6018_functions[] = { + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(audio0), + MSM_PIN_FUNCTION(audio1), + MSM_PIN_FUNCTION(audio2), + MSM_PIN_FUNCTION(audio3), + MSM_PIN_FUNCTION(audio_rxbclk), + MSM_PIN_FUNCTION(audio_rxfsync), + MSM_PIN_FUNCTION(audio_rxmclk), + MSM_PIN_FUNCTION(audio_rxmclkin), + MSM_PIN_FUNCTION(audio_txbclk), + MSM_PIN_FUNCTION(audio_txfsync), + MSM_PIN_FUNCTION(audio_txmclk), + MSM_PIN_FUNCTION(audio_txmclkin), + MSM_PIN_FUNCTION(blsp0_i2c), + MSM_PIN_FUNCTION(blsp0_spi), + MSM_PIN_FUNCTION(blsp0_uart), + MSM_PIN_FUNCTION(blsp1_i2c), + MSM_PIN_FUNCTION(blsp1_spi), + MSM_PIN_FUNCTION(blsp1_uart), + MSM_PIN_FUNCTION(blsp2_i2c), + MSM_PIN_FUNCTION(blsp2_spi), + MSM_PIN_FUNCTION(blsp2_uart), + MSM_PIN_FUNCTION(blsp3_i2c), + MSM_PIN_FUNCTION(blsp3_spi), + MSM_PIN_FUNCTION(blsp3_uart), + MSM_PIN_FUNCTION(blsp4_i2c), + MSM_PIN_FUNCTION(blsp4_spi), + MSM_PIN_FUNCTION(blsp4_uart), + MSM_PIN_FUNCTION(blsp5_i2c), + MSM_PIN_FUNCTION(blsp5_uart), + MSM_PIN_FUNCTION(burn0), + MSM_PIN_FUNCTION(burn1), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(cxc0), + MSM_PIN_FUNCTION(cxc1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(gcc_tlmm), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(lpass_aud), + MSM_PIN_FUNCTION(lpass_aud0), + MSM_PIN_FUNCTION(lpass_aud1), + MSM_PIN_FUNCTION(lpass_aud2), + MSM_PIN_FUNCTION(lpass_pcm), + MSM_PIN_FUNCTION(lpass_pdm), + MSM_PIN_FUNCTION(mac00), + MSM_PIN_FUNCTION(mac01), + MSM_PIN_FUNCTION(mac10), + MSM_PIN_FUNCTION(mac11), + MSM_PIN_FUNCTION(mac12), + MSM_PIN_FUNCTION(mac13), + MSM_PIN_FUNCTION(mac20), + MSM_PIN_FUNCTION(mac21), + MSM_PIN_FUNCTION(mdc), + MSM_PIN_FUNCTION(mdio), + MSM_PIN_FUNCTION(pcie0_clk), + MSM_PIN_FUNCTION(pcie0_rst), + MSM_PIN_FUNCTION(pcie0_wake), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(pta1_0), + MSM_PIN_FUNCTION(pta1_1), + MSM_PIN_FUNCTION(pta1_2), + MSM_PIN_FUNCTION(pta2_0), + MSM_PIN_FUNCTION(pta2_1), + MSM_PIN_FUNCTION(pta2_2), + MSM_PIN_FUNCTION(pwm00), + MSM_PIN_FUNCTION(pwm01), + MSM_PIN_FUNCTION(pwm02), + MSM_PIN_FUNCTION(pwm03), + MSM_PIN_FUNCTION(pwm04), + MSM_PIN_FUNCTION(pwm10), + MSM_PIN_FUNCTION(pwm11), + MSM_PIN_FUNCTION(pwm12), + MSM_PIN_FUNCTION(pwm13), + MSM_PIN_FUNCTION(pwm14), + MSM_PIN_FUNCTION(pwm20), + MSM_PIN_FUNCTION(pwm21), + MSM_PIN_FUNCTION(pwm22), + MSM_PIN_FUNCTION(pwm23), + MSM_PIN_FUNCTION(pwm24), + MSM_PIN_FUNCTION(pwm30), + MSM_PIN_FUNCTION(pwm31), + MSM_PIN_FUNCTION(pwm32), + MSM_PIN_FUNCTION(pwm33), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b1), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(qpic_pad), + MSM_PIN_FUNCTION(rx0), + MSM_PIN_FUNCTION(rx1), + MSM_PIN_FUNCTION(rx_swrm), + MSM_PIN_FUNCTION(rx_swrm0), + MSM_PIN_FUNCTION(rx_swrm1), + MSM_PIN_FUNCTION(sd_card), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(tsens_max), + MSM_PIN_FUNCTION(tx_swrm), + MSM_PIN_FUNCTION(tx_swrm0), + MSM_PIN_FUNCTION(tx_swrm1), + MSM_PIN_FUNCTION(tx_swrm2), + MSM_PIN_FUNCTION(wci20), + MSM_PIN_FUNCTION(wci21), + MSM_PIN_FUNCTION(wci22), + MSM_PIN_FUNCTION(wci23), + MSM_PIN_FUNCTION(wsa_swrm), }; static const struct msm_pingroup ipq6018_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-ipq8064.c b/drivers/pinctrl/qcom/pinctrl-ipq8064.c index ac717ee38416..e2bb94e86aef 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq8064.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq8064.c @@ -6,7 +6,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" @@ -161,18 +160,11 @@ static const unsigned int sdc3_clk_pins[] = { 69 }; static const unsigned int sdc3_cmd_pins[] = { 70 }; static const unsigned int sdc3_data_pins[] = { 71 }; -#define FUNCTION(fname) \ - [IPQ_MUX_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ IPQ_MUX_gpio, \ IPQ_MUX_##f1, \ @@ -211,9 +203,9 @@ static const unsigned int sdc3_data_pins[] = { 71 }; #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -487,53 +479,53 @@ static const char * const ps_hold_groups[] = { "gpio26", }; -static const struct msm_function ipq8064_functions[] = { - FUNCTION(gpio), - FUNCTION(mdio), - FUNCTION(ssbi), - FUNCTION(spmi), - FUNCTION(mi2s), - FUNCTION(pdm), - FUNCTION(audio_pcm), - FUNCTION(gsbi1), - FUNCTION(gsbi2), - FUNCTION(gsbi4), - FUNCTION(gsbi5), - FUNCTION(gsbi5_spi_cs1), - FUNCTION(gsbi5_spi_cs2), - FUNCTION(gsbi5_spi_cs3), - FUNCTION(gsbi6), - FUNCTION(gsbi7), - FUNCTION(nss_spi), - FUNCTION(sdc1), - FUNCTION(spdif), - FUNCTION(nand), - FUNCTION(tsif1), - FUNCTION(tsif2), - FUNCTION(usb_fs_n), - FUNCTION(usb_fs), - FUNCTION(usb2_hsic), - FUNCTION(rgmii2), - FUNCTION(sata), - FUNCTION(pcie1_rst), - FUNCTION(pcie1_prsnt), - FUNCTION(pcie1_pwren_n), - FUNCTION(pcie1_pwren), - FUNCTION(pcie1_pwrflt), - FUNCTION(pcie1_clk_req), - FUNCTION(pcie2_rst), - FUNCTION(pcie2_prsnt), - FUNCTION(pcie2_pwren_n), - FUNCTION(pcie2_pwren), - FUNCTION(pcie2_pwrflt), - FUNCTION(pcie2_clk_req), - FUNCTION(pcie3_rst), - FUNCTION(pcie3_prsnt), - FUNCTION(pcie3_pwren_n), - FUNCTION(pcie3_pwren), - FUNCTION(pcie3_pwrflt), - FUNCTION(pcie3_clk_req), - FUNCTION(ps_hold), +static const struct pinfunction ipq8064_functions[] = { + IPQ_PIN_FUNCTION(gpio), + IPQ_PIN_FUNCTION(mdio), + IPQ_PIN_FUNCTION(ssbi), + IPQ_PIN_FUNCTION(spmi), + IPQ_PIN_FUNCTION(mi2s), + IPQ_PIN_FUNCTION(pdm), + IPQ_PIN_FUNCTION(audio_pcm), + IPQ_PIN_FUNCTION(gsbi1), + IPQ_PIN_FUNCTION(gsbi2), + IPQ_PIN_FUNCTION(gsbi4), + IPQ_PIN_FUNCTION(gsbi5), + IPQ_PIN_FUNCTION(gsbi5_spi_cs1), + IPQ_PIN_FUNCTION(gsbi5_spi_cs2), + IPQ_PIN_FUNCTION(gsbi5_spi_cs3), + IPQ_PIN_FUNCTION(gsbi6), + IPQ_PIN_FUNCTION(gsbi7), + IPQ_PIN_FUNCTION(nss_spi), + IPQ_PIN_FUNCTION(sdc1), + IPQ_PIN_FUNCTION(spdif), + IPQ_PIN_FUNCTION(nand), + IPQ_PIN_FUNCTION(tsif1), + IPQ_PIN_FUNCTION(tsif2), + IPQ_PIN_FUNCTION(usb_fs_n), + IPQ_PIN_FUNCTION(usb_fs), + IPQ_PIN_FUNCTION(usb2_hsic), + IPQ_PIN_FUNCTION(rgmii2), + IPQ_PIN_FUNCTION(sata), + IPQ_PIN_FUNCTION(pcie1_rst), + IPQ_PIN_FUNCTION(pcie1_prsnt), + IPQ_PIN_FUNCTION(pcie1_pwren_n), + IPQ_PIN_FUNCTION(pcie1_pwren), + IPQ_PIN_FUNCTION(pcie1_pwrflt), + IPQ_PIN_FUNCTION(pcie1_clk_req), + IPQ_PIN_FUNCTION(pcie2_rst), + IPQ_PIN_FUNCTION(pcie2_prsnt), + IPQ_PIN_FUNCTION(pcie2_pwren_n), + IPQ_PIN_FUNCTION(pcie2_pwren), + IPQ_PIN_FUNCTION(pcie2_pwrflt), + IPQ_PIN_FUNCTION(pcie2_clk_req), + IPQ_PIN_FUNCTION(pcie3_rst), + IPQ_PIN_FUNCTION(pcie3_prsnt), + IPQ_PIN_FUNCTION(pcie3_pwren_n), + IPQ_PIN_FUNCTION(pcie3_pwren), + IPQ_PIN_FUNCTION(pcie3_pwrflt), + IPQ_PIN_FUNCTION(pcie3_clk_req), + IPQ_PIN_FUNCTION(ps_hold), }; static const struct msm_pingroup ipq8064_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-ipq8074.c b/drivers/pinctrl/qcom/pinctrl-ipq8074.c index aec68b1c9f53..337f3a1c92c1 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq8074.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq8074.c @@ -6,23 +6,15 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -797,119 +789,119 @@ static const char * const gpio_groups[] = { "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", }; -static const struct msm_function ipq8074_functions[] = { - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(audio_rxbclk), - FUNCTION(audio_rxd), - FUNCTION(audio_rxfsync), - FUNCTION(audio_rxmclk), - FUNCTION(audio_txbclk), - FUNCTION(audio_txd), - FUNCTION(audio_txfsync), - FUNCTION(audio_txmclk), - FUNCTION(blsp0_i2c), - FUNCTION(blsp0_spi), - FUNCTION(blsp0_uart), - FUNCTION(blsp1_i2c), - FUNCTION(blsp1_spi), - FUNCTION(blsp1_uart), - FUNCTION(blsp2_i2c), - FUNCTION(blsp2_spi), - FUNCTION(blsp2_uart), - FUNCTION(blsp3_i2c), - FUNCTION(blsp3_spi), - FUNCTION(blsp3_spi0), - FUNCTION(blsp3_spi1), - FUNCTION(blsp3_spi2), - FUNCTION(blsp3_spi3), - FUNCTION(blsp3_uart), - FUNCTION(blsp4_i2c0), - FUNCTION(blsp4_i2c1), - FUNCTION(blsp4_spi0), - FUNCTION(blsp4_spi1), - FUNCTION(blsp4_uart0), - FUNCTION(blsp4_uart1), - FUNCTION(blsp5_i2c), - FUNCTION(blsp5_spi), - FUNCTION(blsp5_uart), - FUNCTION(burn0), - FUNCTION(burn1), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(cxc0), - FUNCTION(cxc1), - FUNCTION(dbg_out), - FUNCTION(gcc_plltest), - FUNCTION(gcc_tlmm), - FUNCTION(gpio), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(led0), - FUNCTION(led1), - FUNCTION(led2), - FUNCTION(mac0_sa0), - FUNCTION(mac0_sa1), - FUNCTION(mac1_sa0), - FUNCTION(mac1_sa1), - FUNCTION(mac1_sa2), - FUNCTION(mac1_sa3), - FUNCTION(mac2_sa0), - FUNCTION(mac2_sa1), - FUNCTION(mdc), - FUNCTION(mdio), - FUNCTION(pcie0_clk), - FUNCTION(pcie0_rst), - FUNCTION(pcie0_wake), - FUNCTION(pcie1_clk), - FUNCTION(pcie1_rst), - FUNCTION(pcie1_wake), - FUNCTION(pcm_drx), - FUNCTION(pcm_dtx), - FUNCTION(pcm_fsync), - FUNCTION(pcm_pclk), - FUNCTION(pcm_zsi0), - FUNCTION(pcm_zsi1), - FUNCTION(prng_rosc), - FUNCTION(pta1_0), - FUNCTION(pta1_1), - FUNCTION(pta1_2), - FUNCTION(pta2_0), - FUNCTION(pta2_1), - FUNCTION(pta2_2), - FUNCTION(pwm0), - FUNCTION(pwm1), - FUNCTION(pwm2), - FUNCTION(pwm3), - FUNCTION(qdss_cti_trig_in_a0), - FUNCTION(qdss_cti_trig_in_a1), - FUNCTION(qdss_cti_trig_in_b0), - FUNCTION(qdss_cti_trig_in_b1), - FUNCTION(qdss_cti_trig_out_a0), - FUNCTION(qdss_cti_trig_out_a1), - FUNCTION(qdss_cti_trig_out_b0), - FUNCTION(qdss_cti_trig_out_b1), - FUNCTION(qdss_traceclk_a), - FUNCTION(qdss_traceclk_b), - FUNCTION(qdss_tracectl_a), - FUNCTION(qdss_tracectl_b), - FUNCTION(qdss_tracedata_a), - FUNCTION(qdss_tracedata_b), - FUNCTION(qpic), - FUNCTION(rx0), - FUNCTION(rx1), - FUNCTION(rx2), - FUNCTION(sd_card), - FUNCTION(sd_write), - FUNCTION(tsens_max), - FUNCTION(wci2a), - FUNCTION(wci2b), - FUNCTION(wci2c), - FUNCTION(wci2d), +static const struct pinfunction ipq8074_functions[] = { + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(audio_rxbclk), + MSM_PIN_FUNCTION(audio_rxd), + MSM_PIN_FUNCTION(audio_rxfsync), + MSM_PIN_FUNCTION(audio_rxmclk), + MSM_PIN_FUNCTION(audio_txbclk), + MSM_PIN_FUNCTION(audio_txd), + MSM_PIN_FUNCTION(audio_txfsync), + MSM_PIN_FUNCTION(audio_txmclk), + MSM_PIN_FUNCTION(blsp0_i2c), + MSM_PIN_FUNCTION(blsp0_spi), + MSM_PIN_FUNCTION(blsp0_uart), + MSM_PIN_FUNCTION(blsp1_i2c), + MSM_PIN_FUNCTION(blsp1_spi), + MSM_PIN_FUNCTION(blsp1_uart), + MSM_PIN_FUNCTION(blsp2_i2c), + MSM_PIN_FUNCTION(blsp2_spi), + MSM_PIN_FUNCTION(blsp2_uart), + MSM_PIN_FUNCTION(blsp3_i2c), + MSM_PIN_FUNCTION(blsp3_spi), + MSM_PIN_FUNCTION(blsp3_spi0), + MSM_PIN_FUNCTION(blsp3_spi1), + MSM_PIN_FUNCTION(blsp3_spi2), + MSM_PIN_FUNCTION(blsp3_spi3), + MSM_PIN_FUNCTION(blsp3_uart), + MSM_PIN_FUNCTION(blsp4_i2c0), + MSM_PIN_FUNCTION(blsp4_i2c1), + MSM_PIN_FUNCTION(blsp4_spi0), + MSM_PIN_FUNCTION(blsp4_spi1), + MSM_PIN_FUNCTION(blsp4_uart0), + MSM_PIN_FUNCTION(blsp4_uart1), + MSM_PIN_FUNCTION(blsp5_i2c), + MSM_PIN_FUNCTION(blsp5_spi), + MSM_PIN_FUNCTION(blsp5_uart), + MSM_PIN_FUNCTION(burn0), + MSM_PIN_FUNCTION(burn1), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(cxc0), + MSM_PIN_FUNCTION(cxc1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(gcc_tlmm), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(led0), + MSM_PIN_FUNCTION(led1), + MSM_PIN_FUNCTION(led2), + MSM_PIN_FUNCTION(mac0_sa0), + MSM_PIN_FUNCTION(mac0_sa1), + MSM_PIN_FUNCTION(mac1_sa0), + MSM_PIN_FUNCTION(mac1_sa1), + MSM_PIN_FUNCTION(mac1_sa2), + MSM_PIN_FUNCTION(mac1_sa3), + MSM_PIN_FUNCTION(mac2_sa0), + MSM_PIN_FUNCTION(mac2_sa1), + MSM_PIN_FUNCTION(mdc), + MSM_PIN_FUNCTION(mdio), + MSM_PIN_FUNCTION(pcie0_clk), + MSM_PIN_FUNCTION(pcie0_rst), + MSM_PIN_FUNCTION(pcie0_wake), + MSM_PIN_FUNCTION(pcie1_clk), + MSM_PIN_FUNCTION(pcie1_rst), + MSM_PIN_FUNCTION(pcie1_wake), + MSM_PIN_FUNCTION(pcm_drx), + MSM_PIN_FUNCTION(pcm_dtx), + MSM_PIN_FUNCTION(pcm_fsync), + MSM_PIN_FUNCTION(pcm_pclk), + MSM_PIN_FUNCTION(pcm_zsi0), + MSM_PIN_FUNCTION(pcm_zsi1), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(pta1_0), + MSM_PIN_FUNCTION(pta1_1), + MSM_PIN_FUNCTION(pta1_2), + MSM_PIN_FUNCTION(pta2_0), + MSM_PIN_FUNCTION(pta2_1), + MSM_PIN_FUNCTION(pta2_2), + MSM_PIN_FUNCTION(pwm0), + MSM_PIN_FUNCTION(pwm1), + MSM_PIN_FUNCTION(pwm2), + MSM_PIN_FUNCTION(pwm3), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b1), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(qpic), + MSM_PIN_FUNCTION(rx0), + MSM_PIN_FUNCTION(rx1), + MSM_PIN_FUNCTION(rx2), + MSM_PIN_FUNCTION(sd_card), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(tsens_max), + MSM_PIN_FUNCTION(wci2a), + MSM_PIN_FUNCTION(wci2b), + MSM_PIN_FUNCTION(wci2c), + MSM_PIN_FUNCTION(wci2d), }; static const struct msm_pingroup ipq8074_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-ipq9574.c b/drivers/pinctrl/qcom/pinctrl-ipq9574.c index 7f057b62475f..e2491617b236 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq9574.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq9574.c @@ -6,23 +6,15 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -623,87 +615,87 @@ static const char * const tsens_max_groups[] = { "gpio64", }; -static const struct msm_function ipq9574_functions[] = { - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(audio_pdm0), - FUNCTION(audio_pdm1), - FUNCTION(audio_pri), - FUNCTION(audio_sec), - FUNCTION(blsp0_spi), - FUNCTION(blsp0_uart), - FUNCTION(blsp1_i2c), - FUNCTION(blsp1_spi), - FUNCTION(blsp1_uart), - FUNCTION(blsp2_i2c), - FUNCTION(blsp2_spi), - FUNCTION(blsp2_uart), - FUNCTION(blsp3_i2c), - FUNCTION(blsp3_spi), - FUNCTION(blsp3_uart), - FUNCTION(blsp4_i2c), - FUNCTION(blsp4_spi), - FUNCTION(blsp4_uart), - FUNCTION(blsp5_i2c), - FUNCTION(blsp5_uart), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(cri_trng2), - FUNCTION(cri_trng3), - FUNCTION(cxc0), - FUNCTION(cxc1), - FUNCTION(dbg_out), - FUNCTION(dwc_ddrphy), - FUNCTION(gcc_plltest), - FUNCTION(gcc_tlmm), - FUNCTION(gpio), - FUNCTION(mac), - FUNCTION(mdc), - FUNCTION(mdio), - FUNCTION(pcie0_clk), - FUNCTION(pcie0_wake), - FUNCTION(pcie1_clk), - FUNCTION(pcie1_wake), - FUNCTION(pcie2_clk), - FUNCTION(pcie2_wake), - FUNCTION(pcie3_clk), - FUNCTION(pcie3_wake), - FUNCTION(prng_rosc0), - FUNCTION(prng_rosc1), - FUNCTION(prng_rosc2), - FUNCTION(prng_rosc3), - FUNCTION(pta), - FUNCTION(pwm), - FUNCTION(qdss_cti_trig_in_a0), - FUNCTION(qdss_cti_trig_in_a1), - FUNCTION(qdss_cti_trig_in_b0), - FUNCTION(qdss_cti_trig_in_b1), - FUNCTION(qdss_cti_trig_out_a0), - FUNCTION(qdss_cti_trig_out_a1), - FUNCTION(qdss_cti_trig_out_b0), - FUNCTION(qdss_cti_trig_out_b1), - FUNCTION(qdss_traceclk_a), - FUNCTION(qdss_traceclk_b), - FUNCTION(qdss_tracectl_a), - FUNCTION(qdss_tracectl_b), - FUNCTION(qdss_tracedata_a), - FUNCTION(qdss_tracedata_b), - FUNCTION(qspi_data), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(rx0), - FUNCTION(rx1), - FUNCTION(sdc_data), - FUNCTION(sdc_clk), - FUNCTION(sdc_cmd), - FUNCTION(sdc_rclk), - FUNCTION(tsens_max), - FUNCTION(wci20), - FUNCTION(wci21), - FUNCTION(wsa_swrm), +static const struct pinfunction ipq9574_functions[] = { + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(audio_pdm0), + MSM_PIN_FUNCTION(audio_pdm1), + MSM_PIN_FUNCTION(audio_pri), + MSM_PIN_FUNCTION(audio_sec), + MSM_PIN_FUNCTION(blsp0_spi), + MSM_PIN_FUNCTION(blsp0_uart), + MSM_PIN_FUNCTION(blsp1_i2c), + MSM_PIN_FUNCTION(blsp1_spi), + MSM_PIN_FUNCTION(blsp1_uart), + MSM_PIN_FUNCTION(blsp2_i2c), + MSM_PIN_FUNCTION(blsp2_spi), + MSM_PIN_FUNCTION(blsp2_uart), + MSM_PIN_FUNCTION(blsp3_i2c), + MSM_PIN_FUNCTION(blsp3_spi), + MSM_PIN_FUNCTION(blsp3_uart), + MSM_PIN_FUNCTION(blsp4_i2c), + MSM_PIN_FUNCTION(blsp4_spi), + MSM_PIN_FUNCTION(blsp4_uart), + MSM_PIN_FUNCTION(blsp5_i2c), + MSM_PIN_FUNCTION(blsp5_uart), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(cri_trng2), + MSM_PIN_FUNCTION(cri_trng3), + MSM_PIN_FUNCTION(cxc0), + MSM_PIN_FUNCTION(cxc1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(dwc_ddrphy), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(gcc_tlmm), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(mac), + MSM_PIN_FUNCTION(mdc), + MSM_PIN_FUNCTION(mdio), + MSM_PIN_FUNCTION(pcie0_clk), + MSM_PIN_FUNCTION(pcie0_wake), + MSM_PIN_FUNCTION(pcie1_clk), + MSM_PIN_FUNCTION(pcie1_wake), + MSM_PIN_FUNCTION(pcie2_clk), + MSM_PIN_FUNCTION(pcie2_wake), + MSM_PIN_FUNCTION(pcie3_clk), + MSM_PIN_FUNCTION(pcie3_wake), + MSM_PIN_FUNCTION(prng_rosc0), + MSM_PIN_FUNCTION(prng_rosc1), + MSM_PIN_FUNCTION(prng_rosc2), + MSM_PIN_FUNCTION(prng_rosc3), + MSM_PIN_FUNCTION(pta), + MSM_PIN_FUNCTION(pwm), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b1), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(qspi_data), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(rx0), + MSM_PIN_FUNCTION(rx1), + MSM_PIN_FUNCTION(sdc_data), + MSM_PIN_FUNCTION(sdc_clk), + MSM_PIN_FUNCTION(sdc_cmd), + MSM_PIN_FUNCTION(sdc_rclk), + MSM_PIN_FUNCTION(tsens_max), + MSM_PIN_FUNCTION(wci20), + MSM_PIN_FUNCTION(wci21), + MSM_PIN_FUNCTION(wsa_swrm), }; static const struct msm_pingroup ipq9574_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-mdm9607.c b/drivers/pinctrl/qcom/pinctrl-mdm9607.c index d622b3df0fe7..e7cd3ef1cf3e 100644 --- a/drivers/pinctrl/qcom/pinctrl-mdm9607.c +++ b/drivers/pinctrl/qcom/pinctrl-mdm9607.c @@ -8,7 +8,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" @@ -204,18 +203,11 @@ static const unsigned int qdsd_data1_pins[] = { 89 }; static const unsigned int qdsd_data2_pins[] = { 90 }; static const unsigned int qdsd_data3_pins[] = { 91 }; -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, \ msm_mux_##f1, \ @@ -252,9 +244,9 @@ static const unsigned int qdsd_data3_pins[] = { 91 }; #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -806,134 +798,134 @@ static const char * const pwr_crypto_enabled_b_groups[] = { "gpio79", }; -static const struct msm_function mdm9607_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(atest_bbrx0), - FUNCTION(atest_bbrx1), - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(atest_combodac_to_gpio_native), - FUNCTION(atest_gpsadc_dtest0_native), - FUNCTION(atest_gpsadc_dtest1_native), - FUNCTION(atest_tsens), - FUNCTION(backlight_en_b), - FUNCTION(bimc_dte0), - FUNCTION(bimc_dte1), - FUNCTION(blsp1_spi), - FUNCTION(blsp2_spi), - FUNCTION(blsp3_spi), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_i2c5), - FUNCTION(blsp_i2c6), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_spi6), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uart3), - FUNCTION(blsp_uart4), - FUNCTION(blsp_uart5), - FUNCTION(blsp_uart6), - FUNCTION(blsp_uim1), - FUNCTION(blsp_uim2), - FUNCTION(codec_int), - FUNCTION(codec_rst), - FUNCTION(coex_uart), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ebi0_wrcdc), - FUNCTION(ebi2_a), - FUNCTION(ebi2_a_d_8_b), - FUNCTION(ebi2_lcd), - FUNCTION(ebi2_lcd_cs_n_b), - FUNCTION(ebi2_lcd_te_b), - FUNCTION(eth_irq), - FUNCTION(eth_rst), - FUNCTION(gcc_gp1_clk_a), - FUNCTION(gcc_gp1_clk_b), - FUNCTION(gcc_gp2_clk_a), - FUNCTION(gcc_gp2_clk_b), - FUNCTION(gcc_gp3_clk_a), - FUNCTION(gcc_gp3_clk_b), - FUNCTION(gcc_plltest), - FUNCTION(gcc_tlmm), - FUNCTION(gmac_mdio), - FUNCTION(gpio), - FUNCTION(gsm0_tx), - FUNCTION(lcd_rst), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(m_voc), - FUNCTION(modem_tsync), - FUNCTION(nav_ptp_pps_in_a), - FUNCTION(nav_ptp_pps_in_b), - FUNCTION(nav_tsync_out_a), - FUNCTION(nav_tsync_out_b), - FUNCTION(pa_indicator), - FUNCTION(pbs0), - FUNCTION(pbs1), - FUNCTION(pbs2), - FUNCTION(pri_mi2s_data0_a), - FUNCTION(pri_mi2s_data1_a), - FUNCTION(pri_mi2s_mclk_a), - FUNCTION(pri_mi2s_sck_a), - FUNCTION(pri_mi2s_ws_a), - FUNCTION(prng_rosc), - FUNCTION(ptp_pps_out_a), - FUNCTION(ptp_pps_out_b), - FUNCTION(pwr_crypto_enabled_a), - FUNCTION(pwr_crypto_enabled_b), - FUNCTION(pwr_modem_enabled_a), - FUNCTION(pwr_modem_enabled_b), - FUNCTION(pwr_nav_enabled_a), - FUNCTION(pwr_nav_enabled_b), - FUNCTION(qdss_cti_trig_in_a0), - FUNCTION(qdss_cti_trig_in_a1), - FUNCTION(qdss_cti_trig_in_b0), - FUNCTION(qdss_cti_trig_in_b1), - FUNCTION(qdss_cti_trig_out_a0), - FUNCTION(qdss_cti_trig_out_a1), - FUNCTION(qdss_cti_trig_out_b0), - FUNCTION(qdss_cti_trig_out_b1), - FUNCTION(qdss_traceclk_a), - FUNCTION(qdss_traceclk_b), - FUNCTION(qdss_tracectl_a), - FUNCTION(qdss_tracectl_b), - FUNCTION(qdss_tracedata_a), - FUNCTION(qdss_tracedata_b), - FUNCTION(rcm_marker1), - FUNCTION(rcm_marker2), - FUNCTION(sd_write), - FUNCTION(sec_mi2s), - FUNCTION(sensor_en), - FUNCTION(sensor_int2), - FUNCTION(sensor_int3), - FUNCTION(sensor_rst), - FUNCTION(ssbi1), - FUNCTION(ssbi2), - FUNCTION(touch_rst), - FUNCTION(ts_int), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(uim_batt), - FUNCTION(wlan_en1) +static const struct pinfunction mdm9607_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(atest_bbrx0), + MSM_PIN_FUNCTION(atest_bbrx1), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(atest_combodac_to_gpio_native), + MSM_PIN_FUNCTION(atest_gpsadc_dtest0_native), + MSM_PIN_FUNCTION(atest_gpsadc_dtest1_native), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(backlight_en_b), + MSM_PIN_FUNCTION(bimc_dte0), + MSM_PIN_FUNCTION(bimc_dte1), + MSM_PIN_FUNCTION(blsp1_spi), + MSM_PIN_FUNCTION(blsp2_spi), + MSM_PIN_FUNCTION(blsp3_spi), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(blsp_i2c6), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(blsp_spi6), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_uart3), + MSM_PIN_FUNCTION(blsp_uart4), + MSM_PIN_FUNCTION(blsp_uart5), + MSM_PIN_FUNCTION(blsp_uart6), + MSM_PIN_FUNCTION(blsp_uim1), + MSM_PIN_FUNCTION(blsp_uim2), + MSM_PIN_FUNCTION(codec_int), + MSM_PIN_FUNCTION(codec_rst), + MSM_PIN_FUNCTION(coex_uart), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ebi0_wrcdc), + MSM_PIN_FUNCTION(ebi2_a), + MSM_PIN_FUNCTION(ebi2_a_d_8_b), + MSM_PIN_FUNCTION(ebi2_lcd), + MSM_PIN_FUNCTION(ebi2_lcd_cs_n_b), + MSM_PIN_FUNCTION(ebi2_lcd_te_b), + MSM_PIN_FUNCTION(eth_irq), + MSM_PIN_FUNCTION(eth_rst), + MSM_PIN_FUNCTION(gcc_gp1_clk_a), + MSM_PIN_FUNCTION(gcc_gp1_clk_b), + MSM_PIN_FUNCTION(gcc_gp2_clk_a), + MSM_PIN_FUNCTION(gcc_gp2_clk_b), + MSM_PIN_FUNCTION(gcc_gp3_clk_a), + MSM_PIN_FUNCTION(gcc_gp3_clk_b), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(gcc_tlmm), + MSM_PIN_FUNCTION(gmac_mdio), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gsm0_tx), + MSM_PIN_FUNCTION(lcd_rst), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(modem_tsync), + MSM_PIN_FUNCTION(nav_ptp_pps_in_a), + MSM_PIN_FUNCTION(nav_ptp_pps_in_b), + MSM_PIN_FUNCTION(nav_tsync_out_a), + MSM_PIN_FUNCTION(nav_tsync_out_b), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pbs0), + MSM_PIN_FUNCTION(pbs1), + MSM_PIN_FUNCTION(pbs2), + MSM_PIN_FUNCTION(pri_mi2s_data0_a), + MSM_PIN_FUNCTION(pri_mi2s_data1_a), + MSM_PIN_FUNCTION(pri_mi2s_mclk_a), + MSM_PIN_FUNCTION(pri_mi2s_sck_a), + MSM_PIN_FUNCTION(pri_mi2s_ws_a), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(ptp_pps_out_a), + MSM_PIN_FUNCTION(ptp_pps_out_b), + MSM_PIN_FUNCTION(pwr_crypto_enabled_a), + MSM_PIN_FUNCTION(pwr_crypto_enabled_b), + MSM_PIN_FUNCTION(pwr_modem_enabled_a), + MSM_PIN_FUNCTION(pwr_modem_enabled_b), + MSM_PIN_FUNCTION(pwr_nav_enabled_a), + MSM_PIN_FUNCTION(pwr_nav_enabled_b), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b1), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(rcm_marker1), + MSM_PIN_FUNCTION(rcm_marker2), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(sensor_en), + MSM_PIN_FUNCTION(sensor_int2), + MSM_PIN_FUNCTION(sensor_int3), + MSM_PIN_FUNCTION(sensor_rst), + MSM_PIN_FUNCTION(ssbi1), + MSM_PIN_FUNCTION(ssbi2), + MSM_PIN_FUNCTION(touch_rst), + MSM_PIN_FUNCTION(ts_int), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(wlan_en1) }; static const struct msm_pingroup mdm9607_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-mdm9615.c b/drivers/pinctrl/qcom/pinctrl-mdm9615.c index 24a4e439edd4..0a2ae383d3d5 100644 --- a/drivers/pinctrl/qcom/pinctrl-mdm9615.c +++ b/drivers/pinctrl/qcom/pinctrl-mdm9615.c @@ -8,7 +8,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinmux.h> #include "pinctrl-msm.h" @@ -195,31 +194,24 @@ DECLARE_MSM_GPIO_PINS(85); DECLARE_MSM_GPIO_PINS(86); DECLARE_MSM_GPIO_PINS(87); -#define FUNCTION(fname) \ - [MSM_MUX_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ - MSM_MUX_gpio, \ - MSM_MUX_##f1, \ - MSM_MUX_##f2, \ - MSM_MUX_##f3, \ - MSM_MUX_##f4, \ - MSM_MUX_##f5, \ - MSM_MUX_##f6, \ - MSM_MUX_##f7, \ - MSM_MUX_##f8, \ - MSM_MUX_##f9, \ - MSM_MUX_##f10, \ - MSM_MUX_##f11 \ + msm_mux_gpio, \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7, \ + msm_mux_##f8, \ + msm_mux_##f9, \ + msm_mux_##f10, \ + msm_mux_##f11 \ }, \ .nfuncs = 12, \ .ctl_reg = 0x1000 + 0x10 * id, \ @@ -245,19 +237,19 @@ DECLARE_MSM_GPIO_PINS(87); } enum mdm9615_functions { - MSM_MUX_gpio, - MSM_MUX_gsbi2_i2c, - MSM_MUX_gsbi3, - MSM_MUX_gsbi4, - MSM_MUX_gsbi5_i2c, - MSM_MUX_gsbi5_uart, - MSM_MUX_sdc2, - MSM_MUX_ebi2_lcdc, - MSM_MUX_ps_hold, - MSM_MUX_prim_audio, - MSM_MUX_sec_audio, - MSM_MUX_cdc_mclk, - MSM_MUX_NA, + msm_mux_gpio, + msm_mux_gsbi2_i2c, + msm_mux_gsbi3, + msm_mux_gsbi4, + msm_mux_gsbi5_i2c, + msm_mux_gsbi5_uart, + msm_mux_sdc2, + msm_mux_ebi2_lcdc, + msm_mux_ps_hold, + msm_mux_prim_audio, + msm_mux_sec_audio, + msm_mux_cdc_mclk, + msm_mux_NA, }; static const char * const gpio_groups[] = { @@ -320,19 +312,19 @@ static const char * const cdc_mclk_groups[] = { "gpio24", }; -static const struct msm_function mdm9615_functions[] = { - FUNCTION(gpio), - FUNCTION(gsbi2_i2c), - FUNCTION(gsbi3), - FUNCTION(gsbi4), - FUNCTION(gsbi5_i2c), - FUNCTION(gsbi5_uart), - FUNCTION(sdc2), - FUNCTION(ebi2_lcdc), - FUNCTION(ps_hold), - FUNCTION(prim_audio), - FUNCTION(sec_audio), - FUNCTION(cdc_mclk), +static const struct pinfunction mdm9615_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gsbi2_i2c), + MSM_PIN_FUNCTION(gsbi3), + MSM_PIN_FUNCTION(gsbi4), + MSM_PIN_FUNCTION(gsbi5_i2c), + MSM_PIN_FUNCTION(gsbi5_uart), + MSM_PIN_FUNCTION(sdc2), + MSM_PIN_FUNCTION(ebi2_lcdc), + MSM_PIN_FUNCTION(ps_hold), + MSM_PIN_FUNCTION(prim_audio), + MSM_PIN_FUNCTION(sec_audio), + MSM_PIN_FUNCTION(cdc_mclk), }; static const struct msm_pingroup mdm9615_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index c5f52d4f7781..2585ef2b2793 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -23,7 +23,6 @@ #include <linux/pinctrl/machine.h> #include <linux/pinctrl/pinconf-generic.h> #include <linux/pinctrl/pinconf.h> -#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinmux.h> #include <linux/soc/qcom/irq.h> @@ -121,7 +120,7 @@ static const char *msm_get_group_name(struct pinctrl_dev *pctldev, { struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); - return pctrl->soc->groups[group].name; + return pctrl->soc->groups[group].grp.name; } static int msm_get_group_pins(struct pinctrl_dev *pctldev, @@ -131,8 +130,8 @@ static int msm_get_group_pins(struct pinctrl_dev *pctldev, { struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); - *pins = pctrl->soc->groups[group].pins; - *num_pins = pctrl->soc->groups[group].npins; + *pins = pctrl->soc->groups[group].grp.pins; + *num_pins = pctrl->soc->groups[group].grp.npins; return 0; } @@ -706,11 +705,11 @@ static void msm_gpio_dbg_show_one(struct seq_file *s, val = !!(io_reg & BIT(g->in_bit)); if (egpio_enable) { - seq_printf(s, " %-8s: egpio\n", g->name); + seq_printf(s, " %-8s: egpio\n", g->grp.name); return; } - seq_printf(s, " %-8s: %-3s", g->name, is_out ? "out" : "in"); + seq_printf(s, " %-8s: %-3s", g->grp.name, is_out ? "out" : "in"); seq_printf(s, " %-4s func%d", val ? "high" : "low", func); seq_printf(s, " %dmA", msm_regval_to_drive(drive)); if (pctrl->soc->pull_no_keeper) @@ -1442,7 +1441,7 @@ static void msm_ps_hold_poweroff(void) static void msm_pinctrl_setup_pm_reset(struct msm_pinctrl *pctrl) { int i; - const struct msm_function *func = pctrl->soc->functions; + const struct pinfunction *func = pctrl->soc->functions; for (i = 0; i < pctrl->soc->nfunctions; i++) if (!strcmp(func[i].name, "ps_hold")) { diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h index 985eceda2517..5e4410bed823 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.h +++ b/drivers/pinctrl/qcom/pinctrl-msm.h @@ -8,27 +8,35 @@ #include <linux/pm.h> #include <linux/types.h> +#include <linux/pinctrl/pinctrl.h> + struct platform_device; struct pinctrl_pin_desc; -/** - * struct msm_function - a pinmux function - * @name: Name of the pinmux function. - * @groups: List of pingroups for this function. - * @ngroups: Number of entries in @groups. - */ -struct msm_function { - const char *name; - const char * const *groups; - unsigned ngroups; -}; +#define APQ_PIN_FUNCTION(fname) \ + [APQ_MUX_##fname] = PINCTRL_PINFUNCTION(#fname, \ + fname##_groups, \ + ARRAY_SIZE(fname##_groups)) + +#define IPQ_PIN_FUNCTION(fname) \ + [IPQ_MUX_##fname] = PINCTRL_PINFUNCTION(#fname, \ + fname##_groups, \ + ARRAY_SIZE(fname##_groups)) + +#define MSM_PIN_FUNCTION(fname) \ + [msm_mux_##fname] = PINCTRL_PINFUNCTION(#fname, \ + fname##_groups, \ + ARRAY_SIZE(fname##_groups)) + +#define QCA_PIN_FUNCTION(fname) \ + [qca_mux_##fname] = PINCTRL_PINFUNCTION(#fname, \ + fname##_groups, \ + ARRAY_SIZE(fname##_groups)) /** * struct msm_pingroup - Qualcomm pingroup definition - * @name: Name of the pingroup. - * @pins: A list of pins assigned to this pingroup. - * @npins: Number of entries in @pins. + * @grp: Generic data of the pin group (name and pins) * @funcs: A list of pinmux functions that can be selected for * this group. The index of the selected function is used * for programming the function selector. @@ -61,9 +69,7 @@ struct msm_function { * otherwise 1. */ struct msm_pingroup { - const char *name; - const unsigned *pins; - unsigned npins; + struct pingroup grp; unsigned *funcs; unsigned nfuncs; @@ -138,7 +144,7 @@ struct msm_gpio_wakeirq_map { struct msm_pinctrl_soc_data { const struct pinctrl_pin_desc *pins; unsigned npins; - const struct msm_function *functions; + const struct pinfunction *functions; unsigned nfunctions; const struct msm_pingroup *groups; unsigned ngroups; diff --git a/drivers/pinctrl/qcom/pinctrl-msm8226.c b/drivers/pinctrl/qcom/pinctrl-msm8226.c index 0f05725e0a21..994619840a70 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8226.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8226.c @@ -6,7 +6,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" @@ -263,27 +262,20 @@ static const unsigned int sdc2_clk_pins[] = { 120 }; static const unsigned int sdc2_cmd_pins[] = { 121 }; static const unsigned int sdc2_data_pins[] = { 122 }; -#define FUNCTION(fname) \ - [MSM_MUX_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ - MSM_MUX_gpio, \ - MSM_MUX_##f1, \ - MSM_MUX_##f2, \ - MSM_MUX_##f3, \ - MSM_MUX_##f4, \ - MSM_MUX_##f5, \ - MSM_MUX_##f6, \ - MSM_MUX_##f7 \ + msm_mux_gpio, \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7 \ }, \ .nfuncs = 8, \ .ctl_reg = 0x1000 + 0x10 * id, \ @@ -309,9 +301,9 @@ static const unsigned int sdc2_data_pins[] = { 122 }; #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -338,36 +330,36 @@ static const unsigned int sdc2_data_pins[] = { 122 }; * the pingroup table below. */ enum msm8226_functions { - MSM_MUX_audio_pcm, - MSM_MUX_blsp_i2c1, - MSM_MUX_blsp_i2c2, - MSM_MUX_blsp_i2c3, - MSM_MUX_blsp_i2c4, - MSM_MUX_blsp_i2c5, - MSM_MUX_blsp_spi1, - MSM_MUX_blsp_spi2, - MSM_MUX_blsp_spi3, - MSM_MUX_blsp_spi4, - MSM_MUX_blsp_spi5, - MSM_MUX_blsp_uart1, - MSM_MUX_blsp_uart2, - MSM_MUX_blsp_uart3, - MSM_MUX_blsp_uart4, - MSM_MUX_blsp_uart5, - MSM_MUX_blsp_uim1, - MSM_MUX_blsp_uim2, - MSM_MUX_blsp_uim3, - MSM_MUX_blsp_uim4, - MSM_MUX_blsp_uim5, - MSM_MUX_cam_mclk0, - MSM_MUX_cam_mclk1, - MSM_MUX_cci_i2c0, - MSM_MUX_gp0_clk, - MSM_MUX_gp1_clk, - MSM_MUX_gpio, - MSM_MUX_sdc3, - MSM_MUX_wlan, - MSM_MUX_NA, + msm_mux_audio_pcm, + msm_mux_blsp_i2c1, + msm_mux_blsp_i2c2, + msm_mux_blsp_i2c3, + msm_mux_blsp_i2c4, + msm_mux_blsp_i2c5, + msm_mux_blsp_spi1, + msm_mux_blsp_spi2, + msm_mux_blsp_spi3, + msm_mux_blsp_spi4, + msm_mux_blsp_spi5, + msm_mux_blsp_uart1, + msm_mux_blsp_uart2, + msm_mux_blsp_uart3, + msm_mux_blsp_uart4, + msm_mux_blsp_uart5, + msm_mux_blsp_uim1, + msm_mux_blsp_uim2, + msm_mux_blsp_uim3, + msm_mux_blsp_uim4, + msm_mux_blsp_uim5, + msm_mux_cam_mclk0, + msm_mux_cam_mclk1, + msm_mux_cci_i2c0, + msm_mux_gp0_clk, + msm_mux_gp1_clk, + msm_mux_gpio, + msm_mux_sdc3, + msm_mux_wlan, + msm_mux_NA, }; static const char * const gpio_groups[] = { @@ -460,36 +452,36 @@ static const char * const wlan_groups[] = { "gpio40", "gpio41", "gpio42", "gpio43", "gpio44" }; -static const struct msm_function msm8226_functions[] = { - FUNCTION(audio_pcm), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_i2c5), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uart3), - FUNCTION(blsp_uart4), - FUNCTION(blsp_uart5), - FUNCTION(blsp_uim1), - FUNCTION(blsp_uim2), - FUNCTION(blsp_uim3), - FUNCTION(blsp_uim4), - FUNCTION(blsp_uim5), - FUNCTION(cam_mclk0), - FUNCTION(cam_mclk1), - FUNCTION(cci_i2c0), - FUNCTION(gp0_clk), - FUNCTION(gp1_clk), - FUNCTION(gpio), - FUNCTION(sdc3), - FUNCTION(wlan), +static const struct pinfunction msm8226_functions[] = { + MSM_PIN_FUNCTION(audio_pcm), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_uart3), + MSM_PIN_FUNCTION(blsp_uart4), + MSM_PIN_FUNCTION(blsp_uart5), + MSM_PIN_FUNCTION(blsp_uim1), + MSM_PIN_FUNCTION(blsp_uim2), + MSM_PIN_FUNCTION(blsp_uim3), + MSM_PIN_FUNCTION(blsp_uim4), + MSM_PIN_FUNCTION(blsp_uim5), + MSM_PIN_FUNCTION(cam_mclk0), + MSM_PIN_FUNCTION(cam_mclk1), + MSM_PIN_FUNCTION(cci_i2c0), + MSM_PIN_FUNCTION(gp0_clk), + MSM_PIN_FUNCTION(gp1_clk), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(sdc3), + MSM_PIN_FUNCTION(wlan), }; static const struct msm_pingroup msm8226_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-msm8660.c b/drivers/pinctrl/qcom/pinctrl-msm8660.c index 16e562eaad17..999a5f867eb5 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8660.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8660.c @@ -6,7 +6,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" @@ -375,27 +374,20 @@ static const unsigned int sdc3_clk_pins[] = { 176 }; static const unsigned int sdc3_cmd_pins[] = { 177 }; static const unsigned int sdc3_data_pins[] = { 178 }; -#define FUNCTION(fname) \ - [MSM_MUX_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ - MSM_MUX_gpio, \ - MSM_MUX_##f1, \ - MSM_MUX_##f2, \ - MSM_MUX_##f3, \ - MSM_MUX_##f4, \ - MSM_MUX_##f5, \ - MSM_MUX_##f6, \ - MSM_MUX_##f7, \ + msm_mux_gpio, \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7, \ }, \ .nfuncs = 8, \ .ctl_reg = 0x1000 + 0x10 * id, \ @@ -422,9 +414,9 @@ static const unsigned int sdc3_data_pins[] = { 178 }; #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -447,60 +439,60 @@ static const unsigned int sdc3_data_pins[] = { 178 }; } enum msm8660_functions { - MSM_MUX_gpio, - MSM_MUX_cam_mclk, - MSM_MUX_dsub, - MSM_MUX_ext_gps, - MSM_MUX_gp_clk_0a, - MSM_MUX_gp_clk_0b, - MSM_MUX_gp_clk_1a, - MSM_MUX_gp_clk_1b, - MSM_MUX_gp_clk_2a, - MSM_MUX_gp_clk_2b, - MSM_MUX_gp_mn, - MSM_MUX_gsbi1, - MSM_MUX_gsbi1_spi_cs1_n, - MSM_MUX_gsbi1_spi_cs2a_n, - MSM_MUX_gsbi1_spi_cs2b_n, - MSM_MUX_gsbi1_spi_cs3_n, - MSM_MUX_gsbi2, - MSM_MUX_gsbi2_spi_cs1_n, - MSM_MUX_gsbi2_spi_cs2_n, - MSM_MUX_gsbi2_spi_cs3_n, - MSM_MUX_gsbi3, - MSM_MUX_gsbi3_spi_cs1_n, - MSM_MUX_gsbi3_spi_cs2_n, - MSM_MUX_gsbi3_spi_cs3_n, - MSM_MUX_gsbi4, - MSM_MUX_gsbi5, - MSM_MUX_gsbi6, - MSM_MUX_gsbi7, - MSM_MUX_gsbi8, - MSM_MUX_gsbi9, - MSM_MUX_gsbi10, - MSM_MUX_gsbi11, - MSM_MUX_gsbi12, - MSM_MUX_hdmi, - MSM_MUX_i2s, - MSM_MUX_lcdc, - MSM_MUX_mdp_vsync, - MSM_MUX_mi2s, - MSM_MUX_pcm, - MSM_MUX_ps_hold, - MSM_MUX_sdc1, - MSM_MUX_sdc2, - MSM_MUX_sdc5, - MSM_MUX_tsif1, - MSM_MUX_tsif2, - MSM_MUX_usb_fs1, - MSM_MUX_usb_fs1_oe_n, - MSM_MUX_usb_fs2, - MSM_MUX_usb_fs2_oe_n, - MSM_MUX_vfe, - MSM_MUX_vsens_alarm, - MSM_MUX_ebi2cs, - MSM_MUX_ebi2, - MSM_MUX__, + msm_mux_gpio, + msm_mux_cam_mclk, + msm_mux_dsub, + msm_mux_ext_gps, + msm_mux_gp_clk_0a, + msm_mux_gp_clk_0b, + msm_mux_gp_clk_1a, + msm_mux_gp_clk_1b, + msm_mux_gp_clk_2a, + msm_mux_gp_clk_2b, + msm_mux_gp_mn, + msm_mux_gsbi1, + msm_mux_gsbi1_spi_cs1_n, + msm_mux_gsbi1_spi_cs2a_n, + msm_mux_gsbi1_spi_cs2b_n, + msm_mux_gsbi1_spi_cs3_n, + msm_mux_gsbi2, + msm_mux_gsbi2_spi_cs1_n, + msm_mux_gsbi2_spi_cs2_n, + msm_mux_gsbi2_spi_cs3_n, + msm_mux_gsbi3, + msm_mux_gsbi3_spi_cs1_n, + msm_mux_gsbi3_spi_cs2_n, + msm_mux_gsbi3_spi_cs3_n, + msm_mux_gsbi4, + msm_mux_gsbi5, + msm_mux_gsbi6, + msm_mux_gsbi7, + msm_mux_gsbi8, + msm_mux_gsbi9, + msm_mux_gsbi10, + msm_mux_gsbi11, + msm_mux_gsbi12, + msm_mux_hdmi, + msm_mux_i2s, + msm_mux_lcdc, + msm_mux_mdp_vsync, + msm_mux_mi2s, + msm_mux_pcm, + msm_mux_ps_hold, + msm_mux_sdc1, + msm_mux_sdc2, + msm_mux_sdc5, + msm_mux_tsif1, + msm_mux_tsif2, + msm_mux_usb_fs1, + msm_mux_usb_fs1_oe_n, + msm_mux_usb_fs2, + msm_mux_usb_fs2_oe_n, + msm_mux_vfe, + msm_mux_vsens_alarm, + msm_mux_ebi2cs, + msm_mux_ebi2, + msm_mux__, }; static const char * const gpio_groups[] = { @@ -721,60 +713,60 @@ static const char * const ebi2_groups[] = { "gpio158", /* busy */ }; -static const struct msm_function msm8660_functions[] = { - FUNCTION(gpio), - FUNCTION(cam_mclk), - FUNCTION(dsub), - FUNCTION(ext_gps), - FUNCTION(gp_clk_0a), - FUNCTION(gp_clk_0b), - FUNCTION(gp_clk_1a), - FUNCTION(gp_clk_1b), - FUNCTION(gp_clk_2a), - FUNCTION(gp_clk_2b), - FUNCTION(gp_mn), - FUNCTION(gsbi1), - FUNCTION(gsbi1_spi_cs1_n), - FUNCTION(gsbi1_spi_cs2a_n), - FUNCTION(gsbi1_spi_cs2b_n), - FUNCTION(gsbi1_spi_cs3_n), - FUNCTION(gsbi2), - FUNCTION(gsbi2_spi_cs1_n), - FUNCTION(gsbi2_spi_cs2_n), - FUNCTION(gsbi2_spi_cs3_n), - FUNCTION(gsbi3), - FUNCTION(gsbi3_spi_cs1_n), - FUNCTION(gsbi3_spi_cs2_n), - FUNCTION(gsbi3_spi_cs3_n), - FUNCTION(gsbi4), - FUNCTION(gsbi5), - FUNCTION(gsbi6), - FUNCTION(gsbi7), - FUNCTION(gsbi8), - FUNCTION(gsbi9), - FUNCTION(gsbi10), - FUNCTION(gsbi11), - FUNCTION(gsbi12), - FUNCTION(hdmi), - FUNCTION(i2s), - FUNCTION(lcdc), - FUNCTION(mdp_vsync), - FUNCTION(mi2s), - FUNCTION(pcm), - FUNCTION(ps_hold), - FUNCTION(sdc1), - FUNCTION(sdc2), - FUNCTION(sdc5), - FUNCTION(tsif1), - FUNCTION(tsif2), - FUNCTION(usb_fs1), - FUNCTION(usb_fs1_oe_n), - FUNCTION(usb_fs2), - FUNCTION(usb_fs2_oe_n), - FUNCTION(vfe), - FUNCTION(vsens_alarm), - FUNCTION(ebi2cs), /* for EBI2 chip selects */ - FUNCTION(ebi2), /* for general EBI2 pins */ +static const struct pinfunction msm8660_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(dsub), + MSM_PIN_FUNCTION(ext_gps), + MSM_PIN_FUNCTION(gp_clk_0a), + MSM_PIN_FUNCTION(gp_clk_0b), + MSM_PIN_FUNCTION(gp_clk_1a), + MSM_PIN_FUNCTION(gp_clk_1b), + MSM_PIN_FUNCTION(gp_clk_2a), + MSM_PIN_FUNCTION(gp_clk_2b), + MSM_PIN_FUNCTION(gp_mn), + MSM_PIN_FUNCTION(gsbi1), + MSM_PIN_FUNCTION(gsbi1_spi_cs1_n), + MSM_PIN_FUNCTION(gsbi1_spi_cs2a_n), + MSM_PIN_FUNCTION(gsbi1_spi_cs2b_n), + MSM_PIN_FUNCTION(gsbi1_spi_cs3_n), + MSM_PIN_FUNCTION(gsbi2), + MSM_PIN_FUNCTION(gsbi2_spi_cs1_n), + MSM_PIN_FUNCTION(gsbi2_spi_cs2_n), + MSM_PIN_FUNCTION(gsbi2_spi_cs3_n), + MSM_PIN_FUNCTION(gsbi3), + MSM_PIN_FUNCTION(gsbi3_spi_cs1_n), + MSM_PIN_FUNCTION(gsbi3_spi_cs2_n), + MSM_PIN_FUNCTION(gsbi3_spi_cs3_n), + MSM_PIN_FUNCTION(gsbi4), + MSM_PIN_FUNCTION(gsbi5), + MSM_PIN_FUNCTION(gsbi6), + MSM_PIN_FUNCTION(gsbi7), + MSM_PIN_FUNCTION(gsbi8), + MSM_PIN_FUNCTION(gsbi9), + MSM_PIN_FUNCTION(gsbi10), + MSM_PIN_FUNCTION(gsbi11), + MSM_PIN_FUNCTION(gsbi12), + MSM_PIN_FUNCTION(hdmi), + MSM_PIN_FUNCTION(i2s), + MSM_PIN_FUNCTION(lcdc), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mi2s), + MSM_PIN_FUNCTION(pcm), + MSM_PIN_FUNCTION(ps_hold), + MSM_PIN_FUNCTION(sdc1), + MSM_PIN_FUNCTION(sdc2), + MSM_PIN_FUNCTION(sdc5), + MSM_PIN_FUNCTION(tsif1), + MSM_PIN_FUNCTION(tsif2), + MSM_PIN_FUNCTION(usb_fs1), + MSM_PIN_FUNCTION(usb_fs1_oe_n), + MSM_PIN_FUNCTION(usb_fs2), + MSM_PIN_FUNCTION(usb_fs2_oe_n), + MSM_PIN_FUNCTION(vfe), + MSM_PIN_FUNCTION(vsens_alarm), + MSM_PIN_FUNCTION(ebi2cs), /* for EBI2 chip selects */ + MSM_PIN_FUNCTION(ebi2), /* for general EBI2 pins */ }; static const struct msm_pingroup msm8660_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-msm8909.c b/drivers/pinctrl/qcom/pinctrl-msm8909.c index 6dd15b910632..756856d20d6b 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8909.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8909.c @@ -7,23 +7,15 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, \ msm_mux_##f1, \ @@ -60,9 +52,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -643,130 +635,130 @@ static const char * const wcss_wlan_groups[] = { "gpio40", "gpio41", "gpio42", "gpio43", "gpio44" }; -static const struct msm_function msm8909_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(atest_bbrx0), - FUNCTION(atest_bbrx1), - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(atest_combodac), - FUNCTION(atest_gpsadc0), - FUNCTION(atest_gpsadc1), - FUNCTION(atest_wlan0), - FUNCTION(atest_wlan1), - FUNCTION(bimc_dte0), - FUNCTION(bimc_dte1), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_i2c5), - FUNCTION(blsp_i2c6), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi1_cs1), - FUNCTION(blsp_spi1_cs2), - FUNCTION(blsp_spi1_cs3), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi2_cs1), - FUNCTION(blsp_spi2_cs2), - FUNCTION(blsp_spi2_cs3), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi3_cs1), - FUNCTION(blsp_spi3_cs2), - FUNCTION(blsp_spi3_cs3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_spi6), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uim1), - FUNCTION(blsp_uim2), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cdc_pdm0), - FUNCTION(dbg_out), - FUNCTION(dmic0_clk), - FUNCTION(dmic0_data), - FUNCTION(ebi0_wrcdc), - FUNCTION(ebi2_a), - FUNCTION(ebi2_lcd), - FUNCTION(ext_lpass), - FUNCTION(gcc_gp1_clk_a), - FUNCTION(gcc_gp1_clk_b), - FUNCTION(gcc_gp2_clk_a), - FUNCTION(gcc_gp2_clk_b), - FUNCTION(gcc_gp3_clk_a), - FUNCTION(gcc_gp3_clk_b), - FUNCTION(gcc_plltest), - FUNCTION(gpio), - FUNCTION(gsm0_tx), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(m_voc), - FUNCTION(mdp_vsync), - FUNCTION(modem_tsync), - FUNCTION(nav_pps), - FUNCTION(nav_tsync), - FUNCTION(pa_indicator), - FUNCTION(pbs0), - FUNCTION(pbs1), - FUNCTION(pbs2), - FUNCTION(pri_mi2s_data0_a), - FUNCTION(pri_mi2s_data0_b), - FUNCTION(pri_mi2s_data1_a), - FUNCTION(pri_mi2s_data1_b), - FUNCTION(pri_mi2s_mclk_a), - FUNCTION(pri_mi2s_mclk_b), - FUNCTION(pri_mi2s_sck_a), - FUNCTION(pri_mi2s_sck_b), - FUNCTION(pri_mi2s_ws_a), - FUNCTION(pri_mi2s_ws_b), - FUNCTION(prng_rosc), - FUNCTION(pwr_crypto_enabled_a), - FUNCTION(pwr_crypto_enabled_b), - FUNCTION(pwr_modem_enabled_a), - FUNCTION(pwr_modem_enabled_b), - FUNCTION(pwr_nav_enabled_a), - FUNCTION(pwr_nav_enabled_b), - FUNCTION(qdss_cti_trig_in_a0), - FUNCTION(qdss_cti_trig_in_a1), - FUNCTION(qdss_cti_trig_in_b0), - FUNCTION(qdss_cti_trig_in_b1), - FUNCTION(qdss_cti_trig_out_a0), - FUNCTION(qdss_cti_trig_out_a1), - FUNCTION(qdss_cti_trig_out_b0), - FUNCTION(qdss_cti_trig_out_b1), - FUNCTION(qdss_traceclk_a), - FUNCTION(qdss_tracectl_a), - FUNCTION(qdss_tracedata_a), - FUNCTION(qdss_tracedata_b), - FUNCTION(sd_write), - FUNCTION(sec_mi2s), - FUNCTION(smb_int), - FUNCTION(ssbi0), - FUNCTION(ssbi1), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(uim3_clk), - FUNCTION(uim3_data), - FUNCTION(uim3_present), - FUNCTION(uim3_reset), - FUNCTION(uim_batt), - FUNCTION(wcss_bt), - FUNCTION(wcss_fm), - FUNCTION(wcss_wlan), +static const struct pinfunction msm8909_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(atest_bbrx0), + MSM_PIN_FUNCTION(atest_bbrx1), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(atest_combodac), + MSM_PIN_FUNCTION(atest_gpsadc0), + MSM_PIN_FUNCTION(atest_gpsadc1), + MSM_PIN_FUNCTION(atest_wlan0), + MSM_PIN_FUNCTION(atest_wlan1), + MSM_PIN_FUNCTION(bimc_dte0), + MSM_PIN_FUNCTION(bimc_dte1), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(blsp_i2c6), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi1_cs1), + MSM_PIN_FUNCTION(blsp_spi1_cs2), + MSM_PIN_FUNCTION(blsp_spi1_cs3), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi2_cs1), + MSM_PIN_FUNCTION(blsp_spi2_cs2), + MSM_PIN_FUNCTION(blsp_spi2_cs3), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi3_cs1), + MSM_PIN_FUNCTION(blsp_spi3_cs2), + MSM_PIN_FUNCTION(blsp_spi3_cs3), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(blsp_spi6), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_uim1), + MSM_PIN_FUNCTION(blsp_uim2), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cdc_pdm0), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(dmic0_clk), + MSM_PIN_FUNCTION(dmic0_data), + MSM_PIN_FUNCTION(ebi0_wrcdc), + MSM_PIN_FUNCTION(ebi2_a), + MSM_PIN_FUNCTION(ebi2_lcd), + MSM_PIN_FUNCTION(ext_lpass), + MSM_PIN_FUNCTION(gcc_gp1_clk_a), + MSM_PIN_FUNCTION(gcc_gp1_clk_b), + MSM_PIN_FUNCTION(gcc_gp2_clk_a), + MSM_PIN_FUNCTION(gcc_gp2_clk_b), + MSM_PIN_FUNCTION(gcc_gp3_clk_a), + MSM_PIN_FUNCTION(gcc_gp3_clk_b), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gsm0_tx), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(modem_tsync), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(nav_tsync), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pbs0), + MSM_PIN_FUNCTION(pbs1), + MSM_PIN_FUNCTION(pbs2), + MSM_PIN_FUNCTION(pri_mi2s_data0_a), + MSM_PIN_FUNCTION(pri_mi2s_data0_b), + MSM_PIN_FUNCTION(pri_mi2s_data1_a), + MSM_PIN_FUNCTION(pri_mi2s_data1_b), + MSM_PIN_FUNCTION(pri_mi2s_mclk_a), + MSM_PIN_FUNCTION(pri_mi2s_mclk_b), + MSM_PIN_FUNCTION(pri_mi2s_sck_a), + MSM_PIN_FUNCTION(pri_mi2s_sck_b), + MSM_PIN_FUNCTION(pri_mi2s_ws_a), + MSM_PIN_FUNCTION(pri_mi2s_ws_b), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(pwr_crypto_enabled_a), + MSM_PIN_FUNCTION(pwr_crypto_enabled_b), + MSM_PIN_FUNCTION(pwr_modem_enabled_a), + MSM_PIN_FUNCTION(pwr_modem_enabled_b), + MSM_PIN_FUNCTION(pwr_nav_enabled_a), + MSM_PIN_FUNCTION(pwr_nav_enabled_b), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b1), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(smb_int), + MSM_PIN_FUNCTION(ssbi0), + MSM_PIN_FUNCTION(ssbi1), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(uim3_clk), + MSM_PIN_FUNCTION(uim3_data), + MSM_PIN_FUNCTION(uim3_present), + MSM_PIN_FUNCTION(uim3_reset), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(wcss_bt), + MSM_PIN_FUNCTION(wcss_fm), + MSM_PIN_FUNCTION(wcss_wlan), }; static const struct msm_pingroup msm8909_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-msm8916.c b/drivers/pinctrl/qcom/pinctrl-msm8916.c index bf68913ba821..cea5c54f92fe 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8916.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8916.c @@ -6,7 +6,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" @@ -286,29 +285,22 @@ static const unsigned int qdsd_data1_pins[] = { 131 }; static const unsigned int qdsd_data2_pins[] = { 132 }; static const unsigned int qdsd_data3_pins[] = { 133 }; -#define FUNCTION(fname) \ - [MSM_MUX_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ - MSM_MUX_gpio, \ - MSM_MUX_##f1, \ - MSM_MUX_##f2, \ - MSM_MUX_##f3, \ - MSM_MUX_##f4, \ - MSM_MUX_##f5, \ - MSM_MUX_##f6, \ - MSM_MUX_##f7, \ - MSM_MUX_##f8, \ - MSM_MUX_##f9 \ + msm_mux_gpio, \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7, \ + msm_mux_##f8, \ + msm_mux_##f9 \ }, \ .nfuncs = 10, \ .ctl_reg = 0x1000 * id, \ @@ -334,9 +326,9 @@ static const unsigned int qdsd_data3_pins[] = { 133 }; #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -359,135 +351,135 @@ static const unsigned int qdsd_data3_pins[] = { 133 }; } enum msm8916_functions { - MSM_MUX_adsp_ext, - MSM_MUX_alsp_int, - MSM_MUX_atest_bbrx0, - MSM_MUX_atest_bbrx1, - MSM_MUX_atest_char, - MSM_MUX_atest_char0, - MSM_MUX_atest_char1, - MSM_MUX_atest_char2, - MSM_MUX_atest_char3, - MSM_MUX_atest_combodac, - MSM_MUX_atest_gpsadc0, - MSM_MUX_atest_gpsadc1, - MSM_MUX_atest_tsens, - MSM_MUX_atest_wlan0, - MSM_MUX_atest_wlan1, - MSM_MUX_backlight_en, - MSM_MUX_bimc_dte0, - MSM_MUX_bimc_dte1, - MSM_MUX_blsp_i2c1, - MSM_MUX_blsp_i2c2, - MSM_MUX_blsp_i2c3, - MSM_MUX_blsp_i2c4, - MSM_MUX_blsp_i2c5, - MSM_MUX_blsp_i2c6, - MSM_MUX_blsp_spi1, - MSM_MUX_blsp_spi1_cs1, - MSM_MUX_blsp_spi1_cs2, - MSM_MUX_blsp_spi1_cs3, - MSM_MUX_blsp_spi2, - MSM_MUX_blsp_spi2_cs1, - MSM_MUX_blsp_spi2_cs2, - MSM_MUX_blsp_spi2_cs3, - MSM_MUX_blsp_spi3, - MSM_MUX_blsp_spi3_cs1, - MSM_MUX_blsp_spi3_cs2, - MSM_MUX_blsp_spi3_cs3, - MSM_MUX_blsp_spi4, - MSM_MUX_blsp_spi5, - MSM_MUX_blsp_spi6, - MSM_MUX_blsp_uart1, - MSM_MUX_blsp_uart2, - MSM_MUX_blsp_uim1, - MSM_MUX_blsp_uim2, - MSM_MUX_cam1_rst, - MSM_MUX_cam1_standby, - MSM_MUX_cam_mclk0, - MSM_MUX_cam_mclk1, - MSM_MUX_cci_async, - MSM_MUX_cci_i2c, - MSM_MUX_cci_timer0, - MSM_MUX_cci_timer1, - MSM_MUX_cci_timer2, - MSM_MUX_cdc_pdm0, - MSM_MUX_codec_mad, - MSM_MUX_dbg_out, - MSM_MUX_display_5v, - MSM_MUX_dmic0_clk, - MSM_MUX_dmic0_data, - MSM_MUX_dsi_rst, - MSM_MUX_ebi0_wrcdc, - MSM_MUX_euro_us, - MSM_MUX_ext_lpass, - MSM_MUX_flash_strobe, - MSM_MUX_gcc_gp1_clk_a, - MSM_MUX_gcc_gp1_clk_b, - MSM_MUX_gcc_gp2_clk_a, - MSM_MUX_gcc_gp2_clk_b, - MSM_MUX_gcc_gp3_clk_a, - MSM_MUX_gcc_gp3_clk_b, - MSM_MUX_gpio, - MSM_MUX_gsm0_tx0, - MSM_MUX_gsm0_tx1, - MSM_MUX_gsm1_tx0, - MSM_MUX_gsm1_tx1, - MSM_MUX_gyro_accl, - MSM_MUX_kpsns0, - MSM_MUX_kpsns1, - MSM_MUX_kpsns2, - MSM_MUX_ldo_en, - MSM_MUX_ldo_update, - MSM_MUX_mag_int, - MSM_MUX_mdp_vsync, - MSM_MUX_modem_tsync, - MSM_MUX_m_voc, - MSM_MUX_nav_pps, - MSM_MUX_nav_tsync, - MSM_MUX_pa_indicator, - MSM_MUX_pbs0, - MSM_MUX_pbs1, - MSM_MUX_pbs2, - MSM_MUX_pri_mi2s, - MSM_MUX_pri_mi2s_ws, - MSM_MUX_prng_rosc, - MSM_MUX_pwr_crypto_enabled_a, - MSM_MUX_pwr_crypto_enabled_b, - MSM_MUX_pwr_modem_enabled_a, - MSM_MUX_pwr_modem_enabled_b, - MSM_MUX_pwr_nav_enabled_a, - MSM_MUX_pwr_nav_enabled_b, - MSM_MUX_qdss_ctitrig_in_a0, - MSM_MUX_qdss_ctitrig_in_a1, - MSM_MUX_qdss_ctitrig_in_b0, - MSM_MUX_qdss_ctitrig_in_b1, - MSM_MUX_qdss_ctitrig_out_a0, - MSM_MUX_qdss_ctitrig_out_a1, - MSM_MUX_qdss_ctitrig_out_b0, - MSM_MUX_qdss_ctitrig_out_b1, - MSM_MUX_qdss_traceclk_a, - MSM_MUX_qdss_traceclk_b, - MSM_MUX_qdss_tracectl_a, - MSM_MUX_qdss_tracectl_b, - MSM_MUX_qdss_tracedata_a, - MSM_MUX_qdss_tracedata_b, - MSM_MUX_reset_n, - MSM_MUX_sd_card, - MSM_MUX_sd_write, - MSM_MUX_sec_mi2s, - MSM_MUX_smb_int, - MSM_MUX_ssbi_wtr0, - MSM_MUX_ssbi_wtr1, - MSM_MUX_uim1, - MSM_MUX_uim2, - MSM_MUX_uim3, - MSM_MUX_uim_batt, - MSM_MUX_wcss_bt, - MSM_MUX_wcss_fm, - MSM_MUX_wcss_wlan, - MSM_MUX_webcam1_rst, - MSM_MUX_NA, + msm_mux_adsp_ext, + msm_mux_alsp_int, + msm_mux_atest_bbrx0, + msm_mux_atest_bbrx1, + msm_mux_atest_char, + msm_mux_atest_char0, + msm_mux_atest_char1, + msm_mux_atest_char2, + msm_mux_atest_char3, + msm_mux_atest_combodac, + msm_mux_atest_gpsadc0, + msm_mux_atest_gpsadc1, + msm_mux_atest_tsens, + msm_mux_atest_wlan0, + msm_mux_atest_wlan1, + msm_mux_backlight_en, + msm_mux_bimc_dte0, + msm_mux_bimc_dte1, + msm_mux_blsp_i2c1, + msm_mux_blsp_i2c2, + msm_mux_blsp_i2c3, + msm_mux_blsp_i2c4, + msm_mux_blsp_i2c5, + msm_mux_blsp_i2c6, + msm_mux_blsp_spi1, + msm_mux_blsp_spi1_cs1, + msm_mux_blsp_spi1_cs2, + msm_mux_blsp_spi1_cs3, + msm_mux_blsp_spi2, + msm_mux_blsp_spi2_cs1, + msm_mux_blsp_spi2_cs2, + msm_mux_blsp_spi2_cs3, + msm_mux_blsp_spi3, + msm_mux_blsp_spi3_cs1, + msm_mux_blsp_spi3_cs2, + msm_mux_blsp_spi3_cs3, + msm_mux_blsp_spi4, + msm_mux_blsp_spi5, + msm_mux_blsp_spi6, + msm_mux_blsp_uart1, + msm_mux_blsp_uart2, + msm_mux_blsp_uim1, + msm_mux_blsp_uim2, + msm_mux_cam1_rst, + msm_mux_cam1_standby, + msm_mux_cam_mclk0, + msm_mux_cam_mclk1, + msm_mux_cci_async, + msm_mux_cci_i2c, + msm_mux_cci_timer0, + msm_mux_cci_timer1, + msm_mux_cci_timer2, + msm_mux_cdc_pdm0, + msm_mux_codec_mad, + msm_mux_dbg_out, + msm_mux_display_5v, + msm_mux_dmic0_clk, + msm_mux_dmic0_data, + msm_mux_dsi_rst, + msm_mux_ebi0_wrcdc, + msm_mux_euro_us, + msm_mux_ext_lpass, + msm_mux_flash_strobe, + msm_mux_gcc_gp1_clk_a, + msm_mux_gcc_gp1_clk_b, + msm_mux_gcc_gp2_clk_a, + msm_mux_gcc_gp2_clk_b, + msm_mux_gcc_gp3_clk_a, + msm_mux_gcc_gp3_clk_b, + msm_mux_gpio, + msm_mux_gsm0_tx0, + msm_mux_gsm0_tx1, + msm_mux_gsm1_tx0, + msm_mux_gsm1_tx1, + msm_mux_gyro_accl, + msm_mux_kpsns0, + msm_mux_kpsns1, + msm_mux_kpsns2, + msm_mux_ldo_en, + msm_mux_ldo_update, + msm_mux_mag_int, + msm_mux_mdp_vsync, + msm_mux_modem_tsync, + msm_mux_m_voc, + msm_mux_nav_pps, + msm_mux_nav_tsync, + msm_mux_pa_indicator, + msm_mux_pbs0, + msm_mux_pbs1, + msm_mux_pbs2, + msm_mux_pri_mi2s, + msm_mux_pri_mi2s_ws, + msm_mux_prng_rosc, + msm_mux_pwr_crypto_enabled_a, + msm_mux_pwr_crypto_enabled_b, + msm_mux_pwr_modem_enabled_a, + msm_mux_pwr_modem_enabled_b, + msm_mux_pwr_nav_enabled_a, + msm_mux_pwr_nav_enabled_b, + msm_mux_qdss_ctitrig_in_a0, + msm_mux_qdss_ctitrig_in_a1, + msm_mux_qdss_ctitrig_in_b0, + msm_mux_qdss_ctitrig_in_b1, + msm_mux_qdss_ctitrig_out_a0, + msm_mux_qdss_ctitrig_out_a1, + msm_mux_qdss_ctitrig_out_b0, + msm_mux_qdss_ctitrig_out_b1, + msm_mux_qdss_traceclk_a, + msm_mux_qdss_traceclk_b, + msm_mux_qdss_tracectl_a, + msm_mux_qdss_tracectl_b, + msm_mux_qdss_tracedata_a, + msm_mux_qdss_tracedata_b, + msm_mux_reset_n, + msm_mux_sd_card, + msm_mux_sd_write, + msm_mux_sec_mi2s, + msm_mux_smb_int, + msm_mux_ssbi_wtr0, + msm_mux_ssbi_wtr1, + msm_mux_uim1, + msm_mux_uim2, + msm_mux_uim3, + msm_mux_uim_batt, + msm_mux_wcss_bt, + msm_mux_wcss_fm, + msm_mux_wcss_wlan, + msm_mux_webcam1_rst, + msm_mux_NA, }; static const char * const gpio_groups[] = { @@ -681,135 +673,135 @@ static const char * const wcss_wlan_groups[] = { }; static const char * const webcam1_rst_groups[] = { "gpio28" }; -static const struct msm_function msm8916_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(alsp_int), - FUNCTION(atest_bbrx0), - FUNCTION(atest_bbrx1), - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(atest_combodac), - FUNCTION(atest_gpsadc0), - FUNCTION(atest_gpsadc1), - FUNCTION(atest_tsens), - FUNCTION(atest_wlan0), - FUNCTION(atest_wlan1), - FUNCTION(backlight_en), - FUNCTION(bimc_dte0), - FUNCTION(bimc_dte1), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_i2c5), - FUNCTION(blsp_i2c6), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi1_cs1), - FUNCTION(blsp_spi1_cs2), - FUNCTION(blsp_spi1_cs3), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi2_cs1), - FUNCTION(blsp_spi2_cs2), - FUNCTION(blsp_spi2_cs3), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi3_cs1), - FUNCTION(blsp_spi3_cs2), - FUNCTION(blsp_spi3_cs3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_spi6), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uim1), - FUNCTION(blsp_uim2), - FUNCTION(cam1_rst), - FUNCTION(cam1_standby), - FUNCTION(cam_mclk0), - FUNCTION(cam_mclk1), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cdc_pdm0), - FUNCTION(codec_mad), - FUNCTION(dbg_out), - FUNCTION(display_5v), - FUNCTION(dmic0_clk), - FUNCTION(dmic0_data), - FUNCTION(dsi_rst), - FUNCTION(ebi0_wrcdc), - FUNCTION(euro_us), - FUNCTION(ext_lpass), - FUNCTION(flash_strobe), - FUNCTION(gcc_gp1_clk_a), - FUNCTION(gcc_gp1_clk_b), - FUNCTION(gcc_gp2_clk_a), - FUNCTION(gcc_gp2_clk_b), - FUNCTION(gcc_gp3_clk_a), - FUNCTION(gcc_gp3_clk_b), - FUNCTION(gpio), - FUNCTION(gsm0_tx0), - FUNCTION(gsm0_tx1), - FUNCTION(gsm1_tx0), - FUNCTION(gsm1_tx1), - FUNCTION(gyro_accl), - FUNCTION(kpsns0), - FUNCTION(kpsns1), - FUNCTION(kpsns2), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(mag_int), - FUNCTION(mdp_vsync), - FUNCTION(modem_tsync), - FUNCTION(m_voc), - FUNCTION(nav_pps), - FUNCTION(nav_tsync), - FUNCTION(pa_indicator), - FUNCTION(pbs0), - FUNCTION(pbs1), - FUNCTION(pbs2), - FUNCTION(pri_mi2s), - FUNCTION(pri_mi2s_ws), - FUNCTION(prng_rosc), - FUNCTION(pwr_crypto_enabled_a), - FUNCTION(pwr_crypto_enabled_b), - FUNCTION(pwr_modem_enabled_a), - FUNCTION(pwr_modem_enabled_b), - FUNCTION(pwr_nav_enabled_a), - FUNCTION(pwr_nav_enabled_b), - FUNCTION(qdss_ctitrig_in_a0), - FUNCTION(qdss_ctitrig_in_a1), - FUNCTION(qdss_ctitrig_in_b0), - FUNCTION(qdss_ctitrig_in_b1), - FUNCTION(qdss_ctitrig_out_a0), - FUNCTION(qdss_ctitrig_out_a1), - FUNCTION(qdss_ctitrig_out_b0), - FUNCTION(qdss_ctitrig_out_b1), - FUNCTION(qdss_traceclk_a), - FUNCTION(qdss_traceclk_b), - FUNCTION(qdss_tracectl_a), - FUNCTION(qdss_tracectl_b), - FUNCTION(qdss_tracedata_a), - FUNCTION(qdss_tracedata_b), - FUNCTION(reset_n), - FUNCTION(sd_card), - FUNCTION(sd_write), - FUNCTION(sec_mi2s), - FUNCTION(smb_int), - FUNCTION(ssbi_wtr0), - FUNCTION(ssbi_wtr1), - FUNCTION(uim1), - FUNCTION(uim2), - FUNCTION(uim3), - FUNCTION(uim_batt), - FUNCTION(wcss_bt), - FUNCTION(wcss_fm), - FUNCTION(wcss_wlan), - FUNCTION(webcam1_rst) +static const struct pinfunction msm8916_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(alsp_int), + MSM_PIN_FUNCTION(atest_bbrx0), + MSM_PIN_FUNCTION(atest_bbrx1), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(atest_combodac), + MSM_PIN_FUNCTION(atest_gpsadc0), + MSM_PIN_FUNCTION(atest_gpsadc1), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_wlan0), + MSM_PIN_FUNCTION(atest_wlan1), + MSM_PIN_FUNCTION(backlight_en), + MSM_PIN_FUNCTION(bimc_dte0), + MSM_PIN_FUNCTION(bimc_dte1), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(blsp_i2c6), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi1_cs1), + MSM_PIN_FUNCTION(blsp_spi1_cs2), + MSM_PIN_FUNCTION(blsp_spi1_cs3), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi2_cs1), + MSM_PIN_FUNCTION(blsp_spi2_cs2), + MSM_PIN_FUNCTION(blsp_spi2_cs3), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi3_cs1), + MSM_PIN_FUNCTION(blsp_spi3_cs2), + MSM_PIN_FUNCTION(blsp_spi3_cs3), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(blsp_spi6), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_uim1), + MSM_PIN_FUNCTION(blsp_uim2), + MSM_PIN_FUNCTION(cam1_rst), + MSM_PIN_FUNCTION(cam1_standby), + MSM_PIN_FUNCTION(cam_mclk0), + MSM_PIN_FUNCTION(cam_mclk1), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cdc_pdm0), + MSM_PIN_FUNCTION(codec_mad), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(display_5v), + MSM_PIN_FUNCTION(dmic0_clk), + MSM_PIN_FUNCTION(dmic0_data), + MSM_PIN_FUNCTION(dsi_rst), + MSM_PIN_FUNCTION(ebi0_wrcdc), + MSM_PIN_FUNCTION(euro_us), + MSM_PIN_FUNCTION(ext_lpass), + MSM_PIN_FUNCTION(flash_strobe), + MSM_PIN_FUNCTION(gcc_gp1_clk_a), + MSM_PIN_FUNCTION(gcc_gp1_clk_b), + MSM_PIN_FUNCTION(gcc_gp2_clk_a), + MSM_PIN_FUNCTION(gcc_gp2_clk_b), + MSM_PIN_FUNCTION(gcc_gp3_clk_a), + MSM_PIN_FUNCTION(gcc_gp3_clk_b), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gsm0_tx0), + MSM_PIN_FUNCTION(gsm0_tx1), + MSM_PIN_FUNCTION(gsm1_tx0), + MSM_PIN_FUNCTION(gsm1_tx1), + MSM_PIN_FUNCTION(gyro_accl), + MSM_PIN_FUNCTION(kpsns0), + MSM_PIN_FUNCTION(kpsns1), + MSM_PIN_FUNCTION(kpsns2), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(mag_int), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(modem_tsync), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(nav_tsync), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pbs0), + MSM_PIN_FUNCTION(pbs1), + MSM_PIN_FUNCTION(pbs2), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(pri_mi2s_ws), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(pwr_crypto_enabled_a), + MSM_PIN_FUNCTION(pwr_crypto_enabled_b), + MSM_PIN_FUNCTION(pwr_modem_enabled_a), + MSM_PIN_FUNCTION(pwr_modem_enabled_b), + MSM_PIN_FUNCTION(pwr_nav_enabled_a), + MSM_PIN_FUNCTION(pwr_nav_enabled_b), + MSM_PIN_FUNCTION(qdss_ctitrig_in_a0), + MSM_PIN_FUNCTION(qdss_ctitrig_in_a1), + MSM_PIN_FUNCTION(qdss_ctitrig_in_b0), + MSM_PIN_FUNCTION(qdss_ctitrig_in_b1), + MSM_PIN_FUNCTION(qdss_ctitrig_out_a0), + MSM_PIN_FUNCTION(qdss_ctitrig_out_a1), + MSM_PIN_FUNCTION(qdss_ctitrig_out_b0), + MSM_PIN_FUNCTION(qdss_ctitrig_out_b1), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(reset_n), + MSM_PIN_FUNCTION(sd_card), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(smb_int), + MSM_PIN_FUNCTION(ssbi_wtr0), + MSM_PIN_FUNCTION(ssbi_wtr1), + MSM_PIN_FUNCTION(uim1), + MSM_PIN_FUNCTION(uim2), + MSM_PIN_FUNCTION(uim3), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(wcss_bt), + MSM_PIN_FUNCTION(wcss_fm), + MSM_PIN_FUNCTION(wcss_wlan), + MSM_PIN_FUNCTION(webcam1_rst) }; static const struct msm_pingroup msm8916_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-msm8953.c b/drivers/pinctrl/qcom/pinctrl-msm8953.c index e0c939ff3d54..998351bdfee1 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8953.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8953.c @@ -4,22 +4,14 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -56,9 +48,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -1431,208 +1423,208 @@ static const char * const wsa_irq_groups[] = { "gpio97", }; -static const struct msm_function msm8953_functions[] = { - FUNCTION(accel_int), - FUNCTION(adsp_ext), - FUNCTION(alsp_int), - FUNCTION(atest_bbrx0), - FUNCTION(atest_bbrx1), - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(atest_gpsadc_dtest0_native), - FUNCTION(atest_gpsadc_dtest1_native), - FUNCTION(atest_tsens), - FUNCTION(atest_wlan0), - FUNCTION(atest_wlan1), - FUNCTION(bimc_dte0), - FUNCTION(bimc_dte1), - FUNCTION(blsp1_spi), - FUNCTION(blsp3_spi), - FUNCTION(blsp6_spi), - FUNCTION(blsp7_spi), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_i2c5), - FUNCTION(blsp_i2c6), - FUNCTION(blsp_i2c7), - FUNCTION(blsp_i2c8), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_spi6), - FUNCTION(blsp_spi7), - FUNCTION(blsp_spi8), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uart4), - FUNCTION(blsp_uart5), - FUNCTION(blsp_uart6), - FUNCTION(cam0_ldo), - FUNCTION(cam1_ldo), - FUNCTION(cam1_rst), - FUNCTION(cam1_standby), - FUNCTION(cam2_rst), - FUNCTION(cam2_standby), - FUNCTION(cam3_rst), - FUNCTION(cam3_standby), - FUNCTION(cam_irq), - FUNCTION(cam_mclk), - FUNCTION(cap_int), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cdc_pdm0), - FUNCTION(codec_int1), - FUNCTION(codec_int2), - FUNCTION(codec_reset), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dac_calib0), - FUNCTION(dac_calib1), - FUNCTION(dac_calib10), - FUNCTION(dac_calib11), - FUNCTION(dac_calib12), - FUNCTION(dac_calib13), - FUNCTION(dac_calib14), - FUNCTION(dac_calib15), - FUNCTION(dac_calib16), - FUNCTION(dac_calib17), - FUNCTION(dac_calib18), - FUNCTION(dac_calib19), - FUNCTION(dac_calib2), - FUNCTION(dac_calib20), - FUNCTION(dac_calib21), - FUNCTION(dac_calib22), - FUNCTION(dac_calib23), - FUNCTION(dac_calib24), - FUNCTION(dac_calib25), - FUNCTION(dac_calib3), - FUNCTION(dac_calib4), - FUNCTION(dac_calib5), - FUNCTION(dac_calib6), - FUNCTION(dac_calib7), - FUNCTION(dac_calib8), - FUNCTION(dac_calib9), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(dmic0_clk), - FUNCTION(dmic0_data), - FUNCTION(ebi_cdc), - FUNCTION(ebi_ch0), - FUNCTION(ext_lpass), - FUNCTION(flash_strobe), - FUNCTION(fp_int), - FUNCTION(gcc_gp1_clk_a), - FUNCTION(gcc_gp1_clk_b), - FUNCTION(gcc_gp2_clk_a), - FUNCTION(gcc_gp2_clk_b), - FUNCTION(gcc_gp3_clk_a), - FUNCTION(gcc_gp3_clk_b), - FUNCTION(gcc_plltest), - FUNCTION(gcc_tlmm), - FUNCTION(gpio), - FUNCTION(gsm0_tx), - FUNCTION(gsm1_tx), - FUNCTION(gyro_int), - FUNCTION(hall_int), - FUNCTION(hdmi_int), - FUNCTION(key_focus), - FUNCTION(key_home), - FUNCTION(key_snapshot), - FUNCTION(key_volp), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(lpass_slimbus), - FUNCTION(lpass_slimbus0), - FUNCTION(lpass_slimbus1), - FUNCTION(m_voc), - FUNCTION(mag_int), - FUNCTION(mdp_vsync), - FUNCTION(mipi_dsi0), - FUNCTION(modem_tsync), - FUNCTION(mss_lte), - FUNCTION(nav_pps), - FUNCTION(nav_pps_in_a), - FUNCTION(nav_pps_in_b), - FUNCTION(nav_tsync), - FUNCTION(nfc_disable), - FUNCTION(nfc_dwl), - FUNCTION(nfc_irq), - FUNCTION(ois_sync), - FUNCTION(pa_indicator), - FUNCTION(pbs0), - FUNCTION(pbs1), - FUNCTION(pbs2), - FUNCTION(pressure_int), - FUNCTION(pri_mi2s), - FUNCTION(pri_mi2s_mclk_a), - FUNCTION(pri_mi2s_mclk_b), - FUNCTION(pri_mi2s_ws), - FUNCTION(prng_rosc), - FUNCTION(pwr_crypto_enabled_a), - FUNCTION(pwr_crypto_enabled_b), - FUNCTION(pwr_down), - FUNCTION(pwr_modem_enabled_a), - FUNCTION(pwr_modem_enabled_b), - FUNCTION(pwr_nav_enabled_a), - FUNCTION(pwr_nav_enabled_b), - FUNCTION(qdss_cti_trig_in_a0), - FUNCTION(qdss_cti_trig_in_a1), - FUNCTION(qdss_cti_trig_in_b0), - FUNCTION(qdss_cti_trig_in_b1), - FUNCTION(qdss_cti_trig_out_a0), - FUNCTION(qdss_cti_trig_out_a1), - FUNCTION(qdss_cti_trig_out_b0), - FUNCTION(qdss_cti_trig_out_b1), - FUNCTION(qdss_traceclk_a), - FUNCTION(qdss_traceclk_b), - FUNCTION(qdss_tracectl_a), - FUNCTION(qdss_tracectl_b), - FUNCTION(qdss_tracedata_a), - FUNCTION(qdss_tracedata_b), - FUNCTION(sd_write), - FUNCTION(sdcard_det), - FUNCTION(sec_mi2s), - FUNCTION(sec_mi2s_mclk_a), - FUNCTION(sec_mi2s_mclk_b), - FUNCTION(smb_int), - FUNCTION(ss_switch), - FUNCTION(ssbi_wtr1), - FUNCTION(ts_resout), - FUNCTION(ts_sample), - FUNCTION(ts_xvdd), - FUNCTION(tsens_max), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(uim_batt), - FUNCTION(us_emitter), - FUNCTION(us_euro), - FUNCTION(wcss_bt), - FUNCTION(wcss_fm), - FUNCTION(wcss_wlan), - FUNCTION(wcss_wlan0), - FUNCTION(wcss_wlan1), - FUNCTION(wcss_wlan2), - FUNCTION(wsa_en), - FUNCTION(wsa_io), - FUNCTION(wsa_irq), +static const struct pinfunction msm8953_functions[] = { + MSM_PIN_FUNCTION(accel_int), + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(alsp_int), + MSM_PIN_FUNCTION(atest_bbrx0), + MSM_PIN_FUNCTION(atest_bbrx1), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(atest_gpsadc_dtest0_native), + MSM_PIN_FUNCTION(atest_gpsadc_dtest1_native), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_wlan0), + MSM_PIN_FUNCTION(atest_wlan1), + MSM_PIN_FUNCTION(bimc_dte0), + MSM_PIN_FUNCTION(bimc_dte1), + MSM_PIN_FUNCTION(blsp1_spi), + MSM_PIN_FUNCTION(blsp3_spi), + MSM_PIN_FUNCTION(blsp6_spi), + MSM_PIN_FUNCTION(blsp7_spi), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(blsp_i2c6), + MSM_PIN_FUNCTION(blsp_i2c7), + MSM_PIN_FUNCTION(blsp_i2c8), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(blsp_spi6), + MSM_PIN_FUNCTION(blsp_spi7), + MSM_PIN_FUNCTION(blsp_spi8), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_uart4), + MSM_PIN_FUNCTION(blsp_uart5), + MSM_PIN_FUNCTION(blsp_uart6), + MSM_PIN_FUNCTION(cam0_ldo), + MSM_PIN_FUNCTION(cam1_ldo), + MSM_PIN_FUNCTION(cam1_rst), + MSM_PIN_FUNCTION(cam1_standby), + MSM_PIN_FUNCTION(cam2_rst), + MSM_PIN_FUNCTION(cam2_standby), + MSM_PIN_FUNCTION(cam3_rst), + MSM_PIN_FUNCTION(cam3_standby), + MSM_PIN_FUNCTION(cam_irq), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cap_int), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cdc_pdm0), + MSM_PIN_FUNCTION(codec_int1), + MSM_PIN_FUNCTION(codec_int2), + MSM_PIN_FUNCTION(codec_reset), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dac_calib0), + MSM_PIN_FUNCTION(dac_calib1), + MSM_PIN_FUNCTION(dac_calib10), + MSM_PIN_FUNCTION(dac_calib11), + MSM_PIN_FUNCTION(dac_calib12), + MSM_PIN_FUNCTION(dac_calib13), + MSM_PIN_FUNCTION(dac_calib14), + MSM_PIN_FUNCTION(dac_calib15), + MSM_PIN_FUNCTION(dac_calib16), + MSM_PIN_FUNCTION(dac_calib17), + MSM_PIN_FUNCTION(dac_calib18), + MSM_PIN_FUNCTION(dac_calib19), + MSM_PIN_FUNCTION(dac_calib2), + MSM_PIN_FUNCTION(dac_calib20), + MSM_PIN_FUNCTION(dac_calib21), + MSM_PIN_FUNCTION(dac_calib22), + MSM_PIN_FUNCTION(dac_calib23), + MSM_PIN_FUNCTION(dac_calib24), + MSM_PIN_FUNCTION(dac_calib25), + MSM_PIN_FUNCTION(dac_calib3), + MSM_PIN_FUNCTION(dac_calib4), + MSM_PIN_FUNCTION(dac_calib5), + MSM_PIN_FUNCTION(dac_calib6), + MSM_PIN_FUNCTION(dac_calib7), + MSM_PIN_FUNCTION(dac_calib8), + MSM_PIN_FUNCTION(dac_calib9), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(dmic0_clk), + MSM_PIN_FUNCTION(dmic0_data), + MSM_PIN_FUNCTION(ebi_cdc), + MSM_PIN_FUNCTION(ebi_ch0), + MSM_PIN_FUNCTION(ext_lpass), + MSM_PIN_FUNCTION(flash_strobe), + MSM_PIN_FUNCTION(fp_int), + MSM_PIN_FUNCTION(gcc_gp1_clk_a), + MSM_PIN_FUNCTION(gcc_gp1_clk_b), + MSM_PIN_FUNCTION(gcc_gp2_clk_a), + MSM_PIN_FUNCTION(gcc_gp2_clk_b), + MSM_PIN_FUNCTION(gcc_gp3_clk_a), + MSM_PIN_FUNCTION(gcc_gp3_clk_b), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(gcc_tlmm), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gsm0_tx), + MSM_PIN_FUNCTION(gsm1_tx), + MSM_PIN_FUNCTION(gyro_int), + MSM_PIN_FUNCTION(hall_int), + MSM_PIN_FUNCTION(hdmi_int), + MSM_PIN_FUNCTION(key_focus), + MSM_PIN_FUNCTION(key_home), + MSM_PIN_FUNCTION(key_snapshot), + MSM_PIN_FUNCTION(key_volp), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(lpass_slimbus0), + MSM_PIN_FUNCTION(lpass_slimbus1), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mag_int), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mipi_dsi0), + MSM_PIN_FUNCTION(modem_tsync), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(nav_pps_in_a), + MSM_PIN_FUNCTION(nav_pps_in_b), + MSM_PIN_FUNCTION(nav_tsync), + MSM_PIN_FUNCTION(nfc_disable), + MSM_PIN_FUNCTION(nfc_dwl), + MSM_PIN_FUNCTION(nfc_irq), + MSM_PIN_FUNCTION(ois_sync), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pbs0), + MSM_PIN_FUNCTION(pbs1), + MSM_PIN_FUNCTION(pbs2), + MSM_PIN_FUNCTION(pressure_int), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(pri_mi2s_mclk_a), + MSM_PIN_FUNCTION(pri_mi2s_mclk_b), + MSM_PIN_FUNCTION(pri_mi2s_ws), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(pwr_crypto_enabled_a), + MSM_PIN_FUNCTION(pwr_crypto_enabled_b), + MSM_PIN_FUNCTION(pwr_down), + MSM_PIN_FUNCTION(pwr_modem_enabled_a), + MSM_PIN_FUNCTION(pwr_modem_enabled_b), + MSM_PIN_FUNCTION(pwr_nav_enabled_a), + MSM_PIN_FUNCTION(pwr_nav_enabled_b), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b1), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdcard_det), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(sec_mi2s_mclk_a), + MSM_PIN_FUNCTION(sec_mi2s_mclk_b), + MSM_PIN_FUNCTION(smb_int), + MSM_PIN_FUNCTION(ss_switch), + MSM_PIN_FUNCTION(ssbi_wtr1), + MSM_PIN_FUNCTION(ts_resout), + MSM_PIN_FUNCTION(ts_sample), + MSM_PIN_FUNCTION(ts_xvdd), + MSM_PIN_FUNCTION(tsens_max), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(us_emitter), + MSM_PIN_FUNCTION(us_euro), + MSM_PIN_FUNCTION(wcss_bt), + MSM_PIN_FUNCTION(wcss_fm), + MSM_PIN_FUNCTION(wcss_wlan), + MSM_PIN_FUNCTION(wcss_wlan0), + MSM_PIN_FUNCTION(wcss_wlan1), + MSM_PIN_FUNCTION(wcss_wlan2), + MSM_PIN_FUNCTION(wsa_en), + MSM_PIN_FUNCTION(wsa_io), + MSM_PIN_FUNCTION(wsa_irq), }; static const struct msm_pingroup msm8953_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-msm8960.c b/drivers/pinctrl/qcom/pinctrl-msm8960.c index e3928f5f8d5b..ebe230b3b437 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8960.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8960.c @@ -6,7 +6,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinmux.h> #include "pinctrl-msm.h" @@ -334,31 +333,24 @@ static const unsigned int sdc3_clk_pins[] = { 155 }; static const unsigned int sdc3_cmd_pins[] = { 156 }; static const unsigned int sdc3_data_pins[] = { 157 }; -#define FUNCTION(fname) \ - [MSM_MUX_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ - MSM_MUX_gpio, \ - MSM_MUX_##f1, \ - MSM_MUX_##f2, \ - MSM_MUX_##f3, \ - MSM_MUX_##f4, \ - MSM_MUX_##f5, \ - MSM_MUX_##f6, \ - MSM_MUX_##f7, \ - MSM_MUX_##f8, \ - MSM_MUX_##f9, \ - MSM_MUX_##f10, \ - MSM_MUX_##f11 \ + msm_mux_gpio, \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7, \ + msm_mux_##f8, \ + msm_mux_##f9, \ + msm_mux_##f10, \ + msm_mux_##f11 \ }, \ .nfuncs = 12, \ .ctl_reg = 0x1000 + 0x10 * id, \ @@ -385,9 +377,9 @@ static const unsigned int sdc3_data_pins[] = { 157 }; #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -410,111 +402,111 @@ static const unsigned int sdc3_data_pins[] = { 157 }; } enum msm8960_functions { - MSM_MUX_audio_pcm, - MSM_MUX_bt, - MSM_MUX_cam_mclk0, - MSM_MUX_cam_mclk1, - MSM_MUX_cam_mclk2, - MSM_MUX_codec_mic_i2s, - MSM_MUX_codec_spkr_i2s, - MSM_MUX_ext_gps, - MSM_MUX_fm, - MSM_MUX_gps_blanking, - MSM_MUX_gps_pps_in, - MSM_MUX_gps_pps_out, - MSM_MUX_gp_clk_0a, - MSM_MUX_gp_clk_0b, - MSM_MUX_gp_clk_1a, - MSM_MUX_gp_clk_1b, - MSM_MUX_gp_clk_2a, - MSM_MUX_gp_clk_2b, - MSM_MUX_gp_mn, - MSM_MUX_gp_pdm_0a, - MSM_MUX_gp_pdm_0b, - MSM_MUX_gp_pdm_1a, - MSM_MUX_gp_pdm_1b, - MSM_MUX_gp_pdm_2a, - MSM_MUX_gp_pdm_2b, - MSM_MUX_gpio, - MSM_MUX_gsbi1, - MSM_MUX_gsbi1_spi_cs1_n, - MSM_MUX_gsbi1_spi_cs2a_n, - MSM_MUX_gsbi1_spi_cs2b_n, - MSM_MUX_gsbi1_spi_cs3_n, - MSM_MUX_gsbi2, - MSM_MUX_gsbi2_spi_cs1_n, - MSM_MUX_gsbi2_spi_cs2_n, - MSM_MUX_gsbi2_spi_cs3_n, - MSM_MUX_gsbi3, - MSM_MUX_gsbi4, - MSM_MUX_gsbi4_3d_cam_i2c_l, - MSM_MUX_gsbi4_3d_cam_i2c_r, - MSM_MUX_gsbi5, - MSM_MUX_gsbi5_3d_cam_i2c_l, - MSM_MUX_gsbi5_3d_cam_i2c_r, - MSM_MUX_gsbi6, - MSM_MUX_gsbi7, - MSM_MUX_gsbi8, - MSM_MUX_gsbi9, - MSM_MUX_gsbi10, - MSM_MUX_gsbi11, - MSM_MUX_gsbi11_spi_cs1a_n, - MSM_MUX_gsbi11_spi_cs1b_n, - MSM_MUX_gsbi11_spi_cs2a_n, - MSM_MUX_gsbi11_spi_cs2b_n, - MSM_MUX_gsbi11_spi_cs3_n, - MSM_MUX_gsbi12, - MSM_MUX_hdmi_cec, - MSM_MUX_hdmi_ddc_clock, - MSM_MUX_hdmi_ddc_data, - MSM_MUX_hdmi_hot_plug_detect, - MSM_MUX_hsic, - MSM_MUX_mdp_vsync, - MSM_MUX_mi2s, - MSM_MUX_mic_i2s, - MSM_MUX_pmb_clk, - MSM_MUX_pmb_ext_ctrl, - MSM_MUX_ps_hold, - MSM_MUX_rpm_wdog, - MSM_MUX_sdc2, - MSM_MUX_sdc4, - MSM_MUX_sdc5, - MSM_MUX_slimbus1, - MSM_MUX_slimbus2, - MSM_MUX_spkr_i2s, - MSM_MUX_ssbi1, - MSM_MUX_ssbi2, - MSM_MUX_ssbi_ext_gps, - MSM_MUX_ssbi_pmic2, - MSM_MUX_ssbi_qpa1, - MSM_MUX_ssbi_ts, - MSM_MUX_tsif1, - MSM_MUX_tsif2, - MSM_MUX_ts_eoc, - MSM_MUX_usb_fs1, - MSM_MUX_usb_fs1_oe, - MSM_MUX_usb_fs1_oe_n, - MSM_MUX_usb_fs2, - MSM_MUX_usb_fs2_oe, - MSM_MUX_usb_fs2_oe_n, - MSM_MUX_vfe_camif_timer1_a, - MSM_MUX_vfe_camif_timer1_b, - MSM_MUX_vfe_camif_timer2, - MSM_MUX_vfe_camif_timer3_a, - MSM_MUX_vfe_camif_timer3_b, - MSM_MUX_vfe_camif_timer4_a, - MSM_MUX_vfe_camif_timer4_b, - MSM_MUX_vfe_camif_timer4_c, - MSM_MUX_vfe_camif_timer5_a, - MSM_MUX_vfe_camif_timer5_b, - MSM_MUX_vfe_camif_timer6_a, - MSM_MUX_vfe_camif_timer6_b, - MSM_MUX_vfe_camif_timer6_c, - MSM_MUX_vfe_camif_timer7_a, - MSM_MUX_vfe_camif_timer7_b, - MSM_MUX_vfe_camif_timer7_c, - MSM_MUX_wlan, - MSM_MUX_NA, + msm_mux_audio_pcm, + msm_mux_bt, + msm_mux_cam_mclk0, + msm_mux_cam_mclk1, + msm_mux_cam_mclk2, + msm_mux_codec_mic_i2s, + msm_mux_codec_spkr_i2s, + msm_mux_ext_gps, + msm_mux_fm, + msm_mux_gps_blanking, + msm_mux_gps_pps_in, + msm_mux_gps_pps_out, + msm_mux_gp_clk_0a, + msm_mux_gp_clk_0b, + msm_mux_gp_clk_1a, + msm_mux_gp_clk_1b, + msm_mux_gp_clk_2a, + msm_mux_gp_clk_2b, + msm_mux_gp_mn, + msm_mux_gp_pdm_0a, + msm_mux_gp_pdm_0b, + msm_mux_gp_pdm_1a, + msm_mux_gp_pdm_1b, + msm_mux_gp_pdm_2a, + msm_mux_gp_pdm_2b, + msm_mux_gpio, + msm_mux_gsbi1, + msm_mux_gsbi1_spi_cs1_n, + msm_mux_gsbi1_spi_cs2a_n, + msm_mux_gsbi1_spi_cs2b_n, + msm_mux_gsbi1_spi_cs3_n, + msm_mux_gsbi2, + msm_mux_gsbi2_spi_cs1_n, + msm_mux_gsbi2_spi_cs2_n, + msm_mux_gsbi2_spi_cs3_n, + msm_mux_gsbi3, + msm_mux_gsbi4, + msm_mux_gsbi4_3d_cam_i2c_l, + msm_mux_gsbi4_3d_cam_i2c_r, + msm_mux_gsbi5, + msm_mux_gsbi5_3d_cam_i2c_l, + msm_mux_gsbi5_3d_cam_i2c_r, + msm_mux_gsbi6, + msm_mux_gsbi7, + msm_mux_gsbi8, + msm_mux_gsbi9, + msm_mux_gsbi10, + msm_mux_gsbi11, + msm_mux_gsbi11_spi_cs1a_n, + msm_mux_gsbi11_spi_cs1b_n, + msm_mux_gsbi11_spi_cs2a_n, + msm_mux_gsbi11_spi_cs2b_n, + msm_mux_gsbi11_spi_cs3_n, + msm_mux_gsbi12, + msm_mux_hdmi_cec, + msm_mux_hdmi_ddc_clock, + msm_mux_hdmi_ddc_data, + msm_mux_hdmi_hot_plug_detect, + msm_mux_hsic, + msm_mux_mdp_vsync, + msm_mux_mi2s, + msm_mux_mic_i2s, + msm_mux_pmb_clk, + msm_mux_pmb_ext_ctrl, + msm_mux_ps_hold, + msm_mux_rpm_wdog, + msm_mux_sdc2, + msm_mux_sdc4, + msm_mux_sdc5, + msm_mux_slimbus1, + msm_mux_slimbus2, + msm_mux_spkr_i2s, + msm_mux_ssbi1, + msm_mux_ssbi2, + msm_mux_ssbi_ext_gps, + msm_mux_ssbi_pmic2, + msm_mux_ssbi_qpa1, + msm_mux_ssbi_ts, + msm_mux_tsif1, + msm_mux_tsif2, + msm_mux_ts_eoc, + msm_mux_usb_fs1, + msm_mux_usb_fs1_oe, + msm_mux_usb_fs1_oe_n, + msm_mux_usb_fs2, + msm_mux_usb_fs2_oe, + msm_mux_usb_fs2_oe_n, + msm_mux_vfe_camif_timer1_a, + msm_mux_vfe_camif_timer1_b, + msm_mux_vfe_camif_timer2, + msm_mux_vfe_camif_timer3_a, + msm_mux_vfe_camif_timer3_b, + msm_mux_vfe_camif_timer4_a, + msm_mux_vfe_camif_timer4_b, + msm_mux_vfe_camif_timer4_c, + msm_mux_vfe_camif_timer5_a, + msm_mux_vfe_camif_timer5_b, + msm_mux_vfe_camif_timer6_a, + msm_mux_vfe_camif_timer6_b, + msm_mux_vfe_camif_timer6_c, + msm_mux_vfe_camif_timer7_a, + msm_mux_vfe_camif_timer7_b, + msm_mux_vfe_camif_timer7_c, + msm_mux_wlan, + msm_mux_NA, }; static const char * const audio_pcm_groups[] = { @@ -956,111 +948,111 @@ static const char * const wlan_groups[] = { "gpio84", "gpio85", "gpio86", "gpio87", "gpio88" }; -static const struct msm_function msm8960_functions[] = { - FUNCTION(audio_pcm), - FUNCTION(bt), - FUNCTION(cam_mclk0), - FUNCTION(cam_mclk1), - FUNCTION(cam_mclk2), - FUNCTION(codec_mic_i2s), - FUNCTION(codec_spkr_i2s), - FUNCTION(ext_gps), - FUNCTION(fm), - FUNCTION(gps_blanking), - FUNCTION(gps_pps_in), - FUNCTION(gps_pps_out), - FUNCTION(gp_clk_0a), - FUNCTION(gp_clk_0b), - FUNCTION(gp_clk_1a), - FUNCTION(gp_clk_1b), - FUNCTION(gp_clk_2a), - FUNCTION(gp_clk_2b), - FUNCTION(gp_mn), - FUNCTION(gp_pdm_0a), - FUNCTION(gp_pdm_0b), - FUNCTION(gp_pdm_1a), - FUNCTION(gp_pdm_1b), - FUNCTION(gp_pdm_2a), - FUNCTION(gp_pdm_2b), - FUNCTION(gpio), - FUNCTION(gsbi1), - FUNCTION(gsbi1_spi_cs1_n), - FUNCTION(gsbi1_spi_cs2a_n), - FUNCTION(gsbi1_spi_cs2b_n), - FUNCTION(gsbi1_spi_cs3_n), - FUNCTION(gsbi2), - FUNCTION(gsbi2_spi_cs1_n), - FUNCTION(gsbi2_spi_cs2_n), - FUNCTION(gsbi2_spi_cs3_n), - FUNCTION(gsbi3), - FUNCTION(gsbi4), - FUNCTION(gsbi4_3d_cam_i2c_l), - FUNCTION(gsbi4_3d_cam_i2c_r), - FUNCTION(gsbi5), - FUNCTION(gsbi5_3d_cam_i2c_l), - FUNCTION(gsbi5_3d_cam_i2c_r), - FUNCTION(gsbi6), - FUNCTION(gsbi7), - FUNCTION(gsbi8), - FUNCTION(gsbi9), - FUNCTION(gsbi10), - FUNCTION(gsbi11), - FUNCTION(gsbi11_spi_cs1a_n), - FUNCTION(gsbi11_spi_cs1b_n), - FUNCTION(gsbi11_spi_cs2a_n), - FUNCTION(gsbi11_spi_cs2b_n), - FUNCTION(gsbi11_spi_cs3_n), - FUNCTION(gsbi12), - FUNCTION(hdmi_cec), - FUNCTION(hdmi_ddc_clock), - FUNCTION(hdmi_ddc_data), - FUNCTION(hdmi_hot_plug_detect), - FUNCTION(hsic), - FUNCTION(mdp_vsync), - FUNCTION(mi2s), - FUNCTION(mic_i2s), - FUNCTION(pmb_clk), - FUNCTION(pmb_ext_ctrl), - FUNCTION(ps_hold), - FUNCTION(rpm_wdog), - FUNCTION(sdc2), - FUNCTION(sdc4), - FUNCTION(sdc5), - FUNCTION(slimbus1), - FUNCTION(slimbus2), - FUNCTION(spkr_i2s), - FUNCTION(ssbi1), - FUNCTION(ssbi2), - FUNCTION(ssbi_ext_gps), - FUNCTION(ssbi_pmic2), - FUNCTION(ssbi_qpa1), - FUNCTION(ssbi_ts), - FUNCTION(tsif1), - FUNCTION(tsif2), - FUNCTION(ts_eoc), - FUNCTION(usb_fs1), - FUNCTION(usb_fs1_oe), - FUNCTION(usb_fs1_oe_n), - FUNCTION(usb_fs2), - FUNCTION(usb_fs2_oe), - FUNCTION(usb_fs2_oe_n), - FUNCTION(vfe_camif_timer1_a), - FUNCTION(vfe_camif_timer1_b), - FUNCTION(vfe_camif_timer2), - FUNCTION(vfe_camif_timer3_a), - FUNCTION(vfe_camif_timer3_b), - FUNCTION(vfe_camif_timer4_a), - FUNCTION(vfe_camif_timer4_b), - FUNCTION(vfe_camif_timer4_c), - FUNCTION(vfe_camif_timer5_a), - FUNCTION(vfe_camif_timer5_b), - FUNCTION(vfe_camif_timer6_a), - FUNCTION(vfe_camif_timer6_b), - FUNCTION(vfe_camif_timer6_c), - FUNCTION(vfe_camif_timer7_a), - FUNCTION(vfe_camif_timer7_b), - FUNCTION(vfe_camif_timer7_c), - FUNCTION(wlan), +static const struct pinfunction msm8960_functions[] = { + MSM_PIN_FUNCTION(audio_pcm), + MSM_PIN_FUNCTION(bt), + MSM_PIN_FUNCTION(cam_mclk0), + MSM_PIN_FUNCTION(cam_mclk1), + MSM_PIN_FUNCTION(cam_mclk2), + MSM_PIN_FUNCTION(codec_mic_i2s), + MSM_PIN_FUNCTION(codec_spkr_i2s), + MSM_PIN_FUNCTION(ext_gps), + MSM_PIN_FUNCTION(fm), + MSM_PIN_FUNCTION(gps_blanking), + MSM_PIN_FUNCTION(gps_pps_in), + MSM_PIN_FUNCTION(gps_pps_out), + MSM_PIN_FUNCTION(gp_clk_0a), + MSM_PIN_FUNCTION(gp_clk_0b), + MSM_PIN_FUNCTION(gp_clk_1a), + MSM_PIN_FUNCTION(gp_clk_1b), + MSM_PIN_FUNCTION(gp_clk_2a), + MSM_PIN_FUNCTION(gp_clk_2b), + MSM_PIN_FUNCTION(gp_mn), + MSM_PIN_FUNCTION(gp_pdm_0a), + MSM_PIN_FUNCTION(gp_pdm_0b), + MSM_PIN_FUNCTION(gp_pdm_1a), + MSM_PIN_FUNCTION(gp_pdm_1b), + MSM_PIN_FUNCTION(gp_pdm_2a), + MSM_PIN_FUNCTION(gp_pdm_2b), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gsbi1), + MSM_PIN_FUNCTION(gsbi1_spi_cs1_n), + MSM_PIN_FUNCTION(gsbi1_spi_cs2a_n), + MSM_PIN_FUNCTION(gsbi1_spi_cs2b_n), + MSM_PIN_FUNCTION(gsbi1_spi_cs3_n), + MSM_PIN_FUNCTION(gsbi2), + MSM_PIN_FUNCTION(gsbi2_spi_cs1_n), + MSM_PIN_FUNCTION(gsbi2_spi_cs2_n), + MSM_PIN_FUNCTION(gsbi2_spi_cs3_n), + MSM_PIN_FUNCTION(gsbi3), + MSM_PIN_FUNCTION(gsbi4), + MSM_PIN_FUNCTION(gsbi4_3d_cam_i2c_l), + MSM_PIN_FUNCTION(gsbi4_3d_cam_i2c_r), + MSM_PIN_FUNCTION(gsbi5), + MSM_PIN_FUNCTION(gsbi5_3d_cam_i2c_l), + MSM_PIN_FUNCTION(gsbi5_3d_cam_i2c_r), + MSM_PIN_FUNCTION(gsbi6), + MSM_PIN_FUNCTION(gsbi7), + MSM_PIN_FUNCTION(gsbi8), + MSM_PIN_FUNCTION(gsbi9), + MSM_PIN_FUNCTION(gsbi10), + MSM_PIN_FUNCTION(gsbi11), + MSM_PIN_FUNCTION(gsbi11_spi_cs1a_n), + MSM_PIN_FUNCTION(gsbi11_spi_cs1b_n), + MSM_PIN_FUNCTION(gsbi11_spi_cs2a_n), + MSM_PIN_FUNCTION(gsbi11_spi_cs2b_n), + MSM_PIN_FUNCTION(gsbi11_spi_cs3_n), + MSM_PIN_FUNCTION(gsbi12), + MSM_PIN_FUNCTION(hdmi_cec), + MSM_PIN_FUNCTION(hdmi_ddc_clock), + MSM_PIN_FUNCTION(hdmi_ddc_data), + MSM_PIN_FUNCTION(hdmi_hot_plug_detect), + MSM_PIN_FUNCTION(hsic), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mi2s), + MSM_PIN_FUNCTION(mic_i2s), + MSM_PIN_FUNCTION(pmb_clk), + MSM_PIN_FUNCTION(pmb_ext_ctrl), + MSM_PIN_FUNCTION(ps_hold), + MSM_PIN_FUNCTION(rpm_wdog), + MSM_PIN_FUNCTION(sdc2), + MSM_PIN_FUNCTION(sdc4), + MSM_PIN_FUNCTION(sdc5), + MSM_PIN_FUNCTION(slimbus1), + MSM_PIN_FUNCTION(slimbus2), + MSM_PIN_FUNCTION(spkr_i2s), + MSM_PIN_FUNCTION(ssbi1), + MSM_PIN_FUNCTION(ssbi2), + MSM_PIN_FUNCTION(ssbi_ext_gps), + MSM_PIN_FUNCTION(ssbi_pmic2), + MSM_PIN_FUNCTION(ssbi_qpa1), + MSM_PIN_FUNCTION(ssbi_ts), + MSM_PIN_FUNCTION(tsif1), + MSM_PIN_FUNCTION(tsif2), + MSM_PIN_FUNCTION(ts_eoc), + MSM_PIN_FUNCTION(usb_fs1), + MSM_PIN_FUNCTION(usb_fs1_oe), + MSM_PIN_FUNCTION(usb_fs1_oe_n), + MSM_PIN_FUNCTION(usb_fs2), + MSM_PIN_FUNCTION(usb_fs2_oe), + MSM_PIN_FUNCTION(usb_fs2_oe_n), + MSM_PIN_FUNCTION(vfe_camif_timer1_a), + MSM_PIN_FUNCTION(vfe_camif_timer1_b), + MSM_PIN_FUNCTION(vfe_camif_timer2), + MSM_PIN_FUNCTION(vfe_camif_timer3_a), + MSM_PIN_FUNCTION(vfe_camif_timer3_b), + MSM_PIN_FUNCTION(vfe_camif_timer4_a), + MSM_PIN_FUNCTION(vfe_camif_timer4_b), + MSM_PIN_FUNCTION(vfe_camif_timer4_c), + MSM_PIN_FUNCTION(vfe_camif_timer5_a), + MSM_PIN_FUNCTION(vfe_camif_timer5_b), + MSM_PIN_FUNCTION(vfe_camif_timer6_a), + MSM_PIN_FUNCTION(vfe_camif_timer6_b), + MSM_PIN_FUNCTION(vfe_camif_timer6_c), + MSM_PIN_FUNCTION(vfe_camif_timer7_a), + MSM_PIN_FUNCTION(vfe_camif_timer7_b), + MSM_PIN_FUNCTION(vfe_camif_timer7_c), + MSM_PIN_FUNCTION(wlan), }; static const struct msm_pingroup msm8960_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-msm8976.c b/drivers/pinctrl/qcom/pinctrl-msm8976.c index e11d84584719..c30d80e4e98c 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8976.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8976.c @@ -8,24 +8,16 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_BASE 0x0 #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -62,9 +54,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -819,102 +811,102 @@ static const char * const ss_switch_groups[] = { "gpio139", }; -static const struct msm_function msm8976_functions[] = { - FUNCTION(gpio), - FUNCTION(blsp_spi1), - FUNCTION(smb_int), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_spi2), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart2), - FUNCTION(blsp_i2c2), - FUNCTION(gcc_gp1_clk_b), - FUNCTION(blsp_spi3), - FUNCTION(qdss_tracedata_b), - FUNCTION(blsp_i2c3), - FUNCTION(gcc_gp2_clk_b), - FUNCTION(gcc_gp3_clk_b), - FUNCTION(blsp_spi4), - FUNCTION(cap_int), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_uart5), - FUNCTION(qdss_traceclk_a), - FUNCTION(m_voc), - FUNCTION(blsp_i2c5), - FUNCTION(qdss_tracectl_a), - FUNCTION(qdss_tracedata_a), - FUNCTION(blsp_spi6), - FUNCTION(blsp_uart6), - FUNCTION(qdss_tracectl_b), - FUNCTION(blsp_i2c6), - FUNCTION(qdss_traceclk_b), - FUNCTION(mdp_vsync), - FUNCTION(pri_mi2s_mclk_a), - FUNCTION(sec_mi2s_mclk_a), - FUNCTION(cam_mclk), - FUNCTION(cci0_i2c), - FUNCTION(cci1_i2c), - FUNCTION(blsp1_spi), - FUNCTION(blsp3_spi), - FUNCTION(gcc_gp1_clk_a), - FUNCTION(gcc_gp2_clk_a), - FUNCTION(gcc_gp3_clk_a), - FUNCTION(uim_batt), - FUNCTION(sd_write), - FUNCTION(uim1_data), - FUNCTION(uim1_clk), - FUNCTION(uim1_reset), - FUNCTION(uim1_present), - FUNCTION(uim2_data), - FUNCTION(uim2_clk), - FUNCTION(uim2_reset), - FUNCTION(uim2_present), - FUNCTION(ts_xvdd), - FUNCTION(mipi_dsi0), - FUNCTION(us_euro), - FUNCTION(ts_resout), - FUNCTION(ts_sample), - FUNCTION(sec_mi2s_mclk_b), - FUNCTION(pri_mi2s), - FUNCTION(codec_reset), - FUNCTION(cdc_pdm0), - FUNCTION(us_emitter), - FUNCTION(pri_mi2s_mclk_b), - FUNCTION(pri_mi2s_mclk_c), - FUNCTION(lpass_slimbus), - FUNCTION(lpass_slimbus0), - FUNCTION(lpass_slimbus1), - FUNCTION(codec_int1), - FUNCTION(codec_int2), - FUNCTION(wcss_bt), - FUNCTION(sdc3), - FUNCTION(wcss_wlan2), - FUNCTION(wcss_wlan1), - FUNCTION(wcss_wlan0), - FUNCTION(wcss_wlan), - FUNCTION(wcss_fm), - FUNCTION(key_volp), - FUNCTION(key_snapshot), - FUNCTION(key_focus), - FUNCTION(key_home), - FUNCTION(pwr_down), - FUNCTION(dmic0_clk), - FUNCTION(hdmi_int), - FUNCTION(dmic0_data), - FUNCTION(wsa_vi), - FUNCTION(wsa_en), - FUNCTION(blsp_spi8), - FUNCTION(wsa_irq), - FUNCTION(blsp_i2c8), - FUNCTION(pa_indicator), - FUNCTION(modem_tsync), - FUNCTION(ssbi_wtr1), - FUNCTION(gsm1_tx), - FUNCTION(gsm0_tx), - FUNCTION(sdcard_det), - FUNCTION(sec_mi2s), - FUNCTION(ss_switch), +static const struct pinfunction msm8976_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(smb_int), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(gcc_gp1_clk_b), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(gcc_gp2_clk_b), + MSM_PIN_FUNCTION(gcc_gp3_clk_b), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(cap_int), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(blsp_uart5), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(blsp_spi6), + MSM_PIN_FUNCTION(blsp_uart6), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(blsp_i2c6), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(pri_mi2s_mclk_a), + MSM_PIN_FUNCTION(sec_mi2s_mclk_a), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci0_i2c), + MSM_PIN_FUNCTION(cci1_i2c), + MSM_PIN_FUNCTION(blsp1_spi), + MSM_PIN_FUNCTION(blsp3_spi), + MSM_PIN_FUNCTION(gcc_gp1_clk_a), + MSM_PIN_FUNCTION(gcc_gp2_clk_a), + MSM_PIN_FUNCTION(gcc_gp3_clk_a), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(ts_xvdd), + MSM_PIN_FUNCTION(mipi_dsi0), + MSM_PIN_FUNCTION(us_euro), + MSM_PIN_FUNCTION(ts_resout), + MSM_PIN_FUNCTION(ts_sample), + MSM_PIN_FUNCTION(sec_mi2s_mclk_b), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(codec_reset), + MSM_PIN_FUNCTION(cdc_pdm0), + MSM_PIN_FUNCTION(us_emitter), + MSM_PIN_FUNCTION(pri_mi2s_mclk_b), + MSM_PIN_FUNCTION(pri_mi2s_mclk_c), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(lpass_slimbus0), + MSM_PIN_FUNCTION(lpass_slimbus1), + MSM_PIN_FUNCTION(codec_int1), + MSM_PIN_FUNCTION(codec_int2), + MSM_PIN_FUNCTION(wcss_bt), + MSM_PIN_FUNCTION(sdc3), + MSM_PIN_FUNCTION(wcss_wlan2), + MSM_PIN_FUNCTION(wcss_wlan1), + MSM_PIN_FUNCTION(wcss_wlan0), + MSM_PIN_FUNCTION(wcss_wlan), + MSM_PIN_FUNCTION(wcss_fm), + MSM_PIN_FUNCTION(key_volp), + MSM_PIN_FUNCTION(key_snapshot), + MSM_PIN_FUNCTION(key_focus), + MSM_PIN_FUNCTION(key_home), + MSM_PIN_FUNCTION(pwr_down), + MSM_PIN_FUNCTION(dmic0_clk), + MSM_PIN_FUNCTION(hdmi_int), + MSM_PIN_FUNCTION(dmic0_data), + MSM_PIN_FUNCTION(wsa_vi), + MSM_PIN_FUNCTION(wsa_en), + MSM_PIN_FUNCTION(blsp_spi8), + MSM_PIN_FUNCTION(wsa_irq), + MSM_PIN_FUNCTION(blsp_i2c8), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(modem_tsync), + MSM_PIN_FUNCTION(ssbi_wtr1), + MSM_PIN_FUNCTION(gsm1_tx), + MSM_PIN_FUNCTION(gsm0_tx), + MSM_PIN_FUNCTION(sdcard_det), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(ss_switch), }; static const struct msm_pingroup msm8976_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-msm8994.c b/drivers/pinctrl/qcom/pinctrl-msm8994.c index 0ec886563f45..b1a6759ab4a5 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8994.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8994.c @@ -6,35 +6,27 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [MSM_MUX_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ - MSM_MUX_gpio, \ - MSM_MUX_##f1, \ - MSM_MUX_##f2, \ - MSM_MUX_##f3, \ - MSM_MUX_##f4, \ - MSM_MUX_##f5, \ - MSM_MUX_##f6, \ - MSM_MUX_##f7, \ - MSM_MUX_##f8, \ - MSM_MUX_##f9, \ - MSM_MUX_##f10, \ - MSM_MUX_##f11 \ + msm_mux_gpio, \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7, \ + msm_mux_##f8, \ + msm_mux_##f9, \ + msm_mux_##f10, \ + msm_mux_##f11 \ }, \ .nfuncs = 12, \ .ctl_reg = 0x1000 + 0x10 * id, \ @@ -60,9 +52,9 @@ #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -403,136 +395,136 @@ static const unsigned int sdc3_cmd_pins[] = { 154 }; static const unsigned int sdc3_data_pins[] = { 155 }; enum msm8994_functions { - MSM_MUX_audio_ref_clk, - MSM_MUX_blsp_i2c1, - MSM_MUX_blsp_i2c2, - MSM_MUX_blsp_i2c3, - MSM_MUX_blsp_i2c4, - MSM_MUX_blsp_i2c5, - MSM_MUX_blsp_i2c6, - MSM_MUX_blsp_i2c7, - MSM_MUX_blsp_i2c8, - MSM_MUX_blsp_i2c9, - MSM_MUX_blsp_i2c10, - MSM_MUX_blsp_i2c11, - MSM_MUX_blsp_i2c12, - MSM_MUX_blsp_spi1, - MSM_MUX_blsp_spi1_cs1, - MSM_MUX_blsp_spi1_cs2, - MSM_MUX_blsp_spi1_cs3, - MSM_MUX_blsp_spi2, - MSM_MUX_blsp_spi2_cs1, - MSM_MUX_blsp_spi2_cs2, - MSM_MUX_blsp_spi2_cs3, - MSM_MUX_blsp_spi3, - MSM_MUX_blsp_spi4, - MSM_MUX_blsp_spi5, - MSM_MUX_blsp_spi6, - MSM_MUX_blsp_spi7, - MSM_MUX_blsp_spi8, - MSM_MUX_blsp_spi9, - MSM_MUX_blsp_spi10, - MSM_MUX_blsp_spi10_cs1, - MSM_MUX_blsp_spi10_cs2, - MSM_MUX_blsp_spi10_cs3, - MSM_MUX_blsp_spi11, - MSM_MUX_blsp_spi12, - MSM_MUX_blsp_uart1, - MSM_MUX_blsp_uart2, - MSM_MUX_blsp_uart3, - MSM_MUX_blsp_uart4, - MSM_MUX_blsp_uart5, - MSM_MUX_blsp_uart6, - MSM_MUX_blsp_uart7, - MSM_MUX_blsp_uart8, - MSM_MUX_blsp_uart9, - MSM_MUX_blsp_uart10, - MSM_MUX_blsp_uart11, - MSM_MUX_blsp_uart12, - MSM_MUX_blsp_uim1, - MSM_MUX_blsp_uim2, - MSM_MUX_blsp_uim3, - MSM_MUX_blsp_uim4, - MSM_MUX_blsp_uim5, - MSM_MUX_blsp_uim6, - MSM_MUX_blsp_uim7, - MSM_MUX_blsp_uim8, - MSM_MUX_blsp_uim9, - MSM_MUX_blsp_uim10, - MSM_MUX_blsp_uim11, - MSM_MUX_blsp_uim12, - MSM_MUX_blsp11_i2c_scl_b, - MSM_MUX_blsp11_i2c_sda_b, - MSM_MUX_blsp11_uart_rx_b, - MSM_MUX_blsp11_uart_tx_b, - MSM_MUX_cam_mclk0, - MSM_MUX_cam_mclk1, - MSM_MUX_cam_mclk2, - MSM_MUX_cam_mclk3, - MSM_MUX_cci_async_in0, - MSM_MUX_cci_async_in1, - MSM_MUX_cci_async_in2, - MSM_MUX_cci_i2c0, - MSM_MUX_cci_i2c1, - MSM_MUX_cci_timer0, - MSM_MUX_cci_timer1, - MSM_MUX_cci_timer2, - MSM_MUX_cci_timer3, - MSM_MUX_cci_timer4, - MSM_MUX_gcc_gp1_clk_a, - MSM_MUX_gcc_gp1_clk_b, - MSM_MUX_gcc_gp2_clk_a, - MSM_MUX_gcc_gp2_clk_b, - MSM_MUX_gcc_gp3_clk_a, - MSM_MUX_gcc_gp3_clk_b, - MSM_MUX_gp_mn, - MSM_MUX_gp_pdm0, - MSM_MUX_gp_pdm1, - MSM_MUX_gp_pdm2, - MSM_MUX_gp0_clk, - MSM_MUX_gp1_clk, - MSM_MUX_gps_tx, - MSM_MUX_gsm_tx, - MSM_MUX_hdmi_cec, - MSM_MUX_hdmi_ddc, - MSM_MUX_hdmi_hpd, - MSM_MUX_hdmi_rcv, - MSM_MUX_mdp_vsync, - MSM_MUX_mss_lte, - MSM_MUX_nav_pps, - MSM_MUX_nav_tsync, - MSM_MUX_qdss_cti_trig_in_a, - MSM_MUX_qdss_cti_trig_in_b, - MSM_MUX_qdss_cti_trig_in_c, - MSM_MUX_qdss_cti_trig_in_d, - MSM_MUX_qdss_cti_trig_out_a, - MSM_MUX_qdss_cti_trig_out_b, - MSM_MUX_qdss_cti_trig_out_c, - MSM_MUX_qdss_cti_trig_out_d, - MSM_MUX_qdss_traceclk_a, - MSM_MUX_qdss_traceclk_b, - MSM_MUX_qdss_tracectl_a, - MSM_MUX_qdss_tracectl_b, - MSM_MUX_qdss_tracedata_a, - MSM_MUX_qdss_tracedata_b, - MSM_MUX_qua_mi2s, - MSM_MUX_pci_e0, - MSM_MUX_pci_e1, - MSM_MUX_pri_mi2s, - MSM_MUX_sdc4, - MSM_MUX_sec_mi2s, - MSM_MUX_slimbus, - MSM_MUX_spkr_i2s, - MSM_MUX_ter_mi2s, - MSM_MUX_tsif1, - MSM_MUX_tsif2, - MSM_MUX_uim1, - MSM_MUX_uim2, - MSM_MUX_uim3, - MSM_MUX_uim4, - MSM_MUX_uim_batt_alarm, - MSM_MUX_gpio, - MSM_MUX_NA, + msm_mux_audio_ref_clk, + msm_mux_blsp_i2c1, + msm_mux_blsp_i2c2, + msm_mux_blsp_i2c3, + msm_mux_blsp_i2c4, + msm_mux_blsp_i2c5, + msm_mux_blsp_i2c6, + msm_mux_blsp_i2c7, + msm_mux_blsp_i2c8, + msm_mux_blsp_i2c9, + msm_mux_blsp_i2c10, + msm_mux_blsp_i2c11, + msm_mux_blsp_i2c12, + msm_mux_blsp_spi1, + msm_mux_blsp_spi1_cs1, + msm_mux_blsp_spi1_cs2, + msm_mux_blsp_spi1_cs3, + msm_mux_blsp_spi2, + msm_mux_blsp_spi2_cs1, + msm_mux_blsp_spi2_cs2, + msm_mux_blsp_spi2_cs3, + msm_mux_blsp_spi3, + msm_mux_blsp_spi4, + msm_mux_blsp_spi5, + msm_mux_blsp_spi6, + msm_mux_blsp_spi7, + msm_mux_blsp_spi8, + msm_mux_blsp_spi9, + msm_mux_blsp_spi10, + msm_mux_blsp_spi10_cs1, + msm_mux_blsp_spi10_cs2, + msm_mux_blsp_spi10_cs3, + msm_mux_blsp_spi11, + msm_mux_blsp_spi12, + msm_mux_blsp_uart1, + msm_mux_blsp_uart2, + msm_mux_blsp_uart3, + msm_mux_blsp_uart4, + msm_mux_blsp_uart5, + msm_mux_blsp_uart6, + msm_mux_blsp_uart7, + msm_mux_blsp_uart8, + msm_mux_blsp_uart9, + msm_mux_blsp_uart10, + msm_mux_blsp_uart11, + msm_mux_blsp_uart12, + msm_mux_blsp_uim1, + msm_mux_blsp_uim2, + msm_mux_blsp_uim3, + msm_mux_blsp_uim4, + msm_mux_blsp_uim5, + msm_mux_blsp_uim6, + msm_mux_blsp_uim7, + msm_mux_blsp_uim8, + msm_mux_blsp_uim9, + msm_mux_blsp_uim10, + msm_mux_blsp_uim11, + msm_mux_blsp_uim12, + msm_mux_blsp11_i2c_scl_b, + msm_mux_blsp11_i2c_sda_b, + msm_mux_blsp11_uart_rx_b, + msm_mux_blsp11_uart_tx_b, + msm_mux_cam_mclk0, + msm_mux_cam_mclk1, + msm_mux_cam_mclk2, + msm_mux_cam_mclk3, + msm_mux_cci_async_in0, + msm_mux_cci_async_in1, + msm_mux_cci_async_in2, + msm_mux_cci_i2c0, + msm_mux_cci_i2c1, + msm_mux_cci_timer0, + msm_mux_cci_timer1, + msm_mux_cci_timer2, + msm_mux_cci_timer3, + msm_mux_cci_timer4, + msm_mux_gcc_gp1_clk_a, + msm_mux_gcc_gp1_clk_b, + msm_mux_gcc_gp2_clk_a, + msm_mux_gcc_gp2_clk_b, + msm_mux_gcc_gp3_clk_a, + msm_mux_gcc_gp3_clk_b, + msm_mux_gp_mn, + msm_mux_gp_pdm0, + msm_mux_gp_pdm1, + msm_mux_gp_pdm2, + msm_mux_gp0_clk, + msm_mux_gp1_clk, + msm_mux_gps_tx, + msm_mux_gsm_tx, + msm_mux_hdmi_cec, + msm_mux_hdmi_ddc, + msm_mux_hdmi_hpd, + msm_mux_hdmi_rcv, + msm_mux_mdp_vsync, + msm_mux_mss_lte, + msm_mux_nav_pps, + msm_mux_nav_tsync, + msm_mux_qdss_cti_trig_in_a, + msm_mux_qdss_cti_trig_in_b, + msm_mux_qdss_cti_trig_in_c, + msm_mux_qdss_cti_trig_in_d, + msm_mux_qdss_cti_trig_out_a, + msm_mux_qdss_cti_trig_out_b, + msm_mux_qdss_cti_trig_out_c, + msm_mux_qdss_cti_trig_out_d, + msm_mux_qdss_traceclk_a, + msm_mux_qdss_traceclk_b, + msm_mux_qdss_tracectl_a, + msm_mux_qdss_tracectl_b, + msm_mux_qdss_tracedata_a, + msm_mux_qdss_tracedata_b, + msm_mux_qua_mi2s, + msm_mux_pci_e0, + msm_mux_pci_e1, + msm_mux_pri_mi2s, + msm_mux_sdc4, + msm_mux_sec_mi2s, + msm_mux_slimbus, + msm_mux_spkr_i2s, + msm_mux_ter_mi2s, + msm_mux_tsif1, + msm_mux_tsif2, + msm_mux_uim1, + msm_mux_uim2, + msm_mux_uim3, + msm_mux_uim4, + msm_mux_uim_batt_alarm, + msm_mux_gpio, + msm_mux_NA, }; static const char * const gpio_groups[] = { @@ -950,136 +942,136 @@ static const char * const mss_lte_groups[] = { "gpio134", "gpio135" }; -static const struct msm_function msm8994_functions[] = { - FUNCTION(audio_ref_clk), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_i2c5), - FUNCTION(blsp_i2c6), - FUNCTION(blsp_i2c7), - FUNCTION(blsp_i2c8), - FUNCTION(blsp_i2c9), - FUNCTION(blsp_i2c10), - FUNCTION(blsp_i2c11), - FUNCTION(blsp_i2c12), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi1_cs1), - FUNCTION(blsp_spi1_cs2), - FUNCTION(blsp_spi1_cs3), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi2_cs1), - FUNCTION(blsp_spi2_cs2), - FUNCTION(blsp_spi2_cs3), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_spi6), - FUNCTION(blsp_spi7), - FUNCTION(blsp_spi8), - FUNCTION(blsp_spi9), - FUNCTION(blsp_spi10), - FUNCTION(blsp_spi10_cs1), - FUNCTION(blsp_spi10_cs2), - FUNCTION(blsp_spi10_cs3), - FUNCTION(blsp_spi11), - FUNCTION(blsp_spi12), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uart3), - FUNCTION(blsp_uart4), - FUNCTION(blsp_uart5), - FUNCTION(blsp_uart6), - FUNCTION(blsp_uart7), - FUNCTION(blsp_uart8), - FUNCTION(blsp_uart9), - FUNCTION(blsp_uart10), - FUNCTION(blsp_uart11), - FUNCTION(blsp_uart12), - FUNCTION(blsp_uim1), - FUNCTION(blsp_uim2), - FUNCTION(blsp_uim3), - FUNCTION(blsp_uim4), - FUNCTION(blsp_uim5), - FUNCTION(blsp_uim6), - FUNCTION(blsp_uim7), - FUNCTION(blsp_uim8), - FUNCTION(blsp_uim9), - FUNCTION(blsp_uim10), - FUNCTION(blsp_uim11), - FUNCTION(blsp_uim12), - FUNCTION(blsp11_i2c_scl_b), - FUNCTION(blsp11_i2c_sda_b), - FUNCTION(blsp11_uart_rx_b), - FUNCTION(blsp11_uart_tx_b), - FUNCTION(cam_mclk0), - FUNCTION(cam_mclk1), - FUNCTION(cam_mclk2), - FUNCTION(cam_mclk3), - FUNCTION(cci_async_in0), - FUNCTION(cci_async_in1), - FUNCTION(cci_async_in2), - FUNCTION(cci_i2c0), - FUNCTION(cci_i2c1), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(gcc_gp1_clk_a), - FUNCTION(gcc_gp1_clk_b), - FUNCTION(gcc_gp2_clk_a), - FUNCTION(gcc_gp2_clk_b), - FUNCTION(gcc_gp3_clk_a), - FUNCTION(gcc_gp3_clk_b), - FUNCTION(gp_mn), - FUNCTION(gp_pdm0), - FUNCTION(gp_pdm1), - FUNCTION(gp_pdm2), - FUNCTION(gp0_clk), - FUNCTION(gp1_clk), - FUNCTION(gps_tx), - FUNCTION(gsm_tx), - FUNCTION(hdmi_cec), - FUNCTION(hdmi_ddc), - FUNCTION(hdmi_hpd), - FUNCTION(hdmi_rcv), - FUNCTION(mdp_vsync), - FUNCTION(mss_lte), - FUNCTION(nav_pps), - FUNCTION(nav_tsync), - FUNCTION(qdss_cti_trig_in_a), - FUNCTION(qdss_cti_trig_in_b), - FUNCTION(qdss_cti_trig_in_c), - FUNCTION(qdss_cti_trig_in_d), - FUNCTION(qdss_cti_trig_out_a), - FUNCTION(qdss_cti_trig_out_b), - FUNCTION(qdss_cti_trig_out_c), - FUNCTION(qdss_cti_trig_out_d), - FUNCTION(qdss_traceclk_a), - FUNCTION(qdss_traceclk_b), - FUNCTION(qdss_tracectl_a), - FUNCTION(qdss_tracectl_b), - FUNCTION(qdss_tracedata_a), - FUNCTION(qdss_tracedata_b), - FUNCTION(qua_mi2s), - FUNCTION(pci_e0), - FUNCTION(pci_e1), - FUNCTION(pri_mi2s), - FUNCTION(sdc4), - FUNCTION(sec_mi2s), - FUNCTION(slimbus), - FUNCTION(spkr_i2s), - FUNCTION(ter_mi2s), - FUNCTION(tsif1), - FUNCTION(tsif2), - FUNCTION(uim_batt_alarm), - FUNCTION(uim1), - FUNCTION(uim2), - FUNCTION(uim3), - FUNCTION(uim4), - FUNCTION(gpio), +static const struct pinfunction msm8994_functions[] = { + MSM_PIN_FUNCTION(audio_ref_clk), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(blsp_i2c6), + MSM_PIN_FUNCTION(blsp_i2c7), + MSM_PIN_FUNCTION(blsp_i2c8), + MSM_PIN_FUNCTION(blsp_i2c9), + MSM_PIN_FUNCTION(blsp_i2c10), + MSM_PIN_FUNCTION(blsp_i2c11), + MSM_PIN_FUNCTION(blsp_i2c12), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi1_cs1), + MSM_PIN_FUNCTION(blsp_spi1_cs2), + MSM_PIN_FUNCTION(blsp_spi1_cs3), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi2_cs1), + MSM_PIN_FUNCTION(blsp_spi2_cs2), + MSM_PIN_FUNCTION(blsp_spi2_cs3), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(blsp_spi6), + MSM_PIN_FUNCTION(blsp_spi7), + MSM_PIN_FUNCTION(blsp_spi8), + MSM_PIN_FUNCTION(blsp_spi9), + MSM_PIN_FUNCTION(blsp_spi10), + MSM_PIN_FUNCTION(blsp_spi10_cs1), + MSM_PIN_FUNCTION(blsp_spi10_cs2), + MSM_PIN_FUNCTION(blsp_spi10_cs3), + MSM_PIN_FUNCTION(blsp_spi11), + MSM_PIN_FUNCTION(blsp_spi12), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_uart3), + MSM_PIN_FUNCTION(blsp_uart4), + MSM_PIN_FUNCTION(blsp_uart5), + MSM_PIN_FUNCTION(blsp_uart6), + MSM_PIN_FUNCTION(blsp_uart7), + MSM_PIN_FUNCTION(blsp_uart8), + MSM_PIN_FUNCTION(blsp_uart9), + MSM_PIN_FUNCTION(blsp_uart10), + MSM_PIN_FUNCTION(blsp_uart11), + MSM_PIN_FUNCTION(blsp_uart12), + MSM_PIN_FUNCTION(blsp_uim1), + MSM_PIN_FUNCTION(blsp_uim2), + MSM_PIN_FUNCTION(blsp_uim3), + MSM_PIN_FUNCTION(blsp_uim4), + MSM_PIN_FUNCTION(blsp_uim5), + MSM_PIN_FUNCTION(blsp_uim6), + MSM_PIN_FUNCTION(blsp_uim7), + MSM_PIN_FUNCTION(blsp_uim8), + MSM_PIN_FUNCTION(blsp_uim9), + MSM_PIN_FUNCTION(blsp_uim10), + MSM_PIN_FUNCTION(blsp_uim11), + MSM_PIN_FUNCTION(blsp_uim12), + MSM_PIN_FUNCTION(blsp11_i2c_scl_b), + MSM_PIN_FUNCTION(blsp11_i2c_sda_b), + MSM_PIN_FUNCTION(blsp11_uart_rx_b), + MSM_PIN_FUNCTION(blsp11_uart_tx_b), + MSM_PIN_FUNCTION(cam_mclk0), + MSM_PIN_FUNCTION(cam_mclk1), + MSM_PIN_FUNCTION(cam_mclk2), + MSM_PIN_FUNCTION(cam_mclk3), + MSM_PIN_FUNCTION(cci_async_in0), + MSM_PIN_FUNCTION(cci_async_in1), + MSM_PIN_FUNCTION(cci_async_in2), + MSM_PIN_FUNCTION(cci_i2c0), + MSM_PIN_FUNCTION(cci_i2c1), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(gcc_gp1_clk_a), + MSM_PIN_FUNCTION(gcc_gp1_clk_b), + MSM_PIN_FUNCTION(gcc_gp2_clk_a), + MSM_PIN_FUNCTION(gcc_gp2_clk_b), + MSM_PIN_FUNCTION(gcc_gp3_clk_a), + MSM_PIN_FUNCTION(gcc_gp3_clk_b), + MSM_PIN_FUNCTION(gp_mn), + MSM_PIN_FUNCTION(gp_pdm0), + MSM_PIN_FUNCTION(gp_pdm1), + MSM_PIN_FUNCTION(gp_pdm2), + MSM_PIN_FUNCTION(gp0_clk), + MSM_PIN_FUNCTION(gp1_clk), + MSM_PIN_FUNCTION(gps_tx), + MSM_PIN_FUNCTION(gsm_tx), + MSM_PIN_FUNCTION(hdmi_cec), + MSM_PIN_FUNCTION(hdmi_ddc), + MSM_PIN_FUNCTION(hdmi_hpd), + MSM_PIN_FUNCTION(hdmi_rcv), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(nav_tsync), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b), + MSM_PIN_FUNCTION(qdss_cti_trig_in_c), + MSM_PIN_FUNCTION(qdss_cti_trig_in_d), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b), + MSM_PIN_FUNCTION(qdss_cti_trig_out_c), + MSM_PIN_FUNCTION(qdss_cti_trig_out_d), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(qua_mi2s), + MSM_PIN_FUNCTION(pci_e0), + MSM_PIN_FUNCTION(pci_e1), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(sdc4), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(slimbus), + MSM_PIN_FUNCTION(spkr_i2s), + MSM_PIN_FUNCTION(ter_mi2s), + MSM_PIN_FUNCTION(tsif1), + MSM_PIN_FUNCTION(tsif2), + MSM_PIN_FUNCTION(uim_batt_alarm), + MSM_PIN_FUNCTION(uim1), + MSM_PIN_FUNCTION(uim2), + MSM_PIN_FUNCTION(uim3), + MSM_PIN_FUNCTION(uim4), + MSM_PIN_FUNCTION(gpio), }; static const struct msm_pingroup msm8994_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-msm8996.c b/drivers/pinctrl/qcom/pinctrl-msm8996.c index 05812dfdb368..46cc0b49dbab 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8996.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8996.c @@ -6,24 +6,16 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_BASE 0x0 #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -60,9 +52,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -1409,250 +1401,250 @@ static const char * const qspi3_groups[] = { "gpio149", }; -static const struct msm_function msm8996_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(atest_bbrx0), - FUNCTION(atest_bbrx1), - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(atest_gpsadc0), - FUNCTION(atest_gpsadc1), - FUNCTION(atest_tsens), - FUNCTION(atest_tsens2), - FUNCTION(atest_usb1), - FUNCTION(atest_usb10), - FUNCTION(atest_usb11), - FUNCTION(atest_usb12), - FUNCTION(atest_usb13), - FUNCTION(atest_usb2), - FUNCTION(atest_usb20), - FUNCTION(atest_usb21), - FUNCTION(atest_usb22), - FUNCTION(atest_usb23), - FUNCTION(audio_ref), - FUNCTION(bimc_dte0), - FUNCTION(bimc_dte1), - FUNCTION(blsp10_spi), - FUNCTION(blsp11_i2c_scl_b), - FUNCTION(blsp11_i2c_sda_b), - FUNCTION(blsp11_uart_rx_b), - FUNCTION(blsp11_uart_tx_b), - FUNCTION(blsp1_spi), - FUNCTION(blsp2_spi), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c10), - FUNCTION(blsp_i2c11), - FUNCTION(blsp_i2c12), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_i2c5), - FUNCTION(blsp_i2c6), - FUNCTION(blsp_i2c7), - FUNCTION(blsp_i2c8), - FUNCTION(blsp_i2c9), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi10), - FUNCTION(blsp_spi11), - FUNCTION(blsp_spi12), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_spi6), - FUNCTION(blsp_spi7), - FUNCTION(blsp_spi8), - FUNCTION(blsp_spi9), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart10), - FUNCTION(blsp_uart11), - FUNCTION(blsp_uart12), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uart3), - FUNCTION(blsp_uart4), - FUNCTION(blsp_uart5), - FUNCTION(blsp_uart6), - FUNCTION(blsp_uart7), - FUNCTION(blsp_uart8), - FUNCTION(blsp_uart9), - FUNCTION(blsp_uim1), - FUNCTION(blsp_uim10), - FUNCTION(blsp_uim11), - FUNCTION(blsp_uim12), - FUNCTION(blsp_uim2), - FUNCTION(blsp_uim3), - FUNCTION(blsp_uim4), - FUNCTION(blsp_uim5), - FUNCTION(blsp_uim6), - FUNCTION(blsp_uim7), - FUNCTION(blsp_uim8), - FUNCTION(blsp_uim9), - FUNCTION(btfm_slimbus), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dac_calib0), - FUNCTION(dac_calib1), - FUNCTION(dac_calib10), - FUNCTION(dac_calib11), - FUNCTION(dac_calib12), - FUNCTION(dac_calib13), - FUNCTION(dac_calib14), - FUNCTION(dac_calib15), - FUNCTION(dac_calib16), - FUNCTION(dac_calib17), - FUNCTION(dac_calib18), - FUNCTION(dac_calib19), - FUNCTION(dac_calib2), - FUNCTION(dac_calib20), - FUNCTION(dac_calib21), - FUNCTION(dac_calib22), - FUNCTION(dac_calib23), - FUNCTION(dac_calib24), - FUNCTION(dac_calib25), - FUNCTION(dac_calib26), - FUNCTION(dac_calib3), - FUNCTION(dac_calib4), - FUNCTION(dac_calib5), - FUNCTION(dac_calib6), - FUNCTION(dac_calib7), - FUNCTION(dac_calib8), - FUNCTION(dac_calib9), - FUNCTION(dac_gpio), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(edp_hot), - FUNCTION(edp_lcd), - FUNCTION(gcc_gp1_clk_a), - FUNCTION(gcc_gp1_clk_b), - FUNCTION(gcc_gp2_clk_a), - FUNCTION(gcc_gp2_clk_b), - FUNCTION(gcc_gp3_clk_a), - FUNCTION(gcc_gp3_clk_b), - FUNCTION(gpio), - FUNCTION(gsm_tx), - FUNCTION(hdmi_cec), - FUNCTION(hdmi_ddc), - FUNCTION(hdmi_hot), - FUNCTION(hdmi_rcv), - FUNCTION(isense_dbg), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(lpass_slimbus), - FUNCTION(m_voc), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync_p_b), - FUNCTION(mdp_vsync_s_b), - FUNCTION(modem_tsync), - FUNCTION(mss_lte), - FUNCTION(nav_dr), - FUNCTION(nav_pps), - FUNCTION(pa_indicator), - FUNCTION(pci_e0), - FUNCTION(pci_e1), - FUNCTION(pci_e2), - FUNCTION(pll_bypassnl), - FUNCTION(pll_reset), - FUNCTION(pri_mi2s), - FUNCTION(prng_rosc), - FUNCTION(pwr_crypto), - FUNCTION(pwr_modem), - FUNCTION(pwr_nav), - FUNCTION(qdss_cti), - FUNCTION(qdss_cti_trig_in_a), - FUNCTION(qdss_cti_trig_in_b), - FUNCTION(qdss_cti_trig_out_a), - FUNCTION(qdss_cti_trig_out_b), - FUNCTION(qdss_stm0), - FUNCTION(qdss_stm1), - FUNCTION(qdss_stm10), - FUNCTION(qdss_stm11), - FUNCTION(qdss_stm12), - FUNCTION(qdss_stm13), - FUNCTION(qdss_stm14), - FUNCTION(qdss_stm15), - FUNCTION(qdss_stm16), - FUNCTION(qdss_stm17), - FUNCTION(qdss_stm18), - FUNCTION(qdss_stm19), - FUNCTION(qdss_stm2), - FUNCTION(qdss_stm20), - FUNCTION(qdss_stm21), - FUNCTION(qdss_stm22), - FUNCTION(qdss_stm23), - FUNCTION(qdss_stm24), - FUNCTION(qdss_stm25), - FUNCTION(qdss_stm26), - FUNCTION(qdss_stm27), - FUNCTION(qdss_stm28), - FUNCTION(qdss_stm29), - FUNCTION(qdss_stm3), - FUNCTION(qdss_stm30), - FUNCTION(qdss_stm31), - FUNCTION(qdss_stm4), - FUNCTION(qdss_stm5), - FUNCTION(qdss_stm6), - FUNCTION(qdss_stm7), - FUNCTION(qdss_stm8), - FUNCTION(qdss_stm9), - FUNCTION(qdss_traceclk_a), - FUNCTION(qdss_traceclk_b), - FUNCTION(qdss_tracectl_a), - FUNCTION(qdss_tracectl_b), - FUNCTION(qdss_tracedata_11), - FUNCTION(qdss_tracedata_12), - FUNCTION(qdss_tracedata_a), - FUNCTION(qdss_tracedata_b), - FUNCTION(qspi0), - FUNCTION(qspi1), - FUNCTION(qspi2), - FUNCTION(qspi3), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qua_mi2s), - FUNCTION(sd_card), - FUNCTION(sd_write), - FUNCTION(sdc40), - FUNCTION(sdc41), - FUNCTION(sdc42), - FUNCTION(sdc43), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(sec_mi2s), - FUNCTION(spkr_i2s), - FUNCTION(ssbi1), - FUNCTION(ssbi2), - FUNCTION(ssc_irq), - FUNCTION(ter_mi2s), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(tsif1_clk), - FUNCTION(tsif1_data), - FUNCTION(tsif1_en), - FUNCTION(tsif1_error), - FUNCTION(tsif1_sync), - FUNCTION(tsif2_clk), - FUNCTION(tsif2_data), - FUNCTION(tsif2_en), - FUNCTION(tsif2_error), - FUNCTION(tsif2_sync), - FUNCTION(uim1), - FUNCTION(uim2), - FUNCTION(uim3), - FUNCTION(uim4), - FUNCTION(uim_batt), - FUNCTION(vfr_1), +static const struct pinfunction msm8996_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(atest_bbrx0), + MSM_PIN_FUNCTION(atest_bbrx1), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(atest_gpsadc0), + MSM_PIN_FUNCTION(atest_gpsadc1), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_tsens2), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(atest_usb10), + MSM_PIN_FUNCTION(atest_usb11), + MSM_PIN_FUNCTION(atest_usb12), + MSM_PIN_FUNCTION(atest_usb13), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(atest_usb20), + MSM_PIN_FUNCTION(atest_usb21), + MSM_PIN_FUNCTION(atest_usb22), + MSM_PIN_FUNCTION(atest_usb23), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(bimc_dte0), + MSM_PIN_FUNCTION(bimc_dte1), + MSM_PIN_FUNCTION(blsp10_spi), + MSM_PIN_FUNCTION(blsp11_i2c_scl_b), + MSM_PIN_FUNCTION(blsp11_i2c_sda_b), + MSM_PIN_FUNCTION(blsp11_uart_rx_b), + MSM_PIN_FUNCTION(blsp11_uart_tx_b), + MSM_PIN_FUNCTION(blsp1_spi), + MSM_PIN_FUNCTION(blsp2_spi), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c10), + MSM_PIN_FUNCTION(blsp_i2c11), + MSM_PIN_FUNCTION(blsp_i2c12), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(blsp_i2c6), + MSM_PIN_FUNCTION(blsp_i2c7), + MSM_PIN_FUNCTION(blsp_i2c8), + MSM_PIN_FUNCTION(blsp_i2c9), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi10), + MSM_PIN_FUNCTION(blsp_spi11), + MSM_PIN_FUNCTION(blsp_spi12), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(blsp_spi6), + MSM_PIN_FUNCTION(blsp_spi7), + MSM_PIN_FUNCTION(blsp_spi8), + MSM_PIN_FUNCTION(blsp_spi9), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_uart10), + MSM_PIN_FUNCTION(blsp_uart11), + MSM_PIN_FUNCTION(blsp_uart12), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_uart3), + MSM_PIN_FUNCTION(blsp_uart4), + MSM_PIN_FUNCTION(blsp_uart5), + MSM_PIN_FUNCTION(blsp_uart6), + MSM_PIN_FUNCTION(blsp_uart7), + MSM_PIN_FUNCTION(blsp_uart8), + MSM_PIN_FUNCTION(blsp_uart9), + MSM_PIN_FUNCTION(blsp_uim1), + MSM_PIN_FUNCTION(blsp_uim10), + MSM_PIN_FUNCTION(blsp_uim11), + MSM_PIN_FUNCTION(blsp_uim12), + MSM_PIN_FUNCTION(blsp_uim2), + MSM_PIN_FUNCTION(blsp_uim3), + MSM_PIN_FUNCTION(blsp_uim4), + MSM_PIN_FUNCTION(blsp_uim5), + MSM_PIN_FUNCTION(blsp_uim6), + MSM_PIN_FUNCTION(blsp_uim7), + MSM_PIN_FUNCTION(blsp_uim8), + MSM_PIN_FUNCTION(blsp_uim9), + MSM_PIN_FUNCTION(btfm_slimbus), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dac_calib0), + MSM_PIN_FUNCTION(dac_calib1), + MSM_PIN_FUNCTION(dac_calib10), + MSM_PIN_FUNCTION(dac_calib11), + MSM_PIN_FUNCTION(dac_calib12), + MSM_PIN_FUNCTION(dac_calib13), + MSM_PIN_FUNCTION(dac_calib14), + MSM_PIN_FUNCTION(dac_calib15), + MSM_PIN_FUNCTION(dac_calib16), + MSM_PIN_FUNCTION(dac_calib17), + MSM_PIN_FUNCTION(dac_calib18), + MSM_PIN_FUNCTION(dac_calib19), + MSM_PIN_FUNCTION(dac_calib2), + MSM_PIN_FUNCTION(dac_calib20), + MSM_PIN_FUNCTION(dac_calib21), + MSM_PIN_FUNCTION(dac_calib22), + MSM_PIN_FUNCTION(dac_calib23), + MSM_PIN_FUNCTION(dac_calib24), + MSM_PIN_FUNCTION(dac_calib25), + MSM_PIN_FUNCTION(dac_calib26), + MSM_PIN_FUNCTION(dac_calib3), + MSM_PIN_FUNCTION(dac_calib4), + MSM_PIN_FUNCTION(dac_calib5), + MSM_PIN_FUNCTION(dac_calib6), + MSM_PIN_FUNCTION(dac_calib7), + MSM_PIN_FUNCTION(dac_calib8), + MSM_PIN_FUNCTION(dac_calib9), + MSM_PIN_FUNCTION(dac_gpio), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(edp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(gcc_gp1_clk_a), + MSM_PIN_FUNCTION(gcc_gp1_clk_b), + MSM_PIN_FUNCTION(gcc_gp2_clk_a), + MSM_PIN_FUNCTION(gcc_gp2_clk_b), + MSM_PIN_FUNCTION(gcc_gp3_clk_a), + MSM_PIN_FUNCTION(gcc_gp3_clk_b), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gsm_tx), + MSM_PIN_FUNCTION(hdmi_cec), + MSM_PIN_FUNCTION(hdmi_ddc), + MSM_PIN_FUNCTION(hdmi_hot), + MSM_PIN_FUNCTION(hdmi_rcv), + MSM_PIN_FUNCTION(isense_dbg), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync_p_b), + MSM_PIN_FUNCTION(mdp_vsync_s_b), + MSM_PIN_FUNCTION(modem_tsync), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_dr), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pci_e0), + MSM_PIN_FUNCTION(pci_e1), + MSM_PIN_FUNCTION(pci_e2), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(pwr_crypto), + MSM_PIN_FUNCTION(pwr_modem), + MSM_PIN_FUNCTION(pwr_nav), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b), + MSM_PIN_FUNCTION(qdss_stm0), + MSM_PIN_FUNCTION(qdss_stm1), + MSM_PIN_FUNCTION(qdss_stm10), + MSM_PIN_FUNCTION(qdss_stm11), + MSM_PIN_FUNCTION(qdss_stm12), + MSM_PIN_FUNCTION(qdss_stm13), + MSM_PIN_FUNCTION(qdss_stm14), + MSM_PIN_FUNCTION(qdss_stm15), + MSM_PIN_FUNCTION(qdss_stm16), + MSM_PIN_FUNCTION(qdss_stm17), + MSM_PIN_FUNCTION(qdss_stm18), + MSM_PIN_FUNCTION(qdss_stm19), + MSM_PIN_FUNCTION(qdss_stm2), + MSM_PIN_FUNCTION(qdss_stm20), + MSM_PIN_FUNCTION(qdss_stm21), + MSM_PIN_FUNCTION(qdss_stm22), + MSM_PIN_FUNCTION(qdss_stm23), + MSM_PIN_FUNCTION(qdss_stm24), + MSM_PIN_FUNCTION(qdss_stm25), + MSM_PIN_FUNCTION(qdss_stm26), + MSM_PIN_FUNCTION(qdss_stm27), + MSM_PIN_FUNCTION(qdss_stm28), + MSM_PIN_FUNCTION(qdss_stm29), + MSM_PIN_FUNCTION(qdss_stm3), + MSM_PIN_FUNCTION(qdss_stm30), + MSM_PIN_FUNCTION(qdss_stm31), + MSM_PIN_FUNCTION(qdss_stm4), + MSM_PIN_FUNCTION(qdss_stm5), + MSM_PIN_FUNCTION(qdss_stm6), + MSM_PIN_FUNCTION(qdss_stm7), + MSM_PIN_FUNCTION(qdss_stm8), + MSM_PIN_FUNCTION(qdss_stm9), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(qdss_tracedata_11), + MSM_PIN_FUNCTION(qdss_tracedata_12), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(qspi0), + MSM_PIN_FUNCTION(qspi1), + MSM_PIN_FUNCTION(qspi2), + MSM_PIN_FUNCTION(qspi3), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qua_mi2s), + MSM_PIN_FUNCTION(sd_card), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdc40), + MSM_PIN_FUNCTION(sdc41), + MSM_PIN_FUNCTION(sdc42), + MSM_PIN_FUNCTION(sdc43), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(spkr_i2s), + MSM_PIN_FUNCTION(ssbi1), + MSM_PIN_FUNCTION(ssbi2), + MSM_PIN_FUNCTION(ssc_irq), + MSM_PIN_FUNCTION(ter_mi2s), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(tsif1_clk), + MSM_PIN_FUNCTION(tsif1_data), + MSM_PIN_FUNCTION(tsif1_en), + MSM_PIN_FUNCTION(tsif1_error), + MSM_PIN_FUNCTION(tsif1_sync), + MSM_PIN_FUNCTION(tsif2_clk), + MSM_PIN_FUNCTION(tsif2_data), + MSM_PIN_FUNCTION(tsif2_en), + MSM_PIN_FUNCTION(tsif2_error), + MSM_PIN_FUNCTION(tsif2_sync), + MSM_PIN_FUNCTION(uim1), + MSM_PIN_FUNCTION(uim2), + MSM_PIN_FUNCTION(uim3), + MSM_PIN_FUNCTION(uim4), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(vfr_1), }; static const struct msm_pingroup msm8996_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-msm8998.c b/drivers/pinctrl/qcom/pinctrl-msm8998.c index 1a061bc9b8fa..b7cbf32b3125 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8998.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8998.c @@ -6,7 +6,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" @@ -14,18 +13,11 @@ #define WEST 0x100000 #define EAST 0x900000 -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, base, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -62,9 +54,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -87,9 +79,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -1167,183 +1159,183 @@ static const char * const mss_lte_groups[] = { "gpio144", "gpio145", }; -static const struct msm_function msm8998_functions[] = { - FUNCTION(gpio), - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(atest_char), - FUNCTION(atest_gpsadc0), - FUNCTION(atest_gpsadc1), - FUNCTION(atest_tsens), - FUNCTION(atest_tsens2), - FUNCTION(atest_usb1), - FUNCTION(atest_usb10), - FUNCTION(atest_usb11), - FUNCTION(atest_usb12), - FUNCTION(atest_usb13), - FUNCTION(audio_ref), - FUNCTION(bimc_dte0), - FUNCTION(bimc_dte1), - FUNCTION(blsp10_spi), - FUNCTION(blsp10_spi_a), - FUNCTION(blsp10_spi_b), - FUNCTION(blsp11_i2c), - FUNCTION(blsp1_spi), - FUNCTION(blsp1_spi_a), - FUNCTION(blsp1_spi_b), - FUNCTION(blsp2_spi), - FUNCTION(blsp9_spi), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_i2c5), - FUNCTION(blsp_i2c6), - FUNCTION(blsp_i2c7), - FUNCTION(blsp_i2c8), - FUNCTION(blsp_i2c9), - FUNCTION(blsp_i2c10), - FUNCTION(blsp_i2c11), - FUNCTION(blsp_i2c12), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_spi6), - FUNCTION(blsp_spi7), - FUNCTION(blsp_spi8), - FUNCTION(blsp_spi9), - FUNCTION(blsp_spi10), - FUNCTION(blsp_spi11), - FUNCTION(blsp_spi12), - FUNCTION(blsp_uart1_a), - FUNCTION(blsp_uart1_b), - FUNCTION(blsp_uart2_a), - FUNCTION(blsp_uart2_b), - FUNCTION(blsp_uart3_a), - FUNCTION(blsp_uart3_b), - FUNCTION(blsp_uart7_a), - FUNCTION(blsp_uart7_b), - FUNCTION(blsp_uart8), - FUNCTION(blsp_uart8_a), - FUNCTION(blsp_uart8_b), - FUNCTION(blsp_uart9_a), - FUNCTION(blsp_uart9_b), - FUNCTION(blsp_uim1_a), - FUNCTION(blsp_uim1_b), - FUNCTION(blsp_uim2_a), - FUNCTION(blsp_uim2_b), - FUNCTION(blsp_uim3_a), - FUNCTION(blsp_uim3_b), - FUNCTION(blsp_uim7_a), - FUNCTION(blsp_uim7_b), - FUNCTION(blsp_uim8_a), - FUNCTION(blsp_uim8_b), - FUNCTION(blsp_uim9_a), - FUNCTION(blsp_uim9_b), - FUNCTION(bt_reset), - FUNCTION(btfm_slimbus), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(edp_hot), - FUNCTION(edp_lcd), - FUNCTION(gcc_gp1_a), - FUNCTION(gcc_gp1_b), - FUNCTION(gcc_gp2_a), - FUNCTION(gcc_gp2_b), - FUNCTION(gcc_gp3_a), - FUNCTION(gcc_gp3_b), - FUNCTION(hdmi_cec), - FUNCTION(hdmi_ddc), - FUNCTION(hdmi_hot), - FUNCTION(hdmi_rcv), - FUNCTION(isense_dbg), - FUNCTION(jitter_bist), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(lpass_slimbus), - FUNCTION(m_voc), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mdp_vsync_a), - FUNCTION(mdp_vsync_b), - FUNCTION(modem_tsync), - FUNCTION(mss_lte), - FUNCTION(nav_dr), - FUNCTION(nav_pps), - FUNCTION(pa_indicator), - FUNCTION(pci_e0), - FUNCTION(phase_flag), - FUNCTION(pll_bypassnl), - FUNCTION(pll_reset), - FUNCTION(pri_mi2s), - FUNCTION(pri_mi2s_ws), - FUNCTION(prng_rosc), - FUNCTION(pwr_crypto), - FUNCTION(pwr_modem), - FUNCTION(pwr_nav), - FUNCTION(qdss_cti0_a), - FUNCTION(qdss_cti0_b), - FUNCTION(qdss_cti1_a), - FUNCTION(qdss_cti1_b), - FUNCTION(qdss), - FUNCTION(qlink_enable), - FUNCTION(qlink_request), - FUNCTION(qua_mi2s), - FUNCTION(sd_card), - FUNCTION(sd_write), - FUNCTION(sdc40), - FUNCTION(sdc41), - FUNCTION(sdc42), - FUNCTION(sdc43), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(sec_mi2s), - FUNCTION(sp_cmu), - FUNCTION(spkr_i2s), - FUNCTION(ssbi1), - FUNCTION(ssc_irq), - FUNCTION(ter_mi2s), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(tsif0), - FUNCTION(tsif1), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(uim_batt), - FUNCTION(usb_phy), - FUNCTION(vfr_1), - FUNCTION(vsense_clkout), - FUNCTION(vsense_data0), - FUNCTION(vsense_data1), - FUNCTION(vsense_mode), - FUNCTION(wlan1_adc0), - FUNCTION(wlan1_adc1), - FUNCTION(wlan2_adc0), - FUNCTION(wlan2_adc1), +static const struct pinfunction msm8998_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_gpsadc0), + MSM_PIN_FUNCTION(atest_gpsadc1), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_tsens2), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(atest_usb10), + MSM_PIN_FUNCTION(atest_usb11), + MSM_PIN_FUNCTION(atest_usb12), + MSM_PIN_FUNCTION(atest_usb13), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(bimc_dte0), + MSM_PIN_FUNCTION(bimc_dte1), + MSM_PIN_FUNCTION(blsp10_spi), + MSM_PIN_FUNCTION(blsp10_spi_a), + MSM_PIN_FUNCTION(blsp10_spi_b), + MSM_PIN_FUNCTION(blsp11_i2c), + MSM_PIN_FUNCTION(blsp1_spi), + MSM_PIN_FUNCTION(blsp1_spi_a), + MSM_PIN_FUNCTION(blsp1_spi_b), + MSM_PIN_FUNCTION(blsp2_spi), + MSM_PIN_FUNCTION(blsp9_spi), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(blsp_i2c6), + MSM_PIN_FUNCTION(blsp_i2c7), + MSM_PIN_FUNCTION(blsp_i2c8), + MSM_PIN_FUNCTION(blsp_i2c9), + MSM_PIN_FUNCTION(blsp_i2c10), + MSM_PIN_FUNCTION(blsp_i2c11), + MSM_PIN_FUNCTION(blsp_i2c12), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(blsp_spi6), + MSM_PIN_FUNCTION(blsp_spi7), + MSM_PIN_FUNCTION(blsp_spi8), + MSM_PIN_FUNCTION(blsp_spi9), + MSM_PIN_FUNCTION(blsp_spi10), + MSM_PIN_FUNCTION(blsp_spi11), + MSM_PIN_FUNCTION(blsp_spi12), + MSM_PIN_FUNCTION(blsp_uart1_a), + MSM_PIN_FUNCTION(blsp_uart1_b), + MSM_PIN_FUNCTION(blsp_uart2_a), + MSM_PIN_FUNCTION(blsp_uart2_b), + MSM_PIN_FUNCTION(blsp_uart3_a), + MSM_PIN_FUNCTION(blsp_uart3_b), + MSM_PIN_FUNCTION(blsp_uart7_a), + MSM_PIN_FUNCTION(blsp_uart7_b), + MSM_PIN_FUNCTION(blsp_uart8), + MSM_PIN_FUNCTION(blsp_uart8_a), + MSM_PIN_FUNCTION(blsp_uart8_b), + MSM_PIN_FUNCTION(blsp_uart9_a), + MSM_PIN_FUNCTION(blsp_uart9_b), + MSM_PIN_FUNCTION(blsp_uim1_a), + MSM_PIN_FUNCTION(blsp_uim1_b), + MSM_PIN_FUNCTION(blsp_uim2_a), + MSM_PIN_FUNCTION(blsp_uim2_b), + MSM_PIN_FUNCTION(blsp_uim3_a), + MSM_PIN_FUNCTION(blsp_uim3_b), + MSM_PIN_FUNCTION(blsp_uim7_a), + MSM_PIN_FUNCTION(blsp_uim7_b), + MSM_PIN_FUNCTION(blsp_uim8_a), + MSM_PIN_FUNCTION(blsp_uim8_b), + MSM_PIN_FUNCTION(blsp_uim9_a), + MSM_PIN_FUNCTION(blsp_uim9_b), + MSM_PIN_FUNCTION(bt_reset), + MSM_PIN_FUNCTION(btfm_slimbus), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(edp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(gcc_gp1_a), + MSM_PIN_FUNCTION(gcc_gp1_b), + MSM_PIN_FUNCTION(gcc_gp2_a), + MSM_PIN_FUNCTION(gcc_gp2_b), + MSM_PIN_FUNCTION(gcc_gp3_a), + MSM_PIN_FUNCTION(gcc_gp3_b), + MSM_PIN_FUNCTION(hdmi_cec), + MSM_PIN_FUNCTION(hdmi_ddc), + MSM_PIN_FUNCTION(hdmi_hot), + MSM_PIN_FUNCTION(hdmi_rcv), + MSM_PIN_FUNCTION(isense_dbg), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mdp_vsync_a), + MSM_PIN_FUNCTION(mdp_vsync_b), + MSM_PIN_FUNCTION(modem_tsync), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_dr), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pci_e0), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(pri_mi2s_ws), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(pwr_crypto), + MSM_PIN_FUNCTION(pwr_modem), + MSM_PIN_FUNCTION(pwr_nav), + MSM_PIN_FUNCTION(qdss_cti0_a), + MSM_PIN_FUNCTION(qdss_cti0_b), + MSM_PIN_FUNCTION(qdss_cti1_a), + MSM_PIN_FUNCTION(qdss_cti1_b), + MSM_PIN_FUNCTION(qdss), + MSM_PIN_FUNCTION(qlink_enable), + MSM_PIN_FUNCTION(qlink_request), + MSM_PIN_FUNCTION(qua_mi2s), + MSM_PIN_FUNCTION(sd_card), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdc40), + MSM_PIN_FUNCTION(sdc41), + MSM_PIN_FUNCTION(sdc42), + MSM_PIN_FUNCTION(sdc43), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(sp_cmu), + MSM_PIN_FUNCTION(spkr_i2s), + MSM_PIN_FUNCTION(ssbi1), + MSM_PIN_FUNCTION(ssc_irq), + MSM_PIN_FUNCTION(ter_mi2s), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(tsif0), + MSM_PIN_FUNCTION(tsif1), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_clkout), + MSM_PIN_FUNCTION(vsense_data0), + MSM_PIN_FUNCTION(vsense_data1), + MSM_PIN_FUNCTION(vsense_mode), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(wlan1_adc1), + MSM_PIN_FUNCTION(wlan2_adc0), + MSM_PIN_FUNCTION(wlan2_adc1), }; static const struct msm_pingroup msm8998_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-msm8x74.c b/drivers/pinctrl/qcom/pinctrl-msm8x74.c index 3d193acee6a3..d5fe62992849 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8x74.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8x74.c @@ -6,7 +6,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" @@ -325,27 +324,20 @@ static const unsigned int sdc2_data_pins[] = { 151 }; static const unsigned int hsic_strobe_pins[] = { 152 }; static const unsigned int hsic_data_pins[] = { 153 }; -#define FUNCTION(fname) \ - [MSM_MUX_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ - MSM_MUX_gpio, \ - MSM_MUX_##f1, \ - MSM_MUX_##f2, \ - MSM_MUX_##f3, \ - MSM_MUX_##f4, \ - MSM_MUX_##f5, \ - MSM_MUX_##f6, \ - MSM_MUX_##f7 \ + msm_mux_gpio, \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7 \ }, \ .nfuncs = 8, \ .ctl_reg = 0x1000 + 0x10 * id, \ @@ -371,9 +363,9 @@ static const unsigned int hsic_data_pins[] = { 153 }; #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -397,12 +389,12 @@ static const unsigned int hsic_data_pins[] = { 153 }; #define HSIC_PINGROUP(pg_name, ctl) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .funcs = (int[]){ \ - MSM_MUX_gpio, \ - MSM_MUX_hsic_ctl, \ + msm_mux_gpio, \ + msm_mux_hsic_ctl, \ }, \ .nfuncs = 2, \ .ctl_reg = ctl, \ @@ -431,113 +423,113 @@ static const unsigned int hsic_data_pins[] = { 153 }; * the pingroup table below. */ enum msm8x74_functions { - MSM_MUX_gpio, - MSM_MUX_cci_i2c0, - MSM_MUX_cci_i2c1, - MSM_MUX_blsp_i2c1, - MSM_MUX_blsp_i2c2, - MSM_MUX_blsp_i2c3, - MSM_MUX_blsp_i2c4, - MSM_MUX_blsp_i2c5, - MSM_MUX_blsp_i2c6, - MSM_MUX_blsp_i2c7, - MSM_MUX_blsp_i2c8, - MSM_MUX_blsp_i2c9, - MSM_MUX_blsp_i2c10, - MSM_MUX_blsp_i2c11, - MSM_MUX_blsp_i2c12, - MSM_MUX_blsp_spi1, - MSM_MUX_blsp_spi1_cs1, - MSM_MUX_blsp_spi1_cs2, - MSM_MUX_blsp_spi1_cs3, - MSM_MUX_blsp_spi2, - MSM_MUX_blsp_spi2_cs1, - MSM_MUX_blsp_spi2_cs2, - MSM_MUX_blsp_spi2_cs3, - MSM_MUX_blsp_spi3, - MSM_MUX_blsp_spi4, - MSM_MUX_blsp_spi5, - MSM_MUX_blsp_spi6, - MSM_MUX_blsp_spi7, - MSM_MUX_blsp_spi8, - MSM_MUX_blsp_spi9, - MSM_MUX_blsp_spi10, - MSM_MUX_blsp_spi10_cs1, - MSM_MUX_blsp_spi10_cs2, - MSM_MUX_blsp_spi10_cs3, - MSM_MUX_blsp_spi11, - MSM_MUX_blsp_spi12, - MSM_MUX_blsp_uart1, - MSM_MUX_blsp_uart2, - MSM_MUX_blsp_uart3, - MSM_MUX_blsp_uart4, - MSM_MUX_blsp_uart5, - MSM_MUX_blsp_uart6, - MSM_MUX_blsp_uart7, - MSM_MUX_blsp_uart8, - MSM_MUX_blsp_uart9, - MSM_MUX_blsp_uart10, - MSM_MUX_blsp_uart11, - MSM_MUX_blsp_uart12, - MSM_MUX_blsp_uim1, - MSM_MUX_blsp_uim2, - MSM_MUX_blsp_uim3, - MSM_MUX_blsp_uim4, - MSM_MUX_blsp_uim5, - MSM_MUX_blsp_uim6, - MSM_MUX_blsp_uim7, - MSM_MUX_blsp_uim8, - MSM_MUX_blsp_uim9, - MSM_MUX_blsp_uim10, - MSM_MUX_blsp_uim11, - MSM_MUX_blsp_uim12, - MSM_MUX_uim1, - MSM_MUX_uim2, - MSM_MUX_uim_batt_alarm, - MSM_MUX_sdc3, - MSM_MUX_sdc4, - MSM_MUX_gcc_gp_clk1, - MSM_MUX_gcc_gp_clk2, - MSM_MUX_gcc_gp_clk3, - MSM_MUX_qua_mi2s, - MSM_MUX_pri_mi2s, - MSM_MUX_spkr_mi2s, - MSM_MUX_ter_mi2s, - MSM_MUX_sec_mi2s, - MSM_MUX_hdmi_cec, - MSM_MUX_hdmi_ddc, - MSM_MUX_hdmi_hpd, - MSM_MUX_edp_hpd, - MSM_MUX_mdp_vsync, - MSM_MUX_cam_mclk0, - MSM_MUX_cam_mclk1, - MSM_MUX_cam_mclk2, - MSM_MUX_cam_mclk3, - MSM_MUX_cci_timer0, - MSM_MUX_cci_timer1, - MSM_MUX_cci_timer2, - MSM_MUX_cci_timer3, - MSM_MUX_cci_timer4, - MSM_MUX_cci_async_in0, - MSM_MUX_cci_async_in1, - MSM_MUX_cci_async_in2, - MSM_MUX_gp_pdm0, - MSM_MUX_gp_pdm1, - MSM_MUX_gp_pdm2, - MSM_MUX_gp0_clk, - MSM_MUX_gp1_clk, - MSM_MUX_gp_mn, - MSM_MUX_tsif1, - MSM_MUX_tsif2, - MSM_MUX_hsic, - MSM_MUX_grfc, - MSM_MUX_audio_ref_clk, - MSM_MUX_bt, - MSM_MUX_fm, - MSM_MUX_wlan, - MSM_MUX_slimbus, - MSM_MUX_hsic_ctl, - MSM_MUX_NA, + msm_mux_gpio, + msm_mux_cci_i2c0, + msm_mux_cci_i2c1, + msm_mux_blsp_i2c1, + msm_mux_blsp_i2c2, + msm_mux_blsp_i2c3, + msm_mux_blsp_i2c4, + msm_mux_blsp_i2c5, + msm_mux_blsp_i2c6, + msm_mux_blsp_i2c7, + msm_mux_blsp_i2c8, + msm_mux_blsp_i2c9, + msm_mux_blsp_i2c10, + msm_mux_blsp_i2c11, + msm_mux_blsp_i2c12, + msm_mux_blsp_spi1, + msm_mux_blsp_spi1_cs1, + msm_mux_blsp_spi1_cs2, + msm_mux_blsp_spi1_cs3, + msm_mux_blsp_spi2, + msm_mux_blsp_spi2_cs1, + msm_mux_blsp_spi2_cs2, + msm_mux_blsp_spi2_cs3, + msm_mux_blsp_spi3, + msm_mux_blsp_spi4, + msm_mux_blsp_spi5, + msm_mux_blsp_spi6, + msm_mux_blsp_spi7, + msm_mux_blsp_spi8, + msm_mux_blsp_spi9, + msm_mux_blsp_spi10, + msm_mux_blsp_spi10_cs1, + msm_mux_blsp_spi10_cs2, + msm_mux_blsp_spi10_cs3, + msm_mux_blsp_spi11, + msm_mux_blsp_spi12, + msm_mux_blsp_uart1, + msm_mux_blsp_uart2, + msm_mux_blsp_uart3, + msm_mux_blsp_uart4, + msm_mux_blsp_uart5, + msm_mux_blsp_uart6, + msm_mux_blsp_uart7, + msm_mux_blsp_uart8, + msm_mux_blsp_uart9, + msm_mux_blsp_uart10, + msm_mux_blsp_uart11, + msm_mux_blsp_uart12, + msm_mux_blsp_uim1, + msm_mux_blsp_uim2, + msm_mux_blsp_uim3, + msm_mux_blsp_uim4, + msm_mux_blsp_uim5, + msm_mux_blsp_uim6, + msm_mux_blsp_uim7, + msm_mux_blsp_uim8, + msm_mux_blsp_uim9, + msm_mux_blsp_uim10, + msm_mux_blsp_uim11, + msm_mux_blsp_uim12, + msm_mux_uim1, + msm_mux_uim2, + msm_mux_uim_batt_alarm, + msm_mux_sdc3, + msm_mux_sdc4, + msm_mux_gcc_gp_clk1, + msm_mux_gcc_gp_clk2, + msm_mux_gcc_gp_clk3, + msm_mux_qua_mi2s, + msm_mux_pri_mi2s, + msm_mux_spkr_mi2s, + msm_mux_ter_mi2s, + msm_mux_sec_mi2s, + msm_mux_hdmi_cec, + msm_mux_hdmi_ddc, + msm_mux_hdmi_hpd, + msm_mux_edp_hpd, + msm_mux_mdp_vsync, + msm_mux_cam_mclk0, + msm_mux_cam_mclk1, + msm_mux_cam_mclk2, + msm_mux_cam_mclk3, + msm_mux_cci_timer0, + msm_mux_cci_timer1, + msm_mux_cci_timer2, + msm_mux_cci_timer3, + msm_mux_cci_timer4, + msm_mux_cci_async_in0, + msm_mux_cci_async_in1, + msm_mux_cci_async_in2, + msm_mux_gp_pdm0, + msm_mux_gp_pdm1, + msm_mux_gp_pdm2, + msm_mux_gp0_clk, + msm_mux_gp1_clk, + msm_mux_gp_mn, + msm_mux_tsif1, + msm_mux_tsif2, + msm_mux_hsic, + msm_mux_grfc, + msm_mux_audio_ref_clk, + msm_mux_bt, + msm_mux_fm, + msm_mux_wlan, + msm_mux_slimbus, + msm_mux_hsic_ctl, + msm_mux_NA, }; static const char * const gpio_groups[] = { @@ -785,113 +777,113 @@ static const char * const wlan_groups[] = { static const char * const slimbus_groups[] = { "gpio70", "gpio71" }; static const char * const hsic_ctl_groups[] = { "hsic_strobe", "hsic_data" }; -static const struct msm_function msm8x74_functions[] = { - FUNCTION(gpio), - FUNCTION(cci_i2c0), - FUNCTION(cci_i2c1), - FUNCTION(uim1), - FUNCTION(uim2), - FUNCTION(uim_batt_alarm), - FUNCTION(blsp_uim1), - FUNCTION(blsp_uim2), - FUNCTION(blsp_uim3), - FUNCTION(blsp_uim4), - FUNCTION(blsp_uim5), - FUNCTION(blsp_uim6), - FUNCTION(blsp_uim7), - FUNCTION(blsp_uim8), - FUNCTION(blsp_uim9), - FUNCTION(blsp_uim10), - FUNCTION(blsp_uim11), - FUNCTION(blsp_uim12), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_i2c5), - FUNCTION(blsp_i2c6), - FUNCTION(blsp_i2c7), - FUNCTION(blsp_i2c8), - FUNCTION(blsp_i2c9), - FUNCTION(blsp_i2c10), - FUNCTION(blsp_i2c11), - FUNCTION(blsp_i2c12), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi1_cs1), - FUNCTION(blsp_spi1_cs2), - FUNCTION(blsp_spi1_cs3), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi2_cs1), - FUNCTION(blsp_spi2_cs2), - FUNCTION(blsp_spi2_cs3), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_spi6), - FUNCTION(blsp_spi7), - FUNCTION(blsp_spi8), - FUNCTION(blsp_spi9), - FUNCTION(blsp_spi10), - FUNCTION(blsp_spi10_cs1), - FUNCTION(blsp_spi10_cs2), - FUNCTION(blsp_spi10_cs3), - FUNCTION(blsp_spi11), - FUNCTION(blsp_spi12), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uart3), - FUNCTION(blsp_uart4), - FUNCTION(blsp_uart5), - FUNCTION(blsp_uart6), - FUNCTION(blsp_uart7), - FUNCTION(blsp_uart8), - FUNCTION(blsp_uart9), - FUNCTION(blsp_uart10), - FUNCTION(blsp_uart11), - FUNCTION(blsp_uart12), - FUNCTION(sdc3), - FUNCTION(sdc4), - FUNCTION(gcc_gp_clk1), - FUNCTION(gcc_gp_clk2), - FUNCTION(gcc_gp_clk3), - FUNCTION(qua_mi2s), - FUNCTION(pri_mi2s), - FUNCTION(spkr_mi2s), - FUNCTION(ter_mi2s), - FUNCTION(sec_mi2s), - FUNCTION(mdp_vsync), - FUNCTION(cam_mclk0), - FUNCTION(cam_mclk1), - FUNCTION(cam_mclk2), - FUNCTION(cam_mclk3), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cci_async_in0), - FUNCTION(cci_async_in1), - FUNCTION(cci_async_in2), - FUNCTION(hdmi_cec), - FUNCTION(hdmi_ddc), - FUNCTION(hdmi_hpd), - FUNCTION(edp_hpd), - FUNCTION(gp_pdm0), - FUNCTION(gp_pdm1), - FUNCTION(gp_pdm2), - FUNCTION(gp0_clk), - FUNCTION(gp1_clk), - FUNCTION(gp_mn), - FUNCTION(tsif1), - FUNCTION(tsif2), - FUNCTION(hsic), - FUNCTION(grfc), - FUNCTION(audio_ref_clk), - FUNCTION(bt), - FUNCTION(fm), - FUNCTION(wlan), - FUNCTION(slimbus), - FUNCTION(hsic_ctl), +static const struct pinfunction msm8x74_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(cci_i2c0), + MSM_PIN_FUNCTION(cci_i2c1), + MSM_PIN_FUNCTION(uim1), + MSM_PIN_FUNCTION(uim2), + MSM_PIN_FUNCTION(uim_batt_alarm), + MSM_PIN_FUNCTION(blsp_uim1), + MSM_PIN_FUNCTION(blsp_uim2), + MSM_PIN_FUNCTION(blsp_uim3), + MSM_PIN_FUNCTION(blsp_uim4), + MSM_PIN_FUNCTION(blsp_uim5), + MSM_PIN_FUNCTION(blsp_uim6), + MSM_PIN_FUNCTION(blsp_uim7), + MSM_PIN_FUNCTION(blsp_uim8), + MSM_PIN_FUNCTION(blsp_uim9), + MSM_PIN_FUNCTION(blsp_uim10), + MSM_PIN_FUNCTION(blsp_uim11), + MSM_PIN_FUNCTION(blsp_uim12), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(blsp_i2c6), + MSM_PIN_FUNCTION(blsp_i2c7), + MSM_PIN_FUNCTION(blsp_i2c8), + MSM_PIN_FUNCTION(blsp_i2c9), + MSM_PIN_FUNCTION(blsp_i2c10), + MSM_PIN_FUNCTION(blsp_i2c11), + MSM_PIN_FUNCTION(blsp_i2c12), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi1_cs1), + MSM_PIN_FUNCTION(blsp_spi1_cs2), + MSM_PIN_FUNCTION(blsp_spi1_cs3), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi2_cs1), + MSM_PIN_FUNCTION(blsp_spi2_cs2), + MSM_PIN_FUNCTION(blsp_spi2_cs3), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(blsp_spi6), + MSM_PIN_FUNCTION(blsp_spi7), + MSM_PIN_FUNCTION(blsp_spi8), + MSM_PIN_FUNCTION(blsp_spi9), + MSM_PIN_FUNCTION(blsp_spi10), + MSM_PIN_FUNCTION(blsp_spi10_cs1), + MSM_PIN_FUNCTION(blsp_spi10_cs2), + MSM_PIN_FUNCTION(blsp_spi10_cs3), + MSM_PIN_FUNCTION(blsp_spi11), + MSM_PIN_FUNCTION(blsp_spi12), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_uart3), + MSM_PIN_FUNCTION(blsp_uart4), + MSM_PIN_FUNCTION(blsp_uart5), + MSM_PIN_FUNCTION(blsp_uart6), + MSM_PIN_FUNCTION(blsp_uart7), + MSM_PIN_FUNCTION(blsp_uart8), + MSM_PIN_FUNCTION(blsp_uart9), + MSM_PIN_FUNCTION(blsp_uart10), + MSM_PIN_FUNCTION(blsp_uart11), + MSM_PIN_FUNCTION(blsp_uart12), + MSM_PIN_FUNCTION(sdc3), + MSM_PIN_FUNCTION(sdc4), + MSM_PIN_FUNCTION(gcc_gp_clk1), + MSM_PIN_FUNCTION(gcc_gp_clk2), + MSM_PIN_FUNCTION(gcc_gp_clk3), + MSM_PIN_FUNCTION(qua_mi2s), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(spkr_mi2s), + MSM_PIN_FUNCTION(ter_mi2s), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(cam_mclk0), + MSM_PIN_FUNCTION(cam_mclk1), + MSM_PIN_FUNCTION(cam_mclk2), + MSM_PIN_FUNCTION(cam_mclk3), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cci_async_in0), + MSM_PIN_FUNCTION(cci_async_in1), + MSM_PIN_FUNCTION(cci_async_in2), + MSM_PIN_FUNCTION(hdmi_cec), + MSM_PIN_FUNCTION(hdmi_ddc), + MSM_PIN_FUNCTION(hdmi_hpd), + MSM_PIN_FUNCTION(edp_hpd), + MSM_PIN_FUNCTION(gp_pdm0), + MSM_PIN_FUNCTION(gp_pdm1), + MSM_PIN_FUNCTION(gp_pdm2), + MSM_PIN_FUNCTION(gp0_clk), + MSM_PIN_FUNCTION(gp1_clk), + MSM_PIN_FUNCTION(gp_mn), + MSM_PIN_FUNCTION(tsif1), + MSM_PIN_FUNCTION(tsif2), + MSM_PIN_FUNCTION(hsic), + MSM_PIN_FUNCTION(grfc), + MSM_PIN_FUNCTION(audio_ref_clk), + MSM_PIN_FUNCTION(bt), + MSM_PIN_FUNCTION(fm), + MSM_PIN_FUNCTION(wlan), + MSM_PIN_FUNCTION(slimbus), + MSM_PIN_FUNCTION(hsic_ctl), }; static const struct msm_pingroup msm8x74_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-qcm2290.c b/drivers/pinctrl/qcom/pinctrl-qcm2290.c index aa9325f333fb..ba699eac9ee8 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcm2290.c +++ b/drivers/pinctrl/qcom/pinctrl-qcm2290.c @@ -6,24 +6,16 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -60,9 +52,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -85,9 +77,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -837,108 +829,108 @@ static const char * const pwm_9_groups[] = { "gpio115", }; -static const struct msm_function qcm2290_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(atest), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(char_exec), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dac_calib), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gpio), - FUNCTION(gp_pdm0), - FUNCTION(gp_pdm1), - FUNCTION(gp_pdm2), - FUNCTION(gsm0_tx), - FUNCTION(gsm1_tx), - FUNCTION(jitter_bist), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync_out_0), - FUNCTION(mdp_vsync_out_1), - FUNCTION(mpm_pwr), - FUNCTION(mss_lte), - FUNCTION(m_voc), - FUNCTION(nav_gpio), - FUNCTION(pa_indicator), - FUNCTION(pbs0), - FUNCTION(pbs1), - FUNCTION(pbs2), - FUNCTION(pbs3), - FUNCTION(pbs4), - FUNCTION(pbs5), - FUNCTION(pbs6), - FUNCTION(pbs7), - FUNCTION(pbs8), - FUNCTION(pbs9), - FUNCTION(pbs10), - FUNCTION(pbs11), - FUNCTION(pbs12), - FUNCTION(pbs13), - FUNCTION(pbs14), - FUNCTION(pbs15), - FUNCTION(pbs_out), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_bypassnl), - FUNCTION(pll_reset), - FUNCTION(prng_rosc), - FUNCTION(pwm_0), - FUNCTION(pwm_1), - FUNCTION(pwm_2), - FUNCTION(pwm_3), - FUNCTION(pwm_4), - FUNCTION(pwm_5), - FUNCTION(pwm_6), - FUNCTION(pwm_7), - FUNCTION(pwm_8), - FUNCTION(pwm_9), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qup0), - FUNCTION(qup1), - FUNCTION(qup2), - FUNCTION(qup3), - FUNCTION(qup4), - FUNCTION(qup5), - FUNCTION(sdc1_tb), - FUNCTION(sdc2_tb), - FUNCTION(sd_write), - FUNCTION(ssbi_wtr1), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tsense_pwm), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(usb_phy), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), - FUNCTION(wlan1_adc0), - FUNCTION(wlan1_adc1), +static const struct pinfunction qcm2290_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(atest), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(char_exec), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dac_calib), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gp_pdm0), + MSM_PIN_FUNCTION(gp_pdm1), + MSM_PIN_FUNCTION(gp_pdm2), + MSM_PIN_FUNCTION(gsm0_tx), + MSM_PIN_FUNCTION(gsm1_tx), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync_out_0), + MSM_PIN_FUNCTION(mdp_vsync_out_1), + MSM_PIN_FUNCTION(mpm_pwr), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(nav_gpio), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pbs0), + MSM_PIN_FUNCTION(pbs1), + MSM_PIN_FUNCTION(pbs2), + MSM_PIN_FUNCTION(pbs3), + MSM_PIN_FUNCTION(pbs4), + MSM_PIN_FUNCTION(pbs5), + MSM_PIN_FUNCTION(pbs6), + MSM_PIN_FUNCTION(pbs7), + MSM_PIN_FUNCTION(pbs8), + MSM_PIN_FUNCTION(pbs9), + MSM_PIN_FUNCTION(pbs10), + MSM_PIN_FUNCTION(pbs11), + MSM_PIN_FUNCTION(pbs12), + MSM_PIN_FUNCTION(pbs13), + MSM_PIN_FUNCTION(pbs14), + MSM_PIN_FUNCTION(pbs15), + MSM_PIN_FUNCTION(pbs_out), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(pwm_0), + MSM_PIN_FUNCTION(pwm_1), + MSM_PIN_FUNCTION(pwm_2), + MSM_PIN_FUNCTION(pwm_3), + MSM_PIN_FUNCTION(pwm_4), + MSM_PIN_FUNCTION(pwm_5), + MSM_PIN_FUNCTION(pwm_6), + MSM_PIN_FUNCTION(pwm_7), + MSM_PIN_FUNCTION(pwm_8), + MSM_PIN_FUNCTION(pwm_9), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qup0), + MSM_PIN_FUNCTION(qup1), + MSM_PIN_FUNCTION(qup2), + MSM_PIN_FUNCTION(qup3), + MSM_PIN_FUNCTION(qup4), + MSM_PIN_FUNCTION(qup5), + MSM_PIN_FUNCTION(sdc1_tb), + MSM_PIN_FUNCTION(sdc2_tb), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(ssbi_wtr1), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tsense_pwm), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(wlan1_adc1), }; /* Every pin is maintained as a single group, and missing or non-existing pin diff --git a/drivers/pinctrl/qcom/pinctrl-qcs404.c b/drivers/pinctrl/qcom/pinctrl-qcs404.c index 1c6ba978c69f..ae7224012f8a 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcs404.c +++ b/drivers/pinctrl/qcom/pinctrl-qcs404.c @@ -6,7 +6,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" @@ -22,18 +21,11 @@ enum { EAST }; -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -71,9 +63,9 @@ enum { #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -1303,190 +1295,190 @@ static const char * const i2s_3_ws_a_groups[] = { "gpio105", }; -static const struct msm_function qcs404_functions[] = { - FUNCTION(gpio), - FUNCTION(hdmi_tx), - FUNCTION(hdmi_ddc), - FUNCTION(blsp_uart_tx_a2), - FUNCTION(blsp_spi2), - FUNCTION(m_voc), - FUNCTION(qdss_cti_trig_in_a0), - FUNCTION(blsp_uart_rx_a2), - FUNCTION(qdss_tracectl_a), - FUNCTION(blsp_uart2), - FUNCTION(aud_cdc), - FUNCTION(blsp_i2c_sda_a2), - FUNCTION(qdss_tracedata_a), - FUNCTION(blsp_i2c_scl_a2), - FUNCTION(qdss_tracectl_b), - FUNCTION(qdss_cti_trig_in_b0), - FUNCTION(blsp_uart1), - FUNCTION(blsp_spi_mosi_a1), - FUNCTION(blsp_spi_miso_a1), - FUNCTION(qdss_tracedata_b), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_spi_cs_n_a1), - FUNCTION(gcc_plltest), - FUNCTION(blsp_spi_clk_a1), - FUNCTION(rgb_data0), - FUNCTION(blsp_uart5), - FUNCTION(blsp_spi5), - FUNCTION(adsp_ext), - FUNCTION(rgb_data1), - FUNCTION(prng_rosc), - FUNCTION(rgb_data2), - FUNCTION(blsp_i2c5), - FUNCTION(gcc_gp1_clk_b), - FUNCTION(rgb_data3), - FUNCTION(gcc_gp2_clk_b), - FUNCTION(blsp_spi0), - FUNCTION(blsp_uart0), - FUNCTION(gcc_gp3_clk_b), - FUNCTION(blsp_i2c0), - FUNCTION(qdss_traceclk_b), - FUNCTION(pcie_clk), - FUNCTION(nfc_irq), - FUNCTION(blsp_spi4), - FUNCTION(nfc_dwl), - FUNCTION(audio_ts), - FUNCTION(rgb_data4), - FUNCTION(spi_lcd), - FUNCTION(blsp_uart_tx_b2), - FUNCTION(gcc_gp3_clk_a), - FUNCTION(rgb_data5), - FUNCTION(blsp_uart_rx_b2), - FUNCTION(blsp_i2c_sda_b2), - FUNCTION(blsp_i2c_scl_b2), - FUNCTION(pwm_led11), - FUNCTION(i2s_3_data0_a), - FUNCTION(ebi2_lcd), - FUNCTION(i2s_3_data1_a), - FUNCTION(i2s_3_data2_a), - FUNCTION(atest_char), - FUNCTION(pwm_led3), - FUNCTION(i2s_3_data3_a), - FUNCTION(pwm_led4), - FUNCTION(i2s_4), - FUNCTION(ebi2_a), - FUNCTION(dsd_clk_b), - FUNCTION(pwm_led5), - FUNCTION(pwm_led6), - FUNCTION(pwm_led7), - FUNCTION(pwm_led8), - FUNCTION(pwm_led24), - FUNCTION(spkr_dac0), - FUNCTION(blsp_i2c4), - FUNCTION(pwm_led9), - FUNCTION(pwm_led10), - FUNCTION(spdifrx_opt), - FUNCTION(pwm_led12), - FUNCTION(pwm_led13), - FUNCTION(pwm_led14), - FUNCTION(wlan1_adc1), - FUNCTION(rgb_data_b0), - FUNCTION(pwm_led15), - FUNCTION(blsp_spi_mosi_b1), - FUNCTION(wlan1_adc0), - FUNCTION(rgb_data_b1), - FUNCTION(pwm_led16), - FUNCTION(blsp_spi_miso_b1), - FUNCTION(qdss_cti_trig_out_b0), - FUNCTION(wlan2_adc1), - FUNCTION(rgb_data_b2), - FUNCTION(pwm_led17), - FUNCTION(blsp_spi_cs_n_b1), - FUNCTION(wlan2_adc0), - FUNCTION(rgb_data_b3), - FUNCTION(pwm_led18), - FUNCTION(blsp_spi_clk_b1), - FUNCTION(rgb_data_b4), - FUNCTION(pwm_led19), - FUNCTION(ext_mclk1_b), - FUNCTION(qdss_traceclk_a), - FUNCTION(rgb_data_b5), - FUNCTION(pwm_led20), - FUNCTION(atest_char3), - FUNCTION(i2s_3_sck_b), - FUNCTION(ldo_update), - FUNCTION(bimc_dte0), - FUNCTION(rgb_hsync), - FUNCTION(pwm_led21), - FUNCTION(i2s_3_ws_b), - FUNCTION(dbg_out), - FUNCTION(rgb_vsync), - FUNCTION(i2s_3_data0_b), - FUNCTION(ldo_en), - FUNCTION(hdmi_dtest), - FUNCTION(rgb_de), - FUNCTION(i2s_3_data1_b), - FUNCTION(hdmi_lbk9), - FUNCTION(rgb_clk), - FUNCTION(atest_char1), - FUNCTION(i2s_3_data2_b), - FUNCTION(ebi_cdc), - FUNCTION(hdmi_lbk8), - FUNCTION(rgb_mdp), - FUNCTION(atest_char0), - FUNCTION(i2s_3_data3_b), - FUNCTION(hdmi_lbk7), - FUNCTION(rgb_data_b6), - FUNCTION(rgb_data_b7), - FUNCTION(hdmi_lbk6), - FUNCTION(rgmii_int), - FUNCTION(cri_trng1), - FUNCTION(rgmii_wol), - FUNCTION(cri_trng0), - FUNCTION(gcc_tlmm), - FUNCTION(rgmii_ck), - FUNCTION(rgmii_tx), - FUNCTION(hdmi_lbk5), - FUNCTION(hdmi_pixel), - FUNCTION(hdmi_rcv), - FUNCTION(hdmi_lbk4), - FUNCTION(rgmii_ctl), - FUNCTION(ext_lpass), - FUNCTION(rgmii_rx), - FUNCTION(cri_trng), - FUNCTION(hdmi_lbk3), - FUNCTION(hdmi_lbk2), - FUNCTION(qdss_cti_trig_out_b1), - FUNCTION(rgmii_mdio), - FUNCTION(hdmi_lbk1), - FUNCTION(rgmii_mdc), - FUNCTION(hdmi_lbk0), - FUNCTION(ir_in), - FUNCTION(wsa_en), - FUNCTION(rgb_data6), - FUNCTION(rgb_data7), - FUNCTION(atest_char2), - FUNCTION(ebi_ch0), - FUNCTION(blsp_uart3), - FUNCTION(blsp_spi3), - FUNCTION(sd_write), - FUNCTION(blsp_i2c3), - FUNCTION(gcc_gp1_clk_a), - FUNCTION(qdss_cti_trig_in_b1), - FUNCTION(gcc_gp2_clk_a), - FUNCTION(ext_mclk0), - FUNCTION(mclk_in1), - FUNCTION(i2s_1), - FUNCTION(dsd_clk_a), - FUNCTION(qdss_cti_trig_in_a1), - FUNCTION(rgmi_dll1), - FUNCTION(pwm_led22), - FUNCTION(pwm_led23), - FUNCTION(qdss_cti_trig_out_a0), - FUNCTION(rgmi_dll2), - FUNCTION(pwm_led1), - FUNCTION(qdss_cti_trig_out_a1), - FUNCTION(pwm_led2), - FUNCTION(i2s_2), - FUNCTION(pll_bist), - FUNCTION(ext_mclk1_a), - FUNCTION(mclk_in2), - FUNCTION(bimc_dte1), - FUNCTION(i2s_3_sck_a), - FUNCTION(i2s_3_ws_a), +static const struct pinfunction qcs404_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(hdmi_tx), + MSM_PIN_FUNCTION(hdmi_ddc), + MSM_PIN_FUNCTION(blsp_uart_tx_a2), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a0), + MSM_PIN_FUNCTION(blsp_uart_rx_a2), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(aud_cdc), + MSM_PIN_FUNCTION(blsp_i2c_sda_a2), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(blsp_i2c_scl_a2), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b0), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_spi_mosi_a1), + MSM_PIN_FUNCTION(blsp_spi_miso_a1), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_spi_cs_n_a1), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(blsp_spi_clk_a1), + MSM_PIN_FUNCTION(rgb_data0), + MSM_PIN_FUNCTION(blsp_uart5), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(rgb_data1), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(rgb_data2), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(gcc_gp1_clk_b), + MSM_PIN_FUNCTION(rgb_data3), + MSM_PIN_FUNCTION(gcc_gp2_clk_b), + MSM_PIN_FUNCTION(blsp_spi0), + MSM_PIN_FUNCTION(blsp_uart0), + MSM_PIN_FUNCTION(gcc_gp3_clk_b), + MSM_PIN_FUNCTION(blsp_i2c0), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(pcie_clk), + MSM_PIN_FUNCTION(nfc_irq), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(nfc_dwl), + MSM_PIN_FUNCTION(audio_ts), + MSM_PIN_FUNCTION(rgb_data4), + MSM_PIN_FUNCTION(spi_lcd), + MSM_PIN_FUNCTION(blsp_uart_tx_b2), + MSM_PIN_FUNCTION(gcc_gp3_clk_a), + MSM_PIN_FUNCTION(rgb_data5), + MSM_PIN_FUNCTION(blsp_uart_rx_b2), + MSM_PIN_FUNCTION(blsp_i2c_sda_b2), + MSM_PIN_FUNCTION(blsp_i2c_scl_b2), + MSM_PIN_FUNCTION(pwm_led11), + MSM_PIN_FUNCTION(i2s_3_data0_a), + MSM_PIN_FUNCTION(ebi2_lcd), + MSM_PIN_FUNCTION(i2s_3_data1_a), + MSM_PIN_FUNCTION(i2s_3_data2_a), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(pwm_led3), + MSM_PIN_FUNCTION(i2s_3_data3_a), + MSM_PIN_FUNCTION(pwm_led4), + MSM_PIN_FUNCTION(i2s_4), + MSM_PIN_FUNCTION(ebi2_a), + MSM_PIN_FUNCTION(dsd_clk_b), + MSM_PIN_FUNCTION(pwm_led5), + MSM_PIN_FUNCTION(pwm_led6), + MSM_PIN_FUNCTION(pwm_led7), + MSM_PIN_FUNCTION(pwm_led8), + MSM_PIN_FUNCTION(pwm_led24), + MSM_PIN_FUNCTION(spkr_dac0), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(pwm_led9), + MSM_PIN_FUNCTION(pwm_led10), + MSM_PIN_FUNCTION(spdifrx_opt), + MSM_PIN_FUNCTION(pwm_led12), + MSM_PIN_FUNCTION(pwm_led13), + MSM_PIN_FUNCTION(pwm_led14), + MSM_PIN_FUNCTION(wlan1_adc1), + MSM_PIN_FUNCTION(rgb_data_b0), + MSM_PIN_FUNCTION(pwm_led15), + MSM_PIN_FUNCTION(blsp_spi_mosi_b1), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(rgb_data_b1), + MSM_PIN_FUNCTION(pwm_led16), + MSM_PIN_FUNCTION(blsp_spi_miso_b1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b0), + MSM_PIN_FUNCTION(wlan2_adc1), + MSM_PIN_FUNCTION(rgb_data_b2), + MSM_PIN_FUNCTION(pwm_led17), + MSM_PIN_FUNCTION(blsp_spi_cs_n_b1), + MSM_PIN_FUNCTION(wlan2_adc0), + MSM_PIN_FUNCTION(rgb_data_b3), + MSM_PIN_FUNCTION(pwm_led18), + MSM_PIN_FUNCTION(blsp_spi_clk_b1), + MSM_PIN_FUNCTION(rgb_data_b4), + MSM_PIN_FUNCTION(pwm_led19), + MSM_PIN_FUNCTION(ext_mclk1_b), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(rgb_data_b5), + MSM_PIN_FUNCTION(pwm_led20), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(i2s_3_sck_b), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(bimc_dte0), + MSM_PIN_FUNCTION(rgb_hsync), + MSM_PIN_FUNCTION(pwm_led21), + MSM_PIN_FUNCTION(i2s_3_ws_b), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(rgb_vsync), + MSM_PIN_FUNCTION(i2s_3_data0_b), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(hdmi_dtest), + MSM_PIN_FUNCTION(rgb_de), + MSM_PIN_FUNCTION(i2s_3_data1_b), + MSM_PIN_FUNCTION(hdmi_lbk9), + MSM_PIN_FUNCTION(rgb_clk), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(i2s_3_data2_b), + MSM_PIN_FUNCTION(ebi_cdc), + MSM_PIN_FUNCTION(hdmi_lbk8), + MSM_PIN_FUNCTION(rgb_mdp), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(i2s_3_data3_b), + MSM_PIN_FUNCTION(hdmi_lbk7), + MSM_PIN_FUNCTION(rgb_data_b6), + MSM_PIN_FUNCTION(rgb_data_b7), + MSM_PIN_FUNCTION(hdmi_lbk6), + MSM_PIN_FUNCTION(rgmii_int), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(rgmii_wol), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(gcc_tlmm), + MSM_PIN_FUNCTION(rgmii_ck), + MSM_PIN_FUNCTION(rgmii_tx), + MSM_PIN_FUNCTION(hdmi_lbk5), + MSM_PIN_FUNCTION(hdmi_pixel), + MSM_PIN_FUNCTION(hdmi_rcv), + MSM_PIN_FUNCTION(hdmi_lbk4), + MSM_PIN_FUNCTION(rgmii_ctl), + MSM_PIN_FUNCTION(ext_lpass), + MSM_PIN_FUNCTION(rgmii_rx), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(hdmi_lbk3), + MSM_PIN_FUNCTION(hdmi_lbk2), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b1), + MSM_PIN_FUNCTION(rgmii_mdio), + MSM_PIN_FUNCTION(hdmi_lbk1), + MSM_PIN_FUNCTION(rgmii_mdc), + MSM_PIN_FUNCTION(hdmi_lbk0), + MSM_PIN_FUNCTION(ir_in), + MSM_PIN_FUNCTION(wsa_en), + MSM_PIN_FUNCTION(rgb_data6), + MSM_PIN_FUNCTION(rgb_data7), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(ebi_ch0), + MSM_PIN_FUNCTION(blsp_uart3), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(gcc_gp1_clk_a), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b1), + MSM_PIN_FUNCTION(gcc_gp2_clk_a), + MSM_PIN_FUNCTION(ext_mclk0), + MSM_PIN_FUNCTION(mclk_in1), + MSM_PIN_FUNCTION(i2s_1), + MSM_PIN_FUNCTION(dsd_clk_a), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a1), + MSM_PIN_FUNCTION(rgmi_dll1), + MSM_PIN_FUNCTION(pwm_led22), + MSM_PIN_FUNCTION(pwm_led23), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a0), + MSM_PIN_FUNCTION(rgmi_dll2), + MSM_PIN_FUNCTION(pwm_led1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a1), + MSM_PIN_FUNCTION(pwm_led2), + MSM_PIN_FUNCTION(i2s_2), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(ext_mclk1_a), + MSM_PIN_FUNCTION(mclk_in2), + MSM_PIN_FUNCTION(bimc_dte1), + MSM_PIN_FUNCTION(i2s_3_sck_a), + MSM_PIN_FUNCTION(i2s_3_ws_a), }; /* Every pin is maintained as a single group, and missing or non-existing pin diff --git a/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c b/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c index 43bd15f16377..b5808fcfb13c 100644 --- a/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c +++ b/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c @@ -90,17 +90,17 @@ static int qdf2xxx_pinctrl_probe(struct platform_device *pdev) */ for (i = 0; i < num_gpios; i++) { pins[i].number = i; - groups[i].pins = &pins[i].number; + groups[i].grp.pins = &pins[i].number; } /* Populate the entries that are meant to be exposed as GPIOs. */ for (i = 0; i < avail_gpios; i++) { unsigned int gpio = gpios[i]; - groups[gpio].npins = 1; + groups[gpio].grp.npins = 1; snprintf(names[i], NAME_SIZE, "gpio%u", gpio); pins[gpio].name = names[i]; - groups[gpio].name = names[i]; + groups[gpio].grp.name = names[i]; groups[gpio].ctl_reg = 0x10000 * gpio; groups[gpio].io_reg = 0x04 + 0x10000 * gpio; @@ -142,7 +142,7 @@ MODULE_DEVICE_TABLE(acpi, qdf2xxx_acpi_ids); static struct platform_driver qdf2xxx_pinctrl_driver = { .driver = { .name = "qdf2xxx-pinctrl", - .acpi_match_table = ACPI_PTR(qdf2xxx_acpi_ids), + .acpi_match_table = qdf2xxx_acpi_ids, }, .probe = qdf2xxx_pinctrl_probe, .remove = msm_pinctrl_remove, diff --git a/drivers/pinctrl/qcom/pinctrl-qdu1000.c b/drivers/pinctrl/qcom/pinctrl-qdu1000.c index b1d7674a2bec..47bc529ef550 100644 --- a/drivers/pinctrl/qcom/pinctrl-qdu1000.c +++ b/drivers/pinctrl/qcom/pinctrl-qdu1000.c @@ -7,24 +7,17 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_BASE 0x100000 #define REG_SIZE 0x1000 + #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -61,9 +54,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = REG_BASE + ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -86,9 +79,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -910,117 +903,117 @@ static const char * const vsense_trigger_groups[] = { "gpio135", }; -static const struct msm_function qdu1000_functions[] = { - FUNCTION(gpio), - FUNCTION(cmo_pri), - FUNCTION(si5518_int), - FUNCTION(atest_char), - FUNCTION(atest_usb), - FUNCTION(char_exec), - FUNCTION(cmu_rng), - FUNCTION(dbg_out_clk), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(ddr_pxi4), - FUNCTION(ddr_pxi5), - FUNCTION(ddr_pxi6), - FUNCTION(ddr_pxi7), - FUNCTION(eth012_int_n), - FUNCTION(eth345_int_n), - FUNCTION(eth6_int_n), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gps_pps_in), - FUNCTION(hardsync_pps_in), - FUNCTION(intr_c), - FUNCTION(jitter_bist_ref), - FUNCTION(pcie_clkreqn), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_clk), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qlink0_enable), - FUNCTION(qlink0_request), - FUNCTION(qlink0_wmss), - FUNCTION(qlink1_enable), - FUNCTION(qlink1_request), - FUNCTION(qlink1_wmss), - FUNCTION(qlink2_enable), - FUNCTION(qlink2_request), - FUNCTION(qlink2_wmss), - FUNCTION(qlink3_enable), - FUNCTION(qlink3_request), - FUNCTION(qlink3_wmss), - FUNCTION(qlink4_enable), - FUNCTION(qlink4_request), - FUNCTION(qlink4_wmss), - FUNCTION(qlink5_enable), - FUNCTION(qlink5_request), - FUNCTION(qlink5_wmss), - FUNCTION(qlink6_enable), - FUNCTION(qlink6_request), - FUNCTION(qlink6_wmss), - FUNCTION(qlink7_enable), - FUNCTION(qlink7_request), - FUNCTION(qlink7_wmss), - FUNCTION(qspi0), - FUNCTION(qspi1), - FUNCTION(qspi2), - FUNCTION(qspi3), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qup00), - FUNCTION(qup01), - FUNCTION(qup02), - FUNCTION(qup03), - FUNCTION(qup04), - FUNCTION(qup05), - FUNCTION(qup06), - FUNCTION(qup07), - FUNCTION(qup08), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(qup16), - FUNCTION(qup17), - FUNCTION(qup20), - FUNCTION(qup21), - FUNCTION(qup22), - FUNCTION(smb_alert), - FUNCTION(smb_clk), - FUNCTION(smb_dat), - FUNCTION(tb_trig), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tgu_ch4), - FUNCTION(tgu_ch5), - FUNCTION(tgu_ch6), - FUNCTION(tgu_ch7), - FUNCTION(tmess_prng0), - FUNCTION(tmess_prng1), - FUNCTION(tmess_prng2), - FUNCTION(tmess_prng3), - FUNCTION(tod_pps_in), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(usb2phy_ac), - FUNCTION(usb_con_det), - FUNCTION(usb_dfp_en), - FUNCTION(usb_phy), - FUNCTION(vfr_0), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), +static const struct pinfunction qdu1000_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(cmo_pri), + MSM_PIN_FUNCTION(si5518_int), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_usb), + MSM_PIN_FUNCTION(char_exec), + MSM_PIN_FUNCTION(cmu_rng), + MSM_PIN_FUNCTION(dbg_out_clk), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(ddr_pxi4), + MSM_PIN_FUNCTION(ddr_pxi5), + MSM_PIN_FUNCTION(ddr_pxi6), + MSM_PIN_FUNCTION(ddr_pxi7), + MSM_PIN_FUNCTION(eth012_int_n), + MSM_PIN_FUNCTION(eth345_int_n), + MSM_PIN_FUNCTION(eth6_int_n), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gps_pps_in), + MSM_PIN_FUNCTION(hardsync_pps_in), + MSM_PIN_FUNCTION(intr_c), + MSM_PIN_FUNCTION(jitter_bist_ref), + MSM_PIN_FUNCTION(pcie_clkreqn), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_clk), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qlink0_enable), + MSM_PIN_FUNCTION(qlink0_request), + MSM_PIN_FUNCTION(qlink0_wmss), + MSM_PIN_FUNCTION(qlink1_enable), + MSM_PIN_FUNCTION(qlink1_request), + MSM_PIN_FUNCTION(qlink1_wmss), + MSM_PIN_FUNCTION(qlink2_enable), + MSM_PIN_FUNCTION(qlink2_request), + MSM_PIN_FUNCTION(qlink2_wmss), + MSM_PIN_FUNCTION(qlink3_enable), + MSM_PIN_FUNCTION(qlink3_request), + MSM_PIN_FUNCTION(qlink3_wmss), + MSM_PIN_FUNCTION(qlink4_enable), + MSM_PIN_FUNCTION(qlink4_request), + MSM_PIN_FUNCTION(qlink4_wmss), + MSM_PIN_FUNCTION(qlink5_enable), + MSM_PIN_FUNCTION(qlink5_request), + MSM_PIN_FUNCTION(qlink5_wmss), + MSM_PIN_FUNCTION(qlink6_enable), + MSM_PIN_FUNCTION(qlink6_request), + MSM_PIN_FUNCTION(qlink6_wmss), + MSM_PIN_FUNCTION(qlink7_enable), + MSM_PIN_FUNCTION(qlink7_request), + MSM_PIN_FUNCTION(qlink7_wmss), + MSM_PIN_FUNCTION(qspi0), + MSM_PIN_FUNCTION(qspi1), + MSM_PIN_FUNCTION(qspi2), + MSM_PIN_FUNCTION(qspi3), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qup00), + MSM_PIN_FUNCTION(qup01), + MSM_PIN_FUNCTION(qup02), + MSM_PIN_FUNCTION(qup03), + MSM_PIN_FUNCTION(qup04), + MSM_PIN_FUNCTION(qup05), + MSM_PIN_FUNCTION(qup06), + MSM_PIN_FUNCTION(qup07), + MSM_PIN_FUNCTION(qup08), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(qup16), + MSM_PIN_FUNCTION(qup17), + MSM_PIN_FUNCTION(qup20), + MSM_PIN_FUNCTION(qup21), + MSM_PIN_FUNCTION(qup22), + MSM_PIN_FUNCTION(smb_alert), + MSM_PIN_FUNCTION(smb_clk), + MSM_PIN_FUNCTION(smb_dat), + MSM_PIN_FUNCTION(tb_trig), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tgu_ch4), + MSM_PIN_FUNCTION(tgu_ch5), + MSM_PIN_FUNCTION(tgu_ch6), + MSM_PIN_FUNCTION(tgu_ch7), + MSM_PIN_FUNCTION(tmess_prng0), + MSM_PIN_FUNCTION(tmess_prng1), + MSM_PIN_FUNCTION(tmess_prng2), + MSM_PIN_FUNCTION(tmess_prng3), + MSM_PIN_FUNCTION(tod_pps_in), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(usb_con_det), + MSM_PIN_FUNCTION(usb_dfp_en), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_0), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), }; /* diff --git a/drivers/pinctrl/qcom/pinctrl-sa8775p.c b/drivers/pinctrl/qcom/pinctrl-sa8775p.c index 2ae7cdca65d3..8a5cd15512b9 100644 --- a/drivers/pinctrl/qcom/pinctrl-sa8775p.c +++ b/drivers/pinctrl/qcom/pinctrl-sa8775p.c @@ -7,24 +7,16 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_BASE 0x100000 #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9)\ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -63,9 +55,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -88,9 +80,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -1179,147 +1171,147 @@ static const char * const vsense_trigger_groups[] = { "gpio111", }; -static const struct msm_function sa8775p_functions[] = { - FUNCTION(gpio), - FUNCTION(atest_char), - FUNCTION(atest_usb2), - FUNCTION(audio_ref), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cci_timer5), - FUNCTION(cci_timer6), - FUNCTION(cci_timer7), - FUNCTION(cci_timer8), - FUNCTION(cci_timer9), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(ddr_pxi4), - FUNCTION(ddr_pxi5), - FUNCTION(edp0_hot), - FUNCTION(edp0_lcd), - FUNCTION(edp1_hot), - FUNCTION(edp1_lcd), - FUNCTION(edp2_hot), - FUNCTION(edp2_lcd), - FUNCTION(edp3_hot), - FUNCTION(edp3_lcd), - FUNCTION(emac0_mcg0), - FUNCTION(emac0_mcg1), - FUNCTION(emac0_mcg2), - FUNCTION(emac0_mcg3), - FUNCTION(emac0_mdc), - FUNCTION(emac0_mdio), - FUNCTION(emac0_ptp_aux), - FUNCTION(emac0_ptp_pps), - FUNCTION(emac1_mcg0), - FUNCTION(emac1_mcg1), - FUNCTION(emac1_mcg2), - FUNCTION(emac1_mcg3), - FUNCTION(emac1_mdc), - FUNCTION(emac1_mdio), - FUNCTION(emac1_ptp_aux), - FUNCTION(emac1_ptp_pps), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gcc_gp4), - FUNCTION(gcc_gp5), - FUNCTION(hs0_mi2s), - FUNCTION(hs1_mi2s), - FUNCTION(hs2_mi2s), - FUNCTION(ibi_i3c), - FUNCTION(jitter_bist), - FUNCTION(mdp0_vsync0), - FUNCTION(mdp0_vsync1), - FUNCTION(mdp0_vsync2), - FUNCTION(mdp0_vsync3), - FUNCTION(mdp0_vsync4), - FUNCTION(mdp0_vsync5), - FUNCTION(mdp0_vsync6), - FUNCTION(mdp0_vsync7), - FUNCTION(mdp0_vsync8), - FUNCTION(mdp1_vsync0), - FUNCTION(mdp1_vsync1), - FUNCTION(mdp1_vsync2), - FUNCTION(mdp1_vsync3), - FUNCTION(mdp1_vsync4), - FUNCTION(mdp1_vsync5), - FUNCTION(mdp1_vsync6), - FUNCTION(mdp1_vsync7), - FUNCTION(mdp1_vsync8), - FUNCTION(mdp_vsync), - FUNCTION(mi2s1_data0), - FUNCTION(mi2s1_data1), - FUNCTION(mi2s1_sck), - FUNCTION(mi2s1_ws), - FUNCTION(mi2s2_data0), - FUNCTION(mi2s2_data1), - FUNCTION(mi2s2_sck), - FUNCTION(mi2s2_ws), - FUNCTION(mi2s_mclk0), - FUNCTION(mi2s_mclk1), - FUNCTION(pcie0_clkreq), - FUNCTION(pcie1_clkreq), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_clk), - FUNCTION(prng_rosc0), - FUNCTION(prng_rosc1), - FUNCTION(prng_rosc2), - FUNCTION(prng_rosc3), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qup0_se0), - FUNCTION(qup0_se1), - FUNCTION(qup0_se2), - FUNCTION(qup0_se3), - FUNCTION(qup0_se4), - FUNCTION(qup0_se5), - FUNCTION(qup1_se0), - FUNCTION(qup1_se1), - FUNCTION(qup1_se2), - FUNCTION(qup1_se3), - FUNCTION(qup1_se4), - FUNCTION(qup1_se5), - FUNCTION(qup1_se6), - FUNCTION(qup2_se0), - FUNCTION(qup2_se1), - FUNCTION(qup2_se2), - FUNCTION(qup2_se3), - FUNCTION(qup2_se4), - FUNCTION(qup2_se5), - FUNCTION(qup2_se6), - FUNCTION(qup3_se0), - FUNCTION(sail_top), - FUNCTION(sailss_emac0), - FUNCTION(sailss_ospi), - FUNCTION(sgmii_phy), - FUNCTION(tb_trig), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tgu_ch4), - FUNCTION(tgu_ch5), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(tsense_pwm3), - FUNCTION(tsense_pwm4), - FUNCTION(usb2phy_ac), - FUNCTION(vsense_trigger), +static const struct pinfunction sa8775p_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cci_timer5), + MSM_PIN_FUNCTION(cci_timer6), + MSM_PIN_FUNCTION(cci_timer7), + MSM_PIN_FUNCTION(cci_timer8), + MSM_PIN_FUNCTION(cci_timer9), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(ddr_pxi4), + MSM_PIN_FUNCTION(ddr_pxi5), + MSM_PIN_FUNCTION(edp0_hot), + MSM_PIN_FUNCTION(edp0_lcd), + MSM_PIN_FUNCTION(edp1_hot), + MSM_PIN_FUNCTION(edp1_lcd), + MSM_PIN_FUNCTION(edp2_hot), + MSM_PIN_FUNCTION(edp2_lcd), + MSM_PIN_FUNCTION(edp3_hot), + MSM_PIN_FUNCTION(edp3_lcd), + MSM_PIN_FUNCTION(emac0_mcg0), + MSM_PIN_FUNCTION(emac0_mcg1), + MSM_PIN_FUNCTION(emac0_mcg2), + MSM_PIN_FUNCTION(emac0_mcg3), + MSM_PIN_FUNCTION(emac0_mdc), + MSM_PIN_FUNCTION(emac0_mdio), + MSM_PIN_FUNCTION(emac0_ptp_aux), + MSM_PIN_FUNCTION(emac0_ptp_pps), + MSM_PIN_FUNCTION(emac1_mcg0), + MSM_PIN_FUNCTION(emac1_mcg1), + MSM_PIN_FUNCTION(emac1_mcg2), + MSM_PIN_FUNCTION(emac1_mcg3), + MSM_PIN_FUNCTION(emac1_mdc), + MSM_PIN_FUNCTION(emac1_mdio), + MSM_PIN_FUNCTION(emac1_ptp_aux), + MSM_PIN_FUNCTION(emac1_ptp_pps), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gcc_gp4), + MSM_PIN_FUNCTION(gcc_gp5), + MSM_PIN_FUNCTION(hs0_mi2s), + MSM_PIN_FUNCTION(hs1_mi2s), + MSM_PIN_FUNCTION(hs2_mi2s), + MSM_PIN_FUNCTION(ibi_i3c), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(mdp0_vsync0), + MSM_PIN_FUNCTION(mdp0_vsync1), + MSM_PIN_FUNCTION(mdp0_vsync2), + MSM_PIN_FUNCTION(mdp0_vsync3), + MSM_PIN_FUNCTION(mdp0_vsync4), + MSM_PIN_FUNCTION(mdp0_vsync5), + MSM_PIN_FUNCTION(mdp0_vsync6), + MSM_PIN_FUNCTION(mdp0_vsync7), + MSM_PIN_FUNCTION(mdp0_vsync8), + MSM_PIN_FUNCTION(mdp1_vsync0), + MSM_PIN_FUNCTION(mdp1_vsync1), + MSM_PIN_FUNCTION(mdp1_vsync2), + MSM_PIN_FUNCTION(mdp1_vsync3), + MSM_PIN_FUNCTION(mdp1_vsync4), + MSM_PIN_FUNCTION(mdp1_vsync5), + MSM_PIN_FUNCTION(mdp1_vsync6), + MSM_PIN_FUNCTION(mdp1_vsync7), + MSM_PIN_FUNCTION(mdp1_vsync8), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mi2s1_data0), + MSM_PIN_FUNCTION(mi2s1_data1), + MSM_PIN_FUNCTION(mi2s1_sck), + MSM_PIN_FUNCTION(mi2s1_ws), + MSM_PIN_FUNCTION(mi2s2_data0), + MSM_PIN_FUNCTION(mi2s2_data1), + MSM_PIN_FUNCTION(mi2s2_sck), + MSM_PIN_FUNCTION(mi2s2_ws), + MSM_PIN_FUNCTION(mi2s_mclk0), + MSM_PIN_FUNCTION(mi2s_mclk1), + MSM_PIN_FUNCTION(pcie0_clkreq), + MSM_PIN_FUNCTION(pcie1_clkreq), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_clk), + MSM_PIN_FUNCTION(prng_rosc0), + MSM_PIN_FUNCTION(prng_rosc1), + MSM_PIN_FUNCTION(prng_rosc2), + MSM_PIN_FUNCTION(prng_rosc3), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qup0_se0), + MSM_PIN_FUNCTION(qup0_se1), + MSM_PIN_FUNCTION(qup0_se2), + MSM_PIN_FUNCTION(qup0_se3), + MSM_PIN_FUNCTION(qup0_se4), + MSM_PIN_FUNCTION(qup0_se5), + MSM_PIN_FUNCTION(qup1_se0), + MSM_PIN_FUNCTION(qup1_se1), + MSM_PIN_FUNCTION(qup1_se2), + MSM_PIN_FUNCTION(qup1_se3), + MSM_PIN_FUNCTION(qup1_se4), + MSM_PIN_FUNCTION(qup1_se5), + MSM_PIN_FUNCTION(qup1_se6), + MSM_PIN_FUNCTION(qup2_se0), + MSM_PIN_FUNCTION(qup2_se1), + MSM_PIN_FUNCTION(qup2_se2), + MSM_PIN_FUNCTION(qup2_se3), + MSM_PIN_FUNCTION(qup2_se4), + MSM_PIN_FUNCTION(qup2_se5), + MSM_PIN_FUNCTION(qup2_se6), + MSM_PIN_FUNCTION(qup3_se0), + MSM_PIN_FUNCTION(sail_top), + MSM_PIN_FUNCTION(sailss_emac0), + MSM_PIN_FUNCTION(sailss_ospi), + MSM_PIN_FUNCTION(sgmii_phy), + MSM_PIN_FUNCTION(tb_trig), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tgu_ch4), + MSM_PIN_FUNCTION(tgu_ch5), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(tsense_pwm3), + MSM_PIN_FUNCTION(tsense_pwm4), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(vsense_trigger), }; /* @@ -1491,6 +1483,23 @@ static const struct msm_pingroup sa8775p_groups[] = { [153] = SDC_QDSD_PINGROUP(sdc1_data, 0x199000, 9, 0), }; +static const struct msm_gpio_wakeirq_map sa8775p_pdc_map[] = { + { 0, 169 }, { 1, 174 }, { 2, 170 }, { 3, 175 }, { 4, 171 }, { 5, 173 }, + { 6, 172 }, { 7, 182 }, { 10, 220 }, { 11, 213 }, { 12, 221 }, + { 16, 230 }, { 19, 231 }, { 20, 232 }, { 23, 233 }, { 24, 234 }, + { 26, 223 }, { 27, 235 }, { 28, 209 }, { 29, 176 }, { 30, 200 }, + { 31, 201 }, { 32, 212 }, { 35, 177 }, { 36, 178 }, { 39, 184 }, + { 40, 185 }, { 41, 227 }, { 42, 186 }, { 43, 228 }, { 45, 187 }, + { 47, 188 }, { 48, 194 }, { 51, 195 }, { 52, 196 }, { 55, 197 }, + { 56, 198 }, { 57, 236 }, { 58, 192 }, { 59, 193 }, { 72, 179 }, + { 73, 180 }, { 74, 181 }, { 75, 202 }, { 76, 183 }, { 77, 189 }, + { 78, 190 }, { 79, 191 }, { 80, 199 }, { 83, 204 }, { 84, 205 }, + { 85, 229 }, { 86, 206 }, { 89, 207 }, { 91, 208 }, { 94, 214 }, + { 95, 215 }, { 96, 237 }, { 97, 216 }, { 98, 238 }, { 99, 217 }, + { 100, 239 }, { 105, 219 }, { 106, 210 }, { 107, 211 }, { 108, 222 }, + { 109, 203 }, { 145, 225 }, { 146, 226 }, +}; + static const struct msm_pinctrl_soc_data sa8775p_pinctrl = { .pins = sa8775p_pins, .npins = ARRAY_SIZE(sa8775p_pins), @@ -1499,6 +1508,8 @@ static const struct msm_pinctrl_soc_data sa8775p_pinctrl = { .groups = sa8775p_groups, .ngroups = ARRAY_SIZE(sa8775p_groups), .ngpios = 150, + .wakeirq_map = sa8775p_pdc_map, + .nwakeirq_map = ARRAY_SIZE(sa8775p_pdc_map), }; static int sa8775p_pinctrl_probe(struct platform_device *pdev) diff --git a/drivers/pinctrl/qcom/pinctrl-sc7180.c b/drivers/pinctrl/qcom/pinctrl-sc7180.c index 1d9acad3c1ce..6eb0c73791c0 100644 --- a/drivers/pinctrl/qcom/pinctrl-sc7180.c +++ b/drivers/pinctrl/qcom/pinctrl-sc7180.c @@ -4,7 +4,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" @@ -20,18 +19,11 @@ enum { WEST }; -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -69,9 +61,9 @@ enum { #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -95,9 +87,9 @@ enum { #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -868,120 +860,120 @@ static const char * const qup04_uart_groups[] = { "gpio115", "gpio116", }; -static const struct msm_function sc7180_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(aoss_cti), - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(atest_tsens), - FUNCTION(atest_tsens2), - FUNCTION(atest_usb1), - FUNCTION(atest_usb2), - FUNCTION(atest_usb10), - FUNCTION(atest_usb11), - FUNCTION(atest_usb12), - FUNCTION(atest_usb13), - FUNCTION(atest_usb20), - FUNCTION(atest_usb21), - FUNCTION(atest_usb22), - FUNCTION(atest_usb23), - FUNCTION(audio_ref), - FUNCTION(btfm_slimbus), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cri_trng), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(dp_hot), - FUNCTION(edp_lcd), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gpio), - FUNCTION(gp_pdm0), - FUNCTION(gp_pdm1), - FUNCTION(gp_pdm2), - FUNCTION(gps_tx), - FUNCTION(jitter_bist), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(lpass_ext), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mi2s_0), - FUNCTION(mi2s_1), - FUNCTION(mi2s_2), - FUNCTION(mss_lte), - FUNCTION(m_voc), - FUNCTION(pa_indicator), - FUNCTION(phase_flag), - FUNCTION(PLL_BIST), - FUNCTION(pll_bypassnl), - FUNCTION(pll_reset), - FUNCTION(prng_rosc), - FUNCTION(qdss), - FUNCTION(qdss_cti), - FUNCTION(qlink_enable), - FUNCTION(qlink_request), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qspi_data), - FUNCTION(qup00), - FUNCTION(qup01), - FUNCTION(qup02_i2c), - FUNCTION(qup02_uart), - FUNCTION(qup03), - FUNCTION(qup04_i2c), - FUNCTION(qup04_uart), - FUNCTION(qup05), - FUNCTION(qup10), - FUNCTION(qup11_i2c), - FUNCTION(qup11_uart), - FUNCTION(qup12), - FUNCTION(qup13_i2c), - FUNCTION(qup13_uart), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(sdc1_tb), - FUNCTION(sdc2_tb), - FUNCTION(sd_write), - FUNCTION(sp_cmu), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(uim1), - FUNCTION(uim2), - FUNCTION(uim_batt), - FUNCTION(usb_phy), - FUNCTION(vfr_1), - FUNCTION(_V_GPIO), - FUNCTION(_V_PPS_IN), - FUNCTION(_V_PPS_OUT), - FUNCTION(vsense_trigger), - FUNCTION(wlan1_adc0), - FUNCTION(wlan1_adc1), - FUNCTION(wlan2_adc0), - FUNCTION(wlan2_adc1), +static const struct pinfunction sc7180_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(aoss_cti), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_tsens2), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(atest_usb10), + MSM_PIN_FUNCTION(atest_usb11), + MSM_PIN_FUNCTION(atest_usb12), + MSM_PIN_FUNCTION(atest_usb13), + MSM_PIN_FUNCTION(atest_usb20), + MSM_PIN_FUNCTION(atest_usb21), + MSM_PIN_FUNCTION(atest_usb22), + MSM_PIN_FUNCTION(atest_usb23), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(btfm_slimbus), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(dp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gp_pdm0), + MSM_PIN_FUNCTION(gp_pdm1), + MSM_PIN_FUNCTION(gp_pdm2), + MSM_PIN_FUNCTION(gps_tx), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(lpass_ext), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mi2s_0), + MSM_PIN_FUNCTION(mi2s_1), + MSM_PIN_FUNCTION(mi2s_2), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(PLL_BIST), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qlink_enable), + MSM_PIN_FUNCTION(qlink_request), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qspi_data), + MSM_PIN_FUNCTION(qup00), + MSM_PIN_FUNCTION(qup01), + MSM_PIN_FUNCTION(qup02_i2c), + MSM_PIN_FUNCTION(qup02_uart), + MSM_PIN_FUNCTION(qup03), + MSM_PIN_FUNCTION(qup04_i2c), + MSM_PIN_FUNCTION(qup04_uart), + MSM_PIN_FUNCTION(qup05), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11_i2c), + MSM_PIN_FUNCTION(qup11_uart), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13_i2c), + MSM_PIN_FUNCTION(qup13_uart), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(sdc1_tb), + MSM_PIN_FUNCTION(sdc2_tb), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sp_cmu), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(uim1), + MSM_PIN_FUNCTION(uim2), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(_V_GPIO), + MSM_PIN_FUNCTION(_V_PPS_IN), + MSM_PIN_FUNCTION(_V_PPS_OUT), + MSM_PIN_FUNCTION(vsense_trigger), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(wlan1_adc1), + MSM_PIN_FUNCTION(wlan2_adc0), + MSM_PIN_FUNCTION(wlan2_adc1), }; /* Every pin is maintained as a single group, and missing or non-existing pin diff --git a/drivers/pinctrl/qcom/pinctrl-sc7280.c b/drivers/pinctrl/qcom/pinctrl-sc7280.c index 31df55c79cb3..0c10eeb60b55 100644 --- a/drivers/pinctrl/qcom/pinctrl-sc7280.c +++ b/drivers/pinctrl/qcom/pinctrl-sc7280.c @@ -6,22 +6,14 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -60,9 +52,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -85,9 +77,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -1120,154 +1112,154 @@ static const char * const vsense_trigger_groups[] = { "gpio100", }; -static const struct msm_function sc7280_functions[] = { - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(atest_usb0), - FUNCTION(atest_usb00), - FUNCTION(atest_usb01), - FUNCTION(atest_usb02), - FUNCTION(atest_usb03), - FUNCTION(atest_usb1), - FUNCTION(atest_usb10), - FUNCTION(atest_usb11), - FUNCTION(atest_usb12), - FUNCTION(atest_usb13), - FUNCTION(audio_ref), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cmu_rng0), - FUNCTION(cmu_rng1), - FUNCTION(cmu_rng2), - FUNCTION(cmu_rng3), - FUNCTION(coex_uart1), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(dp_hot), - FUNCTION(dp_lcd), - FUNCTION(edp_hot), - FUNCTION(edp_lcd), - FUNCTION(egpio), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gpio), - FUNCTION(host2wlan_sol), - FUNCTION(ibi_i3c), - FUNCTION(jitter_bist), - FUNCTION(lpass_slimbus), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mdp_vsync4), - FUNCTION(mdp_vsync5), - FUNCTION(mi2s0_data0), - FUNCTION(mi2s0_data1), - FUNCTION(mi2s0_sck), - FUNCTION(mi2s0_ws), - FUNCTION(mi2s1_data0), - FUNCTION(mi2s1_data1), - FUNCTION(mi2s1_sck), - FUNCTION(mi2s1_ws), - FUNCTION(mi2s2_data0), - FUNCTION(mi2s2_data1), - FUNCTION(mi2s2_sck), - FUNCTION(mi2s2_ws), - FUNCTION(mss_grfc0), - FUNCTION(mss_grfc1), - FUNCTION(mss_grfc10), - FUNCTION(mss_grfc11), - FUNCTION(mss_grfc12), - FUNCTION(mss_grfc2), - FUNCTION(mss_grfc3), - FUNCTION(mss_grfc4), - FUNCTION(mss_grfc5), - FUNCTION(mss_grfc6), - FUNCTION(mss_grfc7), - FUNCTION(mss_grfc8), - FUNCTION(mss_grfc9), - FUNCTION(nav_gpio0), - FUNCTION(nav_gpio1), - FUNCTION(nav_gpio2), - FUNCTION(pa_indicator), - FUNCTION(pcie0_clkreqn), - FUNCTION(pcie1_clkreqn), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_bypassnl), - FUNCTION(pll_clk), - FUNCTION(pll_reset), - FUNCTION(pri_mi2s), - FUNCTION(prng_rosc), - FUNCTION(qdss), - FUNCTION(qdss_cti), - FUNCTION(qlink0_enable), - FUNCTION(qlink0_request), - FUNCTION(qlink0_wmss), - FUNCTION(qlink1_enable), - FUNCTION(qlink1_request), - FUNCTION(qlink1_wmss), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qspi_data), - FUNCTION(qup00), - FUNCTION(qup01), - FUNCTION(qup02), - FUNCTION(qup03), - FUNCTION(qup04), - FUNCTION(qup05), - FUNCTION(qup06), - FUNCTION(qup07), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(qup16), - FUNCTION(qup17), - FUNCTION(sdc40), - FUNCTION(sdc41), - FUNCTION(sdc42), - FUNCTION(sdc43), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(sd_write), - FUNCTION(sec_mi2s), - FUNCTION(tb_trig), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(uim0_clk), - FUNCTION(uim0_data), - FUNCTION(uim0_present), - FUNCTION(uim0_reset), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(usb2phy_ac), - FUNCTION(usb_phy), - FUNCTION(vfr_0), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), +static const struct pinfunction sc7280_functions[] = { + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(atest_usb0), + MSM_PIN_FUNCTION(atest_usb00), + MSM_PIN_FUNCTION(atest_usb01), + MSM_PIN_FUNCTION(atest_usb02), + MSM_PIN_FUNCTION(atest_usb03), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(atest_usb10), + MSM_PIN_FUNCTION(atest_usb11), + MSM_PIN_FUNCTION(atest_usb12), + MSM_PIN_FUNCTION(atest_usb13), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cmu_rng0), + MSM_PIN_FUNCTION(cmu_rng1), + MSM_PIN_FUNCTION(cmu_rng2), + MSM_PIN_FUNCTION(cmu_rng3), + MSM_PIN_FUNCTION(coex_uart1), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(dp_hot), + MSM_PIN_FUNCTION(dp_lcd), + MSM_PIN_FUNCTION(edp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(egpio), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(host2wlan_sol), + MSM_PIN_FUNCTION(ibi_i3c), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mdp_vsync4), + MSM_PIN_FUNCTION(mdp_vsync5), + MSM_PIN_FUNCTION(mi2s0_data0), + MSM_PIN_FUNCTION(mi2s0_data1), + MSM_PIN_FUNCTION(mi2s0_sck), + MSM_PIN_FUNCTION(mi2s0_ws), + MSM_PIN_FUNCTION(mi2s1_data0), + MSM_PIN_FUNCTION(mi2s1_data1), + MSM_PIN_FUNCTION(mi2s1_sck), + MSM_PIN_FUNCTION(mi2s1_ws), + MSM_PIN_FUNCTION(mi2s2_data0), + MSM_PIN_FUNCTION(mi2s2_data1), + MSM_PIN_FUNCTION(mi2s2_sck), + MSM_PIN_FUNCTION(mi2s2_ws), + MSM_PIN_FUNCTION(mss_grfc0), + MSM_PIN_FUNCTION(mss_grfc1), + MSM_PIN_FUNCTION(mss_grfc10), + MSM_PIN_FUNCTION(mss_grfc11), + MSM_PIN_FUNCTION(mss_grfc12), + MSM_PIN_FUNCTION(mss_grfc2), + MSM_PIN_FUNCTION(mss_grfc3), + MSM_PIN_FUNCTION(mss_grfc4), + MSM_PIN_FUNCTION(mss_grfc5), + MSM_PIN_FUNCTION(mss_grfc6), + MSM_PIN_FUNCTION(mss_grfc7), + MSM_PIN_FUNCTION(mss_grfc8), + MSM_PIN_FUNCTION(mss_grfc9), + MSM_PIN_FUNCTION(nav_gpio0), + MSM_PIN_FUNCTION(nav_gpio1), + MSM_PIN_FUNCTION(nav_gpio2), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pcie0_clkreqn), + MSM_PIN_FUNCTION(pcie1_clkreqn), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_clk), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qlink0_enable), + MSM_PIN_FUNCTION(qlink0_request), + MSM_PIN_FUNCTION(qlink0_wmss), + MSM_PIN_FUNCTION(qlink1_enable), + MSM_PIN_FUNCTION(qlink1_request), + MSM_PIN_FUNCTION(qlink1_wmss), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qspi_data), + MSM_PIN_FUNCTION(qup00), + MSM_PIN_FUNCTION(qup01), + MSM_PIN_FUNCTION(qup02), + MSM_PIN_FUNCTION(qup03), + MSM_PIN_FUNCTION(qup04), + MSM_PIN_FUNCTION(qup05), + MSM_PIN_FUNCTION(qup06), + MSM_PIN_FUNCTION(qup07), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(qup16), + MSM_PIN_FUNCTION(qup17), + MSM_PIN_FUNCTION(sdc40), + MSM_PIN_FUNCTION(sdc41), + MSM_PIN_FUNCTION(sdc42), + MSM_PIN_FUNCTION(sdc43), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(tb_trig), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(uim0_clk), + MSM_PIN_FUNCTION(uim0_data), + MSM_PIN_FUNCTION(uim0_present), + MSM_PIN_FUNCTION(uim0_reset), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_0), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), }; /* Every pin is maintained as a single group, and missing or non-existing pin diff --git a/drivers/pinctrl/qcom/pinctrl-sc8180x.c b/drivers/pinctrl/qcom/pinctrl-sc8180x.c index 704a99d2f93c..d6a79ad41a40 100644 --- a/drivers/pinctrl/qcom/pinctrl-sc8180x.c +++ b/drivers/pinctrl/qcom/pinctrl-sc8180x.c @@ -7,7 +7,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" @@ -38,19 +37,12 @@ static const struct tile_info sc8180x_tile_info[] = { { 0x00100000, 0x00300000, }, }; -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP_OFFSET(id, _tile, offset, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -91,9 +83,9 @@ static const struct tile_info sc8180x_tile_info[] = { #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -117,9 +109,9 @@ static const struct tile_info sc8180x_tile_info[] = { #define UFS_RESET(pg_name) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = 0xb6000, \ .io_reg = 0xb6004, \ .intr_cfg_reg = 0, \ @@ -1238,136 +1230,136 @@ static const char * const wmss_reset_groups[] = { "gpio63", }; -static const struct msm_function sc8180x_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(aoss_cti), - FUNCTION(atest_char), - FUNCTION(atest_tsens), - FUNCTION(atest_tsens2), - FUNCTION(atest_usb0), - FUNCTION(atest_usb1), - FUNCTION(atest_usb2), - FUNCTION(atest_usb3), - FUNCTION(atest_usb4), - FUNCTION(audio_ref), - FUNCTION(btfm_slimbus), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cci_timer5), - FUNCTION(cci_timer6), - FUNCTION(cci_timer7), - FUNCTION(cci_timer8), - FUNCTION(cci_timer9), - FUNCTION(cri_trng), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi), - FUNCTION(debug_hot), - FUNCTION(dp_hot), - FUNCTION(edp_hot), - FUNCTION(edp_lcd), - FUNCTION(emac_phy), - FUNCTION(emac_pps), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gcc_gp4), - FUNCTION(gcc_gp5), - FUNCTION(gpio), - FUNCTION(gps), - FUNCTION(grfc), - FUNCTION(hs1_mi2s), - FUNCTION(hs2_mi2s), - FUNCTION(hs3_mi2s), - FUNCTION(jitter_bist), - FUNCTION(lpass_slimbus), - FUNCTION(m_voc), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mdp_vsync4), - FUNCTION(mdp_vsync5), - FUNCTION(mss_lte), - FUNCTION(nav_pps), - FUNCTION(pa_indicator), - FUNCTION(pci_e0), - FUNCTION(pci_e1), - FUNCTION(pci_e2), - FUNCTION(pci_e3), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_bypassnl), - FUNCTION(pll_reset), - FUNCTION(pri_mi2s), - FUNCTION(pri_mi2s_ws), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qlink), - FUNCTION(qspi0), - FUNCTION(qspi0_clk), - FUNCTION(qspi0_cs), - FUNCTION(qspi1), - FUNCTION(qspi1_clk), - FUNCTION(qspi1_cs), - FUNCTION(qua_mi2s), - FUNCTION(qup0), - FUNCTION(qup1), - FUNCTION(qup2), - FUNCTION(qup3), - FUNCTION(qup4), - FUNCTION(qup5), - FUNCTION(qup6), - FUNCTION(qup7), - FUNCTION(qup8), - FUNCTION(qup9), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(qup16), - FUNCTION(qup17), - FUNCTION(qup18), - FUNCTION(qup19), - FUNCTION(qup_l4), - FUNCTION(qup_l5), - FUNCTION(qup_l6), - FUNCTION(rgmii), - FUNCTION(sd_write), - FUNCTION(sdc4), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(sec_mi2s), - FUNCTION(sp_cmu), - FUNCTION(spkr_i2s), - FUNCTION(ter_mi2s), - FUNCTION(tgu), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(tsif1), - FUNCTION(tsif2), - FUNCTION(uim1), - FUNCTION(uim2), - FUNCTION(uim_batt), - FUNCTION(usb0_phy), - FUNCTION(usb1_phy), - FUNCTION(usb2phy_ac), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), - FUNCTION(wlan1_adc), - FUNCTION(wlan2_adc), - FUNCTION(wmss_reset), +static const struct pinfunction sc8180x_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(aoss_cti), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_tsens2), + MSM_PIN_FUNCTION(atest_usb0), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(atest_usb3), + MSM_PIN_FUNCTION(atest_usb4), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(btfm_slimbus), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cci_timer5), + MSM_PIN_FUNCTION(cci_timer6), + MSM_PIN_FUNCTION(cci_timer7), + MSM_PIN_FUNCTION(cci_timer8), + MSM_PIN_FUNCTION(cci_timer9), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi), + MSM_PIN_FUNCTION(debug_hot), + MSM_PIN_FUNCTION(dp_hot), + MSM_PIN_FUNCTION(edp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(emac_phy), + MSM_PIN_FUNCTION(emac_pps), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gcc_gp4), + MSM_PIN_FUNCTION(gcc_gp5), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gps), + MSM_PIN_FUNCTION(grfc), + MSM_PIN_FUNCTION(hs1_mi2s), + MSM_PIN_FUNCTION(hs2_mi2s), + MSM_PIN_FUNCTION(hs3_mi2s), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mdp_vsync4), + MSM_PIN_FUNCTION(mdp_vsync5), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pci_e0), + MSM_PIN_FUNCTION(pci_e1), + MSM_PIN_FUNCTION(pci_e2), + MSM_PIN_FUNCTION(pci_e3), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(pri_mi2s_ws), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qlink), + MSM_PIN_FUNCTION(qspi0), + MSM_PIN_FUNCTION(qspi0_clk), + MSM_PIN_FUNCTION(qspi0_cs), + MSM_PIN_FUNCTION(qspi1), + MSM_PIN_FUNCTION(qspi1_clk), + MSM_PIN_FUNCTION(qspi1_cs), + MSM_PIN_FUNCTION(qua_mi2s), + MSM_PIN_FUNCTION(qup0), + MSM_PIN_FUNCTION(qup1), + MSM_PIN_FUNCTION(qup2), + MSM_PIN_FUNCTION(qup3), + MSM_PIN_FUNCTION(qup4), + MSM_PIN_FUNCTION(qup5), + MSM_PIN_FUNCTION(qup6), + MSM_PIN_FUNCTION(qup7), + MSM_PIN_FUNCTION(qup8), + MSM_PIN_FUNCTION(qup9), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(qup16), + MSM_PIN_FUNCTION(qup17), + MSM_PIN_FUNCTION(qup18), + MSM_PIN_FUNCTION(qup19), + MSM_PIN_FUNCTION(qup_l4), + MSM_PIN_FUNCTION(qup_l5), + MSM_PIN_FUNCTION(qup_l6), + MSM_PIN_FUNCTION(rgmii), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdc4), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(sp_cmu), + MSM_PIN_FUNCTION(spkr_i2s), + MSM_PIN_FUNCTION(ter_mi2s), + MSM_PIN_FUNCTION(tgu), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(tsif1), + MSM_PIN_FUNCTION(tsif2), + MSM_PIN_FUNCTION(uim1), + MSM_PIN_FUNCTION(uim2), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(usb0_phy), + MSM_PIN_FUNCTION(usb1_phy), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), + MSM_PIN_FUNCTION(wlan1_adc), + MSM_PIN_FUNCTION(wlan2_adc), + MSM_PIN_FUNCTION(wmss_reset), }; /* Every pin is maintained as a single group, and missing or non-existing pin @@ -1630,7 +1622,8 @@ static const struct msm_pinctrl_soc_data sc8180x_acpi_pinctrl = { static int sc8180x_pinctrl_add_tile_resources(struct platform_device *pdev) { int nres_num = pdev->num_resources + ARRAY_SIZE(sc8180x_tiles) - 1; - struct resource *mres, *nres, *res; + struct resource *mres = NULL; + struct resource *nres, *res; int i, ret; /* @@ -1657,6 +1650,9 @@ static int sc8180x_pinctrl_add_tile_resources(struct platform_device *pdev) *res++ = *r; } + if (!mres) + return -EINVAL; + /* Append tile memory resources */ for (i = 0; i < ARRAY_SIZE(sc8180x_tiles); i++, res++) { const struct tile_info *info = &sc8180x_tile_info[i]; diff --git a/drivers/pinctrl/qcom/pinctrl-sc8280xp.c b/drivers/pinctrl/qcom/pinctrl-sc8280xp.c index e96c00686a25..96f4fb5a5d29 100644 --- a/drivers/pinctrl/qcom/pinctrl-sc8280xp.c +++ b/drivers/pinctrl/qcom/pinctrl-sc8280xp.c @@ -7,23 +7,15 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -60,9 +52,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -85,9 +77,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -1476,172 +1468,172 @@ static const char * const vsense_trigger_groups[] = { "gpio81", }; -static const struct msm_function sc8280xp_functions[] = { - FUNCTION(atest_char), - FUNCTION(atest_usb), - FUNCTION(audio_ref), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cci_timer5), - FUNCTION(cci_timer6), - FUNCTION(cci_timer7), - FUNCTION(cci_timer8), - FUNCTION(cci_timer9), - FUNCTION(cmu_rng), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(ddr_pxi4), - FUNCTION(ddr_pxi5), - FUNCTION(ddr_pxi6), - FUNCTION(ddr_pxi7), - FUNCTION(dp2_hot), - FUNCTION(dp3_hot), - FUNCTION(edp0_lcd), - FUNCTION(edp1_lcd), - FUNCTION(edp2_lcd), - FUNCTION(edp3_lcd), - FUNCTION(edp_hot), - FUNCTION(egpio), - FUNCTION(emac0_dll), - FUNCTION(emac0_mcg0), - FUNCTION(emac0_mcg1), - FUNCTION(emac0_mcg2), - FUNCTION(emac0_mcg3), - FUNCTION(emac0_phy), - FUNCTION(emac0_ptp), - FUNCTION(emac1_dll0), - FUNCTION(emac1_dll1), - FUNCTION(emac1_mcg0), - FUNCTION(emac1_mcg1), - FUNCTION(emac1_mcg2), - FUNCTION(emac1_mcg3), - FUNCTION(emac1_phy), - FUNCTION(emac1_ptp), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gcc_gp4), - FUNCTION(gcc_gp5), - FUNCTION(gpio), - FUNCTION(hs1_mi2s), - FUNCTION(hs2_mi2s), - FUNCTION(hs3_mi2s), - FUNCTION(ibi_i3c), - FUNCTION(jitter_bist), - FUNCTION(lpass_slimbus), - FUNCTION(mdp0_vsync0), - FUNCTION(mdp0_vsync1), - FUNCTION(mdp0_vsync2), - FUNCTION(mdp0_vsync3), - FUNCTION(mdp0_vsync4), - FUNCTION(mdp0_vsync5), - FUNCTION(mdp0_vsync6), - FUNCTION(mdp0_vsync7), - FUNCTION(mdp0_vsync8), - FUNCTION(mdp1_vsync0), - FUNCTION(mdp1_vsync1), - FUNCTION(mdp1_vsync2), - FUNCTION(mdp1_vsync3), - FUNCTION(mdp1_vsync4), - FUNCTION(mdp1_vsync5), - FUNCTION(mdp1_vsync6), - FUNCTION(mdp1_vsync7), - FUNCTION(mdp1_vsync8), - FUNCTION(mdp_vsync), - FUNCTION(mi2s0_data0), - FUNCTION(mi2s0_data1), - FUNCTION(mi2s0_sck), - FUNCTION(mi2s0_ws), - FUNCTION(mi2s1_data0), - FUNCTION(mi2s1_data1), - FUNCTION(mi2s1_sck), - FUNCTION(mi2s1_ws), - FUNCTION(mi2s2_data0), - FUNCTION(mi2s2_data1), - FUNCTION(mi2s2_sck), - FUNCTION(mi2s2_ws), - FUNCTION(mi2s_mclk1), - FUNCTION(mi2s_mclk2), - FUNCTION(pcie2a_clkreq), - FUNCTION(pcie2b_clkreq), - FUNCTION(pcie3a_clkreq), - FUNCTION(pcie3b_clkreq), - FUNCTION(pcie4_clkreq), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_clk), - FUNCTION(prng_rosc0), - FUNCTION(prng_rosc1), - FUNCTION(prng_rosc2), - FUNCTION(prng_rosc3), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qspi), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qup0), - FUNCTION(qup1), - FUNCTION(qup2), - FUNCTION(qup3), - FUNCTION(qup4), - FUNCTION(qup5), - FUNCTION(qup6), - FUNCTION(qup7), - FUNCTION(qup8), - FUNCTION(qup9), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(qup16), - FUNCTION(qup17), - FUNCTION(qup18), - FUNCTION(qup19), - FUNCTION(qup20), - FUNCTION(qup21), - FUNCTION(qup22), - FUNCTION(qup23), - FUNCTION(rgmii_0), - FUNCTION(rgmii_1), - FUNCTION(sd_write), - FUNCTION(sdc40), - FUNCTION(sdc42), - FUNCTION(sdc43), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(tb_trig), - FUNCTION(tgu), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(tsense_pwm3), - FUNCTION(tsense_pwm4), - FUNCTION(usb0_dp), - FUNCTION(usb0_phy), - FUNCTION(usb0_sbrx), - FUNCTION(usb0_sbtx), - FUNCTION(usb0_usb4), - FUNCTION(usb1_dp), - FUNCTION(usb1_phy), - FUNCTION(usb1_sbrx), - FUNCTION(usb1_sbtx), - FUNCTION(usb1_usb4), - FUNCTION(usb2phy_ac), - FUNCTION(vsense_trigger), +static const struct pinfunction sc8280xp_functions[] = { + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_usb), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cci_timer5), + MSM_PIN_FUNCTION(cci_timer6), + MSM_PIN_FUNCTION(cci_timer7), + MSM_PIN_FUNCTION(cci_timer8), + MSM_PIN_FUNCTION(cci_timer9), + MSM_PIN_FUNCTION(cmu_rng), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(ddr_pxi4), + MSM_PIN_FUNCTION(ddr_pxi5), + MSM_PIN_FUNCTION(ddr_pxi6), + MSM_PIN_FUNCTION(ddr_pxi7), + MSM_PIN_FUNCTION(dp2_hot), + MSM_PIN_FUNCTION(dp3_hot), + MSM_PIN_FUNCTION(edp0_lcd), + MSM_PIN_FUNCTION(edp1_lcd), + MSM_PIN_FUNCTION(edp2_lcd), + MSM_PIN_FUNCTION(edp3_lcd), + MSM_PIN_FUNCTION(edp_hot), + MSM_PIN_FUNCTION(egpio), + MSM_PIN_FUNCTION(emac0_dll), + MSM_PIN_FUNCTION(emac0_mcg0), + MSM_PIN_FUNCTION(emac0_mcg1), + MSM_PIN_FUNCTION(emac0_mcg2), + MSM_PIN_FUNCTION(emac0_mcg3), + MSM_PIN_FUNCTION(emac0_phy), + MSM_PIN_FUNCTION(emac0_ptp), + MSM_PIN_FUNCTION(emac1_dll0), + MSM_PIN_FUNCTION(emac1_dll1), + MSM_PIN_FUNCTION(emac1_mcg0), + MSM_PIN_FUNCTION(emac1_mcg1), + MSM_PIN_FUNCTION(emac1_mcg2), + MSM_PIN_FUNCTION(emac1_mcg3), + MSM_PIN_FUNCTION(emac1_phy), + MSM_PIN_FUNCTION(emac1_ptp), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gcc_gp4), + MSM_PIN_FUNCTION(gcc_gp5), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(hs1_mi2s), + MSM_PIN_FUNCTION(hs2_mi2s), + MSM_PIN_FUNCTION(hs3_mi2s), + MSM_PIN_FUNCTION(ibi_i3c), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(mdp0_vsync0), + MSM_PIN_FUNCTION(mdp0_vsync1), + MSM_PIN_FUNCTION(mdp0_vsync2), + MSM_PIN_FUNCTION(mdp0_vsync3), + MSM_PIN_FUNCTION(mdp0_vsync4), + MSM_PIN_FUNCTION(mdp0_vsync5), + MSM_PIN_FUNCTION(mdp0_vsync6), + MSM_PIN_FUNCTION(mdp0_vsync7), + MSM_PIN_FUNCTION(mdp0_vsync8), + MSM_PIN_FUNCTION(mdp1_vsync0), + MSM_PIN_FUNCTION(mdp1_vsync1), + MSM_PIN_FUNCTION(mdp1_vsync2), + MSM_PIN_FUNCTION(mdp1_vsync3), + MSM_PIN_FUNCTION(mdp1_vsync4), + MSM_PIN_FUNCTION(mdp1_vsync5), + MSM_PIN_FUNCTION(mdp1_vsync6), + MSM_PIN_FUNCTION(mdp1_vsync7), + MSM_PIN_FUNCTION(mdp1_vsync8), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mi2s0_data0), + MSM_PIN_FUNCTION(mi2s0_data1), + MSM_PIN_FUNCTION(mi2s0_sck), + MSM_PIN_FUNCTION(mi2s0_ws), + MSM_PIN_FUNCTION(mi2s1_data0), + MSM_PIN_FUNCTION(mi2s1_data1), + MSM_PIN_FUNCTION(mi2s1_sck), + MSM_PIN_FUNCTION(mi2s1_ws), + MSM_PIN_FUNCTION(mi2s2_data0), + MSM_PIN_FUNCTION(mi2s2_data1), + MSM_PIN_FUNCTION(mi2s2_sck), + MSM_PIN_FUNCTION(mi2s2_ws), + MSM_PIN_FUNCTION(mi2s_mclk1), + MSM_PIN_FUNCTION(mi2s_mclk2), + MSM_PIN_FUNCTION(pcie2a_clkreq), + MSM_PIN_FUNCTION(pcie2b_clkreq), + MSM_PIN_FUNCTION(pcie3a_clkreq), + MSM_PIN_FUNCTION(pcie3b_clkreq), + MSM_PIN_FUNCTION(pcie4_clkreq), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_clk), + MSM_PIN_FUNCTION(prng_rosc0), + MSM_PIN_FUNCTION(prng_rosc1), + MSM_PIN_FUNCTION(prng_rosc2), + MSM_PIN_FUNCTION(prng_rosc3), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qspi), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qup0), + MSM_PIN_FUNCTION(qup1), + MSM_PIN_FUNCTION(qup2), + MSM_PIN_FUNCTION(qup3), + MSM_PIN_FUNCTION(qup4), + MSM_PIN_FUNCTION(qup5), + MSM_PIN_FUNCTION(qup6), + MSM_PIN_FUNCTION(qup7), + MSM_PIN_FUNCTION(qup8), + MSM_PIN_FUNCTION(qup9), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(qup16), + MSM_PIN_FUNCTION(qup17), + MSM_PIN_FUNCTION(qup18), + MSM_PIN_FUNCTION(qup19), + MSM_PIN_FUNCTION(qup20), + MSM_PIN_FUNCTION(qup21), + MSM_PIN_FUNCTION(qup22), + MSM_PIN_FUNCTION(qup23), + MSM_PIN_FUNCTION(rgmii_0), + MSM_PIN_FUNCTION(rgmii_1), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdc40), + MSM_PIN_FUNCTION(sdc42), + MSM_PIN_FUNCTION(sdc43), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(tb_trig), + MSM_PIN_FUNCTION(tgu), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(tsense_pwm3), + MSM_PIN_FUNCTION(tsense_pwm4), + MSM_PIN_FUNCTION(usb0_dp), + MSM_PIN_FUNCTION(usb0_phy), + MSM_PIN_FUNCTION(usb0_sbrx), + MSM_PIN_FUNCTION(usb0_sbtx), + MSM_PIN_FUNCTION(usb0_usb4), + MSM_PIN_FUNCTION(usb1_dp), + MSM_PIN_FUNCTION(usb1_phy), + MSM_PIN_FUNCTION(usb1_sbrx), + MSM_PIN_FUNCTION(usb1_sbtx), + MSM_PIN_FUNCTION(usb1_usb4), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(vsense_trigger), }; static const struct msm_pingroup sc8280xp_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-sdm660.c b/drivers/pinctrl/qcom/pinctrl-sdm660.c index 1bfb0ae6b387..c2e0d5c034ac 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdm660.c +++ b/drivers/pinctrl/qcom/pinctrl-sdm660.c @@ -7,7 +7,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" @@ -25,19 +24,11 @@ enum { #define REG_SIZE 0x1000 -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - - #define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -75,9 +66,9 @@ enum { #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -1099,189 +1090,189 @@ static const char * const wlan2_adc1_groups[] = { "gpio10", }; -static const struct msm_function sdm660_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(atest_gpsadc0), - FUNCTION(atest_gpsadc1), - FUNCTION(atest_tsens), - FUNCTION(atest_tsens2), - FUNCTION(atest_usb1), - FUNCTION(atest_usb10), - FUNCTION(atest_usb11), - FUNCTION(atest_usb12), - FUNCTION(atest_usb13), - FUNCTION(atest_usb2), - FUNCTION(atest_usb20), - FUNCTION(atest_usb21), - FUNCTION(atest_usb22), - FUNCTION(atest_usb23), - FUNCTION(audio_ref), - FUNCTION(bimc_dte0), - FUNCTION(bimc_dte1), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_i2c5), - FUNCTION(blsp_i2c6), - FUNCTION(blsp_i2c7), - FUNCTION(blsp_i2c8_a), - FUNCTION(blsp_i2c8_b), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi3_cs1), - FUNCTION(blsp_spi3_cs2), - FUNCTION(blsp_spi4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_spi6), - FUNCTION(blsp_spi7), - FUNCTION(blsp_spi8_a), - FUNCTION(blsp_spi8_b), - FUNCTION(blsp_spi8_cs1), - FUNCTION(blsp_spi8_cs2), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uart5), - FUNCTION(blsp_uart6_a), - FUNCTION(blsp_uart6_b), - FUNCTION(blsp_uim1), - FUNCTION(blsp_uim2), - FUNCTION(blsp_uim5), - FUNCTION(blsp_uim6), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gpio), - FUNCTION(gps_tx_a), - FUNCTION(gps_tx_b), - FUNCTION(gps_tx_c), - FUNCTION(isense_dbg), - FUNCTION(jitter_bist), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(m_voc), - FUNCTION(mdp_vsync), - FUNCTION(mdss_vsync0), - FUNCTION(mdss_vsync1), - FUNCTION(mdss_vsync2), - FUNCTION(mdss_vsync3), - FUNCTION(mss_lte), - FUNCTION(nav_pps_a), - FUNCTION(nav_pps_b), - FUNCTION(nav_pps_c), - FUNCTION(pa_indicator), - FUNCTION(phase_flag0), - FUNCTION(phase_flag1), - FUNCTION(phase_flag2), - FUNCTION(phase_flag3), - FUNCTION(phase_flag4), - FUNCTION(phase_flag5), - FUNCTION(phase_flag6), - FUNCTION(phase_flag7), - FUNCTION(phase_flag8), - FUNCTION(phase_flag9), - FUNCTION(phase_flag10), - FUNCTION(phase_flag11), - FUNCTION(phase_flag12), - FUNCTION(phase_flag13), - FUNCTION(phase_flag14), - FUNCTION(phase_flag15), - FUNCTION(phase_flag16), - FUNCTION(phase_flag17), - FUNCTION(phase_flag18), - FUNCTION(phase_flag19), - FUNCTION(phase_flag20), - FUNCTION(phase_flag21), - FUNCTION(phase_flag22), - FUNCTION(phase_flag23), - FUNCTION(phase_flag24), - FUNCTION(phase_flag25), - FUNCTION(phase_flag26), - FUNCTION(phase_flag27), - FUNCTION(phase_flag28), - FUNCTION(phase_flag29), - FUNCTION(phase_flag30), - FUNCTION(phase_flag31), - FUNCTION(pll_bypassnl), - FUNCTION(pll_reset), - FUNCTION(pri_mi2s), - FUNCTION(pri_mi2s_ws), - FUNCTION(prng_rosc), - FUNCTION(pwr_crypto), - FUNCTION(pwr_modem), - FUNCTION(pwr_nav), - FUNCTION(qdss_cti0_a), - FUNCTION(qdss_cti0_b), - FUNCTION(qdss_cti1_a), - FUNCTION(qdss_cti1_b), - FUNCTION(qdss_gpio), - FUNCTION(qdss_gpio0), - FUNCTION(qdss_gpio1), - FUNCTION(qdss_gpio10), - FUNCTION(qdss_gpio11), - FUNCTION(qdss_gpio12), - FUNCTION(qdss_gpio13), - FUNCTION(qdss_gpio14), - FUNCTION(qdss_gpio15), - FUNCTION(qdss_gpio2), - FUNCTION(qdss_gpio3), - FUNCTION(qdss_gpio4), - FUNCTION(qdss_gpio5), - FUNCTION(qdss_gpio6), - FUNCTION(qdss_gpio7), - FUNCTION(qdss_gpio8), - FUNCTION(qdss_gpio9), - FUNCTION(qlink_enable), - FUNCTION(qlink_request), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qspi_data0), - FUNCTION(qspi_data1), - FUNCTION(qspi_data2), - FUNCTION(qspi_data3), - FUNCTION(qspi_resetn), - FUNCTION(sec_mi2s), - FUNCTION(sndwire_clk), - FUNCTION(sndwire_data), - FUNCTION(sp_cmu), - FUNCTION(ssc_irq), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(uim_batt), - FUNCTION(vfr_1), - FUNCTION(vsense_clkout), - FUNCTION(vsense_data0), - FUNCTION(vsense_data1), - FUNCTION(vsense_mode), - FUNCTION(wlan1_adc0), - FUNCTION(wlan1_adc1), - FUNCTION(wlan2_adc0), - FUNCTION(wlan2_adc1), +static const struct pinfunction sdm660_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(atest_gpsadc0), + MSM_PIN_FUNCTION(atest_gpsadc1), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_tsens2), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(atest_usb10), + MSM_PIN_FUNCTION(atest_usb11), + MSM_PIN_FUNCTION(atest_usb12), + MSM_PIN_FUNCTION(atest_usb13), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(atest_usb20), + MSM_PIN_FUNCTION(atest_usb21), + MSM_PIN_FUNCTION(atest_usb22), + MSM_PIN_FUNCTION(atest_usb23), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(bimc_dte0), + MSM_PIN_FUNCTION(bimc_dte1), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(blsp_i2c6), + MSM_PIN_FUNCTION(blsp_i2c7), + MSM_PIN_FUNCTION(blsp_i2c8_a), + MSM_PIN_FUNCTION(blsp_i2c8_b), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi3_cs1), + MSM_PIN_FUNCTION(blsp_spi3_cs2), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(blsp_spi6), + MSM_PIN_FUNCTION(blsp_spi7), + MSM_PIN_FUNCTION(blsp_spi8_a), + MSM_PIN_FUNCTION(blsp_spi8_b), + MSM_PIN_FUNCTION(blsp_spi8_cs1), + MSM_PIN_FUNCTION(blsp_spi8_cs2), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_uart5), + MSM_PIN_FUNCTION(blsp_uart6_a), + MSM_PIN_FUNCTION(blsp_uart6_b), + MSM_PIN_FUNCTION(blsp_uim1), + MSM_PIN_FUNCTION(blsp_uim2), + MSM_PIN_FUNCTION(blsp_uim5), + MSM_PIN_FUNCTION(blsp_uim6), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gps_tx_a), + MSM_PIN_FUNCTION(gps_tx_b), + MSM_PIN_FUNCTION(gps_tx_c), + MSM_PIN_FUNCTION(isense_dbg), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdss_vsync0), + MSM_PIN_FUNCTION(mdss_vsync1), + MSM_PIN_FUNCTION(mdss_vsync2), + MSM_PIN_FUNCTION(mdss_vsync3), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_pps_a), + MSM_PIN_FUNCTION(nav_pps_b), + MSM_PIN_FUNCTION(nav_pps_c), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(phase_flag0), + MSM_PIN_FUNCTION(phase_flag1), + MSM_PIN_FUNCTION(phase_flag2), + MSM_PIN_FUNCTION(phase_flag3), + MSM_PIN_FUNCTION(phase_flag4), + MSM_PIN_FUNCTION(phase_flag5), + MSM_PIN_FUNCTION(phase_flag6), + MSM_PIN_FUNCTION(phase_flag7), + MSM_PIN_FUNCTION(phase_flag8), + MSM_PIN_FUNCTION(phase_flag9), + MSM_PIN_FUNCTION(phase_flag10), + MSM_PIN_FUNCTION(phase_flag11), + MSM_PIN_FUNCTION(phase_flag12), + MSM_PIN_FUNCTION(phase_flag13), + MSM_PIN_FUNCTION(phase_flag14), + MSM_PIN_FUNCTION(phase_flag15), + MSM_PIN_FUNCTION(phase_flag16), + MSM_PIN_FUNCTION(phase_flag17), + MSM_PIN_FUNCTION(phase_flag18), + MSM_PIN_FUNCTION(phase_flag19), + MSM_PIN_FUNCTION(phase_flag20), + MSM_PIN_FUNCTION(phase_flag21), + MSM_PIN_FUNCTION(phase_flag22), + MSM_PIN_FUNCTION(phase_flag23), + MSM_PIN_FUNCTION(phase_flag24), + MSM_PIN_FUNCTION(phase_flag25), + MSM_PIN_FUNCTION(phase_flag26), + MSM_PIN_FUNCTION(phase_flag27), + MSM_PIN_FUNCTION(phase_flag28), + MSM_PIN_FUNCTION(phase_flag29), + MSM_PIN_FUNCTION(phase_flag30), + MSM_PIN_FUNCTION(phase_flag31), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(pri_mi2s_ws), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(pwr_crypto), + MSM_PIN_FUNCTION(pwr_modem), + MSM_PIN_FUNCTION(pwr_nav), + MSM_PIN_FUNCTION(qdss_cti0_a), + MSM_PIN_FUNCTION(qdss_cti0_b), + MSM_PIN_FUNCTION(qdss_cti1_a), + MSM_PIN_FUNCTION(qdss_cti1_b), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qdss_gpio0), + MSM_PIN_FUNCTION(qdss_gpio1), + MSM_PIN_FUNCTION(qdss_gpio10), + MSM_PIN_FUNCTION(qdss_gpio11), + MSM_PIN_FUNCTION(qdss_gpio12), + MSM_PIN_FUNCTION(qdss_gpio13), + MSM_PIN_FUNCTION(qdss_gpio14), + MSM_PIN_FUNCTION(qdss_gpio15), + MSM_PIN_FUNCTION(qdss_gpio2), + MSM_PIN_FUNCTION(qdss_gpio3), + MSM_PIN_FUNCTION(qdss_gpio4), + MSM_PIN_FUNCTION(qdss_gpio5), + MSM_PIN_FUNCTION(qdss_gpio6), + MSM_PIN_FUNCTION(qdss_gpio7), + MSM_PIN_FUNCTION(qdss_gpio8), + MSM_PIN_FUNCTION(qdss_gpio9), + MSM_PIN_FUNCTION(qlink_enable), + MSM_PIN_FUNCTION(qlink_request), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qspi_data0), + MSM_PIN_FUNCTION(qspi_data1), + MSM_PIN_FUNCTION(qspi_data2), + MSM_PIN_FUNCTION(qspi_data3), + MSM_PIN_FUNCTION(qspi_resetn), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(sndwire_clk), + MSM_PIN_FUNCTION(sndwire_data), + MSM_PIN_FUNCTION(sp_cmu), + MSM_PIN_FUNCTION(ssc_irq), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_clkout), + MSM_PIN_FUNCTION(vsense_data0), + MSM_PIN_FUNCTION(vsense_data1), + MSM_PIN_FUNCTION(vsense_mode), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(wlan1_adc1), + MSM_PIN_FUNCTION(wlan2_adc0), + MSM_PIN_FUNCTION(wlan2_adc1), }; static const struct msm_pingroup sdm660_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-sdm670.c b/drivers/pinctrl/qcom/pinctrl-sdm670.c index b888bca7ecd7..cc3cce077de4 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdm670.c +++ b/drivers/pinctrl/qcom/pinctrl-sdm670.c @@ -7,17 +7,9 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define NORTH 0x00500000 #define SOUTH 0x00900000 #define WEST 0x00100000 @@ -25,9 +17,9 @@ #define REG_SIZE 0x1000 #define PINGROUP(id, base, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -68,9 +60,9 @@ */ #define PINGROUP_DUMMY(id) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .ctl_reg = 0, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -93,9 +85,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -118,9 +110,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -998,132 +990,132 @@ static const char * const mss_lte_groups[] = { "gpio144", "gpio145", }; -static const struct msm_function sdm670_functions[] = { - FUNCTION(gpio), - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(atest_char), - FUNCTION(atest_tsens), - FUNCTION(atest_tsens2), - FUNCTION(atest_usb1), - FUNCTION(atest_usb10), - FUNCTION(atest_usb11), - FUNCTION(atest_usb12), - FUNCTION(atest_usb13), - FUNCTION(atest_usb2), - FUNCTION(atest_usb20), - FUNCTION(atest_usb21), - FUNCTION(atest_usb22), - FUNCTION(atest_usb23), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(copy_gp), - FUNCTION(copy_phase), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(edp_hot), - FUNCTION(edp_lcd), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gp_pdm0), - FUNCTION(gp_pdm1), - FUNCTION(gp_pdm2), - FUNCTION(gps_tx), - FUNCTION(jitter_bist), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(lpass_slimbus), - FUNCTION(m_voc), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mss_lte), - FUNCTION(nav_pps), - FUNCTION(pa_indicator), - FUNCTION(pci_e0), - FUNCTION(pci_e1), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_bypassnl), - FUNCTION(pll_reset), - FUNCTION(pri_mi2s), - FUNCTION(pri_mi2s_ws), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss), - FUNCTION(qlink_enable), - FUNCTION(qlink_request), - FUNCTION(qua_mi2s), - FUNCTION(qup0), - FUNCTION(qup1), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(qup2), - FUNCTION(qup3), - FUNCTION(qup4), - FUNCTION(qup5), - FUNCTION(qup6), - FUNCTION(qup7), - FUNCTION(qup8), - FUNCTION(qup9), - FUNCTION(qup_l4), - FUNCTION(qup_l5), - FUNCTION(qup_l6), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(sdc4_data), - FUNCTION(sd_write), - FUNCTION(sec_mi2s), - FUNCTION(ter_mi2s), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tsif1_clk), - FUNCTION(tsif1_data), - FUNCTION(tsif1_en), - FUNCTION(tsif1_error), - FUNCTION(tsif1_sync), - FUNCTION(tsif2_clk), - FUNCTION(tsif2_data), - FUNCTION(tsif2_en), - FUNCTION(tsif2_error), - FUNCTION(tsif2_sync), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(uim_batt), - FUNCTION(usb_phy), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), - FUNCTION(wlan1_adc0), - FUNCTION(wlan1_adc1), - FUNCTION(wlan2_adc0), - FUNCTION(wlan2_adc1), - FUNCTION(wsa_clk), - FUNCTION(wsa_data), +static const struct pinfunction sdm670_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_tsens2), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(atest_usb10), + MSM_PIN_FUNCTION(atest_usb11), + MSM_PIN_FUNCTION(atest_usb12), + MSM_PIN_FUNCTION(atest_usb13), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(atest_usb20), + MSM_PIN_FUNCTION(atest_usb21), + MSM_PIN_FUNCTION(atest_usb22), + MSM_PIN_FUNCTION(atest_usb23), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(copy_gp), + MSM_PIN_FUNCTION(copy_phase), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(edp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gp_pdm0), + MSM_PIN_FUNCTION(gp_pdm1), + MSM_PIN_FUNCTION(gp_pdm2), + MSM_PIN_FUNCTION(gps_tx), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pci_e0), + MSM_PIN_FUNCTION(pci_e1), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(pri_mi2s_ws), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss), + MSM_PIN_FUNCTION(qlink_enable), + MSM_PIN_FUNCTION(qlink_request), + MSM_PIN_FUNCTION(qua_mi2s), + MSM_PIN_FUNCTION(qup0), + MSM_PIN_FUNCTION(qup1), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(qup2), + MSM_PIN_FUNCTION(qup3), + MSM_PIN_FUNCTION(qup4), + MSM_PIN_FUNCTION(qup5), + MSM_PIN_FUNCTION(qup6), + MSM_PIN_FUNCTION(qup7), + MSM_PIN_FUNCTION(qup8), + MSM_PIN_FUNCTION(qup9), + MSM_PIN_FUNCTION(qup_l4), + MSM_PIN_FUNCTION(qup_l5), + MSM_PIN_FUNCTION(qup_l6), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(sdc4_data), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(ter_mi2s), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tsif1_clk), + MSM_PIN_FUNCTION(tsif1_data), + MSM_PIN_FUNCTION(tsif1_en), + MSM_PIN_FUNCTION(tsif1_error), + MSM_PIN_FUNCTION(tsif1_sync), + MSM_PIN_FUNCTION(tsif2_clk), + MSM_PIN_FUNCTION(tsif2_data), + MSM_PIN_FUNCTION(tsif2_en), + MSM_PIN_FUNCTION(tsif2_error), + MSM_PIN_FUNCTION(tsif2_sync), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(wlan1_adc1), + MSM_PIN_FUNCTION(wlan2_adc0), + MSM_PIN_FUNCTION(wlan2_adc1), + MSM_PIN_FUNCTION(wsa_clk), + MSM_PIN_FUNCTION(wsa_data), }; /* diff --git a/drivers/pinctrl/qcom/pinctrl-sdm845.c b/drivers/pinctrl/qcom/pinctrl-sdm845.c index fdfd7b8f3a76..cc05c415ed15 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdm845.c +++ b/drivers/pinctrl/qcom/pinctrl-sdm845.c @@ -7,26 +7,18 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define NORTH 0x00500000 #define SOUTH 0x00900000 #define EAST 0x00100000 #define REG_SIZE 0x1000 #define PINGROUP(id, base, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -64,9 +56,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -89,9 +81,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -983,136 +975,136 @@ static const char * const tsif1_sync_groups[] = { "gpio12", }; -static const struct msm_function sdm845_functions[] = { - FUNCTION(gpio), - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(atest_char), - FUNCTION(atest_tsens), - FUNCTION(atest_tsens2), - FUNCTION(atest_usb1), - FUNCTION(atest_usb10), - FUNCTION(atest_usb11), - FUNCTION(atest_usb12), - FUNCTION(atest_usb13), - FUNCTION(atest_usb2), - FUNCTION(atest_usb20), - FUNCTION(atest_usb21), - FUNCTION(atest_usb22), - FUNCTION(atest_usb23), - FUNCTION(audio_ref), - FUNCTION(btfm_slimbus), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(edp_hot), - FUNCTION(edp_lcd), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(jitter_bist), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(lpass_slimbus), - FUNCTION(m_voc), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mss_lte), - FUNCTION(nav_pps), - FUNCTION(pa_indicator), - FUNCTION(pci_e0), - FUNCTION(pci_e1), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_bypassnl), - FUNCTION(pll_reset), - FUNCTION(pri_mi2s), - FUNCTION(pri_mi2s_ws), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss), - FUNCTION(qlink_enable), - FUNCTION(qlink_request), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qspi_data), - FUNCTION(qua_mi2s), - FUNCTION(qup0), - FUNCTION(qup1), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(qup2), - FUNCTION(qup3), - FUNCTION(qup4), - FUNCTION(qup5), - FUNCTION(qup6), - FUNCTION(qup7), - FUNCTION(qup8), - FUNCTION(qup9), - FUNCTION(qup_l4), - FUNCTION(qup_l5), - FUNCTION(qup_l6), - FUNCTION(sd_write), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(sdc4_data), - FUNCTION(sec_mi2s), - FUNCTION(sp_cmu), - FUNCTION(spkr_i2s), - FUNCTION(ter_mi2s), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(tsif1_clk), - FUNCTION(tsif1_data), - FUNCTION(tsif1_en), - FUNCTION(tsif1_error), - FUNCTION(tsif1_sync), - FUNCTION(tsif2_clk), - FUNCTION(tsif2_data), - FUNCTION(tsif2_en), - FUNCTION(tsif2_error), - FUNCTION(tsif2_sync), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(uim_batt), - FUNCTION(usb_phy), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), - FUNCTION(wlan1_adc0), - FUNCTION(wlan1_adc1), - FUNCTION(wlan2_adc0), - FUNCTION(wlan2_adc1), +static const struct pinfunction sdm845_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_tsens2), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(atest_usb10), + MSM_PIN_FUNCTION(atest_usb11), + MSM_PIN_FUNCTION(atest_usb12), + MSM_PIN_FUNCTION(atest_usb13), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(atest_usb20), + MSM_PIN_FUNCTION(atest_usb21), + MSM_PIN_FUNCTION(atest_usb22), + MSM_PIN_FUNCTION(atest_usb23), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(btfm_slimbus), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(edp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pci_e0), + MSM_PIN_FUNCTION(pci_e1), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(pri_mi2s_ws), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss), + MSM_PIN_FUNCTION(qlink_enable), + MSM_PIN_FUNCTION(qlink_request), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qspi_data), + MSM_PIN_FUNCTION(qua_mi2s), + MSM_PIN_FUNCTION(qup0), + MSM_PIN_FUNCTION(qup1), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(qup2), + MSM_PIN_FUNCTION(qup3), + MSM_PIN_FUNCTION(qup4), + MSM_PIN_FUNCTION(qup5), + MSM_PIN_FUNCTION(qup6), + MSM_PIN_FUNCTION(qup7), + MSM_PIN_FUNCTION(qup8), + MSM_PIN_FUNCTION(qup9), + MSM_PIN_FUNCTION(qup_l4), + MSM_PIN_FUNCTION(qup_l5), + MSM_PIN_FUNCTION(qup_l6), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(sdc4_data), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(sp_cmu), + MSM_PIN_FUNCTION(spkr_i2s), + MSM_PIN_FUNCTION(ter_mi2s), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(tsif1_clk), + MSM_PIN_FUNCTION(tsif1_data), + MSM_PIN_FUNCTION(tsif1_en), + MSM_PIN_FUNCTION(tsif1_error), + MSM_PIN_FUNCTION(tsif1_sync), + MSM_PIN_FUNCTION(tsif2_clk), + MSM_PIN_FUNCTION(tsif2_data), + MSM_PIN_FUNCTION(tsif2_en), + MSM_PIN_FUNCTION(tsif2_error), + MSM_PIN_FUNCTION(tsif2_sync), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(wlan1_adc1), + MSM_PIN_FUNCTION(wlan2_adc0), + MSM_PIN_FUNCTION(wlan2_adc1), }; /* Every pin is maintained as a single group, and missing or non-existing pin diff --git a/drivers/pinctrl/qcom/pinctrl-sdx55.c b/drivers/pinctrl/qcom/pinctrl-sdx55.c index 0bb4931cec59..8826db9d21d0 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdx55.c +++ b/drivers/pinctrl/qcom/pinctrl-sdx55.c @@ -6,24 +6,16 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -60,9 +52,9 @@ #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -765,91 +757,91 @@ static const char * const spmi_coex_groups[] = { "gpio44", "gpio45", }; -static const struct msm_function sdx55_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(atest), - FUNCTION(audio_ref), - FUNCTION(bimc_dte0), - FUNCTION(bimc_dte1), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uart3), - FUNCTION(blsp_uart4), - FUNCTION(char_exec), - FUNCTION(coex_uart), - FUNCTION(coex_uart2), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ebi0_wrcdc), - FUNCTION(ebi2_a), - FUNCTION(ebi2_lcd), - FUNCTION(emac_gcc0), - FUNCTION(emac_gcc1), - FUNCTION(emac_pps0), - FUNCTION(emac_pps1), - FUNCTION(ext_dbg), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gcc_plltest), - FUNCTION(gpio), - FUNCTION(i2s_mclk), - FUNCTION(jitter_bist), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(mgpi_clk), - FUNCTION(m_voc), - FUNCTION(native_char), - FUNCTION(native_char0), - FUNCTION(native_char1), - FUNCTION(native_char2), - FUNCTION(native_char3), - FUNCTION(native_tsens), - FUNCTION(native_tsense), - FUNCTION(nav_gpio), - FUNCTION(pa_indicator), - FUNCTION(pcie_clkreq), - FUNCTION(pci_e), - FUNCTION(pll_bist), - FUNCTION(pll_ref), - FUNCTION(pll_test), - FUNCTION(pri_mi2s), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qdss_stm), - FUNCTION(qlink0_en), - FUNCTION(qlink0_req), - FUNCTION(qlink0_wmss), - FUNCTION(qlink1_en), - FUNCTION(qlink1_req), - FUNCTION(qlink1_wmss), - FUNCTION(spmi_coex), - FUNCTION(sec_mi2s), - FUNCTION(spmi_vgi), - FUNCTION(tgu_ch0), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(usb2phy_ac), - FUNCTION(vsense_trigger), +static const struct pinfunction sdx55_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(atest), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(bimc_dte0), + MSM_PIN_FUNCTION(bimc_dte1), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_uart3), + MSM_PIN_FUNCTION(blsp_uart4), + MSM_PIN_FUNCTION(char_exec), + MSM_PIN_FUNCTION(coex_uart), + MSM_PIN_FUNCTION(coex_uart2), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ebi0_wrcdc), + MSM_PIN_FUNCTION(ebi2_a), + MSM_PIN_FUNCTION(ebi2_lcd), + MSM_PIN_FUNCTION(emac_gcc0), + MSM_PIN_FUNCTION(emac_gcc1), + MSM_PIN_FUNCTION(emac_pps0), + MSM_PIN_FUNCTION(emac_pps1), + MSM_PIN_FUNCTION(ext_dbg), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(i2s_mclk), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(mgpi_clk), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(native_char), + MSM_PIN_FUNCTION(native_char0), + MSM_PIN_FUNCTION(native_char1), + MSM_PIN_FUNCTION(native_char2), + MSM_PIN_FUNCTION(native_char3), + MSM_PIN_FUNCTION(native_tsens), + MSM_PIN_FUNCTION(native_tsense), + MSM_PIN_FUNCTION(nav_gpio), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pcie_clkreq), + MSM_PIN_FUNCTION(pci_e), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_ref), + MSM_PIN_FUNCTION(pll_test), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qdss_stm), + MSM_PIN_FUNCTION(qlink0_en), + MSM_PIN_FUNCTION(qlink0_req), + MSM_PIN_FUNCTION(qlink0_wmss), + MSM_PIN_FUNCTION(qlink1_en), + MSM_PIN_FUNCTION(qlink1_req), + MSM_PIN_FUNCTION(qlink1_wmss), + MSM_PIN_FUNCTION(spmi_coex), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(spmi_vgi), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(vsense_trigger), }; /* Every pin is maintained as a single group, and missing or non-existing pin diff --git a/drivers/pinctrl/qcom/pinctrl-sdx65.c b/drivers/pinctrl/qcom/pinctrl-sdx65.c index e793ea713965..f6f319c997fc 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdx65.c +++ b/drivers/pinctrl/qcom/pinctrl-sdx65.c @@ -6,24 +6,16 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_BASE 0x0 #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -60,9 +52,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -85,9 +77,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -700,90 +692,90 @@ static const char * const sdc1_tb_groups[] = { "gpio106", }; -static const struct msm_function sdx65_functions[] = { - FUNCTION(qlink0_wmss), - FUNCTION(adsp_ext), - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(audio_ref), - FUNCTION(bimc_dte0), - FUNCTION(bimc_dte1), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uart3), - FUNCTION(blsp_uart4), - FUNCTION(char_exec), - FUNCTION(coex_uart), - FUNCTION(coex_uart2), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ebi0_wrcdc), - FUNCTION(ebi2_a), - FUNCTION(ebi2_lcd), - FUNCTION(ext_dbg), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gcc_plltest), - FUNCTION(gpio), - FUNCTION(i2s_mclk), - FUNCTION(jitter_bist), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(m_voc), - FUNCTION(mgpi_clk), - FUNCTION(native_char), - FUNCTION(native_tsens), - FUNCTION(native_tsense), - FUNCTION(nav_gpio), - FUNCTION(pa_indicator), - FUNCTION(pci_e), - FUNCTION(pcie_clkreq), - FUNCTION(pll_bist), - FUNCTION(pll_ref), - FUNCTION(pri_mi2s), - FUNCTION(pri_mi2s_ws), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qlink0_en), - FUNCTION(qlink0_req), - FUNCTION(qlink1_en), - FUNCTION(qlink1_req), - FUNCTION(qlink1_wmss), - FUNCTION(qlink2_en), - FUNCTION(qlink2_req), - FUNCTION(qlink2_wmss), - FUNCTION(sdc1_tb), - FUNCTION(sec_mi2s), - FUNCTION(spmi_coex), - FUNCTION(spmi_vgi), - FUNCTION(tgu_ch0), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(usb2phy_ac), - FUNCTION(vsense_trigger), +static const struct pinfunction sdx65_functions[] = { + MSM_PIN_FUNCTION(qlink0_wmss), + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(bimc_dte0), + MSM_PIN_FUNCTION(bimc_dte1), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_uart3), + MSM_PIN_FUNCTION(blsp_uart4), + MSM_PIN_FUNCTION(char_exec), + MSM_PIN_FUNCTION(coex_uart), + MSM_PIN_FUNCTION(coex_uart2), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ebi0_wrcdc), + MSM_PIN_FUNCTION(ebi2_a), + MSM_PIN_FUNCTION(ebi2_lcd), + MSM_PIN_FUNCTION(ext_dbg), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(i2s_mclk), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mgpi_clk), + MSM_PIN_FUNCTION(native_char), + MSM_PIN_FUNCTION(native_tsens), + MSM_PIN_FUNCTION(native_tsense), + MSM_PIN_FUNCTION(nav_gpio), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pci_e), + MSM_PIN_FUNCTION(pcie_clkreq), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_ref), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(pri_mi2s_ws), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qlink0_en), + MSM_PIN_FUNCTION(qlink0_req), + MSM_PIN_FUNCTION(qlink1_en), + MSM_PIN_FUNCTION(qlink1_req), + MSM_PIN_FUNCTION(qlink1_wmss), + MSM_PIN_FUNCTION(qlink2_en), + MSM_PIN_FUNCTION(qlink2_req), + MSM_PIN_FUNCTION(qlink2_wmss), + MSM_PIN_FUNCTION(sdc1_tb), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(spmi_coex), + MSM_PIN_FUNCTION(spmi_vgi), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(vsense_trigger), }; /* Every pin is maintained as a single group, and missing or non-existing pin diff --git a/drivers/pinctrl/qcom/pinctrl-sdx75.c b/drivers/pinctrl/qcom/pinctrl-sdx75.c new file mode 100644 index 000000000000..2ade7866dbc5 --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-sdx75.c @@ -0,0 +1,1144 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include "pinctrl-msm.h" + +#define REG_BASE 0x100000 +#define REG_SIZE 0x1000 + +#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) \ + { \ + .grp = PINCTRL_PINGROUP("gpio"#id, gpio##id##_pins, \ + (unsigned int)ARRAY_SIZE(gpio##id##_pins)), \ + .ctl_reg = REG_BASE + REG_SIZE * id, \ + .io_reg = REG_BASE + 0x4 + REG_SIZE * id, \ + .intr_cfg_reg = REG_BASE + 0x8 + REG_SIZE * id, \ + .intr_status_reg = REG_BASE + 0xc + REG_SIZE * id, \ + .intr_target_reg = REG_BASE + 0x8 + REG_SIZE * id, \ + .mux_bit = 2, \ + .pull_bit = 0, \ + .drv_bit = 6, \ + .egpio_enable = 12, \ + .egpio_present = 11, \ + .oe_bit = 9, \ + .in_bit = 0, \ + .out_bit = 1, \ + .intr_enable_bit = 0, \ + .intr_status_bit = 0, \ + .intr_target_bit = 5, \ + .intr_target_kpss_val = 3, \ + .intr_raw_status_bit = 4, \ + .intr_polarity_bit = 1, \ + .intr_detection_bit = 2, \ + .intr_detection_width = 2, \ + .funcs = (int[]){ \ + msm_mux_gpio, /* gpio mode */ \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7, \ + msm_mux_##f8, \ + msm_mux_##f9, \ + msm_mux_##f10 \ + }, \ + .nfuncs = 11, \ + } + +#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ + { \ + .grp = PINCTRL_PINGROUP(#pg_name, pg_name##_pins, \ + (unsigned int)ARRAY_SIZE(pg_name##_pins)), \ + .ctl_reg = ctl, \ + .io_reg = 0, \ + .intr_cfg_reg = 0, \ + .intr_status_reg = 0, \ + .intr_target_reg = 0, \ + .mux_bit = -1, \ + .pull_bit = pull, \ + .drv_bit = drv, \ + .oe_bit = -1, \ + .in_bit = -1, \ + .out_bit = -1, \ + .intr_enable_bit = -1, \ + .intr_status_bit = -1, \ + .intr_target_bit = -1, \ + .intr_raw_status_bit = -1, \ + .intr_polarity_bit = -1, \ + .intr_detection_bit = -1, \ + .intr_detection_width = -1, \ + } + +static const struct pinctrl_pin_desc sdx75_pins[] = { + PINCTRL_PIN(0, "GPIO_0"), + PINCTRL_PIN(1, "GPIO_1"), + PINCTRL_PIN(2, "GPIO_2"), + PINCTRL_PIN(3, "GPIO_3"), + PINCTRL_PIN(4, "GPIO_4"), + PINCTRL_PIN(5, "GPIO_5"), + PINCTRL_PIN(6, "GPIO_6"), + PINCTRL_PIN(7, "GPIO_7"), + PINCTRL_PIN(8, "GPIO_8"), + PINCTRL_PIN(9, "GPIO_9"), + PINCTRL_PIN(10, "GPIO_10"), + PINCTRL_PIN(11, "GPIO_11"), + PINCTRL_PIN(12, "GPIO_12"), + PINCTRL_PIN(13, "GPIO_13"), + PINCTRL_PIN(14, "GPIO_14"), + PINCTRL_PIN(15, "GPIO_15"), + PINCTRL_PIN(16, "GPIO_16"), + PINCTRL_PIN(17, "GPIO_17"), + PINCTRL_PIN(18, "GPIO_18"), + PINCTRL_PIN(19, "GPIO_19"), + PINCTRL_PIN(20, "GPIO_20"), + PINCTRL_PIN(21, "GPIO_21"), + PINCTRL_PIN(22, "GPIO_22"), + PINCTRL_PIN(23, "GPIO_23"), + PINCTRL_PIN(24, "GPIO_24"), + PINCTRL_PIN(25, "GPIO_25"), + PINCTRL_PIN(26, "GPIO_26"), + PINCTRL_PIN(27, "GPIO_27"), + PINCTRL_PIN(28, "GPIO_28"), + PINCTRL_PIN(29, "GPIO_29"), + PINCTRL_PIN(30, "GPIO_30"), + PINCTRL_PIN(31, "GPIO_31"), + PINCTRL_PIN(32, "GPIO_32"), + PINCTRL_PIN(33, "GPIO_33"), + PINCTRL_PIN(34, "GPIO_34"), + PINCTRL_PIN(35, "GPIO_35"), + PINCTRL_PIN(36, "GPIO_36"), + PINCTRL_PIN(37, "GPIO_37"), + PINCTRL_PIN(38, "GPIO_38"), + PINCTRL_PIN(39, "GPIO_39"), + PINCTRL_PIN(40, "GPIO_40"), + PINCTRL_PIN(41, "GPIO_41"), + PINCTRL_PIN(42, "GPIO_42"), + PINCTRL_PIN(43, "GPIO_43"), + PINCTRL_PIN(44, "GPIO_44"), + PINCTRL_PIN(45, "GPIO_45"), + PINCTRL_PIN(46, "GPIO_46"), + PINCTRL_PIN(47, "GPIO_47"), + PINCTRL_PIN(48, "GPIO_48"), + PINCTRL_PIN(49, "GPIO_49"), + PINCTRL_PIN(50, "GPIO_50"), + PINCTRL_PIN(51, "GPIO_51"), + PINCTRL_PIN(52, "GPIO_52"), + PINCTRL_PIN(53, "GPIO_53"), + PINCTRL_PIN(54, "GPIO_54"), + PINCTRL_PIN(55, "GPIO_55"), + PINCTRL_PIN(56, "GPIO_56"), + PINCTRL_PIN(57, "GPIO_57"), + PINCTRL_PIN(58, "GPIO_58"), + PINCTRL_PIN(59, "GPIO_59"), + PINCTRL_PIN(60, "GPIO_60"), + PINCTRL_PIN(61, "GPIO_61"), + PINCTRL_PIN(62, "GPIO_62"), + PINCTRL_PIN(63, "GPIO_63"), + PINCTRL_PIN(64, "GPIO_64"), + PINCTRL_PIN(65, "GPIO_65"), + PINCTRL_PIN(66, "GPIO_66"), + PINCTRL_PIN(67, "GPIO_67"), + PINCTRL_PIN(68, "GPIO_68"), + PINCTRL_PIN(69, "GPIO_69"), + PINCTRL_PIN(70, "GPIO_70"), + PINCTRL_PIN(71, "GPIO_71"), + PINCTRL_PIN(72, "GPIO_72"), + PINCTRL_PIN(73, "GPIO_73"), + PINCTRL_PIN(74, "GPIO_74"), + PINCTRL_PIN(75, "GPIO_75"), + PINCTRL_PIN(76, "GPIO_76"), + PINCTRL_PIN(77, "GPIO_77"), + PINCTRL_PIN(78, "GPIO_78"), + PINCTRL_PIN(79, "GPIO_79"), + PINCTRL_PIN(80, "GPIO_80"), + PINCTRL_PIN(81, "GPIO_81"), + PINCTRL_PIN(82, "GPIO_82"), + PINCTRL_PIN(83, "GPIO_83"), + PINCTRL_PIN(84, "GPIO_84"), + PINCTRL_PIN(85, "GPIO_85"), + PINCTRL_PIN(86, "GPIO_86"), + PINCTRL_PIN(87, "GPIO_87"), + PINCTRL_PIN(88, "GPIO_88"), + PINCTRL_PIN(89, "GPIO_89"), + PINCTRL_PIN(90, "GPIO_90"), + PINCTRL_PIN(91, "GPIO_91"), + PINCTRL_PIN(92, "GPIO_92"), + PINCTRL_PIN(93, "GPIO_93"), + PINCTRL_PIN(94, "GPIO_94"), + PINCTRL_PIN(95, "GPIO_95"), + PINCTRL_PIN(96, "GPIO_96"), + PINCTRL_PIN(97, "GPIO_97"), + PINCTRL_PIN(98, "GPIO_98"), + PINCTRL_PIN(99, "GPIO_99"), + PINCTRL_PIN(100, "GPIO_100"), + PINCTRL_PIN(101, "GPIO_101"), + PINCTRL_PIN(102, "GPIO_102"), + PINCTRL_PIN(103, "GPIO_103"), + PINCTRL_PIN(104, "GPIO_104"), + PINCTRL_PIN(105, "GPIO_105"), + PINCTRL_PIN(106, "GPIO_106"), + PINCTRL_PIN(107, "GPIO_107"), + PINCTRL_PIN(108, "GPIO_108"), + PINCTRL_PIN(109, "GPIO_109"), + PINCTRL_PIN(110, "GPIO_110"), + PINCTRL_PIN(111, "GPIO_111"), + PINCTRL_PIN(112, "GPIO_112"), + PINCTRL_PIN(113, "GPIO_113"), + PINCTRL_PIN(114, "GPIO_114"), + PINCTRL_PIN(115, "GPIO_115"), + PINCTRL_PIN(116, "GPIO_116"), + PINCTRL_PIN(117, "GPIO_117"), + PINCTRL_PIN(118, "GPIO_118"), + PINCTRL_PIN(119, "GPIO_119"), + PINCTRL_PIN(120, "GPIO_120"), + PINCTRL_PIN(121, "GPIO_121"), + PINCTRL_PIN(122, "GPIO_122"), + PINCTRL_PIN(123, "GPIO_123"), + PINCTRL_PIN(124, "GPIO_124"), + PINCTRL_PIN(125, "GPIO_125"), + PINCTRL_PIN(126, "GPIO_126"), + PINCTRL_PIN(127, "GPIO_127"), + PINCTRL_PIN(128, "GPIO_128"), + PINCTRL_PIN(129, "GPIO_129"), + PINCTRL_PIN(130, "GPIO_130"), + PINCTRL_PIN(131, "GPIO_131"), + PINCTRL_PIN(132, "GPIO_132"), + PINCTRL_PIN(133, "SDC1_RCLK"), + PINCTRL_PIN(134, "SDC1_CLK"), + PINCTRL_PIN(135, "SDC1_CMD"), + PINCTRL_PIN(136, "SDC1_DATA"), + PINCTRL_PIN(137, "SDC2_CLK"), + PINCTRL_PIN(138, "SDC2_CMD"), + PINCTRL_PIN(139, "SDC2_DATA"), +}; + +#define DECLARE_MSM_GPIO_PINS(pin) \ + static const unsigned int gpio##pin##_pins[] = {pin} +DECLARE_MSM_GPIO_PINS(0); +DECLARE_MSM_GPIO_PINS(1); +DECLARE_MSM_GPIO_PINS(2); +DECLARE_MSM_GPIO_PINS(3); +DECLARE_MSM_GPIO_PINS(4); +DECLARE_MSM_GPIO_PINS(5); +DECLARE_MSM_GPIO_PINS(6); +DECLARE_MSM_GPIO_PINS(7); +DECLARE_MSM_GPIO_PINS(8); +DECLARE_MSM_GPIO_PINS(9); +DECLARE_MSM_GPIO_PINS(10); +DECLARE_MSM_GPIO_PINS(11); +DECLARE_MSM_GPIO_PINS(12); +DECLARE_MSM_GPIO_PINS(13); +DECLARE_MSM_GPIO_PINS(14); +DECLARE_MSM_GPIO_PINS(15); +DECLARE_MSM_GPIO_PINS(16); +DECLARE_MSM_GPIO_PINS(17); +DECLARE_MSM_GPIO_PINS(18); +DECLARE_MSM_GPIO_PINS(19); +DECLARE_MSM_GPIO_PINS(20); +DECLARE_MSM_GPIO_PINS(21); +DECLARE_MSM_GPIO_PINS(22); +DECLARE_MSM_GPIO_PINS(23); +DECLARE_MSM_GPIO_PINS(24); +DECLARE_MSM_GPIO_PINS(25); +DECLARE_MSM_GPIO_PINS(26); +DECLARE_MSM_GPIO_PINS(27); +DECLARE_MSM_GPIO_PINS(28); +DECLARE_MSM_GPIO_PINS(29); +DECLARE_MSM_GPIO_PINS(30); +DECLARE_MSM_GPIO_PINS(31); +DECLARE_MSM_GPIO_PINS(32); +DECLARE_MSM_GPIO_PINS(33); +DECLARE_MSM_GPIO_PINS(34); +DECLARE_MSM_GPIO_PINS(35); +DECLARE_MSM_GPIO_PINS(36); +DECLARE_MSM_GPIO_PINS(37); +DECLARE_MSM_GPIO_PINS(38); +DECLARE_MSM_GPIO_PINS(39); +DECLARE_MSM_GPIO_PINS(40); +DECLARE_MSM_GPIO_PINS(41); +DECLARE_MSM_GPIO_PINS(42); +DECLARE_MSM_GPIO_PINS(43); +DECLARE_MSM_GPIO_PINS(44); +DECLARE_MSM_GPIO_PINS(45); +DECLARE_MSM_GPIO_PINS(46); +DECLARE_MSM_GPIO_PINS(47); +DECLARE_MSM_GPIO_PINS(48); +DECLARE_MSM_GPIO_PINS(49); +DECLARE_MSM_GPIO_PINS(50); +DECLARE_MSM_GPIO_PINS(51); +DECLARE_MSM_GPIO_PINS(52); +DECLARE_MSM_GPIO_PINS(53); +DECLARE_MSM_GPIO_PINS(54); +DECLARE_MSM_GPIO_PINS(55); +DECLARE_MSM_GPIO_PINS(56); +DECLARE_MSM_GPIO_PINS(57); +DECLARE_MSM_GPIO_PINS(58); +DECLARE_MSM_GPIO_PINS(59); +DECLARE_MSM_GPIO_PINS(60); +DECLARE_MSM_GPIO_PINS(61); +DECLARE_MSM_GPIO_PINS(62); +DECLARE_MSM_GPIO_PINS(63); +DECLARE_MSM_GPIO_PINS(64); +DECLARE_MSM_GPIO_PINS(65); +DECLARE_MSM_GPIO_PINS(66); +DECLARE_MSM_GPIO_PINS(67); +DECLARE_MSM_GPIO_PINS(68); +DECLARE_MSM_GPIO_PINS(69); +DECLARE_MSM_GPIO_PINS(70); +DECLARE_MSM_GPIO_PINS(71); +DECLARE_MSM_GPIO_PINS(72); +DECLARE_MSM_GPIO_PINS(73); +DECLARE_MSM_GPIO_PINS(74); +DECLARE_MSM_GPIO_PINS(75); +DECLARE_MSM_GPIO_PINS(76); +DECLARE_MSM_GPIO_PINS(77); +DECLARE_MSM_GPIO_PINS(78); +DECLARE_MSM_GPIO_PINS(79); +DECLARE_MSM_GPIO_PINS(80); +DECLARE_MSM_GPIO_PINS(81); +DECLARE_MSM_GPIO_PINS(82); +DECLARE_MSM_GPIO_PINS(83); +DECLARE_MSM_GPIO_PINS(84); +DECLARE_MSM_GPIO_PINS(85); +DECLARE_MSM_GPIO_PINS(86); +DECLARE_MSM_GPIO_PINS(87); +DECLARE_MSM_GPIO_PINS(88); +DECLARE_MSM_GPIO_PINS(89); +DECLARE_MSM_GPIO_PINS(90); +DECLARE_MSM_GPIO_PINS(91); +DECLARE_MSM_GPIO_PINS(92); +DECLARE_MSM_GPIO_PINS(93); +DECLARE_MSM_GPIO_PINS(94); +DECLARE_MSM_GPIO_PINS(95); +DECLARE_MSM_GPIO_PINS(96); +DECLARE_MSM_GPIO_PINS(97); +DECLARE_MSM_GPIO_PINS(98); +DECLARE_MSM_GPIO_PINS(99); +DECLARE_MSM_GPIO_PINS(100); +DECLARE_MSM_GPIO_PINS(101); +DECLARE_MSM_GPIO_PINS(102); +DECLARE_MSM_GPIO_PINS(103); +DECLARE_MSM_GPIO_PINS(104); +DECLARE_MSM_GPIO_PINS(105); +DECLARE_MSM_GPIO_PINS(106); +DECLARE_MSM_GPIO_PINS(107); +DECLARE_MSM_GPIO_PINS(108); +DECLARE_MSM_GPIO_PINS(109); +DECLARE_MSM_GPIO_PINS(110); +DECLARE_MSM_GPIO_PINS(111); +DECLARE_MSM_GPIO_PINS(112); +DECLARE_MSM_GPIO_PINS(113); +DECLARE_MSM_GPIO_PINS(114); +DECLARE_MSM_GPIO_PINS(115); +DECLARE_MSM_GPIO_PINS(116); +DECLARE_MSM_GPIO_PINS(117); +DECLARE_MSM_GPIO_PINS(118); +DECLARE_MSM_GPIO_PINS(119); +DECLARE_MSM_GPIO_PINS(120); +DECLARE_MSM_GPIO_PINS(121); +DECLARE_MSM_GPIO_PINS(122); +DECLARE_MSM_GPIO_PINS(123); +DECLARE_MSM_GPIO_PINS(124); +DECLARE_MSM_GPIO_PINS(125); +DECLARE_MSM_GPIO_PINS(126); +DECLARE_MSM_GPIO_PINS(127); +DECLARE_MSM_GPIO_PINS(128); +DECLARE_MSM_GPIO_PINS(129); +DECLARE_MSM_GPIO_PINS(130); +DECLARE_MSM_GPIO_PINS(131); +DECLARE_MSM_GPIO_PINS(132); + +static const unsigned int sdc1_rclk_pins[] = {133}; +static const unsigned int sdc1_clk_pins[] = {134}; +static const unsigned int sdc1_cmd_pins[] = {135}; +static const unsigned int sdc1_data_pins[] = {136}; +static const unsigned int sdc2_clk_pins[] = {137}; +static const unsigned int sdc2_cmd_pins[] = {138}; +static const unsigned int sdc2_data_pins[] = {139}; + +enum sdx75_functions { + msm_mux_adsp_ext, + msm_mux_atest_char, + msm_mux_audio_ref_clk, + msm_mux_bimc_dte, + msm_mux_char_exec, + msm_mux_coex_uart2, + msm_mux_coex_uart, + msm_mux_cri_trng, + msm_mux_cri_trng0, + msm_mux_cri_trng1, + msm_mux_dbg_out_clk, + msm_mux_ddr_bist, + msm_mux_ddr_pxi0, + msm_mux_ebi0_wrcdc, + msm_mux_ebi2_a, + msm_mux_ebi2_lcd, + msm_mux_ebi2_lcd_te, + msm_mux_emac0_mcg, + msm_mux_emac0_ptp, + msm_mux_emac1_mcg, + msm_mux_emac1_ptp, + msm_mux_emac_cdc, + msm_mux_emac_pps_in, + msm_mux_eth0_mdc, + msm_mux_eth0_mdio, + msm_mux_eth1_mdc, + msm_mux_eth1_mdio, + msm_mux_ext_dbg, + msm_mux_gcc_125_clk, + msm_mux_gcc_gp1_clk, + msm_mux_gcc_gp2_clk, + msm_mux_gcc_gp3_clk, + msm_mux_gcc_plltest, + msm_mux_gpio, + msm_mux_i2s_mclk, + msm_mux_jitter_bist, + msm_mux_ldo_en, + msm_mux_ldo_update, + msm_mux_m_voc, + msm_mux_mgpi_clk, + msm_mux_native_char, + msm_mux_native_tsens, + msm_mux_native_tsense, + msm_mux_nav_dr_sync, + msm_mux_nav_gpio, + msm_mux_pa_indicator, + msm_mux_pci_e, + msm_mux_pcie0_clkreq_n, + msm_mux_pcie1_clkreq_n, + msm_mux_pcie2_clkreq_n, + msm_mux_pll_bist_sync, + msm_mux_pll_clk_aux, + msm_mux_pll_ref_clk, + msm_mux_pri_mi2s, + msm_mux_prng_rosc, + msm_mux_qdss_cti, + msm_mux_qdss_gpio, + msm_mux_qlink0_b_en, + msm_mux_qlink0_b_req, + msm_mux_qlink0_l_en, + msm_mux_qlink0_l_req, + msm_mux_qlink0_wmss, + msm_mux_qlink1_l_en, + msm_mux_qlink1_l_req, + msm_mux_qlink1_wmss, + msm_mux_qup_se0, + msm_mux_qup_se1_l2_mira, + msm_mux_qup_se1_l2_mirb, + msm_mux_qup_se1_l3_mira, + msm_mux_qup_se1_l3_mirb, + msm_mux_qup_se2, + msm_mux_qup_se3, + msm_mux_qup_se4, + msm_mux_qup_se5, + msm_mux_qup_se6, + msm_mux_qup_se7, + msm_mux_qup_se8, + msm_mux_rgmii_rx_ctl, + msm_mux_rgmii_rxc, + msm_mux_rgmii_rxd, + msm_mux_rgmii_tx_ctl, + msm_mux_rgmii_txc, + msm_mux_rgmii_txd, + msm_mux_sd_card, + msm_mux_sdc1_tb, + msm_mux_sdc2_tb_trig, + msm_mux_sec_mi2s, + msm_mux_sgmii_phy_intr0_n, + msm_mux_sgmii_phy_intr1_n, + msm_mux_spmi_coex, + msm_mux_spmi_vgi, + msm_mux_tgu_ch0_trigout, + msm_mux_tmess_prng0, + msm_mux_tmess_prng1, + msm_mux_tmess_prng2, + msm_mux_tmess_prng3, + msm_mux_tri_mi2s, + msm_mux_uim1_clk, + msm_mux_uim1_data, + msm_mux_uim1_present, + msm_mux_uim1_reset, + msm_mux_uim2_clk, + msm_mux_uim2_data, + msm_mux_uim2_present, + msm_mux_uim2_reset, + msm_mux_usb2phy_ac_en, + msm_mux_vsense_trigger_mirnat, + msm_mux__, +}; + +static const char *const gpio_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", + "gpio7", "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", + "gpio14", "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", + "gpio21", "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", + "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", + "gpio35", "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", + "gpio42", "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", + "gpio49", "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", + "gpio56", "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", + "gpio63", "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", + "gpio70", "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", + "gpio77", "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", + "gpio84", "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", + "gpio91", "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", + "gpio98", "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104", + "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110", "gpio111", + "gpio112", "gpio113", "gpio114", "gpio115", "gpio116", "gpio117", "gpio118", + "gpio119", "gpio120", "gpio121", "gpio122", "gpio123", "gpio124", "gpio125", + "gpio126", "gpio127", "gpio128", "gpio129", "gpio130", "gpio131", "gpio132", +}; +static const char *const adsp_ext_groups[] = { + "gpio59", "gpio68", +}; +static const char *const atest_char_groups[] = { + "gpio24", "gpio25", "gpio26", "gpio41", "gpio63", +}; +static const char *const audio_ref_clk_groups[] = { + "gpio126", +}; +static const char *const bimc_dte_groups[] = { + "gpio14", "gpio15", "gpio61", "gpio59", +}; +static const char *const char_exec_groups[] = { + "gpio6", "gpio7", +}; +static const char *const coex_uart2_groups[] = { + "gpio48", "gpio49", "gpio90", "gpio91", +}; +static const char *const coex_uart_groups[] = { + "gpio46", "gpio47", +}; +static const char *const cri_trng_groups[] = { + "gpio36", +}; +static const char *const cri_trng0_groups[] = { + "gpio31", +}; +static const char *const cri_trng1_groups[] = { + "gpio32", +}; +static const char *const dbg_out_clk_groups[] = { + "gpio26", +}; +static const char *const ddr_bist_groups[] = { + "gpio46", "gpio47", "gpio48", "gpio49", +}; +static const char *const ddr_pxi0_groups[] = { + "gpio45", "gpio46", +}; +static const char *const ebi0_wrcdc_groups[] = { + "gpio0", "gpio2", +}; +static const char *const ebi2_a_groups[] = { + "gpio100", +}; +static const char *const ebi2_lcd_groups[] = { + "gpio99", "gpio101", +}; +static const char *const ebi2_lcd_te_groups[] = { + "gpio98", +}; +static const char *const emac0_mcg_groups[] = { + "gpio83", "gpio84", "gpio85", "gpio89", +}; +static const char *const emac0_ptp_groups[] = { + "gpio35", "gpio83", "gpio84", "gpio85", "gpio89", "gpio119", "gpio123", +}; +static const char *const emac1_mcg_groups[] = { + "gpio90", "gpio92", "gpio93", "gpio122", +}; +static const char *const emac1_ptp_groups[] = { + "gpio112", "gpio113", "gpio114", "gpio115", +}; +static const char *const emac_cdc_groups[] = { + "gpio38", "gpio39", +}; +static const char *const emac_pps_in_groups[] = { + "gpio127", +}; +static const char *const eth0_mdc_groups[] = { + "gpio94", +}; +static const char *const eth0_mdio_groups[] = { + "gpio95", +}; +static const char *const eth1_mdc_groups[] = { + "gpio106", +}; +static const char *const eth1_mdio_groups[] = { + "gpio107", +}; +static const char *const ext_dbg_groups[] = { + "gpio12", "gpio13", "gpio14", "gpio15", +}; +static const char *const gcc_125_clk_groups[] = { + "gpio25", +}; +static const char *const gcc_gp1_clk_groups[] = { + "gpio39", +}; +static const char *const gcc_gp2_clk_groups[] = { + "gpio40", +}; +static const char *const gcc_gp3_clk_groups[] = { + "gpio41", +}; +static const char *const gcc_plltest_groups[] = { + "gpio81", "gpio82", +}; +static const char *const i2s_mclk_groups[] = { + "gpio74", +}; +static const char *const jitter_bist_groups[] = { + "gpio41", +}; +static const char *const ldo_en_groups[] = { + "gpio8", +}; +static const char *const ldo_update_groups[] = { + "gpio62", +}; +static const char *const m_voc_groups[] = { + "gpio62", "gpio63", "gpio64", "gpio65", "gpio71", +}; +static const char *const mgpi_clk_groups[] = { + "gpio39", "gpio40", +}; +static const char *const native_char_groups[] = { + "gpio29", "gpio33", "gpio57", "gpio66", "gpio67", +}; +static const char *const native_tsens_groups[] = { + "gpio38", +}; +static const char *const native_tsense_groups[] = { + "gpio64", "gpio76", +}; +static const char *const nav_dr_sync_groups[] = { + "gpio36", +}; +static const char *const nav_gpio_groups[] = { + "gpio35", "gpio36", "gpio104", +}; +static const char *const pa_indicator_groups[] = { + "gpio58", +}; +static const char *const pci_e_groups[] = { + "gpio42", +}; +static const char *const pcie0_clkreq_n_groups[] = { + "gpio43", +}; +static const char *const pcie1_clkreq_n_groups[] = { + "gpio124", +}; +static const char *const pcie2_clkreq_n_groups[] = { + "gpio121", +}; +static const char *const pll_bist_sync_groups[] = { + "gpio38", +}; +static const char *const pll_clk_aux_groups[] = { + "gpio40", +}; +static const char *const pll_ref_clk_groups[] = { + "gpio37", +}; +static const char *const pri_mi2s_groups[] = { + "gpio16", "gpio17", "gpio18", "gpio19", +}; +static const char *const prng_rosc_groups[] = { + "gpio27", "gpio36", "gpio37", "gpio38", +}; +static const char *const qdss_cti_groups[] = { + "gpio16", "gpio17", "gpio52", "gpio53", "gpio56", + "gpio57", "gpio59", "gpio60", "gpio78", "gpio79", +}; +static const char *const qdss_gpio_groups[] = { + "gpio82", "gpio83", "gpio84", "gpio85", "gpio94", + "gpio95", "gpio96", "gpio97", "gpio110", "gpio111", + "gpio112", "gpio113", "gpio114", "gpio115", "gpio116", + "gpio117", "gpio118", "gpio119", +}; +static const char *const qlink0_b_en_groups[] = { + "gpio40", +}; +static const char *const qlink0_b_req_groups[] = { + "gpio41", +}; +static const char *const qlink0_l_en_groups[] = { + "gpio37", +}; +static const char *const qlink0_l_req_groups[] = { + "gpio38", +}; +static const char *const qlink0_wmss_groups[] = { + "gpio39", +}; +static const char *const qlink1_l_en_groups[] = { + "gpio26", +}; +static const char *const qlink1_l_req_groups[] = { + "gpio27", +}; +static const char *const qlink1_wmss_groups[] = { + "gpio28", +}; +static const char *const qup_se0_groups[] = { + "gpio8", "gpio9", "gpio10", "gpio11", +}; +static const char *const qup_se1_l2_mira_groups[] = { + "gpio12", +}; +static const char *const qup_se1_l2_mirb_groups[] = { + "gpio16", +}; +static const char *const qup_se1_l3_mira_groups[] = { + "gpio13", +}; +static const char *const qup_se1_l3_mirb_groups[] = { + "gpio17", +}; +static const char *const qup_se2_groups[] = { + "gpio14", "gpio15", "gpio16", "gpio17", +}; +static const char *const qup_se3_groups[] = { + "gpio52", "gpio53", "gpio54", "gpio55", +}; +static const char *const qup_se4_groups[] = { + "gpio64", "gpio65", +}; +static const char *const qup_se5_groups[] = { + "gpio110", "gpio111", +}; +static const char *const qup_se6_groups[] = { + "gpio112", "gpio113", "gpio114", "gpio115", +}; +static const char *const qup_se7_groups[] = { + "gpio116", "gpio117", "gpio118", "gpio119", +}; +static const char *const qup_se8_groups[] = { + "gpio124", "gpio125", +}; +static const char *const rgmii_rx_ctl_groups[] = { + "gpio93", +}; +static const char *const rgmii_rxc_groups[] = { + "gpio88", +}; +static const char *const rgmii_rxd_groups[] = { + "gpio89", "gpio90", "gpio91", "gpio92", +}; +static const char *const rgmii_tx_ctl_groups[] = { + "gpio87", +}; +static const char *const rgmii_txc_groups[] = { + "gpio82", +}; +static const char *const rgmii_txd_groups[] = { + "gpio83", "gpio84", "gpio85", "gpio86", +}; +static const char *const sd_card_groups[] = { + "gpio105", +}; +static const char *const sdc1_tb_groups[] = { + "gpio84", "gpio130", +}; +static const char *const sdc2_tb_trig_groups[] = { + "gpio129", +}; +static const char *const sec_mi2s_groups[] = { + "gpio20", "gpio21", "gpio22", "gpio23", +}; +static const char *const sgmii_phy_intr0_n_groups[] = { + "gpio97", +}; +static const char *const sgmii_phy_intr1_n_groups[] = { + "gpio109", +}; +static const char *const spmi_coex_groups[] = { + "gpio48", "gpio49", +}; +static const char *const spmi_vgi_groups[] = { + "gpio50", "gpio51", +}; +static const char *const tgu_ch0_trigout_groups[] = { + "gpio55", +}; +static const char *const tmess_prng0_groups[] = { + "gpio28", +}; +static const char *const tmess_prng1_groups[] = { + "gpio29", +}; +static const char *const tmess_prng2_groups[] = { + "gpio30", +}; +static const char *const tmess_prng3_groups[] = { + "gpio31", +}; +static const char *const tri_mi2s_groups[] = { + "gpio98", "gpio99", "gpio100", "gpio101", +}; +static const char *const uim1_clk_groups[] = { + "gpio7", +}; +static const char *const uim1_data_groups[] = { + "gpio4", +}; +static const char *const uim1_present_groups[] = { + "gpio5", +}; +static const char *const uim1_reset_groups[] = { + "gpio6", +}; +static const char *const uim2_clk_groups[] = { + "gpio3", +}; +static const char *const uim2_data_groups[] = { + "gpio0", +}; +static const char *const uim2_present_groups[] = { + "gpio1", +}; +static const char *const uim2_reset_groups[] = { + "gpio2", +}; +static const char *const usb2phy_ac_en_groups[] = { + "gpio80", +}; +static const char *const vsense_trigger_mirnat_groups[] = { + "gpio37", +}; + +static const struct pinfunction sdx75_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(audio_ref_clk), + MSM_PIN_FUNCTION(bimc_dte), + MSM_PIN_FUNCTION(char_exec), + MSM_PIN_FUNCTION(coex_uart2), + MSM_PIN_FUNCTION(coex_uart), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out_clk), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ebi0_wrcdc), + MSM_PIN_FUNCTION(ebi2_a), + MSM_PIN_FUNCTION(ebi2_lcd), + MSM_PIN_FUNCTION(ebi2_lcd_te), + MSM_PIN_FUNCTION(emac0_mcg), + MSM_PIN_FUNCTION(emac0_ptp), + MSM_PIN_FUNCTION(emac1_mcg), + MSM_PIN_FUNCTION(emac1_ptp), + MSM_PIN_FUNCTION(emac_cdc), + MSM_PIN_FUNCTION(emac_pps_in), + MSM_PIN_FUNCTION(eth0_mdc), + MSM_PIN_FUNCTION(eth0_mdio), + MSM_PIN_FUNCTION(eth1_mdc), + MSM_PIN_FUNCTION(eth1_mdio), + MSM_PIN_FUNCTION(ext_dbg), + MSM_PIN_FUNCTION(gcc_125_clk), + MSM_PIN_FUNCTION(gcc_gp1_clk), + MSM_PIN_FUNCTION(gcc_gp2_clk), + MSM_PIN_FUNCTION(gcc_gp3_clk), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(i2s_mclk), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mgpi_clk), + MSM_PIN_FUNCTION(native_char), + MSM_PIN_FUNCTION(native_tsens), + MSM_PIN_FUNCTION(native_tsense), + MSM_PIN_FUNCTION(nav_dr_sync), + MSM_PIN_FUNCTION(nav_gpio), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pci_e), + MSM_PIN_FUNCTION(pcie0_clkreq_n), + MSM_PIN_FUNCTION(pcie1_clkreq_n), + MSM_PIN_FUNCTION(pcie2_clkreq_n), + MSM_PIN_FUNCTION(pll_bist_sync), + MSM_PIN_FUNCTION(pll_clk_aux), + MSM_PIN_FUNCTION(pll_ref_clk), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qlink0_b_en), + MSM_PIN_FUNCTION(qlink0_b_req), + MSM_PIN_FUNCTION(qlink0_l_en), + MSM_PIN_FUNCTION(qlink0_l_req), + MSM_PIN_FUNCTION(qlink1_l_en), + MSM_PIN_FUNCTION(qlink1_l_req), + MSM_PIN_FUNCTION(qlink0_wmss), + MSM_PIN_FUNCTION(qlink1_wmss), + MSM_PIN_FUNCTION(qup_se0), + MSM_PIN_FUNCTION(qup_se1_l2_mira), + MSM_PIN_FUNCTION(qup_se1_l2_mirb), + MSM_PIN_FUNCTION(qup_se1_l3_mira), + MSM_PIN_FUNCTION(qup_se1_l3_mirb), + MSM_PIN_FUNCTION(qup_se2), + MSM_PIN_FUNCTION(qup_se3), + MSM_PIN_FUNCTION(qup_se4), + MSM_PIN_FUNCTION(qup_se5), + MSM_PIN_FUNCTION(qup_se6), + MSM_PIN_FUNCTION(qup_se7), + MSM_PIN_FUNCTION(qup_se8), + MSM_PIN_FUNCTION(rgmii_rx_ctl), + MSM_PIN_FUNCTION(rgmii_rxc), + MSM_PIN_FUNCTION(rgmii_rxd), + MSM_PIN_FUNCTION(rgmii_tx_ctl), + MSM_PIN_FUNCTION(rgmii_txc), + MSM_PIN_FUNCTION(rgmii_txd), + MSM_PIN_FUNCTION(sd_card), + MSM_PIN_FUNCTION(sdc1_tb), + MSM_PIN_FUNCTION(sdc2_tb_trig), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(sgmii_phy_intr0_n), + MSM_PIN_FUNCTION(sgmii_phy_intr1_n), + MSM_PIN_FUNCTION(spmi_coex), + MSM_PIN_FUNCTION(spmi_vgi), + MSM_PIN_FUNCTION(tgu_ch0_trigout), + MSM_PIN_FUNCTION(tmess_prng0), + MSM_PIN_FUNCTION(tmess_prng1), + MSM_PIN_FUNCTION(tmess_prng2), + MSM_PIN_FUNCTION(tmess_prng3), + MSM_PIN_FUNCTION(tri_mi2s), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(usb2phy_ac_en), + MSM_PIN_FUNCTION(vsense_trigger_mirnat), +}; + +static const struct msm_pingroup sdx75_groups[] = { + [0] = PINGROUP(0, uim2_data, ebi0_wrcdc, _, _, _, _, _, _, _, _), + [1] = PINGROUP(1, uim2_present, _, _, _, _, _, _, _, _, _), + [2] = PINGROUP(2, uim2_reset, ebi0_wrcdc, _, _, _, _, _, _, _, _), + [3] = PINGROUP(3, uim2_clk, _, _, _, _, _, _, _, _, _), + [4] = PINGROUP(4, uim1_data, _, _, _, _, _, _, _, _, _), + [5] = PINGROUP(5, uim1_present, _, _, _, _, _, _, _, _, _), + [6] = PINGROUP(6, uim1_reset, char_exec, _, _, _, _, _, _, _, _), + [7] = PINGROUP(7, uim1_clk, char_exec, _, _, _, _, _, _, _, _), + [8] = PINGROUP(8, qup_se0, ldo_en, _, _, _, _, _, _, _, _), + [9] = PINGROUP(9, qup_se0, _, _, _, _, _, _, _, _, _), + [10] = PINGROUP(10, qup_se0, _, _, _, _, _, _, _, _, _), + [11] = PINGROUP(11, qup_se0, _, _, _, _, _, _, _, _, _), + [12] = PINGROUP(12, qup_se1_l2_mira, ext_dbg, _, _, _, _, _, _, _, _), + [13] = PINGROUP(13, qup_se1_l3_mira, ext_dbg, _, _, _, _, _, _, _, _), + [14] = PINGROUP(14, qup_se2, ext_dbg, bimc_dte, _, _, _, _, _, _, _), + [15] = PINGROUP(15, qup_se2, ext_dbg, bimc_dte, _, _, _, _, _, _, _), + [16] = PINGROUP(16, pri_mi2s, qup_se2, qup_se1_l2_mirb, qdss_cti, qdss_cti, _, _, _, _, _), + [17] = PINGROUP(17, pri_mi2s, qup_se2, qup_se1_l3_mirb, qdss_cti, qdss_cti, _, _, _, _, _), + [18] = PINGROUP(18, pri_mi2s, _, _, _, _, _, _, _, _, _), + [19] = PINGROUP(19, pri_mi2s, _, _, _, _, _, _, _, _, _), + [20] = PINGROUP(20, sec_mi2s, _, _, _, _, _, _, _, _, _), + [21] = PINGROUP(21, sec_mi2s, _, _, _, _, _, _, _, _, _), + [22] = PINGROUP(22, sec_mi2s, _, _, _, _, _, _, _, _, _), + [23] = PINGROUP(23, sec_mi2s, _, _, _, _, _, _, _, _, _), + [24] = PINGROUP(24, _, atest_char, _, _, _, _, _, _, _, _), + [25] = PINGROUP(25, gcc_125_clk, _, atest_char, _, _, _, _, _, _, _), + [26] = PINGROUP(26, _, _, qlink1_l_en, dbg_out_clk, atest_char, _, _, _, _, _), + [27] = PINGROUP(27, _, _, qlink1_l_req, prng_rosc, _, _, _, _, _, _), + [28] = PINGROUP(28, _, qlink1_wmss, tmess_prng0, _, _, _, _, _, _, _), + [29] = PINGROUP(29, _, _, _, native_char, tmess_prng1, _, _, _, _, _), + [30] = PINGROUP(30, _, _, _, tmess_prng2, _, _, _, _, _, _), + [31] = PINGROUP(31, _, _, cri_trng0, _, tmess_prng3, _, _, _, _, _), + [32] = PINGROUP(32, _, _, cri_trng1, _, _, _, _, _, _, _), + [33] = PINGROUP(33, _, _, native_char, _, _, _, _, _, _, _), + [34] = PINGROUP(34, _, _, _, _, _, _, _, _, _, _), + [35] = PINGROUP(35, nav_gpio, emac0_ptp, emac0_ptp, _, _, _, _, _, _, _), + [36] = PINGROUP(36, nav_gpio, nav_dr_sync, nav_gpio, cri_trng, prng_rosc, _, _, _, _, _), + [37] = PINGROUP(37, qlink0_l_en, _, pll_ref_clk, prng_rosc, vsense_trigger_mirnat, _, _, _, _, _), + [38] = PINGROUP(38, qlink0_l_req, _, pll_bist_sync, prng_rosc, _, emac_cdc, _, native_tsens, _, _), + [39] = PINGROUP(39, qlink0_wmss, _, mgpi_clk, gcc_gp1_clk, _, emac_cdc, _, _, _, _), + [40] = PINGROUP(40, qlink0_b_en, _, mgpi_clk, pll_clk_aux, gcc_gp2_clk, _, _, _, _, _), + [41] = PINGROUP(41, qlink0_b_req, _, jitter_bist, gcc_gp3_clk, _, _, atest_char, _, _, _), + [42] = PINGROUP(42, pci_e, _, _, _, _, _, _, _, _, _), + [43] = PINGROUP(43, pcie0_clkreq_n, _, _, _, _, _, _, _, _, _), + [44] = PINGROUP(44, _, _, _, _, _, _, _, _, _, _), + [45] = PINGROUP(45, ddr_pxi0, _, _, _, _, _, _, _, _, _), + [46] = PINGROUP(46, coex_uart, ddr_bist, ddr_pxi0, _, _, _, _, _, _, _), + [47] = PINGROUP(47, coex_uart, ddr_bist, _, _, _, _, _, _, _, _), + [48] = PINGROUP(48, coex_uart2, spmi_coex, ddr_bist, _, _, _, _, _, _, _), + [49] = PINGROUP(49, coex_uart2, spmi_coex, ddr_bist, _, _, _, _, _, _, _), + [50] = PINGROUP(50, spmi_vgi, _, _, _, _, _, _, _, _, _), + [51] = PINGROUP(51, spmi_vgi, _, _, _, _, _, _, _, _, _), + [52] = PINGROUP(52, qup_se3, qdss_cti, qdss_cti, _, _, _, _, _, _, _), + [53] = PINGROUP(53, qup_se3, qdss_cti, qdss_cti, _, _, _, _, _, _, _), + [54] = PINGROUP(54, qup_se3, _, _, _, _, _, _, _, _, _), + [55] = PINGROUP(55, qup_se3, tgu_ch0_trigout, _, _, _, _, _, _, _, _), + [56] = PINGROUP(56, qdss_cti, qdss_cti, _, _, _, _, _, _, _, _), + [57] = PINGROUP(57, qdss_cti, qdss_cti, _, native_char, _, _, _, _, _, _), + [58] = PINGROUP(58, _, pa_indicator, _, _, _, _, _, _, _, _), + [59] = PINGROUP(59, adsp_ext, qdss_cti, _, bimc_dte, _, _, _, _, _, _), + [60] = PINGROUP(60, qdss_cti, _, _, _, _, _, _, _, _, _), + [61] = PINGROUP(61, _, bimc_dte, _, _, _, _, _, _, _, _), + [62] = PINGROUP(62, m_voc, ldo_update, _, _, _, _, _, _, _, _), + [63] = PINGROUP(63, m_voc, _, atest_char, _, _, _, _, _, _, _), + [64] = PINGROUP(64, qup_se4, m_voc, _, native_tsense, _, _, _, _, _, _), + [65] = PINGROUP(65, qup_se4, m_voc, _, _, _, _, _, _, _, _), + [66] = PINGROUP(66, _, native_char, _, _, _, _, _, _, _, _), + [67] = PINGROUP(67, _, native_char, _, _, _, _, _, _, _, _), + [68] = PINGROUP(68, adsp_ext, _, _, _, _, _, _, _, _, _), + [69] = PINGROUP(69, _, _, _, _, _, _, _, _, _, _), + [70] = PINGROUP(70, _, _, _, _, _, _, _, _, _, _), + [71] = PINGROUP(71, m_voc, _, _, _, _, _, _, _, _, _), + [72] = PINGROUP(72, _, _, _, _, _, _, _, _, _, _), + [73] = PINGROUP(73, _, _, _, _, _, _, _, _, _, _), + [74] = PINGROUP(74, i2s_mclk, _, _, _, _, _, _, _, _, _), + [75] = PINGROUP(75, _, _, _, _, _, _, _, _, _, _), + [76] = PINGROUP(76, native_tsense, _, _, _, _, _, _, _, _, _), + [77] = PINGROUP(77, _, _, _, _, _, _, _, _, _, _), + [78] = PINGROUP(78, qdss_cti, qdss_cti, _, _, _, _, _, _, _, _), + [79] = PINGROUP(79, qdss_cti, qdss_cti, _, _, _, _, _, _, _, _), + [80] = PINGROUP(80, usb2phy_ac_en, _, _, _, _, _, _, _, _, _), + [81] = PINGROUP(81, gcc_plltest, _, _, _, _, _, _, _, _, _), + [82] = PINGROUP(82, rgmii_txc, gcc_plltest, qdss_gpio, _, _, _, _, _, _, _), + [83] = PINGROUP(83, rgmii_txd, emac0_ptp, emac0_ptp, emac0_mcg, qdss_gpio, _, _, _, _, _), + [84] = PINGROUP(84, rgmii_txd, emac0_ptp, emac0_mcg, qdss_gpio, _, sdc1_tb, _, _, _, _), + [85] = PINGROUP(85, rgmii_txd, emac0_ptp, emac0_mcg, qdss_gpio, _, _, _, _, _, _), + [86] = PINGROUP(86, rgmii_txd, _, _, _, _, _, _, _, _, _), + [87] = PINGROUP(87, rgmii_tx_ctl, _, _, _, _, _, _, _, _, _), + [88] = PINGROUP(88, rgmii_rxc, _, _, _, _, _, _, _, _, _), + [89] = PINGROUP(89, rgmii_rxd, emac0_ptp, emac0_ptp, emac0_mcg, _, _, _, _, _, _), + [90] = PINGROUP(90, rgmii_rxd, coex_uart2, emac1_mcg, _, _, _, _, _, _, _), + [91] = PINGROUP(91, rgmii_rxd, coex_uart2, _, _, _, _, _, _, _, _), + [92] = PINGROUP(92, rgmii_rxd, emac1_mcg, _, _, _, _, _, _, _, _), + [93] = PINGROUP(93, rgmii_rx_ctl, emac1_mcg, _, _, _, _, _, _, _, _), + [94] = PINGROUP(94, eth0_mdc, qdss_gpio, _, _, _, _, _, _, _, _), + [95] = PINGROUP(95, eth0_mdio, qdss_gpio, _, _, _, _, _, _, _, _), + [96] = PINGROUP(96, qdss_gpio, _, _, _, _, _, _, _, _, _), + [97] = PINGROUP(97, sgmii_phy_intr0_n, _, qdss_gpio, _, _, _, _, _, _, _), + [98] = PINGROUP(98, tri_mi2s, ebi2_lcd_te, _, _, _, _, _, _, _, _), + [99] = PINGROUP(99, tri_mi2s, ebi2_lcd, _, _, _, _, _, _, _, _), + [100] = PINGROUP(100, tri_mi2s, ebi2_a, _, _, _, _, _, _, _, _), + [101] = PINGROUP(101, tri_mi2s, ebi2_lcd, _, _, _, _, _, _, _, _), + [102] = PINGROUP(102, _, _, _, _, _, _, _, _, _, _), + [103] = PINGROUP(103, _, _, _, _, _, _, _, _, _, _), + [104] = PINGROUP(104, nav_gpio, _, _, _, _, _, _, _, _, _), + [105] = PINGROUP(105, sd_card, _, _, _, _, _, _, _, _, _), + [106] = PINGROUP(106, eth1_mdc, _, _, _, _, _, _, _, _, _), + [107] = PINGROUP(107, eth1_mdio, _, _, _, _, _, _, _, _, _), + [108] = PINGROUP(108, _, _, _, _, _, _, _, _, _, _), + [109] = PINGROUP(109, sgmii_phy_intr1_n, _, _, _, _, _, _, _, _, _), + [110] = PINGROUP(110, qup_se5, qdss_gpio, _, _, _, _, _, _, _, _), + [111] = PINGROUP(111, qup_se5, qdss_gpio, _, _, _, _, _, _, _, _), + [112] = PINGROUP(112, qup_se6, emac1_ptp, emac1_ptp, qdss_gpio, _, _, _, _, _, _), + [113] = PINGROUP(113, qup_se6, emac1_ptp, emac1_ptp, qdss_gpio, _, _, _, _, _, _), + [114] = PINGROUP(114, qup_se6, emac1_ptp, emac1_ptp, qdss_gpio, _, _, _, _, _, _), + [115] = PINGROUP(115, qup_se6, emac1_ptp, emac1_ptp, qdss_gpio, _, _, _, _, _, _), + [116] = PINGROUP(116, qup_se7, qdss_gpio, _, _, _, _, _, _, _, _), + [117] = PINGROUP(117, qup_se7, qdss_gpio, _, _, _, _, _, _, _, _), + [118] = PINGROUP(118, qup_se7, qdss_gpio, _, _, _, _, _, _, _, _), + [119] = PINGROUP(119, qup_se7, emac0_ptp, qdss_gpio, _, _, _, _, _, _, _), + [120] = PINGROUP(120, _, _, _, _, _, _, _, _, _, _), + [121] = PINGROUP(121, pcie2_clkreq_n, _, _, _, _, _, _, _, _, _), + [122] = PINGROUP(122, emac1_mcg, _, _, _, _, _, _, _, _, _), + [123] = PINGROUP(123, emac0_ptp, emac0_ptp, emac0_ptp, emac0_ptp, _, _, _, _, _, _), + [124] = PINGROUP(124, pcie1_clkreq_n, qup_se8, _, _, _, _, _, _, _, _), + [125] = PINGROUP(125, qup_se8, _, _, _, _, _, _, _, _, _), + [126] = PINGROUP(126, audio_ref_clk, _, _, _, _, _, _, _, _, _), + [127] = PINGROUP(127, emac_pps_in, _, _, _, _, _, _, _, _, _), + [128] = PINGROUP(128, _, _, _, _, _, _, _, _, _, _), + [129] = PINGROUP(129, sdc2_tb_trig, _, _, _, _, _, _, _, _, _), + [130] = PINGROUP(130, sdc1_tb, _, _, _, _, _, _, _, _, _), + [131] = PINGROUP(131, _, _, _, _, _, _, _, _, _, _), + [132] = PINGROUP(132, _, _, _, _, _, _, _, _, _, _), + [133] = SDC_QDSD_PINGROUP(sdc1_rclk, 0x19a000, 16, 0), + [134] = SDC_QDSD_PINGROUP(sdc1_clk, 0x19a000, 14, 6), + [135] = SDC_QDSD_PINGROUP(sdc1_cmd, 0x19a000, 11, 3), + [136] = SDC_QDSD_PINGROUP(sdc1_data, 0x19a000, 9, 0), + [137] = SDC_QDSD_PINGROUP(sdc2_clk, 0x19b000, 14, 6), + [138] = SDC_QDSD_PINGROUP(sdc2_cmd, 0x19b000, 11, 3), + [139] = SDC_QDSD_PINGROUP(sdc2_data, 0x19b000, 9, 0), +}; + +static const struct msm_gpio_wakeirq_map sdx75_pdc_map[] = { + { 1, 57 }, { 2, 91 }, {5, 52 }, { 6, 109 }, { 9, 129 }, { 11, 62 }, + { 13, 84 }, { 15, 87 }, { 17, 88 }, { 18, 89 }, { 19, 90 }, { 20, 92 }, + { 21, 93 }, { 22, 94 }, { 23, 95 }, { 25, 96 }, { 27, 97 }, { 35, 58 }, + { 36, 53 }, { 38, 98 }, { 39, 99 }, { 40, 100 }, { 41, 101 }, { 42, 54 }, + { 43, 56 }, { 44, 71 }, { 46, 60 }, { 47, 61 }, { 49, 47 }, { 50, 126 }, + { 51, 55 }, { 52, 102 }, { 53, 141 }, { 54, 104 }, { 55, 105 }, { 56, 106 }, + { 57, 107 }, { 59, 108 }, { 60, 110 }, { 62, 111 }, { 63, 112 }, { 64, 113 }, + { 65, 114 }, { 67, 115 }, { 68, 116 }, { 69, 117 }, { 70, 118 }, { 71, 119 }, + { 72, 120 }, { 75, 121 }, { 76, 122 }, { 78, 123 }, { 79, 124 }, { 80, 125 }, + { 81, 50 }, { 85, 127 }, { 87, 128 }, { 91, 130 }, { 92, 131 }, { 93, 132 }, + { 94, 133 }, { 95, 134 }, { 97, 135 }, { 98, 136 }, { 101, 64 }, { 103, 51 }, + { 105, 65 }, { 106, 66 }, { 107, 67 }, { 108, 68 }, { 109, 69 }, { 111, 70 }, + { 113, 59 }, { 115, 72 }, { 116, 73 }, { 117, 74 }, { 118, 75 }, { 119, 76 }, + { 120, 77 }, { 121, 78 }, { 123, 79 }, { 124, 80 }, { 125, 63 }, { 127, 81 }, + { 128, 82 }, { 129, 83 }, { 130, 85 }, { 132, 86 }, +}; + +static const struct msm_pinctrl_soc_data sdx75_pinctrl = { + .pins = sdx75_pins, + .npins = ARRAY_SIZE(sdx75_pins), + .functions = sdx75_functions, + .nfunctions = ARRAY_SIZE(sdx75_functions), + .groups = sdx75_groups, + .ngroups = ARRAY_SIZE(sdx75_groups), + .ngpios = 133, + .wakeirq_map = sdx75_pdc_map, + .nwakeirq_map = ARRAY_SIZE(sdx75_pdc_map), +}; + +static const struct of_device_id sdx75_pinctrl_of_match[] = { + { .compatible = "qcom,sdx75-tlmm", .data = &sdx75_pinctrl }, + { } +}; +MODULE_DEVICE_TABLE(of, sdx75_pinctrl_of_match); + +static int sdx75_pinctrl_probe(struct platform_device *pdev) +{ + const struct msm_pinctrl_soc_data *pinctrl_data; + + pinctrl_data = of_device_get_match_data(&pdev->dev); + if (!pinctrl_data) + return -EINVAL; + + return msm_pinctrl_probe(pdev, pinctrl_data); +} + +static struct platform_driver sdx75_pinctrl_driver = { + .driver = { + .name = "sdx75-tlmm", + .of_match_table = sdx75_pinctrl_of_match, + }, + .probe = sdx75_pinctrl_probe, + .remove = msm_pinctrl_remove, +}; + +static int __init sdx75_pinctrl_init(void) +{ + return platform_driver_register(&sdx75_pinctrl_driver); +} +arch_initcall(sdx75_pinctrl_init); + +static void __exit sdx75_pinctrl_exit(void) +{ + platform_driver_unregister(&sdx75_pinctrl_driver); +} +module_exit(sdx75_pinctrl_exit); + +MODULE_DESCRIPTION("QTI sdx75 pinctrl driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/qcom/pinctrl-sm6115.c b/drivers/pinctrl/qcom/pinctrl-sm6115.c index b3a0161ca377..2a06025f4885 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm6115.c +++ b/drivers/pinctrl/qcom/pinctrl-sm6115.c @@ -6,7 +6,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" @@ -22,18 +21,11 @@ enum { WEST }; -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -71,9 +63,9 @@ enum { #define SDC_QDSD_PINGROUP(pg_name, _tile, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -97,9 +89,9 @@ enum { #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -676,74 +668,74 @@ static const char * const ddr_pxi3_groups[] = { "gpio104", "gpio105", }; -static const struct msm_function sm6115_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(atest), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer), - FUNCTION(cri_trng), - FUNCTION(dac_calib), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gpio), - FUNCTION(gp_pdm0), - FUNCTION(gp_pdm1), - FUNCTION(gp_pdm2), - FUNCTION(gsm0_tx), - FUNCTION(gsm1_tx), - FUNCTION(jitter_bist), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync_out_0), - FUNCTION(mdp_vsync_out_1), - FUNCTION(mpm_pwr), - FUNCTION(mss_lte), - FUNCTION(m_voc), - FUNCTION(nav_gpio), - FUNCTION(pa_indicator), - FUNCTION(pbs), - FUNCTION(pbs_out), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_bypassnl), - FUNCTION(pll_reset), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qup0), - FUNCTION(qup1), - FUNCTION(qup2), - FUNCTION(qup3), - FUNCTION(qup4), - FUNCTION(qup5), - FUNCTION(sdc1_tb), - FUNCTION(sdc2_tb), - FUNCTION(sd_write), - FUNCTION(ssbi_wtr1), - FUNCTION(tgu), - FUNCTION(tsense_pwm), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(usb_phy), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), - FUNCTION(wlan1_adc0), - FUNCTION(wlan1_adc1), +static const struct pinfunction sm6115_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(atest), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(dac_calib), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gp_pdm0), + MSM_PIN_FUNCTION(gp_pdm1), + MSM_PIN_FUNCTION(gp_pdm2), + MSM_PIN_FUNCTION(gsm0_tx), + MSM_PIN_FUNCTION(gsm1_tx), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync_out_0), + MSM_PIN_FUNCTION(mdp_vsync_out_1), + MSM_PIN_FUNCTION(mpm_pwr), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(nav_gpio), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pbs), + MSM_PIN_FUNCTION(pbs_out), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qup0), + MSM_PIN_FUNCTION(qup1), + MSM_PIN_FUNCTION(qup2), + MSM_PIN_FUNCTION(qup3), + MSM_PIN_FUNCTION(qup4), + MSM_PIN_FUNCTION(qup5), + MSM_PIN_FUNCTION(sdc1_tb), + MSM_PIN_FUNCTION(sdc2_tb), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(ssbi_wtr1), + MSM_PIN_FUNCTION(tgu), + MSM_PIN_FUNCTION(tsense_pwm), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(wlan1_adc1), }; /* Every pin is maintained as a single group, and missing or non-existing pin diff --git a/drivers/pinctrl/qcom/pinctrl-sm6125.c b/drivers/pinctrl/qcom/pinctrl-sm6125.c index 170d4ffbb919..d5e2b896954c 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm6125.c +++ b/drivers/pinctrl/qcom/pinctrl-sm6125.c @@ -3,7 +3,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" @@ -19,18 +18,11 @@ enum { WEST }; -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -68,9 +60,9 @@ enum { #define SDC_QDSD_PINGROUP(pg_name, _tile, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -94,9 +86,9 @@ enum { #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -949,134 +941,134 @@ static const char * const dmic1_data_groups[] = { "gpio128", }; -static const struct msm_function sm6125_functions[] = { - FUNCTION(qup00), - FUNCTION(gpio), - FUNCTION(qdss), - FUNCTION(qup01), - FUNCTION(qup02), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_bist), - FUNCTION(atest_tsens2), - FUNCTION(vsense_trigger), - FUNCTION(atest_usb1), - FUNCTION(gp_pdm1), - FUNCTION(phase_flag), - FUNCTION(dbg_out), - FUNCTION(qup14), - FUNCTION(atest_usb11), - FUNCTION(ddr_pxi2), - FUNCTION(atest_usb10), - FUNCTION(jitter_bist), - FUNCTION(ddr_pxi3), - FUNCTION(pll_bypassnl), - FUNCTION(pll_bist), - FUNCTION(qup03), - FUNCTION(pll_reset), - FUNCTION(agera_pll), - FUNCTION(qdss_cti), - FUNCTION(qup04), - FUNCTION(wlan2_adc1), - FUNCTION(wlan2_adc0), - FUNCTION(wsa_clk), - FUNCTION(qup13), - FUNCTION(ter_mi2s), - FUNCTION(wsa_data), - FUNCTION(qup10), - FUNCTION(gcc_gp3), - FUNCTION(qup12), - FUNCTION(sd_write), - FUNCTION(qup11), - FUNCTION(cam_mclk), - FUNCTION(atest_tsens), - FUNCTION(cci_i2c), - FUNCTION(cci_timer2), - FUNCTION(cci_timer1), - FUNCTION(gcc_gp2), - FUNCTION(cci_async), - FUNCTION(cci_timer4), - FUNCTION(cci_timer0), - FUNCTION(gcc_gp1), - FUNCTION(cci_timer3), - FUNCTION(wlan1_adc1), - FUNCTION(wlan1_adc0), - FUNCTION(qlink_request), - FUNCTION(qlink_enable), - FUNCTION(pa_indicator), - FUNCTION(nav_pps), - FUNCTION(gps_tx), - FUNCTION(gp_pdm0), - FUNCTION(atest_usb13), - FUNCTION(ddr_pxi1), - FUNCTION(atest_usb12), - FUNCTION(cri_trng0), - FUNCTION(cri_trng), - FUNCTION(cri_trng1), - FUNCTION(gp_pdm2), - FUNCTION(sp_cmu), - FUNCTION(atest_usb2), - FUNCTION(atest_usb23), - FUNCTION(uim2_data), - FUNCTION(uim2_clk), - FUNCTION(uim2_reset), - FUNCTION(atest_usb22), - FUNCTION(uim2_present), - FUNCTION(atest_usb21), - FUNCTION(uim1_data), - FUNCTION(atest_usb20), - FUNCTION(uim1_clk), - FUNCTION(uim1_reset), - FUNCTION(uim1_present), - FUNCTION(mdp_vsync), - FUNCTION(copy_gp), - FUNCTION(tsense_pwm), - FUNCTION(mpm_pwr), - FUNCTION(tgu_ch3), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mdp_vsync4), - FUNCTION(mdp_vsync5), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(atest_char1), - FUNCTION(vfr_1), - FUNCTION(tgu_ch2), - FUNCTION(atest_char0), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(prng_rosc), - FUNCTION(dp_hot), - FUNCTION(debug_hot), - FUNCTION(copy_phase), - FUNCTION(usb_phy), - FUNCTION(atest_char), - FUNCTION(unused1), - FUNCTION(qua_mi2s), - FUNCTION(mss_lte), - FUNCTION(swr_tx), - FUNCTION(aud_sb), - FUNCTION(unused2), - FUNCTION(swr_rx), - FUNCTION(edp_hot), - FUNCTION(audio_ref), - FUNCTION(pri_mi2s), - FUNCTION(pri_mi2s_ws), - FUNCTION(adsp_ext), - FUNCTION(edp_lcd), - FUNCTION(mclk2), - FUNCTION(m_voc), - FUNCTION(mclk1), - FUNCTION(qca_sb), - FUNCTION(qui_mi2s), - FUNCTION(dmic0_clk), - FUNCTION(sec_mi2s), - FUNCTION(dmic0_data), - FUNCTION(dmic1_clk), - FUNCTION(dmic1_data), +static const struct pinfunction sm6125_functions[] = { + MSM_PIN_FUNCTION(qup00), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(qdss), + MSM_PIN_FUNCTION(qup01), + MSM_PIN_FUNCTION(qup02), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(atest_tsens2), + MSM_PIN_FUNCTION(vsense_trigger), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(gp_pdm1), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(atest_usb11), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(atest_usb10), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(qup03), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qup04), + MSM_PIN_FUNCTION(wlan2_adc1), + MSM_PIN_FUNCTION(wlan2_adc0), + MSM_PIN_FUNCTION(wsa_clk), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(ter_mi2s), + MSM_PIN_FUNCTION(wsa_data), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(wlan1_adc1), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(qlink_request), + MSM_PIN_FUNCTION(qlink_enable), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(gps_tx), + MSM_PIN_FUNCTION(gp_pdm0), + MSM_PIN_FUNCTION(atest_usb13), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(atest_usb12), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(gp_pdm2), + MSM_PIN_FUNCTION(sp_cmu), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(atest_usb23), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(atest_usb22), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(atest_usb21), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(atest_usb20), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(copy_gp), + MSM_PIN_FUNCTION(tsense_pwm), + MSM_PIN_FUNCTION(mpm_pwr), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mdp_vsync4), + MSM_PIN_FUNCTION(mdp_vsync5), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(dp_hot), + MSM_PIN_FUNCTION(debug_hot), + MSM_PIN_FUNCTION(copy_phase), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(unused1), + MSM_PIN_FUNCTION(qua_mi2s), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(swr_tx), + MSM_PIN_FUNCTION(aud_sb), + MSM_PIN_FUNCTION(unused2), + MSM_PIN_FUNCTION(swr_rx), + MSM_PIN_FUNCTION(edp_hot), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(pri_mi2s_ws), + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(mclk2), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mclk1), + MSM_PIN_FUNCTION(qca_sb), + MSM_PIN_FUNCTION(qui_mi2s), + MSM_PIN_FUNCTION(dmic0_clk), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(dmic0_data), + MSM_PIN_FUNCTION(dmic1_clk), + MSM_PIN_FUNCTION(dmic1_data), }; /* diff --git a/drivers/pinctrl/qcom/pinctrl-sm6350.c b/drivers/pinctrl/qcom/pinctrl-sm6350.c index a91a86628f2f..f3828c07b134 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm6350.c +++ b/drivers/pinctrl/qcom/pinctrl-sm6350.c @@ -7,23 +7,15 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -60,9 +52,9 @@ #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -85,9 +77,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -1016,141 +1008,141 @@ static const char * const usb_phy_groups[] = { "gpio124", }; -static const struct msm_function sm6350_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(atest_tsens), - FUNCTION(atest_tsens2), - FUNCTION(atest_usb), - FUNCTION(audio_ref), - FUNCTION(btfm_slimbus), - FUNCTION(cam_mclk0), - FUNCTION(cam_mclk1), - FUNCTION(cam_mclk2), - FUNCTION(cam_mclk3), - FUNCTION(cam_mclk4), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cri_trng), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(dp_hot), - FUNCTION(edp_lcd), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gp_pdm0), - FUNCTION(gp_pdm1), - FUNCTION(gp_pdm2), - FUNCTION(gpio), - FUNCTION(gps_tx), - FUNCTION(ibi_i3c), - FUNCTION(jitter_bist), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(lpass_ext), - FUNCTION(m_voc), - FUNCTION(mclk), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mi2s_0), - FUNCTION(mi2s_1), - FUNCTION(mi2s_2), - FUNCTION(mss_lte), - FUNCTION(nav_gpio), - FUNCTION(nav_pps), - FUNCTION(pa_indicator), - FUNCTION(pcie0_clk), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_bypassnl), - FUNCTION(pll_reset), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qdss_gpio0), - FUNCTION(qdss_gpio1), - FUNCTION(qdss_gpio10), - FUNCTION(qdss_gpio11), - FUNCTION(qdss_gpio12), - FUNCTION(qdss_gpio13), - FUNCTION(qdss_gpio14), - FUNCTION(qdss_gpio15), - FUNCTION(qdss_gpio2), - FUNCTION(qdss_gpio3), - FUNCTION(qdss_gpio4), - FUNCTION(qdss_gpio5), - FUNCTION(qdss_gpio6), - FUNCTION(qdss_gpio7), - FUNCTION(qdss_gpio8), - FUNCTION(qdss_gpio9), - FUNCTION(qlink0_enable), - FUNCTION(qlink0_request), - FUNCTION(qlink0_wmss), - FUNCTION(qlink1_enable), - FUNCTION(qlink1_request), - FUNCTION(qlink1_wmss), - FUNCTION(qup00), - FUNCTION(qup01), - FUNCTION(qup02), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13_f1), - FUNCTION(qup13_f2), - FUNCTION(qup14), - FUNCTION(rffe0_clk), - FUNCTION(rffe0_data), - FUNCTION(rffe1_clk), - FUNCTION(rffe1_data), - FUNCTION(rffe2_clk), - FUNCTION(rffe2_data), - FUNCTION(rffe3_clk), - FUNCTION(rffe3_data), - FUNCTION(rffe4_clk), - FUNCTION(rffe4_data), - FUNCTION(sd_write), - FUNCTION(sdc1_tb), - FUNCTION(sdc2_tb), - FUNCTION(sp_cmu), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(usb_phy), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), - FUNCTION(wlan1_adc0), - FUNCTION(wlan1_adc1), - FUNCTION(wlan2_adc0), - FUNCTION(wlan2_adc1), +static const struct pinfunction sm6350_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_tsens2), + MSM_PIN_FUNCTION(atest_usb), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(btfm_slimbus), + MSM_PIN_FUNCTION(cam_mclk0), + MSM_PIN_FUNCTION(cam_mclk1), + MSM_PIN_FUNCTION(cam_mclk2), + MSM_PIN_FUNCTION(cam_mclk3), + MSM_PIN_FUNCTION(cam_mclk4), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(dp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gp_pdm0), + MSM_PIN_FUNCTION(gp_pdm1), + MSM_PIN_FUNCTION(gp_pdm2), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gps_tx), + MSM_PIN_FUNCTION(ibi_i3c), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(lpass_ext), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mclk), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mi2s_0), + MSM_PIN_FUNCTION(mi2s_1), + MSM_PIN_FUNCTION(mi2s_2), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_gpio), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pcie0_clk), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qdss_gpio0), + MSM_PIN_FUNCTION(qdss_gpio1), + MSM_PIN_FUNCTION(qdss_gpio10), + MSM_PIN_FUNCTION(qdss_gpio11), + MSM_PIN_FUNCTION(qdss_gpio12), + MSM_PIN_FUNCTION(qdss_gpio13), + MSM_PIN_FUNCTION(qdss_gpio14), + MSM_PIN_FUNCTION(qdss_gpio15), + MSM_PIN_FUNCTION(qdss_gpio2), + MSM_PIN_FUNCTION(qdss_gpio3), + MSM_PIN_FUNCTION(qdss_gpio4), + MSM_PIN_FUNCTION(qdss_gpio5), + MSM_PIN_FUNCTION(qdss_gpio6), + MSM_PIN_FUNCTION(qdss_gpio7), + MSM_PIN_FUNCTION(qdss_gpio8), + MSM_PIN_FUNCTION(qdss_gpio9), + MSM_PIN_FUNCTION(qlink0_enable), + MSM_PIN_FUNCTION(qlink0_request), + MSM_PIN_FUNCTION(qlink0_wmss), + MSM_PIN_FUNCTION(qlink1_enable), + MSM_PIN_FUNCTION(qlink1_request), + MSM_PIN_FUNCTION(qlink1_wmss), + MSM_PIN_FUNCTION(qup00), + MSM_PIN_FUNCTION(qup01), + MSM_PIN_FUNCTION(qup02), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13_f1), + MSM_PIN_FUNCTION(qup13_f2), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(rffe0_clk), + MSM_PIN_FUNCTION(rffe0_data), + MSM_PIN_FUNCTION(rffe1_clk), + MSM_PIN_FUNCTION(rffe1_data), + MSM_PIN_FUNCTION(rffe2_clk), + MSM_PIN_FUNCTION(rffe2_data), + MSM_PIN_FUNCTION(rffe3_clk), + MSM_PIN_FUNCTION(rffe3_data), + MSM_PIN_FUNCTION(rffe4_clk), + MSM_PIN_FUNCTION(rffe4_data), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdc1_tb), + MSM_PIN_FUNCTION(sdc2_tb), + MSM_PIN_FUNCTION(sp_cmu), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(wlan1_adc1), + MSM_PIN_FUNCTION(wlan2_adc0), + MSM_PIN_FUNCTION(wlan2_adc1), }; /* diff --git a/drivers/pinctrl/qcom/pinctrl-sm6375.c b/drivers/pinctrl/qcom/pinctrl-sm6375.c index 1138e683e6f4..c82c8516932e 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm6375.c +++ b/drivers/pinctrl/qcom/pinctrl-sm6375.c @@ -7,24 +7,16 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_BASE 0x100000 #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -63,9 +55,9 @@ #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -88,9 +80,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -1135,172 +1127,172 @@ static const char * const wlan2_adc1_groups[] = { "gpio93", }; -static const struct msm_function sm6375_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(atest_tsens), - FUNCTION(atest_tsens2), - FUNCTION(atest_usb1), - FUNCTION(atest_usb10), - FUNCTION(atest_usb11), - FUNCTION(atest_usb12), - FUNCTION(atest_usb13), - FUNCTION(atest_usb2), - FUNCTION(atest_usb20), - FUNCTION(atest_usb21), - FUNCTION(atest_usb22), - FUNCTION(atest_usb23), - FUNCTION(audio_ref), - FUNCTION(btfm_slimbus), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cri_trng), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(dp_hot), - FUNCTION(edp_lcd), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gp_pdm0), - FUNCTION(gp_pdm1), - FUNCTION(gp_pdm2), - FUNCTION(gpio), - FUNCTION(gps_tx), - FUNCTION(ibi_i3c), - FUNCTION(jitter_bist), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(lpass_ext), - FUNCTION(m_voc), - FUNCTION(mclk), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mi2s_0), - FUNCTION(mi2s_1), - FUNCTION(mi2s_2), - FUNCTION(mss_lte), - FUNCTION(nav_gpio), - FUNCTION(nav_pps), - FUNCTION(pa_indicator), - FUNCTION(phase_flag0), - FUNCTION(phase_flag1), - FUNCTION(phase_flag10), - FUNCTION(phase_flag11), - FUNCTION(phase_flag12), - FUNCTION(phase_flag13), - FUNCTION(phase_flag14), - FUNCTION(phase_flag15), - FUNCTION(phase_flag16), - FUNCTION(phase_flag17), - FUNCTION(phase_flag18), - FUNCTION(phase_flag19), - FUNCTION(phase_flag2), - FUNCTION(phase_flag20), - FUNCTION(phase_flag21), - FUNCTION(phase_flag22), - FUNCTION(phase_flag23), - FUNCTION(phase_flag24), - FUNCTION(phase_flag25), - FUNCTION(phase_flag26), - FUNCTION(phase_flag27), - FUNCTION(phase_flag28), - FUNCTION(phase_flag29), - FUNCTION(phase_flag3), - FUNCTION(phase_flag30), - FUNCTION(phase_flag31), - FUNCTION(phase_flag4), - FUNCTION(phase_flag5), - FUNCTION(phase_flag6), - FUNCTION(phase_flag7), - FUNCTION(phase_flag8), - FUNCTION(phase_flag9), - FUNCTION(pll_bist), - FUNCTION(pll_bypassnl), - FUNCTION(pll_clk), - FUNCTION(pll_reset), - FUNCTION(prng_rosc0), - FUNCTION(prng_rosc1), - FUNCTION(prng_rosc2), - FUNCTION(prng_rosc3), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qdss_gpio0), - FUNCTION(qdss_gpio1), - FUNCTION(qdss_gpio10), - FUNCTION(qdss_gpio11), - FUNCTION(qdss_gpio12), - FUNCTION(qdss_gpio13), - FUNCTION(qdss_gpio14), - FUNCTION(qdss_gpio15), - FUNCTION(qdss_gpio2), - FUNCTION(qdss_gpio3), - FUNCTION(qdss_gpio4), - FUNCTION(qdss_gpio5), - FUNCTION(qdss_gpio6), - FUNCTION(qdss_gpio7), - FUNCTION(qdss_gpio8), - FUNCTION(qdss_gpio9), - FUNCTION(qlink0_enable), - FUNCTION(qlink0_request), - FUNCTION(qlink0_wmss), - FUNCTION(qlink1_enable), - FUNCTION(qlink1_request), - FUNCTION(qlink1_wmss), - FUNCTION(qup00), - FUNCTION(qup01), - FUNCTION(qup02), - FUNCTION(qup10), - FUNCTION(qup11_f1), - FUNCTION(qup11_f2), - FUNCTION(qup12), - FUNCTION(qup13_f1), - FUNCTION(qup13_f2), - FUNCTION(qup14), - FUNCTION(sd_write), - FUNCTION(sdc1_tb), - FUNCTION(sdc2_tb), - FUNCTION(sp_cmu), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(usb2phy_ac), - FUNCTION(usb_phy), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), - FUNCTION(wlan1_adc0), - FUNCTION(wlan1_adc1), - FUNCTION(wlan2_adc0), - FUNCTION(wlan2_adc1), +static const struct pinfunction sm6375_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_tsens2), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(atest_usb10), + MSM_PIN_FUNCTION(atest_usb11), + MSM_PIN_FUNCTION(atest_usb12), + MSM_PIN_FUNCTION(atest_usb13), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(atest_usb20), + MSM_PIN_FUNCTION(atest_usb21), + MSM_PIN_FUNCTION(atest_usb22), + MSM_PIN_FUNCTION(atest_usb23), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(btfm_slimbus), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(dp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gp_pdm0), + MSM_PIN_FUNCTION(gp_pdm1), + MSM_PIN_FUNCTION(gp_pdm2), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gps_tx), + MSM_PIN_FUNCTION(ibi_i3c), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(lpass_ext), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mclk), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mi2s_0), + MSM_PIN_FUNCTION(mi2s_1), + MSM_PIN_FUNCTION(mi2s_2), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_gpio), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(phase_flag0), + MSM_PIN_FUNCTION(phase_flag1), + MSM_PIN_FUNCTION(phase_flag10), + MSM_PIN_FUNCTION(phase_flag11), + MSM_PIN_FUNCTION(phase_flag12), + MSM_PIN_FUNCTION(phase_flag13), + MSM_PIN_FUNCTION(phase_flag14), + MSM_PIN_FUNCTION(phase_flag15), + MSM_PIN_FUNCTION(phase_flag16), + MSM_PIN_FUNCTION(phase_flag17), + MSM_PIN_FUNCTION(phase_flag18), + MSM_PIN_FUNCTION(phase_flag19), + MSM_PIN_FUNCTION(phase_flag2), + MSM_PIN_FUNCTION(phase_flag20), + MSM_PIN_FUNCTION(phase_flag21), + MSM_PIN_FUNCTION(phase_flag22), + MSM_PIN_FUNCTION(phase_flag23), + MSM_PIN_FUNCTION(phase_flag24), + MSM_PIN_FUNCTION(phase_flag25), + MSM_PIN_FUNCTION(phase_flag26), + MSM_PIN_FUNCTION(phase_flag27), + MSM_PIN_FUNCTION(phase_flag28), + MSM_PIN_FUNCTION(phase_flag29), + MSM_PIN_FUNCTION(phase_flag3), + MSM_PIN_FUNCTION(phase_flag30), + MSM_PIN_FUNCTION(phase_flag31), + MSM_PIN_FUNCTION(phase_flag4), + MSM_PIN_FUNCTION(phase_flag5), + MSM_PIN_FUNCTION(phase_flag6), + MSM_PIN_FUNCTION(phase_flag7), + MSM_PIN_FUNCTION(phase_flag8), + MSM_PIN_FUNCTION(phase_flag9), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_clk), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(prng_rosc0), + MSM_PIN_FUNCTION(prng_rosc1), + MSM_PIN_FUNCTION(prng_rosc2), + MSM_PIN_FUNCTION(prng_rosc3), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qdss_gpio0), + MSM_PIN_FUNCTION(qdss_gpio1), + MSM_PIN_FUNCTION(qdss_gpio10), + MSM_PIN_FUNCTION(qdss_gpio11), + MSM_PIN_FUNCTION(qdss_gpio12), + MSM_PIN_FUNCTION(qdss_gpio13), + MSM_PIN_FUNCTION(qdss_gpio14), + MSM_PIN_FUNCTION(qdss_gpio15), + MSM_PIN_FUNCTION(qdss_gpio2), + MSM_PIN_FUNCTION(qdss_gpio3), + MSM_PIN_FUNCTION(qdss_gpio4), + MSM_PIN_FUNCTION(qdss_gpio5), + MSM_PIN_FUNCTION(qdss_gpio6), + MSM_PIN_FUNCTION(qdss_gpio7), + MSM_PIN_FUNCTION(qdss_gpio8), + MSM_PIN_FUNCTION(qdss_gpio9), + MSM_PIN_FUNCTION(qlink0_enable), + MSM_PIN_FUNCTION(qlink0_request), + MSM_PIN_FUNCTION(qlink0_wmss), + MSM_PIN_FUNCTION(qlink1_enable), + MSM_PIN_FUNCTION(qlink1_request), + MSM_PIN_FUNCTION(qlink1_wmss), + MSM_PIN_FUNCTION(qup00), + MSM_PIN_FUNCTION(qup01), + MSM_PIN_FUNCTION(qup02), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11_f1), + MSM_PIN_FUNCTION(qup11_f2), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13_f1), + MSM_PIN_FUNCTION(qup13_f2), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdc1_tb), + MSM_PIN_FUNCTION(sdc2_tb), + MSM_PIN_FUNCTION(sp_cmu), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(wlan1_adc1), + MSM_PIN_FUNCTION(wlan2_adc0), + MSM_PIN_FUNCTION(wlan2_adc1), }; /* diff --git a/drivers/pinctrl/qcom/pinctrl-sm7150.c b/drivers/pinctrl/qcom/pinctrl-sm7150.c index 2a87e3f144fd..33657cf98fb9 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm7150.c +++ b/drivers/pinctrl/qcom/pinctrl-sm7150.c @@ -23,20 +23,13 @@ enum { WEST }; -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -74,9 +67,9 @@ enum { #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -100,9 +93,9 @@ enum { #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -966,117 +959,117 @@ static const char * const wsa_data_groups[] = { "gpio50", }; -static const struct msm_function sm7150_functions[] = { - FUNCTION(gpio), - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(aoss_cti), - FUNCTION(atest_char), - FUNCTION(atest_tsens), - FUNCTION(atest_tsens2), - FUNCTION(atest_usb1), - FUNCTION(atest_usb2), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(edp_hot), - FUNCTION(edp_lcd), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gp_pdm0), - FUNCTION(gp_pdm1), - FUNCTION(gp_pdm2), - FUNCTION(gps_tx), - FUNCTION(jitter_bist), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(m_voc), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mss_lte), - FUNCTION(nav_pps_in), - FUNCTION(nav_pps_out), - FUNCTION(pa_indicator), - FUNCTION(pci_e), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_bypassnl), - FUNCTION(pll_reset), - FUNCTION(pri_mi2s), - FUNCTION(pri_mi2s_ws), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss), - FUNCTION(qlink_enable), - FUNCTION(qlink_request), - FUNCTION(qua_mi2s), - FUNCTION(qup00), - FUNCTION(qup01), - FUNCTION(qup02), - FUNCTION(qup03), - FUNCTION(qup04), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(sd_write), - FUNCTION(sdc40), - FUNCTION(sdc41), - FUNCTION(sdc42), - FUNCTION(sdc43), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(sec_mi2s), - FUNCTION(ter_mi2s), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tsif1_clk), - FUNCTION(tsif1_data), - FUNCTION(tsif1_en), - FUNCTION(tsif1_error), - FUNCTION(tsif1_sync), - FUNCTION(tsif2_clk), - FUNCTION(tsif2_data), - FUNCTION(tsif2_en), - FUNCTION(tsif2_error), - FUNCTION(tsif2_sync), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(uim_batt), - FUNCTION(usb_phy), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), - FUNCTION(wlan1_adc0), - FUNCTION(wlan1_adc1), - FUNCTION(wlan2_adc0), - FUNCTION(wlan2_adc1), - FUNCTION(wsa_clk), - FUNCTION(wsa_data), +static const struct pinfunction sm7150_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(aoss_cti), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_tsens2), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(edp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gp_pdm0), + MSM_PIN_FUNCTION(gp_pdm1), + MSM_PIN_FUNCTION(gp_pdm2), + MSM_PIN_FUNCTION(gps_tx), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_pps_in), + MSM_PIN_FUNCTION(nav_pps_out), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pci_e), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(pri_mi2s_ws), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss), + MSM_PIN_FUNCTION(qlink_enable), + MSM_PIN_FUNCTION(qlink_request), + MSM_PIN_FUNCTION(qua_mi2s), + MSM_PIN_FUNCTION(qup00), + MSM_PIN_FUNCTION(qup01), + MSM_PIN_FUNCTION(qup02), + MSM_PIN_FUNCTION(qup03), + MSM_PIN_FUNCTION(qup04), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdc40), + MSM_PIN_FUNCTION(sdc41), + MSM_PIN_FUNCTION(sdc42), + MSM_PIN_FUNCTION(sdc43), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(ter_mi2s), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tsif1_clk), + MSM_PIN_FUNCTION(tsif1_data), + MSM_PIN_FUNCTION(tsif1_en), + MSM_PIN_FUNCTION(tsif1_error), + MSM_PIN_FUNCTION(tsif1_sync), + MSM_PIN_FUNCTION(tsif2_clk), + MSM_PIN_FUNCTION(tsif2_data), + MSM_PIN_FUNCTION(tsif2_en), + MSM_PIN_FUNCTION(tsif2_error), + MSM_PIN_FUNCTION(tsif2_sync), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(wlan1_adc1), + MSM_PIN_FUNCTION(wlan2_adc0), + MSM_PIN_FUNCTION(wlan2_adc1), + MSM_PIN_FUNCTION(wsa_clk), + MSM_PIN_FUNCTION(wsa_data), }; /* diff --git a/drivers/pinctrl/qcom/pinctrl-sm8150.c b/drivers/pinctrl/qcom/pinctrl-sm8150.c index 1cc622694553..01aea9c70b7a 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8150.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8150.c @@ -4,7 +4,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" @@ -22,18 +21,11 @@ enum { WEST }; -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -71,9 +63,9 @@ enum { #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -97,9 +89,9 @@ enum { #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -1180,136 +1172,136 @@ static const char * const mss_lte_groups[] = { "gpio69", "gpio70", }; -static const struct msm_function sm8150_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(aoss_cti), - FUNCTION(ddr_pxi2), - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(audio_ref), - FUNCTION(atest_usb1), - FUNCTION(atest_usb2), - FUNCTION(atest_usb10), - FUNCTION(atest_usb11), - FUNCTION(atest_usb12), - FUNCTION(atest_usb13), - FUNCTION(atest_usb20), - FUNCTION(atest_usb21), - FUNCTION(atest_usb22), - FUNCTION(atest_usb23), - FUNCTION(btfm_slimbus), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi3), - FUNCTION(edp_hot), - FUNCTION(edp_lcd), - FUNCTION(emac_phy), - FUNCTION(emac_pps), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gpio), - FUNCTION(hs1_mi2s), - FUNCTION(hs2_mi2s), - FUNCTION(hs3_mi2s), - FUNCTION(jitter_bist), - FUNCTION(lpass_slimbus), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mss_lte), - FUNCTION(m_voc), - FUNCTION(nav_pps), - FUNCTION(pa_indicator), - FUNCTION(pci_e0), - FUNCTION(phase_flag), - FUNCTION(pll_bypassnl), - FUNCTION(pll_bist), - FUNCTION(pci_e1), - FUNCTION(pll_reset), - FUNCTION(pri_mi2s), - FUNCTION(pri_mi2s_ws), - FUNCTION(prng_rosc), - FUNCTION(qdss), - FUNCTION(qdss_cti), - FUNCTION(qlink_request), - FUNCTION(qlink_enable), - FUNCTION(qspi0), - FUNCTION(qspi1), - FUNCTION(qspi2), - FUNCTION(qspi3), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qua_mi2s), - FUNCTION(qup0), - FUNCTION(qup1), - FUNCTION(qup2), - FUNCTION(qup3), - FUNCTION(qup4), - FUNCTION(qup5), - FUNCTION(qup6), - FUNCTION(qup7), - FUNCTION(qup8), - FUNCTION(qup9), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(qup16), - FUNCTION(qup17), - FUNCTION(qup18), - FUNCTION(qup19), - FUNCTION(qup_l4), - FUNCTION(qup_l5), - FUNCTION(qup_l6), - FUNCTION(rgmii), - FUNCTION(sdc4), - FUNCTION(sd_write), - FUNCTION(sec_mi2s), - FUNCTION(spkr_i2s), - FUNCTION(sp_cmu), - FUNCTION(ter_mi2s), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(tsif1), - FUNCTION(tsif2), - FUNCTION(uim1), - FUNCTION(uim2), - FUNCTION(uim_batt), - FUNCTION(usb2phy_ac), - FUNCTION(usb_phy), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), - FUNCTION(wlan1_adc0), - FUNCTION(wlan1_adc1), - FUNCTION(wlan2_adc0), - FUNCTION(wlan2_adc1), - FUNCTION(wmss_reset), +static const struct pinfunction sm8150_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(aoss_cti), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(atest_usb10), + MSM_PIN_FUNCTION(atest_usb11), + MSM_PIN_FUNCTION(atest_usb12), + MSM_PIN_FUNCTION(atest_usb13), + MSM_PIN_FUNCTION(atest_usb20), + MSM_PIN_FUNCTION(atest_usb21), + MSM_PIN_FUNCTION(atest_usb22), + MSM_PIN_FUNCTION(atest_usb23), + MSM_PIN_FUNCTION(btfm_slimbus), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(edp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(emac_phy), + MSM_PIN_FUNCTION(emac_pps), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(hs1_mi2s), + MSM_PIN_FUNCTION(hs2_mi2s), + MSM_PIN_FUNCTION(hs3_mi2s), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pci_e0), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pci_e1), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(pri_mi2s_ws), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qlink_request), + MSM_PIN_FUNCTION(qlink_enable), + MSM_PIN_FUNCTION(qspi0), + MSM_PIN_FUNCTION(qspi1), + MSM_PIN_FUNCTION(qspi2), + MSM_PIN_FUNCTION(qspi3), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qua_mi2s), + MSM_PIN_FUNCTION(qup0), + MSM_PIN_FUNCTION(qup1), + MSM_PIN_FUNCTION(qup2), + MSM_PIN_FUNCTION(qup3), + MSM_PIN_FUNCTION(qup4), + MSM_PIN_FUNCTION(qup5), + MSM_PIN_FUNCTION(qup6), + MSM_PIN_FUNCTION(qup7), + MSM_PIN_FUNCTION(qup8), + MSM_PIN_FUNCTION(qup9), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(qup16), + MSM_PIN_FUNCTION(qup17), + MSM_PIN_FUNCTION(qup18), + MSM_PIN_FUNCTION(qup19), + MSM_PIN_FUNCTION(qup_l4), + MSM_PIN_FUNCTION(qup_l5), + MSM_PIN_FUNCTION(qup_l6), + MSM_PIN_FUNCTION(rgmii), + MSM_PIN_FUNCTION(sdc4), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(spkr_i2s), + MSM_PIN_FUNCTION(sp_cmu), + MSM_PIN_FUNCTION(ter_mi2s), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(tsif1), + MSM_PIN_FUNCTION(tsif2), + MSM_PIN_FUNCTION(uim1), + MSM_PIN_FUNCTION(uim2), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(wlan1_adc1), + MSM_PIN_FUNCTION(wlan2_adc0), + MSM_PIN_FUNCTION(wlan2_adc1), + MSM_PIN_FUNCTION(wmss_reset), }; /* diff --git a/drivers/pinctrl/qcom/pinctrl-sm8250.c b/drivers/pinctrl/qcom/pinctrl-sm8250.c index 3bd7f9fedcc3..e9961a49ff98 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8250.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8250.c @@ -6,7 +6,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" @@ -22,19 +21,12 @@ enum { NORTH, }; -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -72,9 +64,9 @@ enum { #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -98,9 +90,9 @@ enum { #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -1003,122 +995,122 @@ static const char * const sdc42_groups[] = { "gpio74", }; -static const struct msm_function sm8250_functions[] = { - FUNCTION(aoss_cti), - FUNCTION(atest), - FUNCTION(audio_ref), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(dp_hot), - FUNCTION(dp_lcd), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gpio), - FUNCTION(ibi_i3c), - FUNCTION(jitter_bist), - FUNCTION(lpass_slimbus), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mi2s0_data0), - FUNCTION(mi2s0_data1), - FUNCTION(mi2s0_sck), - FUNCTION(mi2s0_ws), - FUNCTION(mi2s1_data0), - FUNCTION(mi2s1_data1), - FUNCTION(mi2s1_sck), - FUNCTION(mi2s1_ws), - FUNCTION(mi2s2_data0), - FUNCTION(mi2s2_data1), - FUNCTION(mi2s2_sck), - FUNCTION(mi2s2_ws), - FUNCTION(pci_e0), - FUNCTION(pci_e1), - FUNCTION(pci_e2), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_bypassnl), - FUNCTION(pll_clk), - FUNCTION(pll_reset), - FUNCTION(pri_mi2s), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qspi0), - FUNCTION(qspi1), - FUNCTION(qspi2), - FUNCTION(qspi3), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qup0), - FUNCTION(qup1), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(qup16), - FUNCTION(qup17), - FUNCTION(qup18), - FUNCTION(qup19), - FUNCTION(qup2), - FUNCTION(qup3), - FUNCTION(qup4), - FUNCTION(qup5), - FUNCTION(qup6), - FUNCTION(qup7), - FUNCTION(qup8), - FUNCTION(qup9), - FUNCTION(qup_l4), - FUNCTION(qup_l5), - FUNCTION(qup_l6), - FUNCTION(sd_write), - FUNCTION(sdc40), - FUNCTION(sdc41), - FUNCTION(sdc42), - FUNCTION(sdc43), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(sec_mi2s), - FUNCTION(sp_cmu), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(tsif0_clk), - FUNCTION(tsif0_data), - FUNCTION(tsif0_en), - FUNCTION(tsif0_error), - FUNCTION(tsif0_sync), - FUNCTION(tsif1_clk), - FUNCTION(tsif1_data), - FUNCTION(tsif1_en), - FUNCTION(tsif1_error), - FUNCTION(tsif1_sync), - FUNCTION(usb2phy_ac), - FUNCTION(usb_phy), - FUNCTION(vsense_trigger), +static const struct pinfunction sm8250_functions[] = { + MSM_PIN_FUNCTION(aoss_cti), + MSM_PIN_FUNCTION(atest), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(dp_hot), + MSM_PIN_FUNCTION(dp_lcd), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(ibi_i3c), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mi2s0_data0), + MSM_PIN_FUNCTION(mi2s0_data1), + MSM_PIN_FUNCTION(mi2s0_sck), + MSM_PIN_FUNCTION(mi2s0_ws), + MSM_PIN_FUNCTION(mi2s1_data0), + MSM_PIN_FUNCTION(mi2s1_data1), + MSM_PIN_FUNCTION(mi2s1_sck), + MSM_PIN_FUNCTION(mi2s1_ws), + MSM_PIN_FUNCTION(mi2s2_data0), + MSM_PIN_FUNCTION(mi2s2_data1), + MSM_PIN_FUNCTION(mi2s2_sck), + MSM_PIN_FUNCTION(mi2s2_ws), + MSM_PIN_FUNCTION(pci_e0), + MSM_PIN_FUNCTION(pci_e1), + MSM_PIN_FUNCTION(pci_e2), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_clk), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qspi0), + MSM_PIN_FUNCTION(qspi1), + MSM_PIN_FUNCTION(qspi2), + MSM_PIN_FUNCTION(qspi3), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qup0), + MSM_PIN_FUNCTION(qup1), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(qup16), + MSM_PIN_FUNCTION(qup17), + MSM_PIN_FUNCTION(qup18), + MSM_PIN_FUNCTION(qup19), + MSM_PIN_FUNCTION(qup2), + MSM_PIN_FUNCTION(qup3), + MSM_PIN_FUNCTION(qup4), + MSM_PIN_FUNCTION(qup5), + MSM_PIN_FUNCTION(qup6), + MSM_PIN_FUNCTION(qup7), + MSM_PIN_FUNCTION(qup8), + MSM_PIN_FUNCTION(qup9), + MSM_PIN_FUNCTION(qup_l4), + MSM_PIN_FUNCTION(qup_l5), + MSM_PIN_FUNCTION(qup_l6), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdc40), + MSM_PIN_FUNCTION(sdc41), + MSM_PIN_FUNCTION(sdc42), + MSM_PIN_FUNCTION(sdc43), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(sp_cmu), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(tsif0_clk), + MSM_PIN_FUNCTION(tsif0_data), + MSM_PIN_FUNCTION(tsif0_en), + MSM_PIN_FUNCTION(tsif0_error), + MSM_PIN_FUNCTION(tsif0_sync), + MSM_PIN_FUNCTION(tsif1_clk), + MSM_PIN_FUNCTION(tsif1_data), + MSM_PIN_FUNCTION(tsif1_en), + MSM_PIN_FUNCTION(tsif1_error), + MSM_PIN_FUNCTION(tsif1_sync), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vsense_trigger), }; /* Every pin is maintained as a single group, and missing or non-existing pin diff --git a/drivers/pinctrl/qcom/pinctrl-sm8350.c b/drivers/pinctrl/qcom/pinctrl-sm8350.c index 1c042d39380c..9c69458bd910 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8350.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8350.c @@ -7,24 +7,16 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -61,9 +53,9 @@ #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -86,9 +78,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -1250,142 +1242,142 @@ static const char * const vsense_trigger_groups[] = { "gpio78", }; -static const struct msm_function sm8350_functions[] = { - FUNCTION(atest_char), - FUNCTION(atest_usb), - FUNCTION(audio_ref), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer), - FUNCTION(cmu_rng), - FUNCTION(coex_uart1), - FUNCTION(coex_uart2), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(dp_hot), - FUNCTION(dp_lcd), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gpio), - FUNCTION(ibi_i3c), - FUNCTION(jitter_bist), - FUNCTION(lpass_slimbus), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mi2s0_data0), - FUNCTION(mi2s0_data1), - FUNCTION(mi2s0_sck), - FUNCTION(mi2s0_ws), - FUNCTION(mi2s1_data0), - FUNCTION(mi2s1_data1), - FUNCTION(mi2s1_sck), - FUNCTION(mi2s1_ws), - FUNCTION(mi2s2_data0), - FUNCTION(mi2s2_data1), - FUNCTION(mi2s2_sck), - FUNCTION(mi2s2_ws), - FUNCTION(mss_grfc0), - FUNCTION(mss_grfc1), - FUNCTION(mss_grfc10), - FUNCTION(mss_grfc11), - FUNCTION(mss_grfc12), - FUNCTION(mss_grfc2), - FUNCTION(mss_grfc3), - FUNCTION(mss_grfc4), - FUNCTION(mss_grfc5), - FUNCTION(mss_grfc6), - FUNCTION(mss_grfc7), - FUNCTION(mss_grfc8), - FUNCTION(mss_grfc9), - FUNCTION(nav_gpio), - FUNCTION(pa_indicator), - FUNCTION(pcie0_clkreqn), - FUNCTION(pcie1_clkreqn), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_clk), - FUNCTION(pri_mi2s), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qlink0_enable), - FUNCTION(qlink0_request), - FUNCTION(qlink0_wmss), - FUNCTION(qlink1_enable), - FUNCTION(qlink1_request), - FUNCTION(qlink1_wmss), - FUNCTION(qlink2_enable), - FUNCTION(qlink2_request), - FUNCTION(qlink2_wmss), - FUNCTION(qspi0), - FUNCTION(qspi1), - FUNCTION(qspi2), - FUNCTION(qspi3), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qup0), - FUNCTION(qup1), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(qup16), - FUNCTION(qup17), - FUNCTION(qup18), - FUNCTION(qup19), - FUNCTION(qup2), - FUNCTION(qup3), - FUNCTION(qup4), - FUNCTION(qup5), - FUNCTION(qup6), - FUNCTION(qup7), - FUNCTION(qup8), - FUNCTION(qup9), - FUNCTION(qup_l4), - FUNCTION(qup_l5), - FUNCTION(qup_l6), - FUNCTION(sd_write), - FUNCTION(sdc40), - FUNCTION(sdc41), - FUNCTION(sdc42), - FUNCTION(sdc43), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(sec_mi2s), - FUNCTION(tb_trig), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(uim0_clk), - FUNCTION(uim0_data), - FUNCTION(uim0_present), - FUNCTION(uim0_reset), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(usb2phy_ac), - FUNCTION(usb_phy), - FUNCTION(vfr_0), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), +static const struct pinfunction sm8350_functions[] = { + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_usb), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer), + MSM_PIN_FUNCTION(cmu_rng), + MSM_PIN_FUNCTION(coex_uart1), + MSM_PIN_FUNCTION(coex_uart2), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(dp_hot), + MSM_PIN_FUNCTION(dp_lcd), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(ibi_i3c), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mi2s0_data0), + MSM_PIN_FUNCTION(mi2s0_data1), + MSM_PIN_FUNCTION(mi2s0_sck), + MSM_PIN_FUNCTION(mi2s0_ws), + MSM_PIN_FUNCTION(mi2s1_data0), + MSM_PIN_FUNCTION(mi2s1_data1), + MSM_PIN_FUNCTION(mi2s1_sck), + MSM_PIN_FUNCTION(mi2s1_ws), + MSM_PIN_FUNCTION(mi2s2_data0), + MSM_PIN_FUNCTION(mi2s2_data1), + MSM_PIN_FUNCTION(mi2s2_sck), + MSM_PIN_FUNCTION(mi2s2_ws), + MSM_PIN_FUNCTION(mss_grfc0), + MSM_PIN_FUNCTION(mss_grfc1), + MSM_PIN_FUNCTION(mss_grfc10), + MSM_PIN_FUNCTION(mss_grfc11), + MSM_PIN_FUNCTION(mss_grfc12), + MSM_PIN_FUNCTION(mss_grfc2), + MSM_PIN_FUNCTION(mss_grfc3), + MSM_PIN_FUNCTION(mss_grfc4), + MSM_PIN_FUNCTION(mss_grfc5), + MSM_PIN_FUNCTION(mss_grfc6), + MSM_PIN_FUNCTION(mss_grfc7), + MSM_PIN_FUNCTION(mss_grfc8), + MSM_PIN_FUNCTION(mss_grfc9), + MSM_PIN_FUNCTION(nav_gpio), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pcie0_clkreqn), + MSM_PIN_FUNCTION(pcie1_clkreqn), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_clk), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qlink0_enable), + MSM_PIN_FUNCTION(qlink0_request), + MSM_PIN_FUNCTION(qlink0_wmss), + MSM_PIN_FUNCTION(qlink1_enable), + MSM_PIN_FUNCTION(qlink1_request), + MSM_PIN_FUNCTION(qlink1_wmss), + MSM_PIN_FUNCTION(qlink2_enable), + MSM_PIN_FUNCTION(qlink2_request), + MSM_PIN_FUNCTION(qlink2_wmss), + MSM_PIN_FUNCTION(qspi0), + MSM_PIN_FUNCTION(qspi1), + MSM_PIN_FUNCTION(qspi2), + MSM_PIN_FUNCTION(qspi3), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qup0), + MSM_PIN_FUNCTION(qup1), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(qup16), + MSM_PIN_FUNCTION(qup17), + MSM_PIN_FUNCTION(qup18), + MSM_PIN_FUNCTION(qup19), + MSM_PIN_FUNCTION(qup2), + MSM_PIN_FUNCTION(qup3), + MSM_PIN_FUNCTION(qup4), + MSM_PIN_FUNCTION(qup5), + MSM_PIN_FUNCTION(qup6), + MSM_PIN_FUNCTION(qup7), + MSM_PIN_FUNCTION(qup8), + MSM_PIN_FUNCTION(qup9), + MSM_PIN_FUNCTION(qup_l4), + MSM_PIN_FUNCTION(qup_l5), + MSM_PIN_FUNCTION(qup_l6), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdc40), + MSM_PIN_FUNCTION(sdc41), + MSM_PIN_FUNCTION(sdc42), + MSM_PIN_FUNCTION(sdc43), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(tb_trig), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(uim0_clk), + MSM_PIN_FUNCTION(uim0_data), + MSM_PIN_FUNCTION(uim0_present), + MSM_PIN_FUNCTION(uim0_reset), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_0), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), }; /* Every pin is maintained as a single group, and missing or non-existing pin diff --git a/drivers/pinctrl/qcom/pinctrl-sm8450.c b/drivers/pinctrl/qcom/pinctrl-sm8450.c index 3110d7bf5698..d11bb1ee9e3d 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8450.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8450.c @@ -7,24 +7,16 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -63,9 +55,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -88,9 +80,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -1276,143 +1268,143 @@ static const char * const vsense_trigger_groups[] = { "gpio18", }; -static const struct msm_function sm8450_functions[] = { - FUNCTION(gpio), - FUNCTION(aon_cam), - FUNCTION(atest_char), - FUNCTION(atest_usb), - FUNCTION(audio_ref), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer), - FUNCTION(cmu_rng), - FUNCTION(coex_uart1), - FUNCTION(coex_uart2), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(dp_hot), - FUNCTION(egpio), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(ibi_i3c), - FUNCTION(jitter_bist), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mi2s0_data0), - FUNCTION(mi2s0_data1), - FUNCTION(mi2s0_sck), - FUNCTION(mi2s0_ws), - FUNCTION(mi2s2_data0), - FUNCTION(mi2s2_data1), - FUNCTION(mi2s2_sck), - FUNCTION(mi2s2_ws), - FUNCTION(mss_grfc0), - FUNCTION(mss_grfc1), - FUNCTION(mss_grfc10), - FUNCTION(mss_grfc11), - FUNCTION(mss_grfc12), - FUNCTION(mss_grfc2), - FUNCTION(mss_grfc3), - FUNCTION(mss_grfc4), - FUNCTION(mss_grfc5), - FUNCTION(mss_grfc6), - FUNCTION(mss_grfc7), - FUNCTION(mss_grfc8), - FUNCTION(mss_grfc9), - FUNCTION(nav), - FUNCTION(pcie0_clkreqn), - FUNCTION(pcie1_clkreqn), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_clk), - FUNCTION(pri_mi2s), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qlink0_enable), - FUNCTION(qlink0_request), - FUNCTION(qlink0_wmss), - FUNCTION(qlink1_enable), - FUNCTION(qlink1_request), - FUNCTION(qlink1_wmss), - FUNCTION(qlink2_enable), - FUNCTION(qlink2_request), - FUNCTION(qlink2_wmss), - FUNCTION(qspi0), - FUNCTION(qspi1), - FUNCTION(qspi2), - FUNCTION(qspi3), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qup0), - FUNCTION(qup1), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(qup16), - FUNCTION(qup17), - FUNCTION(qup18), - FUNCTION(qup19), - FUNCTION(qup2), - FUNCTION(qup20), - FUNCTION(qup21), - FUNCTION(qup3), - FUNCTION(qup4), - FUNCTION(qup5), - FUNCTION(qup6), - FUNCTION(qup7), - FUNCTION(qup8), - FUNCTION(qup9), - FUNCTION(qup_l4), - FUNCTION(qup_l5), - FUNCTION(qup_l6), - FUNCTION(sd_write), - FUNCTION(sdc40), - FUNCTION(sdc41), - FUNCTION(sdc42), - FUNCTION(sdc43), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(sec_mi2s), - FUNCTION(tb_trig), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tmess_prng0), - FUNCTION(tmess_prng1), - FUNCTION(tmess_prng2), - FUNCTION(tmess_prng3), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(uim0_clk), - FUNCTION(uim0_data), - FUNCTION(uim0_present), - FUNCTION(uim0_reset), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(usb2phy_ac), - FUNCTION(usb_phy), - FUNCTION(vfr_0), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), +static const struct pinfunction sm8450_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(aon_cam), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_usb), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer), + MSM_PIN_FUNCTION(cmu_rng), + MSM_PIN_FUNCTION(coex_uart1), + MSM_PIN_FUNCTION(coex_uart2), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(dp_hot), + MSM_PIN_FUNCTION(egpio), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(ibi_i3c), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mi2s0_data0), + MSM_PIN_FUNCTION(mi2s0_data1), + MSM_PIN_FUNCTION(mi2s0_sck), + MSM_PIN_FUNCTION(mi2s0_ws), + MSM_PIN_FUNCTION(mi2s2_data0), + MSM_PIN_FUNCTION(mi2s2_data1), + MSM_PIN_FUNCTION(mi2s2_sck), + MSM_PIN_FUNCTION(mi2s2_ws), + MSM_PIN_FUNCTION(mss_grfc0), + MSM_PIN_FUNCTION(mss_grfc1), + MSM_PIN_FUNCTION(mss_grfc10), + MSM_PIN_FUNCTION(mss_grfc11), + MSM_PIN_FUNCTION(mss_grfc12), + MSM_PIN_FUNCTION(mss_grfc2), + MSM_PIN_FUNCTION(mss_grfc3), + MSM_PIN_FUNCTION(mss_grfc4), + MSM_PIN_FUNCTION(mss_grfc5), + MSM_PIN_FUNCTION(mss_grfc6), + MSM_PIN_FUNCTION(mss_grfc7), + MSM_PIN_FUNCTION(mss_grfc8), + MSM_PIN_FUNCTION(mss_grfc9), + MSM_PIN_FUNCTION(nav), + MSM_PIN_FUNCTION(pcie0_clkreqn), + MSM_PIN_FUNCTION(pcie1_clkreqn), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_clk), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qlink0_enable), + MSM_PIN_FUNCTION(qlink0_request), + MSM_PIN_FUNCTION(qlink0_wmss), + MSM_PIN_FUNCTION(qlink1_enable), + MSM_PIN_FUNCTION(qlink1_request), + MSM_PIN_FUNCTION(qlink1_wmss), + MSM_PIN_FUNCTION(qlink2_enable), + MSM_PIN_FUNCTION(qlink2_request), + MSM_PIN_FUNCTION(qlink2_wmss), + MSM_PIN_FUNCTION(qspi0), + MSM_PIN_FUNCTION(qspi1), + MSM_PIN_FUNCTION(qspi2), + MSM_PIN_FUNCTION(qspi3), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qup0), + MSM_PIN_FUNCTION(qup1), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(qup16), + MSM_PIN_FUNCTION(qup17), + MSM_PIN_FUNCTION(qup18), + MSM_PIN_FUNCTION(qup19), + MSM_PIN_FUNCTION(qup2), + MSM_PIN_FUNCTION(qup20), + MSM_PIN_FUNCTION(qup21), + MSM_PIN_FUNCTION(qup3), + MSM_PIN_FUNCTION(qup4), + MSM_PIN_FUNCTION(qup5), + MSM_PIN_FUNCTION(qup6), + MSM_PIN_FUNCTION(qup7), + MSM_PIN_FUNCTION(qup8), + MSM_PIN_FUNCTION(qup9), + MSM_PIN_FUNCTION(qup_l4), + MSM_PIN_FUNCTION(qup_l5), + MSM_PIN_FUNCTION(qup_l6), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdc40), + MSM_PIN_FUNCTION(sdc41), + MSM_PIN_FUNCTION(sdc42), + MSM_PIN_FUNCTION(sdc43), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(tb_trig), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tmess_prng0), + MSM_PIN_FUNCTION(tmess_prng1), + MSM_PIN_FUNCTION(tmess_prng2), + MSM_PIN_FUNCTION(tmess_prng3), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(uim0_clk), + MSM_PIN_FUNCTION(uim0_data), + MSM_PIN_FUNCTION(uim0_present), + MSM_PIN_FUNCTION(uim0_reset), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_0), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), }; /* Every pin is maintained as a single group, and missing or non-existing pin diff --git a/drivers/pinctrl/qcom/pinctrl-sm8550.c b/drivers/pinctrl/qcom/pinctrl-sm8550.c index c9d038098f2c..3c847d9cb5d9 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8550.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8550.c @@ -8,24 +8,16 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pinctrl/pinctrl.h> #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -65,9 +57,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -90,9 +82,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -1347,153 +1339,153 @@ static const char *const vsense_trigger_mirnat_groups[] = { "gpio24", }; -static const struct msm_function sm8550_functions[] = { - FUNCTION(gpio), - FUNCTION(aon_cci), - FUNCTION(aoss_cti), - FUNCTION(atest_char), - FUNCTION(atest_usb), - FUNCTION(audio_ext_mclk0), - FUNCTION(audio_ext_mclk1), - FUNCTION(audio_ref_clk), - FUNCTION(cam_aon_mclk4), - FUNCTION(cam_mclk), - FUNCTION(cci_async_in), - FUNCTION(cci_i2c_scl), - FUNCTION(cci_i2c_sda), - FUNCTION(cci_timer), - FUNCTION(cmu_rng), - FUNCTION(coex_uart1_rx), - FUNCTION(coex_uart1_tx), - FUNCTION(coex_uart2_rx), - FUNCTION(coex_uart2_tx), - FUNCTION(cri_trng), - FUNCTION(dbg_out_clk), - FUNCTION(ddr_bist_complete), - FUNCTION(ddr_bist_fail), - FUNCTION(ddr_bist_start), - FUNCTION(ddr_bist_stop), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(dp_hot), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(i2chub0_se0), - FUNCTION(i2chub0_se1), - FUNCTION(i2chub0_se2), - FUNCTION(i2chub0_se3), - FUNCTION(i2chub0_se4), - FUNCTION(i2chub0_se5), - FUNCTION(i2chub0_se6), - FUNCTION(i2chub0_se7), - FUNCTION(i2chub0_se8), - FUNCTION(i2chub0_se9), - FUNCTION(i2s0_data0), - FUNCTION(i2s0_data1), - FUNCTION(i2s0_sck), - FUNCTION(i2s0_ws), - FUNCTION(i2s1_data0), - FUNCTION(i2s1_data1), - FUNCTION(i2s1_sck), - FUNCTION(i2s1_ws), - FUNCTION(ibi_i3c), - FUNCTION(jitter_bist), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0_out), - FUNCTION(mdp_vsync1_out), - FUNCTION(mdp_vsync2_out), - FUNCTION(mdp_vsync3_out), - FUNCTION(mdp_vsync_e), - FUNCTION(nav_gpio0), - FUNCTION(nav_gpio1), - FUNCTION(nav_gpio2), - FUNCTION(pcie0_clk_req_n), - FUNCTION(pcie1_clk_req_n), - FUNCTION(phase_flag), - FUNCTION(pll_bist_sync), - FUNCTION(pll_clk_aux), - FUNCTION(prng_rosc0), - FUNCTION(prng_rosc1), - FUNCTION(prng_rosc2), - FUNCTION(prng_rosc3), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qlink0_enable), - FUNCTION(qlink0_request), - FUNCTION(qlink0_wmss), - FUNCTION(qlink1_enable), - FUNCTION(qlink1_request), - FUNCTION(qlink1_wmss), - FUNCTION(qlink2_enable), - FUNCTION(qlink2_request), - FUNCTION(qlink2_wmss), - FUNCTION(qspi0), - FUNCTION(qspi1), - FUNCTION(qspi2), - FUNCTION(qspi3), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qup1_se0), - FUNCTION(qup1_se1), - FUNCTION(qup1_se2), - FUNCTION(qup1_se3), - FUNCTION(qup1_se4), - FUNCTION(qup1_se5), - FUNCTION(qup1_se6), - FUNCTION(qup1_se7), - FUNCTION(qup2_se0), - FUNCTION(qup2_se0_l0_mira), - FUNCTION(qup2_se0_l0_mirb), - FUNCTION(qup2_se0_l1_mira), - FUNCTION(qup2_se0_l1_mirb), - FUNCTION(qup2_se0_l2_mira), - FUNCTION(qup2_se0_l2_mirb), - FUNCTION(qup2_se0_l3_mira), - FUNCTION(qup2_se0_l3_mirb), - FUNCTION(qup2_se1), - FUNCTION(qup2_se2), - FUNCTION(qup2_se3), - FUNCTION(qup2_se4), - FUNCTION(qup2_se5), - FUNCTION(qup2_se6), - FUNCTION(qup2_se7), - FUNCTION(resout_n), - FUNCTION(sd_write_protect), - FUNCTION(sdc40), - FUNCTION(sdc41), - FUNCTION(sdc42), - FUNCTION(sdc43), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(tb_trig_sdc2), - FUNCTION(tb_trig_sdc4), - FUNCTION(tgu_ch0_trigout), - FUNCTION(tgu_ch1_trigout), - FUNCTION(tgu_ch2_trigout), - FUNCTION(tgu_ch3_trigout), - FUNCTION(tmess_prng0), - FUNCTION(tmess_prng1), - FUNCTION(tmess_prng2), - FUNCTION(tmess_prng3), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(tsense_pwm3), - FUNCTION(uim0_clk), - FUNCTION(uim0_data), - FUNCTION(uim0_present), - FUNCTION(uim0_reset), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(usb1_hs), - FUNCTION(usb_phy), - FUNCTION(vfr_0), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger_mirnat), +static const struct pinfunction sm8550_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(aon_cci), + MSM_PIN_FUNCTION(aoss_cti), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_usb), + MSM_PIN_FUNCTION(audio_ext_mclk0), + MSM_PIN_FUNCTION(audio_ext_mclk1), + MSM_PIN_FUNCTION(audio_ref_clk), + MSM_PIN_FUNCTION(cam_aon_mclk4), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async_in), + MSM_PIN_FUNCTION(cci_i2c_scl), + MSM_PIN_FUNCTION(cci_i2c_sda), + MSM_PIN_FUNCTION(cci_timer), + MSM_PIN_FUNCTION(cmu_rng), + MSM_PIN_FUNCTION(coex_uart1_rx), + MSM_PIN_FUNCTION(coex_uart1_tx), + MSM_PIN_FUNCTION(coex_uart2_rx), + MSM_PIN_FUNCTION(coex_uart2_tx), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(dbg_out_clk), + MSM_PIN_FUNCTION(ddr_bist_complete), + MSM_PIN_FUNCTION(ddr_bist_fail), + MSM_PIN_FUNCTION(ddr_bist_start), + MSM_PIN_FUNCTION(ddr_bist_stop), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(dp_hot), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(i2chub0_se0), + MSM_PIN_FUNCTION(i2chub0_se1), + MSM_PIN_FUNCTION(i2chub0_se2), + MSM_PIN_FUNCTION(i2chub0_se3), + MSM_PIN_FUNCTION(i2chub0_se4), + MSM_PIN_FUNCTION(i2chub0_se5), + MSM_PIN_FUNCTION(i2chub0_se6), + MSM_PIN_FUNCTION(i2chub0_se7), + MSM_PIN_FUNCTION(i2chub0_se8), + MSM_PIN_FUNCTION(i2chub0_se9), + MSM_PIN_FUNCTION(i2s0_data0), + MSM_PIN_FUNCTION(i2s0_data1), + MSM_PIN_FUNCTION(i2s0_sck), + MSM_PIN_FUNCTION(i2s0_ws), + MSM_PIN_FUNCTION(i2s1_data0), + MSM_PIN_FUNCTION(i2s1_data1), + MSM_PIN_FUNCTION(i2s1_sck), + MSM_PIN_FUNCTION(i2s1_ws), + MSM_PIN_FUNCTION(ibi_i3c), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0_out), + MSM_PIN_FUNCTION(mdp_vsync1_out), + MSM_PIN_FUNCTION(mdp_vsync2_out), + MSM_PIN_FUNCTION(mdp_vsync3_out), + MSM_PIN_FUNCTION(mdp_vsync_e), + MSM_PIN_FUNCTION(nav_gpio0), + MSM_PIN_FUNCTION(nav_gpio1), + MSM_PIN_FUNCTION(nav_gpio2), + MSM_PIN_FUNCTION(pcie0_clk_req_n), + MSM_PIN_FUNCTION(pcie1_clk_req_n), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist_sync), + MSM_PIN_FUNCTION(pll_clk_aux), + MSM_PIN_FUNCTION(prng_rosc0), + MSM_PIN_FUNCTION(prng_rosc1), + MSM_PIN_FUNCTION(prng_rosc2), + MSM_PIN_FUNCTION(prng_rosc3), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qlink0_enable), + MSM_PIN_FUNCTION(qlink0_request), + MSM_PIN_FUNCTION(qlink0_wmss), + MSM_PIN_FUNCTION(qlink1_enable), + MSM_PIN_FUNCTION(qlink1_request), + MSM_PIN_FUNCTION(qlink1_wmss), + MSM_PIN_FUNCTION(qlink2_enable), + MSM_PIN_FUNCTION(qlink2_request), + MSM_PIN_FUNCTION(qlink2_wmss), + MSM_PIN_FUNCTION(qspi0), + MSM_PIN_FUNCTION(qspi1), + MSM_PIN_FUNCTION(qspi2), + MSM_PIN_FUNCTION(qspi3), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qup1_se0), + MSM_PIN_FUNCTION(qup1_se1), + MSM_PIN_FUNCTION(qup1_se2), + MSM_PIN_FUNCTION(qup1_se3), + MSM_PIN_FUNCTION(qup1_se4), + MSM_PIN_FUNCTION(qup1_se5), + MSM_PIN_FUNCTION(qup1_se6), + MSM_PIN_FUNCTION(qup1_se7), + MSM_PIN_FUNCTION(qup2_se0), + MSM_PIN_FUNCTION(qup2_se0_l0_mira), + MSM_PIN_FUNCTION(qup2_se0_l0_mirb), + MSM_PIN_FUNCTION(qup2_se0_l1_mira), + MSM_PIN_FUNCTION(qup2_se0_l1_mirb), + MSM_PIN_FUNCTION(qup2_se0_l2_mira), + MSM_PIN_FUNCTION(qup2_se0_l2_mirb), + MSM_PIN_FUNCTION(qup2_se0_l3_mira), + MSM_PIN_FUNCTION(qup2_se0_l3_mirb), + MSM_PIN_FUNCTION(qup2_se1), + MSM_PIN_FUNCTION(qup2_se2), + MSM_PIN_FUNCTION(qup2_se3), + MSM_PIN_FUNCTION(qup2_se4), + MSM_PIN_FUNCTION(qup2_se5), + MSM_PIN_FUNCTION(qup2_se6), + MSM_PIN_FUNCTION(qup2_se7), + MSM_PIN_FUNCTION(resout_n), + MSM_PIN_FUNCTION(sd_write_protect), + MSM_PIN_FUNCTION(sdc40), + MSM_PIN_FUNCTION(sdc41), + MSM_PIN_FUNCTION(sdc42), + MSM_PIN_FUNCTION(sdc43), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(tb_trig_sdc2), + MSM_PIN_FUNCTION(tb_trig_sdc4), + MSM_PIN_FUNCTION(tgu_ch0_trigout), + MSM_PIN_FUNCTION(tgu_ch1_trigout), + MSM_PIN_FUNCTION(tgu_ch2_trigout), + MSM_PIN_FUNCTION(tgu_ch3_trigout), + MSM_PIN_FUNCTION(tmess_prng0), + MSM_PIN_FUNCTION(tmess_prng1), + MSM_PIN_FUNCTION(tmess_prng2), + MSM_PIN_FUNCTION(tmess_prng3), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(tsense_pwm3), + MSM_PIN_FUNCTION(uim0_clk), + MSM_PIN_FUNCTION(uim0_data), + MSM_PIN_FUNCTION(uim0_present), + MSM_PIN_FUNCTION(uim0_reset), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(usb1_hs), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_0), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger_mirnat), }; /* diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c index 43c7857c06a5..b4cd66886f29 100644 --- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c @@ -1229,6 +1229,8 @@ static const struct of_device_id pmic_gpio_of_match[] = { { .compatible = "qcom,pm8941-gpio", .data = (void *) 36 }, /* pm8950 has 8 GPIOs with holes on 3 */ { .compatible = "qcom,pm8950-gpio", .data = (void *) 8 }, + /* pm8953 has 8 GPIOs with holes on 3 and 6 */ + { .compatible = "qcom,pm8953-gpio", .data = (void *) 8 }, { .compatible = "qcom,pm8994-gpio", .data = (void *) 22 }, { .compatible = "qcom,pm8998-gpio", .data = (void *) 26 }, { .compatible = "qcom,pma8084-gpio", .data = (void *) 22 }, diff --git a/drivers/pinctrl/renesas/pfc-r8a77970.c b/drivers/pinctrl/renesas/pfc-r8a77970.c index 5b66d7b1af95..e1b3e3b38ec3 100644 --- a/drivers/pinctrl/renesas/pfc-r8a77970.c +++ b/drivers/pinctrl/renesas/pfc-r8a77970.c @@ -171,7 +171,7 @@ #define IP0_31_28 FM(DU_DG3) FM(MSIOF3_SS2) F_(0, 0) FM(A7) FM(PWMFSW0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1_3_0 FM(DU_DG4) F_(0, 0) F_(0, 0) FM(A8) FM(FSO_CFE_0_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1_7_4 FM(DU_DG5) F_(0, 0) F_(0, 0) FM(A9) FM(FSO_CFE_1_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP1_11_8 FM(DU_DG6) F_(0, 0) F_(0, 0) FM(A10) FM(FSO_TOE_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1_11_8 FM(DU_DG6) F_(0, 0) F_(0, 0) FM(A10) FM(FSO_TOE_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1_15_12 FM(DU_DG7) F_(0, 0) F_(0, 0) FM(A11) FM(IRQ1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1_19_16 FM(DU_DB2) F_(0, 0) F_(0, 0) FM(A12) FM(IRQ2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1_23_20 FM(DU_DB3) F_(0, 0) F_(0, 0) FM(A13) FM(FXR_CLKOUT1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) diff --git a/drivers/pinctrl/renesas/pfc-r8a77980.c b/drivers/pinctrl/renesas/pfc-r8a77980.c index 384faa0d6937..877134d78c7e 100644 --- a/drivers/pinctrl/renesas/pfc-r8a77980.c +++ b/drivers/pinctrl/renesas/pfc-r8a77980.c @@ -99,7 +99,7 @@ #define GPSR1_0 F_(IRQ0, IP2_27_24) /* GPSR2 */ -#define GPSR2_29 F_(FSO_TOE_N, IP10_19_16) +#define GPSR2_29 F_(FSO_TOE_N, IP10_19_16) #define GPSR2_28 F_(FSO_CFE_1_N, IP10_15_12) #define GPSR2_27 F_(FSO_CFE_0_N, IP10_11_8) #define GPSR2_26 F_(SDA3, IP10_7_4) @@ -264,11 +264,11 @@ #define IP8_11_8 FM(CANFD0_RX_A) FM(RXDA_EXTFXR) FM(PWM1_B) FM(DU_CDE) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP8_15_12 FM(CANFD1_TX) FM(FXR_TXDB) FM(PWM2_B) FM(TCLK1_B) FM(TX1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP8_19_16 FM(CANFD1_RX) FM(RXDB_EXTFXR) FM(PWM3_B) FM(TCLK2_B) FM(RX1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP8_23_20 FM(CANFD_CLK_A) FM(CLK_EXTFXR) FM(PWM4_B) FM(SPEEDIN_B) FM(SCIF_CLK_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP8_23_20 FM(CANFD_CLK_A) FM(CLK_EXTFXR) FM(PWM4_B) FM(SPEEDIN_B) FM(SCIF_CLK_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP8_27_24 FM(DIGRF_CLKIN) FM(DIGRF_CLKEN_IN) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP8_31_28 FM(DIGRF_CLKOUT) FM(DIGRF_CLKEN_OUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP9_3_0 FM(IRQ4) F_(0, 0) F_(0, 0) FM(VI0_DATA12) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP9_7_4 FM(IRQ5) F_(0, 0) F_(0, 0) FM(VI0_DATA13) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP9_7_4 FM(IRQ5) F_(0, 0) F_(0, 0) FM(VI0_DATA13) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP9_11_8 FM(MSIOF0_RXD) FM(DU_DR0) F_(0, 0) FM(VI0_DATA14) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP9_15_12 FM(MSIOF0_TXD) FM(DU_DR1) F_(0, 0) FM(VI0_DATA15) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP9_19_16 FM(MSIOF0_SCK) FM(DU_DG0) F_(0, 0) FM(VI0_DATA16) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c index 18de2e70ea50..b8caaa5a2d4e 100644 --- a/drivers/pinctrl/spear/pinctrl-spear.c +++ b/drivers/pinctrl/spear/pinctrl-spear.c @@ -18,7 +18,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_gpio.h> #include <linux/platform_device.h> #include <linux/seq_file.h> #include <linux/slab.h> diff --git a/drivers/pinctrl/sunplus/sppctl.c b/drivers/pinctrl/sunplus/sppctl.c index 6bbbab3a6fdf..150996949ede 100644 --- a/drivers/pinctrl/sunplus/sppctl.c +++ b/drivers/pinctrl/sunplus/sppctl.c @@ -834,11 +834,6 @@ static int sppctl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node int i, size = 0; list = of_get_property(np_config, "sunplus,pins", &size); - - if (nmG <= 0) - nmG = 0; - - parent = of_get_parent(np_config); *num_maps = size / sizeof(*list); /* @@ -866,10 +861,14 @@ static int sppctl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node } } + if (nmG <= 0) + nmG = 0; + *map = kcalloc(*num_maps + nmG, sizeof(**map), GFP_KERNEL); - if (*map == NULL) + if (!(*map)) return -ENOMEM; + parent = of_get_parent(np_config); for (i = 0; i < (*num_maps); i++) { dt_pin = be32_to_cpu(list[i]); pin_num = FIELD_GET(GENMASK(31, 24), dt_pin); @@ -883,6 +882,8 @@ static int sppctl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node (*map)[i].data.configs.num_configs = 1; (*map)[i].data.configs.group_or_pin = pin_get_name(pctldev, pin_num); configs = kmalloc(sizeof(*configs), GFP_KERNEL); + if (!configs) + goto sppctl_map_err; *configs = FIELD_GET(GENMASK(7, 0), dt_pin); (*map)[i].data.configs.configs = configs; @@ -896,6 +897,8 @@ static int sppctl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node (*map)[i].data.configs.num_configs = 1; (*map)[i].data.configs.group_or_pin = pin_get_name(pctldev, pin_num); configs = kmalloc(sizeof(*configs), GFP_KERNEL); + if (!configs) + goto sppctl_map_err; *configs = SPPCTL_IOP_CONFIGS; (*map)[i].data.configs.configs = configs; @@ -965,6 +968,14 @@ static int sppctl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node of_node_put(parent); dev_dbg(pctldev->dev, "%d pins mapped\n", *num_maps); return 0; + +sppctl_map_err: + for (i = 0; i < (*num_maps); i++) + if ((*map)[i].type == PIN_MAP_TYPE_CONFIGS_PIN) + kfree((*map)[i].data.configs.configs); + kfree(*map); + of_node_put(parent); + return -ENOMEM; } static const struct pinctrl_ops sppctl_pctl_ops = { diff --git a/drivers/pinctrl/tegra/Kconfig b/drivers/pinctrl/tegra/Kconfig index a67d0d9ae8cd..4e87d19323ba 100644 --- a/drivers/pinctrl/tegra/Kconfig +++ b/drivers/pinctrl/tegra/Kconfig @@ -28,6 +28,10 @@ config PINCTRL_TEGRA194 bool select PINCTRL_TEGRA +config PINCTRL_TEGRA234 + bool + select PINCTRL_TEGRA + config PINCTRL_TEGRA_XUSB def_bool y if ARCH_TEGRA select GENERIC_PHY diff --git a/drivers/pinctrl/tegra/Makefile b/drivers/pinctrl/tegra/Makefile index ead4e10097d0..a93973701d4c 100644 --- a/drivers/pinctrl/tegra/Makefile +++ b/drivers/pinctrl/tegra/Makefile @@ -6,4 +6,5 @@ obj-$(CONFIG_PINCTRL_TEGRA114) += pinctrl-tegra114.o obj-$(CONFIG_PINCTRL_TEGRA124) += pinctrl-tegra124.o obj-$(CONFIG_PINCTRL_TEGRA210) += pinctrl-tegra210.o obj-$(CONFIG_PINCTRL_TEGRA194) += pinctrl-tegra194.o +obj-$(CONFIG_PINCTRL_TEGRA234) += pinctrl-tegra234.o obj-$(CONFIG_PINCTRL_TEGRA_XUSB) += pinctrl-tegra-xusb.o diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c index 1729b7ddfa94..4547cf66d03b 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra.c @@ -232,7 +232,7 @@ static const char *tegra_pinctrl_get_func_name(struct pinctrl_dev *pctldev, { struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - return pmx->soc->functions[function].name; + return pmx->functions[function].name; } static int tegra_pinctrl_get_func_groups(struct pinctrl_dev *pctldev, @@ -242,8 +242,8 @@ static int tegra_pinctrl_get_func_groups(struct pinctrl_dev *pctldev, { struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - *groups = pmx->soc->functions[function].groups; - *num_groups = pmx->soc->functions[function].ngroups; + *groups = pmx->functions[function].groups; + *num_groups = pmx->functions[function].ngroups; return 0; } @@ -789,20 +789,26 @@ int tegra_pinctrl_probe(struct platform_device *pdev, * Each mux group will appear in 4 functions' list of groups. * This over-allocates slightly, since not all groups are mux groups. */ - pmx->group_pins = devm_kcalloc(&pdev->dev, - soc_data->ngroups * 4, sizeof(*pmx->group_pins), - GFP_KERNEL); + pmx->group_pins = devm_kcalloc(&pdev->dev, pmx->soc->ngroups * 4, + sizeof(*pmx->group_pins), GFP_KERNEL); if (!pmx->group_pins) return -ENOMEM; + pmx->functions = devm_kcalloc(&pdev->dev, pmx->soc->nfunctions, + sizeof(*pmx->functions), GFP_KERNEL); + if (!pmx->functions) + return -ENOMEM; + group_pins = pmx->group_pins; - for (fn = 0; fn < soc_data->nfunctions; fn++) { - struct tegra_function *func = &soc_data->functions[fn]; + for (fn = 0; fn < pmx->soc->nfunctions; fn++) { + struct tegra_function *func = &pmx->functions[fn]; + + func->name = pmx->soc->functions[fn]; func->groups = group_pins; - for (gn = 0; gn < soc_data->ngroups; gn++) { - const struct tegra_pingroup *g = &soc_data->groups[gn]; + for (gn = 0; gn < pmx->soc->ngroups; gn++) { + const struct tegra_pingroup *g = &pmx->soc->groups[gn]; if (g->mux_reg == -1) continue; @@ -814,7 +820,7 @@ int tegra_pinctrl_probe(struct platform_device *pdev, continue; BUG_ON(group_pins - pmx->group_pins >= - soc_data->ngroups * 4); + pmx->soc->ngroups * 4); *group_pins++ = g->name; func->ngroups++; } diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.h b/drivers/pinctrl/tegra/pinctrl-tegra.h index 6130cba7cce5..b3289bdf727d 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra.h +++ b/drivers/pinctrl/tegra/pinctrl-tegra.h @@ -13,6 +13,7 @@ struct tegra_pmx { struct pinctrl_dev *pctl; const struct tegra_pinctrl_soc_data *soc; + struct tegra_function *functions; const char **group_pins; struct pinctrl_gpio_range gpio_range; @@ -191,7 +192,7 @@ struct tegra_pinctrl_soc_data { const char *gpio_compatible; const struct pinctrl_pin_desc *pins; unsigned npins; - struct tegra_function *functions; + const char * const *functions; unsigned nfunctions; const struct tegra_pingroup *groups; unsigned ngroups; diff --git a/drivers/pinctrl/tegra/pinctrl-tegra114.c b/drivers/pinctrl/tegra/pinctrl-tegra114.c index e72ab1eb2398..3d425b2018e7 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra114.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra114.c @@ -1452,12 +1452,9 @@ enum tegra_mux { TEGRA_MUX_VI_ALT3, }; -#define FUNCTION(fname) \ - { \ - .name = #fname, \ - } +#define FUNCTION(fname) #fname -static struct tegra_function tegra114_functions[] = { +static const char * const tegra114_functions[] = { FUNCTION(blink), FUNCTION(cec), FUNCTION(cldvfs), diff --git a/drivers/pinctrl/tegra/pinctrl-tegra124.c b/drivers/pinctrl/tegra/pinctrl-tegra124.c index 26096c6b967e..2a50c5c7516c 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra124.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra124.c @@ -1611,12 +1611,9 @@ enum tegra_mux { TEGRA_MUX_VIMCLK2_ALT, }; -#define FUNCTION(fname) \ - { \ - .name = #fname, \ - } +#define FUNCTION(fname) #fname -static struct tegra_function tegra124_functions[] = { +static const char * const tegra124_functions[] = { FUNCTION(blink), FUNCTION(ccla), FUNCTION(cec), diff --git a/drivers/pinctrl/tegra/pinctrl-tegra194.c b/drivers/pinctrl/tegra/pinctrl-tegra194.c index 277973c88434..69f58df62897 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra194.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra194.c @@ -1189,12 +1189,9 @@ enum tegra_mux_dt { }; /* Make list of each function name */ -#define TEGRA_PIN_FUNCTION(lid) \ - { \ - .name = #lid, \ - } +#define TEGRA_PIN_FUNCTION(lid) #lid -static struct tegra_function tegra194_functions[] = { +static const char * const tegra194_functions[] = { TEGRA_PIN_FUNCTION(rsvd0), TEGRA_PIN_FUNCTION(rsvd1), TEGRA_PIN_FUNCTION(rsvd2), diff --git a/drivers/pinctrl/tegra/pinctrl-tegra20.c b/drivers/pinctrl/tegra/pinctrl-tegra20.c index 0dc2cf0d05b1..737fc2000f66 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra20.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra20.c @@ -1889,12 +1889,9 @@ enum tegra_mux { TEGRA_MUX_XIO, }; -#define FUNCTION(fname) \ - { \ - .name = #fname, \ - } +#define FUNCTION(fname) #fname -static struct tegra_function tegra20_functions[] = { +static const char * const tegra20_functions[] = { FUNCTION(ahb_clk), FUNCTION(apb_clk), FUNCTION(audio_sync), diff --git a/drivers/pinctrl/tegra/pinctrl-tegra210.c b/drivers/pinctrl/tegra/pinctrl-tegra210.c index b480f607fa16..9bb29146dfff 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra210.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra210.c @@ -1185,12 +1185,9 @@ enum tegra_mux { TEGRA_MUX_VIMCLK2, }; -#define FUNCTION(fname) \ - { \ - .name = #fname, \ - } +#define FUNCTION(fname) #fname -static struct tegra_function tegra210_functions[] = { +static const char * const tegra210_functions[] = { FUNCTION(aud), FUNCTION(bcl), FUNCTION(blink), diff --git a/drivers/pinctrl/tegra/pinctrl-tegra234.c b/drivers/pinctrl/tegra/pinctrl-tegra234.c new file mode 100644 index 000000000000..86c2b84e792d --- /dev/null +++ b/drivers/pinctrl/tegra/pinctrl-tegra234.c @@ -0,0 +1,1960 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Pinctrl data for the NVIDIA Tegra234 pinmux + * + * Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved. + */ + +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/property.h> + +#include <linux/pinctrl/pinctrl.h> +#include <linux/pinctrl/pinmux.h> + +#include "pinctrl-tegra.h" + +/* Define unique ID for each pins */ +enum { + TEGRA_PIN_DAP6_SCLK_PA0, + TEGRA_PIN_DAP6_DOUT_PA1, + TEGRA_PIN_DAP6_DIN_PA2, + TEGRA_PIN_DAP6_FS_PA3, + TEGRA_PIN_DAP4_SCLK_PA4, + TEGRA_PIN_DAP4_DOUT_PA5, + TEGRA_PIN_DAP4_DIN_PA6, + TEGRA_PIN_DAP4_FS_PA7, + TEGRA_PIN_SOC_GPIO08_PB0, + TEGRA_PIN_QSPI0_SCK_PC0, + TEGRA_PIN_QSPI0_CS_N_PC1, + TEGRA_PIN_QSPI0_IO0_PC2, + TEGRA_PIN_QSPI0_IO1_PC3, + TEGRA_PIN_QSPI0_IO2_PC4, + TEGRA_PIN_QSPI0_IO3_PC5, + TEGRA_PIN_QSPI1_SCK_PC6, + TEGRA_PIN_QSPI1_CS_N_PC7, + TEGRA_PIN_QSPI1_IO0_PD0, + TEGRA_PIN_QSPI1_IO1_PD1, + TEGRA_PIN_QSPI1_IO2_PD2, + TEGRA_PIN_QSPI1_IO3_PD3, + TEGRA_PIN_EQOS_TXC_PE0, + TEGRA_PIN_EQOS_TD0_PE1, + TEGRA_PIN_EQOS_TD1_PE2, + TEGRA_PIN_EQOS_TD2_PE3, + TEGRA_PIN_EQOS_TD3_PE4, + TEGRA_PIN_EQOS_TX_CTL_PE5, + TEGRA_PIN_EQOS_RD0_PE6, + TEGRA_PIN_EQOS_RD1_PE7, + TEGRA_PIN_EQOS_RD2_PF0, + TEGRA_PIN_EQOS_RD3_PF1, + TEGRA_PIN_EQOS_RX_CTL_PF2, + TEGRA_PIN_EQOS_RXC_PF3, + TEGRA_PIN_EQOS_SMA_MDIO_PF4, + TEGRA_PIN_EQOS_SMA_MDC_PF5, + TEGRA_PIN_SOC_GPIO13_PG0, + TEGRA_PIN_SOC_GPIO14_PG1, + TEGRA_PIN_SOC_GPIO15_PG2, + TEGRA_PIN_SOC_GPIO16_PG3, + TEGRA_PIN_SOC_GPIO17_PG4, + TEGRA_PIN_SOC_GPIO18_PG5, + TEGRA_PIN_SOC_GPIO19_PG6, + TEGRA_PIN_SOC_GPIO20_PG7, + TEGRA_PIN_SOC_GPIO21_PH0, + TEGRA_PIN_SOC_GPIO22_PH1, + TEGRA_PIN_SOC_GPIO06_PH2, + TEGRA_PIN_UART4_TX_PH3, + TEGRA_PIN_UART4_RX_PH4, + TEGRA_PIN_UART4_RTS_PH5, + TEGRA_PIN_UART4_CTS_PH6, + TEGRA_PIN_SOC_GPIO41_PH7, + TEGRA_PIN_SOC_GPIO42_PI0, + TEGRA_PIN_SOC_GPIO43_PI1, + TEGRA_PIN_SOC_GPIO44_PI2, + TEGRA_PIN_GEN1_I2C_SCL_PI3, + TEGRA_PIN_GEN1_I2C_SDA_PI4, + TEGRA_PIN_CPU_PWR_REQ_PI5, + TEGRA_PIN_SOC_GPIO07_PI6, + TEGRA_PIN_SDMMC1_CLK_PJ0, + TEGRA_PIN_SDMMC1_CMD_PJ1, + TEGRA_PIN_SDMMC1_DAT0_PJ2, + TEGRA_PIN_SDMMC1_DAT1_PJ3, + TEGRA_PIN_SDMMC1_DAT2_PJ4, + TEGRA_PIN_SDMMC1_DAT3_PJ5, + TEGRA_PIN_PEX_L0_CLKREQ_N_PK0, + TEGRA_PIN_PEX_L0_RST_N_PK1, + TEGRA_PIN_PEX_L1_CLKREQ_N_PK2, + TEGRA_PIN_PEX_L1_RST_N_PK3, + TEGRA_PIN_PEX_L2_CLKREQ_N_PK4, + TEGRA_PIN_PEX_L2_RST_N_PK5, + TEGRA_PIN_PEX_L3_CLKREQ_N_PK6, + TEGRA_PIN_PEX_L3_RST_N_PK7, + TEGRA_PIN_PEX_L4_CLKREQ_N_PL0, + TEGRA_PIN_PEX_L4_RST_N_PL1, + TEGRA_PIN_PEX_WAKE_N_PL2, + TEGRA_PIN_SOC_GPIO34_PL3, + TEGRA_PIN_DP_AUX_CH0_HPD_PM0, + TEGRA_PIN_DP_AUX_CH1_HPD_PM1, + TEGRA_PIN_DP_AUX_CH2_HPD_PM2, + TEGRA_PIN_DP_AUX_CH3_HPD_PM3, + TEGRA_PIN_SOC_GPIO55_PM4, + TEGRA_PIN_SOC_GPIO36_PM5, + TEGRA_PIN_SOC_GPIO53_PM6, + TEGRA_PIN_SOC_GPIO38_PM7, + TEGRA_PIN_DP_AUX_CH3_N_PN0, + TEGRA_PIN_SOC_GPIO39_PN1, + TEGRA_PIN_SOC_GPIO40_PN2, + TEGRA_PIN_DP_AUX_CH1_P_PN3, + TEGRA_PIN_DP_AUX_CH1_N_PN4, + TEGRA_PIN_DP_AUX_CH2_P_PN5, + TEGRA_PIN_DP_AUX_CH2_N_PN6, + TEGRA_PIN_DP_AUX_CH3_P_PN7, + TEGRA_PIN_EXTPERIPH1_CLK_PP0, + TEGRA_PIN_EXTPERIPH2_CLK_PP1, + TEGRA_PIN_CAM_I2C_SCL_PP2, + TEGRA_PIN_CAM_I2C_SDA_PP3, + TEGRA_PIN_SOC_GPIO23_PP4, + TEGRA_PIN_SOC_GPIO24_PP5, + TEGRA_PIN_SOC_GPIO25_PP6, + TEGRA_PIN_PWR_I2C_SCL_PP7, + TEGRA_PIN_PWR_I2C_SDA_PQ0, + TEGRA_PIN_SOC_GPIO28_PQ1, + TEGRA_PIN_SOC_GPIO29_PQ2, + TEGRA_PIN_SOC_GPIO30_PQ3, + TEGRA_PIN_SOC_GPIO31_PQ4, + TEGRA_PIN_SOC_GPIO32_PQ5, + TEGRA_PIN_SOC_GPIO33_PQ6, + TEGRA_PIN_SOC_GPIO35_PQ7, + TEGRA_PIN_SOC_GPIO37_PR0, + TEGRA_PIN_SOC_GPIO56_PR1, + TEGRA_PIN_UART1_TX_PR2, + TEGRA_PIN_UART1_RX_PR3, + TEGRA_PIN_UART1_RTS_PR4, + TEGRA_PIN_UART1_CTS_PR5, + TEGRA_PIN_GPU_PWR_REQ_PX0, + TEGRA_PIN_CV_PWR_REQ_PX1, + TEGRA_PIN_GP_PWM2_PX2, + TEGRA_PIN_GP_PWM3_PX3, + TEGRA_PIN_UART2_TX_PX4, + TEGRA_PIN_UART2_RX_PX5, + TEGRA_PIN_UART2_RTS_PX6, + TEGRA_PIN_UART2_CTS_PX7, + TEGRA_PIN_SPI3_SCK_PY0, + TEGRA_PIN_SPI3_MISO_PY1, + TEGRA_PIN_SPI3_MOSI_PY2, + TEGRA_PIN_SPI3_CS0_PY3, + TEGRA_PIN_SPI3_CS1_PY4, + TEGRA_PIN_UART5_TX_PY5, + TEGRA_PIN_UART5_RX_PY6, + TEGRA_PIN_UART5_RTS_PY7, + TEGRA_PIN_UART5_CTS_PZ0, + TEGRA_PIN_USB_VBUS_EN0_PZ1, + TEGRA_PIN_USB_VBUS_EN1_PZ2, + TEGRA_PIN_SPI1_SCK_PZ3, + TEGRA_PIN_SPI1_MISO_PZ4, + TEGRA_PIN_SPI1_MOSI_PZ5, + TEGRA_PIN_SPI1_CS0_PZ6, + TEGRA_PIN_SPI1_CS1_PZ7, + TEGRA_PIN_SPI5_SCK_PAC0, + TEGRA_PIN_SPI5_MISO_PAC1, + TEGRA_PIN_SPI5_MOSI_PAC2, + TEGRA_PIN_SPI5_CS0_PAC3, + TEGRA_PIN_SOC_GPIO57_PAC4, + TEGRA_PIN_SOC_GPIO58_PAC5, + TEGRA_PIN_SOC_GPIO59_PAC6, + TEGRA_PIN_SOC_GPIO60_PAC7, + TEGRA_PIN_SOC_GPIO45_PAD0, + TEGRA_PIN_SOC_GPIO46_PAD1, + TEGRA_PIN_SOC_GPIO47_PAD2, + TEGRA_PIN_SOC_GPIO48_PAD3, + TEGRA_PIN_UFS0_REF_CLK_PAE0, + TEGRA_PIN_UFS0_RST_N_PAE1, + TEGRA_PIN_PEX_L5_CLKREQ_N_PAF0, + TEGRA_PIN_PEX_L5_RST_N_PAF1, + TEGRA_PIN_PEX_L6_CLKREQ_N_PAF2, + TEGRA_PIN_PEX_L6_RST_N_PAF3, + TEGRA_PIN_PEX_L7_CLKREQ_N_PAG0, + TEGRA_PIN_PEX_L7_RST_N_PAG1, + TEGRA_PIN_PEX_L8_CLKREQ_N_PAG2, + TEGRA_PIN_PEX_L8_RST_N_PAG3, + TEGRA_PIN_PEX_L9_CLKREQ_N_PAG4, + TEGRA_PIN_PEX_L9_RST_N_PAG5, + TEGRA_PIN_PEX_L10_CLKREQ_N_PAG6, + TEGRA_PIN_PEX_L10_RST_N_PAG7, + TEGRA_PIN_EQOS_COMP, + TEGRA_PIN_QSPI_COMP, + TEGRA_PIN_SDMMC1_COMP, +}; + +enum { + TEGRA_PIN_CAN0_DOUT_PAA0, + TEGRA_PIN_CAN0_DIN_PAA1, + TEGRA_PIN_CAN1_DOUT_PAA2, + TEGRA_PIN_CAN1_DIN_PAA3, + TEGRA_PIN_CAN0_STB_PAA4, + TEGRA_PIN_CAN0_EN_PAA5, + TEGRA_PIN_SOC_GPIO49_PAA6, + TEGRA_PIN_CAN0_ERR_PAA7, + TEGRA_PIN_CAN1_STB_PBB0, + TEGRA_PIN_CAN1_EN_PBB1, + TEGRA_PIN_SOC_GPIO50_PBB2, + TEGRA_PIN_CAN1_ERR_PBB3, + TEGRA_PIN_SPI2_SCK_PCC0, + TEGRA_PIN_SPI2_MISO_PCC1, + TEGRA_PIN_SPI2_MOSI_PCC2, + TEGRA_PIN_SPI2_CS0_PCC3, + TEGRA_PIN_TOUCH_CLK_PCC4, + TEGRA_PIN_UART3_TX_PCC5, + TEGRA_PIN_UART3_RX_PCC6, + TEGRA_PIN_GEN2_I2C_SCL_PCC7, + TEGRA_PIN_GEN2_I2C_SDA_PDD0, + TEGRA_PIN_GEN8_I2C_SCL_PDD1, + TEGRA_PIN_GEN8_I2C_SDA_PDD2, + TEGRA_PIN_SCE_ERROR_PEE0, + TEGRA_PIN_VCOMP_ALERT_PEE1, + TEGRA_PIN_AO_RETENTION_N_PEE2, + TEGRA_PIN_BATT_OC_PEE3, + TEGRA_PIN_POWER_ON_PEE4, + TEGRA_PIN_SOC_GPIO26_PEE5, + TEGRA_PIN_SOC_GPIO27_PEE6, + TEGRA_PIN_BOOTV_CTL_N_PEE7, + TEGRA_PIN_HDMI_CEC_PGG0, +}; + +/* Table for pin descriptor */ +static const struct pinctrl_pin_desc tegra234_pins[] = { + PINCTRL_PIN(TEGRA_PIN_DAP6_SCLK_PA0, "DAP6_SCLK_PA0"), + PINCTRL_PIN(TEGRA_PIN_DAP6_DOUT_PA1, "DAP6_DOUT_PA1"), + PINCTRL_PIN(TEGRA_PIN_DAP6_DIN_PA2, "DAP6_DIN_PA2"), + PINCTRL_PIN(TEGRA_PIN_DAP6_FS_PA3, "DAP6_FS_PA3"), + PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PA4, "DAP4_SCLK_PA4"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PA5, "DAP4_DOUT_PA5"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PA6, "DAP4_DIN_PA6"), + PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PA7, "DAP4_FS_PA7"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO08_PB0, "SOC_GPIO08_PB0"), + PINCTRL_PIN(TEGRA_PIN_QSPI0_SCK_PC0, "QSPI0_SCK_PC0"), + PINCTRL_PIN(TEGRA_PIN_QSPI0_CS_N_PC1, "QSPI0_CS_N_PC1"), + PINCTRL_PIN(TEGRA_PIN_QSPI0_IO0_PC2, "QSPI0_IO0_PC2"), + PINCTRL_PIN(TEGRA_PIN_QSPI0_IO1_PC3, "QSPI0_IO1_PC3"), + PINCTRL_PIN(TEGRA_PIN_QSPI0_IO2_PC4, "QSPI0_IO2_PC4"), + PINCTRL_PIN(TEGRA_PIN_QSPI0_IO3_PC5, "QSPI0_IO3_PC5"), + PINCTRL_PIN(TEGRA_PIN_QSPI1_SCK_PC6, "QSPI1_SCK_PC6"), + PINCTRL_PIN(TEGRA_PIN_QSPI1_CS_N_PC7, "QSPI1_CS_N_PC7"), + PINCTRL_PIN(TEGRA_PIN_QSPI1_IO0_PD0, "QSPI1_IO0_PD0"), + PINCTRL_PIN(TEGRA_PIN_QSPI1_IO1_PD1, "QSPI1_IO1_PD1"), + PINCTRL_PIN(TEGRA_PIN_QSPI1_IO2_PD2, "QSPI1_IO2_PD2"), + PINCTRL_PIN(TEGRA_PIN_QSPI1_IO3_PD3, "QSPI1_IO3_PD3"), + PINCTRL_PIN(TEGRA_PIN_EQOS_TXC_PE0, "EQOS_TXC_PE0"), + PINCTRL_PIN(TEGRA_PIN_EQOS_TD0_PE1, "EQOS_TD0_PE1"), + PINCTRL_PIN(TEGRA_PIN_EQOS_TD1_PE2, "EQOS_TD1_PE2"), + PINCTRL_PIN(TEGRA_PIN_EQOS_TD2_PE3, "EQOS_TD2_PE3"), + PINCTRL_PIN(TEGRA_PIN_EQOS_TD3_PE4, "EQOS_TD3_PE4"), + PINCTRL_PIN(TEGRA_PIN_EQOS_TX_CTL_PE5, "EQOS_TX_CTL_PE5"), + PINCTRL_PIN(TEGRA_PIN_EQOS_RD0_PE6, "EQOS_RD0_PE6"), + PINCTRL_PIN(TEGRA_PIN_EQOS_RD1_PE7, "EQOS_RD1_PE7"), + PINCTRL_PIN(TEGRA_PIN_EQOS_RD2_PF0, "EQOS_RD2_PF0"), + PINCTRL_PIN(TEGRA_PIN_EQOS_RD3_PF1, "EQOS_RD3_PF1"), + PINCTRL_PIN(TEGRA_PIN_EQOS_RX_CTL_PF2, "EQOS_RX_CTL_PF2"), + PINCTRL_PIN(TEGRA_PIN_EQOS_RXC_PF3, "EQOS_RXC_PF3"), + PINCTRL_PIN(TEGRA_PIN_EQOS_SMA_MDIO_PF4, "EQOS_SMA_MDIO_PF4"), + PINCTRL_PIN(TEGRA_PIN_EQOS_SMA_MDC_PF5, "EQOS_SMA_MDC_PF5"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO13_PG0, "SOC_GPIO13_PG0"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO14_PG1, "SOC_GPIO14_PG1"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO15_PG2, "SOC_GPIO15_PG2"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO16_PG3, "SOC_GPIO16_PG3"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO17_PG4, "SOC_GPIO17_PG4"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO18_PG5, "SOC_GPIO18_PG5"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO19_PG6, "SOC_GPIO19_PG6"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO20_PG7, "SOC_GPIO20_PG7"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO21_PH0, "SOC_GPIO21_PH0"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO22_PH1, "SOC_GPIO22_PH1"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO06_PH2, "SOC_GPIO06_PH2"), + PINCTRL_PIN(TEGRA_PIN_UART4_TX_PH3, "UART4_TX_PH3"), + PINCTRL_PIN(TEGRA_PIN_UART4_RX_PH4, "UART4_RX_PH4"), + PINCTRL_PIN(TEGRA_PIN_UART4_RTS_PH5, "UART4_RTS_PH5"), + PINCTRL_PIN(TEGRA_PIN_UART4_CTS_PH6, "UART4_CTS_PH6"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO41_PH7, "SOC_GPIO41_PH7"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO42_PI0, "SOC_GPIO42_PI0"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO43_PI1, "SOC_GPIO43_PI1"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO44_PI2, "SOC_GPIO44_PI2"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PI3, "GEN1_I2C_SCL_PI3"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PI4, "GEN1_I2C_SDA_PI4"), + PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ_PI5, "CPU_PWR_REQ_PI5"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO07_PI6, "SOC_GPIO07_PI6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PJ0, "SDMMC1_CLK_PJ0"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PJ1, "SDMMC1_CMD_PJ1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PJ2, "SDMMC1_DAT0_PJ2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PJ3, "SDMMC1_DAT1_PJ3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PJ4, "SDMMC1_DAT2_PJ4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PJ5, "SDMMC1_DAT3_PJ5"), + PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PK0, "PEX_L0_CLKREQ_N_PK0"), + PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PK1, "PEX_L0_RST_N_PK1"), + PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PK2, "PEX_L1_CLKREQ_N_PK2"), + PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PK3, "PEX_L1_RST_N_PK3"), + PINCTRL_PIN(TEGRA_PIN_PEX_L2_CLKREQ_N_PK4, "PEX_L2_CLKREQ_N_PK4"), + PINCTRL_PIN(TEGRA_PIN_PEX_L2_RST_N_PK5, "PEX_L2_RST_N_PK5"), + PINCTRL_PIN(TEGRA_PIN_PEX_L3_CLKREQ_N_PK6, "PEX_L3_CLKREQ_N_PK6"), + PINCTRL_PIN(TEGRA_PIN_PEX_L3_RST_N_PK7, "PEX_L3_RST_N_PK7"), + PINCTRL_PIN(TEGRA_PIN_PEX_L4_CLKREQ_N_PL0, "PEX_L4_CLKREQ_N_PL0"), + PINCTRL_PIN(TEGRA_PIN_PEX_L4_RST_N_PL1, "PEX_L4_RST_N_PL1"), + PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PL2, "PEX_WAKE_N_PL2"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO34_PL3, "SOC_GPIO34_PL3"), + PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH0_HPD_PM0, "DP_AUX_CH0_HPD_PM0"), + PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH1_HPD_PM1, "DP_AUX_CH1_HPD_PM1"), + PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH2_HPD_PM2, "DP_AUX_CH2_HPD_PM2"), + PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH3_HPD_PM3, "DP_AUX_CH3_HPD_PM3"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO55_PM4, "SOC_GPIO55_PM4"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO36_PM5, "SOC_GPIO36_PM5"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO53_PM6, "SOC_GPIO53_PM6"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO38_PM7, "SOC_GPIO38_PM7"), + PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH3_N_PN0, "DP_AUX_CH3_N_PN0"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO39_PN1, "SOC_GPIO39_PN1"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO40_PN2, "SOC_GPIO40_PN2"), + PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH1_P_PN3, "DP_AUX_CH1_P_PN3"), + PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH1_N_PN4, "DP_AUX_CH1_N_PN4"), + PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH2_P_PN5, "DP_AUX_CH2_P_PN5"), + PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH2_N_PN6, "DP_AUX_CH2_N_PN6"), + PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH3_P_PN7, "DP_AUX_CH3_P_PN7"), + PINCTRL_PIN(TEGRA_PIN_EXTPERIPH1_CLK_PP0, "EXTPERIPH1_CLK_PP0"), + PINCTRL_PIN(TEGRA_PIN_EXTPERIPH2_CLK_PP1, "EXTPERIPH2_CLK_PP1"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PP2, "CAM_I2C_SCL_PP2"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PP3, "CAM_I2C_SDA_PP3"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO23_PP4, "SOC_GPIO23_PP4"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO24_PP5, "SOC_GPIO24_PP5"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO25_PP6, "SOC_GPIO25_PP6"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PP7, "PWR_I2C_SCL_PP7"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PQ0, "PWR_I2C_SDA_PQ0"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO28_PQ1, "SOC_GPIO28_PQ1"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO29_PQ2, "SOC_GPIO29_PQ2"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO30_PQ3, "SOC_GPIO30_PQ3"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO31_PQ4, "SOC_GPIO31_PQ4"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO32_PQ5, "SOC_GPIO32_PQ5"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO33_PQ6, "SOC_GPIO33_PQ6"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO35_PQ7, "SOC_GPIO35_PQ7"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO37_PR0, "SOC_GPIO37_PR0"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO56_PR1, "SOC_GPIO56_PR1"), + PINCTRL_PIN(TEGRA_PIN_UART1_TX_PR2, "UART1_TX_PR2"), + PINCTRL_PIN(TEGRA_PIN_UART1_RX_PR3, "UART1_RX_PR3"), + PINCTRL_PIN(TEGRA_PIN_UART1_RTS_PR4, "UART1_RTS_PR4"), + PINCTRL_PIN(TEGRA_PIN_UART1_CTS_PR5, "UART1_CTS_PR5"), + PINCTRL_PIN(TEGRA_PIN_GPU_PWR_REQ_PX0, "GPU_PWR_REQ_PX0"), + PINCTRL_PIN(TEGRA_PIN_CV_PWR_REQ_PX1, "CV_PWR_REQ_PX1"), + PINCTRL_PIN(TEGRA_PIN_GP_PWM2_PX2, "GP_PWM2_PX2"), + PINCTRL_PIN(TEGRA_PIN_GP_PWM3_PX3, "GP_PWM3_PX3"), + PINCTRL_PIN(TEGRA_PIN_UART2_TX_PX4, "UART2_TX_PX4"), + PINCTRL_PIN(TEGRA_PIN_UART2_RX_PX5, "UART2_RX_PX5"), + PINCTRL_PIN(TEGRA_PIN_UART2_RTS_PX6, "UART2_RTS_PX6"), + PINCTRL_PIN(TEGRA_PIN_UART2_CTS_PX7, "UART2_CTS_PX7"), + PINCTRL_PIN(TEGRA_PIN_SPI3_SCK_PY0, "SPI3_SCK_PY0"), + PINCTRL_PIN(TEGRA_PIN_SPI3_MISO_PY1, "SPI3_MISO_PY1"), + PINCTRL_PIN(TEGRA_PIN_SPI3_MOSI_PY2, "SPI3_MOSI_PY2"), + PINCTRL_PIN(TEGRA_PIN_SPI3_CS0_PY3, "SPI3_CS0_PY3"), + PINCTRL_PIN(TEGRA_PIN_SPI3_CS1_PY4, "SPI3_CS1_PY4"), + PINCTRL_PIN(TEGRA_PIN_UART5_TX_PY5, "UART5_TX_PY5"), + PINCTRL_PIN(TEGRA_PIN_UART5_RX_PY6, "UART5_RX_PY6"), + PINCTRL_PIN(TEGRA_PIN_UART5_RTS_PY7, "UART5_RTS_PY7"), + PINCTRL_PIN(TEGRA_PIN_UART5_CTS_PZ0, "UART5_CTS_PZ0"), + PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PZ1, "USB_VBUS_EN0_PZ1"), + PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PZ2, "USB_VBUS_EN1_PZ2"), + PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PZ3, "SPI1_SCK_PZ3"), + PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PZ4, "SPI1_MISO_PZ4"), + PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PZ5, "SPI1_MOSI_PZ5"), + PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_PZ6, "SPI1_CS0_PZ6"), + PINCTRL_PIN(TEGRA_PIN_SPI1_CS1_PZ7, "SPI1_CS1_PZ7"), + PINCTRL_PIN(TEGRA_PIN_SPI5_SCK_PAC0, "SPI5_SCK_PAC0"), + PINCTRL_PIN(TEGRA_PIN_SPI5_MISO_PAC1, "SPI5_MISO_PAC1"), + PINCTRL_PIN(TEGRA_PIN_SPI5_MOSI_PAC2, "SPI5_MOSI_PAC2"), + PINCTRL_PIN(TEGRA_PIN_SPI5_CS0_PAC3, "SPI5_CS0_PAC3"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO57_PAC4, "SOC_GPIO57_PAC4"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO58_PAC5, "SOC_GPIO58_PAC5"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO59_PAC6, "SOC_GPIO59_PAC6"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO60_PAC7, "SOC_GPIO60_PAC7"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO45_PAD0, "SOC_GPIO45_PAD0"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO46_PAD1, "SOC_GPIO46_PAD1"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO47_PAD2, "SOC_GPIO47_PAD2"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO48_PAD3, "SOC_GPIO48_PAD3"), + PINCTRL_PIN(TEGRA_PIN_UFS0_REF_CLK_PAE0, "UFS0_REF_CLK_PAE0"), + PINCTRL_PIN(TEGRA_PIN_UFS0_RST_N_PAE1, "UFS0_RST_N_PAE1"), + PINCTRL_PIN(TEGRA_PIN_PEX_L5_CLKREQ_N_PAF0, "PEX_L5_CLKREQ_N_PAF0"), + PINCTRL_PIN(TEGRA_PIN_PEX_L5_RST_N_PAF1, "PEX_L5_RST_N_PAF1"), + PINCTRL_PIN(TEGRA_PIN_PEX_L6_CLKREQ_N_PAF2, "PEX_L6_CLKREQ_N_PAF2"), + PINCTRL_PIN(TEGRA_PIN_PEX_L6_RST_N_PAF3, "PEX_L6_RST_N_PAF3"), + PINCTRL_PIN(TEGRA_PIN_PEX_L7_CLKREQ_N_PAG0, "PEX_L7_CLKREQ_N_PAG0"), + PINCTRL_PIN(TEGRA_PIN_PEX_L7_RST_N_PAG1, "PEX_L7_RST_N_PAG1"), + PINCTRL_PIN(TEGRA_PIN_PEX_L8_CLKREQ_N_PAG2, "PEX_L8_CLKREQ_N_PAG2"), + PINCTRL_PIN(TEGRA_PIN_PEX_L8_RST_N_PAG3, "PEX_L8_RST_N_PAG3"), + PINCTRL_PIN(TEGRA_PIN_PEX_L9_CLKREQ_N_PAG4, "PEX_L9_CLKREQ_N_PAG4"), + PINCTRL_PIN(TEGRA_PIN_PEX_L9_RST_N_PAG5, "PEX_L9_RST_N_PAG5"), + PINCTRL_PIN(TEGRA_PIN_PEX_L10_CLKREQ_N_PAG6, "PEX_L10_CLKREQ_N_PAG6"), + PINCTRL_PIN(TEGRA_PIN_PEX_L10_RST_N_PAG7, "PEX_L10_RST_N_PAG7"), + PINCTRL_PIN(TEGRA_PIN_EQOS_COMP, "EQOS_COMP"), + PINCTRL_PIN(TEGRA_PIN_QSPI_COMP, "QSPI_COMP"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_COMP, "SDMMC1_COMP"), +}; + +static const unsigned int dap6_sclk_pa0_pins[] = { + TEGRA_PIN_DAP6_SCLK_PA0, +}; + +static const unsigned int dap6_dout_pa1_pins[] = { + TEGRA_PIN_DAP6_DOUT_PA1, +}; + +static const unsigned int dap6_din_pa2_pins[] = { + TEGRA_PIN_DAP6_DIN_PA2, +}; + +static const unsigned int dap6_fs_pa3_pins[] = { + TEGRA_PIN_DAP6_FS_PA3, +}; + +static const unsigned int dap4_sclk_pa4_pins[] = { + TEGRA_PIN_DAP4_SCLK_PA4, +}; + +static const unsigned int dap4_dout_pa5_pins[] = { + TEGRA_PIN_DAP4_DOUT_PA5, +}; + +static const unsigned int dap4_din_pa6_pins[] = { + TEGRA_PIN_DAP4_DIN_PA6, +}; + +static const unsigned int dap4_fs_pa7_pins[] = { + TEGRA_PIN_DAP4_FS_PA7, +}; + +static const unsigned int soc_gpio08_pb0_pins[] = { + TEGRA_PIN_SOC_GPIO08_PB0, +}; + +static const unsigned int qspi0_sck_pc0_pins[] = { + TEGRA_PIN_QSPI0_SCK_PC0, +}; + +static const unsigned int qspi0_cs_n_pc1_pins[] = { + TEGRA_PIN_QSPI0_CS_N_PC1, +}; + +static const unsigned int qspi0_io0_pc2_pins[] = { + TEGRA_PIN_QSPI0_IO0_PC2, +}; + +static const unsigned int qspi0_io1_pc3_pins[] = { + TEGRA_PIN_QSPI0_IO1_PC3, +}; + +static const unsigned int qspi0_io2_pc4_pins[] = { + TEGRA_PIN_QSPI0_IO2_PC4, +}; + +static const unsigned int qspi0_io3_pc5_pins[] = { + TEGRA_PIN_QSPI0_IO3_PC5, +}; + +static const unsigned int qspi1_sck_pc6_pins[] = { + TEGRA_PIN_QSPI1_SCK_PC6, +}; + +static const unsigned int qspi1_cs_n_pc7_pins[] = { + TEGRA_PIN_QSPI1_CS_N_PC7, +}; + +static const unsigned int qspi1_io0_pd0_pins[] = { + TEGRA_PIN_QSPI1_IO0_PD0, +}; + +static const unsigned int qspi1_io1_pd1_pins[] = { + TEGRA_PIN_QSPI1_IO1_PD1, +}; + +static const unsigned int qspi1_io2_pd2_pins[] = { + TEGRA_PIN_QSPI1_IO2_PD2, +}; + +static const unsigned int qspi1_io3_pd3_pins[] = { + TEGRA_PIN_QSPI1_IO3_PD3, +}; + +static const unsigned int eqos_txc_pe0_pins[] = { + TEGRA_PIN_EQOS_TXC_PE0, +}; + +static const unsigned int eqos_td0_pe1_pins[] = { + TEGRA_PIN_EQOS_TD0_PE1, +}; + +static const unsigned int eqos_td1_pe2_pins[] = { + TEGRA_PIN_EQOS_TD1_PE2, +}; + +static const unsigned int eqos_td2_pe3_pins[] = { + TEGRA_PIN_EQOS_TD2_PE3, +}; + +static const unsigned int eqos_td3_pe4_pins[] = { + TEGRA_PIN_EQOS_TD3_PE4, +}; + +static const unsigned int eqos_tx_ctl_pe5_pins[] = { + TEGRA_PIN_EQOS_TX_CTL_PE5, +}; + +static const unsigned int eqos_rd0_pe6_pins[] = { + TEGRA_PIN_EQOS_RD0_PE6, +}; + +static const unsigned int eqos_rd1_pe7_pins[] = { + TEGRA_PIN_EQOS_RD1_PE7, +}; + +static const unsigned int eqos_rd2_pf0_pins[] = { + TEGRA_PIN_EQOS_RD2_PF0, +}; + +static const unsigned int eqos_rd3_pf1_pins[] = { + TEGRA_PIN_EQOS_RD3_PF1, +}; + +static const unsigned int eqos_rx_ctl_pf2_pins[] = { + TEGRA_PIN_EQOS_RX_CTL_PF2, +}; + +static const unsigned int eqos_rxc_pf3_pins[] = { + TEGRA_PIN_EQOS_RXC_PF3, +}; + +static const unsigned int eqos_sma_mdio_pf4_pins[] = { + TEGRA_PIN_EQOS_SMA_MDIO_PF4, +}; + +static const unsigned int eqos_sma_mdc_pf5_pins[] = { + TEGRA_PIN_EQOS_SMA_MDC_PF5, +}; + +static const unsigned int soc_gpio13_pg0_pins[] = { + TEGRA_PIN_SOC_GPIO13_PG0, +}; + +static const unsigned int soc_gpio14_pg1_pins[] = { + TEGRA_PIN_SOC_GPIO14_PG1, +}; + +static const unsigned int soc_gpio15_pg2_pins[] = { + TEGRA_PIN_SOC_GPIO15_PG2, +}; + +static const unsigned int soc_gpio16_pg3_pins[] = { + TEGRA_PIN_SOC_GPIO16_PG3, +}; + +static const unsigned int soc_gpio17_pg4_pins[] = { + TEGRA_PIN_SOC_GPIO17_PG4, +}; + +static const unsigned int soc_gpio18_pg5_pins[] = { + TEGRA_PIN_SOC_GPIO18_PG5, +}; + +static const unsigned int soc_gpio19_pg6_pins[] = { + TEGRA_PIN_SOC_GPIO19_PG6, +}; + +static const unsigned int soc_gpio20_pg7_pins[] = { + TEGRA_PIN_SOC_GPIO20_PG7, +}; + +static const unsigned int soc_gpio21_ph0_pins[] = { + TEGRA_PIN_SOC_GPIO21_PH0, +}; + +static const unsigned int soc_gpio22_ph1_pins[] = { + TEGRA_PIN_SOC_GPIO22_PH1, +}; + +static const unsigned int soc_gpio06_ph2_pins[] = { + TEGRA_PIN_SOC_GPIO06_PH2, +}; + +static const unsigned int uart4_tx_ph3_pins[] = { + TEGRA_PIN_UART4_TX_PH3, +}; + +static const unsigned int uart4_rx_ph4_pins[] = { + TEGRA_PIN_UART4_RX_PH4, +}; + +static const unsigned int uart4_rts_ph5_pins[] = { + TEGRA_PIN_UART4_RTS_PH5, +}; + +static const unsigned int uart4_cts_ph6_pins[] = { + TEGRA_PIN_UART4_CTS_PH6, +}; + +static const unsigned int soc_gpio41_ph7_pins[] = { + TEGRA_PIN_SOC_GPIO41_PH7, +}; + +static const unsigned int soc_gpio42_pi0_pins[] = { + TEGRA_PIN_SOC_GPIO42_PI0, +}; + +static const unsigned int soc_gpio43_pi1_pins[] = { + TEGRA_PIN_SOC_GPIO43_PI1, +}; + +static const unsigned int soc_gpio44_pi2_pins[] = { + TEGRA_PIN_SOC_GPIO44_PI2, +}; + +static const unsigned int gen1_i2c_scl_pi3_pins[] = { + TEGRA_PIN_GEN1_I2C_SCL_PI3, +}; + +static const unsigned int gen1_i2c_sda_pi4_pins[] = { + TEGRA_PIN_GEN1_I2C_SDA_PI4, +}; + +static const unsigned int cpu_pwr_req_pi5_pins[] = { + TEGRA_PIN_CPU_PWR_REQ_PI5, +}; + +static const unsigned int soc_gpio07_pi6_pins[] = { + TEGRA_PIN_SOC_GPIO07_PI6, +}; + +static const unsigned int sdmmc1_clk_pj0_pins[] = { + TEGRA_PIN_SDMMC1_CLK_PJ0, +}; + +static const unsigned int sdmmc1_cmd_pj1_pins[] = { + TEGRA_PIN_SDMMC1_CMD_PJ1, +}; + +static const unsigned int sdmmc1_dat0_pj2_pins[] = { + TEGRA_PIN_SDMMC1_DAT0_PJ2, +}; + +static const unsigned int sdmmc1_dat1_pj3_pins[] = { + TEGRA_PIN_SDMMC1_DAT1_PJ3, +}; + +static const unsigned int sdmmc1_dat2_pj4_pins[] = { + TEGRA_PIN_SDMMC1_DAT2_PJ4, +}; + +static const unsigned int sdmmc1_dat3_pj5_pins[] = { + TEGRA_PIN_SDMMC1_DAT3_PJ5, +}; + +static const unsigned int pex_l0_clkreq_n_pk0_pins[] = { + TEGRA_PIN_PEX_L0_CLKREQ_N_PK0, +}; + +static const unsigned int pex_l0_rst_n_pk1_pins[] = { + TEGRA_PIN_PEX_L0_RST_N_PK1, +}; + +static const unsigned int pex_l1_clkreq_n_pk2_pins[] = { + TEGRA_PIN_PEX_L1_CLKREQ_N_PK2, +}; + +static const unsigned int pex_l1_rst_n_pk3_pins[] = { + TEGRA_PIN_PEX_L1_RST_N_PK3, +}; + +static const unsigned int pex_l2_clkreq_n_pk4_pins[] = { + TEGRA_PIN_PEX_L2_CLKREQ_N_PK4, +}; + +static const unsigned int pex_l2_rst_n_pk5_pins[] = { + TEGRA_PIN_PEX_L2_RST_N_PK5, +}; + +static const unsigned int pex_l3_clkreq_n_pk6_pins[] = { + TEGRA_PIN_PEX_L3_CLKREQ_N_PK6, +}; + +static const unsigned int pex_l3_rst_n_pk7_pins[] = { + TEGRA_PIN_PEX_L3_RST_N_PK7, +}; + +static const unsigned int pex_l4_clkreq_n_pl0_pins[] = { + TEGRA_PIN_PEX_L4_CLKREQ_N_PL0, +}; + +static const unsigned int pex_l4_rst_n_pl1_pins[] = { + TEGRA_PIN_PEX_L4_RST_N_PL1, +}; + +static const unsigned int pex_wake_n_pl2_pins[] = { + TEGRA_PIN_PEX_WAKE_N_PL2, +}; + +static const unsigned int soc_gpio34_pl3_pins[] = { + TEGRA_PIN_SOC_GPIO34_PL3, +}; + +static const unsigned int dp_aux_ch0_hpd_pm0_pins[] = { + TEGRA_PIN_DP_AUX_CH0_HPD_PM0, +}; + +static const unsigned int dp_aux_ch1_hpd_pm1_pins[] = { + TEGRA_PIN_DP_AUX_CH1_HPD_PM1, +}; + +static const unsigned int dp_aux_ch2_hpd_pm2_pins[] = { + TEGRA_PIN_DP_AUX_CH2_HPD_PM2, +}; + +static const unsigned int dp_aux_ch3_hpd_pm3_pins[] = { + TEGRA_PIN_DP_AUX_CH3_HPD_PM3, +}; + +static const unsigned int soc_gpio55_pm4_pins[] = { + TEGRA_PIN_SOC_GPIO55_PM4, +}; + +static const unsigned int soc_gpio36_pm5_pins[] = { + TEGRA_PIN_SOC_GPIO36_PM5, +}; + +static const unsigned int soc_gpio53_pm6_pins[] = { + TEGRA_PIN_SOC_GPIO53_PM6, +}; + +static const unsigned int soc_gpio38_pm7_pins[] = { + TEGRA_PIN_SOC_GPIO38_PM7, +}; + +static const unsigned int dp_aux_ch3_n_pn0_pins[] = { + TEGRA_PIN_DP_AUX_CH3_N_PN0, +}; + +static const unsigned int soc_gpio39_pn1_pins[] = { + TEGRA_PIN_SOC_GPIO39_PN1, +}; + +static const unsigned int soc_gpio40_pn2_pins[] = { + TEGRA_PIN_SOC_GPIO40_PN2, +}; + +static const unsigned int dp_aux_ch1_p_pn3_pins[] = { + TEGRA_PIN_DP_AUX_CH1_P_PN3, +}; + +static const unsigned int dp_aux_ch1_n_pn4_pins[] = { + TEGRA_PIN_DP_AUX_CH1_N_PN4, +}; + +static const unsigned int dp_aux_ch2_p_pn5_pins[] = { + TEGRA_PIN_DP_AUX_CH2_P_PN5, +}; + +static const unsigned int dp_aux_ch2_n_pn6_pins[] = { + TEGRA_PIN_DP_AUX_CH2_N_PN6, +}; + +static const unsigned int dp_aux_ch3_p_pn7_pins[] = { + TEGRA_PIN_DP_AUX_CH3_P_PN7, +}; + +static const unsigned int extperiph1_clk_pp0_pins[] = { + TEGRA_PIN_EXTPERIPH1_CLK_PP0, +}; + +static const unsigned int extperiph2_clk_pp1_pins[] = { + TEGRA_PIN_EXTPERIPH2_CLK_PP1, +}; + +static const unsigned int cam_i2c_scl_pp2_pins[] = { + TEGRA_PIN_CAM_I2C_SCL_PP2, +}; + +static const unsigned int cam_i2c_sda_pp3_pins[] = { + TEGRA_PIN_CAM_I2C_SDA_PP3, +}; + +static const unsigned int soc_gpio23_pp4_pins[] = { + TEGRA_PIN_SOC_GPIO23_PP4, +}; + +static const unsigned int soc_gpio24_pp5_pins[] = { + TEGRA_PIN_SOC_GPIO24_PP5, +}; + +static const unsigned int soc_gpio25_pp6_pins[] = { + TEGRA_PIN_SOC_GPIO25_PP6, +}; + +static const unsigned int pwr_i2c_scl_pp7_pins[] = { + TEGRA_PIN_PWR_I2C_SCL_PP7, +}; + +static const unsigned int pwr_i2c_sda_pq0_pins[] = { + TEGRA_PIN_PWR_I2C_SDA_PQ0, +}; + +static const unsigned int soc_gpio28_pq1_pins[] = { + TEGRA_PIN_SOC_GPIO28_PQ1, +}; + +static const unsigned int soc_gpio29_pq2_pins[] = { + TEGRA_PIN_SOC_GPIO29_PQ2, +}; + +static const unsigned int soc_gpio30_pq3_pins[] = { + TEGRA_PIN_SOC_GPIO30_PQ3, +}; + +static const unsigned int soc_gpio31_pq4_pins[] = { + TEGRA_PIN_SOC_GPIO31_PQ4, +}; + +static const unsigned int soc_gpio32_pq5_pins[] = { + TEGRA_PIN_SOC_GPIO32_PQ5, +}; + +static const unsigned int soc_gpio33_pq6_pins[] = { + TEGRA_PIN_SOC_GPIO33_PQ6, +}; + +static const unsigned int soc_gpio35_pq7_pins[] = { + TEGRA_PIN_SOC_GPIO35_PQ7, +}; + +static const unsigned int soc_gpio37_pr0_pins[] = { + TEGRA_PIN_SOC_GPIO37_PR0, +}; + +static const unsigned int soc_gpio56_pr1_pins[] = { + TEGRA_PIN_SOC_GPIO56_PR1, +}; + +static const unsigned int uart1_tx_pr2_pins[] = { + TEGRA_PIN_UART1_TX_PR2, +}; + +static const unsigned int uart1_rx_pr3_pins[] = { + TEGRA_PIN_UART1_RX_PR3, +}; + +static const unsigned int uart1_rts_pr4_pins[] = { + TEGRA_PIN_UART1_RTS_PR4, +}; + +static const unsigned int uart1_cts_pr5_pins[] = { + TEGRA_PIN_UART1_CTS_PR5, +}; + +static const unsigned int gpu_pwr_req_px0_pins[] = { + TEGRA_PIN_GPU_PWR_REQ_PX0, +}; + +static const unsigned int cv_pwr_req_px1_pins[] = { + TEGRA_PIN_CV_PWR_REQ_PX1, +}; + +static const unsigned int gp_pwm2_px2_pins[] = { + TEGRA_PIN_GP_PWM2_PX2, +}; + +static const unsigned int gp_pwm3_px3_pins[] = { + TEGRA_PIN_GP_PWM3_PX3, +}; + +static const unsigned int uart2_tx_px4_pins[] = { + TEGRA_PIN_UART2_TX_PX4, +}; + +static const unsigned int uart2_rx_px5_pins[] = { + TEGRA_PIN_UART2_RX_PX5, +}; + +static const unsigned int uart2_rts_px6_pins[] = { + TEGRA_PIN_UART2_RTS_PX6, +}; + +static const unsigned int uart2_cts_px7_pins[] = { + TEGRA_PIN_UART2_CTS_PX7, +}; + +static const unsigned int spi3_sck_py0_pins[] = { + TEGRA_PIN_SPI3_SCK_PY0, +}; + +static const unsigned int spi3_miso_py1_pins[] = { + TEGRA_PIN_SPI3_MISO_PY1, +}; + +static const unsigned int spi3_mosi_py2_pins[] = { + TEGRA_PIN_SPI3_MOSI_PY2, +}; + +static const unsigned int spi3_cs0_py3_pins[] = { + TEGRA_PIN_SPI3_CS0_PY3, +}; + +static const unsigned int spi3_cs1_py4_pins[] = { + TEGRA_PIN_SPI3_CS1_PY4, +}; + +static const unsigned int uart5_tx_py5_pins[] = { + TEGRA_PIN_UART5_TX_PY5, +}; + +static const unsigned int uart5_rx_py6_pins[] = { + TEGRA_PIN_UART5_RX_PY6, +}; + +static const unsigned int uart5_rts_py7_pins[] = { + TEGRA_PIN_UART5_RTS_PY7, +}; + +static const unsigned int uart5_cts_pz0_pins[] = { + TEGRA_PIN_UART5_CTS_PZ0, +}; + +static const unsigned int usb_vbus_en0_pz1_pins[] = { + TEGRA_PIN_USB_VBUS_EN0_PZ1, +}; + +static const unsigned int usb_vbus_en1_pz2_pins[] = { + TEGRA_PIN_USB_VBUS_EN1_PZ2, +}; + +static const unsigned int spi1_sck_pz3_pins[] = { + TEGRA_PIN_SPI1_SCK_PZ3, +}; + +static const unsigned int spi1_miso_pz4_pins[] = { + TEGRA_PIN_SPI1_MISO_PZ4, +}; + +static const unsigned int spi1_mosi_pz5_pins[] = { + TEGRA_PIN_SPI1_MOSI_PZ5, +}; + +static const unsigned int spi1_cs0_pz6_pins[] = { + TEGRA_PIN_SPI1_CS0_PZ6, +}; + +static const unsigned int spi1_cs1_pz7_pins[] = { + TEGRA_PIN_SPI1_CS1_PZ7, +}; + +static const unsigned int can0_dout_paa0_pins[] = { + TEGRA_PIN_CAN0_DOUT_PAA0, +}; + +static const unsigned int can0_din_paa1_pins[] = { + TEGRA_PIN_CAN0_DIN_PAA1, +}; + +static const unsigned int can1_dout_paa2_pins[] = { + TEGRA_PIN_CAN1_DOUT_PAA2, +}; + +static const unsigned int can1_din_paa3_pins[] = { + TEGRA_PIN_CAN1_DIN_PAA3, +}; + +static const unsigned int can0_stb_paa4_pins[] = { + TEGRA_PIN_CAN0_STB_PAA4, +}; + +static const unsigned int can0_en_paa5_pins[] = { + TEGRA_PIN_CAN0_EN_PAA5, +}; + +static const unsigned int soc_gpio49_paa6_pins[] = { + TEGRA_PIN_SOC_GPIO49_PAA6, +}; + +static const unsigned int can0_err_paa7_pins[] = { + TEGRA_PIN_CAN0_ERR_PAA7, +}; + +static const unsigned int spi5_sck_pac0_pins[] = { + TEGRA_PIN_SPI5_SCK_PAC0, +}; + +static const unsigned int spi5_miso_pac1_pins[] = { + TEGRA_PIN_SPI5_MISO_PAC1, +}; + +static const unsigned int spi5_mosi_pac2_pins[] = { + TEGRA_PIN_SPI5_MOSI_PAC2, +}; + +static const unsigned int spi5_cs0_pac3_pins[] = { + TEGRA_PIN_SPI5_CS0_PAC3, +}; + +static const unsigned int soc_gpio57_pac4_pins[] = { + TEGRA_PIN_SOC_GPIO57_PAC4, +}; + +static const unsigned int soc_gpio58_pac5_pins[] = { + TEGRA_PIN_SOC_GPIO58_PAC5, +}; + +static const unsigned int soc_gpio59_pac6_pins[] = { + TEGRA_PIN_SOC_GPIO59_PAC6, +}; + +static const unsigned int soc_gpio60_pac7_pins[] = { + TEGRA_PIN_SOC_GPIO60_PAC7, +}; + +static const unsigned int soc_gpio45_pad0_pins[] = { + TEGRA_PIN_SOC_GPIO45_PAD0, +}; + +static const unsigned int soc_gpio46_pad1_pins[] = { + TEGRA_PIN_SOC_GPIO46_PAD1, +}; + +static const unsigned int soc_gpio47_pad2_pins[] = { + TEGRA_PIN_SOC_GPIO47_PAD2, +}; + +static const unsigned int soc_gpio48_pad3_pins[] = { + TEGRA_PIN_SOC_GPIO48_PAD3, +}; + +static const unsigned int ufs0_ref_clk_pae0_pins[] = { + TEGRA_PIN_UFS0_REF_CLK_PAE0, +}; + +static const unsigned int ufs0_rst_n_pae1_pins[] = { + TEGRA_PIN_UFS0_RST_N_PAE1, +}; + +static const unsigned int pex_l5_clkreq_n_paf0_pins[] = { + TEGRA_PIN_PEX_L5_CLKREQ_N_PAF0, +}; + +static const unsigned int pex_l5_rst_n_paf1_pins[] = { + TEGRA_PIN_PEX_L5_RST_N_PAF1, +}; + +static const unsigned int pex_l6_clkreq_n_paf2_pins[] = { + TEGRA_PIN_PEX_L6_CLKREQ_N_PAF2, +}; + +static const unsigned int pex_l6_rst_n_paf3_pins[] = { + TEGRA_PIN_PEX_L6_RST_N_PAF3, +}; + +static const unsigned int pex_l7_clkreq_n_pag0_pins[] = { + TEGRA_PIN_PEX_L7_CLKREQ_N_PAG0, +}; + +static const unsigned int pex_l7_rst_n_pag1_pins[] = { + TEGRA_PIN_PEX_L7_RST_N_PAG1, +}; + +static const unsigned int pex_l8_clkreq_n_pag2_pins[] = { + TEGRA_PIN_PEX_L8_CLKREQ_N_PAG2, +}; + +static const unsigned int pex_l8_rst_n_pag3_pins[] = { + TEGRA_PIN_PEX_L8_RST_N_PAG3, +}; + +static const unsigned int pex_l9_clkreq_n_pag4_pins[] = { + TEGRA_PIN_PEX_L9_CLKREQ_N_PAG4, +}; + +static const unsigned int pex_l9_rst_n_pag5_pins[] = { + TEGRA_PIN_PEX_L9_RST_N_PAG5, +}; + +static const unsigned int pex_l10_clkreq_n_pag6_pins[] = { + TEGRA_PIN_PEX_L10_CLKREQ_N_PAG6, +}; + +static const unsigned int pex_l10_rst_n_pag7_pins[] = { + TEGRA_PIN_PEX_L10_RST_N_PAG7, +}; + +static const unsigned int can1_stb_pbb0_pins[] = { + TEGRA_PIN_CAN1_STB_PBB0, +}; + +static const unsigned int can1_en_pbb1_pins[] = { + TEGRA_PIN_CAN1_EN_PBB1, +}; + +static const unsigned int soc_gpio50_pbb2_pins[] = { + TEGRA_PIN_SOC_GPIO50_PBB2, +}; + +static const unsigned int can1_err_pbb3_pins[] = { + TEGRA_PIN_CAN1_ERR_PBB3, +}; + +static const unsigned int spi2_sck_pcc0_pins[] = { + TEGRA_PIN_SPI2_SCK_PCC0, +}; + +static const unsigned int spi2_miso_pcc1_pins[] = { + TEGRA_PIN_SPI2_MISO_PCC1, +}; + +static const unsigned int spi2_mosi_pcc2_pins[] = { + TEGRA_PIN_SPI2_MOSI_PCC2, +}; + +static const unsigned int spi2_cs0_pcc3_pins[] = { + TEGRA_PIN_SPI2_CS0_PCC3, +}; + +static const unsigned int touch_clk_pcc4_pins[] = { + TEGRA_PIN_TOUCH_CLK_PCC4, +}; + +static const unsigned int uart3_tx_pcc5_pins[] = { + TEGRA_PIN_UART3_TX_PCC5, +}; + +static const unsigned int uart3_rx_pcc6_pins[] = { + TEGRA_PIN_UART3_RX_PCC6, +}; + +static const unsigned int gen2_i2c_scl_pcc7_pins[] = { + TEGRA_PIN_GEN2_I2C_SCL_PCC7, +}; + +static const unsigned int gen2_i2c_sda_pdd0_pins[] = { + TEGRA_PIN_GEN2_I2C_SDA_PDD0, +}; + +static const unsigned int gen8_i2c_scl_pdd1_pins[] = { + TEGRA_PIN_GEN8_I2C_SCL_PDD1, +}; + +static const unsigned int gen8_i2c_sda_pdd2_pins[] = { + TEGRA_PIN_GEN8_I2C_SDA_PDD2, +}; + +static const unsigned int sce_error_pee0_pins[] = { + TEGRA_PIN_SCE_ERROR_PEE0, +}; + +static const unsigned int vcomp_alert_pee1_pins[] = { + TEGRA_PIN_VCOMP_ALERT_PEE1, +}; + +static const unsigned int ao_retention_n_pee2_pins[] = { + TEGRA_PIN_AO_RETENTION_N_PEE2, +}; + +static const unsigned int batt_oc_pee3_pins[] = { + TEGRA_PIN_BATT_OC_PEE3, +}; + +static const unsigned int power_on_pee4_pins[] = { + TEGRA_PIN_POWER_ON_PEE4, +}; + +static const unsigned int soc_gpio26_pee5_pins[] = { + TEGRA_PIN_SOC_GPIO26_PEE5, +}; + +static const unsigned int soc_gpio27_pee6_pins[] = { + TEGRA_PIN_SOC_GPIO27_PEE6, +}; + +static const unsigned int bootv_ctl_n_pee7_pins[] = { + TEGRA_PIN_BOOTV_CTL_N_PEE7, +}; + +static const unsigned int hdmi_cec_pgg0_pins[] = { + TEGRA_PIN_HDMI_CEC_PGG0, +}; + +static const unsigned int eqos_comp_pins[] = { + TEGRA_PIN_EQOS_COMP, +}; + +static const unsigned int qspi_comp_pins[] = { + TEGRA_PIN_QSPI_COMP, +}; + +static const unsigned int sdmmc1_comp_pins[] = { + TEGRA_PIN_SDMMC1_COMP, +}; + +/* Define unique ID for each function */ +enum tegra_mux_dt { + TEGRA_MUX_GP, + TEGRA_MUX_UARTC, + TEGRA_MUX_I2C8, + TEGRA_MUX_SPI2, + TEGRA_MUX_I2C2, + TEGRA_MUX_CAN1, + TEGRA_MUX_CAN0, + TEGRA_MUX_RSVD0, + TEGRA_MUX_ETH0, + TEGRA_MUX_ETH2, + TEGRA_MUX_ETH1, + TEGRA_MUX_DP, + TEGRA_MUX_ETH3, + TEGRA_MUX_I2C4, + TEGRA_MUX_I2C7, + TEGRA_MUX_I2C9, + TEGRA_MUX_EQOS, + TEGRA_MUX_PE2, + TEGRA_MUX_PE1, + TEGRA_MUX_PE0, + TEGRA_MUX_PE3, + TEGRA_MUX_PE4, + TEGRA_MUX_PE5, + TEGRA_MUX_PE6, + TEGRA_MUX_PE10, + TEGRA_MUX_PE7, + TEGRA_MUX_PE8, + TEGRA_MUX_PE9, + TEGRA_MUX_QSPI0, + TEGRA_MUX_QSPI1, + TEGRA_MUX_QSPI, + TEGRA_MUX_SDMMC1, + TEGRA_MUX_SCE, + TEGRA_MUX_SOC, + TEGRA_MUX_GPIO, + TEGRA_MUX_HDMI, + TEGRA_MUX_UFS0, + TEGRA_MUX_SPI3, + TEGRA_MUX_SPI1, + TEGRA_MUX_UARTB, + TEGRA_MUX_UARTE, + TEGRA_MUX_USB, + TEGRA_MUX_EXTPERIPH2, + TEGRA_MUX_EXTPERIPH1, + TEGRA_MUX_I2C3, + TEGRA_MUX_VI0, + TEGRA_MUX_I2C5, + TEGRA_MUX_UARTA, + TEGRA_MUX_UARTD, + TEGRA_MUX_I2C1, + TEGRA_MUX_I2S4, + TEGRA_MUX_I2S6, + TEGRA_MUX_AUD, + TEGRA_MUX_SPI5, + TEGRA_MUX_TOUCH, + TEGRA_MUX_UARTJ, + TEGRA_MUX_RSVD1, + TEGRA_MUX_WDT, + TEGRA_MUX_TSC, + TEGRA_MUX_DMIC3, + TEGRA_MUX_LED, + TEGRA_MUX_VI0_ALT, + TEGRA_MUX_I2S5, + TEGRA_MUX_NV, + TEGRA_MUX_EXTPERIPH3, + TEGRA_MUX_EXTPERIPH4, + TEGRA_MUX_SPI4, + TEGRA_MUX_CCLA, + TEGRA_MUX_I2S2, + TEGRA_MUX_I2S1, + TEGRA_MUX_I2S8, + TEGRA_MUX_I2S3, + TEGRA_MUX_RSVD2, + TEGRA_MUX_DMIC5, + TEGRA_MUX_DCA, + TEGRA_MUX_DISPLAYB, + TEGRA_MUX_DISPLAYA, + TEGRA_MUX_VI1, + TEGRA_MUX_DCB, + TEGRA_MUX_DMIC1, + TEGRA_MUX_DMIC4, + TEGRA_MUX_I2S7, + TEGRA_MUX_DMIC2, + TEGRA_MUX_DSPK0, + TEGRA_MUX_RSVD3, + TEGRA_MUX_TSC_ALT, + TEGRA_MUX_ISTCTRL, + TEGRA_MUX_VI1_ALT, + TEGRA_MUX_DSPK1, + TEGRA_MUX_IGPU, +}; + +/* Make list of each function name */ +#define TEGRA_PIN_FUNCTION(lid) #lid + +static const char * const tegra234_functions[] = { + TEGRA_PIN_FUNCTION(gp), + TEGRA_PIN_FUNCTION(uartc), + TEGRA_PIN_FUNCTION(i2c8), + TEGRA_PIN_FUNCTION(spi2), + TEGRA_PIN_FUNCTION(i2c2), + TEGRA_PIN_FUNCTION(can1), + TEGRA_PIN_FUNCTION(can0), + TEGRA_PIN_FUNCTION(rsvd0), + TEGRA_PIN_FUNCTION(eth0), + TEGRA_PIN_FUNCTION(eth2), + TEGRA_PIN_FUNCTION(eth1), + TEGRA_PIN_FUNCTION(dp), + TEGRA_PIN_FUNCTION(eth3), + TEGRA_PIN_FUNCTION(i2c4), + TEGRA_PIN_FUNCTION(i2c7), + TEGRA_PIN_FUNCTION(i2c9), + TEGRA_PIN_FUNCTION(eqos), + TEGRA_PIN_FUNCTION(pe2), + TEGRA_PIN_FUNCTION(pe1), + TEGRA_PIN_FUNCTION(pe0), + TEGRA_PIN_FUNCTION(pe3), + TEGRA_PIN_FUNCTION(pe4), + TEGRA_PIN_FUNCTION(pe5), + TEGRA_PIN_FUNCTION(pe6), + TEGRA_PIN_FUNCTION(pe10), + TEGRA_PIN_FUNCTION(pe7), + TEGRA_PIN_FUNCTION(pe8), + TEGRA_PIN_FUNCTION(pe9), + TEGRA_PIN_FUNCTION(qspi0), + TEGRA_PIN_FUNCTION(qspi1), + TEGRA_PIN_FUNCTION(qspi), + TEGRA_PIN_FUNCTION(sdmmc1), + TEGRA_PIN_FUNCTION(sce), + TEGRA_PIN_FUNCTION(soc), + TEGRA_PIN_FUNCTION(gpio), + TEGRA_PIN_FUNCTION(hdmi), + TEGRA_PIN_FUNCTION(ufs0), + TEGRA_PIN_FUNCTION(spi3), + TEGRA_PIN_FUNCTION(spi1), + TEGRA_PIN_FUNCTION(uartb), + TEGRA_PIN_FUNCTION(uarte), + TEGRA_PIN_FUNCTION(usb), + TEGRA_PIN_FUNCTION(extperiph2), + TEGRA_PIN_FUNCTION(extperiph1), + TEGRA_PIN_FUNCTION(i2c3), + TEGRA_PIN_FUNCTION(vi0), + TEGRA_PIN_FUNCTION(i2c5), + TEGRA_PIN_FUNCTION(uarta), + TEGRA_PIN_FUNCTION(uartd), + TEGRA_PIN_FUNCTION(i2c1), + TEGRA_PIN_FUNCTION(i2s4), + TEGRA_PIN_FUNCTION(i2s6), + TEGRA_PIN_FUNCTION(aud), + TEGRA_PIN_FUNCTION(spi5), + TEGRA_PIN_FUNCTION(touch), + TEGRA_PIN_FUNCTION(uartj), + TEGRA_PIN_FUNCTION(rsvd1), + TEGRA_PIN_FUNCTION(wdt), + TEGRA_PIN_FUNCTION(tsc), + TEGRA_PIN_FUNCTION(dmic3), + TEGRA_PIN_FUNCTION(led), + TEGRA_PIN_FUNCTION(vi0_alt), + TEGRA_PIN_FUNCTION(i2s5), + TEGRA_PIN_FUNCTION(nv), + TEGRA_PIN_FUNCTION(extperiph3), + TEGRA_PIN_FUNCTION(extperiph4), + TEGRA_PIN_FUNCTION(spi4), + TEGRA_PIN_FUNCTION(ccla), + TEGRA_PIN_FUNCTION(i2s2), + TEGRA_PIN_FUNCTION(i2s1), + TEGRA_PIN_FUNCTION(i2s8), + TEGRA_PIN_FUNCTION(i2s3), + TEGRA_PIN_FUNCTION(rsvd2), + TEGRA_PIN_FUNCTION(dmic5), + TEGRA_PIN_FUNCTION(dca), + TEGRA_PIN_FUNCTION(displayb), + TEGRA_PIN_FUNCTION(displaya), + TEGRA_PIN_FUNCTION(vi1), + TEGRA_PIN_FUNCTION(dcb), + TEGRA_PIN_FUNCTION(dmic1), + TEGRA_PIN_FUNCTION(dmic4), + TEGRA_PIN_FUNCTION(i2s7), + TEGRA_PIN_FUNCTION(dmic2), + TEGRA_PIN_FUNCTION(dspk0), + TEGRA_PIN_FUNCTION(rsvd3), + TEGRA_PIN_FUNCTION(tsc_alt), + TEGRA_PIN_FUNCTION(istctrl), + TEGRA_PIN_FUNCTION(vi1_alt), + TEGRA_PIN_FUNCTION(dspk1), + TEGRA_PIN_FUNCTION(igpu), +}; + +#define PINGROUP_REG_Y(r) ((r)) +#define PINGROUP_REG_N(r) -1 + +#define DRV_PINGROUP_Y(r) ((r)) +#define DRV_PINGROUP_N(r) -1 + +#define DRV_PINGROUP_ENTRY_N(pg_name) \ + .drv_reg = -1, \ + .drv_bank = -1, \ + .drvdn_bit = -1, \ + .drvup_bit = -1, \ + .slwr_bit = -1, \ + .slwf_bit = -1 + +#define DRV_PINGROUP_ENTRY_Y(r, drvdn_b, drvdn_w, drvup_b, \ + drvup_w, slwr_b, slwr_w, slwf_b, \ + slwf_w, bank) \ + .drv_reg = DRV_PINGROUP_Y(r), \ + .drv_bank = bank, \ + .drvdn_bit = drvdn_b, \ + .drvdn_width = drvdn_w, \ + .drvup_bit = drvup_b, \ + .drvup_width = drvup_w, \ + .slwr_bit = slwr_b, \ + .slwr_width = slwr_w, \ + .slwf_bit = slwf_b, \ + .slwf_width = slwf_w + +#define PIN_PINGROUP_ENTRY_N(pg_name) \ + .mux_reg = -1, \ + .pupd_reg = -1, \ + .tri_reg = -1, \ + .einput_bit = -1, \ + .e_io_hv_bit = -1, \ + .odrain_bit = -1, \ + .lock_bit = -1, \ + .parked_bit = -1, \ + .lpmd_bit = -1, \ + .drvtype_bit = -1, \ + .lpdr_bit = -1, \ + .pbias_buf_bit = -1, \ + .preemp_bit = -1, \ + .rfu_in_bit = -1 + +#define PIN_PINGROUP_ENTRY_Y(r, bank, pupd, e_io_hv, e_lpbk, e_input, \ + e_lpdr, e_pbias_buf, gpio_sfio_sel, \ + schmitt_b) \ + .mux_reg = PINGROUP_REG_Y(r), \ + .lpmd_bit = -1, \ + .lock_bit = -1, \ + .hsm_bit = -1, \ + .mux_bank = bank, \ + .mux_bit = 0, \ + .pupd_reg = PINGROUP_REG_##pupd(r), \ + .pupd_bank = bank, \ + .pupd_bit = 2, \ + .tri_reg = PINGROUP_REG_Y(r), \ + .tri_bank = bank, \ + .tri_bit = 4, \ + .einput_bit = e_input, \ + .sfsel_bit = gpio_sfio_sel, \ + .schmitt_bit = schmitt_b, \ + .drvtype_bit = 13, \ + .lpdr_bit = e_lpdr, \ + +/* main drive pin groups */ +#define drive_soc_gpio08_pb0 DRV_PINGROUP_ENTRY_Y(0x500c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio36_pm5 DRV_PINGROUP_ENTRY_Y(0x10004, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio53_pm6 DRV_PINGROUP_ENTRY_Y(0x1000c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio55_pm4 DRV_PINGROUP_ENTRY_Y(0x10014, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio38_pm7 DRV_PINGROUP_ENTRY_Y(0x1001c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio39_pn1 DRV_PINGROUP_ENTRY_Y(0x10024, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio40_pn2 DRV_PINGROUP_ENTRY_Y(0x1002c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dp_aux_ch0_hpd_pm0 DRV_PINGROUP_ENTRY_Y(0x10034, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dp_aux_ch1_hpd_pm1 DRV_PINGROUP_ENTRY_Y(0x1003c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dp_aux_ch2_hpd_pm2 DRV_PINGROUP_ENTRY_Y(0x10044, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dp_aux_ch3_hpd_pm3 DRV_PINGROUP_ENTRY_Y(0x1004c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dp_aux_ch1_p_pn3 DRV_PINGROUP_ENTRY_Y(0x10054, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dp_aux_ch1_n_pn4 DRV_PINGROUP_ENTRY_Y(0x1005c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dp_aux_ch2_p_pn5 DRV_PINGROUP_ENTRY_Y(0x10064, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dp_aux_ch2_n_pn6 DRV_PINGROUP_ENTRY_Y(0x1006c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dp_aux_ch3_p_pn7 DRV_PINGROUP_ENTRY_Y(0x10074, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dp_aux_ch3_n_pn0 DRV_PINGROUP_ENTRY_Y(0x1007c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l2_clkreq_n_pk4 DRV_PINGROUP_ENTRY_Y(0x7004, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_wake_n_pl2 DRV_PINGROUP_ENTRY_Y(0x700c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l1_clkreq_n_pk2 DRV_PINGROUP_ENTRY_Y(0x7014, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l1_rst_n_pk3 DRV_PINGROUP_ENTRY_Y(0x701c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l0_clkreq_n_pk0 DRV_PINGROUP_ENTRY_Y(0x7024, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l0_rst_n_pk1 DRV_PINGROUP_ENTRY_Y(0x702c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l2_rst_n_pk5 DRV_PINGROUP_ENTRY_Y(0x7034, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l3_clkreq_n_pk6 DRV_PINGROUP_ENTRY_Y(0x703c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l3_rst_n_pk7 DRV_PINGROUP_ENTRY_Y(0x7044, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l4_clkreq_n_pl0 DRV_PINGROUP_ENTRY_Y(0x704c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l4_rst_n_pl1 DRV_PINGROUP_ENTRY_Y(0x7054, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio34_pl3 DRV_PINGROUP_ENTRY_Y(0x705c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l5_clkreq_n_paf0 DRV_PINGROUP_ENTRY_Y(0x14004, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l5_rst_n_paf1 DRV_PINGROUP_ENTRY_Y(0x1400c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l6_clkreq_n_paf2 DRV_PINGROUP_ENTRY_Y(0x14014, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l6_rst_n_paf3 DRV_PINGROUP_ENTRY_Y(0x1401c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l10_clkreq_n_pag6 DRV_PINGROUP_ENTRY_Y(0x19004, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l10_rst_n_pag7 DRV_PINGROUP_ENTRY_Y(0x1900c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l7_clkreq_n_pag0 DRV_PINGROUP_ENTRY_Y(0x19014, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l7_rst_n_pag1 DRV_PINGROUP_ENTRY_Y(0x1901c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l8_clkreq_n_pag2 DRV_PINGROUP_ENTRY_Y(0x19024, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l8_rst_n_pag3 DRV_PINGROUP_ENTRY_Y(0x1902c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l9_clkreq_n_pag4 DRV_PINGROUP_ENTRY_Y(0x19034, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l9_rst_n_pag5 DRV_PINGROUP_ENTRY_Y(0x1903c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_sdmmc1_clk_pj0 DRV_PINGROUP_ENTRY_Y(0x8004, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_sdmmc1_cmd_pj1 DRV_PINGROUP_ENTRY_Y(0x800c, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_sdmmc1_dat3_pj5 DRV_PINGROUP_ENTRY_Y(0x801c, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_sdmmc1_dat2_pj4 DRV_PINGROUP_ENTRY_Y(0x8024, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_sdmmc1_dat1_pj3 DRV_PINGROUP_ENTRY_Y(0x802c, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_sdmmc1_dat0_pj2 DRV_PINGROUP_ENTRY_Y(0x8034, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_ufs0_rst_n_pae1 DRV_PINGROUP_ENTRY_Y(0x11004, 12, 5, 24, 5, -1, -1, -1, -1, 0) +#define drive_ufs0_ref_clk_pae0 DRV_PINGROUP_ENTRY_Y(0x1100c, 12, 5, 24, 5, -1, -1, -1, -1, 0) +#define drive_spi3_miso_py1 DRV_PINGROUP_ENTRY_Y(0xd004, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi1_cs0_pz6 DRV_PINGROUP_ENTRY_Y(0xd00c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi3_cs0_py3 DRV_PINGROUP_ENTRY_Y(0xd014, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi1_miso_pz4 DRV_PINGROUP_ENTRY_Y(0xd01c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi3_cs1_py4 DRV_PINGROUP_ENTRY_Y(0xd024, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi1_sck_pz3 DRV_PINGROUP_ENTRY_Y(0xd02c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi3_sck_py0 DRV_PINGROUP_ENTRY_Y(0xd034, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi1_cs1_pz7 DRV_PINGROUP_ENTRY_Y(0xd03c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi1_mosi_pz5 DRV_PINGROUP_ENTRY_Y(0xd044, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi3_mosi_py2 DRV_PINGROUP_ENTRY_Y(0xd04c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart2_tx_px4 DRV_PINGROUP_ENTRY_Y(0xd054, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart2_rx_px5 DRV_PINGROUP_ENTRY_Y(0xd05c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart2_rts_px6 DRV_PINGROUP_ENTRY_Y(0xd064, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart2_cts_px7 DRV_PINGROUP_ENTRY_Y(0xd06c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart5_tx_py5 DRV_PINGROUP_ENTRY_Y(0xd074, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart5_rx_py6 DRV_PINGROUP_ENTRY_Y(0xd07c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart5_rts_py7 DRV_PINGROUP_ENTRY_Y(0xd084, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart5_cts_pz0 DRV_PINGROUP_ENTRY_Y(0xd08c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_gpu_pwr_req_px0 DRV_PINGROUP_ENTRY_Y(0xd094, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_gp_pwm3_px3 DRV_PINGROUP_ENTRY_Y(0xd09c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_gp_pwm2_px2 DRV_PINGROUP_ENTRY_Y(0xd0a4, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_cv_pwr_req_px1 DRV_PINGROUP_ENTRY_Y(0xd0ac, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_usb_vbus_en0_pz1 DRV_PINGROUP_ENTRY_Y(0xd0b4, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_usb_vbus_en1_pz2 DRV_PINGROUP_ENTRY_Y(0xd0bc, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_extperiph2_clk_pp1 DRV_PINGROUP_ENTRY_Y(0x0004, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_extperiph1_clk_pp0 DRV_PINGROUP_ENTRY_Y(0x000c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_cam_i2c_sda_pp3 DRV_PINGROUP_ENTRY_Y(0x0014, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_cam_i2c_scl_pp2 DRV_PINGROUP_ENTRY_Y(0x001c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio23_pp4 DRV_PINGROUP_ENTRY_Y(0x0024, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio24_pp5 DRV_PINGROUP_ENTRY_Y(0x002c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio25_pp6 DRV_PINGROUP_ENTRY_Y(0x0034, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pwr_i2c_scl_pp7 DRV_PINGROUP_ENTRY_Y(0x003c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pwr_i2c_sda_pq0 DRV_PINGROUP_ENTRY_Y(0x0044, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio28_pq1 DRV_PINGROUP_ENTRY_Y(0x004c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio29_pq2 DRV_PINGROUP_ENTRY_Y(0x0054, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio30_pq3 DRV_PINGROUP_ENTRY_Y(0x005c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio31_pq4 DRV_PINGROUP_ENTRY_Y(0x0064, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio32_pq5 DRV_PINGROUP_ENTRY_Y(0x006c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio33_pq6 DRV_PINGROUP_ENTRY_Y(0x0074, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio35_pq7 DRV_PINGROUP_ENTRY_Y(0x007c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio37_pr0 DRV_PINGROUP_ENTRY_Y(0x0084, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio56_pr1 DRV_PINGROUP_ENTRY_Y(0x008c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart1_cts_pr5 DRV_PINGROUP_ENTRY_Y(0x0094, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart1_rts_pr4 DRV_PINGROUP_ENTRY_Y(0x009c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart1_rx_pr3 DRV_PINGROUP_ENTRY_Y(0x00a4, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart1_tx_pr2 DRV_PINGROUP_ENTRY_Y(0x00ac, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_cpu_pwr_req_pi5 DRV_PINGROUP_ENTRY_Y(0x4004, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart4_cts_ph6 DRV_PINGROUP_ENTRY_Y(0x400c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart4_rts_ph5 DRV_PINGROUP_ENTRY_Y(0x4014, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart4_rx_ph4 DRV_PINGROUP_ENTRY_Y(0x401c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart4_tx_ph3 DRV_PINGROUP_ENTRY_Y(0x4024, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_gen1_i2c_scl_pi3 DRV_PINGROUP_ENTRY_Y(0x402c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_gen1_i2c_sda_pi4 DRV_PINGROUP_ENTRY_Y(0x4034, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio20_pg7 DRV_PINGROUP_ENTRY_Y(0x403c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio21_ph0 DRV_PINGROUP_ENTRY_Y(0x4044, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio22_ph1 DRV_PINGROUP_ENTRY_Y(0x404c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio13_pg0 DRV_PINGROUP_ENTRY_Y(0x4054, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio14_pg1 DRV_PINGROUP_ENTRY_Y(0x405c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio15_pg2 DRV_PINGROUP_ENTRY_Y(0x4064, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio16_pg3 DRV_PINGROUP_ENTRY_Y(0x406c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio17_pg4 DRV_PINGROUP_ENTRY_Y(0x4074, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio18_pg5 DRV_PINGROUP_ENTRY_Y(0x407c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio19_pg6 DRV_PINGROUP_ENTRY_Y(0x4084, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio41_ph7 DRV_PINGROUP_ENTRY_Y(0x408c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio42_pi0 DRV_PINGROUP_ENTRY_Y(0x4094, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio43_pi1 DRV_PINGROUP_ENTRY_Y(0x409c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio44_pi2 DRV_PINGROUP_ENTRY_Y(0x40a4, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio06_ph2 DRV_PINGROUP_ENTRY_Y(0x40ac, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio07_pi6 DRV_PINGROUP_ENTRY_Y(0x40b4, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dap4_sclk_pa4 DRV_PINGROUP_ENTRY_Y(0x2004, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dap4_dout_pa5 DRV_PINGROUP_ENTRY_Y(0x200c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dap4_din_pa6 DRV_PINGROUP_ENTRY_Y(0x2014, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dap4_fs_pa7 DRV_PINGROUP_ENTRY_Y(0x201c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dap6_sclk_pa0 DRV_PINGROUP_ENTRY_Y(0x2024, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dap6_dout_pa1 DRV_PINGROUP_ENTRY_Y(0x202c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dap6_din_pa2 DRV_PINGROUP_ENTRY_Y(0x2034, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dap6_fs_pa3 DRV_PINGROUP_ENTRY_Y(0x203c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio45_pad0 DRV_PINGROUP_ENTRY_Y(0x18004, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio46_pad1 DRV_PINGROUP_ENTRY_Y(0x1800c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio47_pad2 DRV_PINGROUP_ENTRY_Y(0x18014, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio48_pad3 DRV_PINGROUP_ENTRY_Y(0x1801c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio57_pac4 DRV_PINGROUP_ENTRY_Y(0x18024, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio58_pac5 DRV_PINGROUP_ENTRY_Y(0x1802c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio59_pac6 DRV_PINGROUP_ENTRY_Y(0x18034, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio60_pac7 DRV_PINGROUP_ENTRY_Y(0x1803c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi5_cs0_pac3 DRV_PINGROUP_ENTRY_Y(0x18044, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi5_miso_pac1 DRV_PINGROUP_ENTRY_Y(0x1804c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi5_mosi_pac2 DRV_PINGROUP_ENTRY_Y(0x18054, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi5_sck_pac0 DRV_PINGROUP_ENTRY_Y(0x1805c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_eqos_td3_pe4 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_td2_pe3 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_td1_pe2 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_td0_pe1 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_rd3_pf1 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_rd2_pf0 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_rd1_pe7 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_sma_mdio_pf4 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_rd0_pe6 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_sma_mdc_pf5 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_comp DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_txc_pe0 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_rxc_pf3 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_tx_ctl_pe5 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_rx_ctl_pf2 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi0_io3_pc5 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi0_io2_pc4 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi0_io1_pc3 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi0_io0_pc2 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi0_sck_pc0 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi0_cs_n_pc1 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi1_io3_pd3 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi1_io2_pd2 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi1_io1_pd1 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi1_io0_pd0 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi1_sck_pc6 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi1_cs_n_pc7 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi_comp DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_sdmmc1_comp DRV_PINGROUP_ENTRY_N(no_entry) + +#define PINGROUP(pg_name, f0, f1, f2, f3, r, bank, pupd, e_io_hv, e_lpbk, e_input, e_lpdr, e_pbias_buf, \ + gpio_sfio_sel, schmitt_b) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = ARRAY_SIZE(pg_name##_pins), \ + .funcs = { \ + TEGRA_MUX_##f0, \ + TEGRA_MUX_##f1, \ + TEGRA_MUX_##f2, \ + TEGRA_MUX_##f3, \ + }, \ + PIN_PINGROUP_ENTRY_Y(r, bank, pupd, e_io_hv, e_lpbk, \ + e_input, e_lpdr, e_pbias_buf, \ + gpio_sfio_sel, schmitt_b) \ + drive_##pg_name, \ + } + +static const struct tegra_pingroup tegra234_groups[] = { + PINGROUP(soc_gpio08_pb0, RSVD0, RSVD1, RSVD2, RSVD3, 0x5008, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio36_pm5, ETH0, RSVD1, DCA, RSVD3, 0x10000, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio53_pm6, ETH0, RSVD1, DCA, RSVD3, 0x10008, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio55_pm4, ETH2, RSVD1, RSVD2, RSVD3, 0x10010, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio38_pm7, ETH1, RSVD1, RSVD2, RSVD3, 0x10018, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio39_pn1, GP, RSVD1, RSVD2, RSVD3, 0x10020, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio40_pn2, ETH1, RSVD1, RSVD2, RSVD3, 0x10028, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(dp_aux_ch0_hpd_pm0, DP, RSVD1, RSVD2, RSVD3, 0x10030, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(dp_aux_ch1_hpd_pm1, ETH3, RSVD1, RSVD2, RSVD3, 0x10038, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(dp_aux_ch2_hpd_pm2, ETH3, RSVD1, DISPLAYB, RSVD3, 0x10040, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(dp_aux_ch3_hpd_pm3, ETH2, RSVD1, DISPLAYA, RSVD3, 0x10048, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(dp_aux_ch1_p_pn3, I2C4, RSVD1, RSVD2, RSVD3, 0x10050, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(dp_aux_ch1_n_pn4, I2C4, RSVD1, RSVD2, RSVD3, 0x10058, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(dp_aux_ch2_p_pn5, I2C7, RSVD1, RSVD2, RSVD3, 0x10060, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(dp_aux_ch2_n_pn6, I2C7, RSVD1, RSVD2, RSVD3, 0x10068, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(dp_aux_ch3_p_pn7, I2C9, RSVD1, RSVD2, RSVD3, 0x10070, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(dp_aux_ch3_n_pn0, I2C9, RSVD1, RSVD2, RSVD3, 0x10078, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(eqos_td3_pe4, EQOS, RSVD1, RSVD2, RSVD3, 0x15000, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_td2_pe3, EQOS, RSVD1, RSVD2, RSVD3, 0x15008, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_td1_pe2, EQOS, RSVD1, RSVD2, RSVD3, 0x15010, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_td0_pe1, EQOS, RSVD1, RSVD2, RSVD3, 0x15018, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_rd3_pf1, EQOS, RSVD1, RSVD2, RSVD3, 0x15020, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_rd2_pf0, EQOS, RSVD1, RSVD2, RSVD3, 0x15028, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_rd1_pe7, EQOS, RSVD1, RSVD2, RSVD3, 0x15030, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_sma_mdio_pf4, EQOS, RSVD1, RSVD2, RSVD3, 0x15038, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_rd0_pe6, EQOS, RSVD1, RSVD2, RSVD3, 0x15040, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_sma_mdc_pf5, EQOS, RSVD1, RSVD2, RSVD3, 0x15048, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_comp, EQOS, RSVD1, RSVD2, RSVD3, 0x15050, 0, N, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(eqos_txc_pe0, EQOS, RSVD1, RSVD2, RSVD3, 0x15058, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_rxc_pf3, EQOS, RSVD1, RSVD2, RSVD3, 0x15060, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_tx_ctl_pe5, EQOS, RSVD1, RSVD2, RSVD3, 0x15068, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_rx_ctl_pf2, EQOS, RSVD1, RSVD2, RSVD3, 0x15070, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(pex_l2_clkreq_n_pk4, PE2, RSVD1, RSVD2, RSVD3, 0x7000, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_wake_n_pl2, RSVD0, RSVD1, RSVD2, RSVD3, 0x7008, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l1_clkreq_n_pk2, PE1, RSVD1, RSVD2, RSVD3, 0x7010, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l1_rst_n_pk3, PE1, RSVD1, RSVD2, RSVD3, 0x7018, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l0_clkreq_n_pk0, PE0, RSVD1, RSVD2, RSVD3, 0x7020, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l0_rst_n_pk1, PE0, RSVD1, RSVD2, RSVD3, 0x7028, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l2_rst_n_pk5, PE2, RSVD1, RSVD2, RSVD3, 0x7030, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l3_clkreq_n_pk6, PE3, RSVD1, RSVD2, RSVD3, 0x7038, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l3_rst_n_pk7, PE3, RSVD1, RSVD2, RSVD3, 0x7040, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l4_clkreq_n_pl0, PE4, RSVD1, RSVD2, RSVD3, 0x7048, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l4_rst_n_pl1, PE4, RSVD1, RSVD2, RSVD3, 0x7050, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio34_pl3, RSVD0, RSVD1, RSVD2, RSVD3, 0x7058, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l5_clkreq_n_paf0, PE5, RSVD1, RSVD2, RSVD3, 0x14000, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l5_rst_n_paf1, PE5, RSVD1, RSVD2, RSVD3, 0x14008, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l6_clkreq_n_paf2, PE6, RSVD1, RSVD2, RSVD3, 0x14010, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l6_rst_n_paf3, PE6, RSVD1, RSVD2, RSVD3, 0x14018, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l10_clkreq_n_pag6, PE10, RSVD1, RSVD2, RSVD3, 0x19000, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l10_rst_n_pag7, PE10, RSVD1, RSVD2, RSVD3, 0x19008, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l7_clkreq_n_pag0, PE7, RSVD1, RSVD2, RSVD3, 0x19010, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l7_rst_n_pag1, PE7, RSVD1, RSVD2, RSVD3, 0x19018, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l8_clkreq_n_pag2, PE8, RSVD1, RSVD2, RSVD3, 0x19020, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l8_rst_n_pag3, PE8, RSVD1, RSVD2, RSVD3, 0x19028, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l9_clkreq_n_pag4, PE9, RSVD1, RSVD2, RSVD3, 0x19030, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l9_rst_n_pag5, PE9, RSVD1, RSVD2, RSVD3, 0x19038, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(qspi0_io3_pc5, QSPI0, RSVD1, RSVD2, RSVD3, 0xB000, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi0_io2_pc4, QSPI0, RSVD1, RSVD2, RSVD3, 0xB008, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi0_io1_pc3, QSPI0, RSVD1, RSVD2, RSVD3, 0xB010, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi0_io0_pc2, QSPI0, RSVD1, RSVD2, RSVD3, 0xB018, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi0_sck_pc0, QSPI0, RSVD1, RSVD2, RSVD3, 0xB020, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi0_cs_n_pc1, QSPI0, RSVD1, RSVD2, RSVD3, 0xB028, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi1_io3_pd3, QSPI1, RSVD1, RSVD2, RSVD3, 0xB030, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi1_io2_pd2, QSPI1, RSVD1, RSVD2, RSVD3, 0xB038, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi1_io1_pd1, QSPI1, RSVD1, RSVD2, RSVD3, 0xB040, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi1_io0_pd0, QSPI1, RSVD1, RSVD2, RSVD3, 0xB048, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi1_sck_pc6, QSPI1, RSVD1, RSVD2, RSVD3, 0xB050, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi1_cs_n_pc7, QSPI1, RSVD1, RSVD2, RSVD3, 0xB058, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi_comp, QSPI, RSVD1, RSVD2, RSVD3, 0xB060, 0, N, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc1_clk_pj0, SDMMC1, RSVD1, RSVD2, RSVD3, 0x8000, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(sdmmc1_cmd_pj1, SDMMC1, RSVD1, RSVD2, RSVD3, 0x8008, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(sdmmc1_comp, SDMMC1, RSVD1, RSVD2, RSVD3, 0x8010, 0, N, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc1_dat3_pj5, SDMMC1, RSVD1, RSVD2, RSVD3, 0x8018, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(sdmmc1_dat2_pj4, SDMMC1, RSVD1, RSVD2, RSVD3, 0x8020, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(sdmmc1_dat1_pj3, SDMMC1, RSVD1, RSVD2, RSVD3, 0x8028, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(sdmmc1_dat0_pj2, SDMMC1, RSVD1, RSVD2, RSVD3, 0x8030, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(ufs0_rst_n_pae1, UFS0, RSVD1, RSVD2, RSVD3, 0x11000, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(ufs0_ref_clk_pae0, UFS0, RSVD1, RSVD2, RSVD3, 0x11008, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(spi3_miso_py1, SPI3, RSVD1, RSVD2, RSVD3, 0xD000, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi1_cs0_pz6, SPI1, RSVD1, RSVD2, RSVD3, 0xD008, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi3_cs0_py3, SPI3, RSVD1, RSVD2, RSVD3, 0xD010, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi1_miso_pz4, SPI1, RSVD1, RSVD2, RSVD3, 0xD018, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi3_cs1_py4, SPI3, RSVD1, RSVD2, RSVD3, 0xD020, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi1_sck_pz3, SPI1, RSVD1, RSVD2, RSVD3, 0xD028, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi3_sck_py0, SPI3, RSVD1, RSVD2, RSVD3, 0xD030, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi1_cs1_pz7, SPI1, RSVD1, RSVD2, RSVD3, 0xD038, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi1_mosi_pz5, SPI1, RSVD1, RSVD2, RSVD3, 0xD040, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi3_mosi_py2, SPI3, RSVD1, RSVD2, RSVD3, 0xD048, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(uart2_tx_px4, UARTB, RSVD1, RSVD2, RSVD3, 0xD050, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(uart2_rx_px5, UARTB, RSVD1, RSVD2, RSVD3, 0xD058, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(uart2_rts_px6, UARTB, RSVD1, RSVD2, RSVD3, 0xD060, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart2_cts_px7, UARTB, RSVD1, RSVD2, RSVD3, 0xD068, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart5_tx_py5, UARTE, RSVD1, RSVD2, RSVD3, 0xD070, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart5_rx_py6, UARTE, RSVD1, RSVD2, RSVD3, 0xD078, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart5_rts_py7, UARTE, RSVD1, RSVD2, RSVD3, 0xD080, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart5_cts_pz0, UARTE, RSVD1, RSVD2, RSVD3, 0xD088, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(gpu_pwr_req_px0, RSVD0, RSVD1, RSVD2, RSVD3, 0xD090, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(gp_pwm3_px3, GP, RSVD1, RSVD2, RSVD3, 0xD098, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(gp_pwm2_px2, GP, RSVD1, RSVD2, RSVD3, 0xD0A0, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(cv_pwr_req_px1, RSVD0, RSVD1, RSVD2, RSVD3, 0xD0A8, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(usb_vbus_en0_pz1, USB, RSVD1, RSVD2, RSVD3, 0xD0B0, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(usb_vbus_en1_pz2, USB, RSVD1, RSVD2, RSVD3, 0xD0B8, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(extperiph2_clk_pp1, EXTPERIPH2, RSVD1, RSVD2, RSVD3, 0x0000, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(extperiph1_clk_pp0, EXTPERIPH1, RSVD1, RSVD2, RSVD3, 0x0008, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(cam_i2c_sda_pp3, I2C3, VI0, RSVD2, VI1, 0x0010, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(cam_i2c_scl_pp2, I2C3, VI0, VI0_ALT, VI1, 0x0018, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio23_pp4, VI0, VI0_ALT, VI1, VI1_ALT, 0x0020, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio24_pp5, VI0, SOC, VI1, VI1_ALT, 0x0028, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio25_pp6, VI0, I2S5, VI1, DMIC1, 0x0030, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pwr_i2c_scl_pp7, I2C5, RSVD1, RSVD2, RSVD3, 0x0038, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pwr_i2c_sda_pq0, I2C5, RSVD1, RSVD2, RSVD3, 0x0040, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio28_pq1, VI0, RSVD1, VI1, RSVD3, 0x0048, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio29_pq2, RSVD0, NV, RSVD2, RSVD3, 0x0050, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio30_pq3, RSVD0, WDT, RSVD2, RSVD3, 0x0058, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio31_pq4, RSVD0, RSVD1, RSVD2, RSVD3, 0x0060, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio32_pq5, RSVD0, EXTPERIPH3, DCB, RSVD3, 0x0068, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio33_pq6, RSVD0, EXTPERIPH4, DCB, RSVD3, 0x0070, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio35_pq7, RSVD0, I2S5, DMIC1, RSVD3, 0x0078, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio37_pr0, GP, I2S5, DMIC4, DSPK1, 0x0080, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio56_pr1, RSVD0, I2S5, DMIC4, DSPK1, 0x0088, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(uart1_cts_pr5, UARTA, RSVD1, RSVD2, RSVD3, 0x0090, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart1_rts_pr4, UARTA, RSVD1, RSVD2, RSVD3, 0x0098, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart1_rx_pr3, UARTA, RSVD1, RSVD2, RSVD3, 0x00A0, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart1_tx_pr2, UARTA, RSVD1, RSVD2, RSVD3, 0x00A8, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(cpu_pwr_req_pi5, RSVD0, RSVD1, RSVD2, RSVD3, 0x4000, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart4_cts_ph6, UARTD, RSVD1, I2S7, RSVD3, 0x4008, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart4_rts_ph5, UARTD, SPI4, RSVD2, RSVD3, 0x4010, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart4_rx_ph4, UARTD, RSVD1, I2S7, RSVD3, 0x4018, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart4_tx_ph3, UARTD, SPI4, RSVD2, RSVD3, 0x4020, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(gen1_i2c_scl_pi3, I2C1, RSVD1, RSVD2, RSVD3, 0x4028, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(gen1_i2c_sda_pi4, I2C1, RSVD1, RSVD2, RSVD3, 0x4030, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio20_pg7, RSVD0, SDMMC1, RSVD2, RSVD3, 0x4038, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio21_ph0, RSVD0, GP, I2S7, RSVD3, 0x4040, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio22_ph1, RSVD0, RSVD1, I2S7, RSVD3, 0x4048, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio13_pg0, RSVD0, RSVD1, RSVD2, RSVD3, 0x4050, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio14_pg1, RSVD0, SPI4, RSVD2, RSVD3, 0x4058, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio15_pg2, RSVD0, SPI4, RSVD2, RSVD3, 0x4060, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio16_pg3, RSVD0, SPI4, RSVD2, RSVD3, 0x4068, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio17_pg4, RSVD0, CCLA, RSVD2, RSVD3, 0x4070, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio18_pg5, RSVD0, RSVD1, RSVD2, RSVD3, 0x4078, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio19_pg6, GP, RSVD1, RSVD2, RSVD3, 0x4080, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio41_ph7, RSVD0, I2S2, RSVD2, RSVD3, 0x4088, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio42_pi0, RSVD0, I2S2, RSVD2, RSVD3, 0x4090, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio43_pi1, RSVD0, I2S2, RSVD2, RSVD3, 0x4098, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio44_pi2, RSVD0, I2S2, RSVD2, RSVD3, 0x40A0, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio06_ph2, RSVD0, RSVD1, RSVD2, RSVD3, 0x40A8, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio07_pi6, GP, RSVD1, RSVD2, RSVD3, 0x40B0, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(dap4_sclk_pa4, I2S4, RSVD1, RSVD2, RSVD3, 0x2000, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(dap4_dout_pa5, I2S4, RSVD1, RSVD2, RSVD3, 0x2008, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(dap4_din_pa6, I2S4, RSVD1, RSVD2, RSVD3, 0x2010, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(dap4_fs_pa7, I2S4, RSVD1, RSVD2, RSVD3, 0x2018, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(dap6_sclk_pa0, I2S6, RSVD1, RSVD2, RSVD3, 0x2020, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(dap6_dout_pa1, I2S6, RSVD1, RSVD2, RSVD3, 0x2028, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(dap6_din_pa2, I2S6, RSVD1, RSVD2, RSVD3, 0x2030, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(dap6_fs_pa3, I2S6, RSVD1, RSVD2, RSVD3, 0x2038, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio45_pad0, RSVD0, I2S1, RSVD2, RSVD3, 0x18000, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio46_pad1, RSVD0, I2S1, RSVD2, RSVD3, 0x18008, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio47_pad2, RSVD0, I2S1, RSVD2, RSVD3, 0x18010, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio48_pad3, RSVD0, I2S1, RSVD2, RSVD3, 0x18018, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio57_pac4, RSVD0, I2S8, RSVD2, SDMMC1, 0x18020, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio58_pac5, RSVD0, I2S8, RSVD2, SDMMC1, 0x18028, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio59_pac6, AUD, I2S8, RSVD2, RSVD3, 0x18030, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio60_pac7, RSVD0, I2S8, NV, IGPU, 0x18038, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(spi5_cs0_pac3, SPI5, I2S3, DMIC2, RSVD3, 0x18040, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(spi5_miso_pac1, SPI5, I2S3, DSPK0, RSVD3, 0x18048, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(spi5_mosi_pac2, SPI5, I2S3, DMIC2, RSVD3, 0x18050, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(spi5_sck_pac0, SPI5, I2S3, DSPK0, RSVD3, 0x18058, 0, Y, -1, 7, 6, 8, -1, 10, 12), + +}; + +static const struct tegra_pinctrl_soc_data tegra234_pinctrl = { + .pins = tegra234_pins, + .npins = ARRAY_SIZE(tegra234_pins), + .functions = tegra234_functions, + .nfunctions = ARRAY_SIZE(tegra234_functions), + .groups = tegra234_groups, + .ngroups = ARRAY_SIZE(tegra234_groups), + .hsm_in_mux = false, + .schmitt_in_mux = true, + .drvtype_in_mux = true, + .sfsel_in_mux = true, +}; + +static const struct pinctrl_pin_desc tegra234_aon_pins[] = { + PINCTRL_PIN(TEGRA_PIN_CAN0_DOUT_PAA0, "CAN0_DOUT_PAA0"), + PINCTRL_PIN(TEGRA_PIN_CAN0_DIN_PAA1, "CAN0_DIN_PAA1"), + PINCTRL_PIN(TEGRA_PIN_CAN1_DOUT_PAA2, "CAN1_DOUT_PAA2"), + PINCTRL_PIN(TEGRA_PIN_CAN1_DIN_PAA3, "CAN1_DIN_PAA3"), + PINCTRL_PIN(TEGRA_PIN_CAN0_STB_PAA4, "CAN0_STB_PAA4"), + PINCTRL_PIN(TEGRA_PIN_CAN0_EN_PAA5, "CAN0_EN_PAA5"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO49_PAA6, "SOC_GPIO49_PAA6"), + PINCTRL_PIN(TEGRA_PIN_CAN0_ERR_PAA7, "CAN0_ERR_PAA7"), + PINCTRL_PIN(TEGRA_PIN_CAN1_STB_PBB0, "CAN1_STB_PBB0"), + PINCTRL_PIN(TEGRA_PIN_CAN1_EN_PBB1, "CAN1_EN_PBB1"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO50_PBB2, "SOC_GPIO50_PBB2"), + PINCTRL_PIN(TEGRA_PIN_CAN1_ERR_PBB3, "CAN1_ERR_PBB3"), + PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PCC0, "SPI2_SCK_PCC0"), + PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PCC1, "SPI2_MISO_PCC1"), + PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PCC2, "SPI2_MOSI_PCC2"), + PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_PCC3, "SPI2_CS0_PCC3"), + PINCTRL_PIN(TEGRA_PIN_TOUCH_CLK_PCC4, "TOUCH_CLK_PCC4"), + PINCTRL_PIN(TEGRA_PIN_UART3_TX_PCC5, "UART3_TX_PCC5"), + PINCTRL_PIN(TEGRA_PIN_UART3_RX_PCC6, "UART3_RX_PCC6"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PCC7, "GEN2_I2C_SCL_PCC7"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PDD0, "GEN2_I2C_SDA_PDD0"), + PINCTRL_PIN(TEGRA_PIN_GEN8_I2C_SCL_PDD1, "GEN8_I2C_SCL_PDD1"), + PINCTRL_PIN(TEGRA_PIN_GEN8_I2C_SDA_PDD2, "GEN8_I2C_SDA_PDD2"), + PINCTRL_PIN(TEGRA_PIN_SCE_ERROR_PEE0, "SCE_ERROR_PEE0"), + PINCTRL_PIN(TEGRA_PIN_VCOMP_ALERT_PEE1, "VCOMP_ALERT_PEE1"), + PINCTRL_PIN(TEGRA_PIN_AO_RETENTION_N_PEE2, "AO_RETENTION_N_PEE2"), + PINCTRL_PIN(TEGRA_PIN_BATT_OC_PEE3, "BATT_OC_PEE3"), + PINCTRL_PIN(TEGRA_PIN_POWER_ON_PEE4, "POWER_ON_PEE4"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO26_PEE5, "SOC_GPIO26_PEE5"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO27_PEE6, "SOC_GPIO27_PEE6"), + PINCTRL_PIN(TEGRA_PIN_BOOTV_CTL_N_PEE7, "BOOTV_CTL_N_PEE7"), + PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PGG0, "HDMI_CEC_PGG0"), +}; + +/* AON drive pin groups */ +#define drive_touch_clk_pcc4 DRV_PINGROUP_ENTRY_Y(0x2004, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart3_rx_pcc6 DRV_PINGROUP_ENTRY_Y(0x200c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart3_tx_pcc5 DRV_PINGROUP_ENTRY_Y(0x2014, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_gen8_i2c_sda_pdd2 DRV_PINGROUP_ENTRY_Y(0x201c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_gen8_i2c_scl_pdd1 DRV_PINGROUP_ENTRY_Y(0x2024, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi2_mosi_pcc2 DRV_PINGROUP_ENTRY_Y(0x202c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_gen2_i2c_scl_pcc7 DRV_PINGROUP_ENTRY_Y(0x2034, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi2_cs0_pcc3 DRV_PINGROUP_ENTRY_Y(0x203c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_gen2_i2c_sda_pdd0 DRV_PINGROUP_ENTRY_Y(0x2044, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi2_sck_pcc0 DRV_PINGROUP_ENTRY_Y(0x204c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi2_miso_pcc1 DRV_PINGROUP_ENTRY_Y(0x2054, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_can1_dout_paa2 DRV_PINGROUP_ENTRY_Y(0x3004, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_can1_din_paa3 DRV_PINGROUP_ENTRY_Y(0x300c, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_can0_dout_paa0 DRV_PINGROUP_ENTRY_Y(0x3014, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_can0_din_paa1 DRV_PINGROUP_ENTRY_Y(0x301c, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_can0_stb_paa4 DRV_PINGROUP_ENTRY_Y(0x3024, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_can0_en_paa5 DRV_PINGROUP_ENTRY_Y(0x302c, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_soc_gpio49_paa6 DRV_PINGROUP_ENTRY_Y(0x3034, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_can0_err_paa7 DRV_PINGROUP_ENTRY_Y(0x303c, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_can1_stb_pbb0 DRV_PINGROUP_ENTRY_Y(0x3044, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_can1_en_pbb1 DRV_PINGROUP_ENTRY_Y(0x304c, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_soc_gpio50_pbb2 DRV_PINGROUP_ENTRY_Y(0x3054, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_can1_err_pbb3 DRV_PINGROUP_ENTRY_Y(0x305c, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_sce_error_pee0 DRV_PINGROUP_ENTRY_Y(0x1014, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_batt_oc_pee3 DRV_PINGROUP_ENTRY_Y(0x1024, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_bootv_ctl_n_pee7 DRV_PINGROUP_ENTRY_Y(0x102c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_power_on_pee4 DRV_PINGROUP_ENTRY_Y(0x103c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio26_pee5 DRV_PINGROUP_ENTRY_Y(0x1044, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio27_pee6 DRV_PINGROUP_ENTRY_Y(0x104c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_ao_retention_n_pee2 DRV_PINGROUP_ENTRY_Y(0x1054, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_vcomp_alert_pee1 DRV_PINGROUP_ENTRY_Y(0x105c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_hdmi_cec_pgg0 DRV_PINGROUP_ENTRY_Y(0x1064, 12, 5, 20, 5, -1, -1, -1, -1, 0) + +static const struct tegra_pingroup tegra234_aon_groups[] = { + PINGROUP(touch_clk_pcc4, GP, TOUCH, RSVD2, RSVD3, 0x2000, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(uart3_rx_pcc6, UARTC, UARTJ, RSVD2, RSVD3, 0x2008, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(uart3_tx_pcc5, UARTC, UARTJ, RSVD2, RSVD3, 0x2010, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(gen8_i2c_sda_pdd2, I2C8, RSVD1, RSVD2, RSVD3, 0x2018, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(gen8_i2c_scl_pdd1, I2C8, RSVD1, RSVD2, RSVD3, 0x2020, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi2_mosi_pcc2, SPI2, RSVD1, RSVD2, RSVD3, 0x2028, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(gen2_i2c_scl_pcc7, I2C2, RSVD1, RSVD2, RSVD3, 0x2030, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi2_cs0_pcc3, SPI2, RSVD1, RSVD2, RSVD3, 0x2038, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(gen2_i2c_sda_pdd0, I2C2, RSVD1, RSVD2, RSVD3, 0x2040, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi2_sck_pcc0, SPI2, RSVD1, RSVD2, RSVD3, 0x2048, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi2_miso_pcc1, SPI2, RSVD1, RSVD2, RSVD3, 0x2050, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(can1_dout_paa2, CAN1, RSVD1, RSVD2, RSVD3, 0x3000, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(can1_din_paa3, CAN1, RSVD1, RSVD2, RSVD3, 0x3008, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(can0_dout_paa0, CAN0, RSVD1, RSVD2, RSVD3, 0x3010, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(can0_din_paa1, CAN0, RSVD1, RSVD2, RSVD3, 0x3018, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(can0_stb_paa4, RSVD0, WDT, TSC, TSC_ALT, 0x3020, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(can0_en_paa5, RSVD0, RSVD1, RSVD2, RSVD3, 0x3028, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(soc_gpio49_paa6, RSVD0, RSVD1, RSVD2, RSVD3, 0x3030, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(can0_err_paa7, RSVD0, TSC, RSVD2, TSC_ALT, 0x3038, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(can1_stb_pbb0, RSVD0, DMIC3, DMIC5, RSVD3, 0x3040, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(can1_en_pbb1, RSVD0, DMIC3, DMIC5, RSVD3, 0x3048, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(soc_gpio50_pbb2, RSVD0, TSC, RSVD2, TSC_ALT, 0x3050, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(can1_err_pbb3, RSVD0, TSC, RSVD2, TSC_ALT, 0x3058, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(sce_error_pee0, SCE, RSVD1, RSVD2, RSVD3, 0x1010, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(batt_oc_pee3, SOC, RSVD1, RSVD2, RSVD3, 0x1020, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(bootv_ctl_n_pee7, RSVD0, RSVD1, RSVD2, RSVD3, 0x1028, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(power_on_pee4, RSVD0, RSVD1, RSVD2, RSVD3, 0x1038, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio26_pee5, RSVD0, RSVD1, RSVD2, RSVD3, 0x1040, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio27_pee6, RSVD0, RSVD1, RSVD2, RSVD3, 0x1048, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(ao_retention_n_pee2, GPIO, LED, RSVD2, ISTCTRL, 0x1050, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(vcomp_alert_pee1, SOC, RSVD1, RSVD2, RSVD3, 0x1058, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(hdmi_cec_pgg0, HDMI, RSVD1, RSVD2, RSVD3, 0x1060, 0, Y, 5, 7, 6, 8, -1, 10, 12), +}; + +static const struct tegra_pinctrl_soc_data tegra234_pinctrl_aon = { + .pins = tegra234_aon_pins, + .npins = ARRAY_SIZE(tegra234_aon_pins), + .functions = tegra234_functions, + .nfunctions = ARRAY_SIZE(tegra234_functions), + .groups = tegra234_aon_groups, + .ngroups = ARRAY_SIZE(tegra234_aon_groups), + .hsm_in_mux = false, + .schmitt_in_mux = true, + .drvtype_in_mux = true, + .sfsel_in_mux = true, +}; + +static int tegra234_pinctrl_probe(struct platform_device *pdev) +{ + const struct tegra_pinctrl_soc_data *soc = device_get_match_data(&pdev->dev); + + return tegra_pinctrl_probe(pdev, soc); +} + +static const struct of_device_id tegra234_pinctrl_of_match[] = { + { .compatible = "nvidia,tegra234-pinmux", .data = &tegra234_pinctrl}, + { .compatible = "nvidia,tegra234-pinmux-aon", .data = &tegra234_pinctrl_aon }, + { } +}; +MODULE_DEVICE_TABLE(of, tegra234_pinctrl_of_match); + +static struct platform_driver tegra234_pinctrl_driver = { + .driver = { + .name = "tegra234-pinctrl", + .of_match_table = tegra234_pinctrl_of_match, + }, + .probe = tegra234_pinctrl_probe, +}; + +static int __init tegra234_pinctrl_init(void) +{ + return platform_driver_register(&tegra234_pinctrl_driver); +} +arch_initcall(tegra234_pinctrl_init); diff --git a/drivers/pinctrl/tegra/pinctrl-tegra30.c b/drivers/pinctrl/tegra/pinctrl-tegra30.c index 7299a371827f..de5aa2d4d28d 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra30.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra30.c @@ -2010,12 +2010,9 @@ enum tegra_mux { TEGRA_MUX_VI_ALT3, }; -#define FUNCTION(fname) \ - { \ - .name = #fname, \ - } +#define FUNCTION(fname) #fname -static struct tegra_function tegra30_functions[] = { +static const char * const tegra30_functions[] = { FUNCTION(blink), FUNCTION(cec), FUNCTION(clk_12m_out), diff --git a/drivers/platform/mellanox/mlxbf-bootctl.c b/drivers/platform/mellanox/mlxbf-bootctl.c index 1bad1d278672..fb9f7815c6cd 100644 --- a/drivers/platform/mellanox/mlxbf-bootctl.c +++ b/drivers/platform/mellanox/mlxbf-bootctl.c @@ -11,6 +11,7 @@ #include <linux/acpi.h> #include <linux/arm-smccc.h> #include <linux/delay.h> +#include <linux/iopoll.h> #include <linux/module.h> #include <linux/platform_device.h> @@ -45,10 +46,39 @@ static const char * const mlxbf_bootctl_lifecycle_states[] = { [3] = "RMA", }; +/* Log header format. */ +#define MLXBF_RSH_LOG_TYPE_MASK GENMASK_ULL(59, 56) +#define MLXBF_RSH_LOG_LEN_MASK GENMASK_ULL(54, 48) +#define MLXBF_RSH_LOG_LEVEL_MASK GENMASK_ULL(7, 0) + +/* Log module ID and type (only MSG type in Linux driver for now). */ +#define MLXBF_RSH_LOG_TYPE_MSG 0x04ULL + +/* Log ctl/data register offset. */ +#define MLXBF_RSH_SCRATCH_BUF_CTL_OFF 0 +#define MLXBF_RSH_SCRATCH_BUF_DATA_OFF 0x10 + +/* Log message levels. */ +enum { + MLXBF_RSH_LOG_INFO, + MLXBF_RSH_LOG_WARN, + MLXBF_RSH_LOG_ERR, + MLXBF_RSH_LOG_ASSERT +}; + /* Mapped pointer for RSH_BOOT_FIFO_DATA and RSH_BOOT_FIFO_COUNT register. */ static void __iomem *mlxbf_rsh_boot_data; static void __iomem *mlxbf_rsh_boot_cnt; +/* Mapped pointer for rsh log semaphore/ctrl/data register. */ +static void __iomem *mlxbf_rsh_semaphore; +static void __iomem *mlxbf_rsh_scratch_buf_ctl; +static void __iomem *mlxbf_rsh_scratch_buf_data; + +/* Rsh log levels. */ +static const char * const mlxbf_rsh_log_level[] = { + "INFO", "WARN", "ERR", "ASSERT"}; + /* ARM SMC call which is atomic and no need for lock. */ static int mlxbf_bootctl_smc(unsigned int smc_op, int smc_arg) { @@ -266,12 +296,108 @@ static ssize_t fw_reset_store(struct device *dev, return count; } +/* Size(8-byte words) of the log buffer. */ +#define RSH_SCRATCH_BUF_CTL_IDX_MASK 0x7f + +/* 100ms timeout */ +#define RSH_SCRATCH_BUF_POLL_TIMEOUT 100000 + +static int mlxbf_rsh_log_sem_lock(void) +{ + unsigned long reg; + + return readq_poll_timeout(mlxbf_rsh_semaphore, reg, !reg, 0, + RSH_SCRATCH_BUF_POLL_TIMEOUT); +} + +static void mlxbf_rsh_log_sem_unlock(void) +{ + writeq(0, mlxbf_rsh_semaphore); +} + +static ssize_t rsh_log_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int rc, idx, num, len, level = MLXBF_RSH_LOG_INFO; + size_t size = count; + u64 data; + + if (!size) + return -EINVAL; + + if (!mlxbf_rsh_semaphore || !mlxbf_rsh_scratch_buf_ctl) + return -EOPNOTSUPP; + + /* Ignore line break at the end. */ + if (buf[size - 1] == '\n') + size--; + + /* Check the message prefix. */ + for (idx = 0; idx < ARRAY_SIZE(mlxbf_rsh_log_level); idx++) { + len = strlen(mlxbf_rsh_log_level[idx]); + if (len + 1 < size && + !strncmp(buf, mlxbf_rsh_log_level[idx], len)) { + buf += len; + size -= len; + level = idx; + break; + } + } + + /* Ignore leading spaces. */ + while (size > 0 && buf[0] == ' ') { + size--; + buf++; + } + + /* Take the semaphore. */ + rc = mlxbf_rsh_log_sem_lock(); + if (rc) + return rc; + + /* Calculate how many words are available. */ + idx = readq(mlxbf_rsh_scratch_buf_ctl); + num = min((int)DIV_ROUND_UP(size, sizeof(u64)), + RSH_SCRATCH_BUF_CTL_IDX_MASK - idx - 1); + if (num <= 0) + goto done; + + /* Write Header. */ + data = FIELD_PREP(MLXBF_RSH_LOG_TYPE_MASK, MLXBF_RSH_LOG_TYPE_MSG); + data |= FIELD_PREP(MLXBF_RSH_LOG_LEN_MASK, num); + data |= FIELD_PREP(MLXBF_RSH_LOG_LEVEL_MASK, level); + writeq(data, mlxbf_rsh_scratch_buf_data); + + /* Write message. */ + for (idx = 0; idx < num && size > 0; idx++) { + if (size < sizeof(u64)) { + data = 0; + memcpy(&data, buf, size); + size = 0; + } else { + memcpy(&data, buf, sizeof(u64)); + size -= sizeof(u64); + buf += sizeof(u64); + } + writeq(data, mlxbf_rsh_scratch_buf_data); + } + +done: + /* Release the semaphore. */ + mlxbf_rsh_log_sem_unlock(); + + /* Ignore the rest if no more space. */ + return count; +} + static DEVICE_ATTR_RW(post_reset_wdog); static DEVICE_ATTR_RW(reset_action); static DEVICE_ATTR_RW(second_reset_action); static DEVICE_ATTR_RO(lifecycle_state); static DEVICE_ATTR_RO(secure_boot_fuse_state); static DEVICE_ATTR_WO(fw_reset); +static DEVICE_ATTR_WO(rsh_log); static struct attribute *mlxbf_bootctl_attrs[] = { &dev_attr_post_reset_wdog.attr, @@ -280,6 +406,7 @@ static struct attribute *mlxbf_bootctl_attrs[] = { &dev_attr_lifecycle_state.attr, &dev_attr_secure_boot_fuse_state.attr, &dev_attr_fw_reset.attr, + &dev_attr_rsh_log.attr, NULL }; @@ -345,19 +472,32 @@ static bool mlxbf_bootctl_guid_match(const guid_t *guid, static int mlxbf_bootctl_probe(struct platform_device *pdev) { struct arm_smccc_res res = { 0 }; + void __iomem *reg; guid_t guid; int ret; - /* Get the resource of the bootfifo data register. */ + /* Map the resource of the bootfifo data register. */ mlxbf_rsh_boot_data = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(mlxbf_rsh_boot_data)) return PTR_ERR(mlxbf_rsh_boot_data); - /* Get the resource of the bootfifo counter register. */ + /* Map the resource of the bootfifo counter register. */ mlxbf_rsh_boot_cnt = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(mlxbf_rsh_boot_cnt)) return PTR_ERR(mlxbf_rsh_boot_cnt); + /* Map the resource of the rshim semaphore register. */ + mlxbf_rsh_semaphore = devm_platform_ioremap_resource(pdev, 2); + if (IS_ERR(mlxbf_rsh_semaphore)) + return PTR_ERR(mlxbf_rsh_semaphore); + + /* Map the resource of the scratch buffer (log) registers. */ + reg = devm_platform_ioremap_resource(pdev, 3); + if (IS_ERR(reg)) + return PTR_ERR(reg); + mlxbf_rsh_scratch_buf_ctl = reg + MLXBF_RSH_SCRATCH_BUF_CTL_OFF; + mlxbf_rsh_scratch_buf_data = reg + MLXBF_RSH_SCRATCH_BUF_DATA_OFF; + /* Ensure we have the UUID we expect for this service. */ arm_smccc_smc(MLXBF_BOOTCTL_SIP_SVC_UID, 0, 0, 0, 0, 0, 0, 0, &res); guid_parse(mlxbf_bootctl_svc_uuid_str, &guid); diff --git a/drivers/platform/surface/aggregator/Kconfig b/drivers/platform/surface/aggregator/Kconfig index c114f9dd5fe1..88afc38ffdc5 100644 --- a/drivers/platform/surface/aggregator/Kconfig +++ b/drivers/platform/surface/aggregator/Kconfig @@ -4,7 +4,7 @@ menuconfig SURFACE_AGGREGATOR tristate "Microsoft Surface System Aggregator Module Subsystem and Drivers" depends on SERIAL_DEV_BUS - depends on ACPI + depends on ACPI && !RISCV select CRC_CCITT help The Surface System Aggregator Module (Surface SAM or SSAM) is an diff --git a/drivers/platform/surface/surface3_power.c b/drivers/platform/surface/surface3_power.c index 73961a24c849..4c0f92562a79 100644 --- a/drivers/platform/surface/surface3_power.c +++ b/drivers/platform/surface/surface3_power.c @@ -573,7 +573,7 @@ static const struct acpi_device_id mshw0011_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, mshw0011_acpi_match); static struct i2c_driver mshw0011_driver = { - .probe_new = mshw0011_probe, + .probe = mshw0011_probe, .remove = mshw0011_remove, .driver = { .name = "mshw0011", diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 22052031c719..49c2c4cd8d00 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -43,8 +43,8 @@ config WMI_BMOF default ACPI_WMI help Say Y here if you want to be able to read a firmware-embedded - WMI Binary MOF data. Using this requires userspace tools and may be - rather tedious. + WMI Binary MOF (Managed Object Format) data. Using this requires + userspace tools and may be rather tedious. To compile this driver as a module, choose M here: the module will be called wmi-bmof. @@ -121,10 +121,11 @@ config GIGABYTE_WMI To compile this driver as a module, choose M here: the module will be called gigabyte-wmi. -config YOGABOOK_WMI - tristate "Lenovo Yoga Book tablet WMI key driver" +config YOGABOOK + tristate "Lenovo Yoga Book tablet key driver" depends on ACPI_WMI depends on INPUT + depends on I2C select LEDS_CLASS select NEW_LEDS help @@ -132,7 +133,7 @@ config YOGABOOK_WMI control on the Lenovo Yoga Book tablets. To compile this driver as a module, choose M here: the module will - be called lenovo-yogabook-wmi. + be called lenovo-yogabook. config ACERHDF tristate "Acer Aspire One temperature and fan driver" diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 2cafe51ec4d8..52dfdf574ac2 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -14,7 +14,6 @@ obj-$(CONFIG_MXM_WMI) += mxm-wmi.o obj-$(CONFIG_NVIDIA_WMI_EC_BACKLIGHT) += nvidia-wmi-ec-backlight.o obj-$(CONFIG_XIAOMI_WMI) += xiaomi-wmi.o obj-$(CONFIG_GIGABYTE_WMI) += gigabyte-wmi.o -obj-$(CONFIG_YOGABOOK_WMI) += lenovo-yogabook-wmi.o # Acer obj-$(CONFIG_ACERHDF) += acerhdf.o @@ -66,6 +65,7 @@ obj-$(CONFIG_LENOVO_YMC) += lenovo-ymc.o obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o obj-$(CONFIG_THINKPAD_LMI) += think-lmi.o +obj-$(CONFIG_YOGABOOK) += lenovo-yogabook.o # Intel obj-y += intel/ diff --git a/drivers/platform/x86/amd/pmc.c b/drivers/platform/x86/amd/pmc.c index 1304cd6f13f6..7d3d080ff174 100644 --- a/drivers/platform/x86/amd/pmc.c +++ b/drivers/platform/x86/amd/pmc.c @@ -45,7 +45,6 @@ #define AMD_PMC_STB_DUMMY_PC 0xC6000007 /* STB S2D(Spill to DRAM) has different message port offset */ -#define STB_SPILL_TO_DRAM 0xBE #define AMD_S2D_REGISTER_MESSAGE 0xA20 #define AMD_S2D_REGISTER_RESPONSE 0xA80 #define AMD_S2D_REGISTER_ARGUMENT 0xA88 @@ -99,7 +98,6 @@ #define PMC_MSG_DELAY_MIN_US 50 #define RESPONSE_REGISTER_LOOP_MAX 20000 -#define SOC_SUBSYSTEM_IP_MAX 12 #define DELAY_MIN_US 2000 #define DELAY_MAX_US 3000 #define FIFO_SIZE 4096 @@ -115,6 +113,7 @@ enum s2d_arg { S2D_PHYS_ADDR_LOW, S2D_PHYS_ADDR_HIGH, S2D_NUM_SAMPLES, + S2D_DRAM_SIZE, }; struct amd_pmc_bit_map { @@ -132,9 +131,18 @@ static const struct amd_pmc_bit_map soc15_ip_blk[] = { {"ISP", BIT(6)}, {"NBIO", BIT(7)}, {"DF", BIT(8)}, - {"USB0", BIT(9)}, - {"USB1", BIT(10)}, + {"USB3_0", BIT(9)}, + {"USB3_1", BIT(10)}, {"LAPIC", BIT(11)}, + {"USB3_2", BIT(12)}, + {"USB3_3", BIT(13)}, + {"USB3_4", BIT(14)}, + {"USB4_0", BIT(15)}, + {"USB4_1", BIT(16)}, + {"MPM", BIT(17)}, + {"JPEG", BIT(18)}, + {"IPU", BIT(19)}, + {"UMSCH", BIT(20)}, {} }; @@ -147,6 +155,9 @@ struct amd_pmc_dev { u32 base_addr; u32 cpu_id; u32 active_ips; + u32 dram_size; + u32 num_ips; + u32 s2d_msg_id; /* SMU version information */ u8 smu_program; u8 major; @@ -194,8 +205,8 @@ struct smu_metrics { u64 timein_s0i3_totaltime; u64 timein_swdrips_lastcapture; u64 timein_swdrips_totaltime; - u64 timecondition_notmet_lastcapture[SOC_SUBSYSTEM_IP_MAX]; - u64 timecondition_notmet_totaltime[SOC_SUBSYSTEM_IP_MAX]; + u64 timecondition_notmet_lastcapture[32]; + u64 timecondition_notmet_totaltime[32]; } __packed; static int amd_pmc_stb_debugfs_open(struct inode *inode, struct file *filp) @@ -261,7 +272,7 @@ static int amd_pmc_stb_debugfs_open_v2(struct inode *inode, struct file *filp) dev->msg_port = 1; /* Get the num_samples to calculate the last push location */ - ret = amd_pmc_send_cmd(dev, S2D_NUM_SAMPLES, &num_samples, STB_SPILL_TO_DRAM, 1); + ret = amd_pmc_send_cmd(dev, S2D_NUM_SAMPLES, &num_samples, dev->s2d_msg_id, true); /* Clear msg_port for other SMU operation */ dev->msg_port = 0; if (ret) { @@ -308,6 +319,23 @@ static const struct file_operations amd_pmc_stb_debugfs_fops_v2 = { .release = amd_pmc_stb_debugfs_release_v2, }; +static void amd_pmc_get_ip_info(struct amd_pmc_dev *dev) +{ + switch (dev->cpu_id) { + case AMD_CPU_ID_PCO: + case AMD_CPU_ID_RN: + case AMD_CPU_ID_YC: + case AMD_CPU_ID_CB: + dev->num_ips = 12; + dev->s2d_msg_id = 0xBE; + break; + case AMD_CPU_ID_PS: + dev->num_ips = 21; + dev->s2d_msg_id = 0x85; + break; + } +} + static int amd_pmc_setup_smu_logging(struct amd_pmc_dev *dev) { if (dev->cpu_id == AMD_CPU_ID_PCO) { @@ -317,15 +345,15 @@ static int amd_pmc_setup_smu_logging(struct amd_pmc_dev *dev) /* Get Active devices list from SMU */ if (!dev->active_ips) - amd_pmc_send_cmd(dev, 0, &dev->active_ips, SMU_MSG_GET_SUP_CONSTRAINTS, 1); + amd_pmc_send_cmd(dev, 0, &dev->active_ips, SMU_MSG_GET_SUP_CONSTRAINTS, true); /* Get dram address */ if (!dev->smu_virt_addr) { u32 phys_addr_low, phys_addr_hi; u64 smu_phys_addr; - amd_pmc_send_cmd(dev, 0, &phys_addr_low, SMU_MSG_LOG_GETDRAM_ADDR_LO, 1); - amd_pmc_send_cmd(dev, 0, &phys_addr_hi, SMU_MSG_LOG_GETDRAM_ADDR_HI, 1); + amd_pmc_send_cmd(dev, 0, &phys_addr_low, SMU_MSG_LOG_GETDRAM_ADDR_LO, true); + amd_pmc_send_cmd(dev, 0, &phys_addr_hi, SMU_MSG_LOG_GETDRAM_ADDR_HI, true); smu_phys_addr = ((u64)phys_addr_hi << 32 | phys_addr_low); dev->smu_virt_addr = devm_ioremap(dev->dev, smu_phys_addr, @@ -335,8 +363,8 @@ static int amd_pmc_setup_smu_logging(struct amd_pmc_dev *dev) } /* Start the logging */ - amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_RESET, 0); - amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_START, 0); + amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_RESET, false); + amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_START, false); return 0; } @@ -377,7 +405,7 @@ static int amd_pmc_get_smu_version(struct amd_pmc_dev *dev) if (dev->cpu_id == AMD_CPU_ID_PCO) return -ENODEV; - rc = amd_pmc_send_cmd(dev, 0, &val, SMU_MSG_GETSMUVERSION, 1); + rc = amd_pmc_send_cmd(dev, 0, &val, SMU_MSG_GETSMUVERSION, true); if (rc) return rc; @@ -469,7 +497,7 @@ static int smu_fw_info_show(struct seq_file *s, void *unused) table.timeto_resume_to_os_lastcapture); seq_puts(s, "\n=== Active time (in us) ===\n"); - for (idx = 0 ; idx < SOC_SUBSYSTEM_IP_MAX ; idx++) { + for (idx = 0 ; idx < dev->num_ips ; idx++) { if (soc15_ip_blk[idx].bit_mask & dev->active_ips) seq_printf(s, "%-8s : %lld\n", soc15_ip_blk[idx].name, table.timecondition_notmet_lastcapture[idx]); @@ -562,6 +590,18 @@ static void amd_pmc_dbgfs_unregister(struct amd_pmc_dev *dev) debugfs_remove_recursive(dev->dbgfs_dir); } +static bool amd_pmc_is_stb_supported(struct amd_pmc_dev *dev) +{ + switch (dev->cpu_id) { + case AMD_CPU_ID_YC: + case AMD_CPU_ID_CB: + case AMD_CPU_ID_PS: + return true; + default: + return false; + } +} + static void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev) { dev->dbgfs_dir = debugfs_create_dir("amd_pmc", NULL); @@ -573,8 +613,7 @@ static void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev) &amd_pmc_idlemask_fops); /* Enable STB only when the module_param is set */ if (enable_stb) { - if (dev->cpu_id == AMD_CPU_ID_YC || dev->cpu_id == AMD_CPU_ID_CB || - dev->cpu_id == AMD_CPU_ID_PS) + if (amd_pmc_is_stb_supported(dev)) debugfs_create_file("stb_read", 0644, dev->dbgfs_dir, dev, &amd_pmc_stb_debugfs_fops_v2); else @@ -794,7 +833,7 @@ static void amd_pmc_s2idle_prepare(void) } msg = amd_pmc_get_os_hint(pdev); - rc = amd_pmc_send_cmd(pdev, arg, NULL, msg, 0); + rc = amd_pmc_send_cmd(pdev, arg, NULL, msg, false); if (rc) { dev_err(pdev->dev, "suspend failed: %d\n", rc); return; @@ -829,7 +868,7 @@ static int amd_pmc_dump_data(struct amd_pmc_dev *pdev) if (pdev->cpu_id == AMD_CPU_ID_PCO) return -ENODEV; - return amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_DUMP_DATA, 0); + return amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_DUMP_DATA, false); } static void amd_pmc_s2idle_restore(void) @@ -839,7 +878,7 @@ static void amd_pmc_s2idle_restore(void) u8 msg; msg = amd_pmc_get_os_hint(pdev); - rc = amd_pmc_send_cmd(pdev, 0, NULL, msg, 0); + rc = amd_pmc_send_cmd(pdev, 0, NULL, msg, false); if (rc) dev_err(pdev->dev, "resume failed: %d\n", rc); @@ -890,29 +929,65 @@ static const struct pci_device_id pmc_pci_ids[] = { { } }; +static int amd_pmc_get_dram_size(struct amd_pmc_dev *dev) +{ + int ret; + + switch (dev->cpu_id) { + case AMD_CPU_ID_YC: + if (!(dev->major > 90 || (dev->major == 90 && dev->minor > 39))) { + ret = -EINVAL; + goto err_dram_size; + } + break; + default: + ret = -EINVAL; + goto err_dram_size; + } + + ret = amd_pmc_send_cmd(dev, S2D_DRAM_SIZE, &dev->dram_size, dev->s2d_msg_id, true); + if (ret || !dev->dram_size) + goto err_dram_size; + + return 0; + +err_dram_size: + dev_err(dev->dev, "DRAM size command not supported for this platform\n"); + return ret; +} + static int amd_pmc_s2d_init(struct amd_pmc_dev *dev) { u32 phys_addr_low, phys_addr_hi; u64 stb_phys_addr; u32 size = 0; + int ret; /* Spill to DRAM feature uses separate SMU message port */ dev->msg_port = 1; - amd_pmc_send_cmd(dev, S2D_TELEMETRY_SIZE, &size, STB_SPILL_TO_DRAM, 1); + /* Get num of IP blocks within the SoC */ + amd_pmc_get_ip_info(dev); + + amd_pmc_send_cmd(dev, S2D_TELEMETRY_SIZE, &size, dev->s2d_msg_id, true); if (size != S2D_TELEMETRY_BYTES_MAX) return -EIO; + /* Get DRAM size */ + ret = amd_pmc_get_dram_size(dev); + if (ret) + dev->dram_size = S2D_TELEMETRY_DRAMBYTES_MAX; + /* Get STB DRAM address */ - amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_LOW, &phys_addr_low, STB_SPILL_TO_DRAM, 1); - amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_HIGH, &phys_addr_hi, STB_SPILL_TO_DRAM, 1); + amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_LOW, &phys_addr_low, dev->s2d_msg_id, true); + amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_HIGH, &phys_addr_hi, dev->s2d_msg_id, true); stb_phys_addr = ((u64)phys_addr_hi << 32 | phys_addr_low); /* Clear msg_port for other SMU operation */ dev->msg_port = 0; - dev->stb_virt_addr = devm_ioremap(dev->dev, stb_phys_addr, S2D_TELEMETRY_DRAMBYTES_MAX); + dev->stb_virt_addr = devm_ioremap(dev->dev, stb_phys_addr, dev->dram_size); if (!dev->stb_virt_addr) return -ENOMEM; @@ -1001,7 +1076,7 @@ static int amd_pmc_probe(struct platform_device *pdev) mutex_init(&dev->lock); - if (enable_stb && (dev->cpu_id == AMD_CPU_ID_YC || dev->cpu_id == AMD_CPU_ID_CB)) { + if (enable_stb && amd_pmc_is_stb_supported(dev)) { err = amd_pmc_s2d_init(dev); if (err) goto err_pci_dev_put; diff --git a/drivers/platform/x86/amd/pmf/Kconfig b/drivers/platform/x86/amd/pmf/Kconfig index d87986adf91e..3064bc8ea167 100644 --- a/drivers/platform/x86/amd/pmf/Kconfig +++ b/drivers/platform/x86/amd/pmf/Kconfig @@ -16,3 +16,14 @@ config AMD_PMF To compile this driver as a module, choose M here: the module will be called amd_pmf. + +config AMD_PMF_DEBUG + bool "PMF debug information" + depends on AMD_PMF + help + Enabling this option would give more debug information on the OEM fed + power setting values for each of the PMF feature. PMF driver gets this + information after evaluating a ACPI method and the information is stored + in the PMF config store. + + Say Y here to enable more debug logs and Say N here if you are not sure. diff --git a/drivers/platform/x86/amd/pmf/auto-mode.c b/drivers/platform/x86/amd/pmf/auto-mode.c index 96a8e1832c05..02ff68be10d0 100644 --- a/drivers/platform/x86/amd/pmf/auto-mode.c +++ b/drivers/platform/x86/amd/pmf/auto-mode.c @@ -15,6 +15,100 @@ static struct auto_mode_mode_config config_store; static const char *state_as_str(unsigned int state); +#ifdef CONFIG_AMD_PMF_DEBUG +static void amd_pmf_dump_auto_mode_defaults(struct auto_mode_mode_config *data) +{ + struct auto_mode_mode_settings *its_mode; + + pr_debug("Auto Mode Data - BEGIN\n"); + + /* time constant */ + pr_debug("balanced_to_perf: %u ms\n", + data->transition[AUTO_TRANSITION_TO_PERFORMANCE].time_constant); + pr_debug("perf_to_balanced: %u ms\n", + data->transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].time_constant); + pr_debug("quiet_to_balanced: %u ms\n", + data->transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].time_constant); + pr_debug("balanced_to_quiet: %u ms\n", + data->transition[AUTO_TRANSITION_TO_QUIET].time_constant); + + /* power floor */ + pr_debug("pfloor_perf: %u mW\n", data->mode_set[AUTO_PERFORMANCE].power_floor); + pr_debug("pfloor_balanced: %u mW\n", data->mode_set[AUTO_BALANCE].power_floor); + pr_debug("pfloor_quiet: %u mW\n", data->mode_set[AUTO_QUIET].power_floor); + + /* Power delta for mode change */ + pr_debug("pd_balanced_to_perf: %u mW\n", + data->transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta); + pr_debug("pd_perf_to_balanced: %u mW\n", + data->transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta); + pr_debug("pd_quiet_to_balanced: %u mW\n", + data->transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta); + pr_debug("pd_balanced_to_quiet: %u mW\n", + data->transition[AUTO_TRANSITION_TO_QUIET].power_delta); + + /* skin temperature limits */ + its_mode = &data->mode_set[AUTO_PERFORMANCE_ON_LAP]; + pr_debug("stt_apu_perf_on_lap: %u C\n", + its_mode->power_control.stt_skin_temp[STT_TEMP_APU]); + pr_debug("stt_hs2_perf_on_lap: %u C\n", + its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]); + pr_debug("stt_min_limit_perf_on_lap: %u mW\n", its_mode->power_control.stt_min); + + its_mode = &data->mode_set[AUTO_PERFORMANCE]; + pr_debug("stt_apu_perf: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_APU]); + pr_debug("stt_hs2_perf: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]); + pr_debug("stt_min_limit_perf: %u mW\n", its_mode->power_control.stt_min); + + its_mode = &data->mode_set[AUTO_BALANCE]; + pr_debug("stt_apu_balanced: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_APU]); + pr_debug("stt_hs2_balanced: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]); + pr_debug("stt_min_limit_balanced: %u mW\n", its_mode->power_control.stt_min); + + its_mode = &data->mode_set[AUTO_QUIET]; + pr_debug("stt_apu_quiet: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_APU]); + pr_debug("stt_hs2_quiet: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]); + pr_debug("stt_min_limit_quiet: %u mW\n", its_mode->power_control.stt_min); + + /* SPL based power limits */ + its_mode = &data->mode_set[AUTO_PERFORMANCE_ON_LAP]; + pr_debug("fppt_perf_on_lap: %u mW\n", its_mode->power_control.fppt); + pr_debug("sppt_perf_on_lap: %u mW\n", its_mode->power_control.sppt); + pr_debug("spl_perf_on_lap: %u mW\n", its_mode->power_control.spl); + pr_debug("sppt_apu_only_perf_on_lap: %u mW\n", its_mode->power_control.sppt_apu_only); + + its_mode = &data->mode_set[AUTO_PERFORMANCE]; + pr_debug("fppt_perf: %u mW\n", its_mode->power_control.fppt); + pr_debug("sppt_perf: %u mW\n", its_mode->power_control.sppt); + pr_debug("spl_perf: %u mW\n", its_mode->power_control.spl); + pr_debug("sppt_apu_only_perf: %u mW\n", its_mode->power_control.sppt_apu_only); + + its_mode = &data->mode_set[AUTO_BALANCE]; + pr_debug("fppt_balanced: %u mW\n", its_mode->power_control.fppt); + pr_debug("sppt_balanced: %u mW\n", its_mode->power_control.sppt); + pr_debug("spl_balanced: %u mW\n", its_mode->power_control.spl); + pr_debug("sppt_apu_only_balanced: %u mW\n", its_mode->power_control.sppt_apu_only); + + its_mode = &data->mode_set[AUTO_QUIET]; + pr_debug("fppt_quiet: %u mW\n", its_mode->power_control.fppt); + pr_debug("sppt_quiet: %u mW\n", its_mode->power_control.sppt); + pr_debug("spl_quiet: %u mW\n", its_mode->power_control.spl); + pr_debug("sppt_apu_only_quiet: %u mW\n", its_mode->power_control.sppt_apu_only); + + /* Fan ID */ + pr_debug("fan_id_perf: %lu\n", + data->mode_set[AUTO_PERFORMANCE].fan_control.fan_id); + pr_debug("fan_id_balanced: %lu\n", + data->mode_set[AUTO_BALANCE].fan_control.fan_id); + pr_debug("fan_id_quiet: %lu\n", + data->mode_set[AUTO_QUIET].fan_control.fan_id); + + pr_debug("Auto Mode Data - END\n"); +} +#else +static void amd_pmf_dump_auto_mode_defaults(struct auto_mode_mode_config *data) {} +#endif + static void amd_pmf_set_automode(struct amd_pmf_dev *dev, int idx, struct auto_mode_mode_config *table) { @@ -85,11 +179,34 @@ void amd_pmf_trans_automode(struct amd_pmf_dev *dev, int socket_power, ktime_t t config_store.transition[i].applied = false; update = true; } + +#ifdef CONFIG_AMD_PMF_DEBUG + dev_dbg(dev->dev, "[AUTO MODE] average_power : %d mW mode: %s\n", avg_power, + state_as_str(config_store.current_mode)); + + dev_dbg(dev->dev, "[AUTO MODE] time: %lld ms timer: %u ms tc: %u ms\n", + time_elapsed_ms, config_store.transition[i].timer, + config_store.transition[i].time_constant); + + dev_dbg(dev->dev, "[AUTO MODE] shiftup: %u pt: %u mW pf: %u mW pd: %u mW\n", + config_store.transition[i].shifting_up, + config_store.transition[i].power_threshold, + config_store.mode_set[i].power_floor, + config_store.transition[i].power_delta); +#endif } dev_dbg(dev->dev, "[AUTO_MODE] avg power: %u mW mode: %s\n", avg_power, state_as_str(config_store.current_mode)); +#ifdef CONFIG_AMD_PMF_DEBUG + dev_dbg(dev->dev, "[AUTO MODE] priority1: %u priority2: %u priority3: %u priority4: %u\n", + config_store.transition[0].applied, + config_store.transition[1].applied, + config_store.transition[2].applied, + config_store.transition[3].applied); +#endif + if (update) { for (j = 0; j < AUTO_TRANSITION_MAX; j++) { /* Apply the mode with highest priority indentified */ @@ -140,6 +257,30 @@ static void amd_pmf_get_power_threshold(void) config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_threshold = config_store.mode_set[AUTO_PERFORMANCE].power_floor - config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta; + +#ifdef CONFIG_AMD_PMF_DEBUG + pr_debug("[AUTO MODE TO_QUIET] pt: %u mW pf: %u mW pd: %u mW\n", + config_store.transition[AUTO_TRANSITION_TO_QUIET].power_threshold, + config_store.mode_set[AUTO_BALANCE].power_floor, + config_store.transition[AUTO_TRANSITION_TO_QUIET].power_delta); + + pr_debug("[AUTO MODE TO_PERFORMANCE] pt: %u mW pf: %u mW pd: %u mW\n", + config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_threshold, + config_store.mode_set[AUTO_BALANCE].power_floor, + config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta); + + pr_debug("[AUTO MODE QUIET_TO_BALANCE] pt: %u mW pf: %u mW pd: %u mW\n", + config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE] + .power_threshold, + config_store.mode_set[AUTO_QUIET].power_floor, + config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta); + + pr_debug("[AUTO MODE PERFORMANCE_TO_BALANCE] pt: %u mW pf: %u mW pd: %u mW\n", + config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE] + .power_threshold, + config_store.mode_set[AUTO_PERFORMANCE].power_floor, + config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta); +#endif } static const char *state_as_str(unsigned int state) @@ -262,6 +403,8 @@ static void amd_pmf_load_defaults_auto_mode(struct amd_pmf_dev *dev) /* set to initial default values */ config_store.current_mode = AUTO_BALANCE; dev->socket_power_history_idx = -1; + + amd_pmf_dump_auto_mode_defaults(&config_store); } int amd_pmf_reset_amt(struct amd_pmf_dev *dev) diff --git a/drivers/platform/x86/amd/pmf/cnqf.c b/drivers/platform/x86/amd/pmf/cnqf.c index 4beb22a19466..539b186e9027 100644 --- a/drivers/platform/x86/amd/pmf/cnqf.c +++ b/drivers/platform/x86/amd/pmf/cnqf.c @@ -13,6 +13,61 @@ static struct cnqf_config config_store; +#ifdef CONFIG_AMD_PMF_DEBUG +static const char *state_as_str_cnqf(unsigned int state) +{ + switch (state) { + case APMF_CNQF_TURBO: + return "turbo"; + case APMF_CNQF_PERFORMANCE: + return "performance"; + case APMF_CNQF_BALANCE: + return "balance"; + case APMF_CNQF_QUIET: + return "quiet"; + default: + return "Unknown CnQF State"; + } +} + +static void amd_pmf_cnqf_dump_defaults(struct apmf_dyn_slider_output *data, int idx) +{ + int i; + + pr_debug("Dynamic Slider %s Defaults - BEGIN\n", idx ? "DC" : "AC"); + pr_debug("size: %u\n", data->size); + pr_debug("flags: 0x%x\n", data->flags); + + /* Time constants */ + pr_debug("t_perf_to_turbo: %u ms\n", data->t_perf_to_turbo); + pr_debug("t_balanced_to_perf: %u ms\n", data->t_balanced_to_perf); + pr_debug("t_quiet_to_balanced: %u ms\n", data->t_quiet_to_balanced); + pr_debug("t_balanced_to_quiet: %u ms\n", data->t_balanced_to_quiet); + pr_debug("t_perf_to_balanced: %u ms\n", data->t_perf_to_balanced); + pr_debug("t_turbo_to_perf: %u ms\n", data->t_turbo_to_perf); + + for (i = 0 ; i < CNQF_MODE_MAX ; i++) { + pr_debug("pfloor_%s: %u mW\n", state_as_str_cnqf(i), data->ps[i].pfloor); + pr_debug("fppt_%s: %u mW\n", state_as_str_cnqf(i), data->ps[i].fppt); + pr_debug("sppt_%s: %u mW\n", state_as_str_cnqf(i), data->ps[i].sppt); + pr_debug("sppt_apuonly_%s: %u mW\n", + state_as_str_cnqf(i), data->ps[i].sppt_apu_only); + pr_debug("spl_%s: %u mW\n", state_as_str_cnqf(i), data->ps[i].spl); + pr_debug("stt_minlimit_%s: %u mW\n", + state_as_str_cnqf(i), data->ps[i].stt_min_limit); + pr_debug("stt_skintemp_apu_%s: %u C\n", state_as_str_cnqf(i), + data->ps[i].stt_skintemp[STT_TEMP_APU]); + pr_debug("stt_skintemp_hs2_%s: %u C\n", state_as_str_cnqf(i), + data->ps[i].stt_skintemp[STT_TEMP_HS2]); + pr_debug("fan_id_%s: %u\n", state_as_str_cnqf(i), data->ps[i].fan_id); + } + + pr_debug("Dynamic Slider %s Defaults - END\n", idx ? "DC" : "AC"); +} +#else +static void amd_pmf_cnqf_dump_defaults(struct apmf_dyn_slider_output *data, int idx) {} +#endif + static int amd_pmf_set_cnqf(struct amd_pmf_dev *dev, int src, int idx, struct cnqf_config *table) { @@ -120,6 +175,13 @@ int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t time_l config_store.trans_param[src][i].count++; tp = &config_store.trans_param[src][i]; + +#ifdef CONFIG_AMD_PMF_DEBUG + dev_dbg(dev->dev, "avg_power: %u mW total_power: %u mW count: %u timer: %u ms\n", + avg_power, config_store.trans_param[src][i].total_power, + config_store.trans_param[src][i].count, + config_store.trans_param[src][i].timer); +#endif if (tp->timer >= tp->time_constant && tp->count) { avg_power = tp->total_power / tp->count; @@ -140,6 +202,18 @@ int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t time_l dev_dbg(dev->dev, "[CNQF] Avg power: %u mW socket power: %u mW mode:%s\n", avg_power, socket_power, state_as_str(config_store.current_mode)); +#ifdef CONFIG_AMD_PMF_DEBUG + dev_dbg(dev->dev, "[CNQF] priority1: %u priority2: %u priority3: %u\n", + config_store.trans_param[src][0].priority, + config_store.trans_param[src][1].priority, + config_store.trans_param[src][2].priority); + + dev_dbg(dev->dev, "[CNQF] priority4: %u priority5: %u priority6: %u\n", + config_store.trans_param[src][3].priority, + config_store.trans_param[src][4].priority, + config_store.trans_param[src][5].priority); +#endif + for (j = 0; j < CNQF_TRANSITION_MAX; j++) { /* apply the highest priority */ if (config_store.trans_param[src][j].priority) { @@ -284,6 +358,7 @@ static int amd_pmf_load_defaults_cnqf(struct amd_pmf_dev *dev) return ret; } + amd_pmf_cnqf_dump_defaults(&out, i); amd_pmf_update_mode_set(i, &out); amd_pmf_update_trans_data(i, &out); amd_pmf_update_power_threshold(i); diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c index bed762d47a14..445ff053b4df 100644 --- a/drivers/platform/x86/amd/pmf/sps.c +++ b/drivers/platform/x86/amd/pmf/sps.c @@ -12,6 +12,60 @@ static struct amd_pmf_static_slider_granular config_store; +#ifdef CONFIG_AMD_PMF_DEBUG +static const char *slider_as_str(unsigned int state) +{ + switch (state) { + case POWER_MODE_PERFORMANCE: + return "PERFORMANCE"; + case POWER_MODE_BALANCED_POWER: + return "BALANCED_POWER"; + case POWER_MODE_POWER_SAVER: + return "POWER_SAVER"; + default: + return "Unknown Slider State"; + } +} + +static const char *source_as_str(unsigned int state) +{ + switch (state) { + case POWER_SOURCE_AC: + return "AC"; + case POWER_SOURCE_DC: + return "DC"; + default: + return "Unknown Power State"; + } +} + +static void amd_pmf_dump_sps_defaults(struct amd_pmf_static_slider_granular *data) +{ + int i, j; + + pr_debug("Static Slider Data - BEGIN\n"); + + for (i = 0; i < POWER_SOURCE_MAX; i++) { + for (j = 0; j < POWER_MODE_MAX; j++) { + pr_debug("--- Source:%s Mode:%s ---\n", source_as_str(i), slider_as_str(j)); + pr_debug("SPL: %u mW\n", data->prop[i][j].spl); + pr_debug("SPPT: %u mW\n", data->prop[i][j].sppt); + pr_debug("SPPT_ApuOnly: %u mW\n", data->prop[i][j].sppt_apu_only); + pr_debug("FPPT: %u mW\n", data->prop[i][j].fppt); + pr_debug("STTMinLimit: %u mW\n", data->prop[i][j].stt_min); + pr_debug("STT_SkinTempLimit_APU: %u C\n", + data->prop[i][j].stt_skin_temp[STT_TEMP_APU]); + pr_debug("STT_SkinTempLimit_HS2: %u C\n", + data->prop[i][j].stt_skin_temp[STT_TEMP_HS2]); + } + } + + pr_debug("Static Slider Data - END\n"); +} +#else +static void amd_pmf_dump_sps_defaults(struct amd_pmf_static_slider_granular *data) {} +#endif + static void amd_pmf_load_defaults_sps(struct amd_pmf_dev *dev) { struct apmf_static_slider_granular_output output; @@ -36,6 +90,7 @@ static void amd_pmf_load_defaults_sps(struct amd_pmf_dev *dev) idx++; } } + amd_pmf_dump_sps_defaults(&config_store); } void amd_pmf_update_slider(struct amd_pmf_dev *dev, bool op, int idx, diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index e02b4aea4f1e..cadbb557a108 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -278,7 +278,7 @@ static u32 gmux_mmio_read32(struct apple_gmux_data *gmux_data, int port) iowrite8(GMUX_MMIO_READ | sizeof(val), gmux_data->iomem_base + GMUX_MMIO_COMMAND_SEND); gmux_mmio_wait(gmux_data); - val = be32_to_cpu(ioread32(gmux_data->iomem_base)); + val = ioread32be(gmux_data->iomem_base); mutex_unlock(&gmux_data->index_lock); return val; @@ -288,7 +288,7 @@ static void gmux_mmio_write32(struct apple_gmux_data *gmux_data, int port, u32 val) { mutex_lock(&gmux_data->index_lock); - iowrite32(cpu_to_be32(val), gmux_data->iomem_base); + iowrite32be(val, gmux_data->iomem_base); iowrite8(port & 0xff, gmux_data->iomem_base + GMUX_MMIO_PORT_SELECT); iowrite8(GMUX_MMIO_WRITE | sizeof(val), gmux_data->iomem_base + GMUX_MMIO_COMMAND_SEND); diff --git a/drivers/platform/x86/asus-tf103c-dock.c b/drivers/platform/x86/asus-tf103c-dock.c index aeb1138464df..8f0f87637c5f 100644 --- a/drivers/platform/x86/asus-tf103c-dock.c +++ b/drivers/platform/x86/asus-tf103c-dock.c @@ -933,7 +933,7 @@ static struct i2c_driver tf103c_dock_driver = { .pm = &tf103c_dock_pm_ops, .acpi_match_table = tf103c_dock_acpi_match, }, - .probe_new = tf103c_dock_probe, + .probe = tf103c_dock_probe, .remove = tf103c_dock_remove, }; module_i2c_driver(tf103c_dock_driver); diff --git a/drivers/platform/x86/dell/dell-rbtn.c b/drivers/platform/x86/dell/dell-rbtn.c index aa0e6c907494..c8fcb537fd65 100644 --- a/drivers/platform/x86/dell/dell-rbtn.c +++ b/drivers/platform/x86/dell/dell-rbtn.c @@ -395,16 +395,16 @@ static int rbtn_add(struct acpi_device *device) return -EINVAL; } + rbtn_data = devm_kzalloc(&device->dev, sizeof(*rbtn_data), GFP_KERNEL); + if (!rbtn_data) + return -ENOMEM; + ret = rbtn_acquire(device, true); if (ret < 0) { dev_err(&device->dev, "Cannot enable device\n"); return ret; } - rbtn_data = devm_kzalloc(&device->dev, sizeof(*rbtn_data), GFP_KERNEL); - if (!rbtn_data) - return -ENOMEM; - rbtn_data->type = type; device->driver_data = rbtn_data; @@ -420,10 +420,12 @@ static int rbtn_add(struct acpi_device *device) break; default: ret = -EINVAL; + break; } + if (ret) + rbtn_acquire(device, false); return ret; - } static void rbtn_remove(struct acpi_device *device) @@ -442,7 +444,6 @@ static void rbtn_remove(struct acpi_device *device) } rbtn_acquire(device, false); - device->driver_data = NULL; } static void rbtn_notify(struct acpi_device *device, u32 event) diff --git a/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c b/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c index 0285b47d99d1..b68dd11cb892 100644 --- a/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c +++ b/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c @@ -303,16 +303,13 @@ union acpi_object *get_wmiobj_pointer(int instance_id, const char *guid_string) */ int get_instance_count(const char *guid_string) { - union acpi_object *wmi_obj = NULL; - int i = 0; + int ret; - do { - kfree(wmi_obj); - wmi_obj = get_wmiobj_pointer(i, guid_string); - i++; - } while (wmi_obj); + ret = wmi_instance_count(guid_string); + if (ret < 0) + return 0; - return (i-1); + return ret; } /** diff --git a/drivers/platform/x86/gigabyte-wmi.c b/drivers/platform/x86/gigabyte-wmi.c index 2a426040f749..f6ba88baee4d 100644 --- a/drivers/platform/x86/gigabyte-wmi.c +++ b/drivers/platform/x86/gigabyte-wmi.c @@ -5,7 +5,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/acpi.h> -#include <linux/dmi.h> #include <linux/hwmon.h> #include <linux/module.h> #include <linux/wmi.h> @@ -13,10 +12,6 @@ #define GIGABYTE_WMI_GUID "DEADBEEF-2001-0000-00A0-C90629100000" #define NUM_TEMPERATURE_SENSORS 6 -static bool force_load; -module_param(force_load, bool, 0444); -MODULE_PARM_DESC(force_load, "Force loading on unknown platform"); - static u8 usable_sensors_mask; enum gigabyte_wmi_commandtype { @@ -99,7 +94,7 @@ static umode_t gigabyte_wmi_hwmon_is_visible(const void *data, enum hwmon_sensor return usable_sensors_mask & BIT(channel) ? 0444 : 0; } -static const struct hwmon_channel_info *gigabyte_wmi_hwmon_info[] = { +static const struct hwmon_channel_info * const gigabyte_wmi_hwmon_info[] = { HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT, HWMON_T_INPUT, @@ -133,49 +128,10 @@ static u8 gigabyte_wmi_detect_sensor_usability(struct wmi_device *wdev) return r; } -#define DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME(name) \ - { .matches = { \ - DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."), \ - DMI_EXACT_MATCH(DMI_BOARD_NAME, name), \ - }} - -static const struct dmi_system_id gigabyte_wmi_known_working_platforms[] = { - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("A320M-S2H V2-CF"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M DS3H-CF"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M DS3H WIFI-CF"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M S2H V2"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE AX V2"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE V2"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 GAMING X V2"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550I AORUS PRO AX"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550M AORUS PRO-P"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550M DS3H"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B650 AORUS ELITE AX"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B660 GAMING X DDR4"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B660I AORUS PRO DDR4"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("Z390 I AORUS PRO WIFI-CF"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("Z490 AORUS ELITE AC"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 AORUS ELITE"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 AORUS ELITE WIFI"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 GAMING X"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 I AORUS PRO WIFI"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 UD"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570S AORUS ELITE"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("Z690M AORUS ELITE AX DDR4"), - { } -}; - static int gigabyte_wmi_probe(struct wmi_device *wdev, const void *context) { struct device *hwmon_dev; - if (!dmi_check_system(gigabyte_wmi_known_working_platforms)) { - if (!force_load) - return -ENODEV; - dev_warn(&wdev->dev, "Forcing load on unknown platform"); - } - usable_sensors_mask = gigabyte_wmi_detect_sensor_usability(wdev); if (!usable_sensors_mask) { dev_info(&wdev->dev, "No temperature sensors usable"); diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c index 6364ae262705..e76e5458db35 100644 --- a/drivers/platform/x86/hp/hp-wmi.c +++ b/drivers/platform/x86/hp/hp-wmi.c @@ -66,6 +66,11 @@ static const char *const omen_thermal_profile_force_v0_boards[] = { "8607", "8746", "8747", "8749", "874A", "8748" }; +/* DMI Board names of Victus laptops */ +static const char * const victus_thermal_profile_boards[] = { + "8A25" +}; + enum hp_wmi_radio { HPWMI_WIFI = 0x0, HPWMI_BLUETOOTH = 0x1, @@ -90,6 +95,7 @@ enum hp_wmi_event_ids { HPWMI_PEAKSHIFT_PERIOD = 0x0F, HPWMI_BATTERY_CHARGE_PERIOD = 0x10, HPWMI_SANITIZATION_MODE = 0x17, + HPWMI_CAMERA_TOGGLE = 0x1A, HPWMI_OMEN_KEY = 0x1D, HPWMI_SMART_EXPERIENCE_APP = 0x21, }; @@ -176,6 +182,12 @@ enum hp_thermal_profile_omen_v1 { HP_OMEN_V1_THERMAL_PROFILE_COOL = 0x50, }; +enum hp_thermal_profile_victus { + HP_VICTUS_THERMAL_PROFILE_DEFAULT = 0x00, + HP_VICTUS_THERMAL_PROFILE_PERFORMANCE = 0x01, + HP_VICTUS_THERMAL_PROFILE_QUIET = 0x03, +}; + enum hp_thermal_profile { HP_THERMAL_PROFILE_PERFORMANCE = 0x00, HP_THERMAL_PROFILE_DEFAULT = 0x01, @@ -222,6 +234,7 @@ static const struct key_entry hp_wmi_keymap[] = { { KE_IGNORE, 0x121a4, }, /* Win Lock Off */ { KE_KEY, 0x21a5, { KEY_PROG2 } }, /* HP Omen Key */ { KE_KEY, 0x21a7, { KEY_FN_ESC } }, + { KE_KEY, 0x21a8, { KEY_PROG2 } }, /* HP Envy x360 programmable key */ { KE_KEY, 0x21a9, { KEY_TOUCHPAD_OFF } }, { KE_KEY, 0x121a9, { KEY_TOUCHPAD_ON } }, { KE_KEY, 0x231b, { KEY_HELP } }, @@ -229,6 +242,7 @@ static const struct key_entry hp_wmi_keymap[] = { }; static struct input_dev *hp_wmi_input_dev; +static struct input_dev *camera_shutter_input_dev; static struct platform_device *hp_wmi_platform_dev; static struct platform_profile_handler platform_profile_handler; static bool platform_profile_support; @@ -740,6 +754,33 @@ static ssize_t postcode_store(struct device *dev, struct device_attribute *attr, return count; } +static int camera_shutter_input_setup(void) +{ + int err; + + camera_shutter_input_dev = input_allocate_device(); + if (!camera_shutter_input_dev) + return -ENOMEM; + + camera_shutter_input_dev->name = "HP WMI camera shutter"; + camera_shutter_input_dev->phys = "wmi/input1"; + camera_shutter_input_dev->id.bustype = BUS_HOST; + + __set_bit(EV_SW, camera_shutter_input_dev->evbit); + __set_bit(SW_CAMERA_LENS_COVER, camera_shutter_input_dev->swbit); + + err = input_register_device(camera_shutter_input_dev); + if (err) + goto err_free_dev; + + return 0; + + err_free_dev: + input_free_device(camera_shutter_input_dev); + camera_shutter_input_dev = NULL; + return err; +} + static DEVICE_ATTR_RO(display); static DEVICE_ATTR_RO(hddtemp); static DEVICE_ATTR_RW(als); @@ -816,7 +857,6 @@ static void hp_wmi_notify(u32 value, void *context) case HPWMI_SMART_ADAPTER: break; case HPWMI_BEZEL_BUTTON: - case HPWMI_OMEN_KEY: key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY); if (key_code < 0) break; @@ -825,6 +865,16 @@ static void hp_wmi_notify(u32 value, void *context) key_code, 1, true)) pr_info("Unknown key code - 0x%x\n", key_code); break; + case HPWMI_OMEN_KEY: + if (event_data) /* Only should be true for HP Omen */ + key_code = event_data; + else + key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY); + + if (!sparse_keymap_report_event(hp_wmi_input_dev, + key_code, 1, true)) + pr_info("Unknown key code - 0x%x\n", key_code); + break; case HPWMI_WIRELESS: if (rfkill2_count) { hp_wmi_rfkill2_refresh(); @@ -867,6 +917,20 @@ static void hp_wmi_notify(u32 value, void *context) break; case HPWMI_SANITIZATION_MODE: break; + case HPWMI_CAMERA_TOGGLE: + if (!camera_shutter_input_dev) + if (camera_shutter_input_setup()) { + pr_err("Failed to setup camera shutter input device\n"); + break; + } + if (event_data == 0xff) + input_report_switch(camera_shutter_input_dev, SW_CAMERA_LENS_COVER, 1); + else if (event_data == 0xfe) + input_report_switch(camera_shutter_input_dev, SW_CAMERA_LENS_COVER, 0); + else + pr_warn("Unknown camera shutter state - 0x%x\n", event_data); + input_sync(camera_shutter_input_dev); + break; case HPWMI_SMART_EXPERIENCE_APP: break; default: @@ -1246,6 +1310,70 @@ static int hp_wmi_platform_profile_set(struct platform_profile_handler *pprof, return 0; } +static bool is_victus_thermal_profile(void) +{ + const char *board_name = dmi_get_system_info(DMI_BOARD_NAME); + + if (!board_name) + return false; + + return match_string(victus_thermal_profile_boards, + ARRAY_SIZE(victus_thermal_profile_boards), + board_name) >= 0; +} + +static int platform_profile_victus_get(struct platform_profile_handler *pprof, + enum platform_profile_option *profile) +{ + int tp; + + tp = omen_thermal_profile_get(); + if (tp < 0) + return tp; + + switch (tp) { + case HP_VICTUS_THERMAL_PROFILE_PERFORMANCE: + *profile = PLATFORM_PROFILE_PERFORMANCE; + break; + case HP_VICTUS_THERMAL_PROFILE_DEFAULT: + *profile = PLATFORM_PROFILE_BALANCED; + break; + case HP_VICTUS_THERMAL_PROFILE_QUIET: + *profile = PLATFORM_PROFILE_QUIET; + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static int platform_profile_victus_set(struct platform_profile_handler *pprof, + enum platform_profile_option profile) +{ + int err, tp; + + switch (profile) { + case PLATFORM_PROFILE_PERFORMANCE: + tp = HP_VICTUS_THERMAL_PROFILE_PERFORMANCE; + break; + case PLATFORM_PROFILE_BALANCED: + tp = HP_VICTUS_THERMAL_PROFILE_DEFAULT; + break; + case PLATFORM_PROFILE_QUIET: + tp = HP_VICTUS_THERMAL_PROFILE_QUIET; + break; + default: + return -EOPNOTSUPP; + } + + err = omen_thermal_profile_set(tp); + if (err < 0) + return err; + + return 0; +} + static int thermal_profile_setup(void) { int err, tp; @@ -1266,6 +1394,25 @@ static int thermal_profile_setup(void) platform_profile_handler.profile_get = platform_profile_omen_get; platform_profile_handler.profile_set = platform_profile_omen_set; + + set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices); + } else if (is_victus_thermal_profile()) { + tp = omen_thermal_profile_get(); + if (tp < 0) + return tp; + + /* + * call thermal profile write command to ensure that the + * firmware correctly sets the OEM variables + */ + err = omen_thermal_profile_set(tp); + if (err < 0) + return err; + + platform_profile_handler.profile_get = platform_profile_victus_get; + platform_profile_handler.profile_set = platform_profile_victus_set; + + set_bit(PLATFORM_PROFILE_QUIET, platform_profile_handler.choices); } else { tp = thermal_profile_get(); @@ -1284,9 +1431,9 @@ static int thermal_profile_setup(void) platform_profile_handler.profile_set = hp_wmi_platform_profile_set; set_bit(PLATFORM_PROFILE_QUIET, platform_profile_handler.choices); + set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices); } - set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices); set_bit(PLATFORM_PROFILE_BALANCED, platform_profile_handler.choices); set_bit(PLATFORM_PROFILE_PERFORMANCE, platform_profile_handler.choices); @@ -1483,7 +1630,7 @@ static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type, } } -static const struct hwmon_channel_info *info[] = { +static const struct hwmon_channel_info * const info[] = { HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT, HWMON_F_INPUT), HWMON_CHANNEL_INFO(pwm, HWMON_PWM_ENABLE), NULL @@ -1565,6 +1712,9 @@ static void __exit hp_wmi_exit(void) if (wmi_has_guid(HPWMI_EVENT_GUID)) hp_wmi_input_destroy(); + if (camera_shutter_input_dev) + input_unregister_device(camera_shutter_input_dev); + if (hp_wmi_platform_dev) { platform_device_unregister(hp_wmi_platform_dev); platform_driver_unregister(&hp_wmi_driver); diff --git a/drivers/platform/x86/intel/int3472/clk_and_regulator.c b/drivers/platform/x86/intel/int3472/clk_and_regulator.c index 399f0623ca1b..61aeca804ba2 100644 --- a/drivers/platform/x86/intel/int3472/clk_and_regulator.c +++ b/drivers/platform/x86/intel/int3472/clk_and_regulator.c @@ -5,6 +5,7 @@ #include <linux/clkdev.h> #include <linux/clk-provider.h> #include <linux/device.h> +#include <linux/dmi.h> #include <linux/gpio/consumer.h> #include <linux/regulator/driver.h> #include <linux/slab.h> @@ -12,6 +13,41 @@ #include "common.h" /* + * 82c0d13a-78c5-4244-9bb1-eb8b539a8d11 + * This _DSM GUID allows controlling the sensor clk when it is not controlled + * through a GPIO. + */ +static const guid_t img_clk_guid = + GUID_INIT(0x82c0d13a, 0x78c5, 0x4244, + 0x9b, 0xb1, 0xeb, 0x8b, 0x53, 0x9a, 0x8d, 0x11); + +static void skl_int3472_enable_clk(struct int3472_clock *clk, int enable) +{ + struct int3472_discrete_device *int3472 = to_int3472_device(clk); + union acpi_object args[3]; + union acpi_object argv4; + + if (clk->ena_gpio) { + gpiod_set_value_cansleep(clk->ena_gpio, enable); + return; + } + + args[0].integer.type = ACPI_TYPE_INTEGER; + args[0].integer.value = clk->imgclk_index; + args[1].integer.type = ACPI_TYPE_INTEGER; + args[1].integer.value = enable; + args[2].integer.type = ACPI_TYPE_INTEGER; + args[2].integer.value = 1; + + argv4.type = ACPI_TYPE_PACKAGE; + argv4.package.count = 3; + argv4.package.elements = args; + + acpi_evaluate_dsm(acpi_device_handle(int3472->adev), &img_clk_guid, + 0, 1, &argv4); +} + +/* * The regulators have to have .ops to be valid, but the only ops we actually * support are .enable and .disable which are handled via .ena_gpiod. Pass an * empty struct to clear the check without lying about capabilities. @@ -20,17 +56,13 @@ static const struct regulator_ops int3472_gpio_regulator_ops; static int skl_int3472_clk_prepare(struct clk_hw *hw) { - struct int3472_gpio_clock *clk = to_int3472_clk(hw); - - gpiod_set_value_cansleep(clk->ena_gpio, 1); + skl_int3472_enable_clk(to_int3472_clk(hw), 1); return 0; } static void skl_int3472_clk_unprepare(struct clk_hw *hw) { - struct int3472_gpio_clock *clk = to_int3472_clk(hw); - - gpiod_set_value_cansleep(clk->ena_gpio, 0); + skl_int3472_enable_clk(to_int3472_clk(hw), 0); } static int skl_int3472_clk_enable(struct clk_hw *hw) @@ -73,7 +105,7 @@ static unsigned int skl_int3472_get_clk_frequency(struct int3472_discrete_device static unsigned long skl_int3472_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct int3472_gpio_clock *clk = to_int3472_clk(hw); + struct int3472_clock *clk = to_int3472_clk(hw); return clk->frequency; } @@ -86,8 +118,51 @@ static const struct clk_ops skl_int3472_clock_ops = { .recalc_rate = skl_int3472_clk_recalc_rate, }; -int skl_int3472_register_clock(struct int3472_discrete_device *int3472, - struct acpi_resource_gpio *agpio, u32 polarity) +int skl_int3472_register_dsm_clock(struct int3472_discrete_device *int3472) +{ + struct acpi_device *adev = int3472->adev; + struct clk_init_data init = { + .ops = &skl_int3472_clock_ops, + .flags = CLK_GET_RATE_NOCACHE, + }; + int ret; + + if (int3472->clock.cl) + return 0; /* A GPIO controlled clk has already been registered */ + + if (!acpi_check_dsm(adev->handle, &img_clk_guid, 0, BIT(1))) + return 0; /* DSM clock control is not available */ + + init.name = kasprintf(GFP_KERNEL, "%s-clk", acpi_dev_name(adev)); + if (!init.name) + return -ENOMEM; + + int3472->clock.frequency = skl_int3472_get_clk_frequency(int3472); + int3472->clock.clk_hw.init = &init; + int3472->clock.clk = clk_register(&adev->dev, &int3472->clock.clk_hw); + if (IS_ERR(int3472->clock.clk)) { + ret = PTR_ERR(int3472->clock.clk); + goto out_free_init_name; + } + + int3472->clock.cl = clkdev_create(int3472->clock.clk, NULL, int3472->sensor_name); + if (!int3472->clock.cl) { + ret = -ENOMEM; + goto err_unregister_clk; + } + + kfree(init.name); + return 0; + +err_unregister_clk: + clk_unregister(int3472->clock.clk); +out_free_init_name: + kfree(init.name); + return ret; +} + +int skl_int3472_register_gpio_clock(struct int3472_discrete_device *int3472, + struct acpi_resource_gpio *agpio, u32 polarity) { char *path = agpio->resource_source.string_ptr; struct clk_init_data init = { @@ -160,32 +235,73 @@ void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472) gpiod_put(int3472->clock.ena_gpio); } +/* + * The INT3472 device is going to be the only supplier of a regulator for + * the sensor device. But unlike the clk framework the regulator framework + * does not allow matching by consumer-device-name only. + * + * Ideally all sensor drivers would use "avdd" as supply-id. But for drivers + * where this cannot be changed because another supply-id is already used in + * e.g. DeviceTree files an alias for the other supply-id can be added here. + * + * Do not forget to update GPIO_REGULATOR_SUPPLY_MAP_COUNT when changing this. + */ +static const char * const skl_int3472_regulator_map_supplies[] = { + "avdd", + "AVDD", +}; + +static_assert(ARRAY_SIZE(skl_int3472_regulator_map_supplies) == + GPIO_REGULATOR_SUPPLY_MAP_COUNT); + +/* + * On some models there is a single GPIO regulator which is shared between + * sensors and only listed in the ACPI resources of one sensor. + * This DMI table contains the name of the second sensor. This is used to add + * entries for the second sensor to the supply_map. + */ +const struct dmi_system_id skl_int3472_regulator_second_sensor[] = { + { + /* Lenovo Miix 510-12IKB */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "MIIX 510-12IKB"), + }, + .driver_data = "i2c-OVTI2680:00", + }, + { } +}; + int skl_int3472_register_regulator(struct int3472_discrete_device *int3472, struct acpi_resource_gpio *agpio) { - const struct int3472_sensor_config *sensor_config; char *path = agpio->resource_source.string_ptr; - struct regulator_consumer_supply supply_map; struct regulator_init_data init_data = { }; struct regulator_config cfg = { }; - int ret; - - sensor_config = int3472->sensor_config; - if (IS_ERR(sensor_config)) { - dev_err(int3472->dev, "No sensor module config\n"); - return PTR_ERR(sensor_config); - } - - if (!sensor_config->supply_map.supply) { - dev_err(int3472->dev, "No supply name defined\n"); - return -ENODEV; + const char *second_sensor = NULL; + const struct dmi_system_id *id; + int i, j, ret; + + id = dmi_first_match(skl_int3472_regulator_second_sensor); + if (id) + second_sensor = id->driver_data; + + for (i = 0, j = 0; i < ARRAY_SIZE(skl_int3472_regulator_map_supplies); i++) { + int3472->regulator.supply_map[j].supply = skl_int3472_regulator_map_supplies[i]; + int3472->regulator.supply_map[j].dev_name = int3472->sensor_name; + j++; + + if (second_sensor) { + int3472->regulator.supply_map[j].supply = + skl_int3472_regulator_map_supplies[i]; + int3472->regulator.supply_map[j].dev_name = second_sensor; + j++; + } } init_data.constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS; - init_data.num_consumer_supplies = 1; - supply_map = sensor_config->supply_map; - supply_map.dev_name = int3472->sensor_name; - init_data.consumer_supplies = &supply_map; + init_data.consumer_supplies = int3472->regulator.supply_map; + init_data.num_consumer_supplies = j; snprintf(int3472->regulator.regulator_name, sizeof(int3472->regulator.regulator_name), "%s-regulator", diff --git a/drivers/platform/x86/intel/int3472/common.h b/drivers/platform/x86/intel/int3472/common.h index 61688e450ce5..9f29baa13860 100644 --- a/drivers/platform/x86/intel/int3472/common.h +++ b/drivers/platform/x86/intel/int3472/common.h @@ -28,6 +28,7 @@ #define GPIO_REGULATOR_NAME_LENGTH 21 #define GPIO_REGULATOR_SUPPLY_NAME_LENGTH 9 +#define GPIO_REGULATOR_SUPPLY_MAP_COUNT 2 #define INT3472_LED_MAX_NAME_LEN 32 @@ -43,7 +44,7 @@ } #define to_int3472_clk(hw) \ - container_of(hw, struct int3472_gpio_clock, clk_hw) + container_of(hw, struct int3472_clock, clk_hw) #define to_int3472_device(clk) \ container_of(clk, struct int3472_discrete_device, clock) @@ -64,18 +65,9 @@ struct int3472_cldb { u8 control_logic_type; u8 control_logic_id; u8 sensor_card_sku; - u8 reserved[28]; -}; - -struct int3472_gpio_function_remap { - const char *documented; - const char *actual; -}; - -struct int3472_sensor_config { - const char *sensor_module_name; - struct regulator_consumer_supply supply_map; - const struct int3472_gpio_function_remap *function_maps; + u8 reserved[10]; + u8 clock_source; + u8 reserved2[17]; }; struct int3472_discrete_device { @@ -87,6 +79,8 @@ struct int3472_discrete_device { const struct int3472_sensor_config *sensor_config; struct int3472_gpio_regulator { + /* SUPPLY_MAP_COUNT * 2 to make room for second sensor mappings */ + struct regulator_consumer_supply supply_map[GPIO_REGULATOR_SUPPLY_MAP_COUNT * 2]; char regulator_name[GPIO_REGULATOR_NAME_LENGTH]; char supply_name[GPIO_REGULATOR_SUPPLY_NAME_LENGTH]; struct gpio_desc *gpio; @@ -94,12 +88,13 @@ struct int3472_discrete_device { struct regulator_desc rdesc; } regulator; - struct int3472_gpio_clock { + struct int3472_clock { struct clk *clk; struct clk_hw clk_hw; struct clk_lookup *cl; struct gpio_desc *ena_gpio; u32 frequency; + u8 imgclk_index; } clock; struct int3472_pled { @@ -121,8 +116,9 @@ int skl_int3472_get_sensor_adev_and_name(struct device *dev, struct acpi_device **sensor_adev_ret, const char **name_ret); -int skl_int3472_register_clock(struct int3472_discrete_device *int3472, - struct acpi_resource_gpio *agpio, u32 polarity); +int skl_int3472_register_gpio_clock(struct int3472_discrete_device *int3472, + struct acpi_resource_gpio *agpio, u32 polarity); +int skl_int3472_register_dsm_clock(struct int3472_discrete_device *int3472); void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472); int skl_int3472_register_regulator(struct int3472_discrete_device *int3472, diff --git a/drivers/platform/x86/intel/int3472/discrete.c b/drivers/platform/x86/intel/int3472/discrete.c index ef020e23e596..e33c2d75975c 100644 --- a/drivers/platform/x86/intel/int3472/discrete.c +++ b/drivers/platform/x86/intel/int3472/discrete.c @@ -2,6 +2,7 @@ /* Author: Dan Scally <djrscally@gmail.com> */ #include <linux/acpi.h> +#include <linux/bitfield.h> #include <linux/device.h> #include <linux/gpio/consumer.h> #include <linux/gpio/machine.h> @@ -25,6 +26,10 @@ static const guid_t int3472_gpio_guid = GUID_INIT(0x79234640, 0x9e10, 0x4fea, 0xa5, 0xc1, 0xb5, 0xaa, 0x8b, 0x19, 0x75, 0x6f); +#define INT3472_GPIO_DSM_TYPE GENMASK(7, 0) +#define INT3472_GPIO_DSM_PIN GENMASK(15, 8) +#define INT3472_GPIO_DSM_SENSOR_ON_VAL GENMASK(31, 24) + /* * 822ace8f-2814-4174-a56b-5f029fe079ee * This _DSM GUID returns a string from the sensor device, which acts as a @@ -34,69 +39,23 @@ static const guid_t cio2_sensor_module_guid = GUID_INIT(0x822ace8f, 0x2814, 0x4174, 0xa5, 0x6b, 0x5f, 0x02, 0x9f, 0xe0, 0x79, 0xee); -/* - * Here follows platform specific mapping information that we can pass to - * the functions mapping resources to the sensors. Where the sensors have - * a power enable pin defined in DSDT we need to provide a supply name so - * the sensor drivers can find the regulator. The device name will be derived - * from the sensor's ACPI device within the code. Optionally, we can provide a - * NULL terminated array of function name mappings to deal with any platform - * specific deviations from the documented behaviour of GPIOs. - * - * Map a GPIO function name to NULL to prevent the driver from mapping that - * GPIO at all. - */ - -static const struct int3472_gpio_function_remap ov2680_gpio_function_remaps[] = { - { "reset", NULL }, - { "powerdown", "reset" }, - { } -}; - -static const struct int3472_sensor_config int3472_sensor_configs[] = { - /* Lenovo Miix 510-12ISK - OV2680, Front */ - { "GNDF140809R", { 0 }, ov2680_gpio_function_remaps }, - /* Lenovo Miix 510-12ISK - OV5648, Rear */ - { "GEFF150023R", REGULATOR_SUPPLY("avdd", NULL), NULL }, - /* Surface Go 1&2 - OV5693, Front */ - { "YHCU", REGULATOR_SUPPLY("avdd", NULL), NULL }, -}; - -static const struct int3472_sensor_config * -skl_int3472_get_sensor_module_config(struct int3472_discrete_device *int3472) +static void skl_int3472_log_sensor_module_name(struct int3472_discrete_device *int3472) { union acpi_object *obj; - unsigned int i; obj = acpi_evaluate_dsm_typed(int3472->sensor->handle, &cio2_sensor_module_guid, 0x00, 0x01, NULL, ACPI_TYPE_STRING); - - if (!obj) { - dev_err(int3472->dev, - "Failed to get sensor module string from _DSM\n"); - return ERR_PTR(-ENODEV); + if (obj) { + dev_dbg(int3472->dev, "Sensor module id: '%s'\n", obj->string.pointer); + ACPI_FREE(obj); } - - for (i = 0; i < ARRAY_SIZE(int3472_sensor_configs); i++) { - if (!strcmp(int3472_sensor_configs[i].sensor_module_name, - obj->string.pointer)) - break; - } - - ACPI_FREE(obj); - - if (i >= ARRAY_SIZE(int3472_sensor_configs)) - return ERR_PTR(-EINVAL); - - return &int3472_sensor_configs[i]; } static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int3472, struct acpi_resource_gpio *agpio, const char *func, u32 polarity) { - const struct int3472_sensor_config *sensor_config; char *path = agpio->resource_source.string_ptr; struct gpiod_lookup *table_entry; struct acpi_device *adev; @@ -108,22 +67,6 @@ static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int347 return -EINVAL; } - sensor_config = int3472->sensor_config; - if (!IS_ERR(sensor_config) && sensor_config->function_maps) { - const struct int3472_gpio_function_remap *remap; - - for (remap = sensor_config->function_maps; remap->documented; remap++) { - if (!strcmp(func, remap->documented)) { - func = remap->actual; - break; - } - } - } - - /* Functions mapped to NULL should not be mapped to the sensor */ - if (!func) - return 0; - status = acpi_get_handle(NULL, path, &handle); if (ACPI_FAILURE(status)) return -EINVAL; @@ -211,8 +154,8 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares, { struct int3472_discrete_device *int3472 = data; struct acpi_resource_gpio *agpio; + u8 active_value, pin, type; union acpi_object *obj; - u8 active_value, type; const char *err_msg; const char *func; u32 polarity; @@ -236,12 +179,17 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares, return 1; } - type = obj->integer.value & 0xff; + type = FIELD_GET(INT3472_GPIO_DSM_TYPE, obj->integer.value); int3472_get_func_and_polarity(type, &func, &polarity); - /* If bits 31-24 of the _DSM entry are all 0 then the signal is inverted */ - active_value = obj->integer.value >> 24; + pin = FIELD_GET(INT3472_GPIO_DSM_PIN, obj->integer.value); + if (pin != agpio->pin_table[0]) + dev_warn(int3472->dev, "%s %s pin number mismatch _DSM %d resource %d\n", + func, agpio->resource_source.string_ptr, pin, + agpio->pin_table[0]); + + active_value = FIELD_GET(INT3472_GPIO_DSM_SENSOR_ON_VAL, obj->integer.value); if (!active_value) polarity ^= GPIO_ACTIVE_LOW; @@ -258,7 +206,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares, break; case INT3472_GPIO_TYPE_CLK_ENABLE: - ret = skl_int3472_register_clock(int3472, agpio, polarity); + ret = skl_int3472_register_gpio_clock(int3472, agpio, polarity); if (ret) err_msg = "Failed to register clock\n"; @@ -297,11 +245,7 @@ static int skl_int3472_parse_crs(struct int3472_discrete_device *int3472) LIST_HEAD(resource_list); int ret; - /* - * No error check, because not having a sensor config is not necessarily - * a failure mode. - */ - int3472->sensor_config = skl_int3472_get_sensor_module_config(int3472); + skl_int3472_log_sensor_module_name(int3472); ret = acpi_dev_get_resources(int3472->adev, &resource_list, skl_int3472_handle_gpio_resources, @@ -311,6 +255,11 @@ static int skl_int3472_parse_crs(struct int3472_discrete_device *int3472) acpi_dev_free_resource_list(&resource_list); + /* Register _DSM based clock (no-op if a GPIO clock was already registered) */ + ret = skl_int3472_register_dsm_clock(int3472); + if (ret < 0) + return ret; + int3472->gpios.dev_id = int3472->sensor_name; gpiod_add_lookup_table(&int3472->gpios); @@ -356,6 +305,7 @@ static int skl_int3472_discrete_probe(struct platform_device *pdev) int3472->adev = adev; int3472->dev = &pdev->dev; platform_set_drvdata(pdev, int3472); + int3472->clock.imgclk_index = cldb.clock_source; ret = skl_int3472_get_sensor_adev_and_name(&pdev->dev, &int3472->sensor, &int3472->sensor_name); diff --git a/drivers/platform/x86/intel/int3472/tps68470.c b/drivers/platform/x86/intel/int3472/tps68470.c index 5b8d1a9620a5..1e107fd49f82 100644 --- a/drivers/platform/x86/intel/int3472/tps68470.c +++ b/drivers/platform/x86/intel/int3472/tps68470.c @@ -250,7 +250,7 @@ static struct i2c_driver int3472_tps68470 = { .name = "int3472-tps68470", .acpi_match_table = int3472_device_id, }, - .probe_new = skl_int3472_tps68470_probe, + .probe = skl_int3472_tps68470_probe, .remove = skl_int3472_tps68470_remove, }; module_i2c_driver(int3472_tps68470); diff --git a/drivers/platform/x86/intel/pmc/Makefile b/drivers/platform/x86/intel/pmc/Makefile index f96bc2e19503..3a4cf1cbc1ca 100644 --- a/drivers/platform/x86/intel/pmc/Makefile +++ b/drivers/platform/x86/intel/pmc/Makefile @@ -3,8 +3,8 @@ # Intel x86 Platform-Specific Drivers # -intel_pmc_core-y := core.o spt.o cnp.o icl.o tgl.o \ - adl.o mtl.o +intel_pmc_core-y := core.o core_ssram.o spt.o cnp.o \ + icl.o tgl.o adl.o mtl.o obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o intel_pmc_core_pltdrv-y := pltdrv.o obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core_pltdrv.o diff --git a/drivers/platform/x86/intel/pmc/adl.c b/drivers/platform/x86/intel/pmc/adl.c index 5cbd40979f2a..5006008e01be 100644 --- a/drivers/platform/x86/intel/pmc/adl.c +++ b/drivers/platform/x86/intel/pmc/adl.c @@ -309,17 +309,21 @@ const struct pmc_reg_map adl_reg_map = { .lpm_live_status_offset = ADL_LPM_LIVE_STATUS_OFFSET, }; -void adl_core_configure(struct pmc_dev *pmcdev) +int adl_core_init(struct pmc_dev *pmcdev) { + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + int ret; + + pmc->map = &adl_reg_map; + ret = get_primary_reg_base(pmc); + if (ret) + return ret; + /* Due to a hardware limitation, the GBE LTR blocks PC10 * when a cable is attached. Tell the PMC to ignore it. */ dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); pmc_core_send_ltr_ignore(pmcdev, 3); -} -void adl_core_init(struct pmc_dev *pmcdev) -{ - pmcdev->map = &adl_reg_map; - pmcdev->core_configure = adl_core_configure; + return 0; } diff --git a/drivers/platform/x86/intel/pmc/cnp.c b/drivers/platform/x86/intel/pmc/cnp.c index 7fb38815c4eb..420aaa1d7c76 100644 --- a/drivers/platform/x86/intel/pmc/cnp.c +++ b/drivers/platform/x86/intel/pmc/cnp.c @@ -204,7 +204,21 @@ const struct pmc_reg_map cnp_reg_map = { .etr3_offset = ETR3_OFFSET, }; -void cnp_core_init(struct pmc_dev *pmcdev) +int cnp_core_init(struct pmc_dev *pmcdev) { - pmcdev->map = &cnp_reg_map; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + int ret; + + pmc->map = &cnp_reg_map; + ret = get_primary_reg_base(pmc); + if (ret) + return ret; + + /* Due to a hardware limitation, the GBE LTR blocks PC10 + * when a cable is attached. Tell the PMC to ignore it. + */ + dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); + pmc_core_send_ltr_ignore(pmcdev, 3); + + return 0; } diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c index da6e7206d38b..5a36b3f77bc5 100644 --- a/drivers/platform/x86/intel/pmc/core.c +++ b/drivers/platform/x86/intel/pmc/core.c @@ -53,18 +53,18 @@ const struct pmc_bit_map msr_map[] = { {} }; -static inline u32 pmc_core_reg_read(struct pmc_dev *pmcdev, int reg_offset) +static inline u32 pmc_core_reg_read(struct pmc *pmc, int reg_offset) { - return readl(pmcdev->regbase + reg_offset); + return readl(pmc->regbase + reg_offset); } -static inline void pmc_core_reg_write(struct pmc_dev *pmcdev, int reg_offset, +static inline void pmc_core_reg_write(struct pmc *pmc, int reg_offset, u32 val) { - writel(val, pmcdev->regbase + reg_offset); + writel(val, pmc->regbase + reg_offset); } -static inline u64 pmc_core_adjust_slp_s0_step(struct pmc_dev *pmcdev, u32 value) +static inline u64 pmc_core_adjust_slp_s0_step(struct pmc *pmc, u32 value) { /* * ADL PCH does not have the SLP_S0 counter and LPM Residency counters are @@ -72,17 +72,18 @@ static inline u64 pmc_core_adjust_slp_s0_step(struct pmc_dev *pmcdev, u32 value) * programs have the legacy SLP_S0 residency counter that is using the 122 * usec tick. */ - const int lpm_adj_x2 = pmcdev->map->lpm_res_counter_step_x2; + const int lpm_adj_x2 = pmc->map->lpm_res_counter_step_x2; - if (pmcdev->map == &adl_reg_map) + if (pmc->map == &adl_reg_map) return (u64)value * GET_X2_COUNTER((u64)lpm_adj_x2); else - return (u64)value * pmcdev->map->slp_s0_res_counter_step; + return (u64)value * pmc->map->slp_s0_res_counter_step; } static int set_etr3(struct pmc_dev *pmcdev) { - const struct pmc_reg_map *map = pmcdev->map; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + const struct pmc_reg_map *map = pmc->map; u32 reg; int err; @@ -92,7 +93,7 @@ static int set_etr3(struct pmc_dev *pmcdev) mutex_lock(&pmcdev->lock); /* check if CF9 is locked */ - reg = pmc_core_reg_read(pmcdev, map->etr3_offset); + reg = pmc_core_reg_read(pmc, map->etr3_offset); if (reg & ETR3_CF9LOCK) { err = -EACCES; goto out_unlock; @@ -100,9 +101,9 @@ static int set_etr3(struct pmc_dev *pmcdev) /* write CF9 global reset bit */ reg |= ETR3_CF9GR; - pmc_core_reg_write(pmcdev, map->etr3_offset, reg); + pmc_core_reg_write(pmc, map->etr3_offset, reg); - reg = pmc_core_reg_read(pmcdev, map->etr3_offset); + reg = pmc_core_reg_read(pmc, map->etr3_offset); if (!(reg & ETR3_CF9GR)) { err = -EIO; goto out_unlock; @@ -120,11 +121,12 @@ static umode_t etr3_is_visible(struct kobject *kobj, { struct device *dev = kobj_to_dev(kobj); struct pmc_dev *pmcdev = dev_get_drvdata(dev); - const struct pmc_reg_map *map = pmcdev->map; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + const struct pmc_reg_map *map = pmc->map; u32 reg; mutex_lock(&pmcdev->lock); - reg = pmc_core_reg_read(pmcdev, map->etr3_offset); + reg = pmc_core_reg_read(pmc, map->etr3_offset); mutex_unlock(&pmcdev->lock); return reg & ETR3_CF9LOCK ? attr->mode & (SYSFS_PREALLOC | 0444) : attr->mode; @@ -134,7 +136,8 @@ static ssize_t etr3_show(struct device *dev, struct device_attribute *attr, char *buf) { struct pmc_dev *pmcdev = dev_get_drvdata(dev); - const struct pmc_reg_map *map = pmcdev->map; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + const struct pmc_reg_map *map = pmc->map; u32 reg; if (!map->etr3_offset) @@ -142,7 +145,7 @@ static ssize_t etr3_show(struct device *dev, mutex_lock(&pmcdev->lock); - reg = pmc_core_reg_read(pmcdev, map->etr3_offset); + reg = pmc_core_reg_read(pmc, map->etr3_offset); reg &= ETR3_CF9GR | ETR3_CF9LOCK; mutex_unlock(&pmcdev->lock); @@ -191,37 +194,37 @@ static const struct attribute_group *pmc_dev_groups[] = { static int pmc_core_dev_state_get(void *data, u64 *val) { - struct pmc_dev *pmcdev = data; - const struct pmc_reg_map *map = pmcdev->map; + struct pmc *pmc = data; + const struct pmc_reg_map *map = pmc->map; u32 value; - value = pmc_core_reg_read(pmcdev, map->slp_s0_offset); - *val = pmc_core_adjust_slp_s0_step(pmcdev, value); + value = pmc_core_reg_read(pmc, map->slp_s0_offset); + *val = pmc_core_adjust_slp_s0_step(pmc, value); return 0; } DEFINE_DEBUGFS_ATTRIBUTE(pmc_core_dev_state, pmc_core_dev_state_get, NULL, "%llu\n"); -static int pmc_core_check_read_lock_bit(struct pmc_dev *pmcdev) +static int pmc_core_check_read_lock_bit(struct pmc *pmc) { u32 value; - value = pmc_core_reg_read(pmcdev, pmcdev->map->pm_cfg_offset); - return value & BIT(pmcdev->map->pm_read_disable_bit); + value = pmc_core_reg_read(pmc, pmc->map->pm_cfg_offset); + return value & BIT(pmc->map->pm_read_disable_bit); } -static void pmc_core_slps0_display(struct pmc_dev *pmcdev, struct device *dev, +static void pmc_core_slps0_display(struct pmc *pmc, struct device *dev, struct seq_file *s) { - const struct pmc_bit_map **maps = pmcdev->map->slps0_dbg_maps; + const struct pmc_bit_map **maps = pmc->map->slps0_dbg_maps; const struct pmc_bit_map *map; - int offset = pmcdev->map->slps0_dbg_offset; + int offset = pmc->map->slps0_dbg_offset; u32 data; while (*maps) { map = *maps; - data = pmc_core_reg_read(pmcdev, offset); + data = pmc_core_reg_read(pmc, offset); offset += 4; while (map->name) { if (dev) @@ -248,8 +251,8 @@ static int pmc_core_lpm_get_arr_size(const struct pmc_bit_map **maps) return idx; } -static void pmc_core_lpm_display(struct pmc_dev *pmcdev, struct device *dev, - struct seq_file *s, u32 offset, +static void pmc_core_lpm_display(struct pmc *pmc, struct device *dev, + struct seq_file *s, u32 offset, int pmc_index, const char *str, const struct pmc_bit_map **maps) { @@ -262,25 +265,25 @@ static void pmc_core_lpm_display(struct pmc_dev *pmcdev, struct device *dev, return; for (index = 0; index < arr_size; index++) { - lpm_regs[index] = pmc_core_reg_read(pmcdev, offset); + lpm_regs[index] = pmc_core_reg_read(pmc, offset); offset += 4; } for (idx = 0; idx < arr_size; idx++) { if (dev) - dev_info(dev, "\nLPM_%s_%d:\t0x%x\n", str, idx, + dev_info(dev, "\nPMC%d:LPM_%s_%d:\t0x%x\n", pmc_index, str, idx, lpm_regs[idx]); if (s) - seq_printf(s, "\nLPM_%s_%d:\t0x%x\n", str, idx, + seq_printf(s, "\nPMC%d:LPM_%s_%d:\t0x%x\n", pmc_index, str, idx, lpm_regs[idx]); for (index = 0; maps[idx][index].name && index < len; index++) { bit_mask = maps[idx][index].bit_mask; if (dev) - dev_info(dev, "%-30s %-30d\n", + dev_info(dev, "PMC%d:%-30s %-30d\n", pmc_index, maps[idx][index].name, lpm_regs[idx] & bit_mask ? 1 : 0); if (s) - seq_printf(s, "%-30s %-30d\n", + seq_printf(s, "PMC%d:%-30s %-30d\n", pmc_index, maps[idx][index].name, lpm_regs[idx] & bit_mask ? 1 : 0); } @@ -291,37 +294,46 @@ static void pmc_core_lpm_display(struct pmc_dev *pmcdev, struct device *dev, static bool slps0_dbg_latch; -static inline u8 pmc_core_reg_read_byte(struct pmc_dev *pmcdev, int offset) +static inline u8 pmc_core_reg_read_byte(struct pmc *pmc, int offset) { - return readb(pmcdev->regbase + offset); + return readb(pmc->regbase + offset); } static void pmc_core_display_map(struct seq_file *s, int index, int idx, int ip, - u8 pf_reg, const struct pmc_bit_map **pf_map) + int pmc_index, u8 pf_reg, const struct pmc_bit_map **pf_map) { - seq_printf(s, "PCH IP: %-2d - %-32s\tState: %s\n", - ip, pf_map[idx][index].name, + seq_printf(s, "PMC%d:PCH IP: %-2d - %-32s\tState: %s\n", + pmc_index, ip, pf_map[idx][index].name, pf_map[idx][index].bit_mask & pf_reg ? "Off" : "On"); } static int pmc_core_ppfear_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - const struct pmc_bit_map **maps = pmcdev->map->pfear_sts; - u8 pf_regs[PPFEAR_MAX_NUM_ENTRIES]; - int index, iter, idx, ip = 0; + int i; - iter = pmcdev->map->ppfear0_offset; + for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { + struct pmc *pmc = pmcdev->pmcs[i]; + const struct pmc_bit_map **maps; + u8 pf_regs[PPFEAR_MAX_NUM_ENTRIES]; + int index, iter, idx, ip = 0; - for (index = 0; index < pmcdev->map->ppfear_buckets && - index < PPFEAR_MAX_NUM_ENTRIES; index++, iter++) - pf_regs[index] = pmc_core_reg_read_byte(pmcdev, iter); + if (!pmc) + continue; + + maps = pmc->map->pfear_sts; + iter = pmc->map->ppfear0_offset; + + for (index = 0; index < pmc->map->ppfear_buckets && + index < PPFEAR_MAX_NUM_ENTRIES; index++, iter++) + pf_regs[index] = pmc_core_reg_read_byte(pmc, iter); - for (idx = 0; maps[idx]; idx++) { - for (index = 0; maps[idx][index].name && - index < pmcdev->map->ppfear_buckets * 8; ip++, index++) - pmc_core_display_map(s, index, idx, ip, - pf_regs[index / 8], maps); + for (idx = 0; maps[idx]; idx++) { + for (index = 0; maps[idx][index].name && + index < pmc->map->ppfear_buckets * 8; ip++, index++) + pmc_core_display_map(s, index, idx, ip, i, + pf_regs[index / 8], maps); + } } return 0; @@ -329,37 +341,38 @@ static int pmc_core_ppfear_show(struct seq_file *s, void *unused) DEFINE_SHOW_ATTRIBUTE(pmc_core_ppfear); /* This function should return link status, 0 means ready */ -static int pmc_core_mtpmc_link_status(struct pmc_dev *pmcdev) +static int pmc_core_mtpmc_link_status(struct pmc *pmc) { u32 value; - value = pmc_core_reg_read(pmcdev, SPT_PMC_PM_STS_OFFSET); + value = pmc_core_reg_read(pmc, SPT_PMC_PM_STS_OFFSET); return value & BIT(SPT_PMC_MSG_FULL_STS_BIT); } -static int pmc_core_send_msg(struct pmc_dev *pmcdev, u32 *addr_xram) +static int pmc_core_send_msg(struct pmc *pmc, u32 *addr_xram) { u32 dest; int timeout; for (timeout = NUM_RETRIES; timeout > 0; timeout--) { - if (pmc_core_mtpmc_link_status(pmcdev) == 0) + if (pmc_core_mtpmc_link_status(pmc) == 0) break; msleep(5); } - if (timeout <= 0 && pmc_core_mtpmc_link_status(pmcdev)) + if (timeout <= 0 && pmc_core_mtpmc_link_status(pmc)) return -EBUSY; dest = (*addr_xram & MTPMC_MASK) | (1U << 1); - pmc_core_reg_write(pmcdev, SPT_PMC_MTPMC_OFFSET, dest); + pmc_core_reg_write(pmc, SPT_PMC_MTPMC_OFFSET, dest); return 0; } static int pmc_core_mphy_pg_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - const struct pmc_bit_map *map = pmcdev->map->mphy_sts; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + const struct pmc_bit_map *map = pmc->map->mphy_sts; u32 mphy_core_reg_low, mphy_core_reg_high; u32 val_low, val_high; int index, err = 0; @@ -374,21 +387,21 @@ static int pmc_core_mphy_pg_show(struct seq_file *s, void *unused) mutex_lock(&pmcdev->lock); - if (pmc_core_send_msg(pmcdev, &mphy_core_reg_low) != 0) { + if (pmc_core_send_msg(pmc, &mphy_core_reg_low) != 0) { err = -EBUSY; goto out_unlock; } msleep(10); - val_low = pmc_core_reg_read(pmcdev, SPT_PMC_MFPMC_OFFSET); + val_low = pmc_core_reg_read(pmc, SPT_PMC_MFPMC_OFFSET); - if (pmc_core_send_msg(pmcdev, &mphy_core_reg_high) != 0) { + if (pmc_core_send_msg(pmc, &mphy_core_reg_high) != 0) { err = -EBUSY; goto out_unlock; } msleep(10); - val_high = pmc_core_reg_read(pmcdev, SPT_PMC_MFPMC_OFFSET); + val_high = pmc_core_reg_read(pmc, SPT_PMC_MFPMC_OFFSET); for (index = 0; index < 8 && map[index].name; index++) { seq_printf(s, "%-32s\tState: %s\n", @@ -413,7 +426,8 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_mphy_pg); static int pmc_core_pll_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - const struct pmc_bit_map *map = pmcdev->map->pll_sts; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + const struct pmc_bit_map *map = pmc->map->pll_sts; u32 mphy_common_reg, val; int index, err = 0; @@ -425,14 +439,14 @@ static int pmc_core_pll_show(struct seq_file *s, void *unused) mphy_common_reg = (SPT_PMC_MPHY_COM_STS_0 << 16); mutex_lock(&pmcdev->lock); - if (pmc_core_send_msg(pmcdev, &mphy_common_reg) != 0) { + if (pmc_core_send_msg(pmc, &mphy_common_reg) != 0) { err = -EBUSY; goto out_unlock; } /* Observed PMC HW response latency for MTPMC-MFPMC is ~10 ms */ msleep(10); - val = pmc_core_reg_read(pmcdev, SPT_PMC_MFPMC_OFFSET); + val = pmc_core_reg_read(pmc, SPT_PMC_MFPMC_OFFSET); for (index = 0; map[index].name ; index++) { seq_printf(s, "%-32s\tState: %s\n", @@ -448,25 +462,48 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_pll); int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value) { - const struct pmc_reg_map *map = pmcdev->map; + struct pmc *pmc; + const struct pmc_reg_map *map; u32 reg; - int err = 0; + int pmc_index, ltr_index; - mutex_lock(&pmcdev->lock); + ltr_index = value; + /* For platforms with multiple pmcs, ltr index value given by user + * is based on the contiguous indexes from ltr_show output. + * pmc index and ltr index needs to be calculated from it. + */ + for (pmc_index = 0; pmc_index < ARRAY_SIZE(pmcdev->pmcs) && ltr_index > 0; pmc_index++) { + pmc = pmcdev->pmcs[pmc_index]; - if (value > map->ltr_ignore_max) { - err = -EINVAL; - goto out_unlock; + if (!pmc) + continue; + + map = pmc->map; + if (ltr_index <= map->ltr_ignore_max) + break; + + /* Along with IP names, ltr_show map includes CURRENT_PLATFORM + * and AGGREGATED_SYSTEM values per PMC. Take these two index + * values into account in ltr_index calculation. Also, to start + * ltr index from zero for next pmc, subtract it by 1. + */ + ltr_index = ltr_index - (map->ltr_ignore_max + 2) - 1; } - reg = pmc_core_reg_read(pmcdev, map->ltr_ignore_offset); - reg |= BIT(value); - pmc_core_reg_write(pmcdev, map->ltr_ignore_offset, reg); + if (pmc_index >= ARRAY_SIZE(pmcdev->pmcs) || ltr_index < 0) + return -EINVAL; + + pr_debug("ltr_ignore for pmc%d: ltr_index:%d\n", pmc_index, ltr_index); + + mutex_lock(&pmcdev->lock); + + reg = pmc_core_reg_read(pmc, map->ltr_ignore_offset); + reg |= BIT(ltr_index); + pmc_core_reg_write(pmc, map->ltr_ignore_offset, reg); -out_unlock: mutex_unlock(&pmcdev->lock); - return err; + return 0; } static ssize_t pmc_core_ltr_ignore_write(struct file *file, @@ -509,7 +546,8 @@ static const struct file_operations pmc_core_ltr_ignore_ops = { static void pmc_core_slps0_dbg_latch(struct pmc_dev *pmcdev, bool reset) { - const struct pmc_reg_map *map = pmcdev->map; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + const struct pmc_reg_map *map = pmc->map; u32 fd; mutex_lock(&pmcdev->lock); @@ -517,12 +555,12 @@ static void pmc_core_slps0_dbg_latch(struct pmc_dev *pmcdev, bool reset) if (!reset && !slps0_dbg_latch) goto out_unlock; - fd = pmc_core_reg_read(pmcdev, map->slps0_dbg_offset); + fd = pmc_core_reg_read(pmc, map->slps0_dbg_offset); if (reset) fd &= ~CNP_PMC_LATCH_SLPS0_EVENTS; else fd |= CNP_PMC_LATCH_SLPS0_EVENTS; - pmc_core_reg_write(pmcdev, map->slps0_dbg_offset, fd); + pmc_core_reg_write(pmc, map->slps0_dbg_offset, fd); slps0_dbg_latch = false; @@ -535,7 +573,7 @@ static int pmc_core_slps0_dbg_show(struct seq_file *s, void *unused) struct pmc_dev *pmcdev = s->private; pmc_core_slps0_dbg_latch(pmcdev, false); - pmc_core_slps0_display(pmcdev, NULL, s); + pmc_core_slps0_display(pmcdev->pmcs[PMC_IDX_MAIN], NULL, s); pmc_core_slps0_dbg_latch(pmcdev, true); return 0; @@ -579,44 +617,52 @@ static u32 convert_ltr_scale(u32 val) static int pmc_core_ltr_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - const struct pmc_bit_map *map = pmcdev->map->ltr_show_sts; u64 decoded_snoop_ltr, decoded_non_snoop_ltr; u32 ltr_raw_data, scale, val; u16 snoop_ltr, nonsnoop_ltr; - int index; + int i, index, ltr_index = 0; - for (index = 0; map[index].name ; index++) { - decoded_snoop_ltr = decoded_non_snoop_ltr = 0; - ltr_raw_data = pmc_core_reg_read(pmcdev, - map[index].bit_mask); - snoop_ltr = ltr_raw_data & ~MTPMC_MASK; - nonsnoop_ltr = (ltr_raw_data >> 0x10) & ~MTPMC_MASK; - - if (FIELD_GET(LTR_REQ_NONSNOOP, ltr_raw_data)) { - scale = FIELD_GET(LTR_DECODED_SCALE, nonsnoop_ltr); - val = FIELD_GET(LTR_DECODED_VAL, nonsnoop_ltr); - decoded_non_snoop_ltr = val * convert_ltr_scale(scale); - } + for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { + struct pmc *pmc = pmcdev->pmcs[i]; + const struct pmc_bit_map *map; - if (FIELD_GET(LTR_REQ_SNOOP, ltr_raw_data)) { - scale = FIELD_GET(LTR_DECODED_SCALE, snoop_ltr); - val = FIELD_GET(LTR_DECODED_VAL, snoop_ltr); - decoded_snoop_ltr = val * convert_ltr_scale(scale); - } + if (!pmc) + continue; + + map = pmc->map->ltr_show_sts; + for (index = 0; map[index].name; index++) { + decoded_snoop_ltr = decoded_non_snoop_ltr = 0; + ltr_raw_data = pmc_core_reg_read(pmc, + map[index].bit_mask); + snoop_ltr = ltr_raw_data & ~MTPMC_MASK; + nonsnoop_ltr = (ltr_raw_data >> 0x10) & ~MTPMC_MASK; + + if (FIELD_GET(LTR_REQ_NONSNOOP, ltr_raw_data)) { + scale = FIELD_GET(LTR_DECODED_SCALE, nonsnoop_ltr); + val = FIELD_GET(LTR_DECODED_VAL, nonsnoop_ltr); + decoded_non_snoop_ltr = val * convert_ltr_scale(scale); + } + if (FIELD_GET(LTR_REQ_SNOOP, ltr_raw_data)) { + scale = FIELD_GET(LTR_DECODED_SCALE, snoop_ltr); + val = FIELD_GET(LTR_DECODED_VAL, snoop_ltr); + decoded_snoop_ltr = val * convert_ltr_scale(scale); + } - seq_printf(s, "%-32s\tLTR: RAW: 0x%-16x\tNon-Snoop(ns): %-16llu\tSnoop(ns): %-16llu\n", - map[index].name, ltr_raw_data, - decoded_non_snoop_ltr, - decoded_snoop_ltr); + seq_printf(s, "%d\tPMC%d:%-32s\tLTR: RAW: 0x%-16x\tNon-Snoop(ns): %-16llu\tSnoop(ns): %-16llu\n", + ltr_index, i, map[index].name, ltr_raw_data, + decoded_non_snoop_ltr, + decoded_snoop_ltr); + ltr_index++; + } } return 0; } DEFINE_SHOW_ATTRIBUTE(pmc_core_ltr); -static inline u64 adjust_lpm_residency(struct pmc_dev *pmcdev, u32 offset, +static inline u64 adjust_lpm_residency(struct pmc *pmc, u32 offset, const int lpm_adj_x2) { - u64 lpm_res = pmc_core_reg_read(pmcdev, offset); + u64 lpm_res = pmc_core_reg_read(pmc, offset); return GET_X2_COUNTER((u64)lpm_adj_x2 * lpm_res); } @@ -624,15 +670,16 @@ static inline u64 adjust_lpm_residency(struct pmc_dev *pmcdev, u32 offset, static int pmc_core_substate_res_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - const int lpm_adj_x2 = pmcdev->map->lpm_res_counter_step_x2; - u32 offset = pmcdev->map->lpm_residency_offset; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + const int lpm_adj_x2 = pmc->map->lpm_res_counter_step_x2; + u32 offset = pmc->map->lpm_residency_offset; int i, mode; seq_printf(s, "%-10s %-15s\n", "Substate", "Residency"); pmc_for_each_mode(i, mode, pmcdev) { seq_printf(s, "%-10s %-15llu\n", pmc_lpm_modes[mode], - adjust_lpm_residency(pmcdev, offset + (4 * mode), lpm_adj_x2)); + adjust_lpm_residency(pmc, offset + (4 * mode), lpm_adj_x2)); } return 0; @@ -642,10 +689,19 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_res); static int pmc_core_substate_sts_regs_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - const struct pmc_bit_map **maps = pmcdev->map->lpm_sts; - u32 offset = pmcdev->map->lpm_status_offset; + int i; - pmc_core_lpm_display(pmcdev, NULL, s, offset, "STATUS", maps); + for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { + struct pmc *pmc = pmcdev->pmcs[i]; + const struct pmc_bit_map **maps; + u32 offset; + + if (!pmc) + continue; + maps = pmc->map->lpm_sts; + offset = pmc->map->lpm_status_offset; + pmc_core_lpm_display(pmc, NULL, s, offset, i, "STATUS", maps); + } return 0; } @@ -654,10 +710,19 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_sts_regs); static int pmc_core_substate_l_sts_regs_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - const struct pmc_bit_map **maps = pmcdev->map->lpm_sts; - u32 offset = pmcdev->map->lpm_live_status_offset; + int i; - pmc_core_lpm_display(pmcdev, NULL, s, offset, "LIVE_STATUS", maps); + for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { + struct pmc *pmc = pmcdev->pmcs[i]; + const struct pmc_bit_map **maps; + u32 offset; + + if (!pmc) + continue; + maps = pmc->map->lpm_sts; + offset = pmc->map->lpm_live_status_offset; + pmc_core_lpm_display(pmc, NULL, s, offset, i, "LIVE_STATUS", maps); + } return 0; } @@ -678,11 +743,12 @@ static void pmc_core_substate_req_header_show(struct seq_file *s) static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - const struct pmc_bit_map **maps = pmcdev->map->lpm_sts; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + const struct pmc_bit_map **maps = pmc->map->lpm_sts; const struct pmc_bit_map *map; - const int num_maps = pmcdev->map->lpm_num_maps; - u32 sts_offset = pmcdev->map->lpm_status_offset; - u32 *lpm_req_regs = pmcdev->lpm_req_regs; + const int num_maps = pmc->map->lpm_num_maps; + u32 sts_offset = pmc->map->lpm_status_offset; + u32 *lpm_req_regs = pmc->lpm_req_regs; int mp; /* Display the header */ @@ -703,7 +769,7 @@ static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused) req_mask |= lpm_req_regs[mp + (mode * num_maps)]; /* Get the last latched status for this map */ - lpm_status = pmc_core_reg_read(pmcdev, sts_offset + (mp * 4)); + lpm_status = pmc_core_reg_read(pmc, sts_offset + (mp * 4)); /* Loop over elements in this map */ map = maps[mp]; @@ -746,11 +812,12 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_req_regs); static int pmc_core_lpm_latch_mode_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; bool c10; u32 reg; int idx, mode; - reg = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_sts_latch_en_offset); + reg = pmc_core_reg_read(pmc, pmc->map->lpm_sts_latch_en_offset); if (reg & LPM_STS_LATCH_MODE) { seq_puts(s, "c10"); c10 = false; @@ -777,6 +844,7 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file, { struct seq_file *s = file->private_data; struct pmc_dev *pmcdev = s->private; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; bool clear = false, c10 = false; unsigned char buf[8]; int idx, m, mode; @@ -813,9 +881,9 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file, if (clear) { mutex_lock(&pmcdev->lock); - reg = pmc_core_reg_read(pmcdev, pmcdev->map->etr3_offset); + reg = pmc_core_reg_read(pmc, pmc->map->etr3_offset); reg |= ETR3_CLEAR_LPM_EVENTS; - pmc_core_reg_write(pmcdev, pmcdev->map->etr3_offset, reg); + pmc_core_reg_write(pmc, pmc->map->etr3_offset, reg); mutex_unlock(&pmcdev->lock); @@ -825,9 +893,9 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file, if (c10) { mutex_lock(&pmcdev->lock); - reg = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_sts_latch_en_offset); + reg = pmc_core_reg_read(pmc, pmc->map->lpm_sts_latch_en_offset); reg &= ~LPM_STS_LATCH_MODE; - pmc_core_reg_write(pmcdev, pmcdev->map->lpm_sts_latch_en_offset, reg); + pmc_core_reg_write(pmc, pmc->map->lpm_sts_latch_en_offset, reg); mutex_unlock(&pmcdev->lock); @@ -840,7 +908,7 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file, */ reg = LPM_STS_LATCH_MODE | BIT(mode); mutex_lock(&pmcdev->lock); - pmc_core_reg_write(pmcdev, pmcdev->map->lpm_sts_latch_en_offset, reg); + pmc_core_reg_write(pmc, pmc->map->lpm_sts_latch_en_offset, reg); mutex_unlock(&pmcdev->lock); return count; @@ -849,8 +917,8 @@ DEFINE_PMC_CORE_ATTR_WRITE(pmc_core_lpm_latch_mode); static int pmc_core_pkgc_show(struct seq_file *s, void *unused) { - struct pmc_dev *pmcdev = s->private; - const struct pmc_bit_map *map = pmcdev->map->msr_sts; + struct pmc *pmc = s->private; + const struct pmc_bit_map *map = pmc->map->msr_sts; u64 pcstate_count; int index; @@ -901,6 +969,7 @@ static bool pmc_core_pri_verify(u32 lpm_pri, u8 *mode_order) static void pmc_core_get_low_power_modes(struct platform_device *pdev) { struct pmc_dev *pmcdev = platform_get_drvdata(pdev); + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; u8 pri_order[LPM_MAX_NUM_MODES] = LPM_DEFAULT_PRI; u8 mode_order[LPM_MAX_NUM_MODES]; u32 lpm_pri; @@ -908,10 +977,10 @@ static void pmc_core_get_low_power_modes(struct platform_device *pdev) int mode, i, p; /* Use LPM Maps to indicate support for substates */ - if (!pmcdev->map->lpm_num_maps) + if (!pmc->map->lpm_num_maps) return; - lpm_en = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_en_offset); + lpm_en = pmc_core_reg_read(pmc, pmc->map->lpm_en_offset); /* For MTL, BIT 31 is not an lpm mode but a enable bit. * Lower byte is enough to cover the number of lpm modes for all * platforms and hence mask the upper 3 bytes. @@ -919,7 +988,7 @@ static void pmc_core_get_low_power_modes(struct platform_device *pdev) pmcdev->num_lpm_modes = hweight32(lpm_en & 0xFF); /* Read 32 bit LPM_PRI register */ - lpm_pri = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_priority_offset); + lpm_pri = pmc_core_reg_read(pmc, pmc->map->lpm_priority_offset); /* @@ -948,6 +1017,25 @@ static void pmc_core_get_low_power_modes(struct platform_device *pdev) } } +int get_primary_reg_base(struct pmc *pmc) +{ + u64 slp_s0_addr; + + if (lpit_read_residency_count_address(&slp_s0_addr)) { + pmc->base_addr = PMC_BASE_ADDR_DEFAULT; + + if (page_is_ram(PHYS_PFN(pmc->base_addr))) + return -ENODEV; + } else { + pmc->base_addr = slp_s0_addr - pmc->map->slp_s0_offset; + } + + pmc->regbase = ioremap(pmc->base_addr, pmc->map->regmap_length); + if (!pmc->regbase) + return -ENOMEM; + return 0; +} + static void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev) { debugfs_remove_recursive(pmcdev->dbgfs_dir); @@ -955,15 +1043,16 @@ static void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev) static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev) { + struct pmc *primary_pmc = pmcdev->pmcs[PMC_IDX_MAIN]; struct dentry *dir; dir = debugfs_create_dir("pmc_core", NULL); pmcdev->dbgfs_dir = dir; - debugfs_create_file("slp_s0_residency_usec", 0444, dir, pmcdev, + debugfs_create_file("slp_s0_residency_usec", 0444, dir, primary_pmc, &pmc_core_dev_state); - if (pmcdev->map->pfear_sts) + if (primary_pmc->map->pfear_sts) debugfs_create_file("pch_ip_power_gating_status", 0444, dir, pmcdev, &pmc_core_ppfear_fops); @@ -972,19 +1061,19 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev) debugfs_create_file("ltr_show", 0444, dir, pmcdev, &pmc_core_ltr_fops); - debugfs_create_file("package_cstate_show", 0444, dir, pmcdev, + debugfs_create_file("package_cstate_show", 0444, dir, primary_pmc, &pmc_core_pkgc_fops); - if (pmcdev->map->pll_sts) + if (primary_pmc->map->pll_sts) debugfs_create_file("pll_status", 0444, dir, pmcdev, &pmc_core_pll_fops); - if (pmcdev->map->mphy_sts) + if (primary_pmc->map->mphy_sts) debugfs_create_file("mphy_core_lanes_power_gating_status", 0444, dir, pmcdev, &pmc_core_mphy_pg_fops); - if (pmcdev->map->slps0_dbg_maps) { + if (primary_pmc->map->slps0_dbg_maps) { debugfs_create_file("slp_s0_debug_status", 0444, dir, pmcdev, &pmc_core_slps0_dbg_fops); @@ -993,13 +1082,13 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev) dir, &slps0_dbg_latch); } - if (pmcdev->map->lpm_en_offset) { + if (primary_pmc->map->lpm_en_offset) { debugfs_create_file("substate_residencies", 0444, pmcdev->dbgfs_dir, pmcdev, &pmc_core_substate_res_fops); } - if (pmcdev->map->lpm_status_offset) { + if (primary_pmc->map->lpm_status_offset) { debugfs_create_file("substate_status_registers", 0444, pmcdev->dbgfs_dir, pmcdev, &pmc_core_substate_sts_regs_fops); @@ -1011,7 +1100,7 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev) &pmc_core_lpm_latch_mode_fops); } - if (pmcdev->lpm_req_regs) { + if (primary_pmc->lpm_req_regs) { debugfs_create_file("substate_requirements", 0444, pmcdev->dbgfs_dir, pmcdev, &pmc_core_substate_req_regs_fops); @@ -1039,7 +1128,6 @@ static const struct x86_cpu_id intel_pmc_core_ids[] = { X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, tgl_core_init), X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, adl_core_init), X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_S, adl_core_init), - X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE, mtl_core_init), X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE_L, mtl_core_init), {} }; @@ -1063,16 +1151,16 @@ static int quirk_xtal_ignore(const struct dmi_system_id *id) return 0; } -static void pmc_core_xtal_ignore(struct pmc_dev *pmcdev) +static void pmc_core_xtal_ignore(struct pmc *pmc) { u32 value; - value = pmc_core_reg_read(pmcdev, pmcdev->map->pm_vric1_offset); + value = pmc_core_reg_read(pmc, pmc->map->pm_vric1_offset); /* 24MHz Crystal Shutdown Qualification Disable */ value |= SPT_PMC_VRIC1_XTALSDQDIS; /* Low Voltage Mode Enable */ value &= ~SPT_PMC_VRIC1_SLPS0LVEN; - pmc_core_reg_write(pmcdev, pmcdev->map->pm_vric1_offset, value); + pmc_core_reg_write(pmc, pmc->map->pm_vric1_offset, value); } static const struct dmi_system_id pmc_core_dmi_table[] = { @@ -1087,12 +1175,32 @@ static const struct dmi_system_id pmc_core_dmi_table[] = { {} }; -static void pmc_core_do_dmi_quirks(struct pmc_dev *pmcdev) +static void pmc_core_do_dmi_quirks(struct pmc *pmc) { dmi_check_system(pmc_core_dmi_table); if (xtal_ignore) - pmc_core_xtal_ignore(pmcdev); + pmc_core_xtal_ignore(pmc); +} + +static void pmc_core_clean_structure(struct platform_device *pdev) +{ + struct pmc_dev *pmcdev = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { + struct pmc *pmc = pmcdev->pmcs[i]; + + if (pmc) + iounmap(pmc->regbase); + } + + if (pmcdev->ssram_pcidev) { + pci_dev_put(pmcdev->ssram_pcidev); + pci_disable_device(pmcdev->ssram_pcidev); + } + platform_set_drvdata(pdev, NULL); + mutex_destroy(&pmcdev->lock); } static int pmc_core_probe(struct platform_device *pdev) @@ -1100,8 +1208,9 @@ static int pmc_core_probe(struct platform_device *pdev) static bool device_initialized; struct pmc_dev *pmcdev; const struct x86_cpu_id *cpu_id; - void (*core_init)(struct pmc_dev *pmcdev); - u64 slp_s0_addr; + int (*core_init)(struct pmc_dev *pmcdev); + struct pmc *primary_pmc; + int ret; if (device_initialized) return -ENODEV; @@ -1117,7 +1226,13 @@ static int pmc_core_probe(struct platform_device *pdev) if (!cpu_id) return -ENODEV; - core_init = (void (*)(struct pmc_dev *))cpu_id->driver_data; + core_init = (int (*)(struct pmc_dev *))cpu_id->driver_data; + + /* Primary PMC */ + primary_pmc = devm_kzalloc(&pdev->dev, sizeof(*primary_pmc), GFP_KERNEL); + if (!primary_pmc) + return -ENOMEM; + pmcdev->pmcs[PMC_IDX_MAIN] = primary_pmc; /* * Coffee Lake has CPU ID of Kaby Lake and Cannon Lake PCH. So here @@ -1128,33 +1243,19 @@ static int pmc_core_probe(struct platform_device *pdev) core_init = cnp_core_init; mutex_init(&pmcdev->lock); - core_init(pmcdev); - - - if (lpit_read_residency_count_address(&slp_s0_addr)) { - pmcdev->base_addr = PMC_BASE_ADDR_DEFAULT; - - if (page_is_ram(PHYS_PFN(pmcdev->base_addr))) - return -ENODEV; - } else { - pmcdev->base_addr = slp_s0_addr - pmcdev->map->slp_s0_offset; + ret = core_init(pmcdev); + if (ret) { + pmc_core_clean_structure(pdev); + return ret; } - pmcdev->regbase = ioremap(pmcdev->base_addr, - pmcdev->map->regmap_length); - if (!pmcdev->regbase) - return -ENOMEM; - - if (pmcdev->core_configure) - pmcdev->core_configure(pmcdev); - - pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit(pmcdev); + pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit(primary_pmc); pmc_core_get_low_power_modes(pdev); - pmc_core_do_dmi_quirks(pmcdev); + pmc_core_do_dmi_quirks(primary_pmc); pmc_core_dbgfs_register(pmcdev); pm_report_max_hw_sleep(FIELD_MAX(SLP_S0_RES_COUNTER_MASK) * - pmc_core_adjust_slp_s0_step(pmcdev, 1)); + pmc_core_adjust_slp_s0_step(primary_pmc, 1)); device_initialized = true; dev_info(&pdev->dev, " initialized\n"); @@ -1165,11 +1266,8 @@ static int pmc_core_probe(struct platform_device *pdev) static void pmc_core_remove(struct platform_device *pdev) { struct pmc_dev *pmcdev = platform_get_drvdata(pdev); - pmc_core_dbgfs_unregister(pmcdev); - platform_set_drvdata(pdev, NULL); - mutex_destroy(&pmcdev->lock); - iounmap(pmcdev->regbase); + pmc_core_clean_structure(pdev); } static bool warn_on_s0ix_failures; @@ -1179,6 +1277,7 @@ MODULE_PARM_DESC(warn_on_s0ix_failures, "Check and warn for S0ix failures"); static __maybe_unused int pmc_core_suspend(struct device *dev) { struct pmc_dev *pmcdev = dev_get_drvdata(dev); + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; /* Check if the syspend will actually use S0ix */ if (pm_suspend_via_firmware()) @@ -1189,7 +1288,7 @@ static __maybe_unused int pmc_core_suspend(struct device *dev) return -EIO; /* Save S0ix residency for checking later */ - if (pmc_core_dev_state_get(pmcdev, &pmcdev->s0ix_counter)) + if (pmc_core_dev_state_get(pmc, &pmcdev->s0ix_counter)) return -EIO; return 0; @@ -1212,7 +1311,7 @@ static inline bool pmc_core_is_s0ix_failed(struct pmc_dev *pmcdev) { u64 s0ix_counter; - if (pmc_core_dev_state_get(pmcdev, &s0ix_counter)) + if (pmc_core_dev_state_get(pmcdev->pmcs[PMC_IDX_MAIN], &s0ix_counter)) return false; pm_report_hw_sleep_time((u32)(s0ix_counter - pmcdev->s0ix_counter)); @@ -1223,11 +1322,13 @@ static inline bool pmc_core_is_s0ix_failed(struct pmc_dev *pmcdev) return false; } -static __maybe_unused int pmc_core_resume(struct device *dev) +int pmc_core_resume_common(struct pmc_dev *pmcdev) { - struct pmc_dev *pmcdev = dev_get_drvdata(dev); - const struct pmc_bit_map **maps = pmcdev->map->lpm_sts; - int offset = pmcdev->map->lpm_status_offset; + struct device *dev = &pmcdev->pdev->dev; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + const struct pmc_bit_map **maps = pmc->map->lpm_sts; + int offset = pmc->map->lpm_status_offset; + int i; /* Check if the syspend used S0ix */ if (pm_suspend_via_firmware()) @@ -1249,14 +1350,32 @@ static __maybe_unused int pmc_core_resume(struct device *dev) /* The real interesting case - S0ix failed - lets ask PMC why. */ dev_warn(dev, "CPU did not enter SLP_S0!!! (S0ix cnt=%llu)\n", pmcdev->s0ix_counter); - if (pmcdev->map->slps0_dbg_maps) - pmc_core_slps0_display(pmcdev, dev, NULL); - if (pmcdev->map->lpm_sts) - pmc_core_lpm_display(pmcdev, dev, NULL, offset, "STATUS", maps); + + if (pmc->map->slps0_dbg_maps) + pmc_core_slps0_display(pmc, dev, NULL); + + for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { + struct pmc *pmc = pmcdev->pmcs[i]; + + if (!pmc) + continue; + if (pmc->map->lpm_sts) + pmc_core_lpm_display(pmc, dev, NULL, offset, i, "STATUS", maps); + } return 0; } +static __maybe_unused int pmc_core_resume(struct device *dev) +{ + struct pmc_dev *pmcdev = dev_get_drvdata(dev); + + if (pmcdev->resume) + return pmcdev->resume(pmcdev); + + return pmc_core_resume_common(pmcdev); +} + static const struct dev_pm_ops pmc_core_pm_ops = { SET_LATE_SYSTEM_SLEEP_PM_OPS(pmc_core_suspend, pmc_core_resume) }; diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h index 9ca9b9746719..0729f593c6a7 100644 --- a/drivers/platform/x86/intel/pmc/core.h +++ b/drivers/platform/x86/intel/pmc/core.h @@ -19,6 +19,7 @@ #define SLP_S0_RES_COUNTER_MASK GENMASK(31, 0) #define PMC_BASE_ADDR_DEFAULT 0xFE000000 +#define MAX_NUM_PMC 3 /* Sunrise Point Power Management Controller PCI Device ID */ #define SPT_PMC_PCI_DEVICE_ID 0x9d21 @@ -249,6 +250,17 @@ enum ppfear_regs { #define MTL_LPM_STATUS_LATCH_EN_OFFSET 0x16F8 #define MTL_LPM_STATUS_OFFSET 0x1700 #define MTL_LPM_LIVE_STATUS_OFFSET 0x175C +#define MTL_PMC_LTR_IOE_PMC 0x1C0C +#define MTL_PMC_LTR_ESE 0x1BAC +#define MTL_PMC_LTR_RESERVED 0x1BA4 +#define MTL_IOE_PMC_MMIO_REG_LEN 0x23A4 +#define MTL_SOCM_NUM_IP_IGN_ALLOWED 25 +#define MTL_SOC_PMC_MMIO_REG_LEN 0x2708 +#define MTL_PMC_LTR_SPG 0x1B74 + +/* Meteor Lake PGD PFET Enable Ack Status */ +#define MTL_SOCM_PPFEAR_NUM_ENTRIES 8 +#define MTL_IOE_PPFEAR_NUM_ENTRIES 10 extern const char *pmc_lpm_modes[]; @@ -311,12 +323,38 @@ struct pmc_reg_map { }; /** - * struct pmc_dev - pmc device structure + * struct pmc_info - Structure to keep pmc info + * @devid: device id of the pmc device + * @map: pointer to a pmc_reg_map struct that contains platform + * specific attributes + */ +struct pmc_info { + u16 devid; + const struct pmc_reg_map *map; +}; + +/** + * struct pmc - pmc private info structure * @base_addr: contains pmc base address * @regbase: pointer to io-remapped memory location * @map: pointer to pmc_reg_map struct that contains platform * specific attributes + * @lpm_req_regs: List of substate requirements + * + * pmc contains info about one power management controller device. + */ +struct pmc { + u64 base_addr; + void __iomem *regbase; + const struct pmc_reg_map *map; + u32 *lpm_req_regs; +}; + +/** + * struct pmc_dev - pmc device structure + * @devs: pointer to an array of pmc pointers * @pdev: pointer to platform_device struct + * @ssram_pcidev: pointer to pci device struct for the PMC SSRAM * @dbgfs_dir: path to debugfs interface * @pmc_xram_read_bit: flag to indicate whether PMC XRAM shadow registers * used to read MPHY PG and PLL status are available @@ -325,17 +363,15 @@ struct pmc_reg_map { * @s0ix_counter: S0ix residency (step adjusted) * @num_lpm_modes: Count of enabled modes * @lpm_en_modes: Array of enabled modes from lowest to highest priority - * @lpm_req_regs: List of substate requirements - * @core_configure: Function pointer to configure the platform + * @resume: Function to perform platform specific resume * * pmc_dev contains info about power management controller device. */ struct pmc_dev { - u32 base_addr; - void __iomem *regbase; - const struct pmc_reg_map *map; + struct pmc *pmcs[MAX_NUM_PMC]; struct dentry *dbgfs_dir; struct platform_device *pdev; + struct pci_dev *ssram_pcidev; int pmc_xram_read_bit; struct mutex lock; /* generic mutex lock for PMC Core */ @@ -343,8 +379,20 @@ struct pmc_dev { u64 s0ix_counter; int num_lpm_modes; int lpm_en_modes[LPM_MAX_NUM_MODES]; - u32 *lpm_req_regs; - void (*core_configure)(struct pmc_dev *pmcdev); + int (*resume)(struct pmc_dev *pmcdev); + + bool has_die_c6; + u32 die_c6_offset; + struct telem_endpoint *punit_ep; + struct pmc_info *regmap_list; +}; + +enum pmc_index { + PMC_IDX_MAIN, + PMC_IDX_SOC = PMC_IDX_MAIN, + PMC_IDX_IOE, + PMC_IDX_PCH, + PMC_IDX_MAX }; extern const struct pmc_bit_map msr_map[]; @@ -393,20 +441,64 @@ extern const struct pmc_bit_map adl_vnn_req_status_3_map[]; extern const struct pmc_bit_map adl_vnn_misc_status_map[]; extern const struct pmc_bit_map *adl_lpm_maps[]; extern const struct pmc_reg_map adl_reg_map; -extern const struct pmc_reg_map mtl_reg_map; +extern const struct pmc_bit_map mtl_socm_pfear_map[]; +extern const struct pmc_bit_map *ext_mtl_socm_pfear_map[]; +extern const struct pmc_bit_map mtl_socm_ltr_show_map[]; +extern const struct pmc_bit_map mtl_socm_clocksource_status_map[]; +extern const struct pmc_bit_map mtl_socm_power_gating_status_0_map[]; +extern const struct pmc_bit_map mtl_socm_power_gating_status_1_map[]; +extern const struct pmc_bit_map mtl_socm_power_gating_status_2_map[]; +extern const struct pmc_bit_map mtl_socm_d3_status_0_map[]; +extern const struct pmc_bit_map mtl_socm_d3_status_1_map[]; +extern const struct pmc_bit_map mtl_socm_d3_status_2_map[]; +extern const struct pmc_bit_map mtl_socm_d3_status_3_map[]; +extern const struct pmc_bit_map mtl_socm_vnn_req_status_0_map[]; +extern const struct pmc_bit_map mtl_socm_vnn_req_status_1_map[]; +extern const struct pmc_bit_map mtl_socm_vnn_req_status_2_map[]; +extern const struct pmc_bit_map mtl_socm_vnn_req_status_3_map[]; +extern const struct pmc_bit_map mtl_socm_vnn_misc_status_map[]; +extern const struct pmc_bit_map mtl_socm_signal_status_map[]; +extern const struct pmc_bit_map *mtl_socm_lpm_maps[]; +extern const struct pmc_reg_map mtl_socm_reg_map; +extern const struct pmc_bit_map mtl_ioep_pfear_map[]; +extern const struct pmc_bit_map *ext_mtl_ioep_pfear_map[]; +extern const struct pmc_bit_map mtl_ioep_ltr_show_map[]; +extern const struct pmc_bit_map mtl_ioep_clocksource_status_map[]; +extern const struct pmc_bit_map mtl_ioep_power_gating_status_0_map[]; +extern const struct pmc_bit_map mtl_ioep_power_gating_status_1_map[]; +extern const struct pmc_bit_map mtl_ioep_power_gating_status_2_map[]; +extern const struct pmc_bit_map mtl_ioep_d3_status_0_map[]; +extern const struct pmc_bit_map mtl_ioep_d3_status_1_map[]; +extern const struct pmc_bit_map mtl_ioep_d3_status_2_map[]; +extern const struct pmc_bit_map mtl_ioep_d3_status_3_map[]; +extern const struct pmc_bit_map mtl_ioep_vnn_req_status_0_map[]; +extern const struct pmc_bit_map mtl_ioep_vnn_req_status_1_map[]; +extern const struct pmc_bit_map mtl_ioep_vnn_req_status_2_map[]; +extern const struct pmc_bit_map mtl_ioep_vnn_req_status_3_map[]; +extern const struct pmc_bit_map mtl_ioep_vnn_misc_status_map[]; +extern const struct pmc_bit_map *mtl_ioep_lpm_maps[]; +extern const struct pmc_reg_map mtl_ioep_reg_map; +extern const struct pmc_bit_map mtl_ioem_pfear_map[]; +extern const struct pmc_bit_map *ext_mtl_ioem_pfear_map[]; +extern const struct pmc_bit_map mtl_ioem_power_gating_status_1_map[]; +extern const struct pmc_bit_map mtl_ioem_vnn_req_status_1_map[]; +extern const struct pmc_bit_map *mtl_ioem_lpm_maps[]; +extern const struct pmc_reg_map mtl_ioem_reg_map; extern void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev); extern int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value); -void spt_core_init(struct pmc_dev *pmcdev); -void cnp_core_init(struct pmc_dev *pmcdev); -void icl_core_init(struct pmc_dev *pmcdev); -void tgl_core_init(struct pmc_dev *pmcdev); -void adl_core_init(struct pmc_dev *pmcdev); -void mtl_core_init(struct pmc_dev *pmcdev); -void tgl_core_configure(struct pmc_dev *pmcdev); -void adl_core_configure(struct pmc_dev *pmcdev); -void mtl_core_configure(struct pmc_dev *pmcdev); +int pmc_core_resume_common(struct pmc_dev *pmcdev); +int get_primary_reg_base(struct pmc *pmc); + +extern void pmc_core_ssram_init(struct pmc_dev *pmcdev); + +int spt_core_init(struct pmc_dev *pmcdev); +int cnp_core_init(struct pmc_dev *pmcdev); +int icl_core_init(struct pmc_dev *pmcdev); +int tgl_core_init(struct pmc_dev *pmcdev); +int adl_core_init(struct pmc_dev *pmcdev); +int mtl_core_init(struct pmc_dev *pmcdev); #define pmc_for_each_mode(i, mode, pmcdev) \ for (i = 0, mode = pmcdev->lpm_en_modes[i]; \ diff --git a/drivers/platform/x86/intel/pmc/core_ssram.c b/drivers/platform/x86/intel/pmc/core_ssram.c new file mode 100644 index 000000000000..13fa16f0d52e --- /dev/null +++ b/drivers/platform/x86/intel/pmc/core_ssram.c @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This file contains functions to handle discovery of PMC metrics located + * in the PMC SSRAM PCI device. + * + * Copyright (c) 2023, Intel Corporation. + * All Rights Reserved. + * + */ + +#include <linux/pci.h> +#include <linux/io-64-nonatomic-lo-hi.h> + +#include "core.h" + +#define SSRAM_HDR_SIZE 0x100 +#define SSRAM_PWRM_OFFSET 0x14 +#define SSRAM_DVSEC_OFFSET 0x1C +#define SSRAM_DVSEC_SIZE 0x10 +#define SSRAM_PCH_OFFSET 0x60 +#define SSRAM_IOE_OFFSET 0x68 +#define SSRAM_DEVID_OFFSET 0x70 + +static const struct pmc_reg_map *pmc_core_find_regmap(struct pmc_info *list, u16 devid) +{ + for (; list->map; ++list) + if (devid == list->devid) + return list->map; + + return NULL; +} + +static inline u64 get_base(void __iomem *addr, u32 offset) +{ + return lo_hi_readq(addr + offset) & GENMASK_ULL(63, 3); +} + +static void +pmc_core_pmc_add(struct pmc_dev *pmcdev, u64 pwrm_base, + const struct pmc_reg_map *reg_map, int pmc_index) +{ + struct pmc *pmc = pmcdev->pmcs[pmc_index]; + + if (!pwrm_base) + return; + + /* Memory for primary PMC has been allocated in core.c */ + if (!pmc) { + pmc = devm_kzalloc(&pmcdev->pdev->dev, sizeof(*pmc), GFP_KERNEL); + if (!pmc) + return; + } + + pmc->map = reg_map; + pmc->base_addr = pwrm_base; + pmc->regbase = ioremap(pmc->base_addr, pmc->map->regmap_length); + + if (!pmc->regbase) { + devm_kfree(&pmcdev->pdev->dev, pmc); + return; + } + + pmcdev->pmcs[pmc_index] = pmc; +} + +static void +pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, void __iomem *ssram, u32 offset, + int pmc_idx) +{ + u64 pwrm_base; + u16 devid; + + if (pmc_idx != PMC_IDX_SOC) { + u64 ssram_base = get_base(ssram, offset); + + if (!ssram_base) + return; + + ssram = ioremap(ssram_base, SSRAM_HDR_SIZE); + if (!ssram) + return; + } + + pwrm_base = get_base(ssram, SSRAM_PWRM_OFFSET); + devid = readw(ssram + SSRAM_DEVID_OFFSET); + + if (pmcdev->regmap_list) { + const struct pmc_reg_map *map; + + map = pmc_core_find_regmap(pmcdev->regmap_list, devid); + if (map) + pmc_core_pmc_add(pmcdev, pwrm_base, map, pmc_idx); + } + + if (pmc_idx != PMC_IDX_SOC) + iounmap(ssram); +} + +void pmc_core_ssram_init(struct pmc_dev *pmcdev) +{ + void __iomem *ssram; + struct pci_dev *pcidev; + u64 ssram_base; + int ret; + + pcidev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(20, 2)); + if (!pcidev) + goto out; + + ret = pcim_enable_device(pcidev); + if (ret) + goto release_dev; + + ssram_base = pcidev->resource[0].start; + ssram = ioremap(ssram_base, SSRAM_HDR_SIZE); + if (!ssram) + goto disable_dev; + + pmcdev->ssram_pcidev = pcidev; + + pmc_core_ssram_get_pmc(pmcdev, ssram, 0, PMC_IDX_SOC); + pmc_core_ssram_get_pmc(pmcdev, ssram, SSRAM_IOE_OFFSET, PMC_IDX_IOE); + pmc_core_ssram_get_pmc(pmcdev, ssram, SSRAM_PCH_OFFSET, PMC_IDX_PCH); + + iounmap(ssram); +out: + return; + +disable_dev: + pci_disable_device(pcidev); +release_dev: + pci_dev_put(pcidev); +} diff --git a/drivers/platform/x86/intel/pmc/icl.c b/drivers/platform/x86/intel/pmc/icl.c index 2f11b1a6daeb..d08e3174230d 100644 --- a/drivers/platform/x86/intel/pmc/icl.c +++ b/drivers/platform/x86/intel/pmc/icl.c @@ -50,7 +50,10 @@ const struct pmc_reg_map icl_reg_map = { .etr3_offset = ETR3_OFFSET, }; -void icl_core_init(struct pmc_dev *pmcdev) +int icl_core_init(struct pmc_dev *pmcdev) { - pmcdev->map = &icl_reg_map; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + + pmc->map = &icl_reg_map; + return get_primary_reg_base(pmc); } diff --git a/drivers/platform/x86/intel/pmc/mtl.c b/drivers/platform/x86/intel/pmc/mtl.c index e8cc156412ce..2204bc666980 100644 --- a/drivers/platform/x86/intel/pmc/mtl.c +++ b/drivers/platform/x86/intel/pmc/mtl.c @@ -11,40 +11,937 @@ #include <linux/pci.h> #include "core.h" -const struct pmc_reg_map mtl_reg_map = { - .pfear_sts = ext_tgl_pfear_map, +/* + * Die Mapping to Product. + * Product SOCDie IOEDie PCHDie + * MTL-M SOC-M IOE-M None + * MTL-P SOC-M IOE-P None + * MTL-S SOC-S IOE-P PCH-S + */ + +const struct pmc_bit_map mtl_socm_pfear_map[] = { + {"PMC", BIT(0)}, + {"OPI", BIT(1)}, + {"SPI", BIT(2)}, + {"XHCI", BIT(3)}, + {"SPA", BIT(4)}, + {"SPB", BIT(5)}, + {"SPC", BIT(6)}, + {"GBE", BIT(7)}, + + {"SATA", BIT(0)}, + {"DSP0", BIT(1)}, + {"DSP1", BIT(2)}, + {"DSP2", BIT(3)}, + {"DSP3", BIT(4)}, + {"SPD", BIT(5)}, + {"LPSS", BIT(6)}, + {"LPC", BIT(7)}, + + {"SMB", BIT(0)}, + {"ISH", BIT(1)}, + {"P2SB", BIT(2)}, + {"NPK_VNN", BIT(3)}, + {"SDX", BIT(4)}, + {"SPE", BIT(5)}, + {"FUSE", BIT(6)}, + {"SBR8", BIT(7)}, + + {"RSVD24", BIT(0)}, + {"OTG", BIT(1)}, + {"EXI", BIT(2)}, + {"CSE", BIT(3)}, + {"CSME_KVM", BIT(4)}, + {"CSME_PMT", BIT(5)}, + {"CSME_CLINK", BIT(6)}, + {"CSME_PTIO", BIT(7)}, + + {"CSME_USBR", BIT(0)}, + {"CSME_SUSRAM", BIT(1)}, + {"CSME_SMT1", BIT(2)}, + {"RSVD35", BIT(3)}, + {"CSME_SMS2", BIT(4)}, + {"CSME_SMS", BIT(5)}, + {"CSME_RTC", BIT(6)}, + {"CSME_PSF", BIT(7)}, + + {"SBR0", BIT(0)}, + {"SBR1", BIT(1)}, + {"SBR2", BIT(2)}, + {"SBR3", BIT(3)}, + {"SBR4", BIT(4)}, + {"SBR5", BIT(5)}, + {"RSVD46", BIT(6)}, + {"PSF1", BIT(7)}, + + {"PSF2", BIT(0)}, + {"PSF3", BIT(1)}, + {"PSF4", BIT(2)}, + {"CNVI", BIT(3)}, + {"UFSX2", BIT(4)}, + {"EMMC", BIT(5)}, + {"SPF", BIT(6)}, + {"SBR6", BIT(7)}, + + {"SBR7", BIT(0)}, + {"NPK_AON", BIT(1)}, + {"HDA4", BIT(2)}, + {"HDA5", BIT(3)}, + {"HDA6", BIT(4)}, + {"PSF6", BIT(5)}, + {"RSVD62", BIT(6)}, + {"RSVD63", BIT(7)}, + {} +}; + +const struct pmc_bit_map *ext_mtl_socm_pfear_map[] = { + mtl_socm_pfear_map, + NULL +}; + +const struct pmc_bit_map mtl_socm_ltr_show_map[] = { + {"SOUTHPORT_A", CNP_PMC_LTR_SPA}, + {"SOUTHPORT_B", CNP_PMC_LTR_SPB}, + {"SATA", CNP_PMC_LTR_SATA}, + {"GIGABIT_ETHERNET", CNP_PMC_LTR_GBE}, + {"XHCI", CNP_PMC_LTR_XHCI}, + {"SOUTHPORT_F", ADL_PMC_LTR_SPF}, + {"ME", CNP_PMC_LTR_ME}, + {"SATA1", CNP_PMC_LTR_EVA}, + {"SOUTHPORT_C", CNP_PMC_LTR_SPC}, + {"HD_AUDIO", CNP_PMC_LTR_AZ}, + {"CNV", CNP_PMC_LTR_CNV}, + {"LPSS", CNP_PMC_LTR_LPSS}, + {"SOUTHPORT_D", CNP_PMC_LTR_SPD}, + {"SOUTHPORT_E", CNP_PMC_LTR_SPE}, + {"SATA2", CNP_PMC_LTR_CAM}, + {"ESPI", CNP_PMC_LTR_ESPI}, + {"SCC", CNP_PMC_LTR_SCC}, + {"ISH", CNP_PMC_LTR_ISH}, + {"UFSX2", CNP_PMC_LTR_UFSX2}, + {"EMMC", CNP_PMC_LTR_EMMC}, + {"WIGIG", ICL_PMC_LTR_WIGIG}, + {"THC0", TGL_PMC_LTR_THC0}, + {"THC1", TGL_PMC_LTR_THC1}, + {"SOUTHPORT_G", MTL_PMC_LTR_SPG}, + {"ESE", MTL_PMC_LTR_ESE}, + {"IOE_PMC", MTL_PMC_LTR_IOE_PMC}, + + /* Below two cannot be used for LTR_IGNORE */ + {"CURRENT_PLATFORM", CNP_PMC_LTR_CUR_PLT}, + {"AGGREGATED_SYSTEM", CNP_PMC_LTR_CUR_ASLT}, + {} +}; + +const struct pmc_bit_map mtl_socm_clocksource_status_map[] = { + {"AON2_OFF_STS", BIT(0)}, + {"AON3_OFF_STS", BIT(1)}, + {"AON4_OFF_STS", BIT(2)}, + {"AON5_OFF_STS", BIT(3)}, + {"AON1_OFF_STS", BIT(4)}, + {"XTAL_LVM_OFF_STS", BIT(5)}, + {"MPFPW1_0_PLL_OFF_STS", BIT(6)}, + {"MPFPW1_1_PLL_OFF_STS", BIT(7)}, + {"USB3_PLL_OFF_STS", BIT(8)}, + {"AON3_SPL_OFF_STS", BIT(9)}, + {"MPFPW2_0_PLL_OFF_STS", BIT(12)}, + {"MPFPW3_0_PLL_OFF_STS", BIT(13)}, + {"XTAL_AGGR_OFF_STS", BIT(17)}, + {"USB2_PLL_OFF_STS", BIT(18)}, + {"FILTER_PLL_OFF_STS", BIT(22)}, + {"ACE_PLL_OFF_STS", BIT(24)}, + {"FABRIC_PLL_OFF_STS", BIT(25)}, + {"SOC_PLL_OFF_STS", BIT(26)}, + {"PCIFAB_PLL_OFF_STS", BIT(27)}, + {"REF_PLL_OFF_STS", BIT(28)}, + {"IMG_PLL_OFF_STS", BIT(29)}, + {"RTC_PLL_OFF_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map mtl_socm_power_gating_status_0_map[] = { + {"PMC_PGD0_PG_STS", BIT(0)}, + {"DMI_PGD0_PG_STS", BIT(1)}, + {"ESPISPI_PGD0_PG_STS", BIT(2)}, + {"XHCI_PGD0_PG_STS", BIT(3)}, + {"SPA_PGD0_PG_STS", BIT(4)}, + {"SPB_PGD0_PG_STS", BIT(5)}, + {"SPC_PGD0_PG_STS", BIT(6)}, + {"GBE_PGD0_PG_STS", BIT(7)}, + {"SATA_PGD0_PG_STS", BIT(8)}, + {"PSF13_PGD0_PG_STS", BIT(9)}, + {"SOC_D2D_PGD3_PG_STS", BIT(10)}, + {"MPFPW3_PGD0_PG_STS", BIT(11)}, + {"ESE_PGD0_PG_STS", BIT(12)}, + {"SPD_PGD0_PG_STS", BIT(13)}, + {"LPSS_PGD0_PG_STS", BIT(14)}, + {"LPC_PGD0_PG_STS", BIT(15)}, + {"SMB_PGD0_PG_STS", BIT(16)}, + {"ISH_PGD0_PG_STS", BIT(17)}, + {"P2S_PGD0_PG_STS", BIT(18)}, + {"NPK_PGD0_PG_STS", BIT(19)}, + {"DBG_SBR_PGD0_PG_STS", BIT(20)}, + {"SBRG_PGD0_PG_STS", BIT(21)}, + {"FUSE_PGD0_PG_STS", BIT(22)}, + {"SBR8_PGD0_PG_STS", BIT(23)}, + {"SOC_D2D_PGD2_PG_STS", BIT(24)}, + {"XDCI_PGD0_PG_STS", BIT(25)}, + {"EXI_PGD0_PG_STS", BIT(26)}, + {"CSE_PGD0_PG_STS", BIT(27)}, + {"KVMCC_PGD0_PG_STS", BIT(28)}, + {"PMT_PGD0_PG_STS", BIT(29)}, + {"CLINK_PGD0_PG_STS", BIT(30)}, + {"PTIO_PGD0_PG_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map mtl_socm_power_gating_status_1_map[] = { + {"USBR0_PGD0_PG_STS", BIT(0)}, + {"SUSRAM_PGD0_PG_STS", BIT(1)}, + {"SMT1_PGD0_PG_STS", BIT(2)}, + {"FIACPCB_U_PGD0_PG_STS", BIT(3)}, + {"SMS2_PGD0_PG_STS", BIT(4)}, + {"SMS1_PGD0_PG_STS", BIT(5)}, + {"CSMERTC_PGD0_PG_STS", BIT(6)}, + {"CSMEPSF_PGD0_PG_STS", BIT(7)}, + {"SBR0_PGD0_PG_STS", BIT(8)}, + {"SBR1_PGD0_PG_STS", BIT(9)}, + {"SBR2_PGD0_PG_STS", BIT(10)}, + {"SBR3_PGD0_PG_STS", BIT(11)}, + {"U3FPW1_PGD0_PG_STS", BIT(12)}, + {"SBR5_PGD0_PG_STS", BIT(13)}, + {"MPFPW1_PGD0_PG_STS", BIT(14)}, + {"UFSPW1_PGD0_PG_STS", BIT(15)}, + {"FIA_X_PGD0_PG_STS", BIT(16)}, + {"SOC_D2D_PGD0_PG_STS", BIT(17)}, + {"MPFPW2_PGD0_PG_STS", BIT(18)}, + {"CNVI_PGD0_PG_STS", BIT(19)}, + {"UFSX2_PGD0_PG_STS", BIT(20)}, + {"ENDBG_PGD0_PG_STS", BIT(21)}, + {"DBG_PSF_PGD0_PG_STS", BIT(22)}, + {"SBR6_PGD0_PG_STS", BIT(23)}, + {"SBR7_PGD0_PG_STS", BIT(24)}, + {"NPK_PGD1_PG_STS", BIT(25)}, + {"FIACPCB_X_PGD0_PG_STS", BIT(26)}, + {"DBC_PGD0_PG_STS", BIT(27)}, + {"FUSEGPSB_PGD0_PG_STS", BIT(28)}, + {"PSF6_PGD0_PG_STS", BIT(29)}, + {"PSF7_PGD0_PG_STS", BIT(30)}, + {"GBETSN1_PGD0_PG_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map mtl_socm_power_gating_status_2_map[] = { + {"PSF8_PGD0_PG_STS", BIT(0)}, + {"FIA_PGD0_PG_STS", BIT(1)}, + {"SOC_D2D_PGD1_PG_STS", BIT(2)}, + {"FIA_U_PGD0_PG_STS", BIT(3)}, + {"TAM_PGD0_PG_STS", BIT(4)}, + {"GBETSN_PGD0_PG_STS", BIT(5)}, + {"TBTLSX_PGD0_PG_STS", BIT(6)}, + {"THC0_PGD0_PG_STS", BIT(7)}, + {"THC1_PGD0_PG_STS", BIT(8)}, + {"PMC_PGD1_PG_STS", BIT(9)}, + {"GNA_PGD0_PG_STS", BIT(10)}, + {"ACE_PGD0_PG_STS", BIT(11)}, + {"ACE_PGD1_PG_STS", BIT(12)}, + {"ACE_PGD2_PG_STS", BIT(13)}, + {"ACE_PGD3_PG_STS", BIT(14)}, + {"ACE_PGD4_PG_STS", BIT(15)}, + {"ACE_PGD5_PG_STS", BIT(16)}, + {"ACE_PGD6_PG_STS", BIT(17)}, + {"ACE_PGD7_PG_STS", BIT(18)}, + {"ACE_PGD8_PG_STS", BIT(19)}, + {"FIA_PGS_PGD0_PG_STS", BIT(20)}, + {"FIACPCB_PGS_PGD0_PG_STS", BIT(21)}, + {"FUSEPMSB_PGD0_PG_STS", BIT(22)}, + {} +}; + +const struct pmc_bit_map mtl_socm_d3_status_0_map[] = { + {"LPSS_D3_STS", BIT(3)}, + {"XDCI_D3_STS", BIT(4)}, + {"XHCI_D3_STS", BIT(5)}, + {"SPA_D3_STS", BIT(12)}, + {"SPB_D3_STS", BIT(13)}, + {"SPC_D3_STS", BIT(14)}, + {"SPD_D3_STS", BIT(15)}, + {"ESPISPI_D3_STS", BIT(18)}, + {"SATA_D3_STS", BIT(20)}, + {"PSTH_D3_STS", BIT(21)}, + {"DMI_D3_STS", BIT(22)}, + {} +}; + +const struct pmc_bit_map mtl_socm_d3_status_1_map[] = { + {"GBETSN1_D3_STS", BIT(14)}, + {"GBE_D3_STS", BIT(19)}, + {"ITSS_D3_STS", BIT(23)}, + {"P2S_D3_STS", BIT(24)}, + {"CNVI_D3_STS", BIT(27)}, + {"UFSX2_D3_STS", BIT(28)}, + {} +}; + +const struct pmc_bit_map mtl_socm_d3_status_2_map[] = { + {"GNA_D3_STS", BIT(0)}, + {"CSMERTC_D3_STS", BIT(1)}, + {"SUSRAM_D3_STS", BIT(2)}, + {"CSE_D3_STS", BIT(4)}, + {"KVMCC_D3_STS", BIT(5)}, + {"USBR0_D3_STS", BIT(6)}, + {"ISH_D3_STS", BIT(7)}, + {"SMT1_D3_STS", BIT(8)}, + {"SMT2_D3_STS", BIT(9)}, + {"SMT3_D3_STS", BIT(10)}, + {"CLINK_D3_STS", BIT(14)}, + {"PTIO_D3_STS", BIT(16)}, + {"PMT_D3_STS", BIT(17)}, + {"SMS1_D3_STS", BIT(18)}, + {"SMS2_D3_STS", BIT(19)}, + {} +}; + +const struct pmc_bit_map mtl_socm_d3_status_3_map[] = { + {"ESE_D3_STS", BIT(2)}, + {"GBETSN_D3_STS", BIT(13)}, + {"THC0_D3_STS", BIT(14)}, + {"THC1_D3_STS", BIT(15)}, + {"ACE_D3_STS", BIT(23)}, + {} +}; + +const struct pmc_bit_map mtl_socm_vnn_req_status_0_map[] = { + {"LPSS_VNN_REQ_STS", BIT(3)}, + {"FIA_VNN_REQ_STS", BIT(17)}, + {"ESPISPI_VNN_REQ_STS", BIT(18)}, + {} +}; + +const struct pmc_bit_map mtl_socm_vnn_req_status_1_map[] = { + {"NPK_VNN_REQ_STS", BIT(4)}, + {"DFXAGG_VNN_REQ_STS", BIT(8)}, + {"EXI_VNN_REQ_STS", BIT(9)}, + {"P2D_VNN_REQ_STS", BIT(18)}, + {"GBE_VNN_REQ_STS", BIT(19)}, + {"SMB_VNN_REQ_STS", BIT(25)}, + {"LPC_VNN_REQ_STS", BIT(26)}, + {} +}; + +const struct pmc_bit_map mtl_socm_vnn_req_status_2_map[] = { + {"CSMERTC_VNN_REQ_STS", BIT(1)}, + {"CSE_VNN_REQ_STS", BIT(4)}, + {"ISH_VNN_REQ_STS", BIT(7)}, + {"SMT1_VNN_REQ_STS", BIT(8)}, + {"CLINK_VNN_REQ_STS", BIT(14)}, + {"SMS1_VNN_REQ_STS", BIT(18)}, + {"SMS2_VNN_REQ_STS", BIT(19)}, + {"GPIOCOM4_VNN_REQ_STS", BIT(20)}, + {"GPIOCOM3_VNN_REQ_STS", BIT(21)}, + {"GPIOCOM2_VNN_REQ_STS", BIT(22)}, + {"GPIOCOM1_VNN_REQ_STS", BIT(23)}, + {"GPIOCOM0_VNN_REQ_STS", BIT(24)}, + {} +}; + +const struct pmc_bit_map mtl_socm_vnn_req_status_3_map[] = { + {"ESE_VNN_REQ_STS", BIT(2)}, + {"DTS0_VNN_REQ_STS", BIT(7)}, + {"GPIOCOM5_VNN_REQ_STS", BIT(11)}, + {} +}; + +const struct pmc_bit_map mtl_socm_vnn_misc_status_map[] = { + {"CPU_C10_REQ_STS", BIT(0)}, + {"TS_OFF_REQ_STS", BIT(1)}, + {"PNDE_MET_REQ_STS", BIT(2)}, + {"PCIE_DEEP_PM_REQ_STS", BIT(3)}, + {"PMC_CLK_THROTTLE_EN_REQ_STS", BIT(4)}, + {"NPK_VNNAON_REQ_STS", BIT(5)}, + {"VNN_SOC_REQ_STS", BIT(6)}, + {"ISH_VNNAON_REQ_STS", BIT(7)}, + {"IOE_COND_MET_S02I2_0_REQ_STS", BIT(8)}, + {"IOE_COND_MET_S02I2_1_REQ_STS", BIT(9)}, + {"IOE_COND_MET_S02I2_2_REQ_STS", BIT(10)}, + {"PLT_GREATER_REQ_STS", BIT(11)}, + {"PCIE_CLKREQ_REQ_STS", BIT(12)}, + {"PMC_IDLE_FB_OCP_REQ_STS", BIT(13)}, + {"PM_SYNC_STATES_REQ_STS", BIT(14)}, + {"EA_REQ_STS", BIT(15)}, + {"MPHY_CORE_OFF_REQ_STS", BIT(16)}, + {"BRK_EV_EN_REQ_STS", BIT(17)}, + {"AUTO_DEMO_EN_REQ_STS", BIT(18)}, + {"ITSS_CLK_SRC_REQ_STS", BIT(19)}, + {"LPC_CLK_SRC_REQ_STS", BIT(20)}, + {"ARC_IDLE_REQ_STS", BIT(21)}, + {"MPHY_SUS_REQ_STS", BIT(22)}, + {"FIA_DEEP_PM_REQ_STS", BIT(23)}, + {"UXD_CONNECTED_REQ_STS", BIT(24)}, + {"ARC_INTERRUPT_WAKE_REQ_STS", BIT(25)}, + {"USB2_VNNAON_ACT_REQ_STS", BIT(26)}, + {"PRE_WAKE0_REQ_STS", BIT(27)}, + {"PRE_WAKE1_REQ_STS", BIT(28)}, + {"PRE_WAKE2_EN_REQ_STS", BIT(29)}, + {"WOV_REQ_STS", BIT(30)}, + {"CNVI_V1P05_REQ_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map mtl_socm_signal_status_map[] = { + {"LSX_Wake0_En_STS", BIT(0)}, + {"LSX_Wake0_Pol_STS", BIT(1)}, + {"LSX_Wake1_En_STS", BIT(2)}, + {"LSX_Wake1_Pol_STS", BIT(3)}, + {"LSX_Wake2_En_STS", BIT(4)}, + {"LSX_Wake2_Pol_STS", BIT(5)}, + {"LSX_Wake3_En_STS", BIT(6)}, + {"LSX_Wake3_Pol_STS", BIT(7)}, + {"LSX_Wake4_En_STS", BIT(8)}, + {"LSX_Wake4_Pol_STS", BIT(9)}, + {"LSX_Wake5_En_STS", BIT(10)}, + {"LSX_Wake5_Pol_STS", BIT(11)}, + {"LSX_Wake6_En_STS", BIT(12)}, + {"LSX_Wake6_Pol_STS", BIT(13)}, + {"LSX_Wake7_En_STS", BIT(14)}, + {"LSX_Wake7_Pol_STS", BIT(15)}, + {"LPSS_Wake0_En_STS", BIT(16)}, + {"LPSS_Wake0_Pol_STS", BIT(17)}, + {"LPSS_Wake1_En_STS", BIT(18)}, + {"LPSS_Wake1_Pol_STS", BIT(19)}, + {"Int_Timer_SS_Wake0_En_STS", BIT(20)}, + {"Int_Timer_SS_Wake0_Pol_STS", BIT(21)}, + {"Int_Timer_SS_Wake1_En_STS", BIT(22)}, + {"Int_Timer_SS_Wake1_Pol_STS", BIT(23)}, + {"Int_Timer_SS_Wake2_En_STS", BIT(24)}, + {"Int_Timer_SS_Wake2_Pol_STS", BIT(25)}, + {"Int_Timer_SS_Wake3_En_STS", BIT(26)}, + {"Int_Timer_SS_Wake3_Pol_STS", BIT(27)}, + {"Int_Timer_SS_Wake4_En_STS", BIT(28)}, + {"Int_Timer_SS_Wake4_Pol_STS", BIT(29)}, + {"Int_Timer_SS_Wake5_En_STS", BIT(30)}, + {"Int_Timer_SS_Wake5_Pol_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map *mtl_socm_lpm_maps[] = { + mtl_socm_clocksource_status_map, + mtl_socm_power_gating_status_0_map, + mtl_socm_power_gating_status_1_map, + mtl_socm_power_gating_status_2_map, + mtl_socm_d3_status_0_map, + mtl_socm_d3_status_1_map, + mtl_socm_d3_status_2_map, + mtl_socm_d3_status_3_map, + mtl_socm_vnn_req_status_0_map, + mtl_socm_vnn_req_status_1_map, + mtl_socm_vnn_req_status_2_map, + mtl_socm_vnn_req_status_3_map, + mtl_socm_vnn_misc_status_map, + mtl_socm_signal_status_map, + NULL +}; + +const struct pmc_reg_map mtl_socm_reg_map = { + .pfear_sts = ext_mtl_socm_pfear_map, .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, .slp_s0_res_counter_step = TGL_PMC_SLP_S0_RES_COUNTER_STEP, - .ltr_show_sts = adl_ltr_show_map, + .ltr_show_sts = mtl_socm_ltr_show_map, .msr_sts = msr_map, .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, - .regmap_length = CNP_PMC_MMIO_REG_LEN, + .regmap_length = MTL_SOC_PMC_MMIO_REG_LEN, .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, - .ppfear_buckets = ICL_PPFEAR_NUM_ENTRIES, + .ppfear_buckets = MTL_SOCM_PPFEAR_NUM_ENTRIES, .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, - .ltr_ignore_max = ADL_NUM_IP_IGN_ALLOWED, - .lpm_num_modes = ADL_LPM_NUM_MODES, .lpm_num_maps = ADL_LPM_NUM_MAPS, + .ltr_ignore_max = MTL_SOCM_NUM_IP_IGN_ALLOWED, .lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2, .etr3_offset = ETR3_OFFSET, .lpm_sts_latch_en_offset = MTL_LPM_STATUS_LATCH_EN_OFFSET, .lpm_priority_offset = MTL_LPM_PRI_OFFSET, .lpm_en_offset = MTL_LPM_EN_OFFSET, .lpm_residency_offset = MTL_LPM_RESIDENCY_OFFSET, - .lpm_sts = adl_lpm_maps, + .lpm_sts = mtl_socm_lpm_maps, .lpm_status_offset = MTL_LPM_STATUS_OFFSET, .lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET, }; -void mtl_core_configure(struct pmc_dev *pmcdev) -{ - /* Due to a hardware limitation, the GBE LTR blocks PC10 - * when a cable is attached. Tell the PMC to ignore it. - */ - dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); - pmc_core_send_ltr_ignore(pmcdev, 3); -} +const struct pmc_bit_map mtl_ioep_pfear_map[] = { + {"PMC_0", BIT(0)}, + {"OPI", BIT(1)}, + {"TCSS", BIT(2)}, + {"RSVD3", BIT(3)}, + {"SPA", BIT(4)}, + {"SPB", BIT(5)}, + {"SPC", BIT(6)}, + {"IOE_D2D_3", BIT(7)}, + + {"RSVD8", BIT(0)}, + {"RSVD9", BIT(1)}, + {"SPE", BIT(2)}, + {"RSVD11", BIT(3)}, + {"RSVD12", BIT(4)}, + {"SPD", BIT(5)}, + {"ACE_7", BIT(6)}, + {"RSVD15", BIT(7)}, + + {"ACE_0", BIT(0)}, + {"FIACPCB_P", BIT(1)}, + {"P2S", BIT(2)}, + {"RSVD19", BIT(3)}, + {"ACE_8", BIT(4)}, + {"IOE_D2D_0", BIT(5)}, + {"FUSE", BIT(6)}, + {"RSVD23", BIT(7)}, + + {"FIACPCB_P5", BIT(0)}, + {"ACE_3", BIT(1)}, + {"RSF5", BIT(2)}, + {"ACE_2", BIT(3)}, + {"ACE_4", BIT(4)}, + {"RSVD29", BIT(5)}, + {"RSF10", BIT(6)}, + {"MPFPW5", BIT(7)}, + + {"PSF9", BIT(0)}, + {"MPFPW4", BIT(1)}, + {"RSVD34", BIT(2)}, + {"RSVD35", BIT(3)}, + {"RSVD36", BIT(4)}, + {"RSVD37", BIT(5)}, + {"RSVD38", BIT(6)}, + {"RSVD39", BIT(7)}, + + {"SBR0", BIT(0)}, + {"SBR1", BIT(1)}, + {"SBR2", BIT(2)}, + {"SBR3", BIT(3)}, + {"SBR4", BIT(4)}, + {"SBR5", BIT(5)}, + {"RSVD46", BIT(6)}, + {"RSVD47", BIT(7)}, + + {"RSVD48", BIT(0)}, + {"FIA_P5", BIT(1)}, + {"RSVD50", BIT(2)}, + {"RSVD51", BIT(3)}, + {"RSVD52", BIT(4)}, + {"RSVD53", BIT(5)}, + {"RSVD54", BIT(6)}, + {"ACE_1", BIT(7)}, + + {"RSVD56", BIT(0)}, + {"ACE_5", BIT(1)}, + {"RSVD58", BIT(2)}, + {"G5FPW1", BIT(3)}, + {"RSVD60", BIT(4)}, + {"ACE_6", BIT(5)}, + {"RSVD62", BIT(6)}, + {"GBETSN1", BIT(7)}, + + {"RSVD64", BIT(0)}, + {"FIA", BIT(1)}, + {"RSVD66", BIT(2)}, + {"FIA_P", BIT(3)}, + {"TAM", BIT(4)}, + {"GBETSN", BIT(5)}, + {"IOE_D2D_2", BIT(6)}, + {"IOE_D2D_1", BIT(7)}, + + {"SPF", BIT(0)}, + {"PMC_1", BIT(1)}, + {} +}; + +const struct pmc_bit_map *ext_mtl_ioep_pfear_map[] = { + mtl_ioep_pfear_map, + NULL +}; + +const struct pmc_bit_map mtl_ioep_ltr_show_map[] = { + {"SOUTHPORT_A", CNP_PMC_LTR_SPA}, + {"SOUTHPORT_B", CNP_PMC_LTR_SPB}, + {"SATA", CNP_PMC_LTR_SATA}, + {"GIGABIT_ETHERNET", CNP_PMC_LTR_GBE}, + {"XHCI", CNP_PMC_LTR_XHCI}, + {"SOUTHPORT_F", ADL_PMC_LTR_SPF}, + {"ME", CNP_PMC_LTR_ME}, + {"SATA1", CNP_PMC_LTR_EVA}, + {"SOUTHPORT_C", CNP_PMC_LTR_SPC}, + {"HD_AUDIO", CNP_PMC_LTR_AZ}, + {"CNV", CNP_PMC_LTR_CNV}, + {"LPSS", CNP_PMC_LTR_LPSS}, + {"SOUTHPORT_D", CNP_PMC_LTR_SPD}, + {"SOUTHPORT_E", CNP_PMC_LTR_SPE}, + {"SATA2", CNP_PMC_LTR_CAM}, + {"ESPI", CNP_PMC_LTR_ESPI}, + {"SCC", CNP_PMC_LTR_SCC}, + {"Reserved", MTL_PMC_LTR_RESERVED}, + {"UFSX2", CNP_PMC_LTR_UFSX2}, + {"EMMC", CNP_PMC_LTR_EMMC}, + {"WIGIG", ICL_PMC_LTR_WIGIG}, + {"THC0", TGL_PMC_LTR_THC0}, + {"THC1", TGL_PMC_LTR_THC1}, + {"SOUTHPORT_G", MTL_PMC_LTR_SPG}, + + /* Below two cannot be used for LTR_IGNORE */ + {"CURRENT_PLATFORM", CNP_PMC_LTR_CUR_PLT}, + {"AGGREGATED_SYSTEM", CNP_PMC_LTR_CUR_ASLT}, + {} +}; + +const struct pmc_bit_map mtl_ioep_clocksource_status_map[] = { + {"AON2_OFF_STS", BIT(0)}, + {"AON3_OFF_STS", BIT(1)}, + {"AON4_OFF_STS", BIT(2)}, + {"AON5_OFF_STS", BIT(3)}, + {"AON1_OFF_STS", BIT(4)}, + {"TBT_PLL_OFF_STS", BIT(5)}, + {"TMU_PLL_OFF_STS", BIT(6)}, + {"BCLK_PLL_OFF_STS", BIT(7)}, + {"D2D_PLL_OFF_STS", BIT(8)}, + {"AON3_SPL_OFF_STS", BIT(9)}, + {"MPFPW4_0_PLL_OFF_STS", BIT(12)}, + {"MPFPW5_0_PLL_OFF_STS", BIT(13)}, + {"G5FPW_0_PLL_OFF_STS", BIT(14)}, + {"G5FPW_1_PLL_OFF_STS", BIT(15)}, + {"XTAL_AGGR_OFF_STS", BIT(17)}, + {"FABRIC_PLL_OFF_STS", BIT(25)}, + {"SOC_PLL_OFF_STS", BIT(26)}, + {"REF_PLL_OFF_STS", BIT(28)}, + {"RTC_PLL_OFF_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map mtl_ioep_power_gating_status_0_map[] = { + {"PMC_PGD0_PG_STS", BIT(0)}, + {"DMI_PGD0_PG_STS", BIT(1)}, + {"TCSS_PGD0_PG_STS", BIT(2)}, + {"SPA_PGD0_PG_STS", BIT(4)}, + {"SPB_PGD0_PG_STS", BIT(5)}, + {"SPC_PGD0_PG_STS", BIT(6)}, + {"IOE_D2D_PGD3_PG_STS", BIT(7)}, + {"SPE_PGD0_PG_STS", BIT(10)}, + {"SPD_PGD0_PG_STS", BIT(13)}, + {"ACE_PGD7_PG_STS", BIT(14)}, + {"ACE_PGD0_PG_STS", BIT(16)}, + {"FIACPCB_P_PGD0_PG_STS", BIT(17)}, + {"P2S_PGD0_PG_STS", BIT(18)}, + {"ACE_PGD8_PG_STS", BIT(20)}, + {"IOE_D2D_PGD0_PG_STS", BIT(21)}, + {"FUSE_PGD0_PG_STS", BIT(22)}, + {"FIACPCB_P5_PGD0_PG_STS", BIT(24)}, + {"ACE_PGD3_PG_STS", BIT(25)}, + {"PSF5_PGD0_PG_STS", BIT(26)}, + {"ACE_PGD2_PG_STS", BIT(27)}, + {"ACE_PGD4_PG_STS", BIT(28)}, + {"PSF10_PGD0_PG_STS", BIT(30)}, + {"MPFPW5_PGD0_PG_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map mtl_ioep_power_gating_status_1_map[] = { + {"PSF9_PGD0_PG_STS", BIT(0)}, + {"MPFPW4_PGD0_PG_STS", BIT(1)}, + {"SBR0_PGD0_PG_STS", BIT(8)}, + {"SBR1_PGD0_PG_STS", BIT(9)}, + {"SBR2_PGD0_PG_STS", BIT(10)}, + {"SBR3_PGD0_PG_STS", BIT(11)}, + {"SBR4_PGD0_PG_STS", BIT(12)}, + {"SBR5_PGD0_PG_STS", BIT(13)}, + {"FIA_P5_PGD0_PG_STS", BIT(17)}, + {"ACE_PGD1_PGD0_PG_STS", BIT(23)}, + {"ACE_PGD5_PGD1_PG_STS", BIT(25)}, + {"G5FPW1_PGD0_PG_STS", BIT(27)}, + {"ACE_PGD6_PG_STS", BIT(29)}, + {"GBETSN1_PGD0_PG_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map mtl_ioep_power_gating_status_2_map[] = { + {"FIA_PGD0_PG_STS", BIT(1)}, + {"FIA_P_PGD0_PG_STS", BIT(3)}, + {"TAM_PGD0_PG_STS", BIT(4)}, + {"GBETSN_PGD0_PG_STS", BIT(5)}, + {"IOE_D2D_PGD2_PG_STS", BIT(6)}, + {"IOE_D2D_PGD1_PG_STS", BIT(7)}, + {"SPF_PGD0_PG_STS", BIT(8)}, + {"PMC_PGD1_PG_STS", BIT(9)}, + {} +}; + +const struct pmc_bit_map mtl_ioep_d3_status_0_map[] = { + {"SPF_D3_STS", BIT(0)}, + {"SPA_D3_STS", BIT(12)}, + {"SPB_D3_STS", BIT(13)}, + {"SPC_D3_STS", BIT(14)}, + {"SPD_D3_STS", BIT(15)}, + {"SPE_D3_STS", BIT(16)}, + {"DMI_D3_STS", BIT(22)}, + {} +}; + +const struct pmc_bit_map mtl_ioep_d3_status_1_map[] = { + {"GBETSN1_D3_STS", BIT(14)}, + {"P2S_D3_STS", BIT(24)}, + {} +}; + +const struct pmc_bit_map mtl_ioep_d3_status_2_map[] = { + {} +}; + +const struct pmc_bit_map mtl_ioep_d3_status_3_map[] = { + {"GBETSN_D3_STS", BIT(13)}, + {"ACE_D3_STS", BIT(23)}, + {} +}; + +const struct pmc_bit_map mtl_ioep_vnn_req_status_0_map[] = { + {"FIA_VNN_REQ_STS", BIT(17)}, + {} +}; + +const struct pmc_bit_map mtl_ioep_vnn_req_status_1_map[] = { + {"DFXAGG_VNN_REQ_STS", BIT(8)}, + {} +}; + +const struct pmc_bit_map mtl_ioep_vnn_req_status_2_map[] = { + {} +}; + +const struct pmc_bit_map mtl_ioep_vnn_req_status_3_map[] = { + {"DTS0_VNN_REQ_STS", BIT(7)}, + {"DISP_VNN_REQ_STS", BIT(19)}, + {} +}; + +const struct pmc_bit_map mtl_ioep_vnn_misc_status_map[] = { + {"CPU_C10_REQ_STS", BIT(0)}, + {"TS_OFF_REQ_STS", BIT(1)}, + {"PNDE_MET_REQ_STS", BIT(2)}, + {"PCIE_DEEP_PM_REQ_STS", BIT(3)}, + {"PMC_CLK_THROTTLE_EN_REQ_STS", BIT(4)}, + {"NPK_VNNAON_REQ_STS", BIT(5)}, + {"VNN_SOC_REQ_STS", BIT(6)}, + {"USB_DEVICE_ATTACHED_REQ_STS", BIT(8)}, + {"FIA_EXIT_REQ_STS", BIT(9)}, + {"USB2_SUS_PG_REQ_STS", BIT(10)}, + {"PLT_GREATER_REQ_STS", BIT(11)}, + {"PCIE_CLKREQ_REQ_STS", BIT(12)}, + {"PMC_IDLE_FB_OCP_REQ_STS", BIT(13)}, + {"PM_SYNC_STATES_REQ_STS", BIT(14)}, + {"EA_REQ_STS", BIT(15)}, + {"MPHY_CORE_OFF_REQ_STS", BIT(16)}, + {"BRK_EV_EN_REQ_STS", BIT(17)}, + {"AUTO_DEMO_EN_REQ_STS", BIT(18)}, + {"ITSS_CLK_SRC_REQ_STS", BIT(19)}, + {"LPC_CLK_SRC_REQ_STS", BIT(20)}, + {"ARC_IDLE_REQ_STS", BIT(21)}, + {"MPHY_SUS_REQ_STS", BIT(22)}, + {"FIA_DEEP_PM_REQ_STS", BIT(23)}, + {"UXD_CONNECTED_REQ_STS", BIT(24)}, + {"ARC_INTERRUPT_WAKE_REQ_STS", BIT(25)}, + {"USB2_VNNAON_ACT_REQ_STS", BIT(26)}, + {"PRE_WAKE0_REQ_STS", BIT(27)}, + {"PRE_WAKE1_REQ_STS", BIT(28)}, + {"PRE_WAKE2_EN_REQ_STS", BIT(29)}, + {"WOV_REQ_STS", BIT(30)}, + {"CNVI_V1P05_REQ_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map *mtl_ioep_lpm_maps[] = { + mtl_ioep_clocksource_status_map, + mtl_ioep_power_gating_status_0_map, + mtl_ioep_power_gating_status_1_map, + mtl_ioep_power_gating_status_2_map, + mtl_ioep_d3_status_0_map, + mtl_ioep_d3_status_1_map, + mtl_ioep_d3_status_2_map, + mtl_ioep_d3_status_3_map, + mtl_ioep_vnn_req_status_0_map, + mtl_ioep_vnn_req_status_1_map, + mtl_ioep_vnn_req_status_2_map, + mtl_ioep_vnn_req_status_3_map, + mtl_ioep_vnn_misc_status_map, + mtl_socm_signal_status_map, + NULL +}; + +const struct pmc_reg_map mtl_ioep_reg_map = { + .regmap_length = MTL_IOE_PMC_MMIO_REG_LEN, + .pfear_sts = ext_mtl_ioep_pfear_map, + .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, + .ppfear_buckets = MTL_IOE_PPFEAR_NUM_ENTRIES, + .lpm_status_offset = MTL_LPM_STATUS_OFFSET, + .lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET, + .lpm_sts = mtl_ioep_lpm_maps, + .ltr_show_sts = mtl_ioep_ltr_show_map, + .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, + .ltr_ignore_max = ADL_NUM_IP_IGN_ALLOWED, +}; + +const struct pmc_bit_map mtl_ioem_pfear_map[] = { + {"PMC_0", BIT(0)}, + {"OPI", BIT(1)}, + {"TCSS", BIT(2)}, + {"RSVD3", BIT(3)}, + {"SPA", BIT(4)}, + {"SPB", BIT(5)}, + {"SPC", BIT(6)}, + {"IOE_D2D_3", BIT(7)}, + + {"RSVD8", BIT(0)}, + {"RSVD9", BIT(1)}, + {"SPE", BIT(2)}, + {"RSVD11", BIT(3)}, + {"RSVD12", BIT(4)}, + {"SPD", BIT(5)}, + {"ACE_7", BIT(6)}, + {"RSVD15", BIT(7)}, + + {"ACE_0", BIT(0)}, + {"FIACPCB_P", BIT(1)}, + {"P2S", BIT(2)}, + {"RSVD19", BIT(3)}, + {"ACE_8", BIT(4)}, + {"IOE_D2D_0", BIT(5)}, + {"FUSE", BIT(6)}, + {"RSVD23", BIT(7)}, + + {"FIACPCB_P5", BIT(0)}, + {"ACE_3", BIT(1)}, + {"RSF5", BIT(2)}, + {"ACE_2", BIT(3)}, + {"ACE_4", BIT(4)}, + {"RSVD29", BIT(5)}, + {"RSF10", BIT(6)}, + {"MPFPW5", BIT(7)}, + + {"PSF9", BIT(0)}, + {"MPFPW4", BIT(1)}, + {"RSVD34", BIT(2)}, + {"RSVD35", BIT(3)}, + {"RSVD36", BIT(4)}, + {"RSVD37", BIT(5)}, + {"RSVD38", BIT(6)}, + {"RSVD39", BIT(7)}, + + {"SBR0", BIT(0)}, + {"SBR1", BIT(1)}, + {"SBR2", BIT(2)}, + {"SBR3", BIT(3)}, + {"SBR4", BIT(4)}, + {"RSVD45", BIT(5)}, + {"RSVD46", BIT(6)}, + {"RSVD47", BIT(7)}, + + {"RSVD48", BIT(0)}, + {"FIA_P5", BIT(1)}, + {"RSVD50", BIT(2)}, + {"RSVD51", BIT(3)}, + {"RSVD52", BIT(4)}, + {"RSVD53", BIT(5)}, + {"RSVD54", BIT(6)}, + {"ACE_1", BIT(7)}, + + {"RSVD56", BIT(0)}, + {"ACE_5", BIT(1)}, + {"RSVD58", BIT(2)}, + {"G5FPW1", BIT(3)}, + {"RSVD60", BIT(4)}, + {"ACE_6", BIT(5)}, + {"RSVD62", BIT(6)}, + {"GBETSN1", BIT(7)}, + + {"RSVD64", BIT(0)}, + {"FIA", BIT(1)}, + {"RSVD66", BIT(2)}, + {"FIA_P", BIT(3)}, + {"TAM", BIT(4)}, + {"GBETSN", BIT(5)}, + {"IOE_D2D_2", BIT(6)}, + {"IOE_D2D_1", BIT(7)}, + + {"SPF", BIT(0)}, + {"PMC_1", BIT(1)}, + {} +}; + +const struct pmc_bit_map *ext_mtl_ioem_pfear_map[] = { + mtl_ioem_pfear_map, + NULL +}; + +const struct pmc_bit_map mtl_ioem_power_gating_status_1_map[] = { + {"PSF9_PGD0_PG_STS", BIT(0)}, + {"MPFPW4_PGD0_PG_STS", BIT(1)}, + {"SBR0_PGD0_PG_STS", BIT(8)}, + {"SBR1_PGD0_PG_STS", BIT(9)}, + {"SBR2_PGD0_PG_STS", BIT(10)}, + {"SBR3_PGD0_PG_STS", BIT(11)}, + {"SBR4_PGD0_PG_STS", BIT(12)}, + {"FIA_P5_PGD0_PG_STS", BIT(17)}, + {"ACE_PGD1_PGD0_PG_STS", BIT(23)}, + {"ACE_PGD5_PGD1_PG_STS", BIT(25)}, + {"G5FPW1_PGD0_PG_STS", BIT(27)}, + {"ACE_PGD6_PG_STS", BIT(29)}, + {"GBETSN1_PGD0_PG_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map *mtl_ioem_lpm_maps[] = { + mtl_ioep_clocksource_status_map, + mtl_ioep_power_gating_status_0_map, + mtl_ioem_power_gating_status_1_map, + mtl_ioep_power_gating_status_2_map, + mtl_ioep_d3_status_0_map, + mtl_ioep_d3_status_1_map, + mtl_ioep_d3_status_2_map, + mtl_ioep_d3_status_3_map, + mtl_ioep_vnn_req_status_0_map, + mtl_ioep_vnn_req_status_1_map, + mtl_ioep_vnn_req_status_2_map, + mtl_ioep_vnn_req_status_3_map, + mtl_ioep_vnn_misc_status_map, + mtl_socm_signal_status_map, + NULL +}; + +const struct pmc_reg_map mtl_ioem_reg_map = { + .regmap_length = MTL_IOE_PMC_MMIO_REG_LEN, + .pfear_sts = ext_mtl_ioem_pfear_map, + .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, + .ppfear_buckets = MTL_IOE_PPFEAR_NUM_ENTRIES, + .lpm_status_offset = MTL_LPM_STATUS_OFFSET, + .lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET, + .lpm_sts = mtl_ioem_lpm_maps, + .ltr_show_sts = mtl_ioep_ltr_show_map, + .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, + .ltr_ignore_max = ADL_NUM_IP_IGN_ALLOWED, +}; + +#define PMC_DEVID_SOCM 0x7e7f +#define PMC_DEVID_IOEP 0x7ecf +#define PMC_DEVID_IOEM 0x7ebf +static struct pmc_info mtl_pmc_info_list[] = { + { + .devid = PMC_DEVID_SOCM, + .map = &mtl_socm_reg_map, + }, + { + .devid = PMC_DEVID_IOEP, + .map = &mtl_ioep_reg_map, + }, + { + .devid = PMC_DEVID_IOEM, + .map = &mtl_ioem_reg_map + }, + {} +}; #define MTL_GNA_PCI_DEV 0x7e4c #define MTL_IPU_PCI_DEV 0x7d19 @@ -68,16 +965,48 @@ static void mtl_set_device_d3(unsigned int device) } } -void mtl_core_init(struct pmc_dev *pmcdev) +/* + * Set power state of select devices that do not have drivers to D3 + * so that they do not block Package C entry. + */ +static void mtl_d3_fixup(void) { - pmcdev->map = &mtl_reg_map; - pmcdev->core_configure = mtl_core_configure; - - /* - * Set power state of select devices that do not have drivers to D3 - * so that they do not block Package C entry. - */ mtl_set_device_d3(MTL_GNA_PCI_DEV); mtl_set_device_d3(MTL_IPU_PCI_DEV); mtl_set_device_d3(MTL_VPU_PCI_DEV); } + +static int mtl_resume(struct pmc_dev *pmcdev) +{ + mtl_d3_fixup(); + return pmc_core_resume_common(pmcdev); +} + +int mtl_core_init(struct pmc_dev *pmcdev) +{ + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_SOC]; + int ret = 0; + + mtl_d3_fixup(); + + pmcdev->resume = mtl_resume; + + pmcdev->regmap_list = mtl_pmc_info_list; + pmc_core_ssram_init(pmcdev); + + /* If regbase not assigned, set map and discover using legacy method */ + if (!pmc->regbase) { + pmc->map = &mtl_socm_reg_map; + ret = get_primary_reg_base(pmc); + if (ret) + return ret; + } + + /* Due to a hardware limitation, the GBE LTR blocks PC10 + * when a cable is attached. Tell the PMC to ignore it. + */ + dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); + pmc_core_send_ltr_ignore(pmcdev, 3); + + return 0; +} diff --git a/drivers/platform/x86/intel/pmc/spt.c b/drivers/platform/x86/intel/pmc/spt.c index e16982236778..4b6f5cbda16c 100644 --- a/drivers/platform/x86/intel/pmc/spt.c +++ b/drivers/platform/x86/intel/pmc/spt.c @@ -134,7 +134,10 @@ const struct pmc_reg_map spt_reg_map = { .pm_vric1_offset = SPT_PMC_VRIC1_OFFSET, }; -void spt_core_init(struct pmc_dev *pmcdev) +int spt_core_init(struct pmc_dev *pmcdev) { - pmcdev->map = &spt_reg_map; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + + pmc->map = &spt_reg_map; + return get_primary_reg_base(pmc); } diff --git a/drivers/platform/x86/intel/pmc/tgl.c b/drivers/platform/x86/intel/pmc/tgl.c index c245ada849d0..2449940102db 100644 --- a/drivers/platform/x86/intel/pmc/tgl.c +++ b/drivers/platform/x86/intel/pmc/tgl.c @@ -208,7 +208,8 @@ const struct pmc_reg_map tgl_reg_map = { void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev) { struct pmc_dev *pmcdev = platform_get_drvdata(pdev); - const int num_maps = pmcdev->map->lpm_num_maps; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + const int num_maps = pmc->map->lpm_num_maps; u32 lpm_size = LPM_MAX_NUM_MODES * num_maps * 4; union acpi_object *out_obj; struct acpi_device *adev; @@ -246,24 +247,28 @@ void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev) goto free_acpi_obj; memcpy(lpm_req_regs, addr, lpm_size); - pmcdev->lpm_req_regs = lpm_req_regs; + pmc->lpm_req_regs = lpm_req_regs; free_acpi_obj: ACPI_FREE(out_obj); } -void tgl_core_configure(struct pmc_dev *pmcdev) +int tgl_core_init(struct pmc_dev *pmcdev) { + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + int ret; + + pmc->map = &tgl_reg_map; + ret = get_primary_reg_base(pmc); + if (ret) + return ret; + pmc_core_get_tgl_lpm_reqs(pmcdev->pdev); /* Due to a hardware limitation, the GBE LTR blocks PC10 * when a cable is attached. Tell the PMC to ignore it. */ dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); pmc_core_send_ltr_ignore(pmcdev, 3); -} -void tgl_core_init(struct pmc_dev *pmcdev) -{ - pmcdev->map = &tgl_reg_map; - pmcdev->core_configure = tgl_core_configure; + return 0; } diff --git a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c index 02fe360a59c7..1f59ac55c5f7 100644 --- a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c +++ b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c @@ -829,6 +829,7 @@ void isst_if_cdev_unregister(int device_type) { isst_misc_unreg(); mutex_lock(&punit_misc_dev_open_lock); + punit_callbacks[device_type].def_ioctl = NULL; punit_callbacks[device_type].registered = 0; if (device_type == ISST_IF_DEV_MBOX) isst_delete_hash(); diff --git a/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c b/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c index 664d2ee60385..63faa2ea8327 100644 --- a/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c +++ b/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c @@ -1414,6 +1414,8 @@ int tpmi_sst_init(void) ret = isst_if_cdev_register(ISST_IF_DEV_TPMI, &cb); if (ret) kfree(isst_common.sst_inst); + else + ++isst_core_usage_count; init_done: mutex_unlock(&isst_tpmi_dev_lock); return ret; diff --git a/drivers/platform/x86/intel/tpmi.c b/drivers/platform/x86/intel/tpmi.c index a5227951decc..9c606ee2030c 100644 --- a/drivers/platform/x86/intel/tpmi.c +++ b/drivers/platform/x86/intel/tpmi.c @@ -222,7 +222,7 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info, snprintf(feature_id_name, sizeof(feature_id_name), "tpmi-%s", name); for (i = 0, tmp = res; i < pfs->pfs_header.num_entries; i++, tmp++) { - u64 entry_size_bytes = pfs->pfs_header.entry_size * 4; + u64 entry_size_bytes = pfs->pfs_header.entry_size * sizeof(u32); tmp->start = pfs->vsec_offset + entry_size_bytes * i; tmp->end = tmp->start + entry_size_bytes - 1; @@ -277,7 +277,7 @@ static int tpmi_process_info(struct intel_tpmi_info *tpmi_info, void __iomem *info_mem; info_mem = ioremap(pfs->vsec_offset + TPMI_INFO_BUS_INFO_OFFSET, - pfs->pfs_header.entry_size * 4 - TPMI_INFO_BUS_INFO_OFFSET); + pfs->pfs_header.entry_size * sizeof(u32) - TPMI_INFO_BUS_INFO_OFFSET); if (!info_mem) return -ENOMEM; @@ -308,6 +308,8 @@ static int tpmi_fetch_pfs_header(struct intel_tpmi_pm_feature *pfs, u64 start, i return 0; } +#define TPMI_CAP_OFFSET_UNIT 1024 + static int intel_vsec_tpmi_init(struct auxiliary_device *auxdev) { struct intel_vsec_device *vsec_dev = auxdev_to_ivdev(auxdev); @@ -354,7 +356,7 @@ static int intel_vsec_tpmi_init(struct auxiliary_device *auxdev) if (!pfs_start) pfs_start = res_start; - pfs->pfs_header.cap_offset *= 1024; + pfs->pfs_header.cap_offset *= TPMI_CAP_OFFSET_UNIT; pfs->vsec_offset = pfs_start + pfs->pfs_header.cap_offset; diff --git a/drivers/platform/x86/intel/uncore-frequency/Kconfig b/drivers/platform/x86/intel/uncore-frequency/Kconfig index 21b209124916..a56d55056927 100644 --- a/drivers/platform/x86/intel/uncore-frequency/Kconfig +++ b/drivers/platform/x86/intel/uncore-frequency/Kconfig @@ -6,9 +6,13 @@ menu "Intel Uncore Frequency Control" depends on X86_64 || COMPILE_TEST +config INTEL_UNCORE_FREQ_CONTROL_TPMI + tristate + config INTEL_UNCORE_FREQ_CONTROL tristate "Intel Uncore frequency control driver" depends on X86_64 + select INTEL_UNCORE_FREQ_CONTROL_TPMI if INTEL_TPMI help This driver allows control of Uncore frequency limits on supported server platforms. diff --git a/drivers/platform/x86/intel/uncore-frequency/Makefile b/drivers/platform/x86/intel/uncore-frequency/Makefile index e0f7968e8285..08ff57492b28 100644 --- a/drivers/platform/x86/intel/uncore-frequency/Makefile +++ b/drivers/platform/x86/intel/uncore-frequency/Makefile @@ -7,3 +7,5 @@ obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL) += intel-uncore-frequency.o intel-uncore-frequency-y := uncore-frequency.o obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL) += intel-uncore-frequency-common.o intel-uncore-frequency-common-y := uncore-frequency-common.o +obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL_TPMI) += intel-uncore-frequency-tpmi.o +intel-uncore-frequency-tpmi-y := uncore-frequency-tpmi.o diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c index 064f186ae81b..1152deaa0078 100644 --- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c +++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c @@ -16,11 +16,34 @@ static struct kobject *uncore_root_kobj; /* uncore instance count */ static int uncore_instance_count; +static DEFINE_IDA(intel_uncore_ida); + /* callbacks for actual HW read/write */ static int (*uncore_read)(struct uncore_data *data, unsigned int *min, unsigned int *max); static int (*uncore_write)(struct uncore_data *data, unsigned int input, unsigned int min_max); static int (*uncore_read_freq)(struct uncore_data *data, unsigned int *freq); +static ssize_t show_domain_id(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct uncore_data *data = container_of(attr, struct uncore_data, domain_id_dev_attr); + + return sprintf(buf, "%u\n", data->domain_id); +} + +static ssize_t show_fabric_cluster_id(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct uncore_data *data = container_of(attr, struct uncore_data, fabric_cluster_id_dev_attr); + + return sprintf(buf, "%u\n", data->cluster_id); +} + +static ssize_t show_package_id(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct uncore_data *data = container_of(attr, struct uncore_data, package_id_dev_attr); + + return sprintf(buf, "%u\n", data->package_id); +} + static ssize_t show_min_max_freq_khz(struct uncore_data *data, char *buf, int min_max) { @@ -161,6 +184,15 @@ static int create_attr_group(struct uncore_data *data, char *name) init_attribute_ro(initial_max_freq_khz); init_attribute_root_ro(current_freq_khz); + if (data->domain_id != UNCORE_DOMAIN_ID_INVALID) { + init_attribute_root_ro(domain_id); + data->uncore_attrs[index++] = &data->domain_id_dev_attr.attr; + init_attribute_root_ro(fabric_cluster_id); + data->uncore_attrs[index++] = &data->fabric_cluster_id_dev_attr.attr; + init_attribute_root_ro(package_id); + data->uncore_attrs[index++] = &data->package_id_dev_attr.attr; + } + data->uncore_attrs[index++] = &data->max_freq_khz_dev_attr.attr; data->uncore_attrs[index++] = &data->min_freq_khz_dev_attr.attr; data->uncore_attrs[index++] = &data->initial_min_freq_khz_dev_attr.attr; @@ -191,12 +223,24 @@ int uncore_freq_add_entry(struct uncore_data *data, int cpu) goto uncore_unlock; } - sprintf(data->name, "package_%02d_die_%02d", data->package_id, data->die_id); + if (data->domain_id != UNCORE_DOMAIN_ID_INVALID) { + ret = ida_alloc(&intel_uncore_ida, GFP_KERNEL); + if (ret < 0) + goto uncore_unlock; + + data->instance_id = ret; + sprintf(data->name, "uncore%02d", ret); + } else { + sprintf(data->name, "package_%02d_die_%02d", data->package_id, data->die_id); + } uncore_read(data, &data->initial_min_freq_khz, &data->initial_max_freq_khz); ret = create_attr_group(data, data->name); - if (!ret) { + if (ret) { + if (data->domain_id != UNCORE_DOMAIN_ID_INVALID) + ida_free(&intel_uncore_ida, data->instance_id); + } else { data->control_cpu = cpu; data->valid = true; } @@ -214,6 +258,9 @@ void uncore_freq_remove_die_entry(struct uncore_data *data) delete_attr_group(data, data->name); data->control_cpu = -1; data->valid = false; + if (data->domain_id != UNCORE_DOMAIN_ID_INVALID) + ida_free(&intel_uncore_ida, data->instance_id); + mutex_unlock(&uncore_lock); } EXPORT_SYMBOL_NS_GPL(uncore_freq_remove_die_entry, INTEL_UNCORE_FREQUENCY); diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h index f5dcfa2fb285..7afb69977c7e 100644 --- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h +++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h @@ -21,6 +21,9 @@ * @valid: Mark the data valid/invalid * @package_id: Package id for this instance * @die_id: Die id for this instance + * @domain_id: Power domain id for this instance + * @cluster_id: cluster id in a domain + * @instance_id: Unique instance id to append to directory name * @name: Sysfs entry name for this instance * @uncore_attr_group: Attribute group storage * @max_freq_khz_dev_attr: Storage for device attribute max_freq_khz @@ -28,6 +31,9 @@ * @initial_max_freq_khz_dev_attr: Storage for device attribute initial_max_freq_khz * @initial_min_freq_khz_dev_attr: Storage for device attribute initial_min_freq_khz * @current_freq_khz_dev_attr: Storage for device attribute current_freq_khz + * @domain_id_dev_attr: Storage for device attribute domain_id + * @fabric_cluster_id_dev_attr: Storage for device attribute fabric_cluster_id + * @package_id_dev_attr: Storage for device attribute package_id * @uncore_attrs: Attribute storage for group creation * * This structure is used to encapsulate all data related to uncore sysfs @@ -41,6 +47,9 @@ struct uncore_data { bool valid; int package_id; int die_id; + int domain_id; + int cluster_id; + int instance_id; char name[32]; struct attribute_group uncore_attr_group; @@ -49,9 +58,14 @@ struct uncore_data { struct device_attribute initial_max_freq_khz_dev_attr; struct device_attribute initial_min_freq_khz_dev_attr; struct device_attribute current_freq_khz_dev_attr; - struct attribute *uncore_attrs[6]; + struct device_attribute domain_id_dev_attr; + struct device_attribute fabric_cluster_id_dev_attr; + struct device_attribute package_id_dev_attr; + struct attribute *uncore_attrs[9]; }; +#define UNCORE_DOMAIN_ID_INVALID -1 + int uncore_freq_common_init(int (*read_control_freq)(struct uncore_data *data, unsigned int *min, unsigned int *max), int (*write_control_freq)(struct uncore_data *data, unsigned int input, unsigned int min_max), int (*uncore_read_freq)(struct uncore_data *data, unsigned int *freq)); diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c new file mode 100644 index 000000000000..7d0a67f8b517 --- /dev/null +++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c @@ -0,0 +1,413 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * uncore-frquency-tpmi: Uncore frequency scaling using TPMI + * + * Copyright (c) 2023, Intel Corporation. + * All Rights Reserved. + * + * The hardware interface to read/write is basically substitution of + * MSR 0x620 and 0x621. + * There are specific MMIO offset and bits to get/set minimum and + * maximum uncore ratio, similar to MSRs. + * The scope of the uncore MSRs was package scope. But TPMI allows + * new gen CPUs to have multiple uncore controls at uncore-cluster + * level. Each package can have multiple power domains which further + * can have multiple clusters. + * Here number of power domains = number of resources in this aux + * device. There are offsets and bits to discover number of clusters + * and offset for each cluster level controls. + * + */ + +#include <linux/auxiliary_bus.h> +#include <linux/bitfield.h> +#include <linux/bits.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/intel_tpmi.h> + +#include "uncore-frequency-common.h" + +#define UNCORE_HEADER_VERSION 1 +#define UNCORE_HEADER_INDEX 0 +#define UNCORE_FABRIC_CLUSTER_OFFSET 8 + +/* status + control + adv_ctl1 + adv_ctl2 */ +#define UNCORE_FABRIC_CLUSTER_SIZE (4 * 8) + +#define UNCORE_STATUS_INDEX 0 +#define UNCORE_CONTROL_INDEX 8 + +#define UNCORE_FREQ_KHZ_MULTIPLIER 100000 + +struct tpmi_uncore_struct; + +/* Information for each cluster */ +struct tpmi_uncore_cluster_info { + bool root_domain; + u8 __iomem *cluster_base; + struct uncore_data uncore_data; + struct tpmi_uncore_struct *uncore_root; +}; + +/* Information for each power domain */ +struct tpmi_uncore_power_domain_info { + u8 __iomem *uncore_base; + int ufs_header_ver; + int cluster_count; + struct tpmi_uncore_cluster_info *cluster_infos; +}; + +/* Information for all power domains in a package */ +struct tpmi_uncore_struct { + int power_domain_count; + int max_ratio; + int min_ratio; + struct tpmi_uncore_power_domain_info *pd_info; + struct tpmi_uncore_cluster_info root_cluster; +}; + +#define UNCORE_GENMASK_MIN_RATIO GENMASK_ULL(21, 15) +#define UNCORE_GENMASK_MAX_RATIO GENMASK_ULL(14, 8) +#define UNCORE_GENMASK_CURRENT_RATIO GENMASK_ULL(6, 0) + +/* Helper function to read MMIO offset for max/min control frequency */ +static void read_control_freq(struct tpmi_uncore_cluster_info *cluster_info, + unsigned int *min, unsigned int *max) +{ + u64 control; + + control = readq(cluster_info->cluster_base + UNCORE_CONTROL_INDEX); + *max = FIELD_GET(UNCORE_GENMASK_MAX_RATIO, control) * UNCORE_FREQ_KHZ_MULTIPLIER; + *min = FIELD_GET(UNCORE_GENMASK_MIN_RATIO, control) * UNCORE_FREQ_KHZ_MULTIPLIER; +} + +#define UNCORE_MAX_RATIO FIELD_MAX(UNCORE_GENMASK_MAX_RATIO) + +/* Callback for sysfs read for max/min frequencies. Called under mutex locks */ +static int uncore_read_control_freq(struct uncore_data *data, unsigned int *min, + unsigned int *max) +{ + struct tpmi_uncore_cluster_info *cluster_info; + + cluster_info = container_of(data, struct tpmi_uncore_cluster_info, uncore_data); + + if (cluster_info->root_domain) { + struct tpmi_uncore_struct *uncore_root = cluster_info->uncore_root; + int i, _min = 0, _max = 0; + + *min = UNCORE_MAX_RATIO * UNCORE_FREQ_KHZ_MULTIPLIER; + *max = 0; + + /* + * Get the max/min by looking at each cluster. Get the lowest + * min and highest max. + */ + for (i = 0; i < uncore_root->power_domain_count; ++i) { + int j; + + for (j = 0; j < uncore_root->pd_info[i].cluster_count; ++j) { + read_control_freq(&uncore_root->pd_info[i].cluster_infos[j], + &_min, &_max); + if (*min > _min) + *min = _min; + if (*max < _max) + *max = _max; + } + } + return 0; + } + + read_control_freq(cluster_info, min, max); + + return 0; +} + +/* Helper function to write MMIO offset for max/min control frequency */ +static void write_control_freq(struct tpmi_uncore_cluster_info *cluster_info, unsigned int input, + unsigned int min_max) +{ + u64 control; + + control = readq(cluster_info->cluster_base + UNCORE_CONTROL_INDEX); + + if (min_max) { + control &= ~UNCORE_GENMASK_MAX_RATIO; + control |= FIELD_PREP(UNCORE_GENMASK_MAX_RATIO, input); + } else { + control &= ~UNCORE_GENMASK_MIN_RATIO; + control |= FIELD_PREP(UNCORE_GENMASK_MIN_RATIO, input); + } + + writeq(control, (cluster_info->cluster_base + UNCORE_CONTROL_INDEX)); +} + +/* Callback for sysfs write for max/min frequencies. Called under mutex locks */ +static int uncore_write_control_freq(struct uncore_data *data, unsigned int input, + unsigned int min_max) +{ + struct tpmi_uncore_cluster_info *cluster_info; + struct tpmi_uncore_struct *uncore_root; + + input /= UNCORE_FREQ_KHZ_MULTIPLIER; + if (!input || input > UNCORE_MAX_RATIO) + return -EINVAL; + + cluster_info = container_of(data, struct tpmi_uncore_cluster_info, uncore_data); + uncore_root = cluster_info->uncore_root; + + /* Update each cluster in a package */ + if (cluster_info->root_domain) { + struct tpmi_uncore_struct *uncore_root = cluster_info->uncore_root; + int i; + + for (i = 0; i < uncore_root->power_domain_count; ++i) { + int j; + + for (j = 0; j < uncore_root->pd_info[i].cluster_count; ++j) + write_control_freq(&uncore_root->pd_info[i].cluster_infos[j], + input, min_max); + } + + if (min_max) + uncore_root->max_ratio = input; + else + uncore_root->min_ratio = input; + + return 0; + } + + if (min_max && uncore_root->max_ratio && uncore_root->max_ratio < input) + return -EINVAL; + + if (!min_max && uncore_root->min_ratio && uncore_root->min_ratio > input) + return -EINVAL; + + write_control_freq(cluster_info, input, min_max); + + return 0; +} + +/* Callback for sysfs read for the current uncore frequency. Called under mutex locks */ +static int uncore_read_freq(struct uncore_data *data, unsigned int *freq) +{ + struct tpmi_uncore_cluster_info *cluster_info; + u64 status; + + cluster_info = container_of(data, struct tpmi_uncore_cluster_info, uncore_data); + if (cluster_info->root_domain) + return -ENODATA; + + status = readq((u8 __iomem *)cluster_info->cluster_base + UNCORE_STATUS_INDEX); + *freq = FIELD_GET(UNCORE_GENMASK_CURRENT_RATIO, status) * UNCORE_FREQ_KHZ_MULTIPLIER; + + return 0; +} + +static void remove_cluster_entries(struct tpmi_uncore_struct *tpmi_uncore) +{ + int i; + + for (i = 0; i < tpmi_uncore->power_domain_count; ++i) { + struct tpmi_uncore_power_domain_info *pd_info; + int j; + + pd_info = &tpmi_uncore->pd_info[i]; + if (!pd_info->uncore_base) + continue; + + for (j = 0; j < pd_info->cluster_count; ++j) { + struct tpmi_uncore_cluster_info *cluster_info; + + cluster_info = &pd_info->cluster_infos[j]; + uncore_freq_remove_die_entry(&cluster_info->uncore_data); + } + } +} + +#define UNCORE_VERSION_MASK GENMASK_ULL(7, 0) +#define UNCORE_LOCAL_FABRIC_CLUSTER_ID_MASK GENMASK_ULL(15, 8) +#define UNCORE_CLUSTER_OFF_MASK GENMASK_ULL(7, 0) +#define UNCORE_MAX_CLUSTER_PER_DOMAIN 8 + +static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id) +{ + struct intel_tpmi_plat_info *plat_info; + struct tpmi_uncore_struct *tpmi_uncore; + int ret, i, pkg = 0; + int num_resources; + + /* Get number of power domains, which is equal to number of resources */ + num_resources = tpmi_get_resource_count(auxdev); + if (!num_resources) + return -EINVAL; + + /* Register callbacks to uncore core */ + ret = uncore_freq_common_init(uncore_read_control_freq, uncore_write_control_freq, + uncore_read_freq); + if (ret) + return ret; + + /* Allocate uncore instance per package */ + tpmi_uncore = devm_kzalloc(&auxdev->dev, sizeof(*tpmi_uncore), GFP_KERNEL); + if (!tpmi_uncore) { + ret = -ENOMEM; + goto err_rem_common; + } + + /* Allocate memory for all power domains in a package */ + tpmi_uncore->pd_info = devm_kcalloc(&auxdev->dev, num_resources, + sizeof(*tpmi_uncore->pd_info), + GFP_KERNEL); + if (!tpmi_uncore->pd_info) { + ret = -ENOMEM; + goto err_rem_common; + } + + tpmi_uncore->power_domain_count = num_resources; + + /* Get the package ID from the TPMI core */ + plat_info = tpmi_get_platform_data(auxdev); + if (plat_info) + pkg = plat_info->package_id; + else + dev_info(&auxdev->dev, "Platform information is NULL\n"); + + for (i = 0; i < num_resources; ++i) { + struct tpmi_uncore_power_domain_info *pd_info; + struct resource *res; + u64 cluster_offset; + u8 cluster_mask; + int mask, j; + u64 header; + + res = tpmi_get_resource_at_index(auxdev, i); + if (!res) + continue; + + pd_info = &tpmi_uncore->pd_info[i]; + + pd_info->uncore_base = devm_ioremap_resource(&auxdev->dev, res); + if (IS_ERR(pd_info->uncore_base)) { + ret = PTR_ERR(pd_info->uncore_base); + /* + * Set to NULL so that clean up can still remove other + * entries already created if any by + * remove_cluster_entries() + */ + pd_info->uncore_base = NULL; + goto remove_clusters; + } + + /* Check for version and skip this resource if there is mismatch */ + header = readq(pd_info->uncore_base); + pd_info->ufs_header_ver = header & UNCORE_VERSION_MASK; + if (pd_info->ufs_header_ver != UNCORE_HEADER_VERSION) { + dev_info(&auxdev->dev, "Uncore: Unsupported version:%d\n", + pd_info->ufs_header_ver); + continue; + } + + /* Get Cluster ID Mask */ + cluster_mask = FIELD_GET(UNCORE_LOCAL_FABRIC_CLUSTER_ID_MASK, header); + if (!cluster_mask) { + dev_info(&auxdev->dev, "Uncore: Invalid cluster mask:%x\n", cluster_mask); + continue; + } + + /* Find out number of clusters in this resource */ + pd_info->cluster_count = hweight8(cluster_mask); + + pd_info->cluster_infos = devm_kcalloc(&auxdev->dev, pd_info->cluster_count, + sizeof(struct tpmi_uncore_cluster_info), + GFP_KERNEL); + if (!pd_info->cluster_infos) { + ret = -ENOMEM; + goto remove_clusters; + } + /* + * Each byte in the register point to status and control + * registers belonging to cluster id 0-8. + */ + cluster_offset = readq(pd_info->uncore_base + + UNCORE_FABRIC_CLUSTER_OFFSET); + + for (j = 0; j < pd_info->cluster_count; ++j) { + struct tpmi_uncore_cluster_info *cluster_info; + + /* Get the offset for this cluster */ + mask = (cluster_offset & UNCORE_CLUSTER_OFF_MASK); + /* Offset in QWORD, so change to bytes */ + mask <<= 3; + + cluster_info = &pd_info->cluster_infos[j]; + + cluster_info->cluster_base = pd_info->uncore_base + mask; + + cluster_info->uncore_data.package_id = pkg; + /* There are no dies like Cascade Lake */ + cluster_info->uncore_data.die_id = 0; + cluster_info->uncore_data.domain_id = i; + cluster_info->uncore_data.cluster_id = j; + + cluster_info->uncore_root = tpmi_uncore; + + ret = uncore_freq_add_entry(&cluster_info->uncore_data, 0); + if (ret) { + cluster_info->cluster_base = NULL; + goto remove_clusters; + } + /* Point to next cluster offset */ + cluster_offset >>= UNCORE_MAX_CLUSTER_PER_DOMAIN; + } + } + + auxiliary_set_drvdata(auxdev, tpmi_uncore); + + tpmi_uncore->root_cluster.root_domain = true; + tpmi_uncore->root_cluster.uncore_root = tpmi_uncore; + + tpmi_uncore->root_cluster.uncore_data.package_id = pkg; + tpmi_uncore->root_cluster.uncore_data.domain_id = UNCORE_DOMAIN_ID_INVALID; + ret = uncore_freq_add_entry(&tpmi_uncore->root_cluster.uncore_data, 0); + if (ret) + goto remove_clusters; + + return 0; + +remove_clusters: + remove_cluster_entries(tpmi_uncore); +err_rem_common: + uncore_freq_common_exit(); + + return ret; +} + +static void uncore_remove(struct auxiliary_device *auxdev) +{ + struct tpmi_uncore_struct *tpmi_uncore = auxiliary_get_drvdata(auxdev); + + uncore_freq_remove_die_entry(&tpmi_uncore->root_cluster.uncore_data); + remove_cluster_entries(tpmi_uncore); + + uncore_freq_common_exit(); +} + +static const struct auxiliary_device_id intel_uncore_id_table[] = { + { .name = "intel_vsec.tpmi-uncore" }, + {} +}; +MODULE_DEVICE_TABLE(auxiliary, intel_uncore_id_table); + +static struct auxiliary_driver intel_uncore_aux_driver = { + .id_table = intel_uncore_id_table, + .remove = uncore_remove, + .probe = uncore_probe, +}; + +module_auxiliary_driver(intel_uncore_aux_driver); + +MODULE_IMPORT_NS(INTEL_TPMI); +MODULE_IMPORT_NS(INTEL_UNCORE_FREQUENCY); +MODULE_DESCRIPTION("Intel TPMI UFS Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c index 32e2515ee366..a3b25253b6fd 100644 --- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c +++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c @@ -136,6 +136,7 @@ static int uncore_event_cpu_online(unsigned int cpu) data->package_id = topology_physical_package_id(cpu); data->die_id = topology_die_id(cpu); + data->domain_id = UNCORE_DOMAIN_ID_INVALID; return uncore_freq_add_entry(data, cpu); } diff --git a/drivers/platform/x86/lenovo-yogabook-wmi.c b/drivers/platform/x86/lenovo-yogabook-wmi.c deleted file mode 100644 index 5f4bd1eec38a..000000000000 --- a/drivers/platform/x86/lenovo-yogabook-wmi.c +++ /dev/null @@ -1,408 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* WMI driver for Lenovo Yoga Book YB1-X90* / -X91* tablets */ - -#include <linux/acpi.h> -#include <linux/devm-helpers.h> -#include <linux/gpio/consumer.h> -#include <linux/gpio/machine.h> -#include <linux/interrupt.h> -#include <linux/module.h> -#include <linux/leds.h> -#include <linux/wmi.h> -#include <linux/workqueue.h> - -#define YB_MBTN_EVENT_GUID "243FEC1D-1963-41C1-8100-06A9D82A94B4" -#define YB_MBTN_METHOD_GUID "742B0CA1-0B20-404B-9CAA-AEFCABF30CE0" - -#define YB_PAD_ENABLE 1 -#define YB_PAD_DISABLE 2 -#define YB_LIGHTUP_BTN 3 - -#define YB_KBD_BL_DEFAULT 128 - -/* flags */ -enum { - YB_KBD_IS_ON, - YB_DIGITIZER_IS_ON, - YB_DIGITIZER_MODE, - YB_TABLET_MODE, - YB_SUSPENDED, -}; - -struct yogabook_wmi { - struct wmi_device *wdev; - struct acpi_device *kbd_adev; - struct acpi_device *dig_adev; - struct device *kbd_dev; - struct device *dig_dev; - struct gpio_desc *backside_hall_gpio; - int backside_hall_irq; - struct work_struct work; - struct led_classdev kbd_bl_led; - unsigned long flags; - uint8_t brightness; -}; - -static int yogabook_wmi_do_action(struct wmi_device *wdev, int action) -{ - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; - struct acpi_buffer input; - acpi_status status; - u32 dummy_arg = 0; - - dev_dbg(&wdev->dev, "Do action: %d\n", action); - - input.pointer = &dummy_arg; - input.length = sizeof(dummy_arg); - - status = wmi_evaluate_method(YB_MBTN_METHOD_GUID, 0, action, &input, - &output); - if (ACPI_FAILURE(status)) { - dev_err(&wdev->dev, "Calling WMI method failure: 0x%x\n", - status); - return status; - } - - kfree(output.pointer); - - return 0; -} - -/* - * To control keyboard backlight, call the method KBLC() of the TCS1 ACPI - * device (Goodix touchpad acts as virtual sensor keyboard). - */ -static int yogabook_wmi_set_kbd_backlight(struct wmi_device *wdev, - uint8_t level) -{ - struct yogabook_wmi *data = dev_get_drvdata(&wdev->dev); - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; - struct acpi_object_list input; - union acpi_object param; - acpi_status status; - - if (data->kbd_adev->power.state != ACPI_STATE_D0) { - dev_warn(&wdev->dev, "keyboard touchscreen not in D0, cannot set brightness\n"); - return -ENXIO; - } - - dev_dbg(&wdev->dev, "Set KBLC level to %u\n", level); - - input.count = 1; - input.pointer = ¶m; - - param.type = ACPI_TYPE_INTEGER; - param.integer.value = 255 - level; - - status = acpi_evaluate_object(acpi_device_handle(data->kbd_adev), "KBLC", - &input, &output); - if (ACPI_FAILURE(status)) { - dev_err(&wdev->dev, "Failed to call KBLC method: 0x%x\n", status); - return status; - } - - kfree(output.pointer); - return 0; -} - -static void yogabook_wmi_work(struct work_struct *work) -{ - struct yogabook_wmi *data = container_of(work, struct yogabook_wmi, work); - struct device *dev = &data->wdev->dev; - bool kbd_on, digitizer_on; - int r; - - if (test_bit(YB_SUSPENDED, &data->flags)) - return; - - if (test_bit(YB_TABLET_MODE, &data->flags)) { - kbd_on = false; - digitizer_on = false; - } else if (test_bit(YB_DIGITIZER_MODE, &data->flags)) { - digitizer_on = true; - kbd_on = false; - } else { - kbd_on = true; - digitizer_on = false; - } - - if (!kbd_on && test_bit(YB_KBD_IS_ON, &data->flags)) { - /* - * Must be done before releasing the keyboard touchscreen driver, - * so that the keyboard touchscreen dev is still in D0. - */ - yogabook_wmi_set_kbd_backlight(data->wdev, 0); - device_release_driver(data->kbd_dev); - clear_bit(YB_KBD_IS_ON, &data->flags); - } - - if (!digitizer_on && test_bit(YB_DIGITIZER_IS_ON, &data->flags)) { - yogabook_wmi_do_action(data->wdev, YB_PAD_DISABLE); - device_release_driver(data->dig_dev); - clear_bit(YB_DIGITIZER_IS_ON, &data->flags); - } - - if (kbd_on && !test_bit(YB_KBD_IS_ON, &data->flags)) { - r = device_reprobe(data->kbd_dev); - if (r) - dev_warn(dev, "Reprobe of keyboard touchscreen failed: %d\n", r); - - yogabook_wmi_set_kbd_backlight(data->wdev, data->brightness); - set_bit(YB_KBD_IS_ON, &data->flags); - } - - if (digitizer_on && !test_bit(YB_DIGITIZER_IS_ON, &data->flags)) { - r = device_reprobe(data->dig_dev); - if (r) - dev_warn(dev, "Reprobe of digitizer failed: %d\n", r); - - yogabook_wmi_do_action(data->wdev, YB_PAD_ENABLE); - set_bit(YB_DIGITIZER_IS_ON, &data->flags); - } -} - -static void yogabook_wmi_notify(struct wmi_device *wdev, union acpi_object *dummy) -{ - struct yogabook_wmi *data = dev_get_drvdata(&wdev->dev); - - if (test_bit(YB_SUSPENDED, &data->flags)) - return; - - if (test_bit(YB_DIGITIZER_MODE, &data->flags)) - clear_bit(YB_DIGITIZER_MODE, &data->flags); - else - set_bit(YB_DIGITIZER_MODE, &data->flags); - - /* - * We are called from the ACPI core and the driver [un]binding which is - * done also needs ACPI functions, use a workqueue to avoid deadlocking. - */ - schedule_work(&data->work); -} - -static irqreturn_t yogabook_backside_hall_irq(int irq, void *_data) -{ - struct yogabook_wmi *data = _data; - - if (gpiod_get_value(data->backside_hall_gpio)) - set_bit(YB_TABLET_MODE, &data->flags); - else - clear_bit(YB_TABLET_MODE, &data->flags); - - schedule_work(&data->work); - - return IRQ_HANDLED; -} - -static enum led_brightness kbd_brightness_get(struct led_classdev *cdev) -{ - struct yogabook_wmi *data = - container_of(cdev, struct yogabook_wmi, kbd_bl_led); - - return data->brightness; -} - -static int kbd_brightness_set(struct led_classdev *cdev, - enum led_brightness value) -{ - struct yogabook_wmi *data = - container_of(cdev, struct yogabook_wmi, kbd_bl_led); - struct wmi_device *wdev = data->wdev; - - if ((value < 0) || (value > 255)) - return -EINVAL; - - data->brightness = value; - - if (data->kbd_adev->power.state != ACPI_STATE_D0) - return 0; - - return yogabook_wmi_set_kbd_backlight(wdev, data->brightness); -} - -static struct gpiod_lookup_table yogabook_wmi_gpios = { - .dev_id = "243FEC1D-1963-41C1-8100-06A9D82A94B4", - .table = { - GPIO_LOOKUP("INT33FF:02", 18, "backside_hall_sw", GPIO_ACTIVE_LOW), - {} - }, -}; - -static void yogabook_wmi_rm_gpio_lookup(void *unused) -{ - gpiod_remove_lookup_table(&yogabook_wmi_gpios); -} - -static int yogabook_wmi_probe(struct wmi_device *wdev, const void *context) -{ - struct yogabook_wmi *data; - int r; - - data = devm_kzalloc(&wdev->dev, sizeof(struct yogabook_wmi), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - dev_set_drvdata(&wdev->dev, data); - - data->wdev = wdev; - data->brightness = YB_KBD_BL_DEFAULT; - set_bit(YB_KBD_IS_ON, &data->flags); - set_bit(YB_DIGITIZER_IS_ON, &data->flags); - - r = devm_work_autocancel(&wdev->dev, &data->work, yogabook_wmi_work); - if (r) - return r; - - data->kbd_adev = acpi_dev_get_first_match_dev("GDIX1001", NULL, -1); - if (!data->kbd_adev) { - dev_err(&wdev->dev, "Cannot find the touchpad device in ACPI tables\n"); - return -ENODEV; - } - - data->dig_adev = acpi_dev_get_first_match_dev("WCOM0019", NULL, -1); - if (!data->dig_adev) { - dev_err(&wdev->dev, "Cannot find the digitizer device in ACPI tables\n"); - r = -ENODEV; - goto error_put_devs; - } - - data->kbd_dev = get_device(acpi_get_first_physical_node(data->kbd_adev)); - if (!data->kbd_dev || !data->kbd_dev->driver) { - r = -EPROBE_DEFER; - goto error_put_devs; - } - - data->dig_dev = get_device(acpi_get_first_physical_node(data->dig_adev)); - if (!data->dig_dev || !data->dig_dev->driver) { - r = -EPROBE_DEFER; - goto error_put_devs; - } - - gpiod_add_lookup_table(&yogabook_wmi_gpios); - - r = devm_add_action_or_reset(&wdev->dev, yogabook_wmi_rm_gpio_lookup, NULL); - if (r) - goto error_put_devs; - - data->backside_hall_gpio = - devm_gpiod_get(&wdev->dev, "backside_hall_sw", GPIOD_IN); - if (IS_ERR(data->backside_hall_gpio)) { - r = PTR_ERR(data->backside_hall_gpio); - dev_err_probe(&wdev->dev, r, "Getting backside_hall_sw GPIO\n"); - goto error_put_devs; - } - - r = gpiod_to_irq(data->backside_hall_gpio); - if (r < 0) { - dev_err_probe(&wdev->dev, r, "Getting backside_hall_sw IRQ\n"); - goto error_put_devs; - } - data->backside_hall_irq = r; - - r = devm_request_irq(&wdev->dev, data->backside_hall_irq, - yogabook_backside_hall_irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "backside_hall_sw", data); - if (r) { - dev_err_probe(&wdev->dev, r, "Requesting backside_hall_sw IRQ\n"); - goto error_put_devs; - } - - schedule_work(&data->work); - - data->kbd_bl_led.name = "ybwmi::kbd_backlight"; - data->kbd_bl_led.brightness_set_blocking = kbd_brightness_set; - data->kbd_bl_led.brightness_get = kbd_brightness_get; - data->kbd_bl_led.max_brightness = 255; - - r = devm_led_classdev_register(&wdev->dev, &data->kbd_bl_led); - if (r < 0) { - dev_err_probe(&wdev->dev, r, "Registering backlight LED device\n"); - goto error_put_devs; - } - - return 0; - -error_put_devs: - put_device(data->dig_dev); - put_device(data->kbd_dev); - acpi_dev_put(data->dig_adev); - acpi_dev_put(data->kbd_adev); - return r; -} - -static void yogabook_wmi_remove(struct wmi_device *wdev) -{ - struct yogabook_wmi *data = dev_get_drvdata(&wdev->dev); - - put_device(data->dig_dev); - put_device(data->kbd_dev); - acpi_dev_put(data->dig_adev); - acpi_dev_put(data->kbd_adev); -} - -static int __maybe_unused yogabook_wmi_suspend(struct device *dev) -{ - struct wmi_device *wdev = container_of(dev, struct wmi_device, dev); - struct yogabook_wmi *data = dev_get_drvdata(dev); - - set_bit(YB_SUSPENDED, &data->flags); - - flush_work(&data->work); - - /* Turn off the pen button at sleep */ - if (test_bit(YB_DIGITIZER_IS_ON, &data->flags)) - yogabook_wmi_do_action(wdev, YB_PAD_DISABLE); - - return 0; -} - -static int __maybe_unused yogabook_wmi_resume(struct device *dev) -{ - struct wmi_device *wdev = container_of(dev, struct wmi_device, dev); - struct yogabook_wmi *data = dev_get_drvdata(dev); - - if (test_bit(YB_KBD_IS_ON, &data->flags)) { - /* Ensure keyboard touchpad is on before we call KBLC() */ - acpi_device_set_power(data->kbd_adev, ACPI_STATE_D0); - yogabook_wmi_set_kbd_backlight(wdev, data->brightness); - } - - if (test_bit(YB_DIGITIZER_IS_ON, &data->flags)) - yogabook_wmi_do_action(wdev, YB_PAD_ENABLE); - - clear_bit(YB_SUSPENDED, &data->flags); - - /* Check for YB_TABLET_MODE changes made during suspend */ - schedule_work(&data->work); - - return 0; -} - -static const struct wmi_device_id yogabook_wmi_id_table[] = { - { - .guid_string = YB_MBTN_EVENT_GUID, - }, - { } /* Terminating entry */ -}; - -static SIMPLE_DEV_PM_OPS(yogabook_wmi_pm_ops, - yogabook_wmi_suspend, yogabook_wmi_resume); - -static struct wmi_driver yogabook_wmi_driver = { - .driver = { - .name = "yogabook-wmi", - .pm = &yogabook_wmi_pm_ops, - }, - .no_notify_data = true, - .id_table = yogabook_wmi_id_table, - .probe = yogabook_wmi_probe, - .remove = yogabook_wmi_remove, - .notify = yogabook_wmi_notify, -}; -module_wmi_driver(yogabook_wmi_driver); - -MODULE_DEVICE_TABLE(wmi, yogabook_wmi_id_table); -MODULE_AUTHOR("Yauhen Kharuzhy"); -MODULE_DESCRIPTION("Lenovo Yoga Book WMI driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/platform/x86/lenovo-yogabook.c b/drivers/platform/x86/lenovo-yogabook.c new file mode 100644 index 000000000000..b8d0239192cb --- /dev/null +++ b/drivers/platform/x86/lenovo-yogabook.c @@ -0,0 +1,573 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Platform driver for Lenovo Yoga Book YB1-X90F/L tablets (Android model) + * WMI driver for Lenovo Yoga Book YB1-X91F/L tablets (Windows model) + * + * The keyboard half of the YB1 models can function as both a capacitive + * touch keyboard or as a Wacom digitizer, but not at the same time. + * + * This driver takes care of switching between the 2 functions. + * + * Copyright 2023 Hans de Goede <hansg@kernel.org> + */ + +#include <linux/acpi.h> +#include <linux/gpio/consumer.h> +#include <linux/gpio/machine.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/leds.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/pwm.h> +#include <linux/wmi.h> +#include <linux/workqueue.h> + +#define YB_MBTN_EVENT_GUID "243FEC1D-1963-41C1-8100-06A9D82A94B4" + +#define YB_KBD_BL_DEFAULT 128 +#define YB_KBD_BL_MAX 255 +#define YB_KBD_BL_PWM_PERIOD 13333 + +#define YB_PDEV_NAME "yogabook-touch-kbd-digitizer-switch" + +/* flags */ +enum { + YB_KBD_IS_ON, + YB_DIGITIZER_IS_ON, + YB_DIGITIZER_MODE, + YB_TABLET_MODE, + YB_SUSPENDED, +}; + +struct yogabook_data { + struct device *dev; + struct acpi_device *kbd_adev; + struct acpi_device *dig_adev; + struct device *kbd_dev; + struct device *dig_dev; + struct led_classdev *pen_led; + struct gpio_desc *pen_touch_event; + struct gpio_desc *kbd_bl_led_enable; + struct gpio_desc *backside_hall_gpio; + struct pwm_device *kbd_bl_pwm; + int (*set_kbd_backlight)(struct yogabook_data *data, uint8_t level); + int pen_touch_irq; + int backside_hall_irq; + struct work_struct work; + struct led_classdev kbd_bl_led; + unsigned long flags; + uint8_t brightness; +}; + +static void yogabook_work(struct work_struct *work) +{ + struct yogabook_data *data = container_of(work, struct yogabook_data, work); + bool kbd_on, digitizer_on; + int r; + + if (test_bit(YB_SUSPENDED, &data->flags)) + return; + + if (test_bit(YB_TABLET_MODE, &data->flags)) { + kbd_on = false; + digitizer_on = false; + } else if (test_bit(YB_DIGITIZER_MODE, &data->flags)) { + digitizer_on = true; + kbd_on = false; + } else { + kbd_on = true; + digitizer_on = false; + } + + if (!kbd_on && test_bit(YB_KBD_IS_ON, &data->flags)) { + /* + * Must be done before releasing the keyboard touchscreen driver, + * so that the keyboard touchscreen dev is still in D0. + */ + data->set_kbd_backlight(data, 0); + device_release_driver(data->kbd_dev); + clear_bit(YB_KBD_IS_ON, &data->flags); + } + + if (!digitizer_on && test_bit(YB_DIGITIZER_IS_ON, &data->flags)) { + led_set_brightness(data->pen_led, LED_OFF); + device_release_driver(data->dig_dev); + clear_bit(YB_DIGITIZER_IS_ON, &data->flags); + } + + if (kbd_on && !test_bit(YB_KBD_IS_ON, &data->flags)) { + r = device_reprobe(data->kbd_dev); + if (r) + dev_warn(data->dev, "Reprobe of keyboard touchscreen failed: %d\n", r); + + data->set_kbd_backlight(data, data->brightness); + set_bit(YB_KBD_IS_ON, &data->flags); + } + + if (digitizer_on && !test_bit(YB_DIGITIZER_IS_ON, &data->flags)) { + r = device_reprobe(data->dig_dev); + if (r) + dev_warn(data->dev, "Reprobe of digitizer failed: %d\n", r); + + led_set_brightness(data->pen_led, LED_FULL); + set_bit(YB_DIGITIZER_IS_ON, &data->flags); + } +} + +static void yogabook_toggle_digitizer_mode(struct yogabook_data *data) +{ + if (test_bit(YB_SUSPENDED, &data->flags)) + return; + + if (test_bit(YB_DIGITIZER_MODE, &data->flags)) + clear_bit(YB_DIGITIZER_MODE, &data->flags); + else + set_bit(YB_DIGITIZER_MODE, &data->flags); + + /* + * We are called from the ACPI core and the driver [un]binding which is + * done also needs ACPI functions, use a workqueue to avoid deadlocking. + */ + schedule_work(&data->work); +} + +static irqreturn_t yogabook_backside_hall_irq(int irq, void *_data) +{ + struct yogabook_data *data = _data; + + if (gpiod_get_value(data->backside_hall_gpio)) + set_bit(YB_TABLET_MODE, &data->flags); + else + clear_bit(YB_TABLET_MODE, &data->flags); + + schedule_work(&data->work); + + return IRQ_HANDLED; +} + +#define kbd_led_to_yogabook(cdev) container_of(cdev, struct yogabook_data, kbd_bl_led) + +static enum led_brightness kbd_brightness_get(struct led_classdev *cdev) +{ + struct yogabook_data *data = kbd_led_to_yogabook(cdev); + + return data->brightness; +} + +static int kbd_brightness_set(struct led_classdev *cdev, + enum led_brightness value) +{ + struct yogabook_data *data = kbd_led_to_yogabook(cdev); + + if ((value < 0) || (value > YB_KBD_BL_MAX)) + return -EINVAL; + + data->brightness = value; + + if (!test_bit(YB_KBD_IS_ON, &data->flags)) + return 0; + + return data->set_kbd_backlight(data, data->brightness); +} + +static struct gpiod_lookup_table yogabook_gpios = { + .table = { + GPIO_LOOKUP("INT33FF:02", 18, "backside_hall_sw", GPIO_ACTIVE_LOW), + {} + }, +}; + +static struct led_lookup_data yogabook_pen_led = { + .provider = "platform::indicator", + .con_id = "pen-icon-led", +}; + +static int yogabook_probe(struct device *dev, struct yogabook_data *data, + const char *kbd_bl_led_name) +{ + int r; + + data->dev = dev; + data->brightness = YB_KBD_BL_DEFAULT; + set_bit(YB_KBD_IS_ON, &data->flags); + set_bit(YB_DIGITIZER_IS_ON, &data->flags); + INIT_WORK(&data->work, yogabook_work); + + yogabook_pen_led.dev_id = dev_name(dev); + led_add_lookup(&yogabook_pen_led); + data->pen_led = devm_led_get(dev, "pen-icon-led"); + led_remove_lookup(&yogabook_pen_led); + + if (IS_ERR(data->pen_led)) + return dev_err_probe(dev, PTR_ERR(data->pen_led), "Getting pen icon LED\n"); + + yogabook_gpios.dev_id = dev_name(dev); + gpiod_add_lookup_table(&yogabook_gpios); + data->backside_hall_gpio = devm_gpiod_get(dev, "backside_hall_sw", GPIOD_IN); + gpiod_remove_lookup_table(&yogabook_gpios); + + if (IS_ERR(data->backside_hall_gpio)) + return dev_err_probe(dev, PTR_ERR(data->backside_hall_gpio), + "Getting backside_hall_sw GPIO\n"); + + r = gpiod_to_irq(data->backside_hall_gpio); + if (r < 0) + return dev_err_probe(dev, r, "Getting backside_hall_sw IRQ\n"); + + data->backside_hall_irq = r; + + /* Set default brightness before enabling the IRQ */ + data->set_kbd_backlight(data, YB_KBD_BL_DEFAULT); + + r = request_irq(data->backside_hall_irq, yogabook_backside_hall_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + "backside_hall_sw", data); + if (r) + return dev_err_probe(dev, r, "Requesting backside_hall_sw IRQ\n"); + + schedule_work(&data->work); + + data->kbd_bl_led.name = kbd_bl_led_name; + data->kbd_bl_led.brightness_set_blocking = kbd_brightness_set; + data->kbd_bl_led.brightness_get = kbd_brightness_get; + data->kbd_bl_led.max_brightness = YB_KBD_BL_MAX; + + r = devm_led_classdev_register(dev, &data->kbd_bl_led); + if (r < 0) { + dev_err_probe(dev, r, "Registering backlight LED device\n"); + goto error_free_irq; + } + + dev_set_drvdata(dev, data); + return 0; + +error_free_irq: + free_irq(data->backside_hall_irq, data); + cancel_work_sync(&data->work); + return r; +} + +static void yogabook_remove(struct yogabook_data *data) +{ + int r = 0; + + free_irq(data->backside_hall_irq, data); + cancel_work_sync(&data->work); + + if (!test_bit(YB_KBD_IS_ON, &data->flags)) + r |= device_reprobe(data->kbd_dev); + + if (!test_bit(YB_DIGITIZER_IS_ON, &data->flags)) + r |= device_reprobe(data->dig_dev); + + if (r) + dev_warn(data->dev, "Reprobe of devices failed\n"); +} + +static int yogabook_suspend(struct device *dev) +{ + struct yogabook_data *data = dev_get_drvdata(dev); + + set_bit(YB_SUSPENDED, &data->flags); + flush_work(&data->work); + + if (test_bit(YB_KBD_IS_ON, &data->flags)) + data->set_kbd_backlight(data, 0); + + return 0; +} + +static int yogabook_resume(struct device *dev) +{ + struct yogabook_data *data = dev_get_drvdata(dev); + + if (test_bit(YB_KBD_IS_ON, &data->flags)) + data->set_kbd_backlight(data, data->brightness); + + clear_bit(YB_SUSPENDED, &data->flags); + + /* Check for YB_TABLET_MODE changes made during suspend */ + schedule_work(&data->work); + + return 0; +} + +static DEFINE_SIMPLE_DEV_PM_OPS(yogabook_pm_ops, yogabook_suspend, yogabook_resume); + +/********** WMI driver code **********/ + +/* + * To control keyboard backlight, call the method KBLC() of the TCS1 ACPI + * device (Goodix touchpad acts as virtual sensor keyboard). + */ +static int yogabook_wmi_set_kbd_backlight(struct yogabook_data *data, + uint8_t level) +{ + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_object_list input; + union acpi_object param; + acpi_status status; + + dev_dbg(data->dev, "Set KBLC level to %u\n", level); + + /* Ensure keyboard touchpad is on before we call KBLC() */ + acpi_device_set_power(data->kbd_adev, ACPI_STATE_D0); + + input.count = 1; + input.pointer = ¶m; + + param.type = ACPI_TYPE_INTEGER; + param.integer.value = YB_KBD_BL_MAX - level; + + status = acpi_evaluate_object(acpi_device_handle(data->kbd_adev), "KBLC", + &input, &output); + if (ACPI_FAILURE(status)) { + dev_err(data->dev, "Failed to call KBLC method: 0x%x\n", status); + return status; + } + + kfree(output.pointer); + return 0; +} + +static int yogabook_wmi_probe(struct wmi_device *wdev, const void *context) +{ + struct device *dev = &wdev->dev; + struct yogabook_data *data; + int r; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + data->kbd_adev = acpi_dev_get_first_match_dev("GDIX1001", NULL, -1); + if (!data->kbd_adev) + return dev_err_probe(dev, -ENODEV, "Cannot find the touchpad device in ACPI tables\n"); + + data->dig_adev = acpi_dev_get_first_match_dev("WCOM0019", NULL, -1); + if (!data->dig_adev) { + r = dev_err_probe(dev, -ENODEV, "Cannot find the digitizer device in ACPI tables\n"); + goto error_put_devs; + } + + data->kbd_dev = get_device(acpi_get_first_physical_node(data->kbd_adev)); + if (!data->kbd_dev || !data->kbd_dev->driver) { + r = -EPROBE_DEFER; + goto error_put_devs; + } + + data->dig_dev = get_device(acpi_get_first_physical_node(data->dig_adev)); + if (!data->dig_dev || !data->dig_dev->driver) { + r = -EPROBE_DEFER; + goto error_put_devs; + } + + data->set_kbd_backlight = yogabook_wmi_set_kbd_backlight; + + r = yogabook_probe(dev, data, "ybwmi::kbd_backlight"); + if (r) + goto error_put_devs; + + return 0; + +error_put_devs: + put_device(data->dig_dev); + put_device(data->kbd_dev); + acpi_dev_put(data->dig_adev); + acpi_dev_put(data->kbd_adev); + return r; +} + +static void yogabook_wmi_remove(struct wmi_device *wdev) +{ + struct yogabook_data *data = dev_get_drvdata(&wdev->dev); + + yogabook_remove(data); + + put_device(data->dig_dev); + put_device(data->kbd_dev); + acpi_dev_put(data->dig_adev); + acpi_dev_put(data->kbd_adev); +} + +static void yogabook_wmi_notify(struct wmi_device *wdev, union acpi_object *dummy) +{ + yogabook_toggle_digitizer_mode(dev_get_drvdata(&wdev->dev)); +} + +static const struct wmi_device_id yogabook_wmi_id_table[] = { + { + .guid_string = YB_MBTN_EVENT_GUID, + }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(wmi, yogabook_wmi_id_table); + +static struct wmi_driver yogabook_wmi_driver = { + .driver = { + .name = "yogabook-wmi", + .pm = pm_sleep_ptr(&yogabook_pm_ops), + }, + .no_notify_data = true, + .id_table = yogabook_wmi_id_table, + .probe = yogabook_wmi_probe, + .remove = yogabook_wmi_remove, + .notify = yogabook_wmi_notify, +}; + +/********** platform driver code **********/ + +static struct gpiod_lookup_table yogabook_pdev_gpios = { + .dev_id = YB_PDEV_NAME, + .table = { + GPIO_LOOKUP("INT33FF:00", 95, "pen_touch_event", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("INT33FF:03", 52, "enable_keyboard_led", GPIO_ACTIVE_HIGH), + {} + }, +}; + +static int yogabook_pdev_set_kbd_backlight(struct yogabook_data *data, u8 level) +{ + struct pwm_state state = { + .period = YB_KBD_BL_PWM_PERIOD, + .duty_cycle = YB_KBD_BL_PWM_PERIOD * level / YB_KBD_BL_MAX, + .enabled = level, + }; + + pwm_apply_state(data->kbd_bl_pwm, &state); + gpiod_set_value(data->kbd_bl_led_enable, level ? 1 : 0); + return 0; +} + +static irqreturn_t yogabook_pen_touch_irq(int irq, void *data) +{ + yogabook_toggle_digitizer_mode(data); + return IRQ_HANDLED; +} + +static int yogabook_pdev_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct yogabook_data *data; + int r; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + data->kbd_dev = bus_find_device_by_name(&i2c_bus_type, NULL, "i2c-goodix_ts"); + if (!data->kbd_dev || !data->kbd_dev->driver) { + r = -EPROBE_DEFER; + goto error_put_devs; + } + + data->dig_dev = bus_find_device_by_name(&i2c_bus_type, NULL, "i2c-wacom"); + if (!data->dig_dev || !data->dig_dev->driver) { + r = -EPROBE_DEFER; + goto error_put_devs; + } + + gpiod_add_lookup_table(&yogabook_pdev_gpios); + data->pen_touch_event = devm_gpiod_get(dev, "pen_touch_event", GPIOD_IN); + data->kbd_bl_led_enable = devm_gpiod_get(dev, "enable_keyboard_led", GPIOD_OUT_HIGH); + gpiod_remove_lookup_table(&yogabook_pdev_gpios); + + if (IS_ERR(data->pen_touch_event)) { + r = dev_err_probe(dev, PTR_ERR(data->pen_touch_event), + "Getting pen_touch_event GPIO\n"); + goto error_put_devs; + } + + if (IS_ERR(data->kbd_bl_led_enable)) { + r = dev_err_probe(dev, PTR_ERR(data->kbd_bl_led_enable), + "Getting enable_keyboard_led GPIO\n"); + goto error_put_devs; + } + + data->kbd_bl_pwm = devm_pwm_get(dev, "pwm_soc_lpss_2"); + if (IS_ERR(data->kbd_bl_pwm)) { + r = dev_err_probe(dev, PTR_ERR(data->kbd_bl_pwm), + "Getting keyboard backlight PWM\n"); + goto error_put_devs; + } + + r = gpiod_to_irq(data->pen_touch_event); + if (r < 0) { + dev_err_probe(dev, r, "Getting pen_touch_event IRQ\n"); + goto error_put_devs; + } + data->pen_touch_irq = r; + + r = request_irq(data->pen_touch_irq, yogabook_pen_touch_irq, IRQF_TRIGGER_FALLING, + "pen_touch_event", data); + if (r) { + dev_err_probe(dev, r, "Requesting pen_touch_event IRQ\n"); + goto error_put_devs; + } + + data->set_kbd_backlight = yogabook_pdev_set_kbd_backlight; + + r = yogabook_probe(dev, data, "yogabook::kbd_backlight"); + if (r) + goto error_free_irq; + + return 0; + +error_free_irq: + free_irq(data->pen_touch_irq, data); + cancel_work_sync(&data->work); +error_put_devs: + put_device(data->dig_dev); + put_device(data->kbd_dev); + return r; +} + +static void yogabook_pdev_remove(struct platform_device *pdev) +{ + struct yogabook_data *data = platform_get_drvdata(pdev); + + yogabook_remove(data); + free_irq(data->pen_touch_irq, data); + cancel_work_sync(&data->work); + put_device(data->dig_dev); + put_device(data->kbd_dev); +} + +static struct platform_driver yogabook_pdev_driver = { + .probe = yogabook_pdev_probe, + .remove_new = yogabook_pdev_remove, + .driver = { + .name = YB_PDEV_NAME, + .pm = pm_sleep_ptr(&yogabook_pm_ops), + }, +}; + +static int __init yogabook_module_init(void) +{ + int r; + + r = wmi_driver_register(&yogabook_wmi_driver); + if (r) + return r; + + r = platform_driver_register(&yogabook_pdev_driver); + if (r) + wmi_driver_unregister(&yogabook_wmi_driver); + + return r; +} + +static void __exit yogabook_module_exit(void) +{ + platform_driver_unregister(&yogabook_pdev_driver); + wmi_driver_unregister(&yogabook_wmi_driver); +} + +module_init(yogabook_module_init); +module_exit(yogabook_module_exit); + +MODULE_ALIAS("platform:" YB_PDEV_NAME); +MODULE_AUTHOR("Yauhen Kharuzhy"); +MODULE_DESCRIPTION("Lenovo Yoga Book driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/platform/x86/system76_acpi.c b/drivers/platform/x86/system76_acpi.c index 97f5a8255b91..fc4708fa6ebe 100644 --- a/drivers/platform/x86/system76_acpi.c +++ b/drivers/platform/x86/system76_acpi.c @@ -581,7 +581,7 @@ static const struct hwmon_ops thermal_ops = { }; // Allocate up to 8 fans and temperatures -static const struct hwmon_channel_info *thermal_channel_info[] = { +static const struct hwmon_channel_info * const thermal_channel_info[] = { HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT | HWMON_F_LABEL, HWMON_F_INPUT | HWMON_F_LABEL, diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c index 1138f770149d..52d1ce8dfe44 100644 --- a/drivers/platform/x86/think-lmi.c +++ b/drivers/platform/x86/think-lmi.c @@ -14,6 +14,7 @@ #include <linux/acpi.h> #include <linux/errno.h> #include <linux/fs.h> +#include <linux/mutex.h> #include <linux/string.h> #include <linux/types.h> #include <linux/dmi.h> @@ -168,11 +169,11 @@ MODULE_PARM_DESC(debug_support, "Enable debug command support"); */ #define LENOVO_CERT_THUMBPRINT_GUID "C59119ED-1C0D-4806-A8E9-59AA318176C4" -#define TLMI_POP_PWD (1 << 0) -#define TLMI_PAP_PWD (1 << 1) -#define TLMI_HDD_PWD (1 << 2) -#define TLMI_SYS_PWD (1 << 3) -#define TLMI_CERT (1 << 7) +#define TLMI_POP_PWD BIT(0) /* Supervisor */ +#define TLMI_PAP_PWD BIT(1) /* Power-on */ +#define TLMI_HDD_PWD BIT(2) /* HDD/NVME */ +#define TLMI_SMP_PWD BIT(6) /* System Management */ +#define TLMI_CERT BIT(7) /* Certificate Based */ #define to_tlmi_pwd_setting(kobj) container_of(kobj, struct tlmi_pwd_setting, kobj) #define to_tlmi_attr_setting(kobj) container_of(kobj, struct tlmi_attr_setting, kobj) @@ -195,6 +196,7 @@ static const char * const level_options[] = { }; static struct think_lmi tlmi_priv; static struct class *fw_attr_class; +static DEFINE_MUTEX(tlmi_mutex); /* ------ Utility functions ------------*/ /* Strip out CR if one is present */ @@ -437,6 +439,9 @@ static ssize_t new_password_store(struct kobject *kobj, /* Strip out CR if one is present, setting password won't work if it is present */ strip_cr(new_pwd); + /* Use lock in case multiple WMI operations needed */ + mutex_lock(&tlmi_mutex); + pwdlen = strlen(new_pwd); /* pwdlen == 0 is allowed to clear the password */ if (pwdlen && ((pwdlen < setting->minlen) || (pwdlen > setting->maxlen))) { @@ -456,9 +461,9 @@ static ssize_t new_password_store(struct kobject *kobj, sprintf(pwd_type, "mhdp%d", setting->index); } else if (setting == tlmi_priv.pwd_nvme) { if (setting->level == TLMI_LEVEL_USER) - sprintf(pwd_type, "unvp%d", setting->index); + sprintf(pwd_type, "udrp%d", setting->index); else - sprintf(pwd_type, "mnvp%d", setting->index); + sprintf(pwd_type, "adrp%d", setting->index); } else { sprintf(pwd_type, "%s", setting->pwd_type); } @@ -493,6 +498,7 @@ static ssize_t new_password_store(struct kobject *kobj, kfree(auth_str); } out: + mutex_unlock(&tlmi_mutex); kfree(new_pwd); return ret ?: count; } @@ -879,6 +885,11 @@ static umode_t auth_attr_is_visible(struct kobject *kobj, return 0; } + /* Don't display un-needed settings if opcode available */ + if ((attr == &auth_encoding.attr || attr == &auth_kbdlang.attr) && + tlmi_priv.opcode_support) + return 0; + return attr->mode; } @@ -981,6 +992,9 @@ static ssize_t current_value_store(struct kobject *kobj, /* Strip out CR if one is present */ strip_cr(new_setting); + /* Use lock in case multiple WMI operations needed */ + mutex_lock(&tlmi_mutex); + /* Check if certificate authentication is enabled and active */ if (tlmi_priv.certificate_support && tlmi_priv.pwd_admin->cert_installed) { if (!tlmi_priv.pwd_admin->signature || !tlmi_priv.pwd_admin->save_signature) { @@ -1001,7 +1015,33 @@ static ssize_t current_value_store(struct kobject *kobj, tlmi_priv.pwd_admin->save_signature); if (ret) goto out; - } else { /* Non certiifcate based authentication */ + } else if (tlmi_priv.opcode_support) { + /* + * If opcode support is present use that interface. + * Note - this sets the variable and then the password as separate + * WMI calls. Function tlmi_save_bios_settings will error if the + * password is incorrect. + */ + set_str = kasprintf(GFP_KERNEL, "%s,%s;", setting->display_name, + new_setting); + if (!set_str) { + ret = -ENOMEM; + goto out; + } + + ret = tlmi_simple_call(LENOVO_SET_BIOS_SETTINGS_GUID, set_str); + if (ret) + goto out; + + if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) { + ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin", + tlmi_priv.pwd_admin->password); + if (ret) + goto out; + } + + ret = tlmi_save_bios_settings(""); + } else { /* old non-opcode based authentication method (deprecated) */ if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) { auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;", tlmi_priv.pwd_admin->password, @@ -1039,6 +1079,7 @@ static ssize_t current_value_store(struct kobject *kobj, kobject_uevent(&tlmi_priv.class_dev->kobj, KOBJ_CHANGE); } out: + mutex_unlock(&tlmi_mutex); kfree(auth_str); kfree(set_str); kfree(new_setting); @@ -1483,11 +1524,11 @@ static int tlmi_analyze(void) tlmi_priv.pwd_power->valid = true; if (tlmi_priv.opcode_support) { - tlmi_priv.pwd_system = tlmi_create_auth("sys", "system"); + tlmi_priv.pwd_system = tlmi_create_auth("smp", "system"); if (!tlmi_priv.pwd_system) goto fail_clear_attr; - if (tlmi_priv.pwdcfg.core.password_state & TLMI_SYS_PWD) + if (tlmi_priv.pwdcfg.core.password_state & TLMI_SMP_PWD) tlmi_priv.pwd_system->valid = true; tlmi_priv.pwd_hdd = tlmi_create_auth("hdd", "hdd"); @@ -1498,6 +1539,10 @@ static int tlmi_analyze(void) if (!tlmi_priv.pwd_nvme) goto fail_clear_attr; + /* Set default hdd/nvme index to 1 as there is no device 0 */ + tlmi_priv.pwd_hdd->index = 1; + tlmi_priv.pwd_nvme->index = 1; + if (tlmi_priv.pwdcfg.core.password_state & TLMI_HDD_PWD) { /* Check if PWD is configured and set index to first drive found */ if (tlmi_priv.pwdcfg.ext.hdd_user_password || diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index b3808ad77278..187018ffb068 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -10524,8 +10524,8 @@ unlock: static void dytc_profile_refresh(void) { enum platform_profile_option profile; - int output, err = 0; - int perfmode, funcmode; + int output = 0, err = 0; + int perfmode, funcmode = 0; mutex_lock(&dytc_mutex); if (dytc_capabilities & BIT(DYTC_FC_MMC)) { @@ -10538,6 +10538,8 @@ static void dytc_profile_refresh(void) err = dytc_command(DYTC_CMD_GET, &output); /* Check if we are PSC mode, or have AMT enabled */ funcmode = (output >> DYTC_GET_FUNCTION_BIT) & 0xF; + } else { /* Unknown profile mode */ + err = -ENODEV; } mutex_unlock(&dytc_mutex); if (err) diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index b34984bbee33..291f14ef6702 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -3037,7 +3037,7 @@ static int toshiba_acpi_hwmon_read(struct device *dev, enum hwmon_sensor_types t return -EOPNOTSUPP; } -static const struct hwmon_channel_info *toshiba_acpi_hwmon_info[] = { +static const struct hwmon_channel_info * const toshiba_acpi_hwmon_info[] = { HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT), NULL }; diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index d81319a502ef..5b95d7aa5c2f 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -248,7 +248,9 @@ static acpi_status get_event_data(const struct wmi_block *wblock, struct acpi_bu * @wdev: A wmi bus device from a driver * @length: Required buffer size * - * Allocates memory needed for buffer, stores the buffer size in that memory + * Allocates memory needed for buffer, stores the buffer size in that memory. + * + * Return: 0 on success or a negative error code for failure. */ int set_required_buffer_size(struct wmi_device *wdev, u64 length) { @@ -262,14 +264,57 @@ int set_required_buffer_size(struct wmi_device *wdev, u64 length) EXPORT_SYMBOL_GPL(set_required_buffer_size); /** - * wmi_evaluate_method - Evaluate a WMI method + * wmi_instance_count - Get number of WMI object instances + * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba + * + * Get the number of WMI object instances. + * + * Returns: Number of WMI object instances or negative error code. + */ +int wmi_instance_count(const char *guid_string) +{ + struct wmi_block *wblock; + acpi_status status; + + status = find_guid(guid_string, &wblock); + if (ACPI_FAILURE(status)) { + if (status == AE_BAD_PARAMETER) + return -EINVAL; + + return -ENODEV; + } + + return wmidev_instance_count(&wblock->dev); +} +EXPORT_SYMBOL_GPL(wmi_instance_count); + +/** + * wmidev_instance_count - Get number of WMI object instances + * @wdev: A wmi bus device from a driver + * + * Get the number of WMI object instances. + * + * Returns: Number of WMI object instances. + */ +u8 wmidev_instance_count(struct wmi_device *wdev) +{ + struct wmi_block *wblock = container_of(wdev, struct wmi_block, dev); + + return wblock->gblock.instance_count; +} +EXPORT_SYMBOL_GPL(wmidev_instance_count); + +/** + * wmi_evaluate_method - Evaluate a WMI method (deprecated) * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba * @instance: Instance index * @method_id: Method ID to call * @in: Buffer containing input for the method call * @out: Empty buffer to return the method results * - * Call an ACPI-WMI method + * Call an ACPI-WMI method, the caller must free @out. + * + * Return: acpi_status signaling success or error. */ acpi_status wmi_evaluate_method(const char *guid_string, u8 instance, u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out) @@ -294,7 +339,9 @@ EXPORT_SYMBOL_GPL(wmi_evaluate_method); * @in: Buffer containing input for the method call * @out: Empty buffer to return the method results * - * Call an ACPI-WMI method + * Call an ACPI-WMI method, the caller must free @out. + * + * Return: acpi_status signaling success or error. */ acpi_status wmidev_evaluate_method(struct wmi_device *wdev, u8 instance, u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out) @@ -411,7 +458,9 @@ static acpi_status __query_block(struct wmi_block *wblock, u8 instance, * @instance: Instance index * @out: Empty buffer to return the contents of the data block to * - * Return the contents of an ACPI-WMI data block to a buffer + * Query a ACPI-WMI block, the caller must free @out. + * + * Return: ACPI object containing the content of the WMI block. */ acpi_status wmi_query_block(const char *guid_string, u8 instance, struct acpi_buffer *out) @@ -427,6 +476,15 @@ acpi_status wmi_query_block(const char *guid_string, u8 instance, } EXPORT_SYMBOL_GPL(wmi_query_block); +/** + * wmidev_block_query - Return contents of a WMI block + * @wdev: A wmi bus device from a driver + * @instance: Instance index + * + * Query an ACPI-WMI block, the caller must free the result. + * + * Return: ACPI object containing the content of the WMI block. + */ union acpi_object *wmidev_block_query(struct wmi_device *wdev, u8 instance) { struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -440,12 +498,14 @@ union acpi_object *wmidev_block_query(struct wmi_device *wdev, u8 instance) EXPORT_SYMBOL_GPL(wmidev_block_query); /** - * wmi_set_block - Write to a WMI block + * wmi_set_block - Write to a WMI block (deprecated) * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba * @instance: Instance index * @in: Buffer containing new values for the data block * - * Write the contents of the input buffer to an ACPI-WMI data block + * Write the contents of the input buffer to an ACPI-WMI data block. + * + * Return: acpi_status signaling success or error. */ acpi_status wmi_set_block(const char *guid_string, u8 instance, const struct acpi_buffer *in) @@ -549,12 +609,14 @@ static void wmi_notify_debug(u32 value, void *context) } /** - * wmi_install_notify_handler - Register handler for WMI events + * wmi_install_notify_handler - Register handler for WMI events (deprecated) * @guid: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba * @handler: Function to handle notifications * @data: Data to be returned to handler when event is fired * * Register a handler for events sent to the ACPI-WMI mapper device. + * + * Return: acpi_status signaling success or error. */ acpi_status wmi_install_notify_handler(const char *guid, wmi_notify_handler handler, @@ -593,10 +655,12 @@ acpi_status wmi_install_notify_handler(const char *guid, EXPORT_SYMBOL_GPL(wmi_install_notify_handler); /** - * wmi_remove_notify_handler - Unregister handler for WMI events + * wmi_remove_notify_handler - Unregister handler for WMI events (deprecated) * @guid: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba * * Unregister handler for events sent to the ACPI-WMI mapper device. + * + * Return: acpi_status signaling success or error. */ acpi_status wmi_remove_notify_handler(const char *guid) { @@ -638,12 +702,14 @@ acpi_status wmi_remove_notify_handler(const char *guid) EXPORT_SYMBOL_GPL(wmi_remove_notify_handler); /** - * wmi_get_event_data - Get WMI data associated with an event + * wmi_get_event_data - Get WMI data associated with an event (deprecated) * * @event: Event to find - * @out: Buffer to hold event data. out->pointer should be freed with kfree() + * @out: Buffer to hold event data * - * Returns extra data associated with an event in WMI. + * Get extra data associated with an WMI event, the caller needs to free @out. + * + * Return: acpi_status signaling success or error. */ acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out) { @@ -664,7 +730,9 @@ EXPORT_SYMBOL_GPL(wmi_get_event_data); * wmi_has_guid - Check if a GUID is available * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba * - * Check if a given GUID is defined by _WDG + * Check if a given GUID is defined by _WDG. + * + * Return: True if GUID is available, false otherwise. */ bool wmi_has_guid(const char *guid_string) { @@ -673,12 +741,12 @@ bool wmi_has_guid(const char *guid_string) EXPORT_SYMBOL_GPL(wmi_has_guid); /** - * wmi_get_acpi_device_uid() - Get _UID name of ACPI device that defines GUID + * wmi_get_acpi_device_uid() - Get _UID name of ACPI device that defines GUID (deprecated) * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba * * Find the _UID of ACPI device associated with this WMI GUID. * - * Return: The ACPI _UID field value or NULL if the WMI GUID was not found + * Return: The ACPI _UID field value or NULL if the WMI GUID was not found. */ char *wmi_get_acpi_device_uid(const char *guid_string) { @@ -1454,6 +1522,12 @@ int __must_check __wmi_driver_register(struct wmi_driver *driver, } EXPORT_SYMBOL(__wmi_driver_register); +/** + * wmi_driver_unregister() - Unregister a WMI driver + * @driver: WMI driver to unregister + * + * Unregisters a WMI driver from the WMI bus. + */ void wmi_driver_unregister(struct wmi_driver *driver) { driver_unregister(&driver->driver); diff --git a/drivers/platform/x86/x86-android-tablets/asus.c b/drivers/platform/x86/x86-android-tablets/asus.c index cfa038b44b43..f9c4083be86d 100644 --- a/drivers/platform/x86/x86-android-tablets/asus.c +++ b/drivers/platform/x86/x86-android-tablets/asus.c @@ -24,7 +24,7 @@ static struct gpiod_lookup_table int3496_gpo2_pin22_gpios = { }, }; -static struct x86_gpio_button asus_me176c_tf103c_lid = { +static const struct x86_gpio_button asus_me176c_tf103c_lid __initconst = { .button = { .code = SW_LID, .active_low = true, @@ -175,10 +175,10 @@ const struct x86_dev_info asus_me176c_info __initconst = { .serdev_info = asus_me176c_serdevs, .serdev_count = ARRAY_SIZE(asus_me176c_serdevs), .gpio_button = &asus_me176c_tf103c_lid, + .gpio_button_count = 1, .gpiod_lookup_tables = asus_me176c_gpios, .bat_swnode = &generic_lipo_hv_4v35_battery_node, .modules = bq24190_modules, - .invalid_aei_gpiochip = "INT33FC:02", }; /* Asus TF103C tablets have an Android factory img with everything hardcoded */ @@ -318,8 +318,8 @@ const struct x86_dev_info asus_tf103c_info __initconst = { .pdev_info = int3496_pdevs, .pdev_count = 1, .gpio_button = &asus_me176c_tf103c_lid, + .gpio_button_count = 1, .gpiod_lookup_tables = asus_tf103c_gpios, .bat_swnode = &asus_tf103c_battery_node, .modules = bq24190_modules, - .invalid_aei_gpiochip = "INT33FC:02", }; diff --git a/drivers/platform/x86/x86-android-tablets/core.c b/drivers/platform/x86/x86-android-tablets/core.c index 245167674aa2..2fd6060a31bb 100644 --- a/drivers/platform/x86/x86-android-tablets/core.c +++ b/drivers/platform/x86/x86-android-tablets/core.c @@ -124,6 +124,7 @@ static int serdev_count; static struct i2c_client **i2c_clients; static struct platform_device **pdevs; static struct serdev_device **serdevs; +static struct gpio_keys_button *buttons; static struct gpiod_lookup_table * const *gpiod_lookup_tables; static const struct software_node *bat_swnode; static void (*exit_handler)(void); @@ -238,6 +239,7 @@ static void x86_android_tablet_cleanup(void) platform_device_unregister(pdevs[i]); kfree(pdevs); + kfree(buttons); for (i = 0; i < i2c_client_count; i++) i2c_unregister_device(i2c_clients[i]); @@ -353,22 +355,30 @@ static __init int x86_android_tablet_init(void) } } - if (dev_info->gpio_button) { - struct gpio_keys_platform_data pdata = { - .buttons = &dev_info->gpio_button->button, - .nbuttons = 1, - }; + if (dev_info->gpio_button_count) { + struct gpio_keys_platform_data pdata = { }; struct gpio_desc *gpiod; - /* Get GPIO for the gpio-button */ - ret = x86_android_tablet_get_gpiod(dev_info->gpio_button->chip, - dev_info->gpio_button->pin, &gpiod); - if (ret < 0) { + buttons = kcalloc(dev_info->gpio_button_count, sizeof(*buttons), GFP_KERNEL); + if (!buttons) { x86_android_tablet_cleanup(); - return ret; + return -ENOMEM; + } + + for (i = 0; i < dev_info->gpio_button_count; i++) { + ret = x86_android_tablet_get_gpiod(dev_info->gpio_button[i].chip, + dev_info->gpio_button[i].pin, &gpiod); + if (ret < 0) { + x86_android_tablet_cleanup(); + return ret; + } + + buttons[i] = dev_info->gpio_button[i].button; + buttons[i].gpio = desc_to_gpio(gpiod); } - dev_info->gpio_button->button.gpio = desc_to_gpio(gpiod); + pdata.buttons = buttons; + pdata.nbuttons = dev_info->gpio_button_count; pdevs[pdev_count] = platform_device_register_data(NULL, "gpio-keys", PLATFORM_DEVID_AUTO, diff --git a/drivers/platform/x86/x86-android-tablets/dmi.c b/drivers/platform/x86/x86-android-tablets/dmi.c index 23e640b7003d..5d6c12494f08 100644 --- a/drivers/platform/x86/x86-android-tablets/dmi.c +++ b/drivers/platform/x86/x86-android-tablets/dmi.c @@ -59,6 +59,17 @@ const struct dmi_system_id x86_android_tablet_ids[] __initconst = { .driver_data = (void *)&chuwi_hi8_info, }, { + /* Cyberbook T116 Android version */ + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Default string"), + DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), + /* Above strings are much too generic, also match on SKU + BIOS date */ + DMI_MATCH(DMI_PRODUCT_SKU, "20170531"), + DMI_MATCH(DMI_BIOS_DATE, "07/12/2017"), + }, + .driver_data = (void *)&cyberbook_t116_info, + }, + { /* CZC P10T */ .ident = "CZC ODEON TPC-10 (\"P10T\")", .matches = { @@ -127,7 +138,7 @@ const struct dmi_system_id x86_android_tablet_ids[] __initconst = { .driver_data = (void *)&medion_lifetab_s10346_info, }, { - /* Nextbook Ares 8 */ + /* Nextbook Ares 8 (BYT version) */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), DMI_MATCH(DMI_PRODUCT_NAME, "M890BAP"), @@ -135,6 +146,15 @@ const struct dmi_system_id x86_android_tablet_ids[] __initconst = { .driver_data = (void *)&nextbook_ares8_info, }, { + /* Nextbook Ares 8A (CHT version)*/ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), + DMI_MATCH(DMI_PRODUCT_NAME, "CherryTrail"), + DMI_MATCH(DMI_BIOS_VERSION, "M882"), + }, + .driver_data = (void *)&nextbook_ares8a_info, + }, + { /* Peaq C1010 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "PEAQ"), diff --git a/drivers/platform/x86/x86-android-tablets/lenovo.c b/drivers/platform/x86/x86-android-tablets/lenovo.c index 65cfccaa2894..26a4ef670ad7 100644 --- a/drivers/platform/x86/x86-android-tablets/lenovo.c +++ b/drivers/platform/x86/x86-android-tablets/lenovo.c @@ -147,6 +147,32 @@ static const struct platform_device_info lenovo_yb1_x90_pdevs[] __initconst = { }, }; +/* + * DSDT says UART path is "\\_SB.PCIO.URT1" with a letter 'O' instead of + * the number '0' add the link manually. + */ +static const struct x86_serdev_info lenovo_yb1_x90_serdevs[] __initconst = { + { + .ctrl_hid = "8086228A", + .ctrl_uid = "1", + .ctrl_devname = "serial0", + .serdev_hid = "BCM2E1A", + }, +}; + +static const struct x86_gpio_button lenovo_yb1_x90_lid __initconst = { + .button = { + .code = SW_LID, + .active_low = true, + .desc = "lid_sw", + .type = EV_SW, + .wakeup = true, + .debounce_interval = 50, + }, + .chip = "INT33FF:02", + .pin = 19, +}; + static struct gpiod_lookup_table lenovo_yb1_x90_goodix_gpios = { .dev_id = "i2c-goodix_ts", .table = { @@ -203,6 +229,10 @@ const struct x86_dev_info lenovo_yogabook_x90_info __initconst = { .i2c_client_count = ARRAY_SIZE(lenovo_yb1_x90_i2c_clients), .pdev_info = lenovo_yb1_x90_pdevs, .pdev_count = ARRAY_SIZE(lenovo_yb1_x90_pdevs), + .serdev_info = lenovo_yb1_x90_serdevs, + .serdev_count = ARRAY_SIZE(lenovo_yb1_x90_serdevs), + .gpio_button = &lenovo_yb1_x90_lid, + .gpio_button_count = 1, .gpiod_lookup_tables = lenovo_yb1_x90_gpios, .init = lenovo_yb1_x90_init, }; @@ -239,7 +269,7 @@ static const struct software_node lenovo_yoga_tab2_830_1050_bq24190_node = { .properties = lenovo_yoga_tab2_830_1050_bq24190_props, }; -static struct x86_gpio_button lenovo_yoga_tab2_830_1050_lid = { +static const struct x86_gpio_button lenovo_yoga_tab2_830_1050_lid __initconst = { .button = { .code = SW_LID, .active_low = true, @@ -268,6 +298,14 @@ static struct x86_i2c_client_info lenovo_yoga_tab2_830_1050_i2c_clients[] __init }, .adapter_path = "\\_SB_.I2C5", }, { + /* AL3320A ambient light sensor */ + .board_info = { + .type = "al3320a", + .addr = 0x1c, + .dev_name = "al3320a", + }, + .adapter_path = "\\_SB_.I2C5", + }, { /* bq24292i battery charger */ .board_info = { .type = "bq24190", @@ -357,6 +395,7 @@ const struct x86_dev_info lenovo_yoga_tab2_830_1050_info __initconst = { .pdev_info = int3496_pdevs, .pdev_count = 1, .gpio_button = &lenovo_yoga_tab2_830_1050_lid, + .gpio_button_count = 1, .gpiod_lookup_tables = lenovo_yoga_tab2_830_1050_gpios, .bat_swnode = &generic_lipo_hv_4v35_battery_node, .modules = bq24190_modules, diff --git a/drivers/platform/x86/x86-android-tablets/other.c b/drivers/platform/x86/x86-android-tablets/other.c index 83cd7e16c84c..e79549c6aae1 100644 --- a/drivers/platform/x86/x86-android-tablets/other.c +++ b/drivers/platform/x86/x86-android-tablets/other.c @@ -94,7 +94,7 @@ const struct x86_dev_info acer_b1_750_info __initconst = { * which is not described in the ACPI tables in anyway. * Use the x86-android-tablets infra to create a gpio-button device for this. */ -static struct x86_gpio_button advantech_mica_071_button = { +static const struct x86_gpio_button advantech_mica_071_button __initconst = { .button = { .code = KEY_PROG1, .active_low = true, @@ -109,6 +109,7 @@ static struct x86_gpio_button advantech_mica_071_button = { const struct x86_dev_info advantech_mica_071_info __initconst = { .gpio_button = &advantech_mica_071_button, + .gpio_button_count = 1, }; /* @@ -196,6 +197,45 @@ const struct x86_dev_info chuwi_hi8_info __initconst = { .init = chuwi_hi8_init, }; +/* + * Cyberbook T116 Android version + * This comes in both Windows and Android versions and even on Android + * the DSDT is mostly sane. This tablet has 2 extra general purpose buttons + * in the button row with the power + volume-buttons labeled P and F. + * Use the x86-android-tablets infra to create a gpio-button device for these. + */ +static const struct x86_gpio_button cyberbook_t116_buttons[] __initconst = { + { + .button = { + .code = KEY_PROG1, + .active_low = true, + .desc = "prog1_key", + .type = EV_KEY, + .wakeup = false, + .debounce_interval = 50, + }, + .chip = "INT33FF:00", + .pin = 30, + }, + { + .button = { + .code = KEY_PROG2, + .active_low = true, + .desc = "prog2_key", + .type = EV_KEY, + .wakeup = false, + .debounce_interval = 50, + }, + .chip = "INT33FF:03", + .pin = 48, + }, +}; + +const struct x86_dev_info cyberbook_t116_info __initconst = { + .gpio_button = cyberbook_t116_buttons, + .gpio_button_count = ARRAY_SIZE(cyberbook_t116_buttons), +}; + #define CZC_EC_EXTRA_PORT 0x68 #define CZC_EC_ANDROID_KEYS 0x63 @@ -311,7 +351,7 @@ const struct x86_dev_info medion_lifetab_s10346_info __initconst = { .gpiod_lookup_tables = medion_lifetab_s10346_gpios, }; -/* Nextbook Ares 8 tablets have an Android factory img with everything hardcoded */ +/* Nextbook Ares 8 (BYT) tablets have an Android factory img with everything hardcoded */ static const char * const nextbook_ares8_accel_mount_matrix[] = { "0", "-1", "0", "-1", "0", "0", @@ -377,7 +417,70 @@ const struct x86_dev_info nextbook_ares8_info __initconst = { .pdev_info = int3496_pdevs, .pdev_count = 1, .gpiod_lookup_tables = nextbook_ares8_gpios, - .invalid_aei_gpiochip = "INT33FC:02", +}; + +/* Nextbook Ares 8A (CHT) tablets have an Android factory img with everything hardcoded */ +static const char * const nextbook_ares8a_accel_mount_matrix[] = { + "1", "0", "0", + "0", "-1", "0", + "0", "0", "1" +}; + +static const struct property_entry nextbook_ares8a_accel_props[] = { + PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", nextbook_ares8a_accel_mount_matrix), + { } +}; + +static const struct software_node nextbook_ares8a_accel_node = { + .properties = nextbook_ares8a_accel_props, +}; + +static const struct x86_i2c_client_info nextbook_ares8a_i2c_clients[] __initconst = { + { + /* Freescale MMA8653FC accel */ + .board_info = { + .type = "mma8653", + .addr = 0x1d, + .dev_name = "mma8653", + .swnode = &nextbook_ares8a_accel_node, + }, + .adapter_path = "\\_SB_.PCI0.I2C3", + }, { + /* FT5416DQ9 touchscreen controller */ + .board_info = { + .type = "edt-ft5x06", + .addr = 0x38, + .dev_name = "ft5416", + .swnode = &nextbook_ares8_touchscreen_node, + }, + .adapter_path = "\\_SB_.PCI0.I2C6", + .irq_data = { + .type = X86_ACPI_IRQ_TYPE_GPIOINT, + .chip = "INT33FF:01", + .index = 17, + .trigger = ACPI_EDGE_SENSITIVE, + .polarity = ACPI_ACTIVE_LOW, + }, + }, +}; + +static struct gpiod_lookup_table nextbook_ares8a_ft5416_gpios = { + .dev_id = "i2c-ft5416", + .table = { + GPIO_LOOKUP("INT33FF:01", 25, "reset", GPIO_ACTIVE_LOW), + { } + }, +}; + +static struct gpiod_lookup_table * const nextbook_ares8a_gpios[] = { + &nextbook_ares8a_ft5416_gpios, + NULL +}; + +const struct x86_dev_info nextbook_ares8a_info __initconst = { + .i2c_client_info = nextbook_ares8a_i2c_clients, + .i2c_client_count = ARRAY_SIZE(nextbook_ares8a_i2c_clients), + .gpiod_lookup_tables = nextbook_ares8a_gpios, }; /* @@ -386,7 +489,7 @@ const struct x86_dev_info nextbook_ares8_info __initconst = { * This button has a WMI interface, but that is broken. Instead of trying to * use the broken WMI interface, instantiate a gpio_keys device for this. */ -static struct x86_gpio_button peaq_c1010_button = { +static const struct x86_gpio_button peaq_c1010_button __initconst = { .button = { .code = KEY_SOUND, .active_low = true, @@ -401,6 +504,7 @@ static struct x86_gpio_button peaq_c1010_button = { const struct x86_dev_info peaq_c1010_info __initconst = { .gpio_button = &peaq_c1010_button, + .gpio_button_count = 1, /* * Move the ACPI event handler used by the broken WMI interface out of * the way. This is the only event handler on INT33FC:00. diff --git a/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h b/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h index b6802d75dbdd..e46e1128acc8 100644 --- a/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h +++ b/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h @@ -73,10 +73,11 @@ struct x86_dev_info { const struct x86_i2c_client_info *i2c_client_info; const struct platform_device_info *pdev_info; const struct x86_serdev_info *serdev_info; - struct x86_gpio_button *gpio_button; + const struct x86_gpio_button *gpio_button; int i2c_client_count; int pdev_count; int serdev_count; + int gpio_button_count; int (*init)(void); void (*exit)(void); }; @@ -93,6 +94,7 @@ extern const struct x86_dev_info advantech_mica_071_info; extern const struct x86_dev_info asus_me176c_info; extern const struct x86_dev_info asus_tf103c_info; extern const struct x86_dev_info chuwi_hi8_info; +extern const struct x86_dev_info cyberbook_t116_info; extern const struct x86_dev_info czc_p10t; extern const struct x86_dev_info lenovo_yogabook_x90_info; extern const struct x86_dev_info lenovo_yogabook_x91_info; @@ -100,6 +102,7 @@ extern const struct x86_dev_info lenovo_yoga_tab2_830_1050_info; extern const struct x86_dev_info lenovo_yt3_info; extern const struct x86_dev_info medion_lifetab_s10346_info; extern const struct x86_dev_info nextbook_ares8_info; +extern const struct x86_dev_info nextbook_ares8a_info; extern const struct x86_dev_info peaq_c1010_info; extern const struct x86_dev_info whitelabel_tm800a550l_info; extern const struct x86_dev_info xiaomi_mipad2_info; diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 45788955c4e6..edcbf77852c3 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -2737,7 +2737,12 @@ static void __dasd_cleanup_cqr(struct dasd_ccw_req *cqr) else if (status == 0) { switch (cqr->intrc) { case -EPERM: - error = BLK_STS_NEXUS; + /* + * DASD doesn't implement SCSI/NVMe reservations, but it + * implements a locking scheme similar to them. We + * return this error when we no longer have the lock. + */ + error = BLK_STS_RESV_CONFLICT; break; case -ENOLINK: error = BLK_STS_TRANSPORT; diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 200f88f0e451..405d76df9427 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -54,7 +54,8 @@ static int dcssblk_dax_zero_page_range(struct dax_device *dax_dev, rc = dax_direct_access(dax_dev, pgoff, nr_pages, DAX_ACCESS, &kaddr, NULL); if (rc < 0) - return rc; + return dax_mem2blk_err(rc); + memset(kaddr, 0, nr_pages << PAGE_SHIFT); dax_flush(dax_dev, kaddr, nr_pages << PAGE_SHIFT); return 0; diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index 36c34ced0cc1..f39c9ec2e781 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -2305,8 +2305,10 @@ static int tw_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) TW_DISABLE_INTERRUPTS(tw_dev); /* Initialize the card */ - if (tw_reset_sequence(tw_dev)) + if (tw_reset_sequence(tw_dev)) { + retval = -EINVAL; goto out_release_mem_region; + } /* Set host specific parameters */ host->max_id = TW_MAX_UNITS; diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 0704809d9d99..4962ce989113 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -334,7 +334,7 @@ config SGIWD93_SCSI config BLK_DEV_3W_XXXX_RAID tristate "3ware 5/6/7/8xxx ATA-RAID support" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI help 3ware is the only hardware ATA-Raid product in Linux to date. This card is 2,4, or 8 channel master mode support only. @@ -381,7 +381,7 @@ config SCSI_3W_SAS config SCSI_ACARD tristate "ACARD SCSI support" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI help This driver supports the ACARD SCSI host adapter. Support Chip <ATP870 ATP876 ATP880 ATP885> @@ -462,7 +462,7 @@ config SCSI_MVUMI config SCSI_ADVANSYS tristate "AdvanSys SCSI support" depends on SCSI - depends on ISA || EISA || PCI + depends on (ISA || EISA || PCI) && HAS_IOPORT depends on ISA_DMA_API || !ISA help This is a driver for all SCSI host adapters manufactured by @@ -503,7 +503,7 @@ config SCSI_HPTIOP config SCSI_BUSLOGIC tristate "BusLogic SCSI support" - depends on PCI && SCSI + depends on SCSI && PCI && HAS_IOPORT help This is support for BusLogic MultiMaster and FlashPoint SCSI Host Adapters. Consult the SCSI-HOWTO, available from @@ -518,7 +518,7 @@ config SCSI_BUSLOGIC config SCSI_FLASHPOINT bool "FlashPoint support" - depends on SCSI_BUSLOGIC && PCI + depends on SCSI_BUSLOGIC && PCI && HAS_IOPORT help This option allows you to add FlashPoint support to the BusLogic SCSI driver. The FlashPoint SCCB Manager code is @@ -632,7 +632,7 @@ config SCSI_SNIC_DEBUG_FS config SCSI_DMX3191D tristate "DMX3191D SCSI support" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI select SCSI_SPI_ATTRS help This is support for Domex DMX3191D SCSI Host Adapters. @@ -646,7 +646,7 @@ config SCSI_FDOMAIN config SCSI_FDOMAIN_PCI tristate "Future Domain TMC-3260/AHA-2920A PCI SCSI support" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI select SCSI_FDOMAIN help This is support for Future Domain's PCI SCSI host adapters (TMC-3260) @@ -699,7 +699,7 @@ config SCSI_GENERIC_NCR5380 config SCSI_IPS tristate "IBM ServeRAID support" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI help This is support for the IBM ServeRAID hardware RAID controllers. See <http://www.developer.ibm.com/welcome/netfinity/serveraid.html> @@ -759,7 +759,7 @@ config SCSI_IBMVFC_TRACE config SCSI_INITIO tristate "Initio 9100U(W) support" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI help This is support for the Initio 91XXU(W) SCSI host adapter. Please read the SCSI-HOWTO, available from @@ -770,7 +770,7 @@ config SCSI_INITIO config SCSI_INIA100 tristate "Initio INI-A100U2W support" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI help This is support for the Initio INI-A100U2W SCSI host adapter. Please read the SCSI-HOWTO, available from @@ -782,6 +782,7 @@ config SCSI_INIA100 config SCSI_PPA tristate "IOMEGA parallel port (ppa - older drives)" depends on SCSI && PARPORT_PC + depends on HAS_IOPORT help This driver supports older versions of IOMEGA's parallel port ZIP drive (a 100 MB removable media device). @@ -1175,7 +1176,7 @@ config SCSI_SIM710 config SCSI_DC395x tristate "Tekram DC395(U/UW/F) and DC315(U) SCSI support" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI select SCSI_SPI_ATTRS help This driver supports PCI SCSI host adapters based on the ASIC @@ -1207,7 +1208,7 @@ config SCSI_AM53C974 config SCSI_NSP32 tristate "Workbit NinjaSCSI-32Bi/UDE support" - depends on PCI && SCSI && !64BIT + depends on PCI && SCSI && !64BIT && HAS_IOPORT help This is support for the Workbit NinjaSCSI-32Bi/UDE PCI/Cardbus SCSI host adapter. Please read the SCSI-HOWTO, available from diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx index a47dbd500e9a..4bc53eec4c83 100644 --- a/drivers/scsi/aic7xxx/Kconfig.aic79xx +++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx @@ -5,7 +5,7 @@ # config SCSI_AIC79XX tristate "Adaptec AIC79xx U320 support" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI select SCSI_SPI_ATTRS help This driver supports all of Adaptec's Ultra 320 PCI-X diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx index 0cfd92ce750a..f0425145a5f4 100644 --- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx +++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx @@ -5,7 +5,7 @@ # config SCSI_AIC7XXX tristate "Adaptec AIC7xxx Fast -> U160 support" - depends on (PCI || EISA) && SCSI + depends on (PCI || EISA) && HAS_IOPORT && SCSI select SCSI_SPI_ATTRS help This driver supports all of Adaptec's Fast through Ultra 160 PCI diff --git a/drivers/scsi/aic94xx/Kconfig b/drivers/scsi/aic94xx/Kconfig index 71931c371b1c..aaa8dadc6e1c 100644 --- a/drivers/scsi/aic94xx/Kconfig +++ b/drivers/scsi/aic94xx/Kconfig @@ -8,7 +8,7 @@ config SCSI_AIC94XX tristate "Adaptec AIC94xx SAS/SATA support" - depends on PCI + depends on PCI && HAS_IOPORT select SCSI_SAS_LIBSAS select FW_LOADER help diff --git a/drivers/scsi/bfa/bfa_fcbuild.c b/drivers/scsi/bfa/bfa_fcbuild.c index df18d9d2af53..773c84af784c 100644 --- a/drivers/scsi/bfa/bfa_fcbuild.c +++ b/drivers/scsi/bfa/bfa_fcbuild.c @@ -1134,7 +1134,7 @@ fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, memset(rspnid, 0, sizeof(struct fcgs_rspnid_req_s)); rspnid->dap = s_id; - strlcpy(rspnid->spn, name, sizeof(rspnid->spn)); + strscpy(rspnid->spn, name, sizeof(rspnid->spn)); rspnid->spn_len = (u8) strlen(rspnid->spn); return sizeof(struct fcgs_rspnid_req_s) + sizeof(struct ct_hdr_s); @@ -1155,7 +1155,7 @@ fc_rsnn_nn_build(struct fchs_s *fchs, void *pyld, u32 s_id, memset(rsnn_nn, 0, sizeof(struct fcgs_rsnn_nn_req_s)); rsnn_nn->node_name = node_name; - strlcpy(rsnn_nn->snn, name, sizeof(rsnn_nn->snn)); + strscpy(rsnn_nn->snn, name, sizeof(rsnn_nn->snn)); rsnn_nn->snn_len = (u8) strlen(rsnn_nn->snn); return sizeof(struct fcgs_rsnn_nn_req_s) + sizeof(struct ct_hdr_s); diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c index d2d396ca0e9a..5023c0ab4277 100644 --- a/drivers/scsi/bfa/bfa_fcs.c +++ b/drivers/scsi/bfa/bfa_fcs.c @@ -761,7 +761,7 @@ bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric) bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model); /* Model name/number */ - strlcpy(port_cfg->sym_name.symname, model, + strscpy(port_cfg->sym_name.symname, model, BFA_SYMNAME_MAXLEN); strlcat(port_cfg->sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR, BFA_SYMNAME_MAXLEN); @@ -822,7 +822,7 @@ bfa_fcs_fabric_nsymb_init(struct bfa_fcs_fabric_s *fabric) bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model); /* Model name/number */ - strlcpy(port_cfg->node_sym_name.symname, model, + strscpy(port_cfg->node_sym_name.symname, model, BFA_SYMNAME_MAXLEN); strlcat(port_cfg->node_sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR, diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c index b12afcc4b189..008afd817087 100644 --- a/drivers/scsi/bfa/bfa_fcs_lport.c +++ b/drivers/scsi/bfa/bfa_fcs_lport.c @@ -2642,10 +2642,10 @@ bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi, bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc, hba_attr->fw_version); - strlcpy(hba_attr->driver_version, (char *)driver_info->version, + strscpy(hba_attr->driver_version, (char *)driver_info->version, sizeof(hba_attr->driver_version)); - strlcpy(hba_attr->os_name, driver_info->host_os_name, + strscpy(hba_attr->os_name, driver_info->host_os_name, sizeof(hba_attr->os_name)); /* @@ -2663,13 +2663,13 @@ bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi, bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr); hba_attr->max_ct_pyld = fcs_port_attr.max_frm_size; - strlcpy(hba_attr->node_sym_name.symname, + strscpy(hba_attr->node_sym_name.symname, port->port_cfg.node_sym_name.symname, BFA_SYMNAME_MAXLEN); strcpy(hba_attr->vendor_info, "QLogic"); hba_attr->num_ports = cpu_to_be32(bfa_ioc_get_nports(&port->fcs->bfa->ioc)); hba_attr->fabric_name = port->fabric->lps->pr_nwwn; - strlcpy(hba_attr->bios_ver, hba_attr->option_rom_ver, BFA_VERSION_LEN); + strscpy(hba_attr->bios_ver, hba_attr->option_rom_ver, BFA_VERSION_LEN); } @@ -2736,19 +2736,19 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi, /* * OS device Name */ - strlcpy(port_attr->os_device_name, driver_info->os_device_name, + strscpy(port_attr->os_device_name, driver_info->os_device_name, sizeof(port_attr->os_device_name)); /* * Host name */ - strlcpy(port_attr->host_name, driver_info->host_machine_name, + strscpy(port_attr->host_name, driver_info->host_machine_name, sizeof(port_attr->host_name)); port_attr->node_name = bfa_fcs_lport_get_nwwn(port); port_attr->port_name = bfa_fcs_lport_get_pwwn(port); - strlcpy(port_attr->port_sym_name.symname, + strscpy(port_attr->port_sym_name.symname, bfa_fcs_lport_get_psym_name(port).symname, BFA_SYMNAME_MAXLEN); bfa_fcs_lport_get_attr(port, &lport_attr); port_attr->port_type = cpu_to_be32(lport_attr.port_type); @@ -3229,7 +3229,7 @@ bfa_fcs_lport_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp, rsp_str[gmal_entry->len-1] = 0; /* copy IP Address to fabric */ - strlcpy(bfa_fcs_lport_get_fabric_ipaddr(port), + strscpy(bfa_fcs_lport_get_fabric_ipaddr(port), gmal_entry->ip_addr, BFA_FCS_FABRIC_IPADDR_SZ); break; @@ -4667,7 +4667,7 @@ bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) * to that of the base port. */ - strlcpy(symbl, + strscpy(symbl, (char *)&(bfa_fcs_lport_get_psym_name (bfa_fcs_get_base_port(port->fcs))), sizeof(symbl)); @@ -5194,7 +5194,7 @@ bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg, struct bfa_fcxp_s *fcxp_alloced) * For Vports, we append the vport's port symbolic name * to that of the base port. */ - strlcpy(symbl, (char *)&(bfa_fcs_lport_get_psym_name + strscpy(symbl, (char *)&(bfa_fcs_lport_get_psym_name (bfa_fcs_get_base_port(port->fcs))), sizeof(symbl)); diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 5740302d83ac..e1ed1424fddb 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -2788,7 +2788,7 @@ void bfa_ioc_get_adapter_manufacturer(struct bfa_ioc_s *ioc, char *manufacturer) { memset((void *)manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN); - strlcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN); + strscpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN); } void diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index 4e3cef02f10f..c9745c0b4eee 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c @@ -330,7 +330,7 @@ bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid, lp.eid = event; lp.log_type = BFA_PL_LOG_TYPE_STRING; lp.misc = misc; - strlcpy(lp.log_entry.string_log, log_str, + strscpy(lp.log_entry.string_log, log_str, BFA_PL_STRING_LOG_SZ); lp.log_entry.string_log[BFA_PL_STRING_LOG_SZ - 1] = '\0'; bfa_plog_add(plog, &lp); diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index 529b73a83d69..62cb7a864fd5 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -965,19 +965,19 @@ bfad_start_ops(struct bfad_s *bfad) { /* Fill the driver_info info to fcs*/ memset(&driver_info, 0, sizeof(driver_info)); - strlcpy(driver_info.version, BFAD_DRIVER_VERSION, + strscpy(driver_info.version, BFAD_DRIVER_VERSION, sizeof(driver_info.version)); if (host_name) - strlcpy(driver_info.host_machine_name, host_name, + strscpy(driver_info.host_machine_name, host_name, sizeof(driver_info.host_machine_name)); if (os_name) - strlcpy(driver_info.host_os_name, os_name, + strscpy(driver_info.host_os_name, os_name, sizeof(driver_info.host_os_name)); if (os_patch) - strlcpy(driver_info.host_os_patch, os_patch, + strscpy(driver_info.host_os_patch, os_patch, sizeof(driver_info.host_os_patch)); - strlcpy(driver_info.os_device_name, bfad->pci_name, + strscpy(driver_info.os_device_name, bfad->pci_name, sizeof(driver_info.os_device_name)); /* FCS driver info init */ diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c index 5a85401e9e2d..e96e4b6df265 100644 --- a/drivers/scsi/bfa/bfad_attr.c +++ b/drivers/scsi/bfa/bfad_attr.c @@ -834,7 +834,7 @@ bfad_im_symbolic_name_show(struct device *dev, struct device_attribute *attr, char symname[BFA_SYMNAME_MAXLEN]; bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr); - strlcpy(symname, port_attr.port_cfg.sym_name.symname, + strscpy(symname, port_attr.port_cfg.sym_name.symname, BFA_SYMNAME_MAXLEN); return sysfs_emit(buf, "%s\n", symname); } diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index 79d4f7ee5bcb..520f9152f3bf 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -119,7 +119,7 @@ bfad_iocmd_ioc_get_attr(struct bfad_s *bfad, void *cmd) /* fill in driver attr info */ strcpy(iocmd->ioc_attr.driver_attr.driver, BFAD_DRIVER_NAME); - strlcpy(iocmd->ioc_attr.driver_attr.driver_ver, + strscpy(iocmd->ioc_attr.driver_attr.driver_ver, BFAD_DRIVER_VERSION, BFA_VERSION_LEN); strcpy(iocmd->ioc_attr.driver_attr.fw_ver, iocmd->ioc_attr.adapter_attr.fw_ver); @@ -307,7 +307,7 @@ bfad_iocmd_port_get_attr(struct bfad_s *bfad, void *cmd) iocmd->attr.port_type = port_attr.port_type; iocmd->attr.loopback = port_attr.loopback; iocmd->attr.authfail = port_attr.authfail; - strlcpy(iocmd->attr.port_symname.symname, + strscpy(iocmd->attr.port_symname.symname, port_attr.port_cfg.sym_name.symname, sizeof(iocmd->attr.port_symname.symname)); diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index c335f7a188d2..a9d3d8562d3c 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -1046,7 +1046,7 @@ bfad_fc_host_init(struct bfad_im_port_s *im_port) /* For fibre channel services type 0x20 */ fc_host_supported_fc4s(host)[7] = 1; - strlcpy(symname, bfad->bfa_fcs.fabric.bport.port_cfg.sym_name.symname, + strscpy(symname, bfad->bfa_fcs.fabric.bport.port_cfg.sym_name.symname, BFA_SYMNAME_MAXLEN); sprintf(fc_host_symbolic_name(host), "%s", symname); diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c index 46b0bf237be1..a48d24af9ac3 100644 --- a/drivers/scsi/fcoe/fcoe_transport.c +++ b/drivers/scsi/fcoe/fcoe_transport.c @@ -711,7 +711,7 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer) char ifname[IFNAMSIZ + 2]; if (buffer) { - strlcpy(ifname, buffer, IFNAMSIZ); + strscpy(ifname, buffer, IFNAMSIZ); cp = ifname + strlen(ifname); while (--cp >= ifname && *cp == '\n') *cp = '\0'; diff --git a/drivers/scsi/fnic/fnic_debugfs.c b/drivers/scsi/fnic/fnic_debugfs.c index 6fedc3b7d1ab..c4d9ed0d7d75 100644 --- a/drivers/scsi/fnic/fnic_debugfs.c +++ b/drivers/scsi/fnic/fnic_debugfs.c @@ -201,25 +201,21 @@ static int fnic_trace_debugfs_open(struct inode *inode, return -ENOMEM; if (*rdata_ptr == fc_trc_flag->fnic_trace) { - fnic_dbg_prt->buffer = vmalloc(array3_size(3, trace_max_pages, + fnic_dbg_prt->buffer = vzalloc(array3_size(3, trace_max_pages, PAGE_SIZE)); if (!fnic_dbg_prt->buffer) { kfree(fnic_dbg_prt); return -ENOMEM; } - memset((void *)fnic_dbg_prt->buffer, 0, - 3 * (trace_max_pages * PAGE_SIZE)); fnic_dbg_prt->buffer_len = fnic_get_trace_data(fnic_dbg_prt); } else { fnic_dbg_prt->buffer = - vmalloc(array3_size(3, fnic_fc_trace_max_pages, + vzalloc(array3_size(3, fnic_fc_trace_max_pages, PAGE_SIZE)); if (!fnic_dbg_prt->buffer) { kfree(fnic_dbg_prt); return -ENOMEM; } - memset((void *)fnic_dbg_prt->buffer, 0, - 3 * (fnic_fc_trace_max_pages * PAGE_SIZE)); fnic_dbg_prt->buffer_len = fnic_fc_trace_get_data(fnic_dbg_prt, *rdata_ptr); } diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index fb7c52c119df..9e73e9cbbcfc 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -642,7 +642,7 @@ extern void hisi_sas_sata_done(struct sas_task *task, extern int hisi_sas_get_fw_info(struct hisi_hba *hisi_hba); extern int hisi_sas_probe(struct platform_device *pdev, const struct hisi_sas_hw *ops); -extern int hisi_sas_remove(struct platform_device *pdev); +extern void hisi_sas_remove(struct platform_device *pdev); extern int hisi_sas_slave_configure(struct scsi_device *sdev); extern int hisi_sas_slave_alloc(struct scsi_device *sdev); diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 412431c901a7..8f22ece957bd 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -2560,7 +2560,7 @@ err_out_ha: } EXPORT_SYMBOL_GPL(hisi_sas_probe); -int hisi_sas_remove(struct platform_device *pdev) +void hisi_sas_remove(struct platform_device *pdev) { struct sas_ha_struct *sha = platform_get_drvdata(pdev); struct hisi_hba *hisi_hba = sha->lldd_ha; @@ -2573,7 +2573,6 @@ int hisi_sas_remove(struct platform_device *pdev) hisi_sas_free(hisi_hba); scsi_host_put(shost); - return 0; } EXPORT_SYMBOL_GPL(hisi_sas_remove); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 0aa8c9c88535..94fbbceddc2e 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -1790,11 +1790,6 @@ static int hisi_sas_v1_probe(struct platform_device *pdev) return hisi_sas_probe(pdev, &hisi_sas_v1_hw); } -static int hisi_sas_v1_remove(struct platform_device *pdev) -{ - return hisi_sas_remove(pdev); -} - static const struct of_device_id sas_v1_of_match[] = { { .compatible = "hisilicon,hip05-sas-v1",}, {}, @@ -1810,7 +1805,7 @@ MODULE_DEVICE_TABLE(acpi, sas_v1_acpi_match); static struct platform_driver hisi_sas_v1_driver = { .probe = hisi_sas_v1_probe, - .remove = hisi_sas_v1_remove, + .remove_new = hisi_sas_remove, .driver = { .name = DRV_NAME, .of_match_table = sas_v1_of_match, diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index cd78e4c983aa..87d8e408ccd1 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -3619,11 +3619,6 @@ static int hisi_sas_v2_probe(struct platform_device *pdev) return hisi_sas_probe(pdev, &hisi_sas_v2_hw); } -static int hisi_sas_v2_remove(struct platform_device *pdev) -{ - return hisi_sas_remove(pdev); -} - static const struct of_device_id sas_v2_of_match[] = { { .compatible = "hisilicon,hip06-sas-v2",}, { .compatible = "hisilicon,hip07-sas-v2",}, @@ -3640,7 +3635,7 @@ MODULE_DEVICE_TABLE(acpi, sas_v2_acpi_match); static struct platform_driver hisi_sas_v2_driver = { .probe = hisi_sas_v2_probe, - .remove = hisi_sas_v2_remove, + .remove_new = hisi_sas_remove, .driver = { .name = DRV_NAME, .of_match_table = sas_v2_of_match, diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 12d588454f5d..20e1607c6282 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -30,6 +30,7 @@ #define SATA_INITI_D2H_STORE_ADDR_LO 0x60 #define SATA_INITI_D2H_STORE_ADDR_HI 0x64 #define CFG_MAX_TAG 0x68 +#define TRANS_LOCK_ICT_TIME 0X70 #define HGC_SAS_TX_OPEN_FAIL_RETRY_CTRL 0x84 #define HGC_SAS_TXFAIL_RETRY_CTRL 0x88 #define HGC_GET_ITV_TIME 0x90 @@ -627,13 +628,15 @@ static void interrupt_enable_v3_hw(struct hisi_hba *hisi_hba) static void init_reg_v3_hw(struct hisi_hba *hisi_hba) { + struct pci_dev *pdev = hisi_hba->pci_dev; int i, j; /* Global registers init */ hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, (u32)((1ULL << hisi_hba->queue_count) - 1)); - hisi_sas_write32(hisi_hba, SAS_AXI_USER3, 0); hisi_sas_write32(hisi_hba, CFG_MAX_TAG, 0xfff0400); + /* time / CLK_AHB = 2.5s / 2ns = 0x4A817C80 */ + hisi_sas_write32(hisi_hba, TRANS_LOCK_ICT_TIME, 0x4A817C80); hisi_sas_write32(hisi_hba, HGC_SAS_TXFAIL_RETRY_CTRL, 0x108); hisi_sas_write32(hisi_hba, CFG_AGING_TIME, 0x1); hisi_sas_write32(hisi_hba, INT_COAL_EN, 0x1); @@ -652,6 +655,9 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) hisi_sas_write32(hisi_hba, ARQOS_ARCACHE_CFG, 0xf0f0); hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1); + if (pdev->revision < 0x30) + hisi_sas_write32(hisi_hba, SAS_AXI_USER3, 0); + interrupt_enable_v3_hw(hisi_hba); for (i = 0; i < hisi_hba->n_phy; i++) { enum sas_linkrate max; @@ -669,7 +675,6 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) prog_phy_link_rate |= hisi_sas_get_prog_phy_linkrate_mask(max); hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE, prog_phy_link_rate); - hisi_sas_phy_write32(hisi_hba, i, SERDES_CFG, 0xffc00); hisi_sas_phy_write32(hisi_hba, i, SAS_RX_TRAIN_TIMER, 0x13e80); hisi_sas_phy_write32(hisi_hba, i, CHL_INT0, 0xffffffff); hisi_sas_phy_write32(hisi_hba, i, CHL_INT1, 0xffffffff); @@ -680,13 +685,18 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_OOB_RESTART_MSK, 0x1); hisi_sas_phy_write32(hisi_hba, i, STP_LINK_TIMER, 0x7f7a120); hisi_sas_phy_write32(hisi_hba, i, CON_CFG_DRIVER, 0x2a0a01); - hisi_sas_phy_write32(hisi_hba, i, SAS_SSP_CON_TIMER_CFG, 0x32); hisi_sas_phy_write32(hisi_hba, i, SAS_EC_INT_COAL_TIME, 0x30f4240); - /* used for 12G negotiate */ - hisi_sas_phy_write32(hisi_hba, i, COARSETUNE_TIME, 0x1e); hisi_sas_phy_write32(hisi_hba, i, AIP_LIMIT, 0x2ffff); + /* set value through firmware for 920B and later version */ + if (pdev->revision < 0x30) { + hisi_sas_phy_write32(hisi_hba, i, SAS_SSP_CON_TIMER_CFG, 0x32); + hisi_sas_phy_write32(hisi_hba, i, SERDES_CFG, 0xffc00); + /* used for 12G negotiate */ + hisi_sas_phy_write32(hisi_hba, i, COARSETUNE_TIME, 0x1e); + } + /* get default FFE configuration for BIST */ for (j = 0; j < FFE_CFG_MAX; j++) { u32 val = hisi_sas_phy_read32(hisi_hba, i, @@ -2206,6 +2216,7 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task, u32 trans_tx_fail_type = le32_to_cpu(record->trans_tx_fail_type); u16 sipc_rx_err_type = le16_to_cpu(record->sipc_rx_err_type); u32 dw3 = le32_to_cpu(complete_hdr->dw3); + u32 dw0 = le32_to_cpu(complete_hdr->dw0); switch (task->task_proto) { case SAS_PROTOCOL_SSP: @@ -2215,8 +2226,8 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task, * but I/O information has been written to the host memory, we examine * response IU. */ - if (!(complete_hdr->dw0 & CMPLT_HDR_RSPNS_GOOD_MSK) && - (complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK)) + if (!(dw0 & CMPLT_HDR_RSPNS_GOOD_MSK) && + (dw0 & CMPLT_HDR_RSPNS_XFRD_MSK)) return false; ts->residual = trans_tx_fail_type; @@ -2232,7 +2243,7 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task, case SAS_PROTOCOL_SATA: case SAS_PROTOCOL_STP: case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: - if ((complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK) && + if ((dw0 & CMPLT_HDR_RSPNS_XFRD_MSK) && (sipc_rx_err_type & RX_FIS_STATUS_ERR_MSK)) { ts->stat = SAS_PROTO_RESPONSE; } else if (dma_rx_err_type & RX_DATA_LEN_UNDERFLOW_MSK) { @@ -2999,6 +3010,7 @@ static const struct hisi_sas_debugfs_reg_lu debugfs_global_reg_lu[] = { HISI_SAS_DEBUGFS_REG(SATA_INITI_D2H_STORE_ADDR_LO), HISI_SAS_DEBUGFS_REG(SATA_INITI_D2H_STORE_ADDR_HI), HISI_SAS_DEBUGFS_REG(CFG_MAX_TAG), + HISI_SAS_DEBUGFS_REG(TRANS_LOCK_ICT_TIME), HISI_SAS_DEBUGFS_REG(HGC_SAS_TX_OPEN_FAIL_RETRY_CTRL), HISI_SAS_DEBUGFS_REG(HGC_SAS_TXFAIL_RETRY_CTRL), HISI_SAS_DEBUGFS_REG(HGC_GET_ITV_TIME), diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index f0bc8bbb3938..198edf03f929 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -441,6 +441,7 @@ struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *sht, int priv shost->cmd_per_lun = sht->cmd_per_lun; shost->no_write_same = sht->no_write_same; shost->host_tagset = sht->host_tagset; + shost->queuecommand_may_block = sht->queuecommand_may_block; if (shost_eh_deadline == -1 || !sht->eh_host_reset_handler) shost->eh_deadline = -1; diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index dc670304f181..adcac57aaee6 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -1198,37 +1198,37 @@ static void sas_print_parent_topology_bug(struct domain_device *child, sas_route_char(child, child_phy)); } +static bool sas_eeds_valid(struct domain_device *parent, + struct domain_device *child) +{ + struct sas_discovery *disc = &parent->port->disc; + + return (SAS_ADDR(disc->eeds_a) == SAS_ADDR(parent->sas_addr) || + SAS_ADDR(disc->eeds_a) == SAS_ADDR(child->sas_addr)) && + (SAS_ADDR(disc->eeds_b) == SAS_ADDR(parent->sas_addr) || + SAS_ADDR(disc->eeds_b) == SAS_ADDR(child->sas_addr)); +} + static int sas_check_eeds(struct domain_device *child, - struct ex_phy *parent_phy, - struct ex_phy *child_phy) + struct ex_phy *parent_phy, + struct ex_phy *child_phy) { int res = 0; struct domain_device *parent = child->parent; + struct sas_discovery *disc = &parent->port->disc; - if (SAS_ADDR(parent->port->disc.fanout_sas_addr) != 0) { + if (SAS_ADDR(disc->fanout_sas_addr) != 0) { res = -ENODEV; pr_warn("edge ex %016llx phy S:%02d <--> edge ex %016llx phy S:%02d, while there is a fanout ex %016llx\n", SAS_ADDR(parent->sas_addr), parent_phy->phy_id, SAS_ADDR(child->sas_addr), child_phy->phy_id, - SAS_ADDR(parent->port->disc.fanout_sas_addr)); - } else if (SAS_ADDR(parent->port->disc.eeds_a) == 0) { - memcpy(parent->port->disc.eeds_a, parent->sas_addr, - SAS_ADDR_SIZE); - memcpy(parent->port->disc.eeds_b, child->sas_addr, - SAS_ADDR_SIZE); - } else if (((SAS_ADDR(parent->port->disc.eeds_a) == - SAS_ADDR(parent->sas_addr)) || - (SAS_ADDR(parent->port->disc.eeds_a) == - SAS_ADDR(child->sas_addr))) - && - ((SAS_ADDR(parent->port->disc.eeds_b) == - SAS_ADDR(parent->sas_addr)) || - (SAS_ADDR(parent->port->disc.eeds_b) == - SAS_ADDR(child->sas_addr)))) - ; - else { + SAS_ADDR(disc->fanout_sas_addr)); + } else if (SAS_ADDR(disc->eeds_a) == 0) { + memcpy(disc->eeds_a, parent->sas_addr, SAS_ADDR_SIZE); + memcpy(disc->eeds_b, child->sas_addr, SAS_ADDR_SIZE); + } else if (!sas_eeds_valid(parent, child)) { res = -ENODEV; pr_warn("edge ex %016llx phy%02d <--> edge ex %016llx phy%02d link forms a third EEDS!\n", SAS_ADDR(parent->sas_addr), @@ -1240,11 +1240,56 @@ static int sas_check_eeds(struct domain_device *child, return res; } -/* Here we spill over 80 columns. It is intentional. - */ -static int sas_check_parent_topology(struct domain_device *child) +static int sas_check_edge_expander_topo(struct domain_device *child, + struct ex_phy *parent_phy) +{ + struct expander_device *child_ex = &child->ex_dev; + struct expander_device *parent_ex = &child->parent->ex_dev; + struct ex_phy *child_phy; + + child_phy = &child_ex->ex_phy[parent_phy->attached_phy_id]; + + if (child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) { + if (parent_phy->routing_attr != SUBTRACTIVE_ROUTING || + child_phy->routing_attr != TABLE_ROUTING) + goto error; + } else if (parent_phy->routing_attr == SUBTRACTIVE_ROUTING) { + if (child_phy->routing_attr == SUBTRACTIVE_ROUTING) + return sas_check_eeds(child, parent_phy, child_phy); + else if (child_phy->routing_attr != TABLE_ROUTING) + goto error; + } else if (parent_phy->routing_attr == TABLE_ROUTING) { + if (child_phy->routing_attr != SUBTRACTIVE_ROUTING && + (child_phy->routing_attr != TABLE_ROUTING || + !child_ex->t2t_supp || !parent_ex->t2t_supp)) + goto error; + } + + return 0; +error: + sas_print_parent_topology_bug(child, parent_phy, child_phy); + return -ENODEV; +} + +static int sas_check_fanout_expander_topo(struct domain_device *child, + struct ex_phy *parent_phy) { struct expander_device *child_ex = &child->ex_dev; + struct ex_phy *child_phy; + + child_phy = &child_ex->ex_phy[parent_phy->attached_phy_id]; + + if (parent_phy->routing_attr == TABLE_ROUTING && + child_phy->routing_attr == SUBTRACTIVE_ROUTING) + return 0; + + sas_print_parent_topology_bug(child, parent_phy, child_phy); + + return -ENODEV; +} + +static int sas_check_parent_topology(struct domain_device *child) +{ struct expander_device *parent_ex; int i; int res = 0; @@ -1259,7 +1304,6 @@ static int sas_check_parent_topology(struct domain_device *child) for (i = 0; i < parent_ex->num_phys; i++) { struct ex_phy *parent_phy = &parent_ex->ex_phy[i]; - struct ex_phy *child_phy; if (parent_phy->phy_state == PHY_VACANT || parent_phy->phy_state == PHY_NOT_PRESENT) @@ -1268,40 +1312,14 @@ static int sas_check_parent_topology(struct domain_device *child) if (!sas_phy_match_dev_addr(child, parent_phy)) continue; - child_phy = &child_ex->ex_phy[parent_phy->attached_phy_id]; - switch (child->parent->dev_type) { case SAS_EDGE_EXPANDER_DEVICE: - if (child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) { - if (parent_phy->routing_attr != SUBTRACTIVE_ROUTING || - child_phy->routing_attr != TABLE_ROUTING) { - sas_print_parent_topology_bug(child, parent_phy, child_phy); - res = -ENODEV; - } - } else if (parent_phy->routing_attr == SUBTRACTIVE_ROUTING) { - if (child_phy->routing_attr == SUBTRACTIVE_ROUTING) { - res = sas_check_eeds(child, parent_phy, child_phy); - } else if (child_phy->routing_attr != TABLE_ROUTING) { - sas_print_parent_topology_bug(child, parent_phy, child_phy); - res = -ENODEV; - } - } else if (parent_phy->routing_attr == TABLE_ROUTING) { - if (child_phy->routing_attr == SUBTRACTIVE_ROUTING || - (child_phy->routing_attr == TABLE_ROUTING && - child_ex->t2t_supp && parent_ex->t2t_supp)) { - /* All good */; - } else { - sas_print_parent_topology_bug(child, parent_phy, child_phy); - res = -ENODEV; - } - } + if (sas_check_edge_expander_topo(child, parent_phy)) + res = -ENODEV; break; case SAS_FANOUT_EXPANDER_DEVICE: - if (parent_phy->routing_attr != TABLE_ROUTING || - child_phy->routing_attr != SUBTRACTIVE_ROUTING) { - sas_print_parent_topology_bug(child, parent_phy, child_phy); + if (sas_check_fanout_expander_topo(child, parent_phy)) res = -ENODEV; - } break; default: break; diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index a36fa1c128a8..94c5f14f3c16 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -872,8 +872,7 @@ int sas_change_queue_depth(struct scsi_device *sdev, int depth) struct domain_device *dev = sdev_to_domain_dev(sdev); if (dev_is_sata(dev)) - return ata_change_queue_depth(dev->sata_dev.ap, - sas_to_ata_dev(dev), sdev, depth); + return ata_change_queue_depth(dev->sata_dev.ap, sdev, depth); if (!sdev->tagged_supported) depth = 1; diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 5e3a93d13a91..9a8963684369 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -429,6 +429,15 @@ struct lpfc_cgn_param { /* Max number of days of congestion data */ #define LPFC_MAX_CGN_DAYS 10 +struct lpfc_cgn_ts { + uint8_t month; + uint8_t day; + uint8_t year; + uint8_t hour; + uint8_t minute; + uint8_t second; +}; + /* Format of congestion buffer info * This structure defines memory thats allocated and registered with * the HBA firmware. When adding or removing fields from this structure @@ -442,6 +451,7 @@ struct lpfc_cgn_info { #define LPFC_CGN_INFO_V1 1 #define LPFC_CGN_INFO_V2 2 #define LPFC_CGN_INFO_V3 3 +#define LPFC_CGN_INFO_V4 4 uint8_t cgn_info_mode; /* 0=off 1=managed 2=monitor only */ uint8_t cgn_info_detect; uint8_t cgn_info_action; @@ -450,12 +460,7 @@ struct lpfc_cgn_info { uint8_t cgn_info_level2; /* Start Time */ - uint8_t cgn_info_month; - uint8_t cgn_info_day; - uint8_t cgn_info_year; - uint8_t cgn_info_hour; - uint8_t cgn_info_minute; - uint8_t cgn_info_second; + struct lpfc_cgn_ts base_time; /* minute / hours / daily indices */ uint8_t cgn_index_minute; @@ -496,45 +501,17 @@ struct lpfc_cgn_info { uint8_t cgn_stat_npm; /* Notifications per minute */ /* Start Time */ - uint8_t cgn_stat_month; - uint8_t cgn_stat_day; - uint8_t cgn_stat_year; - uint8_t cgn_stat_hour; - uint8_t cgn_stat_minute; - uint8_t cgn_pad2[2]; + struct lpfc_cgn_ts stat_start; /* Base time */ + uint8_t cgn_pad2; __le32 cgn_notification; __le32 cgn_peer_notification; __le32 link_integ_notification; __le32 delivery_notification; - - uint8_t cgn_stat_cgn_month; /* Last congestion notification FPIN */ - uint8_t cgn_stat_cgn_day; - uint8_t cgn_stat_cgn_year; - uint8_t cgn_stat_cgn_hour; - uint8_t cgn_stat_cgn_min; - uint8_t cgn_stat_cgn_sec; - - uint8_t cgn_stat_peer_month; /* Last peer congestion FPIN */ - uint8_t cgn_stat_peer_day; - uint8_t cgn_stat_peer_year; - uint8_t cgn_stat_peer_hour; - uint8_t cgn_stat_peer_min; - uint8_t cgn_stat_peer_sec; - - uint8_t cgn_stat_lnk_month; /* Last link integrity FPIN */ - uint8_t cgn_stat_lnk_day; - uint8_t cgn_stat_lnk_year; - uint8_t cgn_stat_lnk_hour; - uint8_t cgn_stat_lnk_min; - uint8_t cgn_stat_lnk_sec; - - uint8_t cgn_stat_del_month; /* Last delivery notification FPIN */ - uint8_t cgn_stat_del_day; - uint8_t cgn_stat_del_year; - uint8_t cgn_stat_del_hour; - uint8_t cgn_stat_del_min; - uint8_t cgn_stat_del_sec; + struct lpfc_cgn_ts stat_fpin; /* Last congestion notification FPIN */ + struct lpfc_cgn_ts stat_peer; /* Last peer congestion FPIN */ + struct lpfc_cgn_ts stat_lnk; /* Last link integrity FPIN */ + struct lpfc_cgn_ts stat_delivery; /* Last delivery notification FPIN */ ); __le32 cgn_info_crc; @@ -932,8 +909,6 @@ struct lpfc_hba { void (*__lpfc_sli_release_iocbq)(struct lpfc_hba *, struct lpfc_iocbq *); int (*lpfc_hba_down_post)(struct lpfc_hba *phba); - void (*lpfc_scsi_cmd_iocb_cmpl) - (struct lpfc_hba *, struct lpfc_iocbq *, struct lpfc_iocbq *); /* MBOX interface function jump table entries */ int (*lpfc_sli_issue_mbox) @@ -1045,8 +1020,6 @@ struct lpfc_hba { * capability */ #define HBA_FLOGI_ISSUED 0x100000 /* FLOGI was issued */ -#define HBA_SHORT_CMF 0x200000 /* shorter CMF timer routine */ -#define HBA_CGN_DAY_WRAP 0x400000 /* HBA Congestion info day wraps */ #define HBA_DEFER_FLOGI 0x800000 /* Defer FLOGI till read_sparm cmpl */ #define HBA_SETUP 0x1000000 /* Signifies HBA setup is completed */ #define HBA_NEEDS_CFG_PORT 0x2000000 /* SLI3 - needs a CONFIG_PORT mbox */ @@ -1529,6 +1502,7 @@ struct lpfc_hba { uint64_t cmf_last_sync_bw; #define LPFC_CMF_BLK_SIZE 512 struct hrtimer cmf_timer; + struct hrtimer cmf_stats_timer; /* 1 minute stats timer */ atomic_t cmf_bw_wait; atomic_t cmf_busy; atomic_t cmf_stop_io; /* To block request and stop IO's */ @@ -1576,12 +1550,11 @@ struct lpfc_hba { atomic_t cgn_sync_alarm_cnt; /* Total alarm events for SYNC wqe */ atomic_t cgn_driver_evt_cnt; /* Total driver cgn events for fmw */ atomic_t cgn_latency_evt_cnt; - struct timespec64 cgn_daily_ts; atomic64_t cgn_latency_evt; /* Avg latency per minute */ unsigned long cgn_evt_timestamp; #define LPFC_CGN_TIMER_TO_MIN 60000 /* ms in a minute */ uint32_t cgn_evt_minute; -#define LPFC_SEC_MIN 60 +#define LPFC_SEC_MIN 60UL #define LPFC_MIN_HOUR 60 #define LPFC_HOUR_DAY 24 #define LPFC_MIN_DAY (LPFC_MIN_HOUR * LPFC_HOUR_DAY) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 3863a5341782..21c7ecd3ede5 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -5858,8 +5858,8 @@ int lpfc_fabric_cgn_frequency = 100; /* 100 ms default */ module_param(lpfc_fabric_cgn_frequency, int, 0444); MODULE_PARM_DESC(lpfc_fabric_cgn_frequency, "Congestion signaling fabric freq"); -int lpfc_acqe_cgn_frequency = 10; /* 10 sec default */ -module_param(lpfc_acqe_cgn_frequency, int, 0444); +unsigned char lpfc_acqe_cgn_frequency = 10; /* 10 sec default */ +module_param(lpfc_acqe_cgn_frequency, byte, 0444); MODULE_PARM_DESC(lpfc_acqe_cgn_frequency, "Congestion signaling ACQE freq"); int lpfc_use_cgn_signal = 1; /* 0 - only use FPINs, 1 - Use signals if avail */ diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index b833b983e69d..d4e46a08f94d 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -134,7 +134,6 @@ void lpfc_check_nlp_post_devloss(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp); void lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb); -int lpfc_nlp_not_used(struct lpfc_nodelist *ndlp); struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_vport *, uint32_t); void lpfc_disc_list_loopmap(struct lpfc_vport *); void lpfc_disc_start(struct lpfc_vport *); @@ -248,6 +247,7 @@ irqreturn_t lpfc_sli_sp_intr_handler(int, void *); irqreturn_t lpfc_sli_fp_intr_handler(int, void *); irqreturn_t lpfc_sli4_intr_handler(int, void *); irqreturn_t lpfc_sli4_hba_intr_handler(int, void *); +irqreturn_t lpfc_sli4_hba_intr_handler_th(int irq, void *dev_id); int lpfc_read_object(struct lpfc_hba *phba, char *s, uint32_t *datap, uint32_t len); @@ -664,7 +664,7 @@ extern int lpfc_enable_nvmet_cnt; extern unsigned long long lpfc_enable_nvmet[]; extern int lpfc_no_hba_reset_cnt; extern unsigned long lpfc_no_hba_reset[]; -extern int lpfc_acqe_cgn_frequency; +extern unsigned char lpfc_acqe_cgn_frequency; extern int lpfc_fabric_cgn_frequency; extern int lpfc_use_cgn_signal; diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index f3bdcebe67f5..474834f313a7 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -287,7 +287,7 @@ lpfc_ct_handle_mibreq(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocbq) u32 ulp_status = get_job_ulpstatus(phba, ctiocbq); u32 ulp_word4 = get_job_word4(phba, ctiocbq); u32 did; - u32 mi_cmd; + u16 mi_cmd; did = bf_get(els_rsp64_sid, &ctiocbq->wqe.xmit_els_rsp); if (ulp_status) { @@ -311,7 +311,7 @@ lpfc_ct_handle_mibreq(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocbq) ct_req = (struct lpfc_sli_ct_request *)ctiocbq->cmd_dmabuf->virt; - mi_cmd = ct_req->CommandResponse.bits.CmdRsp; + mi_cmd = be16_to_cpu(ct_req->CommandResponse.bits.CmdRsp); lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "6442 : MI Cmd : x%x Not Supported\n", mi_cmd); lpfc_ct_reject_event(ndlp, ct_req, @@ -486,7 +486,7 @@ lpfc_free_ct_rsp(struct lpfc_hba *phba, struct lpfc_dmabuf *mlist) } static struct lpfc_dmabuf * -lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl, +lpfc_alloc_ct_rsp(struct lpfc_hba *phba, __be16 cmdcode, struct ulp_bde64 *bpl, uint32_t size, int *entries) { struct lpfc_dmabuf *mlist = NULL; @@ -507,8 +507,8 @@ lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl, INIT_LIST_HEAD(&mp->list); - if (cmdcode == be16_to_cpu(SLI_CTNS_GID_FT) || - cmdcode == be16_to_cpu(SLI_CTNS_GFF_ID)) + if (be16_to_cpu(cmdcode) == SLI_CTNS_GID_FT || + be16_to_cpu(cmdcode) == SLI_CTNS_GFF_ID) mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys)); else mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys)); @@ -671,7 +671,7 @@ lpfc_ct_cmd(struct lpfc_vport *vport, struct lpfc_dmabuf *inmp, struct ulp_bde64 *bpl = (struct ulp_bde64 *) bmp->virt; struct lpfc_dmabuf *outmp; int cnt = 0, status; - int cmdcode = ((struct lpfc_sli_ct_request *) inmp->virt)-> + __be16 cmdcode = ((struct lpfc_sli_ct_request *)inmp->virt)-> CommandResponse.bits.CmdRsp; bpl++; /* Skip past ct request */ @@ -1043,8 +1043,8 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, outp, CTreq->un.gid.Fc4Type, get_job_data_placed(phba, rspiocb)); - } else if (CTrsp->CommandResponse.bits.CmdRsp == - be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { + } else if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) == + SLI_CT_RESPONSE_FS_RJT) { /* NameServer Rsp Error */ if ((CTrsp->ReasonCode == SLI_CT_UNABLE_TO_PERFORM_REQ) && (CTrsp->Explanation == SLI_CT_NO_FC4_TYPES)) { @@ -1052,14 +1052,14 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, LOG_DISCOVERY, "0269 No NameServer Entries " "Data: x%x x%x x%x x%x\n", - CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t) CTrsp->ReasonCode, (uint32_t) CTrsp->Explanation, vport->fc_flag); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, "GID_FT no entry cmd:x%x rsn:x%x exp:x%x", - (uint32_t)CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t) CTrsp->ReasonCode, (uint32_t) CTrsp->Explanation); } else { @@ -1067,14 +1067,14 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, LOG_DISCOVERY, "0240 NameServer Rsp Error " "Data: x%x x%x x%x x%x\n", - CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t) CTrsp->ReasonCode, (uint32_t) CTrsp->Explanation, vport->fc_flag); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, "GID_FT rsp err1 cmd:x%x rsn:x%x exp:x%x", - (uint32_t)CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t) CTrsp->ReasonCode, (uint32_t) CTrsp->Explanation); } @@ -1085,14 +1085,14 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0241 NameServer Rsp Error " "Data: x%x x%x x%x x%x\n", - CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t) CTrsp->ReasonCode, (uint32_t) CTrsp->Explanation, vport->fc_flag); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, "GID_FT rsp err2 cmd:x%x rsn:x%x exp:x%x", - (uint32_t)CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t) CTrsp->ReasonCode, (uint32_t) CTrsp->Explanation); } @@ -1247,8 +1247,8 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* Good status, continue checking */ CTreq = (struct lpfc_sli_ct_request *)inp->virt; CTrsp = (struct lpfc_sli_ct_request *)outp->virt; - if (CTrsp->CommandResponse.bits.CmdRsp == - cpu_to_be16(SLI_CT_RESPONSE_FS_ACC)) { + if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) == + SLI_CT_RESPONSE_FS_ACC) { lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "4105 NameServer Rsp Data: x%x x%x " "x%x x%x sz x%x\n", @@ -1262,8 +1262,8 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, outp, CTreq->un.gid.Fc4Type, get_job_data_placed(phba, rspiocb)); - } else if (CTrsp->CommandResponse.bits.CmdRsp == - be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { + } else if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) == + SLI_CT_RESPONSE_FS_RJT) { /* NameServer Rsp Error */ if ((CTrsp->ReasonCode == SLI_CT_UNABLE_TO_PERFORM_REQ) && (CTrsp->Explanation == SLI_CT_NO_FC4_TYPES)) { @@ -1271,7 +1271,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, vport, KERN_INFO, LOG_DISCOVERY, "4106 No NameServer Entries " "Data: x%x x%x x%x x%x\n", - CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t)CTrsp->ReasonCode, (uint32_t)CTrsp->Explanation, vport->fc_flag); @@ -1279,7 +1279,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_debugfs_disc_trc( vport, LPFC_DISC_TRC_CT, "GID_PT no entry cmd:x%x rsn:x%x exp:x%x", - (uint32_t)CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t)CTrsp->ReasonCode, (uint32_t)CTrsp->Explanation); } else { @@ -1287,7 +1287,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, vport, KERN_INFO, LOG_DISCOVERY, "4107 NameServer Rsp Error " "Data: x%x x%x x%x x%x\n", - CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t)CTrsp->ReasonCode, (uint32_t)CTrsp->Explanation, vport->fc_flag); @@ -1295,7 +1295,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_debugfs_disc_trc( vport, LPFC_DISC_TRC_CT, "GID_PT rsp err1 cmd:x%x rsn:x%x exp:x%x", - (uint32_t)CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t)CTrsp->ReasonCode, (uint32_t)CTrsp->Explanation); } @@ -1304,7 +1304,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "4109 NameServer Rsp Error " "Data: x%x x%x x%x x%x\n", - CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t)CTrsp->ReasonCode, (uint32_t)CTrsp->Explanation, vport->fc_flag); @@ -1312,7 +1312,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_debugfs_disc_trc( vport, LPFC_DISC_TRC_CT, "GID_PT rsp err2 cmd:x%x rsn:x%x exp:x%x", - (uint32_t)CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t)CTrsp->ReasonCode, (uint32_t)CTrsp->Explanation); } @@ -1391,8 +1391,8 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, (fbits & FC4_FEATURE_INIT) ? "Initiator" : " ", (fbits & FC4_FEATURE_TARGET) ? "Target" : " "); - if (CTrsp->CommandResponse.bits.CmdRsp == - be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) { + if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) == + SLI_CT_RESPONSE_FS_ACC) { if ((fbits & FC4_FEATURE_INIT) && !(fbits & FC4_FEATURE_TARGET)) { lpfc_printf_vlog(vport, KERN_INFO, @@ -1631,7 +1631,7 @@ lpfc_cmpl_ct(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, "0209 CT Request completes, latt %d, " "ulp_status x%x CmdRsp x%x, Context x%x, Tag x%x\n", latt, ulp_status, - CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), get_job_ulpcontext(phba, cmdiocb), cmdiocb->iotag); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, @@ -1681,8 +1681,8 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, outp = cmdiocb->rsp_dmabuf; CTrsp = (struct lpfc_sli_ct_request *)outp->virt; - if (CTrsp->CommandResponse.bits.CmdRsp == - be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) + if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) == + SLI_CT_RESPONSE_FS_ACC) vport->ct_flags |= FC_CT_RFT_ID; } lpfc_cmpl_ct(phba, cmdiocb, rspiocb); @@ -1702,8 +1702,8 @@ lpfc_cmpl_ct_cmd_rnn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, outp = cmdiocb->rsp_dmabuf; CTrsp = (struct lpfc_sli_ct_request *) outp->virt; - if (CTrsp->CommandResponse.bits.CmdRsp == - be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) + if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) == + SLI_CT_RESPONSE_FS_ACC) vport->ct_flags |= FC_CT_RNN_ID; } lpfc_cmpl_ct(phba, cmdiocb, rspiocb); @@ -1723,8 +1723,8 @@ lpfc_cmpl_ct_cmd_rspn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, outp = cmdiocb->rsp_dmabuf; CTrsp = (struct lpfc_sli_ct_request *)outp->virt; - if (CTrsp->CommandResponse.bits.CmdRsp == - be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) + if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) == + SLI_CT_RESPONSE_FS_ACC) vport->ct_flags |= FC_CT_RSPN_ID; } lpfc_cmpl_ct(phba, cmdiocb, rspiocb); @@ -1744,8 +1744,8 @@ lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, outp = cmdiocb->rsp_dmabuf; CTrsp = (struct lpfc_sli_ct_request *) outp->virt; - if (CTrsp->CommandResponse.bits.CmdRsp == - be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) + if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) == + SLI_CT_RESPONSE_FS_ACC) vport->ct_flags |= FC_CT_RSNN_NN; } lpfc_cmpl_ct(phba, cmdiocb, rspiocb); @@ -1777,8 +1777,8 @@ lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, outp = cmdiocb->rsp_dmabuf; CTrsp = (struct lpfc_sli_ct_request *)outp->virt; - if (CTrsp->CommandResponse.bits.CmdRsp == - be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) + if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) == + SLI_CT_RESPONSE_FS_ACC) vport->ct_flags |= FC_CT_RFF_ID; } lpfc_cmpl_ct(phba, cmdiocb, rspiocb); @@ -2217,8 +2217,8 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_dmabuf *outp = cmdiocb->rsp_dmabuf; struct lpfc_sli_ct_request *CTcmd = inp->virt; struct lpfc_sli_ct_request *CTrsp = outp->virt; - uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp; - uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp; + __be16 fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp; + __be16 fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp; struct lpfc_nodelist *ndlp, *free_ndlp = NULL; uint32_t latt, cmd, err; u32 ulp_status = get_job_ulpstatus(phba, rspiocb); @@ -2278,7 +2278,7 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* Check for a CT LS_RJT response */ cmd = be16_to_cpu(fdmi_cmd); - if (fdmi_rsp == cpu_to_be16(SLI_CT_RESPONSE_FS_RJT)) { + if (be16_to_cpu(fdmi_rsp) == SLI_CT_RESPONSE_FS_RJT) { /* FDMI rsp failed */ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY | LOG_ELS, "0220 FDMI cmd failed FS_RJT Data: x%x", cmd); @@ -3110,7 +3110,7 @@ lpfc_fdmi_vendor_attr_mi(struct lpfc_vport *vport, void *attr) } /* RHBA attribute jump table */ -int (*lpfc_fdmi_hba_action[]) +static int (*lpfc_fdmi_hba_action[]) (struct lpfc_vport *vport, void *attrbuf) = { /* Action routine Mask bit Attribute type */ lpfc_fdmi_hba_attr_wwnn, /* bit0 RHBA_NODENAME */ @@ -3134,7 +3134,7 @@ int (*lpfc_fdmi_hba_action[]) }; /* RPA / RPRT attribute jump table */ -int (*lpfc_fdmi_port_action[]) +static int (*lpfc_fdmi_port_action[]) (struct lpfc_vport *vport, void *attrbuf) = { /* Action routine Mask bit Attribute type */ lpfc_fdmi_port_attr_fc4type, /* bit0 RPRT_SUPPORT_FC4_TYPES */ @@ -3570,7 +3570,7 @@ lpfc_cmpl_ct_cmd_vmid(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_dmabuf *outp = cmdiocb->rsp_dmabuf; struct lpfc_sli_ct_request *ctcmd = inp->virt; struct lpfc_sli_ct_request *ctrsp = outp->virt; - u16 rsp = ctrsp->CommandResponse.bits.CmdRsp; + __be16 rsp = ctrsp->CommandResponse.bits.CmdRsp; struct app_id_object *app; struct lpfc_nodelist *ndlp = cmdiocb->ndlp; u32 cmd, hash, bucket; @@ -3587,7 +3587,7 @@ lpfc_cmpl_ct_cmd_vmid(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, goto free_res; } /* Check for a CT LS_RJT response */ - if (rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { + if (be16_to_cpu(rsp) == SLI_CT_RESPONSE_FS_RJT) { if (cmd != SLI_CTAS_DALLAPP_ID) lpfc_printf_vlog(vport, KERN_DEBUG, LOG_DISCOVERY, "3306 VMID FS_RJT Data: x%x x%x x%x\n", @@ -3748,7 +3748,7 @@ lpfc_vmid_cmd(struct lpfc_vport *vport, rap->obj[0].entity_id_len = vmid->vmid_len; memcpy(rap->obj[0].entity_id, vmid->host_vmid, vmid->vmid_len); size = RAPP_IDENT_OFFSET + - sizeof(struct lpfc_vmid_rapp_ident_list); + struct_size(rap, obj, be32_to_cpu(rap->no_of_objects)); retry = 1; break; @@ -3767,7 +3767,7 @@ lpfc_vmid_cmd(struct lpfc_vport *vport, dap->obj[0].entity_id_len = vmid->vmid_len; memcpy(dap->obj[0].entity_id, vmid->host_vmid, vmid->vmid_len); size = DAPP_IDENT_OFFSET + - sizeof(struct lpfc_vmid_dapp_ident_list); + struct_size(dap, obj, be32_to_cpu(dap->no_of_objects)); write_lock(&vport->vmid_lock); vmid->flag &= ~LPFC_VMID_REGISTERED; write_unlock(&vport->vmid_lock); diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index bdf34af4ef36..7f9b221e7c34 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -2259,11 +2259,15 @@ lpfc_debugfs_ras_log_open(struct inode *inode, struct file *file) goto out; } spin_unlock_irq(&phba->hbalock); - debug = kmalloc(sizeof(*debug), GFP_KERNEL); + + if (check_mul_overflow(LPFC_RAS_MIN_BUFF_POST_SIZE, + phba->cfg_ras_fwlog_buffsize, &size)) + goto out; + + debug = kzalloc(sizeof(*debug), GFP_KERNEL); if (!debug) goto out; - size = LPFC_RAS_MIN_BUFF_POST_SIZE * phba->cfg_ras_fwlog_buffsize; debug->buffer = vmalloc(size); if (!debug->buffer) goto free_debug; diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 6a15f879e517..2bad9954c355 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -5205,14 +5205,9 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb) * * This routine is the completion callback function to the Logout (LOGO) * Accept (ACC) Response ELS command. This routine is invoked to indicate - * the completion of the LOGO process. It invokes the lpfc_nlp_not_used() to - * release the ndlp if it has the last reference remaining (reference count - * is 1). If succeeded (meaning ndlp released), it sets the iocb ndlp - * field to NULL to inform the following lpfc_els_free_iocb() routine no - * ndlp reference count needs to be decremented. Otherwise, the ndlp - * reference use-count shall be decremented by the lpfc_els_free_iocb() - * routine. Finally, the lpfc_els_free_iocb() is invoked to release the - * IOCB data structure. + * the completion of the LOGO process. If the node has transitioned to NPR, + * this routine unregisters the RPI if it is still registered. The + * lpfc_els_free_iocb() is invoked to release the IOCB data structure. **/ static void lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, @@ -5253,19 +5248,9 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, (ndlp->nlp_last_elscmd == ELS_CMD_PLOGI)) goto out; - /* NPort Recovery mode or node is just allocated */ - if (!lpfc_nlp_not_used(ndlp)) { - /* A LOGO is completing and the node is in NPR state. - * Just unregister the RPI because the node is still - * required. - */ + if (ndlp->nlp_flag & NLP_RPI_REGISTERED) lpfc_unreg_rpi(vport, ndlp); - } else { - /* Indicate the node has already released, should - * not reference to it from within lpfc_els_free_iocb. - */ - cmdiocb->ndlp = NULL; - } + } out: /* @@ -5285,9 +5270,8 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, * RPI (Remote Port Index) mailbox command to the @phba. It simply releases * the associated lpfc Direct Memory Access (DMA) buffer back to the pool and * decrements the ndlp reference count held for this completion callback - * function. After that, it invokes the lpfc_nlp_not_used() to check - * whether there is only one reference left on the ndlp. If so, it will - * perform one more decrement and trigger the release of the ndlp. + * function. After that, it invokes the lpfc_drop_node to check + * whether it is appropriate to release the node. **/ void lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) @@ -5468,9 +5452,19 @@ out: ndlp->nlp_flag &= ~NLP_RELEASE_RPI; spin_unlock_irq(&ndlp->lock); } + lpfc_drop_node(vport, ndlp); + } else if (ndlp->nlp_state != NLP_STE_PLOGI_ISSUE && + ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE && + ndlp->nlp_state != NLP_STE_PRLI_ISSUE) { + /* Drop ndlp if there is no planned or outstanding + * issued PRLI. + * + * In cases when the ndlp is acting as both an initiator + * and target function, let our issued PRLI determine + * the final ndlp kref drop. + */ + lpfc_drop_node(vport, ndlp); } - - lpfc_drop_node(vport, ndlp); } /* Release the originating I/O reference. */ diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 5ba3a9ad9501..499849b58ee4 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -458,11 +458,9 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) if (ndlp->nlp_type & NLP_FABRIC) { spin_lock_irqsave(&ndlp->lock, iflags); - /* In massive vport configuration settings or when the FLOGI - * completes with a sequence timeout, it's possible - * dev_loss_tmo fired during node recovery. The driver has to - * account for this race to allow for recovery and keep - * the reference counting correct. + /* The driver has to account for a race between any fabric + * node that's in recovery when dev_loss_tmo expires. When this + * happens, the driver has to allow node recovery. */ switch (ndlp->nlp_DID) { case Fabric_DID: @@ -489,6 +487,17 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ndlp->nlp_state <= NLP_STE_REG_LOGIN_ISSUE) recovering = true; break; + default: + /* Ensure the nlp_DID at least has the correct prefix. + * The fabric domain controller's last three nibbles + * vary so we handle it in the default case. + */ + if (ndlp->nlp_DID & Fabric_DID_MASK) { + if (ndlp->nlp_state >= NLP_STE_PLOGI_ISSUE && + ndlp->nlp_state <= NLP_STE_REG_LOGIN_ISSUE) + recovering = true; + } + break; } spin_unlock_irqrestore(&ndlp->lock, iflags); @@ -556,6 +565,9 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); } + spin_lock_irqsave(&ndlp->lock, iflags); + ndlp->nlp_flag &= ~NLP_IN_DEV_LOSS; + spin_unlock_irqrestore(&ndlp->lock, iflags); /* If we are devloss, but we are in the process of rediscovering the * ndlp, don't issue a NLP_EVT_DEVICE_RM event. @@ -565,9 +577,6 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) return fcf_inuse; } - spin_lock_irqsave(&ndlp->lock, iflags); - ndlp->nlp_flag &= ~NLP_IN_DEV_LOSS; - spin_unlock_irqrestore(&ndlp->lock, iflags); if (!(ndlp->fc4_xpt_flags & NVME_XPT_REGD)) lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); @@ -4333,13 +4342,14 @@ out: /* If the node is not registered with the scsi or nvme * transport, remove the fabric node. The failed reg_login - * is terminal. + * is terminal and forces the removal of the last node + * reference. */ if (!(ndlp->fc4_xpt_flags & (SCSI_XPT_REGD | NVME_XPT_REGD))) { spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; spin_unlock_irq(&ndlp->lock); - lpfc_nlp_not_used(ndlp); + lpfc_nlp_put(ndlp); } if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { @@ -4497,14 +4507,6 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) if (vport->load_flag & FC_UNLOADING) return; - /* - * Disassociate any older association between this ndlp and rport - */ - if (ndlp->rport) { - rdata = ndlp->rport->dd_data; - rdata->pnode = NULL; - } - ndlp->rport = rport = fc_remote_port_add(shost, 0, &rport_ids); if (!rport) { dev_printk(KERN_WARNING, &phba->pcidev->dev, @@ -4835,7 +4837,7 @@ lpfc_nlp_state_name(char *buffer, size_t size, int state) }; if (state < NLP_STE_MAX_STATE && states[state]) - strlcpy(buffer, states[state], size); + strscpy(buffer, states[state], size); else snprintf(buffer, size, "unknown (%d)", state); return buffer; @@ -6704,25 +6706,6 @@ lpfc_nlp_put(struct lpfc_nodelist *ndlp) return ndlp ? kref_put(&ndlp->kref, lpfc_nlp_release) : 0; } -/* This routine free's the specified nodelist if it is not in use - * by any other discovery thread. This routine returns 1 if the - * ndlp has been freed. A return value of 0 indicates the ndlp is - * not yet been released. - */ -int -lpfc_nlp_not_used(struct lpfc_nodelist *ndlp) -{ - lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE, - "node not used: did:x%x flg:x%x refcnt:x%x", - ndlp->nlp_DID, ndlp->nlp_flag, - kref_read(&ndlp->kref)); - - if (kref_read(&ndlp->kref) == 1) - if (lpfc_nlp_put(ndlp)) - return 1; - return 0; -} - /** * lpfc_fcf_inuse - Check if FCF can be unregistered. * @phba: Pointer to hba context object. diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 19b2d2754f32..663755842e4a 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -86,8 +86,8 @@ union CtRevisionId { union CtCommandResponse { /* Structure is in Big Endian format */ struct { - uint32_t CmdRsp:16; - uint32_t Size:16; + __be16 CmdRsp; + __be16 Size; } bits; uint32_t word; }; @@ -124,7 +124,7 @@ struct lpfc_sli_ct_request { #define LPFC_CT_PREAMBLE 20 /* Size of CTReq + 4 up to here */ union { - uint32_t PortID; + __be32 PortID; struct gid { uint8_t PortType; /* for GID_PT requests */ #define GID_PT_N_PORT 1 @@ -1408,19 +1408,19 @@ struct entity_id_object { }; struct app_id_object { - uint32_t port_id; - uint32_t app_id; + __be32 port_id; + __be32 app_id; struct entity_id_object obj; }; struct lpfc_vmid_rapp_ident_list { - uint32_t no_of_objects; - struct entity_id_object obj[1]; + __be32 no_of_objects; + struct entity_id_object obj[]; }; struct lpfc_vmid_dapp_ident_list { - uint32_t no_of_objects; - struct entity_id_object obj[1]; + __be32 no_of_objects; + struct entity_id_object obj[]; }; #define GALLAPPIA_ID_LAST 0x80 @@ -1512,7 +1512,7 @@ struct lpfc_fdmi_hba_ident { * Registered Port List Format */ struct lpfc_fdmi_reg_port_list { - uint32_t EntryCnt; + __be32 EntryCnt; struct lpfc_fdmi_port_entry pe; } __packed; diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 58fa39c403a0..5d4f9f27084d 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -395,9 +395,6 @@ struct lpfc_cqe { #define CQE_STATUS_NEED_BUFF_ENTRY 0xf #define CQE_STATUS_DI_ERROR 0x16 -/* Used when mapping CQE status to IOCB */ -#define LPFC_IOCB_STATUS_MASK 0xf - /* Status returned by hardware (valid only if status = CQE_STATUS_SUCCESS). */ #define CQE_HW_STATUS_NO_ERR 0x0 #define CQE_HW_STATUS_UNDERRUN 0x1 @@ -536,9 +533,9 @@ struct sli4_wcqe_xri_aborted { /* completion queue entry structure for rqe completion */ struct lpfc_rcqe { uint32_t word0; -#define lpfc_rcqe_bindex_SHIFT 16 -#define lpfc_rcqe_bindex_MASK 0x0000FFF -#define lpfc_rcqe_bindex_WORD word0 +#define lpfc_rcqe_iv_SHIFT 31 +#define lpfc_rcqe_iv_MASK 0x00000001 +#define lpfc_rcqe_iv_WORD word0 #define lpfc_rcqe_status_SHIFT 8 #define lpfc_rcqe_status_MASK 0x000000FF #define lpfc_rcqe_status_WORD word0 @@ -546,6 +543,7 @@ struct lpfc_rcqe { #define FC_STATUS_RQ_BUF_LEN_EXCEEDED 0x11 /* payload truncated */ #define FC_STATUS_INSUFF_BUF_NEED_BUF 0x12 /* Insufficient buffers */ #define FC_STATUS_INSUFF_BUF_FRM_DISC 0x13 /* Frame Discard */ +#define FC_STATUS_RQ_DMA_FAILURE 0x14 /* DMA failure */ uint32_t word1; #define lpfc_rcqe_fcf_id_v1_SHIFT 0 #define lpfc_rcqe_fcf_id_v1_MASK 0x0000003F @@ -4813,8 +4811,8 @@ struct cmf_sync_wqe { #define cmf_sync_cqid_WORD word11 uint32_t read_bytes; uint32_t word13; -#define cmf_sync_period_SHIFT 16 -#define cmf_sync_period_MASK 0x0000ffff +#define cmf_sync_period_SHIFT 24 +#define cmf_sync_period_MASK 0x000000ff #define cmf_sync_period_WORD word13 uint32_t word14; uint32_t word15; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 867b4c788f08..3221a934066b 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -101,6 +101,7 @@ static struct scsi_transport_template *lpfc_vport_transport_template = NULL; static DEFINE_IDR(lpfc_hba_index); #define LPFC_NVMET_BUF_POST 254 static int lpfc_vmid_res_alloc(struct lpfc_hba *phba, struct lpfc_vport *vport); +static void lpfc_cgn_update_tstamp(struct lpfc_hba *phba, struct lpfc_cgn_ts *ts); /** * lpfc_config_port_prep - Perform lpfc initialization prior to config port @@ -1279,7 +1280,7 @@ lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) /* * lpfc_idle_stat_delay_work - idle_stat tracking * - * This routine tracks per-cq idle_stat and determines polling decisions. + * This routine tracks per-eq idle_stat and determines polling decisions. * * Return codes: * None @@ -1290,7 +1291,7 @@ lpfc_idle_stat_delay_work(struct work_struct *work) struct lpfc_hba *phba = container_of(to_delayed_work(work), struct lpfc_hba, idle_stat_delay_work); - struct lpfc_queue *cq; + struct lpfc_queue *eq; struct lpfc_sli4_hdw_queue *hdwq; struct lpfc_idle_stat *idle_stat; u32 i, idle_percent; @@ -1306,10 +1307,10 @@ lpfc_idle_stat_delay_work(struct work_struct *work) for_each_present_cpu(i) { hdwq = &phba->sli4_hba.hdwq[phba->sli4_hba.cpu_map[i].hdwq]; - cq = hdwq->io_cq; + eq = hdwq->hba_eq; - /* Skip if we've already handled this cq's primary CPU */ - if (cq->chann != i) + /* Skip if we've already handled this eq's primary CPU */ + if (eq->chann != i) continue; idle_stat = &phba->sli4_hba.idle_stat[i]; @@ -1333,9 +1334,9 @@ lpfc_idle_stat_delay_work(struct work_struct *work) idle_percent = 100 - idle_percent; if (idle_percent < 15) - cq->poll_mode = LPFC_QUEUE_WORK; + eq->poll_mode = LPFC_QUEUE_WORK; else - cq->poll_mode = LPFC_IRQ_POLL; + eq->poll_mode = LPFC_THREADED_IRQ; idle_stat->prev_idle = wall_idle; idle_stat->prev_wall = wall; @@ -3197,6 +3198,7 @@ lpfc_cmf_stop(struct lpfc_hba *phba) "6221 Stop CMF / Cancel Timer\n"); /* Cancel the CMF timer */ + hrtimer_cancel(&phba->cmf_stats_timer); hrtimer_cancel(&phba->cmf_timer); /* Zero CMF counters */ @@ -3283,7 +3285,10 @@ lpfc_cmf_start(struct lpfc_hba *phba) phba->cmf_timer_cnt = 0; hrtimer_start(&phba->cmf_timer, - ktime_set(0, LPFC_CMF_INTERVAL * 1000000), + ktime_set(0, LPFC_CMF_INTERVAL * NSEC_PER_MSEC), + HRTIMER_MODE_REL); + hrtimer_start(&phba->cmf_stats_timer, + ktime_set(0, LPFC_SEC_MIN * NSEC_PER_SEC), HRTIMER_MODE_REL); /* Setup for latency check in IO cmpl routines */ ktime_get_real_ts64(&phba->cmf_latency); @@ -4357,6 +4362,7 @@ lpfc_io_buf_replenish(struct lpfc_hba *phba, struct list_head *cbuf) struct lpfc_sli4_hdw_queue *qp; struct lpfc_io_buf *lpfc_cmd; int idx, cnt; + unsigned long iflags; qp = phba->sli4_hba.hdwq; cnt = 0; @@ -4371,12 +4377,13 @@ lpfc_io_buf_replenish(struct lpfc_hba *phba, struct list_head *cbuf) lpfc_cmd->hdwq_no = idx; lpfc_cmd->hdwq = qp; lpfc_cmd->cur_iocbq.cmd_cmpl = NULL; - spin_lock(&qp->io_buf_list_put_lock); + spin_lock_irqsave(&qp->io_buf_list_put_lock, iflags); list_add_tail(&lpfc_cmd->list, &qp->lpfc_io_buf_list_put); qp->put_io_bufs++; qp->total_io_bufs++; - spin_unlock(&qp->io_buf_list_put_lock); + spin_unlock_irqrestore(&qp->io_buf_list_put_lock, + iflags); } } return cnt; @@ -5593,81 +5600,74 @@ void lpfc_cgn_update_stat(struct lpfc_hba *phba, uint32_t dtag) { struct lpfc_cgn_info *cp; - struct tm broken; - struct timespec64 cur_time; - u32 cnt; u32 value; /* Make sure we have a congestion info buffer */ if (!phba->cgn_i) return; cp = (struct lpfc_cgn_info *)phba->cgn_i->virt; - ktime_get_real_ts64(&cur_time); - time64_to_tm(cur_time.tv_sec, 0, &broken); /* Update congestion statistics */ switch (dtag) { case ELS_DTAG_LNK_INTEGRITY: - cnt = le32_to_cpu(cp->link_integ_notification); - cnt++; - cp->link_integ_notification = cpu_to_le32(cnt); - - cp->cgn_stat_lnk_month = broken.tm_mon + 1; - cp->cgn_stat_lnk_day = broken.tm_mday; - cp->cgn_stat_lnk_year = broken.tm_year - 100; - cp->cgn_stat_lnk_hour = broken.tm_hour; - cp->cgn_stat_lnk_min = broken.tm_min; - cp->cgn_stat_lnk_sec = broken.tm_sec; + le32_add_cpu(&cp->link_integ_notification, 1); + lpfc_cgn_update_tstamp(phba, &cp->stat_lnk); break; case ELS_DTAG_DELIVERY: - cnt = le32_to_cpu(cp->delivery_notification); - cnt++; - cp->delivery_notification = cpu_to_le32(cnt); - - cp->cgn_stat_del_month = broken.tm_mon + 1; - cp->cgn_stat_del_day = broken.tm_mday; - cp->cgn_stat_del_year = broken.tm_year - 100; - cp->cgn_stat_del_hour = broken.tm_hour; - cp->cgn_stat_del_min = broken.tm_min; - cp->cgn_stat_del_sec = broken.tm_sec; + le32_add_cpu(&cp->delivery_notification, 1); + lpfc_cgn_update_tstamp(phba, &cp->stat_delivery); break; case ELS_DTAG_PEER_CONGEST: - cnt = le32_to_cpu(cp->cgn_peer_notification); - cnt++; - cp->cgn_peer_notification = cpu_to_le32(cnt); - - cp->cgn_stat_peer_month = broken.tm_mon + 1; - cp->cgn_stat_peer_day = broken.tm_mday; - cp->cgn_stat_peer_year = broken.tm_year - 100; - cp->cgn_stat_peer_hour = broken.tm_hour; - cp->cgn_stat_peer_min = broken.tm_min; - cp->cgn_stat_peer_sec = broken.tm_sec; + le32_add_cpu(&cp->cgn_peer_notification, 1); + lpfc_cgn_update_tstamp(phba, &cp->stat_peer); break; case ELS_DTAG_CONGESTION: - cnt = le32_to_cpu(cp->cgn_notification); - cnt++; - cp->cgn_notification = cpu_to_le32(cnt); - - cp->cgn_stat_cgn_month = broken.tm_mon + 1; - cp->cgn_stat_cgn_day = broken.tm_mday; - cp->cgn_stat_cgn_year = broken.tm_year - 100; - cp->cgn_stat_cgn_hour = broken.tm_hour; - cp->cgn_stat_cgn_min = broken.tm_min; - cp->cgn_stat_cgn_sec = broken.tm_sec; + le32_add_cpu(&cp->cgn_notification, 1); + lpfc_cgn_update_tstamp(phba, &cp->stat_fpin); } if (phba->cgn_fpin_frequency && phba->cgn_fpin_frequency != LPFC_FPIN_INIT_FREQ) { value = LPFC_CGN_TIMER_TO_MIN / phba->cgn_fpin_frequency; cp->cgn_stat_npm = value; } + value = lpfc_cgn_calc_crc32(cp, LPFC_CGN_INFO_SZ, LPFC_CGN_CRC32_SEED); cp->cgn_info_crc = cpu_to_le32(value); } /** - * lpfc_cgn_save_evt_cnt - Save data into registered congestion buffer + * lpfc_cgn_update_tstamp - Update cmf timestamp * @phba: pointer to lpfc hba data structure. + * @ts: structure to write the timestamp to. + */ +void +lpfc_cgn_update_tstamp(struct lpfc_hba *phba, struct lpfc_cgn_ts *ts) +{ + struct timespec64 cur_time; + struct tm tm_val; + + ktime_get_real_ts64(&cur_time); + time64_to_tm(cur_time.tv_sec, 0, &tm_val); + + ts->month = tm_val.tm_mon + 1; + ts->day = tm_val.tm_mday; + ts->year = tm_val.tm_year - 100; + ts->hour = tm_val.tm_hour; + ts->minute = tm_val.tm_min; + ts->second = tm_val.tm_sec; + + lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT, + "2646 Updated CMF timestamp : " + "%u/%u/%u %u:%u:%u\n", + ts->day, ts->month, + ts->year, ts->hour, + ts->minute, ts->second); +} + +/** + * lpfc_cmf_stats_timer - Save data into registered congestion buffer + * @timer: Timer cookie to access lpfc private data * * Save the congestion event data every minute. * On the hour collapse all the minute data into hour data. Every day @@ -5675,12 +5675,11 @@ lpfc_cgn_update_stat(struct lpfc_hba *phba, uint32_t dtag) * and fabrc congestion event counters that will be saved out * to the registered congestion buffer every minute. */ -static void -lpfc_cgn_save_evt_cnt(struct lpfc_hba *phba) +static enum hrtimer_restart +lpfc_cmf_stats_timer(struct hrtimer *timer) { + struct lpfc_hba *phba; struct lpfc_cgn_info *cp; - struct tm broken; - struct timespec64 cur_time; uint32_t i, index; uint16_t value, mvalue; uint64_t bps; @@ -5691,21 +5690,18 @@ lpfc_cgn_save_evt_cnt(struct lpfc_hba *phba) __le32 *lptr; __le16 *mptr; + phba = container_of(timer, struct lpfc_hba, cmf_stats_timer); /* Make sure we have a congestion info buffer */ if (!phba->cgn_i) - return; + return HRTIMER_NORESTART; cp = (struct lpfc_cgn_info *)phba->cgn_i->virt; - if (time_before(jiffies, phba->cgn_evt_timestamp)) - return; phba->cgn_evt_timestamp = jiffies + msecs_to_jiffies(LPFC_CGN_TIMER_TO_MIN); phba->cgn_evt_minute++; /* We should get to this point in the routine on 1 minute intervals */ - - ktime_get_real_ts64(&cur_time); - time64_to_tm(cur_time.tv_sec, 0, &broken); + lpfc_cgn_update_tstamp(phba, &cp->base_time); if (phba->cgn_fpin_frequency && phba->cgn_fpin_frequency != LPFC_FPIN_INIT_FREQ) { @@ -5858,31 +5854,6 @@ lpfc_cgn_save_evt_cnt(struct lpfc_hba *phba) index = 0; } - /* Anytime we overwrite daily index 0, after we wrap, - * we will be overwriting the oldest day, so we must - * update the congestion data start time for that day. - * That start time should have previously been saved after - * we wrote the last days worth of data. - */ - if ((phba->hba_flag & HBA_CGN_DAY_WRAP) && index == 0) { - time64_to_tm(phba->cgn_daily_ts.tv_sec, 0, &broken); - - cp->cgn_info_month = broken.tm_mon + 1; - cp->cgn_info_day = broken.tm_mday; - cp->cgn_info_year = broken.tm_year - 100; - cp->cgn_info_hour = broken.tm_hour; - cp->cgn_info_minute = broken.tm_min; - cp->cgn_info_second = broken.tm_sec; - - lpfc_printf_log - (phba, KERN_INFO, LOG_CGN_MGMT, - "2646 CGNInfo idx0 Start Time: " - "%d/%d/%d %d:%d:%d\n", - cp->cgn_info_day, cp->cgn_info_month, - cp->cgn_info_year, cp->cgn_info_hour, - cp->cgn_info_minute, cp->cgn_info_second); - } - dvalue = 0; wvalue = 0; lvalue = 0; @@ -5916,15 +5887,6 @@ lpfc_cgn_save_evt_cnt(struct lpfc_hba *phba) "2420 Congestion Info - daily (%d): " "%d %d %d %d %d\n", index, dvalue, wvalue, lvalue, mvalue, avalue); - - /* We just wrote LPFC_MAX_CGN_DAYS of data, - * so we are wrapped on any data after this. - * Save this as the start time for the next day. - */ - if (index == (LPFC_MAX_CGN_DAYS - 1)) { - phba->hba_flag |= HBA_CGN_DAY_WRAP; - ktime_get_real_ts64(&phba->cgn_daily_ts); - } } /* Use the frequency found in the last rcv'ed FPIN */ @@ -5935,6 +5897,10 @@ lpfc_cgn_save_evt_cnt(struct lpfc_hba *phba) lvalue = lpfc_cgn_calc_crc32(cp, LPFC_CGN_INFO_SZ, LPFC_CGN_CRC32_SEED); cp->cgn_info_crc = cpu_to_le32(lvalue); + + hrtimer_forward_now(timer, ktime_set(0, LPFC_SEC_MIN * NSEC_PER_SEC)); + + return HRTIMER_RESTART; } /** @@ -6065,13 +6031,6 @@ lpfc_cmf_timer(struct hrtimer *timer) if (ms && ms < LPFC_CMF_INTERVAL) { cnt = div_u64(total, ms); /* bytes per ms */ cnt *= LPFC_CMF_INTERVAL; /* what total should be */ - - /* If the timeout is scheduled to be shorter, - * this value may skew the data, so cap it at mbpi. - */ - if ((phba->hba_flag & HBA_SHORT_CMF) && cnt > mbpi) - cnt = mbpi; - extra = cnt - total; } lpfc_issue_cmf_sync_wqe(phba, LPFC_CMF_INTERVAL, total + extra); @@ -6141,34 +6100,6 @@ lpfc_cmf_timer(struct hrtimer *timer) } phba->rx_block_cnt += div_u64(rcv, 512); /* save 512 byte block cnt */ - /* Each minute save Fabric and Driver congestion information */ - lpfc_cgn_save_evt_cnt(phba); - - phba->hba_flag &= ~HBA_SHORT_CMF; - - /* Since we need to call lpfc_cgn_save_evt_cnt every minute, on the - * minute, adjust our next timer interval, if needed, to ensure a - * 1 minute granularity when we get the next timer interrupt. - */ - if (time_after(jiffies + msecs_to_jiffies(LPFC_CMF_INTERVAL), - phba->cgn_evt_timestamp)) { - timer_interval = jiffies_to_msecs(phba->cgn_evt_timestamp - - jiffies); - if (timer_interval <= 0) - timer_interval = LPFC_CMF_INTERVAL; - else - phba->hba_flag |= HBA_SHORT_CMF; - - /* If we adjust timer_interval, max_bytes_per_interval - * needs to be adjusted as well. - */ - phba->cmf_link_byte_count = div_u64(phba->cmf_max_line_rate * - timer_interval, 1000); - if (phba->cmf_active_mode == LPFC_CFG_MONITOR) - phba->cmf_max_bytes_per_interval = - phba->cmf_link_byte_count; - } - /* Since total_bytes has already been zero'ed, its okay to unblock * after max_bytes_per_interval is setup. */ @@ -8014,6 +7945,9 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) /* CMF congestion timer */ hrtimer_init(&phba->cmf_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); phba->cmf_timer.function = lpfc_cmf_timer; + /* CMF 1 minute stats collection timer */ + hrtimer_init(&phba->cmf_stats_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + phba->cmf_stats_timer.function = lpfc_cmf_stats_timer; /* * Control structure for handling external multi-buffer mailbox @@ -13117,8 +13051,10 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba) } eqhdl->irq = rc; - rc = request_irq(eqhdl->irq, &lpfc_sli4_hba_intr_handler, 0, - name, eqhdl); + rc = request_threaded_irq(eqhdl->irq, + &lpfc_sli4_hba_intr_handler, + &lpfc_sli4_hba_intr_handler_th, + IRQF_ONESHOT, name, eqhdl); if (rc) { lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, "0486 MSI-X fast-path (%d) " @@ -13521,6 +13457,7 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba) struct pci_dev *pdev = phba->pcidev; lpfc_stop_hba_timers(phba); + hrtimer_cancel(&phba->cmf_stats_timer); hrtimer_cancel(&phba->cmf_timer); if (phba->pport) @@ -13645,8 +13582,6 @@ void lpfc_init_congestion_buf(struct lpfc_hba *phba) { struct lpfc_cgn_info *cp; - struct timespec64 cmpl_time; - struct tm broken; uint16_t size; uint32_t crc; @@ -13666,11 +13601,10 @@ lpfc_init_congestion_buf(struct lpfc_hba *phba) atomic_set(&phba->cgn_latency_evt_cnt, 0); atomic64_set(&phba->cgn_latency_evt, 0); phba->cgn_evt_minute = 0; - phba->hba_flag &= ~HBA_CGN_DAY_WRAP; memset(cp, 0xff, offsetof(struct lpfc_cgn_info, cgn_stat)); cp->cgn_info_size = cpu_to_le16(LPFC_CGN_INFO_SZ); - cp->cgn_info_version = LPFC_CGN_INFO_V3; + cp->cgn_info_version = LPFC_CGN_INFO_V4; /* cgn parameters */ cp->cgn_info_mode = phba->cgn_p.cgn_param_mode; @@ -13678,22 +13612,7 @@ lpfc_init_congestion_buf(struct lpfc_hba *phba) cp->cgn_info_level1 = phba->cgn_p.cgn_param_level1; cp->cgn_info_level2 = phba->cgn_p.cgn_param_level2; - ktime_get_real_ts64(&cmpl_time); - time64_to_tm(cmpl_time.tv_sec, 0, &broken); - - cp->cgn_info_month = broken.tm_mon + 1; - cp->cgn_info_day = broken.tm_mday; - cp->cgn_info_year = broken.tm_year - 100; /* relative to 2000 */ - cp->cgn_info_hour = broken.tm_hour; - cp->cgn_info_minute = broken.tm_min; - cp->cgn_info_second = broken.tm_sec; - - lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT | LOG_INIT, - "2643 CGNInfo Init: Start Time " - "%d/%d/%d %d:%d:%d\n", - cp->cgn_info_day, cp->cgn_info_month, - cp->cgn_info_year, cp->cgn_info_hour, - cp->cgn_info_minute, cp->cgn_info_second); + lpfc_cgn_update_tstamp(phba, &cp->base_time); /* Fill in default LUN qdepth */ if (phba->pport) { @@ -13716,8 +13635,6 @@ void lpfc_init_congestion_stat(struct lpfc_hba *phba) { struct lpfc_cgn_info *cp; - struct timespec64 cmpl_time; - struct tm broken; uint32_t crc; lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT, @@ -13729,22 +13646,7 @@ lpfc_init_congestion_stat(struct lpfc_hba *phba) cp = (struct lpfc_cgn_info *)phba->cgn_i->virt; memset(&cp->cgn_stat, 0, sizeof(cp->cgn_stat)); - ktime_get_real_ts64(&cmpl_time); - time64_to_tm(cmpl_time.tv_sec, 0, &broken); - - cp->cgn_stat_month = broken.tm_mon + 1; - cp->cgn_stat_day = broken.tm_mday; - cp->cgn_stat_year = broken.tm_year - 100; /* relative to 2000 */ - cp->cgn_stat_hour = broken.tm_hour; - cp->cgn_stat_minute = broken.tm_min; - - lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT | LOG_INIT, - "2647 CGNstat Init: Start Time " - "%d/%d/%d %d:%d\n", - cp->cgn_stat_day, cp->cgn_stat_month, - cp->cgn_stat_year, cp->cgn_stat_hour, - cp->cgn_stat_minute); - + lpfc_cgn_update_tstamp(phba, &cp->stat_start); crc = lpfc_cgn_calc_crc32(cp, LPFC_CGN_INFO_SZ, LPFC_CGN_CRC32_SEED); cp->cgn_info_crc = cpu_to_le32(crc); } @@ -14743,10 +14645,10 @@ lpfc_write_firmware(const struct firmware *fw, void *context) INIT_LIST_HEAD(&dma_buffer_list); lpfc_decode_firmware_rev(phba, fwrev, 1); if (strncmp(fwrev, image->revision, strnlen(image->revision, 16))) { - lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, - "3023 Updating Firmware, Current Version:%s " - "New Version:%s\n", - fwrev, image->revision); + lpfc_log_msg(phba, KERN_NOTICE, LOG_INIT | LOG_SLI, + "3023 Updating Firmware, Current Version:%s " + "New Version:%s\n", + fwrev, image->revision); for (i = 0; i < LPFC_MBX_WR_CONFIG_MAX_BDE; i++) { dmabuf = kzalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); @@ -14793,10 +14695,10 @@ lpfc_write_firmware(const struct firmware *fw, void *context) } rc = offset; } else - lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, - "3029 Skipped Firmware update, Current " - "Version:%s New Version:%s\n", - fwrev, image->revision); + lpfc_log_msg(phba, KERN_NOTICE, LOG_INIT | LOG_SLI, + "3029 Skipped Firmware update, Current " + "Version:%s New Version:%s\n", + fwrev, image->revision); release_out: list_for_each_entry_safe(dmabuf, next, &dma_buffer_list, list) { @@ -14808,11 +14710,11 @@ release_out: release_firmware(fw); out: if (rc < 0) - lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, - "3062 Firmware update error, status %d.\n", rc); + lpfc_log_msg(phba, KERN_ERR, LOG_INIT | LOG_SLI, + "3062 Firmware update error, status %d.\n", rc); else - lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, - "3024 Firmware update success: size %d.\n", rc); + lpfc_log_msg(phba, KERN_NOTICE, LOG_INIT | LOG_SLI, + "3024 Firmware update success: size %d.\n", rc); } /** diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h index b39cefcd8703..f896ec610433 100644 --- a/drivers/scsi/lpfc/lpfc_logmsg.h +++ b/drivers/scsi/lpfc/lpfc_logmsg.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2023 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2009 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -55,7 +55,7 @@ void lpfc_dbg_print(struct lpfc_hba *phba, const char *fmt, ...); /* generate message by verbose log setting or severity */ #define lpfc_vlog_msg(vport, level, mask, fmt, arg...) \ -{ if (((mask) & (vport)->cfg_log_verbose) || (level[1] <= '4')) \ +{ if (((mask) & (vport)->cfg_log_verbose) || (level[1] <= '5')) \ dev_printk(level, &((vport)->phba->pcidev)->dev, "%d:(%d):" \ fmt, (vport)->phba->brd_no, vport->vpi, ##arg); } @@ -64,7 +64,7 @@ do { \ { uint32_t log_verbose = (phba)->pport ? \ (phba)->pport->cfg_log_verbose : \ (phba)->cfg_log_verbose; \ - if (((mask) & log_verbose) || (level[1] <= '4')) \ + if (((mask) & log_verbose) || (level[1] <= '5')) \ dev_printk(level, &((phba)->pcidev)->dev, "%d:" \ fmt, phba->brd_no, ##arg); \ } \ diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index adda70423c77..8db7cb99903d 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -310,20 +310,20 @@ lpfc_nvme_handle_lsreq(struct lpfc_hba *phba, * for the LS request. **/ void -__lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport, +__lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport, struct lpfc_iocbq *cmdwqe, struct lpfc_wcqe_complete *wcqe) { struct nvmefc_ls_req *pnvme_lsreq; struct lpfc_dmabuf *buf_ptr; struct lpfc_nodelist *ndlp; - uint32_t status; + int status; pnvme_lsreq = cmdwqe->context_un.nvme_lsreq; ndlp = cmdwqe->ndlp; buf_ptr = cmdwqe->bpl_dmabuf; - status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK; + status = bf_get(lpfc_wcqe_c_status, wcqe); lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, "6047 NVMEx LS REQ x%px cmpl DID %x Xri: %x " @@ -343,14 +343,17 @@ __lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport, kfree(buf_ptr); cmdwqe->bpl_dmabuf = NULL; } - if (pnvme_lsreq->done) + if (pnvme_lsreq->done) { + if (status != CQE_STATUS_SUCCESS) + status = -ENXIO; pnvme_lsreq->done(pnvme_lsreq, status); - else + } else { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6046 NVMEx cmpl without done call back? " "Data x%px DID %x Xri: %x status %x\n", pnvme_lsreq, ndlp ? ndlp->nlp_DID : 0, cmdwqe->sli4_xritag, status); + } if (ndlp) { lpfc_nlp_put(ndlp); cmdwqe->ndlp = NULL; @@ -367,7 +370,7 @@ lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, uint32_t status; struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl; - status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK; + status = bf_get(lpfc_wcqe_c_status, wcqe); if (vport->localport) { lport = (struct lpfc_nvme_lport *)vport->localport->private; @@ -1040,7 +1043,7 @@ lpfc_nvme_io_cmd_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, nCmd->rcv_rsplen = LPFC_NVME_ERSP_LEN; nCmd->transferred_length = nCmd->payload_length; } else { - lpfc_ncmd->status = (status & LPFC_IOCB_STATUS_MASK); + lpfc_ncmd->status = status; lpfc_ncmd->result = (wcqe->parameter & IOERR_PARAM_MASK); /* For NVME, the only failure path that results in an @@ -1893,38 +1896,38 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, pnvme_rport->port_id, pnvme_fcreq); - /* If the hba is getting reset, this flag is set. It is - * cleared when the reset is complete and rings reestablished. - */ - spin_lock_irqsave(&phba->hbalock, flags); - /* driver queued commands are in process of being flushed */ - if (phba->hba_flag & HBA_IOQ_FLUSH) { - spin_unlock_irqrestore(&phba->hbalock, flags); - lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, - "6139 Driver in reset cleanup - flushing " - "NVME Req now. hba_flag x%x\n", - phba->hba_flag); - return; - } - lpfc_nbuf = freqpriv->nvme_buf; if (!lpfc_nbuf) { - spin_unlock_irqrestore(&phba->hbalock, flags); lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6140 NVME IO req has no matching lpfc nvme " "io buffer. Skipping abort req.\n"); return; } else if (!lpfc_nbuf->nvmeCmd) { - spin_unlock_irqrestore(&phba->hbalock, flags); lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6141 lpfc NVME IO req has no nvme_fcreq " "io buffer. Skipping abort req.\n"); return; } - nvmereq_wqe = &lpfc_nbuf->cur_iocbq; /* Guard against IO completion being called at same time */ - spin_lock(&lpfc_nbuf->buf_lock); + spin_lock_irqsave(&lpfc_nbuf->buf_lock, flags); + + /* If the hba is getting reset, this flag is set. It is + * cleared when the reset is complete and rings reestablished. + */ + spin_lock(&phba->hbalock); + /* driver queued commands are in process of being flushed */ + if (phba->hba_flag & HBA_IOQ_FLUSH) { + spin_unlock(&phba->hbalock); + spin_unlock_irqrestore(&lpfc_nbuf->buf_lock, flags); + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "6139 Driver in reset cleanup - flushing " + "NVME Req now. hba_flag x%x\n", + phba->hba_flag); + return; + } + + nvmereq_wqe = &lpfc_nbuf->cur_iocbq; /* * The lpfc_nbuf and the mapped nvme_fcreq in the driver's @@ -1971,8 +1974,8 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, ret_val = lpfc_sli4_issue_abort_iotag(phba, nvmereq_wqe, lpfc_nvme_abort_fcreq_cmpl); - spin_unlock(&lpfc_nbuf->buf_lock); - spin_unlock_irqrestore(&phba->hbalock, flags); + spin_unlock(&phba->hbalock); + spin_unlock_irqrestore(&lpfc_nbuf->buf_lock, flags); /* Make sure HBA is alive */ lpfc_issue_hb_tmo(phba); @@ -1998,8 +2001,8 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, return; out_unlock: - spin_unlock(&lpfc_nbuf->buf_lock); - spin_unlock_irqrestore(&phba->hbalock, flags); + spin_unlock(&phba->hbalock); + spin_unlock_irqrestore(&lpfc_nbuf->buf_lock, flags); return; } diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index 7517dd55fe91..dff4584d338b 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2023 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -300,7 +300,7 @@ __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, struct nvmefc_ls_rsp *ls_rsp = &axchg->ls_rsp; uint32_t status, result; - status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK; + status = bf_get(lpfc_wcqe_c_status, wcqe); result = wcqe->parameter; if (axchg->state != LPFC_NVME_STE_LS_RSP || axchg->entry_cnt != 2) { @@ -350,7 +350,7 @@ lpfc_nvmet_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, if (!phba->targetport) goto finish; - status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK; + status = bf_get(lpfc_wcqe_c_status, wcqe); result = wcqe->parameter; tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private; diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index e989f130434e..a62e091894f6 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -4026,7 +4026,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, struct lpfc_fast_path_event *fast_path_evt; struct Scsi_Host *shost; u32 logit = LOG_FCP; - u32 status, idx; + u32 idx; u32 lat; u8 wait_xb_clr = 0; @@ -4061,8 +4061,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, #endif shost = cmd->device->host; - status = bf_get(lpfc_wcqe_c_status, wcqe); - lpfc_cmd->status = (status & LPFC_IOCB_STATUS_MASK); + lpfc_cmd->status = bf_get(lpfc_wcqe_c_status, wcqe); lpfc_cmd->result = (wcqe->parameter & IOERR_PARAM_MASK); lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY; @@ -4104,11 +4103,6 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, } #endif if (unlikely(lpfc_cmd->status)) { - if (lpfc_cmd->status == IOSTAT_LOCAL_REJECT && - (lpfc_cmd->result & IOERR_DRVR_MASK)) - lpfc_cmd->status = IOSTAT_DRIVER_REJECT; - else if (lpfc_cmd->status >= IOSTAT_CNT) - lpfc_cmd->status = IOSTAT_DEFAULT; if (lpfc_cmd->status == IOSTAT_FCP_RSP_ERROR && !lpfc_cmd->fcp_rsp->rspStatus3 && (lpfc_cmd->fcp_rsp->rspStatus2 & RESID_UNDER) && @@ -4133,16 +4127,16 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, } switch (lpfc_cmd->status) { - case IOSTAT_SUCCESS: + case CQE_STATUS_SUCCESS: cmd->result = DID_OK << 16; break; - case IOSTAT_FCP_RSP_ERROR: + case CQE_STATUS_FCP_RSP_FAILURE: lpfc_handle_fcp_err(vport, lpfc_cmd, pwqeIn->wqe.fcp_iread.total_xfer_len - wcqe->total_data_placed); break; - case IOSTAT_NPORT_BSY: - case IOSTAT_FABRIC_BSY: + case CQE_STATUS_NPORT_BSY: + case CQE_STATUS_FABRIC_BSY: cmd->result = DID_TRANSPORT_DISRUPTED << 16; fast_path_evt = lpfc_alloc_fast_evt(phba); if (!fast_path_evt) @@ -4185,7 +4179,27 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, wcqe->total_data_placed, lpfc_cmd->cur_iocbq.iocb.ulpIoTag); break; - case IOSTAT_REMOTE_STOP: + case CQE_STATUS_DI_ERROR: + if (bf_get(lpfc_wcqe_c_bg_edir, wcqe)) + lpfc_cmd->result = IOERR_RX_DMA_FAILED; + else + lpfc_cmd->result = IOERR_TX_DMA_FAILED; + lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP | LOG_BG, + "9048 DI Error xri x%x status x%x DI ext " + "status x%x data placed x%x\n", + lpfc_cmd->cur_iocbq.sli4_xritag, + lpfc_cmd->status, wcqe->parameter, + wcqe->total_data_placed); + if (scsi_get_prot_op(cmd) != SCSI_PROT_NORMAL) { + /* BG enabled cmd. Parse BG error */ + lpfc_parse_bg_err(phba, lpfc_cmd, pwqeOut); + break; + } + cmd->result = DID_ERROR << 16; + lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, + "9040 DI Error on unprotected cmd\n"); + break; + case CQE_STATUS_REMOTE_STOP: if (ndlp) { /* This I/O was aborted by the target, we don't * know the rxid and because we did not send the @@ -4196,7 +4210,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, 0, 0); } fallthrough; - case IOSTAT_LOCAL_REJECT: + case CQE_STATUS_LOCAL_REJECT: if (lpfc_cmd->result & IOERR_DRVR_MASK) lpfc_cmd->status = IOSTAT_DRIVER_REJECT; if (lpfc_cmd->result == IOERR_ELXSEC_KEY_UNWRAP_ERROR || @@ -4217,24 +4231,6 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, cmd->result = DID_TRANSPORT_DISRUPTED << 16; break; } - if ((lpfc_cmd->result == IOERR_RX_DMA_FAILED || - lpfc_cmd->result == IOERR_TX_DMA_FAILED) && - status == CQE_STATUS_DI_ERROR) { - if (scsi_get_prot_op(cmd) != - SCSI_PROT_NORMAL) { - /* - * This is a response for a BG enabled - * cmd. Parse BG error - */ - lpfc_parse_bg_err(phba, lpfc_cmd, pwqeOut); - break; - } else { - lpfc_printf_vlog(vport, KERN_WARNING, - LOG_BG, - "9040 non-zero BGSTAT " - "on unprotected cmd\n"); - } - } lpfc_printf_vlog(vport, KERN_WARNING, logit, "9036 Local Reject FCP cmd x%x failed" " <%d/%lld> " @@ -4253,10 +4249,8 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, lpfc_cmd->cur_iocbq.iocb.ulpIoTag); fallthrough; default: - if (lpfc_cmd->status >= IOSTAT_CNT) - lpfc_cmd->status = IOSTAT_DEFAULT; cmd->result = DID_ERROR << 16; - lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR, + lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, "9037 FCP Completion Error: xri %x " "status x%x result x%x [x%x] " "placed x%x\n", @@ -4273,7 +4267,8 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, "x%x SNS x%x x%x LBA x%llx Data: x%x x%x\n", cmd->device->id, cmd->device->lun, cmd, cmd->result, *lp, *(lp + 3), - (u64)scsi_get_lba(cmd), + (cmd->device->sector_size) ? + (u64)scsi_get_lba(cmd) : 0, cmd->retries, scsi_get_resid(cmd)); } @@ -5009,7 +5004,6 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) return -ENODEV; } phba->lpfc_rampdown_queue_depth = lpfc_rampdown_queue_depth; - phba->lpfc_scsi_cmd_iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl; return 0; } diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 8693578888f1..58d10f8f75a7 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -82,7 +82,8 @@ static int lpfc_sli4_post_sgl_list(struct lpfc_hba *, struct list_head *, int); static void lpfc_sli4_hba_handle_eqe(struct lpfc_hba *phba, struct lpfc_queue *eq, - struct lpfc_eqe *eqe); + struct lpfc_eqe *eqe, + enum lpfc_poll_mode poll_mode); static bool lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba); static bool lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba); static struct lpfc_cqe *lpfc_sli4_cq_get(struct lpfc_queue *q); @@ -629,7 +630,7 @@ lpfc_sli4_eqcq_flush(struct lpfc_hba *phba, struct lpfc_queue *eq) static int lpfc_sli4_process_eq(struct lpfc_hba *phba, struct lpfc_queue *eq, - uint8_t rearm) + u8 rearm, enum lpfc_poll_mode poll_mode) { struct lpfc_eqe *eqe; int count = 0, consumed = 0; @@ -639,7 +640,7 @@ lpfc_sli4_process_eq(struct lpfc_hba *phba, struct lpfc_queue *eq, eqe = lpfc_sli4_eq_get(eq); while (eqe) { - lpfc_sli4_hba_handle_eqe(phba, eq, eqe); + lpfc_sli4_hba_handle_eqe(phba, eq, eqe, poll_mode); __lpfc_sli4_consume_eqe(phba, eq, eqe); consumed++; @@ -1931,7 +1932,7 @@ lpfc_issue_cmf_sync_wqe(struct lpfc_hba *phba, u32 ms, u64 total) unsigned long iflags; u32 ret_val; u32 atot, wtot, max; - u16 warn_sync_period = 0; + u8 warn_sync_period = 0; /* First address any alarm / warning activity */ atot = atomic_xchg(&phba->cgn_sync_alarm_cnt, 0); @@ -7957,7 +7958,7 @@ out_rdf: * lpfc_init_idle_stat_hb - Initialize idle_stat tracking * @phba: pointer to lpfc hba data structure. * - * This routine initializes the per-cq idle_stat to dynamically dictate + * This routine initializes the per-eq idle_stat to dynamically dictate * polling decisions. * * Return codes: @@ -7967,16 +7968,16 @@ static void lpfc_init_idle_stat_hb(struct lpfc_hba *phba) { int i; struct lpfc_sli4_hdw_queue *hdwq; - struct lpfc_queue *cq; + struct lpfc_queue *eq; struct lpfc_idle_stat *idle_stat; u64 wall; for_each_present_cpu(i) { hdwq = &phba->sli4_hba.hdwq[phba->sli4_hba.cpu_map[i].hdwq]; - cq = hdwq->io_cq; + eq = hdwq->hba_eq; - /* Skip if we've already handled this cq's primary CPU */ - if (cq->chann != i) + /* Skip if we've already handled this eq's primary CPU */ + if (eq->chann != i) continue; idle_stat = &phba->sli4_hba.idle_stat[i]; @@ -7985,13 +7986,14 @@ static void lpfc_init_idle_stat_hb(struct lpfc_hba *phba) idle_stat->prev_wall = wall; if (phba->nvmet_support || - phba->cmf_active_mode != LPFC_CFG_OFF) - cq->poll_mode = LPFC_QUEUE_WORK; + phba->cmf_active_mode != LPFC_CFG_OFF || + phba->intr_type != MSIX) + eq->poll_mode = LPFC_QUEUE_WORK; else - cq->poll_mode = LPFC_IRQ_POLL; + eq->poll_mode = LPFC_THREADED_IRQ; } - if (!phba->nvmet_support) + if (!phba->nvmet_support && phba->intr_type == MSIX) schedule_delayed_work(&phba->idle_stat_delay_work, msecs_to_jiffies(LPFC_IDLE_STAT_DELAY)); } @@ -9218,7 +9220,8 @@ lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba) if (mbox_pending) /* process and rearm the EQ */ - lpfc_sli4_process_eq(phba, fpeq, LPFC_QUEUE_REARM); + lpfc_sli4_process_eq(phba, fpeq, LPFC_QUEUE_REARM, + LPFC_QUEUE_WORK); else /* Always clear and re-arm the EQ */ sli4_hba->sli4_write_eq_db(phba, fpeq, 0, LPFC_QUEUE_REARM); @@ -11254,7 +11257,8 @@ inline void lpfc_sli4_poll_eq(struct lpfc_queue *eq) * will be handled through a sched from polling timer * function which is currently triggered every 1msec. */ - lpfc_sli4_process_eq(phba, eq, LPFC_QUEUE_NOARM); + lpfc_sli4_process_eq(phba, eq, LPFC_QUEUE_NOARM, + LPFC_QUEUE_WORK); } /** @@ -14682,6 +14686,38 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe) spin_unlock_irqrestore(&phba->hbalock, iflags); workposted = true; break; + case FC_STATUS_RQ_DMA_FAILURE: + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2564 RQE DMA Error x%x, x%08x x%08x x%08x " + "x%08x\n", + status, rcqe->word0, rcqe->word1, + rcqe->word2, rcqe->word3); + + /* If IV set, no further recovery */ + if (bf_get(lpfc_rcqe_iv, rcqe)) + break; + + /* recycle consumed resource */ + spin_lock_irqsave(&phba->hbalock, iflags); + lpfc_sli4_rq_release(hrq, drq); + dma_buf = lpfc_sli_hbqbuf_get(&phba->hbqs[0].hbq_buffer_list); + if (!dma_buf) { + hrq->RQ_no_buf_found++; + spin_unlock_irqrestore(&phba->hbalock, iflags); + break; + } + hrq->RQ_rcv_buf++; + hrq->RQ_buf_posted--; + spin_unlock_irqrestore(&phba->hbalock, iflags); + lpfc_in_buf_free(phba, &dma_buf->dbuf); + break; + default: + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2565 Unexpected RQE Status x%x, w0-3 x%08x " + "x%08x x%08x x%08x\n", + status, rcqe->word0, rcqe->word1, + rcqe->word2, rcqe->word3); + break; } out: return workposted; @@ -14803,7 +14839,6 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe, * @cq: Pointer to CQ to be processed * @handler: Routine to process each cqe * @delay: Pointer to usdelay to set in case of rescheduling of the handler - * @poll_mode: Polling mode we were called from * * This routine processes completion queue entries in a CQ. While a valid * queue element is found, the handler is called. During processing checks @@ -14821,8 +14856,7 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe, static bool __lpfc_sli4_process_cq(struct lpfc_hba *phba, struct lpfc_queue *cq, bool (*handler)(struct lpfc_hba *, struct lpfc_queue *, - struct lpfc_cqe *), unsigned long *delay, - enum lpfc_poll_mode poll_mode) + struct lpfc_cqe *), unsigned long *delay) { struct lpfc_cqe *cqe; bool workposted = false; @@ -14863,10 +14897,6 @@ __lpfc_sli4_process_cq(struct lpfc_hba *phba, struct lpfc_queue *cq, arm = false; } - /* Note: complete the irq_poll softirq before rearming CQ */ - if (poll_mode == LPFC_IRQ_POLL) - irq_poll_complete(&cq->iop); - /* Track the max number of CQEs processed in 1 EQ */ if (count > cq->CQ_max_cqe) cq->CQ_max_cqe = count; @@ -14916,17 +14946,17 @@ __lpfc_sli4_sp_process_cq(struct lpfc_queue *cq) case LPFC_MCQ: workposted |= __lpfc_sli4_process_cq(phba, cq, lpfc_sli4_sp_handle_mcqe, - &delay, LPFC_QUEUE_WORK); + &delay); break; case LPFC_WCQ: if (cq->subtype == LPFC_IO) workposted |= __lpfc_sli4_process_cq(phba, cq, lpfc_sli4_fp_handle_cqe, - &delay, LPFC_QUEUE_WORK); + &delay); else workposted |= __lpfc_sli4_process_cq(phba, cq, lpfc_sli4_sp_handle_cqe, - &delay, LPFC_QUEUE_WORK); + &delay); break; default: lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, @@ -15203,6 +15233,38 @@ drop: hrq->RQ_no_posted_buf++; /* Post more buffers if possible */ break; + case FC_STATUS_RQ_DMA_FAILURE: + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2575 RQE DMA Error x%x, x%08x x%08x x%08x " + "x%08x\n", + status, rcqe->word0, rcqe->word1, + rcqe->word2, rcqe->word3); + + /* If IV set, no further recovery */ + if (bf_get(lpfc_rcqe_iv, rcqe)) + break; + + /* recycle consumed resource */ + spin_lock_irqsave(&phba->hbalock, iflags); + lpfc_sli4_rq_release(hrq, drq); + dma_buf = lpfc_sli_rqbuf_get(phba, hrq); + if (!dma_buf) { + hrq->RQ_no_buf_found++; + spin_unlock_irqrestore(&phba->hbalock, iflags); + break; + } + hrq->RQ_rcv_buf++; + hrq->RQ_buf_posted--; + spin_unlock_irqrestore(&phba->hbalock, iflags); + lpfc_rq_buf_free(phba, &dma_buf->hbuf); + break; + default: + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2576 Unexpected RQE Status x%x, w0-3 x%08x " + "x%08x x%08x x%08x\n", + status, rcqe->word0, rcqe->word1, + rcqe->word2, rcqe->word3); + break; } out: return workposted; @@ -15271,45 +15333,64 @@ lpfc_sli4_fp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, } /** - * lpfc_sli4_sched_cq_work - Schedules cq work - * @phba: Pointer to HBA context object. - * @cq: Pointer to CQ - * @cqid: CQ ID - * - * This routine checks the poll mode of the CQ corresponding to - * cq->chann, then either schedules a softirq or queue_work to complete - * cq work. + * __lpfc_sli4_hba_process_cq - Process a fast-path event queue entry + * @cq: Pointer to CQ to be processed * - * queue_work path is taken if in NVMET mode, or if poll_mode is in - * LPFC_QUEUE_WORK mode. Otherwise, softirq path is taken. + * This routine calls the cq processing routine with the handler for + * fast path CQEs. * + * The CQ routine returns two values: the first is the calling status, + * which indicates whether work was queued to the background discovery + * thread. If true, the routine should wakeup the discovery thread; + * the second is the delay parameter. If non-zero, rather than rearming + * the CQ and yet another interrupt, the CQ handler should be queued so + * that it is processed in a subsequent polling action. The value of + * the delay indicates when to reschedule it. **/ -static void lpfc_sli4_sched_cq_work(struct lpfc_hba *phba, - struct lpfc_queue *cq, uint16_t cqid) +static void +__lpfc_sli4_hba_process_cq(struct lpfc_queue *cq) { - int ret = 0; + struct lpfc_hba *phba = cq->phba; + unsigned long delay; + bool workposted = false; + int ret; - switch (cq->poll_mode) { - case LPFC_IRQ_POLL: - /* CGN mgmt is mutually exclusive from softirq processing */ - if (phba->cmf_active_mode == LPFC_CFG_OFF) { - irq_poll_sched(&cq->iop); - break; - } - fallthrough; - case LPFC_QUEUE_WORK: - default: + /* process and rearm the CQ */ + workposted |= __lpfc_sli4_process_cq(phba, cq, lpfc_sli4_fp_handle_cqe, + &delay); + + if (delay) { if (is_kdump_kernel()) - ret = queue_work(phba->wq, &cq->irqwork); + ret = queue_delayed_work(phba->wq, &cq->sched_irqwork, + delay); else - ret = queue_work_on(cq->chann, phba->wq, &cq->irqwork); + ret = queue_delayed_work_on(cq->chann, phba->wq, + &cq->sched_irqwork, delay); if (!ret) lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, - "0383 Cannot schedule queue work " - "for CQ eqcqid=%d, cqid=%d on CPU %d\n", - cqid, cq->queue_id, - raw_smp_processor_id()); + "0367 Cannot schedule queue work " + "for cqid=%d on CPU %d\n", + cq->queue_id, cq->chann); } + + /* wake up worker thread if there are works to be done */ + if (workposted) + lpfc_worker_wake_up(phba); +} + +/** + * lpfc_sli4_hba_process_cq - fast-path work handler when started by + * interrupt + * @work: pointer to work element + * + * translates from the work handler and calls the fast-path handler. + **/ +static void +lpfc_sli4_hba_process_cq(struct work_struct *work) +{ + struct lpfc_queue *cq = container_of(work, struct lpfc_queue, irqwork); + + __lpfc_sli4_hba_process_cq(cq); } /** @@ -15317,6 +15398,7 @@ static void lpfc_sli4_sched_cq_work(struct lpfc_hba *phba, * @phba: Pointer to HBA context object. * @eq: Pointer to the queue structure. * @eqe: Pointer to fast-path event queue entry. + * @poll_mode: poll_mode to execute processing the cq. * * This routine process a event queue entry from the fast-path event queue. * It will check the MajorCode and MinorCode to determine this is for a @@ -15327,11 +15409,12 @@ static void lpfc_sli4_sched_cq_work(struct lpfc_hba *phba, **/ static void lpfc_sli4_hba_handle_eqe(struct lpfc_hba *phba, struct lpfc_queue *eq, - struct lpfc_eqe *eqe) + struct lpfc_eqe *eqe, enum lpfc_poll_mode poll_mode) { struct lpfc_queue *cq = NULL; uint32_t qidx = eq->hdwq; uint16_t cqid, id; + int ret; if (unlikely(bf_get_le32(lpfc_eqe_major_code, eqe) != 0)) { lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, @@ -15391,70 +15474,25 @@ work_cq: else cq->isr_timestamp = 0; #endif - lpfc_sli4_sched_cq_work(phba, cq, cqid); -} - -/** - * __lpfc_sli4_hba_process_cq - Process a fast-path event queue entry - * @cq: Pointer to CQ to be processed - * @poll_mode: Enum lpfc_poll_state to determine poll mode - * - * This routine calls the cq processing routine with the handler for - * fast path CQEs. - * - * The CQ routine returns two values: the first is the calling status, - * which indicates whether work was queued to the background discovery - * thread. If true, the routine should wakeup the discovery thread; - * the second is the delay parameter. If non-zero, rather than rearming - * the CQ and yet another interrupt, the CQ handler should be queued so - * that it is processed in a subsequent polling action. The value of - * the delay indicates when to reschedule it. - **/ -static void -__lpfc_sli4_hba_process_cq(struct lpfc_queue *cq, - enum lpfc_poll_mode poll_mode) -{ - struct lpfc_hba *phba = cq->phba; - unsigned long delay; - bool workposted = false; - int ret = 0; - - /* process and rearm the CQ */ - workposted |= __lpfc_sli4_process_cq(phba, cq, lpfc_sli4_fp_handle_cqe, - &delay, poll_mode); - if (delay) { + switch (poll_mode) { + case LPFC_THREADED_IRQ: + __lpfc_sli4_hba_process_cq(cq); + break; + case LPFC_QUEUE_WORK: + default: if (is_kdump_kernel()) - ret = queue_delayed_work(phba->wq, &cq->sched_irqwork, - delay); + ret = queue_work(phba->wq, &cq->irqwork); else - ret = queue_delayed_work_on(cq->chann, phba->wq, - &cq->sched_irqwork, delay); + ret = queue_work_on(cq->chann, phba->wq, &cq->irqwork); if (!ret) lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, - "0367 Cannot schedule queue work " - "for cqid=%d on CPU %d\n", - cq->queue_id, cq->chann); + "0383 Cannot schedule queue work " + "for CQ eqcqid=%d, cqid=%d on CPU %d\n", + cqid, cq->queue_id, + raw_smp_processor_id()); + break; } - - /* wake up worker thread if there are works to be done */ - if (workposted) - lpfc_worker_wake_up(phba); -} - -/** - * lpfc_sli4_hba_process_cq - fast-path work handler when started by - * interrupt - * @work: pointer to work element - * - * translates from the work handler and calls the fast-path handler. - **/ -static void -lpfc_sli4_hba_process_cq(struct work_struct *work) -{ - struct lpfc_queue *cq = container_of(work, struct lpfc_queue, irqwork); - - __lpfc_sli4_hba_process_cq(cq, LPFC_QUEUE_WORK); } /** @@ -15469,7 +15507,7 @@ lpfc_sli4_dly_hba_process_cq(struct work_struct *work) struct lpfc_queue *cq = container_of(to_delayed_work(work), struct lpfc_queue, sched_irqwork); - __lpfc_sli4_hba_process_cq(cq, LPFC_QUEUE_WORK); + __lpfc_sli4_hba_process_cq(cq); } /** @@ -15495,8 +15533,9 @@ lpfc_sli4_dly_hba_process_cq(struct work_struct *work) * and returns for these events. This function is called without any lock * held. It gets the hbalock to access and update SLI data structures. * - * This function returns IRQ_HANDLED when interrupt is handled else it - * returns IRQ_NONE. + * This function returns IRQ_HANDLED when interrupt is handled, IRQ_WAKE_THREAD + * when interrupt is scheduled to be handled from a threaded irq context, or + * else returns IRQ_NONE. **/ irqreturn_t lpfc_sli4_hba_intr_handler(int irq, void *dev_id) @@ -15505,8 +15544,8 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id) struct lpfc_hba_eq_hdl *hba_eq_hdl; struct lpfc_queue *fpeq; unsigned long iflag; - int ecount = 0; int hba_eqidx; + int ecount = 0; struct lpfc_eq_intr_info *eqi; /* Get the driver's phba structure from the dev_id */ @@ -15535,30 +15574,41 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id) return IRQ_NONE; } - eqi = this_cpu_ptr(phba->sli4_hba.eq_info); - eqi->icnt++; - - fpeq->last_cpu = raw_smp_processor_id(); + switch (fpeq->poll_mode) { + case LPFC_THREADED_IRQ: + /* CGN mgmt is mutually exclusive from irq processing */ + if (phba->cmf_active_mode == LPFC_CFG_OFF) + return IRQ_WAKE_THREAD; + fallthrough; + case LPFC_QUEUE_WORK: + default: + eqi = this_cpu_ptr(phba->sli4_hba.eq_info); + eqi->icnt++; - if (eqi->icnt > LPFC_EQD_ISR_TRIGGER && - fpeq->q_flag & HBA_EQ_DELAY_CHK && - phba->cfg_auto_imax && - fpeq->q_mode != LPFC_MAX_AUTO_EQ_DELAY && - phba->sli.sli_flag & LPFC_SLI_USE_EQDR) - lpfc_sli4_mod_hba_eq_delay(phba, fpeq, LPFC_MAX_AUTO_EQ_DELAY); + fpeq->last_cpu = raw_smp_processor_id(); - /* process and rearm the EQ */ - ecount = lpfc_sli4_process_eq(phba, fpeq, LPFC_QUEUE_REARM); + if (eqi->icnt > LPFC_EQD_ISR_TRIGGER && + fpeq->q_flag & HBA_EQ_DELAY_CHK && + phba->cfg_auto_imax && + fpeq->q_mode != LPFC_MAX_AUTO_EQ_DELAY && + phba->sli.sli_flag & LPFC_SLI_USE_EQDR) + lpfc_sli4_mod_hba_eq_delay(phba, fpeq, + LPFC_MAX_AUTO_EQ_DELAY); - if (unlikely(ecount == 0)) { - fpeq->EQ_no_entry++; - if (phba->intr_type == MSIX) - /* MSI-X treated interrupt served as no EQ share INT */ - lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, - "0358 MSI-X interrupt with no EQE\n"); - else - /* Non MSI-X treated on interrupt as EQ share INT */ - return IRQ_NONE; + /* process and rearm the EQ */ + ecount = lpfc_sli4_process_eq(phba, fpeq, LPFC_QUEUE_REARM, + LPFC_QUEUE_WORK); + + if (unlikely(ecount == 0)) { + fpeq->EQ_no_entry++; + if (phba->intr_type == MSIX) + /* MSI-X treated interrupt served as no EQ share INT */ + lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, + "0358 MSI-X interrupt with no EQE\n"); + else + /* Non MSI-X treated on interrupt as EQ share INT */ + return IRQ_NONE; + } } return IRQ_HANDLED; @@ -16115,13 +16165,69 @@ out: return status; } -static int lpfc_cq_poll_hdler(struct irq_poll *iop, int budget) +/** + * lpfc_sli4_hba_intr_handler_th - SLI4 HBA threaded interrupt handler + * @irq: Interrupt number. + * @dev_id: The device context pointer. + * + * This routine is a mirror of lpfc_sli4_hba_intr_handler, but executed within + * threaded irq context. + * + * Returns + * IRQ_HANDLED - interrupt is handled + * IRQ_NONE - otherwise + **/ +irqreturn_t lpfc_sli4_hba_intr_handler_th(int irq, void *dev_id) { - struct lpfc_queue *cq = container_of(iop, struct lpfc_queue, iop); + struct lpfc_hba *phba; + struct lpfc_hba_eq_hdl *hba_eq_hdl; + struct lpfc_queue *fpeq; + int ecount = 0; + int hba_eqidx; + struct lpfc_eq_intr_info *eqi; - __lpfc_sli4_hba_process_cq(cq, LPFC_IRQ_POLL); + /* Get the driver's phba structure from the dev_id */ + hba_eq_hdl = (struct lpfc_hba_eq_hdl *)dev_id; + phba = hba_eq_hdl->phba; + hba_eqidx = hba_eq_hdl->idx; - return 1; + if (unlikely(!phba)) + return IRQ_NONE; + if (unlikely(!phba->sli4_hba.hdwq)) + return IRQ_NONE; + + /* Get to the EQ struct associated with this vector */ + fpeq = phba->sli4_hba.hba_eq_hdl[hba_eqidx].eq; + if (unlikely(!fpeq)) + return IRQ_NONE; + + eqi = per_cpu_ptr(phba->sli4_hba.eq_info, raw_smp_processor_id()); + eqi->icnt++; + + fpeq->last_cpu = raw_smp_processor_id(); + + if (eqi->icnt > LPFC_EQD_ISR_TRIGGER && + fpeq->q_flag & HBA_EQ_DELAY_CHK && + phba->cfg_auto_imax && + fpeq->q_mode != LPFC_MAX_AUTO_EQ_DELAY && + phba->sli.sli_flag & LPFC_SLI_USE_EQDR) + lpfc_sli4_mod_hba_eq_delay(phba, fpeq, LPFC_MAX_AUTO_EQ_DELAY); + + /* process and rearm the EQ */ + ecount = lpfc_sli4_process_eq(phba, fpeq, LPFC_QUEUE_REARM, + LPFC_THREADED_IRQ); + + if (unlikely(ecount == 0)) { + fpeq->EQ_no_entry++; + if (phba->intr_type == MSIX) + /* MSI-X treated interrupt served as no EQ share INT */ + lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, + "3358 MSI-X interrupt with no EQE\n"); + else + /* Non MSI-X treated on interrupt as EQ share INT */ + return IRQ_NONE; + } + return IRQ_HANDLED; } /** @@ -16265,8 +16371,6 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq, if (cq->queue_id > phba->sli4_hba.cq_max) phba->sli4_hba.cq_max = cq->queue_id; - - irq_poll_init(&cq->iop, LPFC_IRQ_POLL_WEIGHT, lpfc_cq_poll_hdler); out: mempool_free(mbox, phba->mbox_mem_pool); return status; @@ -20696,23 +20800,23 @@ lpfc_log_fw_write_cmpl(struct lpfc_hba *phba, u32 shdr_status, if (shdr_add_status == LPFC_ADD_STATUS_INCOMPAT_OBJ) { switch (shdr_add_status_2) { case LPFC_ADD_STATUS_2_INCOMPAT_FLASH: - lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, - "4199 Firmware write failed: " - "image incompatible with flash x%02x\n", - phba->sli4_hba.flash_id); + lpfc_log_msg(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, + "4199 Firmware write failed: " + "image incompatible with flash x%02x\n", + phba->sli4_hba.flash_id); break; case LPFC_ADD_STATUS_2_INCORRECT_ASIC: - lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, - "4200 Firmware write failed: " - "image incompatible with ASIC " - "architecture x%02x\n", - phba->sli4_hba.asic_rev); + lpfc_log_msg(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, + "4200 Firmware write failed: " + "image incompatible with ASIC " + "architecture x%02x\n", + phba->sli4_hba.asic_rev); break; default: - lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, - "4210 Firmware write failed: " - "add_status_2 x%02x\n", - shdr_add_status_2); + lpfc_log_msg(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, + "4210 Firmware write failed: " + "add_status_2 x%02x\n", + shdr_add_status_2); break; } } else if (!shdr_status && !shdr_add_status) { @@ -20725,26 +20829,26 @@ lpfc_log_fw_write_cmpl(struct lpfc_hba *phba, u32 shdr_status, switch (shdr_change_status) { case (LPFC_CHANGE_STATUS_PHYS_DEV_RESET): - lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, - "3198 Firmware write complete: System " - "reboot required to instantiate\n"); + lpfc_log_msg(phba, KERN_NOTICE, LOG_MBOX | LOG_SLI, + "3198 Firmware write complete: System " + "reboot required to instantiate\n"); break; case (LPFC_CHANGE_STATUS_FW_RESET): - lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, - "3199 Firmware write complete: " - "Firmware reset required to " - "instantiate\n"); + lpfc_log_msg(phba, KERN_NOTICE, LOG_MBOX | LOG_SLI, + "3199 Firmware write complete: " + "Firmware reset required to " + "instantiate\n"); break; case (LPFC_CHANGE_STATUS_PORT_MIGRATION): - lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, - "3200 Firmware write complete: Port " - "Migration or PCI Reset required to " - "instantiate\n"); + lpfc_log_msg(phba, KERN_NOTICE, LOG_MBOX | LOG_SLI, + "3200 Firmware write complete: Port " + "Migration or PCI Reset required to " + "instantiate\n"); break; case (LPFC_CHANGE_STATUS_PCI_RESET): - lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, - "3201 Firmware write complete: PCI " - "Reset required to instantiate\n"); + lpfc_log_msg(phba, KERN_NOTICE, LOG_MBOX | LOG_SLI, + "3201 Firmware write complete: PCI " + "Reset required to instantiate\n"); break; default: break; diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 2a0864e6d7cd..2541a8fba093 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -140,7 +140,7 @@ struct lpfc_rqb { enum lpfc_poll_mode { LPFC_QUEUE_WORK, - LPFC_IRQ_POLL + LPFC_THREADED_IRQ, }; struct lpfc_idle_stat { @@ -279,8 +279,6 @@ struct lpfc_queue { struct list_head _poll_list; void **q_pgs; /* array to index entries per page */ -#define LPFC_IRQ_POLL_WEIGHT 256 - struct irq_poll iop; enum lpfc_poll_mode poll_mode; }; diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index c97411b0992e..6f35491aed0f 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -20,7 +20,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "14.2.0.11" +#define LPFC_DRIVER_VERSION "14.2.0.13" #define LPFC_DRIVER_NAME "lpfc" /* Used for SLI 2/3 */ diff --git a/drivers/scsi/megaraid/Kconfig.megaraid b/drivers/scsi/megaraid/Kconfig.megaraid index 2adc2afd9f91..3f2ce1eb081c 100644 --- a/drivers/scsi/megaraid/Kconfig.megaraid +++ b/drivers/scsi/megaraid/Kconfig.megaraid @@ -1,13 +1,13 @@ # SPDX-License-Identifier: GPL-2.0-only config MEGARAID_NEWGEN bool "LSI Logic New Generation RAID Device Drivers" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI help LSI Logic RAID Device Drivers config MEGARAID_MM tristate "LSI Logic Management Module (New Driver)" - depends on PCI && SCSI && MEGARAID_NEWGEN + depends on PCI && HAS_IOPORT && SCSI && MEGARAID_NEWGEN help Management Module provides ioctl, sysfs support for LSI Logic RAID controllers. @@ -67,7 +67,7 @@ config MEGARAID_MAILBOX config MEGARAID_LEGACY tristate "LSI Logic Legacy MegaRAID Driver" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI help This driver supports the LSI MegaRAID 418, 428, 438, 466, 762, 490 and 467 SCSI host adapters. This driver also support the all U320 diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 63bac3684c19..3554f6b07727 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -1722,11 +1722,9 @@ struct megasas_sge_skinny { } __packed; union megasas_sgl { - - struct megasas_sge32 sge32[1]; - struct megasas_sge64 sge64[1]; - struct megasas_sge_skinny sge_skinny[1]; - + DECLARE_FLEX_ARRAY(struct megasas_sge32, sge32); + DECLARE_FLEX_ARRAY(struct megasas_sge64, sge64); + DECLARE_FLEX_ARRAY(struct megasas_sge_skinny, sge_skinny); } __attribute__ ((packed)); struct megasas_header { diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index dfe6b87fe288..0afb687402e1 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -1133,18 +1133,18 @@ struct mpi3mr_ioc { u32 chain_buf_count; struct dma_pool *chain_buf_pool; struct chain_element *chain_sgl_list; - void *chain_bitmap; + unsigned long *chain_bitmap; spinlock_t chain_buf_lock; struct mpi3mr_drv_cmd bsg_cmds; struct mpi3mr_drv_cmd host_tm_cmds; struct mpi3mr_drv_cmd dev_rmhs_cmds[MPI3MR_NUM_DEVRMCMD]; struct mpi3mr_drv_cmd evtack_cmds[MPI3MR_NUM_EVTACKCMD]; - void *devrem_bitmap; + unsigned long *devrem_bitmap; u16 dev_handle_bitmap_bits; - void *removepend_bitmap; + unsigned long *removepend_bitmap; struct list_head delayed_rmhs_list; - void *evtack_cmds_bitmap; + unsigned long *evtack_cmds_bitmap; struct list_head delayed_evtack_cmds_list; u32 ts_update_counter; diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index 075fa67e95ee..5fa07d6ee5b8 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -402,6 +402,11 @@ static void mpi3mr_process_admin_reply_desc(struct mpi3mr_ioc *mrioc, memcpy((u8 *)cmdptr->reply, (u8 *)def_reply, mrioc->reply_sz); } + if (sense_buf && cmdptr->sensebuf) { + cmdptr->is_sense = 1; + memcpy(cmdptr->sensebuf, sense_buf, + MPI3MR_SENSE_BUF_SZ); + } if (cmdptr->is_waiting) { complete(&cmdptr->done); cmdptr->is_waiting = 0; @@ -1134,7 +1139,7 @@ static int mpi3mr_issue_and_process_mur(struct mpi3mr_ioc *mrioc, static int mpi3mr_revalidate_factsdata(struct mpi3mr_ioc *mrioc) { - void *removepend_bitmap; + unsigned long *removepend_bitmap; if (mrioc->facts.reply_sz > mrioc->reply_sz) { ioc_err(mrioc, diff --git a/drivers/scsi/mpi3mr/mpi3mr_transport.c b/drivers/scsi/mpi3mr/mpi3mr_transport.c index 4d84d5bd173f..82b55e955730 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_transport.c +++ b/drivers/scsi/mpi3mr/mpi3mr_transport.c @@ -2058,7 +2058,7 @@ int mpi3mr_expander_add(struct mpi3mr_ioc *mrioc, u16 handle) sas_expander = kzalloc(sizeof(struct mpi3mr_sas_node), GFP_KERNEL); if (!sas_expander) - return -1; + return -ENOMEM; sas_expander->handle = handle; sas_expander->num_phys = expander_pg0.num_phys; diff --git a/drivers/scsi/mvsas/Kconfig b/drivers/scsi/mvsas/Kconfig index 79812b80743b..5ac7fd593b17 100644 --- a/drivers/scsi/mvsas/Kconfig +++ b/drivers/scsi/mvsas/Kconfig @@ -9,7 +9,7 @@ config SCSI_MVSAS tristate "Marvell 88SE64XX/88SE94XX SAS/SATA support" - depends on PCI + depends on PCI && HAS_IOPORT select SCSI_SAS_LIBSAS select FW_LOADER help diff --git a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig index 9696b6b5591f..449bd85db7bb 100644 --- a/drivers/scsi/pcmcia/Kconfig +++ b/drivers/scsi/pcmcia/Kconfig @@ -12,6 +12,7 @@ if SCSI_LOWLEVEL_PCMCIA && SCSI && PCMCIA && m config PCMCIA_AHA152X tristate "Adaptec AHA152X PCMCIA support" + depends on HAS_IOPORT select SCSI_SPI_ATTRS help Say Y here if you intend to attach this type of PCMCIA SCSI host @@ -22,6 +23,7 @@ config PCMCIA_AHA152X config PCMCIA_FDOMAIN tristate "Future Domain PCMCIA support" + depends on HAS_IOPORT select SCSI_FDOMAIN help Say Y here if you intend to attach this type of PCMCIA SCSI host @@ -32,7 +34,7 @@ config PCMCIA_FDOMAIN config PCMCIA_NINJA_SCSI tristate "NinjaSCSI-3 / NinjaSCSI-32Bi (16bit) PCMCIA support" - depends on !64BIT || COMPILE_TEST + depends on (!64BIT || COMPILE_TEST) && HAS_IOPORT help If you intend to attach this type of PCMCIA SCSI host adapter to your computer, say Y here and read @@ -66,6 +68,7 @@ config PCMCIA_NINJA_SCSI config PCMCIA_QLOGIC tristate "Qlogic PCMCIA support" + depends on HAS_IOPORT help Say Y here if you intend to attach this type of PCMCIA SCSI host adapter to your computer. @@ -75,6 +78,7 @@ config PCMCIA_QLOGIC config PCMCIA_SYM53C500 tristate "Symbios 53c500 PCMCIA support" + depends on HAS_IOPORT help Say Y here if you have a New Media Bus Toaster or other PCMCIA SCSI adapter based on the Symbios 53c500 controller. diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 8b9490011e36..2e886c1d867d 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -43,7 +43,8 @@ #include "pm8001_chips.h" #include "pm80xx_hwi.h" -static ulong logging_level = PM8001_FAIL_LOGGING | PM8001_IOERR_LOGGING; +static ulong logging_level = PM8001_FAIL_LOGGING | PM8001_IOERR_LOGGING | + PM8001_EVENT_LOGGING | PM8001_INIT_LOGGING; module_param(logging_level, ulong, 0644); MODULE_PARM_DESC(logging_level, " bits for enabling logging info."); @@ -666,7 +667,7 @@ static void pm8001_post_sas_ha_init(struct Scsi_Host *shost, * Currently we just set the fixed SAS address to our HBA, for manufacture, * it should read from the EEPROM */ -static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) +static int pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) { u8 i, j; u8 sas_add[8]; @@ -679,6 +680,12 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) struct pm8001_ioctl_payload payload; u16 deviceid; int rc; + unsigned long time_remaining; + + if (PM8001_CHIP_DISP->fatal_errors(pm8001_ha)) { + pm8001_dbg(pm8001_ha, FAIL, "controller is in fatal error state\n"); + return -EIO; + } pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid); pm8001_ha->nvmd_completion = &completion; @@ -703,16 +710,23 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) payload.offset = 0; payload.func_specific = kzalloc(payload.rd_length, GFP_KERNEL); if (!payload.func_specific) { - pm8001_dbg(pm8001_ha, INIT, "mem alloc fail\n"); - return; + pm8001_dbg(pm8001_ha, FAIL, "mem alloc fail\n"); + return -ENOMEM; } rc = PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); if (rc) { kfree(payload.func_specific); - pm8001_dbg(pm8001_ha, INIT, "nvmd failed\n"); - return; + pm8001_dbg(pm8001_ha, FAIL, "nvmd failed\n"); + return -EIO; + } + time_remaining = wait_for_completion_timeout(&completion, + msecs_to_jiffies(60*1000)); // 1 min + if (!time_remaining) { + kfree(payload.func_specific); + pm8001_dbg(pm8001_ha, FAIL, "get_nvmd_req timeout\n"); + return -EIO; } - wait_for_completion(&completion); + for (i = 0, j = 0; i <= 7; i++, j++) { if (pm8001_ha->chip_id == chip_8001) { @@ -751,6 +765,7 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) memcpy(pm8001_ha->sas_addr, &pm8001_ha->phy[0].dev_sas_addr, SAS_ADDR_SIZE); #endif + return 0; } /* @@ -1166,7 +1181,8 @@ static int pm8001_pci_probe(struct pci_dev *pdev, pm80xx_set_thermal_config(pm8001_ha); } - pm8001_init_sas_add(pm8001_ha); + if (pm8001_init_sas_add(pm8001_ha)) + goto err_out_shost; /* phy setting support for motherboard controller */ rc = pm8001_configure_phy_settings(pm8001_ha); if (rc) diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index e5673c774f66..a5a31dfa4512 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -167,6 +167,17 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, pm8001_ha = sas_phy->ha->lldd_ha; phy = &pm8001_ha->phy[phy_id]; pm8001_ha->phy[phy_id].enable_completion = &completion; + + if (PM8001_CHIP_DISP->fatal_errors(pm8001_ha)) { + /* + * If the controller is in fatal error state, + * we will not get a response from the controller + */ + pm8001_dbg(pm8001_ha, FAIL, + "Phy control failed due to fatal errors\n"); + return -EFAULT; + } + switch (func) { case PHY_FUNC_SET_LINK_RATE: rates = funcdata; @@ -908,6 +919,17 @@ int pm8001_lu_reset(struct domain_device *dev, u8 *lun) struct pm8001_device *pm8001_dev = dev->lldd_dev; struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev); DECLARE_COMPLETION_ONSTACK(completion_setstate); + + if (PM8001_CHIP_DISP->fatal_errors(pm8001_ha)) { + /* + * If the controller is in fatal error state, + * we will not get a response from the controller + */ + pm8001_dbg(pm8001_ha, FAIL, + "LUN reset failed due to fatal errors\n"); + return rc; + } + if (dev_is_sata(dev)) { struct sas_phy *phy = sas_get_local_phy(dev); sas_execute_internal_abort_dev(dev, 0, NULL); diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index dc1f4d958e03..953572fc0d9e 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -71,6 +71,7 @@ #define PM8001_DEV_LOGGING 0x80 /* development message logging */ #define PM8001_DEVIO_LOGGING 0x100 /* development io message logging */ #define PM8001_IOERR_LOGGING 0x200 /* development io err message logging */ +#define PM8001_EVENT_LOGGING 0x400 /* HW event logging */ #define pm8001_info(HBA, fmt, ...) \ pr_info("%s:: %s %d: " fmt, \ diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 9584cadc4201..39a12ee94a72 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -3239,9 +3239,9 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) struct pm8001_port *port = &pm8001_ha->port[port_id]; struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; unsigned long flags; - pm8001_dbg(pm8001_ha, DEVIO, - "port id %d, phy id %d link_rate %d portstate 0x%x\n", - port_id, phy_id, link_rate, portstate); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_SATA_PHY_UP phyid:%#x port_id:%#x link_rate:%d portstate:%#x\n", + phy_id, port_id, link_rate, portstate); phy->port = port; port->port_id = port_id; @@ -3291,10 +3291,14 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb) phy->phy_attached = 0; switch (portstate) { case PORT_VALID: + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate: PORT_VALID\n", + phy_id, port_id); break; case PORT_INVALID: - pm8001_dbg(pm8001_ha, MSG, " PortInvalid portID %d\n", - port_id); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate: PORT_INVALID\n", + phy_id, port_id); pm8001_dbg(pm8001_ha, MSG, " Last phy Down and port invalid\n"); if (port_sata) { @@ -3306,18 +3310,21 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb) sas_phy_disconnected(&phy->sas_phy); break; case PORT_IN_RESET: - pm8001_dbg(pm8001_ha, MSG, " Port In Reset portID %d\n", - port_id); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate: PORT_IN_RESET\n", + phy_id, port_id); break; case PORT_NOT_ESTABLISHED: - pm8001_dbg(pm8001_ha, MSG, - " Phy Down and PORT_NOT_ESTABLISHED\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate: PORT_NOT_ESTABLISHED\n", + phy_id, port_id); port->port_attached = 0; break; case PORT_LOSTCOMM: - pm8001_dbg(pm8001_ha, MSG, " Phy Down and PORT_LOSTCOMM\n"); - pm8001_dbg(pm8001_ha, MSG, - " Last phy Down and port invalid\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate: PORT_LOSTCOMM\n", + phy_id, port_id); + pm8001_dbg(pm8001_ha, MSG, " Last phy Down and port invalid\n"); if (port_sata) { port->port_attached = 0; phy->phy_type = 0; @@ -3328,9 +3335,9 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb) break; default: port->port_attached = 0; - pm8001_dbg(pm8001_ha, DEVIO, - " Phy Down and(default) = 0x%x\n", - portstate); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate:%#x\n", + phy_id, port_id, portstate); break; } @@ -3410,6 +3417,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF); u8 phy_id = (u8)((phyid_npip_portstate & 0xFF0000) >> 16); + u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F); u16 eventType = (u16)((lr_status_evt_portid & 0x00FFFF00) >> 8); u8 status = @@ -3425,26 +3433,29 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) switch (eventType) { case HW_EVENT_SAS_PHY_UP: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_START_STATUS\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_SAS_PHY_UP phyid:%#x port_id:%#x\n", + phy_id, port_id); hw_event_sas_phy_up(pm8001_ha, piomb); break; case HW_EVENT_SATA_PHY_UP: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_SATA_PHY_UP\n"); hw_event_sata_phy_up(pm8001_ha, piomb); break; case HW_EVENT_SATA_SPINUP_HOLD: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_SATA_SPINUP_HOLD\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_SATA_SPINUP_HOLD phyid:%#x port_id:%#x\n", + phy_id, port_id); sas_notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD, GFP_ATOMIC); break; case HW_EVENT_PHY_DOWN: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_DOWN\n"); hw_event_phy_down(pm8001_ha, piomb); - phy->phy_attached = 0; phy->phy_state = PHY_LINK_DISABLE; break; case HW_EVENT_PORT_INVALID: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_INVALID\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PORT_INVALID phyid:%#x port_id:%#x\n", + phy_id, port_id); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, @@ -3463,7 +3474,9 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) GFP_ATOMIC); break; case HW_EVENT_PHY_ERROR: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_ERROR\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PHY_ERROR phyid:%#x port_id:%#x\n", + phy_id, port_id); sas_phy_disconnected(&phy->sas_phy); phy->phy_attached = 0; sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR, GFP_ATOMIC); @@ -3477,34 +3490,39 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) GFP_ATOMIC); break; case HW_EVENT_LINK_ERR_INVALID_DWORD: - pm8001_dbg(pm8001_ha, MSG, - "HW_EVENT_LINK_ERR_INVALID_DWORD\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_LINK_ERR_INVALID_DWORD phyid:%#x port_id:%#x\n", + phy_id, port_id); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_INVALID_DWORD, port_id, phy_id, 0, 0); break; case HW_EVENT_LINK_ERR_DISPARITY_ERROR: - pm8001_dbg(pm8001_ha, MSG, - "HW_EVENT_LINK_ERR_DISPARITY_ERROR\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_LINK_ERR_DISPARITY_ERROR phyid:%#x port_id:%#x\n", + phy_id, port_id); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_DISPARITY_ERROR, port_id, phy_id, 0, 0); break; case HW_EVENT_LINK_ERR_CODE_VIOLATION: - pm8001_dbg(pm8001_ha, MSG, - "HW_EVENT_LINK_ERR_CODE_VIOLATION\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_LINK_ERR_CODE_VIOLATION phyid:%#x port_id:%#x\n", + phy_id, port_id); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_CODE_VIOLATION, port_id, phy_id, 0, 0); break; case HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH: - pm8001_dbg(pm8001_ha, MSG, - "HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH phyid:%#x port_id:%#x\n", + phy_id, port_id); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH, port_id, phy_id, 0, 0); break; case HW_EVENT_MALFUNCTION: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_MALFUNCTION\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_MALFUNCTION phyid:%#x\n", phy_id); break; case HW_EVENT_BROADCAST_SES: pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_SES\n"); @@ -3515,25 +3533,30 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) GFP_ATOMIC); break; case HW_EVENT_INBOUND_CRC_ERROR: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_INBOUND_CRC_ERROR\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_INBOUND_CRC_ERROR phyid:%#x port_id:%#x\n", + phy_id, port_id); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_INBOUND_CRC_ERROR, port_id, phy_id, 0, 0); break; case HW_EVENT_HARD_RESET_RECEIVED: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_HARD_RESET_RECEIVED\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_HARD_RESET_RECEIVED phyid:%#x\n", phy_id); sas_notify_port_event(sas_phy, PORTE_HARD_RESET, GFP_ATOMIC); break; case HW_EVENT_ID_FRAME_TIMEOUT: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_ID_FRAME_TIMEOUT\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_ID_FRAME_TIMEOUT phyid:%#x\n", phy_id); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, GFP_ATOMIC); break; case HW_EVENT_LINK_ERR_PHY_RESET_FAILED: - pm8001_dbg(pm8001_ha, MSG, - "HW_EVENT_LINK_ERR_PHY_RESET_FAILED\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_LINK_ERR_PHY_RESET_FAILED phyid:%#x port_id:%#x\n", + phy_id, port_id); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_PHY_RESET_FAILED, port_id, phy_id, 0, 0); @@ -3543,13 +3566,16 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) GFP_ATOMIC); break; case HW_EVENT_PORT_RESET_TIMER_TMO: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RESET_TIMER_TMO\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PORT_RESET_TIMER_TMO phyid:%#x port_id:%#x portstate:%#x\n", + phy_id, port_id, portstate); if (!pm8001_ha->phy[phy_id].reset_completion) { pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN, port_id, phy_id, 0, 0); } sas_phy_disconnected(sas_phy); phy->phy_attached = 0; + port->port_state = portstate; sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, GFP_ATOMIC); if (pm8001_ha->phy[phy_id].reset_completion) { @@ -3560,8 +3586,9 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) } break; case HW_EVENT_PORT_RECOVERY_TIMER_TMO: - pm8001_dbg(pm8001_ha, MSG, - "HW_EVENT_PORT_RECOVERY_TIMER_TMO\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PORT_RECOVERY_TIMER_TMO phyid:%#x port_id:%#x\n", + phy_id, port_id); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PORT_RECOVERY_TIMER_TMO, port_id, phy_id, 0, 0); @@ -3575,24 +3602,32 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) } break; case HW_EVENT_PORT_RECOVER: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RECOVER\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PORT_RECOVER phyid:%#x port_id:%#x\n", + phy_id, port_id); hw_event_port_recover(pm8001_ha, piomb); break; case HW_EVENT_PORT_RESET_COMPLETE: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RESET_COMPLETE\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PORT_RESET_COMPLETE phyid:%#x port_id:%#x portstate:%#x\n", + phy_id, port_id, portstate); if (pm8001_ha->phy[phy_id].reset_completion) { pm8001_ha->phy[phy_id].port_reset_status = PORT_RESET_SUCCESS; complete(pm8001_ha->phy[phy_id].reset_completion); pm8001_ha->phy[phy_id].reset_completion = NULL; } + phy->phy_attached = 1; + phy->phy_state = PHY_STATE_LINK_UP_SPCV; + port->port_state = portstate; break; case EVENT_BROADCAST_ASYNCH_EVENT: pm8001_dbg(pm8001_ha, MSG, "EVENT_BROADCAST_ASYNCH_EVENT\n"); break; default: - pm8001_dbg(pm8001_ha, DEVIO, "Unknown event type 0x%x\n", - eventType); + pm8001_dbg(pm8001_ha, DEVIO, + "Unknown event portid:%d phyid:%d event:0x%x status:0x%x\n", + port_id, phy_id, eventType, status); break; } return 0; @@ -4726,6 +4761,9 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr, SAS_ADDR_SIZE); + pm8001_dbg(pm8001_ha, INIT, + "register device req phy_id 0x%x port_id 0x%x\n", phy_id, + (port->port_id & 0xFF)); rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload, sizeof(payload), 0); if (rc) @@ -4815,7 +4853,7 @@ static void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha, payload.tag = cpu_to_le32(tag); payload.ppc_phyid = cpu_to_le32(((operation & 0xF) << 8) | (phyid & 0xFF)); - pm8001_dbg(pm8001_ha, INIT, + pm8001_dbg(pm8001_ha, DISC, " phy profile command for phy %x ,length is %d\n", le32_to_cpu(payload.ppc_phyid), length); for (i = length; i < (length + PHY_DWORD_LENGTH - 1); i++) { diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index 3b64de81ea0d..2a31ddc99dde 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -3041,9 +3041,8 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf) * addresses of our queues */ if (!qedf->p_cpuq) { - status = -EINVAL; QEDF_ERR(&qedf->dbg_ctx, "p_cpuq is NULL.\n"); - goto mem_alloc_failure; + return -EINVAL; } qedf->global_queues = kzalloc((sizeof(struct global_queue *) diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig index 802c373fd6d9..a584708d3056 100644 --- a/drivers/scsi/qla2xxx/Kconfig +++ b/drivers/scsi/qla2xxx/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only config SCSI_QLA_FC tristate "QLogic QLA2XXX Fibre Channel Support" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI depends on SCSI_FC_ATTRS depends on NVME_FC || !NVME_FC select FW_LOADER diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 70cfc94c3d43..b00222459607 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -2750,6 +2750,7 @@ static void qla2x00_terminate_rport_io(struct fc_rport *rport) { fc_port_t *fcport = *(fc_port_t **)rport->dd_data; + scsi_qla_host_t *vha; if (!fcport) return; @@ -2759,9 +2760,12 @@ qla2x00_terminate_rport_io(struct fc_rport *rport) if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags)) return; + vha = fcport->vha; if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) { qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16); + qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24, + 0, WAIT_TARGET); return; } /* @@ -2786,6 +2790,15 @@ qla2x00_terminate_rport_io(struct fc_rport *rport) qla2x00_port_logout(fcport->vha, fcport); } } + + /* check for any straggling io left behind */ + if (qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24, 0, WAIT_TARGET)) { + ql_log(ql_log_warn, vha, 0x300b, + "IO not return. Resetting. \n"); + set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); + qla2xxx_wake_dpc(vha); + qla2x00_wait_for_chip_reset(vha); + } } static int diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index dba7bba788d7..19bb64bdd88b 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -283,6 +283,10 @@ qla2x00_process_els(struct bsg_job *bsg_job) if (bsg_request->msgcode == FC_BSG_RPT_ELS) { rport = fc_bsg_to_rport(bsg_job); + if (!rport) { + rval = -ENOMEM; + goto done; + } fcport = *(fc_port_t **) rport->dd_data; host = rport_to_shost(rport); vha = shost_priv(host); @@ -2992,6 +2996,8 @@ qla24xx_bsg_request(struct bsg_job *bsg_job) if (bsg_request->msgcode == FC_BSG_RPT_ELS) { rport = fc_bsg_to_rport(bsg_job); + if (!rport) + return ret; host = rport_to_shost(rport); vha = shost_priv(host); } else { diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 84aa3571be6d..d44c4d37b50b 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -465,6 +465,15 @@ static inline be_id_t port_id_to_be_id(port_id_t port_id) return res; } +struct tmf_arg { + struct qla_qpair *qpair; + struct fc_port *fcport; + struct scsi_qla_host *vha; + u64 lun; + u32 flags; + uint8_t modifier; +}; + struct els_logo_payload { uint8_t opcode; uint8_t rsvd[3]; @@ -544,6 +553,10 @@ struct srb_iocb { uint32_t data; struct completion comp; __le16 comp_status; + + uint8_t modifier; + uint8_t vp_index; + uint16_t loop_id; } tmf; struct { #define SRB_FXDISC_REQ_DMA_VALID BIT_0 @@ -647,6 +660,7 @@ struct srb_iocb { #define SRB_SA_UPDATE 25 #define SRB_ELS_CMD_HST_NOLOGIN 26 #define SRB_SA_REPLACE 27 +#define SRB_MARKER 28 struct qla_els_pt_arg { u8 els_opcode; @@ -689,7 +703,6 @@ typedef struct srb { struct iocb_resource iores; struct kref cmd_kref; /* need to migrate ref_count over to this */ void *priv; - wait_queue_head_t nvme_ls_waitq; struct fc_port *fcport; struct scsi_qla_host *vha; unsigned int start_timer:1; @@ -2528,6 +2541,7 @@ enum rscn_addr_format { typedef struct fc_port { struct list_head list; struct scsi_qla_host *vha; + struct list_head tmf_pending; unsigned int conf_compl_supported:1; unsigned int deleted:2; @@ -2548,6 +2562,8 @@ typedef struct fc_port { unsigned int do_prli_nvme:1; uint8_t nvme_flag; + uint8_t active_tmf; +#define MAX_ACTIVE_TMF 8 uint8_t node_name[WWN_SIZE]; uint8_t port_name[WWN_SIZE]; @@ -3157,12 +3173,12 @@ struct ct_sns_gpnft_rsp { uint8_t vendor_unique; }; /* Assume the largest number of targets for the union */ - struct ct_sns_gpn_ft_data { + DECLARE_FLEX_ARRAY(struct ct_sns_gpn_ft_data { u8 control_byte; u8 port_id[3]; u32 reserved; u8 port_name[8]; - } entries[1]; + }, entries); }; /* CT command response */ @@ -5499,4 +5515,8 @@ struct ql_vnd_tgt_stats_resp { _fp->disc_state, _fp->scan_state, _fp->loop_id, _fp->deleted, \ _fp->flags +#define TMF_NOT_READY(_fcport) \ + (!_fcport || IS_SESSION_DELETED(_fcport) || atomic_read(&_fcport->state) != FCS_ONLINE || \ + !_fcport->vha->hw->flags.fw_started) + #endif diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c index ec0e20255bd3..26e6b3e3af43 100644 --- a/drivers/scsi/qla2xxx/qla_edif.c +++ b/drivers/scsi/qla2xxx/qla_edif.c @@ -2361,8 +2361,8 @@ qla24xx_issue_sa_replace_iocb(scsi_qla_host_t *vha, struct qla_work_evt *e) if (!sa_ctl) { ql_dbg(ql_dbg_edif, vha, 0x70e6, "sa_ctl allocation failed\n"); - rval = -ENOMEM; - goto done; + rval = -ENOMEM; + return rval; } fcport = sa_ctl->fcport; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 391c8b3623a6..ba7831f24734 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -69,7 +69,7 @@ extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *); extern int qla2x00_async_prlo(struct scsi_qla_host *, fc_port_t *); extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *, uint16_t *); -extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint32_t, uint32_t); +extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint64_t, uint32_t); struct qla_work_evt *qla2x00_alloc_work(struct scsi_qla_host *, enum qla_work_type); extern int qla24xx_async_gnl(struct scsi_qla_host *, fc_port_t *); diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 4738f8935f7f..1cf9d200d563 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -3776,8 +3776,8 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp) sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE; rspsz = sizeof(struct ct_sns_gpnft_rsp) + - ((vha->hw->max_fibre_devices - 1) * - sizeof(struct ct_sns_gpn_ft_data)); + vha->hw->max_fibre_devices * + sizeof(struct ct_sns_gpn_ft_data); sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev, rspsz, diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 1a955c3ff3d6..c3dd8dd4f734 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1996,6 +1996,11 @@ qla2x00_tmf_iocb_timeout(void *data) int rc, h; unsigned long flags; + if (sp->type == SRB_MARKER) { + complete(&tmf->u.tmf.comp); + return; + } + rc = qla24xx_async_abort_cmd(sp, false); if (rc) { spin_lock_irqsave(sp->qpair->qp_lock_ptr, flags); @@ -2013,24 +2018,131 @@ qla2x00_tmf_iocb_timeout(void *data) } } +static void qla_marker_sp_done(srb_t *sp, int res) +{ + struct srb_iocb *tmf = &sp->u.iocb_cmd; + + if (res != QLA_SUCCESS) + ql_dbg(ql_dbg_taskm, sp->vha, 0x8004, + "Async-marker fail hdl=%x portid=%06x ctrl=%x lun=%lld qp=%d.\n", + sp->handle, sp->fcport->d_id.b24, sp->u.iocb_cmd.u.tmf.flags, + sp->u.iocb_cmd.u.tmf.lun, sp->qpair->id); + + sp->u.iocb_cmd.u.tmf.data = res; + complete(&tmf->u.tmf.comp); +} + +#define START_SP_W_RETRIES(_sp, _rval) \ +{\ + int cnt = 5; \ + do { \ + _rval = qla2x00_start_sp(_sp); \ + if (_rval == EAGAIN) \ + msleep(1); \ + else \ + break; \ + cnt--; \ + } while (cnt); \ +} + +/** + * qla26xx_marker: send marker IOCB and wait for the completion of it. + * @arg: pointer to argument list. + * It is assume caller will provide an fcport pointer and modifier + */ +static int +qla26xx_marker(struct tmf_arg *arg) +{ + struct scsi_qla_host *vha = arg->vha; + struct srb_iocb *tm_iocb; + srb_t *sp; + int rval = QLA_FUNCTION_FAILED; + fc_port_t *fcport = arg->fcport; + + if (TMF_NOT_READY(arg->fcport)) { + ql_dbg(ql_dbg_taskm, vha, 0x8039, + "FC port not ready for marker loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d.\n", + fcport->loop_id, fcport->d_id.b24, + arg->modifier, arg->lun, arg->qpair->id); + return QLA_SUSPENDED; + } + + /* ref: INIT */ + sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL); + if (!sp) + goto done; + + sp->type = SRB_MARKER; + sp->name = "marker"; + qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha), qla_marker_sp_done); + sp->u.iocb_cmd.timeout = qla2x00_tmf_iocb_timeout; + + tm_iocb = &sp->u.iocb_cmd; + init_completion(&tm_iocb->u.tmf.comp); + tm_iocb->u.tmf.modifier = arg->modifier; + tm_iocb->u.tmf.lun = arg->lun; + tm_iocb->u.tmf.loop_id = fcport->loop_id; + tm_iocb->u.tmf.vp_index = vha->vp_idx; + + START_SP_W_RETRIES(sp, rval); + + ql_dbg(ql_dbg_taskm, vha, 0x8006, + "Async-marker hdl=%x loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d rval %d.\n", + sp->handle, fcport->loop_id, fcport->d_id.b24, + arg->modifier, arg->lun, sp->qpair->id, rval); + + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0x8031, + "Marker IOCB send failure (%x).\n", rval); + goto done_free_sp; + } + + wait_for_completion(&tm_iocb->u.tmf.comp); + rval = tm_iocb->u.tmf.data; + + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0x8019, + "Marker failed hdl=%x loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d rval %d.\n", + sp->handle, fcport->loop_id, fcport->d_id.b24, + arg->modifier, arg->lun, sp->qpair->id, rval); + } + +done_free_sp: + /* ref: INIT */ + kref_put(&sp->cmd_kref, qla2x00_sp_release); +done: + return rval; +} + static void qla2x00_tmf_sp_done(srb_t *sp, int res) { struct srb_iocb *tmf = &sp->u.iocb_cmd; + if (res) + tmf->u.tmf.data = res; complete(&tmf->u.tmf.comp); } -int -qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, - uint32_t tag) +static int +__qla2x00_async_tm_cmd(struct tmf_arg *arg) { - struct scsi_qla_host *vha = fcport->vha; + struct scsi_qla_host *vha = arg->vha; struct srb_iocb *tm_iocb; srb_t *sp; int rval = QLA_FUNCTION_FAILED; + fc_port_t *fcport = arg->fcport; + + if (TMF_NOT_READY(arg->fcport)) { + ql_dbg(ql_dbg_taskm, vha, 0x8032, + "FC port not ready for TM command loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d.\n", + fcport->loop_id, fcport->d_id.b24, + arg->modifier, arg->lun, arg->qpair->id); + return QLA_SUSPENDED; + } + /* ref: INIT */ - sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); + sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL); if (!sp) goto done; @@ -2043,15 +2155,16 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, tm_iocb = &sp->u.iocb_cmd; init_completion(&tm_iocb->u.tmf.comp); - tm_iocb->u.tmf.flags = flags; - tm_iocb->u.tmf.lun = lun; + tm_iocb->u.tmf.flags = arg->flags; + tm_iocb->u.tmf.lun = arg->lun; + + START_SP_W_RETRIES(sp, rval); ql_dbg(ql_dbg_taskm, vha, 0x802f, - "Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x.\n", - sp->handle, fcport->loop_id, fcport->d_id.b.domain, - fcport->d_id.b.area, fcport->d_id.b.al_pa); + "Async-tmf hdl=%x loop-id=%x portid=%06x ctrl=%x lun=%lld qp=%d rval=%x.\n", + sp->handle, fcport->loop_id, fcport->d_id.b24, + arg->flags, arg->lun, sp->qpair->id, rval); - rval = qla2x00_start_sp(sp); if (rval != QLA_SUCCESS) goto done_free_sp; wait_for_completion(&tm_iocb->u.tmf.comp); @@ -2063,15 +2176,8 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, "TM IOCB failed (%x).\n", rval); } - if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) { - flags = tm_iocb->u.tmf.flags; - lun = (uint16_t)tm_iocb->u.tmf.lun; - - /* Issue Marker IOCB */ - qla2x00_marker(vha, vha->hw->base_qpair, - fcport->loop_id, lun, - flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID); - } + if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) + rval = qla26xx_marker(arg); done_free_sp: /* ref: INIT */ @@ -2080,6 +2186,115 @@ done: return rval; } +static void qla_put_tmf(fc_port_t *fcport) +{ + struct scsi_qla_host *vha = fcport->vha; + struct qla_hw_data *ha = vha->hw; + unsigned long flags; + + spin_lock_irqsave(&ha->tgt.sess_lock, flags); + fcport->active_tmf--; + spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); +} + +static +int qla_get_tmf(fc_port_t *fcport) +{ + struct scsi_qla_host *vha = fcport->vha; + struct qla_hw_data *ha = vha->hw; + unsigned long flags; + int rc = 0; + LIST_HEAD(tmf_elem); + + spin_lock_irqsave(&ha->tgt.sess_lock, flags); + list_add_tail(&tmf_elem, &fcport->tmf_pending); + + while (fcport->active_tmf >= MAX_ACTIVE_TMF) { + spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); + + msleep(1); + + spin_lock_irqsave(&ha->tgt.sess_lock, flags); + if (TMF_NOT_READY(fcport)) { + ql_log(ql_log_warn, vha, 0x802c, + "Unable to acquire TM resource due to disruption.\n"); + rc = EIO; + break; + } + if (fcport->active_tmf < MAX_ACTIVE_TMF && + list_is_first(&tmf_elem, &fcport->tmf_pending)) + break; + } + + list_del(&tmf_elem); + + if (!rc) + fcport->active_tmf++; + + spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); + + return rc; +} + +int +qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, + uint32_t tag) +{ + struct scsi_qla_host *vha = fcport->vha; + struct qla_qpair *qpair; + struct tmf_arg a; + int i, rval = QLA_SUCCESS; + + if (TMF_NOT_READY(fcport)) + return QLA_SUSPENDED; + + a.vha = fcport->vha; + a.fcport = fcport; + a.lun = lun; + if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET|TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) { + a.modifier = MK_SYNC_ID_LUN; + + if (qla_get_tmf(fcport)) + return QLA_FUNCTION_FAILED; + } else { + a.modifier = MK_SYNC_ID; + } + + if (vha->hw->mqenable) { + for (i = 0; i < vha->hw->num_qpairs; i++) { + qpair = vha->hw->queue_pair_map[i]; + if (!qpair) + continue; + + if (TMF_NOT_READY(fcport)) { + ql_log(ql_log_warn, vha, 0x8026, + "Unable to send TM due to disruption.\n"); + rval = QLA_SUSPENDED; + break; + } + + a.qpair = qpair; + a.flags = flags|TCF_NOTMCMD_TO_TARGET; + rval = __qla2x00_async_tm_cmd(&a); + if (rval) + break; + } + } + + if (rval) + goto bailout; + + a.qpair = vha->hw->base_qpair; + a.flags = flags; + rval = __qla2x00_async_tm_cmd(&a); + +bailout: + if (a.modifier == MK_SYNC_ID_LUN) + qla_put_tmf(fcport); + + return rval; +} + int qla24xx_async_abort_command(srb_t *sp) { @@ -4861,7 +5076,7 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, if (use_tbl && ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && index < QLA_MODEL_NAMES) - strlcpy(ha->model_desc, + strscpy(ha->model_desc, qla2x00_model_name[index * 2 + 1], sizeof(ha->model_desc)); } else { @@ -4869,14 +5084,14 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, if (use_tbl && ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && index < QLA_MODEL_NAMES) { - strlcpy(ha->model_number, + strscpy(ha->model_number, qla2x00_model_name[index * 2], sizeof(ha->model_number)); - strlcpy(ha->model_desc, + strscpy(ha->model_desc, qla2x00_model_name[index * 2 + 1], sizeof(ha->model_desc)); } else { - strlcpy(ha->model_number, def, + strscpy(ha->model_number, def, sizeof(ha->model_number)); } } @@ -5291,6 +5506,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags) INIT_WORK(&fcport->reg_work, qla_register_fcport_fn); INIT_LIST_HEAD(&fcport->gnl_entry); INIT_LIST_HEAD(&fcport->list); + INIT_LIST_HEAD(&fcport->tmf_pending); INIT_LIST_HEAD(&fcport->sess_cmd_list); spin_lock_init(&fcport->sess_cmd_lock); @@ -5333,7 +5549,7 @@ static void qla_get_login_template(scsi_qla_host_t *vha) __be32 *q; memset(ha->init_cb, 0, ha->init_cb_size); - sz = min_t(int, sizeof(struct fc_els_flogi), ha->init_cb_size); + sz = min_t(int, sizeof(struct fc_els_csp), ha->init_cb_size); rval = qla24xx_get_port_login_templ(vha, ha->init_cb_dma, ha->init_cb, sz); if (rval != QLA_SUCCESS) { @@ -6004,7 +6220,6 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) fc_port_t *fcport; uint16_t mb[MAILBOX_REGISTER_COUNT]; uint16_t loop_id; - LIST_HEAD(new_fcports); struct qla_hw_data *ha = vha->hw; int discovery_gen; diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index 7b42558a8839..0167e85ba058 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -109,11 +109,13 @@ qla2x00_set_fcport_disc_state(fc_port_t *fcport, int state) { int old_val; uint8_t shiftbits, mask; + uint8_t port_dstate_str_sz; /* This will have to change when the max no. of states > 16 */ shiftbits = 4; mask = (1 << shiftbits) - 1; + port_dstate_str_sz = sizeof(port_dstate_str) / sizeof(char *); fcport->disc_state = state; while (1) { old_val = atomic_read(&fcport->shadow_disc_state); @@ -121,7 +123,8 @@ qla2x00_set_fcport_disc_state(fc_port_t *fcport, int state) old_val, (old_val << shiftbits) | state)) { ql_dbg(ql_dbg_disc, fcport->vha, 0x2134, "FCPort %8phC disc_state transition: %s to %s - portid=%06x.\n", - fcport->port_name, port_dstate_str[old_val & mask], + fcport->port_name, (old_val & mask) < port_dstate_str_sz ? + port_dstate_str[old_val & mask] : "Unknown", port_dstate_str[state], fcport->d_id.b24); return; } diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index b9b3e6f80ea9..a1675f056a5c 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -522,21 +522,25 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct qla_qpair *qpair, return (QLA_FUNCTION_FAILED); } + mrk24 = (struct mrk_entry_24xx *)mrk; + mrk->entry_type = MARKER_TYPE; mrk->modifier = type; if (type != MK_SYNC_ALL) { if (IS_FWI2_CAPABLE(ha)) { - mrk24 = (struct mrk_entry_24xx *) mrk; mrk24->nport_handle = cpu_to_le16(loop_id); int_to_scsilun(lun, (struct scsi_lun *)&mrk24->lun); host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun)); mrk24->vp_index = vha->vp_idx; - mrk24->handle = make_handle(req->id, mrk24->handle); } else { SET_TARGET_ID(ha, mrk->target, loop_id); mrk->lun = cpu_to_le16((uint16_t)lun); } } + + if (IS_FWI2_CAPABLE(ha)) + mrk24->handle = QLA_SKIP_HANDLE; + wmb(); qla2x00_start_iocbs(vha, req); @@ -603,7 +607,8 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, put_unaligned_le32(COMMAND_TYPE_6, &cmd_pkt->entry_type); /* No data transfer */ - if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { + if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE || + tot_dsds == 0) { cmd_pkt->byte_count = cpu_to_le32(0); return 0; } @@ -2541,7 +2546,7 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk) scsi_qla_host_t *vha = fcport->vha; struct qla_hw_data *ha = vha->hw; struct srb_iocb *iocb = &sp->u.iocb_cmd; - struct req_que *req = vha->req; + struct req_que *req = sp->qpair->req; flags = iocb->u.tmf.flags; lun = iocb->u.tmf.lun; @@ -2557,7 +2562,8 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk) tsk->port_id[2] = fcport->d_id.b.domain; tsk->vp_index = fcport->vha->vp_idx; - if (flags == TCF_LUN_RESET) { + if (flags & (TCF_LUN_RESET | TCF_ABORT_TASK_SET| + TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) { int_to_scsilun(lun, &tsk->lun); host_to_fcp_swap((uint8_t *)&tsk->lun, sizeof(tsk->lun)); @@ -3852,9 +3858,9 @@ static int qla_get_iocbs_resource(struct srb *sp) case SRB_NACK_LOGO: case SRB_LOGOUT_CMD: case SRB_CTRL_VP: - push_it_through = true; - fallthrough; + case SRB_MARKER: default: + push_it_through = true; get_exch = false; } @@ -3870,6 +3876,19 @@ static int qla_get_iocbs_resource(struct srb *sp) return qla_get_fw_resources(sp->qpair, &sp->iores); } +static void +qla_marker_iocb(srb_t *sp, struct mrk_entry_24xx *mrk) +{ + mrk->entry_type = MARKER_TYPE; + mrk->modifier = sp->u.iocb_cmd.u.tmf.modifier; + if (sp->u.iocb_cmd.u.tmf.modifier != MK_SYNC_ALL) { + mrk->nport_handle = cpu_to_le16(sp->u.iocb_cmd.u.tmf.loop_id); + int_to_scsilun(sp->u.iocb_cmd.u.tmf.lun, (struct scsi_lun *)&mrk->lun); + host_to_fcp_swap(mrk->lun, sizeof(mrk->lun)); + mrk->vp_index = sp->u.iocb_cmd.u.tmf.vp_index; + } +} + int qla2x00_start_sp(srb_t *sp) { @@ -3973,6 +3992,9 @@ qla2x00_start_sp(srb_t *sp) case SRB_SA_REPLACE: qla24xx_sa_replace_iocb(sp, pkt); break; + case SRB_MARKER: + qla_marker_iocb(sp, pkt); + break; default: break; } diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 245e3a5d81fd..656700f79325 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1862,9 +1862,9 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha, } } -srb_t * -qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func, - struct req_que *req, void *iocb) +static srb_t * +qla_get_sp_from_handle(scsi_qla_host_t *vha, const char *func, + struct req_que *req, void *iocb, u16 *ret_index) { struct qla_hw_data *ha = vha->hw; sts_entry_t *pkt = iocb; @@ -1899,12 +1899,25 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func, return NULL; } - req->outstanding_cmds[index] = NULL; - + *ret_index = index; qla_put_fw_resources(sp->qpair, &sp->iores); return sp; } +srb_t * +qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func, + struct req_que *req, void *iocb) +{ + uint16_t index; + srb_t *sp; + + sp = qla_get_sp_from_handle(vha, func, req, iocb, &index); + if (sp) + req->outstanding_cmds[index] = NULL; + + return sp; +} + static void qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, struct mbx_entry *mbx) @@ -3237,13 +3250,13 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) return; } - req->outstanding_cmds[handle] = NULL; cp = GET_CMD_SP(sp); if (cp == NULL) { ql_dbg(ql_dbg_io, vha, 0x3018, "Command already returned (0x%x/%p).\n", sts->handle, sp); + req->outstanding_cmds[handle] = NULL; return; } @@ -3514,6 +3527,9 @@ out: if (rsp->status_srb == NULL) sp->done(sp, res); + + /* for io's, clearing of outstanding_cmds[handle] means scsi_done was called */ + req->outstanding_cmds[handle] = NULL; } /** @@ -3590,6 +3606,7 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt) uint16_t que = MSW(pkt->handle); struct req_que *req = NULL; int res = DID_ERROR << 16; + u16 index; ql_dbg(ql_dbg_async, vha, 0x502a, "iocb type %xh with error status %xh, handle %xh, rspq id %d\n", @@ -3608,7 +3625,6 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt) switch (pkt->entry_type) { case NOTIFY_ACK_TYPE: - case STATUS_TYPE: case STATUS_CONT_TYPE: case LOGINOUT_PORT_IOCB_TYPE: case CT_IOCB_TYPE: @@ -3628,6 +3644,14 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt) case CTIO_TYPE7: case CTIO_CRC2: return 1; + case STATUS_TYPE: + sp = qla_get_sp_from_handle(vha, func, req, pkt, &index); + if (sp) { + sp->done(sp, res); + req->outstanding_cmds[index] = NULL; + return 0; + } + break; } fatal: ql_log(ql_log_warn, vha, 0x5030, @@ -3750,6 +3774,28 @@ static int qla_chk_cont_iocb_avail(struct scsi_qla_host *vha, return rc; } +static void qla_marker_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, + struct mrk_entry_24xx *pkt) +{ + const char func[] = "MRK-IOCB"; + srb_t *sp; + int res = QLA_SUCCESS; + + if (!IS_FWI2_CAPABLE(vha->hw)) + return; + + sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); + if (!sp) + return; + + if (pkt->entry_status) { + ql_dbg(ql_dbg_taskm, vha, 0x8025, "marker failure.\n"); + res = QLA_COMMAND_ERROR; + } + sp->u.iocb_cmd.u.tmf.data = res; + sp->done(sp, res); +} + /** * qla24xx_process_response_queue() - Process response queue entries. * @vha: SCSI driver HA context @@ -3866,9 +3912,7 @@ process_err: (struct nack_to_isp *)pkt); break; case MARKER_TYPE: - /* Do nothing in this case, this check is to prevent it - * from falling into default case - */ + qla_marker_iocb_entry(vha, rsp->req, (struct mrk_entry_24xx *)pkt); break; case ABORT_IOCB_TYPE: qla24xx_abort_iocb_entry(vha, rsp->req, diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index f726eb8449c5..083f94e43fba 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -691,7 +691,7 @@ qlafx00_pci_info_str(struct scsi_qla_host *vha, char *str, size_t str_len) struct qla_hw_data *ha = vha->hw; if (pci_is_pcie(ha->pdev)) - strlcpy(str, "PCIe iSA", str_len); + strscpy(str, "PCIe iSA", str_len); return str; } @@ -1850,21 +1850,21 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) phost_info = &preg_hsi->hsi; memset(preg_hsi, 0, sizeof(struct register_host_info)); phost_info->os_type = OS_TYPE_LINUX; - strlcpy(phost_info->sysname, p_sysid->sysname, + strscpy(phost_info->sysname, p_sysid->sysname, sizeof(phost_info->sysname)); - strlcpy(phost_info->nodename, p_sysid->nodename, + strscpy(phost_info->nodename, p_sysid->nodename, sizeof(phost_info->nodename)); if (!strcmp(phost_info->nodename, "(none)")) ha->mr.host_info_resend = true; - strlcpy(phost_info->release, p_sysid->release, + strscpy(phost_info->release, p_sysid->release, sizeof(phost_info->release)); - strlcpy(phost_info->version, p_sysid->version, + strscpy(phost_info->version, p_sysid->version, sizeof(phost_info->version)); - strlcpy(phost_info->machine, p_sysid->machine, + strscpy(phost_info->machine, p_sysid->machine, sizeof(phost_info->machine)); - strlcpy(phost_info->domainname, p_sysid->domainname, + strscpy(phost_info->domainname, p_sysid->domainname, sizeof(phost_info->domainname)); - strlcpy(phost_info->hostdriver, QLA2XXX_VERSION, + strscpy(phost_info->hostdriver, QLA2XXX_VERSION, sizeof(phost_info->hostdriver)); preg_hsi->utc = (uint64_t)ktime_get_real_seconds(); ql_dbg(ql_dbg_init, vha, 0x0149, @@ -1909,9 +1909,9 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) if (fx_type == FXDISC_GET_CONFIG_INFO) { struct config_info_data *pinfo = (struct config_info_data *) fdisc->u.fxiocb.rsp_addr; - strlcpy(vha->hw->model_number, pinfo->model_num, + strscpy(vha->hw->model_number, pinfo->model_num, ARRAY_SIZE(vha->hw->model_number)); - strlcpy(vha->hw->model_desc, pinfo->model_description, + strscpy(vha->hw->model_desc, pinfo->model_description, ARRAY_SIZE(vha->hw->model_desc)); memcpy(&vha->hw->mr.symbolic_name, pinfo->symbolic_name, sizeof(vha->hw->mr.symbolic_name)); diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index 648e8f798606..86e85f2f4782 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -360,7 +360,6 @@ static int qla_nvme_ls_req(struct nvme_fc_local_port *lport, if (rval != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0x700e, "qla2x00_start_sp failed = %d\n", rval); - wake_up(&sp->nvme_ls_waitq); sp->priv = NULL; priv->sp = NULL; qla2x00_rel_sp(sp); @@ -652,7 +651,6 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport, if (!sp) return -EBUSY; - init_waitqueue_head(&sp->nvme_ls_waitq); kref_init(&sp->cmd_kref); spin_lock_init(&priv->cmd_lock); sp->priv = priv; @@ -671,7 +669,6 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport, if (rval != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0x212d, "qla2x00_start_nvme_mq failed = %d\n", rval); - wake_up(&sp->nvme_ls_waitq); sp->priv = NULL; priv->sp = NULL; qla2xxx_rel_qpair_sp(sp->qpair, sp); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 2fa695bf38b7..877e4f446709 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1079,43 +1079,6 @@ qc24_fail_command: } /* - * qla2x00_eh_wait_on_command - * Waits for the command to be returned by the Firmware for some - * max time. - * - * Input: - * cmd = Scsi Command to wait on. - * - * Return: - * Completed in time : QLA_SUCCESS - * Did not complete in time : QLA_FUNCTION_FAILED - */ -static int -qla2x00_eh_wait_on_command(struct scsi_cmnd *cmd) -{ -#define ABORT_POLLING_PERIOD 1000 -#define ABORT_WAIT_ITER ((2 * 1000) / (ABORT_POLLING_PERIOD)) - unsigned long wait_iter = ABORT_WAIT_ITER; - scsi_qla_host_t *vha = shost_priv(cmd->device->host); - struct qla_hw_data *ha = vha->hw; - srb_t *sp = scsi_cmd_priv(cmd); - int ret = QLA_SUCCESS; - - if (unlikely(pci_channel_offline(ha->pdev)) || ha->flags.eeh_busy) { - ql_dbg(ql_dbg_taskm, vha, 0x8005, - "Return:eh_wait.\n"); - return ret; - } - - while (sp->type && wait_iter--) - msleep(ABORT_POLLING_PERIOD); - if (sp->type) - ret = QLA_FUNCTION_FAILED; - - return ret; -} - -/* * qla2x00_wait_for_hba_online * Wait till the HBA is online after going through * <= MAX_RETRIES_OF_ISP_ABORT or @@ -1365,6 +1328,9 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) return ret; } +#define ABORT_POLLING_PERIOD 1000 +#define ABORT_WAIT_ITER ((2 * 1000) / (ABORT_POLLING_PERIOD)) + /* * Returns: QLA_SUCCESS or QLA_FUNCTION_FAILED. */ @@ -1378,41 +1344,73 @@ __qla2x00_eh_wait_for_pending_commands(struct qla_qpair *qpair, unsigned int t, struct req_que *req = qpair->req; srb_t *sp; struct scsi_cmnd *cmd; + unsigned long wait_iter = ABORT_WAIT_ITER; + bool found; + struct qla_hw_data *ha = vha->hw; status = QLA_SUCCESS; - spin_lock_irqsave(qpair->qp_lock_ptr, flags); - for (cnt = 1; status == QLA_SUCCESS && - cnt < req->num_outstanding_cmds; cnt++) { - sp = req->outstanding_cmds[cnt]; - if (!sp) - continue; - if (sp->type != SRB_SCSI_CMD) - continue; - if (vha->vp_idx != sp->vha->vp_idx) - continue; - match = 0; - cmd = GET_CMD_SP(sp); - switch (type) { - case WAIT_HOST: - match = 1; - break; - case WAIT_TARGET: - match = cmd->device->id == t; - break; - case WAIT_LUN: - match = (cmd->device->id == t && - cmd->device->lun == l); - break; - } - if (!match) - continue; + while (wait_iter--) { + found = false; - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); - status = qla2x00_eh_wait_on_command(cmd); spin_lock_irqsave(qpair->qp_lock_ptr, flags); + for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) { + sp = req->outstanding_cmds[cnt]; + if (!sp) + continue; + if (sp->type != SRB_SCSI_CMD) + continue; + if (vha->vp_idx != sp->vha->vp_idx) + continue; + match = 0; + cmd = GET_CMD_SP(sp); + switch (type) { + case WAIT_HOST: + match = 1; + break; + case WAIT_TARGET: + if (sp->fcport) + match = sp->fcport->d_id.b24 == t; + else + match = 0; + break; + case WAIT_LUN: + if (sp->fcport) + match = (sp->fcport->d_id.b24 == t && + cmd->device->lun == l); + else + match = 0; + break; + } + if (!match) + continue; + + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + + if (unlikely(pci_channel_offline(ha->pdev)) || + ha->flags.eeh_busy) { + ql_dbg(ql_dbg_taskm, vha, 0x8005, + "Return:eh_wait.\n"); + return status; + } + + /* + * SRB_SCSI_CMD is still in the outstanding_cmds array. + * it means scsi_done has not called. Wait for it to + * clear from outstanding_cmds. + */ + msleep(ABORT_POLLING_PERIOD); + spin_lock_irqsave(qpair->qp_lock_ptr, flags); + found = true; + } + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + + if (!found) + break; } - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + + if (wait_iter == -1) + status = QLA_FUNCTION_FAILED; return status; } @@ -5090,7 +5088,8 @@ struct scsi_qla_host *qla2x00_create_host(const struct scsi_host_template *sht, } INIT_DELAYED_WORK(&vha->scan.scan_work, qla_scan_work_fn); - sprintf(vha->host_str, "%s_%lu", QLA2XXX_DRIVER_NAME, vha->host_no); + snprintf(vha->host_str, sizeof(vha->host_str), "%s_%lu", + QLA2XXX_DRIVER_NAME, vha->host_no); ql_dbg(ql_dbg_init, vha, 0x0041, "Allocated the host=%p hw=%p vha=%p dev_name=%s", vha->host, vha->hw, vha, diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 42d69d89834f..e3771923b0d7 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -6,9 +6,9 @@ /* * Driver version */ -#define QLA2XXX_VERSION "10.02.08.200-k" +#define QLA2XXX_VERSION "10.02.08.400-k" #define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MINOR_VER 2 #define QLA_DRIVER_PATCH_VER 8 -#define QLA_DRIVER_BETA_VER 200 +#define QLA_DRIVER_BETA_VER 400 diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index cd71074f3abe..249f1d7021d4 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -1611,8 +1611,8 @@ int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password, goto exit_get_chap; } - strlcpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); - strlcpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN); + strscpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); + strscpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN); chap_table->cookie = cpu_to_le16(CHAP_VALID_COOKIE); exit_get_chap: @@ -1732,8 +1732,8 @@ int qla4xxx_get_uni_chap_at_index(struct scsi_qla_host *ha, char *username, goto exit_unlock_uni_chap; } - strlcpy(password, chap_table->secret, MAX_CHAP_SECRET_LEN); - strlcpy(username, chap_table->name, MAX_CHAP_NAME_LEN); + strscpy(password, chap_table->secret, MAX_CHAP_SECRET_LEN); + strscpy(username, chap_table->name, MAX_CHAP_NAME_LEN); rval = QLA_SUCCESS; diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index ee6d784c095c..b2a3988e1e15 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -798,9 +798,9 @@ static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx, continue; chap_rec->chap_tbl_idx = i; - strlcpy(chap_rec->username, chap_table->name, + strscpy(chap_rec->username, chap_table->name, ISCSI_CHAP_AUTH_NAME_MAX_LEN); - strlcpy(chap_rec->password, chap_table->secret, + strscpy(chap_rec->password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); chap_rec->password_length = chap_table->secret_len; @@ -6052,8 +6052,8 @@ static int qla4xxx_get_bidi_chap(struct scsi_qla_host *ha, char *username, if (!(chap_table->flags & BIT_6)) /* Not BIDI */ continue; - strlcpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); - strlcpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN); + strscpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); + strscpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN); ret = 0; break; } @@ -6281,8 +6281,8 @@ static void qla4xxx_get_param_ddb(struct ddb_entry *ddb_entry, tddb->tpgt = sess->tpgt; tddb->port = conn->persistent_port; - strlcpy(tddb->iscsi_name, sess->targetname, ISCSI_NAME_SIZE); - strlcpy(tddb->ip_addr, conn->persistent_address, DDB_IPADDR_LEN); + strscpy(tddb->iscsi_name, sess->targetname, ISCSI_NAME_SIZE); + strscpy(tddb->ip_addr, conn->persistent_address, DDB_IPADDR_LEN); } static void qla4xxx_convert_param_ddb(struct dev_db_entry *fw_ddb_entry, @@ -7781,7 +7781,7 @@ static int qla4xxx_sysfs_ddb_logout(struct iscsi_bus_flash_session *fnode_sess, goto exit_ddb_logout; } - strlcpy(flash_tddb->iscsi_name, fnode_sess->targetname, + strscpy(flash_tddb->iscsi_name, fnode_sess->targetname, ISCSI_NAME_SIZE); if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4)) diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 09ef0b31dfc0..c4bf99a842f3 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -504,18 +504,22 @@ void scsi_attach_vpd(struct scsi_device *sdev) } /** - * scsi_report_opcode - Find out if a given command opcode is supported + * scsi_report_opcode - Find out if a given command is supported * @sdev: scsi device to query * @buffer: scratch buffer (must be at least 20 bytes long) * @len: length of buffer - * @opcode: opcode for command to look up - * - * Uses the REPORT SUPPORTED OPERATION CODES to look up the given - * opcode. Returns -EINVAL if RSOC fails, 0 if the command opcode is - * unsupported and 1 if the device claims to support the command. + * @opcode: opcode for the command to look up + * @sa: service action for the command to look up + * + * Uses the REPORT SUPPORTED OPERATION CODES to check support for the + * command identified with @opcode and @sa. If the command does not + * have a service action, @sa must be 0. Returns -EINVAL if RSOC fails, + * 0 if the command is not supported and 1 if the device claims to + * support the command. */ int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer, - unsigned int len, unsigned char opcode) + unsigned int len, unsigned char opcode, + unsigned short sa) { unsigned char cmd[16]; struct scsi_sense_hdr sshdr; @@ -539,8 +543,14 @@ int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer, memset(cmd, 0, 16); cmd[0] = MAINTENANCE_IN; cmd[1] = MI_REPORT_SUPPORTED_OPERATION_CODES; - cmd[2] = 1; /* One command format */ - cmd[3] = opcode; + if (!sa) { + cmd[2] = 1; /* One command format */ + cmd[3] = opcode; + } else { + cmd[2] = 3; /* One command format with service action */ + cmd[3] = opcode; + put_unaligned_be16(sa, &cmd[4]); + } put_unaligned_be32(request_len, &cmd[6]); memset(buffer, 0, len); @@ -560,6 +570,149 @@ int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer, } EXPORT_SYMBOL(scsi_report_opcode); +#define SCSI_CDL_CHECK_BUF_LEN 64 + +static bool scsi_cdl_check_cmd(struct scsi_device *sdev, u8 opcode, u16 sa, + unsigned char *buf) +{ + int ret; + u8 cdlp; + + /* Check operation code */ + ret = scsi_report_opcode(sdev, buf, SCSI_CDL_CHECK_BUF_LEN, opcode, sa); + if (ret <= 0) + return false; + + if ((buf[1] & 0x03) != 0x03) + return false; + + /* See SPC-6, one command format of REPORT SUPPORTED OPERATION CODES */ + cdlp = (buf[1] & 0x18) >> 3; + if (buf[0] & 0x01) { + /* rwcdlp == 1 */ + switch (cdlp) { + case 0x01: + /* T2A page */ + return true; + case 0x02: + /* T2B page */ + return true; + } + } else { + /* rwcdlp == 0 */ + switch (cdlp) { + case 0x01: + /* A page */ + return true; + case 0x02: + /* B page */ + return true; + } + } + + return false; +} + +/** + * scsi_cdl_check - Check if a SCSI device supports Command Duration Limits + * @sdev: The device to check + */ +void scsi_cdl_check(struct scsi_device *sdev) +{ + bool cdl_supported; + unsigned char *buf; + + buf = kmalloc(SCSI_CDL_CHECK_BUF_LEN, GFP_KERNEL); + if (!buf) { + sdev->cdl_supported = 0; + return; + } + + /* Check support for READ_16, WRITE_16, READ_32 and WRITE_32 commands */ + cdl_supported = + scsi_cdl_check_cmd(sdev, READ_16, 0, buf) || + scsi_cdl_check_cmd(sdev, WRITE_16, 0, buf) || + scsi_cdl_check_cmd(sdev, VARIABLE_LENGTH_CMD, READ_32, buf) || + scsi_cdl_check_cmd(sdev, VARIABLE_LENGTH_CMD, WRITE_32, buf); + if (cdl_supported) { + /* + * We have CDL support: force the use of READ16/WRITE16. + * READ32 and WRITE32 will be used for devices that support + * the T10_PI_TYPE2_PROTECTION protection type. + */ + sdev->use_16_for_rw = 1; + sdev->use_10_for_rw = 0; + + sdev->cdl_supported = 1; + } else { + sdev->cdl_supported = 0; + } + + kfree(buf); +} + +/** + * scsi_cdl_enable - Enable or disable a SCSI device supports for Command + * Duration Limits + * @sdev: The target device + * @enable: the target state + */ +int scsi_cdl_enable(struct scsi_device *sdev, bool enable) +{ + struct scsi_mode_data data; + struct scsi_sense_hdr sshdr; + struct scsi_vpd *vpd; + bool is_ata = false; + char buf[64]; + int ret; + + if (!sdev->cdl_supported) + return -EOPNOTSUPP; + + rcu_read_lock(); + vpd = rcu_dereference(sdev->vpd_pg89); + if (vpd) + is_ata = true; + rcu_read_unlock(); + + /* + * For ATA devices, CDL needs to be enabled with a SET FEATURES command. + */ + if (is_ata) { + char *buf_data; + int len; + + ret = scsi_mode_sense(sdev, 0x08, 0x0a, 0xf2, buf, sizeof(buf), + 5 * HZ, 3, &data, NULL); + if (ret) + return -EINVAL; + + /* Enable CDL using the ATA feature page */ + len = min_t(size_t, sizeof(buf), + data.length - data.header_length - + data.block_descriptor_length); + buf_data = buf + data.header_length + + data.block_descriptor_length; + if (enable) + buf_data[4] = 0x02; + else + buf_data[4] = 0; + + ret = scsi_mode_select(sdev, 1, 0, buf_data, len, 5 * HZ, 3, + &data, &sshdr); + if (ret) { + if (scsi_sense_valid(&sshdr)) + scsi_print_sense_hdr(sdev, + dev_name(&sdev->sdev_gendev), &sshdr); + return ret; + } + } + + sdev->cdl_enable = enable; + + return 0; +} + /** * scsi_device_get - get an additional reference to a scsi_device * @sdev: device to get a reference to diff --git a/drivers/scsi/scsi_common.c b/drivers/scsi/scsi_common.c index 6e50e81a8216..9c14fdf61037 100644 --- a/drivers/scsi/scsi_common.c +++ b/drivers/scsi/scsi_common.c @@ -8,6 +8,7 @@ #include <linux/string.h> #include <linux/errno.h> #include <linux/module.h> +#include <uapi/linux/pr.h> #include <asm/unaligned.h> #include <scsi/scsi_common.h> @@ -63,6 +64,48 @@ const char *scsi_device_type(unsigned type) } EXPORT_SYMBOL(scsi_device_type); +enum pr_type scsi_pr_type_to_block(enum scsi_pr_type type) +{ + switch (type) { + case SCSI_PR_WRITE_EXCLUSIVE: + return PR_WRITE_EXCLUSIVE; + case SCSI_PR_EXCLUSIVE_ACCESS: + return PR_EXCLUSIVE_ACCESS; + case SCSI_PR_WRITE_EXCLUSIVE_REG_ONLY: + return PR_WRITE_EXCLUSIVE_REG_ONLY; + case SCSI_PR_EXCLUSIVE_ACCESS_REG_ONLY: + return PR_EXCLUSIVE_ACCESS_REG_ONLY; + case SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS: + return PR_WRITE_EXCLUSIVE_ALL_REGS; + case SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS: + return PR_EXCLUSIVE_ACCESS_ALL_REGS; + } + + return 0; +} +EXPORT_SYMBOL_GPL(scsi_pr_type_to_block); + +enum scsi_pr_type block_pr_type_to_scsi(enum pr_type type) +{ + switch (type) { + case PR_WRITE_EXCLUSIVE: + return SCSI_PR_WRITE_EXCLUSIVE; + case PR_EXCLUSIVE_ACCESS: + return SCSI_PR_EXCLUSIVE_ACCESS; + case PR_WRITE_EXCLUSIVE_REG_ONLY: + return SCSI_PR_WRITE_EXCLUSIVE_REG_ONLY; + case PR_EXCLUSIVE_ACCESS_REG_ONLY: + return SCSI_PR_EXCLUSIVE_ACCESS_REG_ONLY; + case PR_WRITE_EXCLUSIVE_ALL_REGS: + return SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS; + case PR_EXCLUSIVE_ACCESS_ALL_REGS: + return SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS; + } + + return 0; +} +EXPORT_SYMBOL_GPL(block_pr_type_to_scsi); + /** * scsilun_to_int - convert a scsi_lun to an int * @scsilun: struct scsi_lun to be converted. @@ -176,8 +219,7 @@ bool scsi_normalize_sense(const u8 *sense_buffer, int sb_len, if (sb_len > 2) sshdr->sense_key = (sense_buffer[2] & 0xf); if (sb_len > 7) { - sb_len = (sb_len < (sense_buffer[7] + 8)) ? - sb_len : (sense_buffer[7] + 8); + sb_len = min(sb_len, sense_buffer[7] + 8); if (sb_len > 12) sshdr->asc = sense_buffer[12]; if (sb_len > 13) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 3ec8bfd4090f..c67cdcdc3ba8 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -536,6 +536,7 @@ static inline void set_scsi_ml_byte(struct scsi_cmnd *cmd, u8 status) */ enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd) { + struct request *req = scsi_cmd_to_rq(scmd); struct scsi_device *sdev = scmd->device; struct scsi_sense_hdr sshdr; @@ -595,6 +596,22 @@ enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd) if (sshdr.asc == 0x10) /* DIF */ return SUCCESS; + /* + * Check aborts due to command duration limit policy: + * ABORTED COMMAND additional sense code with the + * COMMAND TIMEOUT BEFORE PROCESSING or + * COMMAND TIMEOUT DURING PROCESSING or + * COMMAND TIMEOUT DURING PROCESSING DUE TO ERROR RECOVERY + * additional sense code qualifiers. + */ + if (sshdr.asc == 0x2e && + sshdr.ascq >= 0x01 && sshdr.ascq <= 0x03) { + set_scsi_ml_byte(scmd, SCSIML_STAT_DL_TIMEOUT); + req->cmd_flags |= REQ_FAILFAST_DEV; + req->rq_flags |= RQF_QUIET; + return SUCCESS; + } + if (sshdr.asc == 0x44 && sdev->sdev_bflags & BLIST_RETRY_ITF) return ADD_TO_MLQUEUE; if (sshdr.asc == 0xc1 && sshdr.ascq == 0x01 && @@ -691,6 +708,14 @@ enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd) } return SUCCESS; + case COMPLETED: + if (sshdr.asc == 0x55 && sshdr.ascq == 0x0a) { + set_scsi_ml_byte(scmd, SCSIML_STAT_DL_TIMEOUT); + req->cmd_flags |= REQ_FAILFAST_DEV; + req->rq_flags |= RQF_QUIET; + } + return SUCCESS; + default: return SUCCESS; } @@ -785,6 +810,14 @@ static enum scsi_disposition scsi_eh_completed_normally(struct scsi_cmnd *scmd) switch (get_status_byte(scmd)) { case SAM_STAT_GOOD: scsi_handle_queue_ramp_up(scmd->device); + if (scmd->sense_buffer && SCSI_SENSE_VALID(scmd)) + /* + * If we have sense data, call scsi_check_sense() in + * order to set the correct SCSI ML byte (if any). + * No point in checking the return value, since the + * command has already completed successfully. + */ + scsi_check_sense(scmd); fallthrough; case SAM_STAT_COMMAND_TERMINATED: return SUCCESS; @@ -1807,6 +1840,10 @@ bool scsi_noretry_cmd(struct scsi_cmnd *scmd) return !!(req->cmd_flags & REQ_FAILFAST_DRIVER); } + /* Never retry commands aborted due to a duration limit timeout */ + if (scsi_ml_byte(scmd->result) == SCSIML_STAT_DL_TIMEOUT) + return true; + if (!scsi_status_is_check_condition(scmd->result)) return false; @@ -1966,6 +2003,14 @@ enum scsi_disposition scsi_decide_disposition(struct scsi_cmnd *scmd) if (scmd->cmnd[0] == REPORT_LUNS) scmd->device->sdev_target->expecting_lun_change = 0; scsi_handle_queue_ramp_up(scmd->device); + if (scmd->sense_buffer && SCSI_SENSE_VALID(scmd)) + /* + * If we have sense data, call scsi_check_sense() in + * order to set the correct SCSI ML byte (if any). + * No point in checking the return value, since the + * command has already completed successfully. + */ + scsi_check_sense(scmd); fallthrough; case SAM_STAT_COMMAND_TERMINATED: return SUCCESS; @@ -2165,7 +2210,8 @@ void scsi_eh_flush_done_q(struct list_head *done_q) * scsi_eh_get_sense), scmd->result is already * set, do not set DID_TIME_OUT. */ - if (!scmd->result) + if (!scmd->result && + !(scmd->flags & SCMD_FORCE_EH_SUCCESS)) scmd->result |= (DID_TIME_OUT << 16); SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 0226c9279cef..ad9afae49544 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -122,11 +122,9 @@ static void scsi_mq_requeue_cmd(struct scsi_cmnd *cmd, unsigned long msecs) WARN_ON_ONCE(true); } - if (msecs) { - blk_mq_requeue_request(rq, false); + blk_mq_requeue_request(rq, false); + if (!scsi_host_in_recovery(cmd->device->host)) blk_mq_delay_kick_requeue_list(rq->q, msecs); - } else - blk_mq_requeue_request(rq, true); } /** @@ -165,7 +163,8 @@ static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, bool unbusy) */ cmd->result = 0; - blk_mq_requeue_request(scsi_cmd_to_rq(cmd), true); + blk_mq_requeue_request(scsi_cmd_to_rq(cmd), + !scsi_host_in_recovery(cmd->device->host)); } /** @@ -453,6 +452,7 @@ static void scsi_run_queue(struct request_queue *q) if (!list_empty(&sdev->host->starved_list)) scsi_starved_list_run(sdev->host); + blk_mq_kick_requeue_list(q); blk_mq_run_hw_queues(q, false); } @@ -503,6 +503,9 @@ static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) static void scsi_run_queue_async(struct scsi_device *sdev) { + if (scsi_host_in_recovery(sdev->host)) + return; + if (scsi_target(sdev)->single_lun || !list_empty(&sdev->host->starved_list)) { kblockd_schedule_work(&sdev->requeue_work); @@ -578,11 +581,6 @@ static bool scsi_end_request(struct request *req, blk_status_t error, return false; } -static inline u8 get_scsi_ml_byte(int result) -{ - return (result >> 8) & 0xff; -} - /** * scsi_result_to_blk_status - translate a SCSI result code into blk_status_t * @result: scsi error code @@ -595,17 +593,19 @@ static blk_status_t scsi_result_to_blk_status(int result) * Check the scsi-ml byte first in case we converted a host or status * byte. */ - switch (get_scsi_ml_byte(result)) { + switch (scsi_ml_byte(result)) { case SCSIML_STAT_OK: break; case SCSIML_STAT_RESV_CONFLICT: - return BLK_STS_NEXUS; + return BLK_STS_RESV_CONFLICT; case SCSIML_STAT_NOSPC: return BLK_STS_NOSPC; case SCSIML_STAT_MED_ERROR: return BLK_STS_MEDIUM; case SCSIML_STAT_TGT_FAILURE: return BLK_STS_TARGET; + case SCSIML_STAT_DL_TIMEOUT: + return BLK_STS_DURATION_LIMIT; } switch (host_byte(result)) { @@ -803,6 +803,8 @@ static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result) blk_stat = BLK_STS_ZONE_OPEN_RESOURCE; } break; + case COMPLETED: + fallthrough; default: action = ACTION_FAIL; break; @@ -1985,6 +1987,8 @@ int scsi_mq_setup_tags(struct Scsi_Host *shost) tag_set->flags = BLK_MQ_F_SHOULD_MERGE; tag_set->flags |= BLK_ALLOC_POLICY_TO_MQ_FLAG(shost->hostt->tag_alloc_policy); + if (shost->queuecommand_may_block) + tag_set->flags |= BLK_MQ_F_BLOCKING; tag_set->driver_data = shost; if (shost->host_tagset) tag_set->flags |= BLK_MQ_F_TAG_HCTX_SHARED; @@ -2152,6 +2156,7 @@ EXPORT_SYMBOL_GPL(scsi_mode_select); * @sdev: SCSI device to be queried * @dbd: set to prevent mode sense from returning block descriptors * @modepage: mode page being requested + * @subpage: sub-page of the mode page being requested * @buffer: request buffer (may not be smaller than eight bytes) * @len: length of request buffer. * @timeout: command timeout @@ -2163,7 +2168,7 @@ EXPORT_SYMBOL_GPL(scsi_mode_select); * Returns zero if successful, or a negative error number on failure */ int -scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, +scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, int subpage, unsigned char *buffer, int len, int timeout, int retries, struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr) { @@ -2183,6 +2188,7 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, dbd = sdev->set_dbd_for_ms ? 8 : dbd; cmd[1] = dbd & 0x18; /* allows DBD and LLBA bits */ cmd[2] = modepage; + cmd[3] = subpage; sshdr = exec_args.sshdr; @@ -2728,24 +2734,16 @@ void scsi_start_queue(struct scsi_device *sdev) blk_mq_unquiesce_queue(sdev->request_queue); } -static void scsi_stop_queue(struct scsi_device *sdev, bool nowait) +static void scsi_stop_queue(struct scsi_device *sdev) { /* * The atomic variable of ->queue_stopped covers that * blk_mq_quiesce_queue* is balanced with blk_mq_unquiesce_queue. * - * However, we still need to wait until quiesce is done - * in case that queue has been stopped. + * The caller needs to wait until quiesce is done. */ - if (!cmpxchg(&sdev->queue_stopped, 0, 1)) { - if (nowait) - blk_mq_quiesce_queue_nowait(sdev->request_queue); - else - blk_mq_quiesce_queue(sdev->request_queue); - } else { - if (!nowait) - blk_mq_wait_quiesce_done(sdev->request_queue->tag_set); - } + if (!cmpxchg(&sdev->queue_stopped, 0, 1)) + blk_mq_quiesce_queue_nowait(sdev->request_queue); } /** @@ -2772,19 +2770,19 @@ int scsi_internal_device_block_nowait(struct scsi_device *sdev) * request queue. */ if (!ret) - scsi_stop_queue(sdev, true); + scsi_stop_queue(sdev); return ret; } EXPORT_SYMBOL_GPL(scsi_internal_device_block_nowait); /** - * scsi_internal_device_block - try to transition to the SDEV_BLOCK state + * scsi_device_block - try to transition to the SDEV_BLOCK state * @sdev: device to block + * @data: dummy argument, ignored * - * Pause SCSI command processing on the specified device and wait until all - * ongoing scsi_request_fn() / scsi_queue_rq() calls have finished. May sleep. - * - * Returns zero if successful or a negative error code upon failure. + * Pause SCSI command processing on the specified device. Callers must wait + * until all ongoing scsi_queue_rq() calls have finished after this function + * returns. * * Note: * This routine transitions the device to the SDEV_BLOCK state (which must be @@ -2792,17 +2790,26 @@ EXPORT_SYMBOL_GPL(scsi_internal_device_block_nowait); * is paused until the device leaves the SDEV_BLOCK state. See also * scsi_internal_device_unblock(). */ -static int scsi_internal_device_block(struct scsi_device *sdev) +static void scsi_device_block(struct scsi_device *sdev, void *data) { int err; + enum scsi_device_state state; mutex_lock(&sdev->state_mutex); err = __scsi_internal_device_block_nowait(sdev); + state = sdev->sdev_state; if (err == 0) - scsi_stop_queue(sdev, false); + /* + * scsi_stop_queue() must be called with the state_mutex + * held. Otherwise a simultaneous scsi_start_queue() call + * might unquiesce the queue before we quiesce it. + */ + scsi_stop_queue(sdev); + mutex_unlock(&sdev->state_mutex); - return err; + WARN_ONCE(err, "%s: failed to block %s in state %d\n", + __func__, dev_name(&sdev->sdev_gendev), state); } /** @@ -2885,36 +2892,35 @@ static int scsi_internal_device_unblock(struct scsi_device *sdev, return ret; } -static void -device_block(struct scsi_device *sdev, void *data) -{ - int ret; - - ret = scsi_internal_device_block(sdev); - - WARN_ONCE(ret, "scsi_internal_device_block(%s) failed: ret = %d\n", - dev_name(&sdev->sdev_gendev), ret); -} - static int target_block(struct device *dev, void *data) { if (scsi_is_target_device(dev)) starget_for_each_device(to_scsi_target(dev), NULL, - device_block); + scsi_device_block); return 0; } +/** + * scsi_block_targets - transition all SCSI child devices to SDEV_BLOCK state + * @dev: a parent device of one or more scsi_target devices + * @shost: the Scsi_Host to which this device belongs + * + * Iterate over all children of @dev, which should be scsi_target devices, + * and switch all subordinate scsi devices to SDEV_BLOCK state. Wait for + * ongoing scsi_queue_rq() calls to finish. May sleep. + * + * Note: + * @dev must not itself be a scsi_target device. + */ void -scsi_target_block(struct device *dev) +scsi_block_targets(struct Scsi_Host *shost, struct device *dev) { - if (scsi_is_target_device(dev)) - starget_for_each_device(to_scsi_target(dev), NULL, - device_block); - else - device_for_each_child(dev, NULL, target_block); + WARN_ON_ONCE(scsi_is_target_device(dev)); + device_for_each_child(dev, NULL, target_block); + blk_mq_wait_quiesce_done(&shost->tag_set); } -EXPORT_SYMBOL_GPL(scsi_target_block); +EXPORT_SYMBOL_GPL(scsi_block_targets); static void device_unblock(struct scsi_device *sdev, void *data) @@ -2942,11 +2948,20 @@ scsi_target_unblock(struct device *dev, enum scsi_device_state new_state) } EXPORT_SYMBOL_GPL(scsi_target_unblock); +/** + * scsi_host_block - Try to transition all logical units to the SDEV_BLOCK state + * @shost: device to block + * + * Pause SCSI command processing for all logical units associated with the SCSI + * host and wait until pending scsi_queue_rq() calls have finished. + * + * Returns zero if successful or a negative error code upon failure. + */ int scsi_host_block(struct Scsi_Host *shost) { struct scsi_device *sdev; - int ret = 0; + int ret; /* * Call scsi_internal_device_block_nowait so we can avoid @@ -2958,20 +2973,14 @@ scsi_host_block(struct Scsi_Host *shost) mutex_unlock(&sdev->state_mutex); if (ret) { scsi_device_put(sdev); - break; + return ret; } } - /* - * SCSI never enables blk-mq's BLK_MQ_F_BLOCKING flag so - * calling synchronize_rcu() once is enough. - */ - WARN_ON_ONCE(shost->tag_set.flags & BLK_MQ_F_BLOCKING); - - if (!ret) - synchronize_rcu(); + /* Wait for ongoing scsi_queue_rq() calls to finish. */ + blk_mq_wait_quiesce_done(&shost->tag_set); - return ret; + return 0; } EXPORT_SYMBOL_GPL(scsi_host_block); diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 96284a0e13fe..f42388ecb024 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -27,8 +27,14 @@ enum scsi_ml_status { SCSIML_STAT_NOSPC = 0x02, /* Space allocation on the dev failed */ SCSIML_STAT_MED_ERROR = 0x03, /* Medium error */ SCSIML_STAT_TGT_FAILURE = 0x04, /* Permanent target failure */ + SCSIML_STAT_DL_TIMEOUT = 0x05, /* Command Duration Limit timeout */ }; +static inline u8 scsi_ml_byte(int result) +{ + return (result >> 8) & 0xff; +} + /* * Scsi Error Handler Flags */ diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index d217be323cc6..aa13feb17c62 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1087,6 +1087,8 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, if (sdev->scsi_level >= SCSI_3) scsi_attach_vpd(sdev); + scsi_cdl_check(sdev); + sdev->max_queue_depth = sdev->queue_depth; WARN_ON_ONCE(sdev->max_queue_depth > sdev->budget_map.depth); sdev->sdev_bflags = *bflags; @@ -1624,6 +1626,7 @@ void scsi_rescan_device(struct device *dev) device_lock(dev); scsi_attach_vpd(sdev); + scsi_cdl_check(sdev); if (sdev->handler && sdev->handler->rescan) sdev->handler->rescan(sdev); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 603e8fcfcb8a..60317676e45f 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -670,6 +670,7 @@ sdev_rd_attr (scsi_level, "%d\n"); sdev_rd_attr (vendor, "%.8s\n"); sdev_rd_attr (model, "%.16s\n"); sdev_rd_attr (rev, "%.4s\n"); +sdev_rd_attr (cdl_supported, "%d\n"); static ssize_t sdev_show_device_busy(struct device *dev, struct device_attribute *attr, @@ -1221,6 +1222,33 @@ static DEVICE_ATTR(queue_ramp_up_period, S_IRUGO | S_IWUSR, sdev_show_queue_ramp_up_period, sdev_store_queue_ramp_up_period); +static ssize_t sdev_show_cdl_enable(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct scsi_device *sdev = to_scsi_device(dev); + + return sysfs_emit(buf, "%d\n", (int)sdev->cdl_enable); +} + +static ssize_t sdev_store_cdl_enable(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret; + bool v; + + if (kstrtobool(buf, &v)) + return -EINVAL; + + ret = scsi_cdl_enable(to_scsi_device(dev), v); + if (ret) + return ret; + + return count; +} +static DEVICE_ATTR(cdl_enable, S_IRUGO | S_IWUSR, + sdev_show_cdl_enable, sdev_store_cdl_enable); + static umode_t scsi_sdev_attr_is_visible(struct kobject *kobj, struct attribute *attr, int i) { @@ -1300,6 +1328,8 @@ static struct attribute *scsi_sdev_attrs[] = { &dev_attr_preferred_path.attr, #endif &dev_attr_queue_ramp_up_period.attr, + &dev_attr_cdl_supported.attr, + &dev_attr_cdl_enable.attr, REF_EVT(media_change), REF_EVT(inquiry_change_reported), REF_EVT(capacity_change_reported), diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 64ff2629eaf9..b04075f19445 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -3451,7 +3451,7 @@ fc_remote_port_delete(struct fc_rport *rport) spin_unlock_irqrestore(shost->host_lock, flags); - scsi_target_block(&rport->dev); + scsi_block_targets(shost, &rport->dev); /* see if we need to kill io faster than waiting for device loss */ if ((rport->fast_io_fail_tmo != -1) && diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index b9b97300e3b3..e527ece12453 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1943,13 +1943,14 @@ static void __iscsi_block_session(struct work_struct *work) struct iscsi_cls_session *session = container_of(work, struct iscsi_cls_session, block_work); + struct Scsi_Host *shost = iscsi_session_to_shost(session); unsigned long flags; ISCSI_DBG_TRANS_SESSION(session, "Blocking session\n"); spin_lock_irqsave(&session->lock, flags); session->state = ISCSI_SESSION_FAILED; spin_unlock_irqrestore(&session->lock, flags); - scsi_target_block(&session->dev); + scsi_block_targets(shost, &session->dev); ISCSI_DBG_TRANS_SESSION(session, "Completed SCSI target blocking\n"); if (session->recovery_tmo >= 0) queue_delayed_work(session->workq, diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 74b99f2b0b74..d704c484a251 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -1245,7 +1245,7 @@ int sas_read_port_mode_page(struct scsi_device *sdev) if (!buffer) return -ENOMEM; - error = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3, + error = scsi_mode_sense(sdev, 1, 0x19, 0, buffer, BUF_SIZE, 30*HZ, 3, &mode_data, NULL); if (error) diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c index 87d0fb8dc503..64f6b22e8cc0 100644 --- a/drivers/scsi/scsi_transport_srp.c +++ b/drivers/scsi/scsi_transport_srp.c @@ -396,7 +396,7 @@ static void srp_reconnect_work(struct work_struct *work) } /* - * scsi_target_block() must have been called before this function is + * scsi_block_targets() must have been called before this function is * called to guarantee that no .queuecommand() calls are in progress. */ static void __rport_fail_io_fast(struct srp_rport *rport) @@ -480,7 +480,7 @@ static void __srp_start_tl_fail_timers(struct srp_rport *rport) srp_rport_set_state(rport, SRP_RPORT_BLOCKED) == 0) { pr_debug("%s new state: %d\n", dev_name(&shost->shost_gendev), rport->state); - scsi_target_block(&shost->shost_gendev); + scsi_block_targets(shost, &shost->shost_gendev); if (fast_io_fail_tmo >= 0) queue_delayed_work(system_long_wq, &rport->fast_io_fail_work, @@ -548,7 +548,7 @@ int srp_reconnect_rport(struct srp_rport *rport) * later is ok though, scsi_internal_device_unblock_nowait() * treats SDEV_TRANSPORT_OFFLINE like SDEV_BLOCK. */ - scsi_target_block(&shost->shost_gendev); + scsi_block_targets(shost, &shost->shost_gendev); res = rport->state != SRP_RPORT_LOST ? i->f->reconnect(rport) : -ENODEV; pr_debug("%s (state %d): transport.reconnect() returned %d\n", dev_name(&shost->shost_gendev), rport->state, res); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index ab216976dbdc..68b12afa0721 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -67,6 +67,7 @@ #include <scsi/scsi_host.h> #include <scsi/scsi_ioctl.h> #include <scsi/scsicam.h> +#include <scsi/scsi_common.h> #include "sd.h" #include "scsi_priv.h" @@ -183,7 +184,7 @@ cache_type_store(struct device *dev, struct device_attribute *attr, return count; } - if (scsi_mode_sense(sdp, 0x08, 8, buffer, sizeof(buffer), SD_TIMEOUT, + if (scsi_mode_sense(sdp, 0x08, 8, 0, buffer, sizeof(buffer), SD_TIMEOUT, sdkp->max_retries, &data, NULL)) return -EINVAL; len = min_t(size_t, sizeof(buffer), data.length - data.header_length - @@ -1041,13 +1042,14 @@ static blk_status_t sd_setup_flush_cmnd(struct scsi_cmnd *cmd) static blk_status_t sd_setup_rw32_cmnd(struct scsi_cmnd *cmd, bool write, sector_t lba, unsigned int nr_blocks, - unsigned char flags) + unsigned char flags, unsigned int dld) { cmd->cmd_len = SD_EXT_CDB_SIZE; cmd->cmnd[0] = VARIABLE_LENGTH_CMD; cmd->cmnd[7] = 0x18; /* Additional CDB len */ cmd->cmnd[9] = write ? WRITE_32 : READ_32; cmd->cmnd[10] = flags; + cmd->cmnd[11] = dld & 0x07; put_unaligned_be64(lba, &cmd->cmnd[12]); put_unaligned_be32(lba, &cmd->cmnd[20]); /* Expected Indirect LBA */ put_unaligned_be32(nr_blocks, &cmd->cmnd[28]); @@ -1057,12 +1059,12 @@ static blk_status_t sd_setup_rw32_cmnd(struct scsi_cmnd *cmd, bool write, static blk_status_t sd_setup_rw16_cmnd(struct scsi_cmnd *cmd, bool write, sector_t lba, unsigned int nr_blocks, - unsigned char flags) + unsigned char flags, unsigned int dld) { cmd->cmd_len = 16; cmd->cmnd[0] = write ? WRITE_16 : READ_16; - cmd->cmnd[1] = flags; - cmd->cmnd[14] = 0; + cmd->cmnd[1] = flags | ((dld >> 2) & 0x01); + cmd->cmnd[14] = (dld & 0x03) << 6; cmd->cmnd[15] = 0; put_unaligned_be64(lba, &cmd->cmnd[2]); put_unaligned_be32(nr_blocks, &cmd->cmnd[10]); @@ -1114,6 +1116,31 @@ static blk_status_t sd_setup_rw6_cmnd(struct scsi_cmnd *cmd, bool write, return BLK_STS_OK; } +/* + * Check if a command has a duration limit set. If it does, and the target + * device supports CDL and the feature is enabled, return the limit + * descriptor index to use. Return 0 (no limit) otherwise. + */ +static int sd_cdl_dld(struct scsi_disk *sdkp, struct scsi_cmnd *scmd) +{ + struct scsi_device *sdp = sdkp->device; + int hint; + + if (!sdp->cdl_supported || !sdp->cdl_enable) + return 0; + + /* + * Use "no limit" if the request ioprio does not specify a duration + * limit hint. + */ + hint = IOPRIO_PRIO_HINT(req_get_ioprio(scsi_cmd_to_rq(scmd))); + if (hint < IOPRIO_HINT_DEV_DURATION_LIMIT_1 || + hint > IOPRIO_HINT_DEV_DURATION_LIMIT_7) + return 0; + + return (hint - IOPRIO_HINT_DEV_DURATION_LIMIT_1) + 1; +} + static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd) { struct request *rq = scsi_cmd_to_rq(cmd); @@ -1125,6 +1152,7 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd) unsigned int mask = logical_to_sectors(sdp, 1) - 1; bool write = rq_data_dir(rq) == WRITE; unsigned char protect, fua; + unsigned int dld; blk_status_t ret; unsigned int dif; bool dix; @@ -1174,6 +1202,7 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd) fua = rq->cmd_flags & REQ_FUA ? 0x8 : 0; dix = scsi_prot_sg_count(cmd); dif = scsi_host_dif_capable(cmd->device->host, sdkp->protection_type); + dld = sd_cdl_dld(sdkp, cmd); if (dif || dix) protect = sd_setup_protect_cmnd(cmd, dix, dif); @@ -1182,10 +1211,10 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd) if (protect && sdkp->protection_type == T10_PI_TYPE2_PROTECTION) { ret = sd_setup_rw32_cmnd(cmd, write, lba, nr_blocks, - protect | fua); + protect | fua, dld); } else if (sdp->use_16_for_rw || (nr_blocks > 0xffff)) { ret = sd_setup_rw16_cmnd(cmd, write, lba, nr_blocks, - protect | fua); + protect | fua, dld); } else if ((nr_blocks > 0xff) || (lba > 0x1fffff) || sdp->use_10_for_rw || protect) { ret = sd_setup_rw10_cmnd(cmd, write, lba, nr_blocks, @@ -1690,26 +1719,6 @@ out_unlock: return ret; } -static char sd_pr_type(enum pr_type type) -{ - switch (type) { - case PR_WRITE_EXCLUSIVE: - return 0x01; - case PR_EXCLUSIVE_ACCESS: - return 0x03; - case PR_WRITE_EXCLUSIVE_REG_ONLY: - return 0x05; - case PR_EXCLUSIVE_ACCESS_REG_ONLY: - return 0x06; - case PR_WRITE_EXCLUSIVE_ALL_REGS: - return 0x07; - case PR_EXCLUSIVE_ACCESS_ALL_REGS: - return 0x08; - default: - return 0; - } -}; - static int sd_scsi_to_pr_err(struct scsi_sense_hdr *sshdr, int result) { switch (host_byte(result)) { @@ -1740,8 +1749,97 @@ static int sd_scsi_to_pr_err(struct scsi_sense_hdr *sshdr, int result) } } -static int sd_pr_command(struct block_device *bdev, u8 sa, - u64 key, u64 sa_key, u8 type, u8 flags) +static int sd_pr_in_command(struct block_device *bdev, u8 sa, + unsigned char *data, int data_len) +{ + struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk); + struct scsi_device *sdev = sdkp->device; + struct scsi_sense_hdr sshdr; + u8 cmd[10] = { PERSISTENT_RESERVE_IN, sa }; + const struct scsi_exec_args exec_args = { + .sshdr = &sshdr, + }; + int result; + + put_unaligned_be16(data_len, &cmd[7]); + + result = scsi_execute_cmd(sdev, cmd, REQ_OP_DRV_IN, data, data_len, + SD_TIMEOUT, sdkp->max_retries, &exec_args); + if (scsi_status_is_check_condition(result) && + scsi_sense_valid(&sshdr)) { + sdev_printk(KERN_INFO, sdev, "PR command failed: %d\n", result); + scsi_print_sense_hdr(sdev, NULL, &sshdr); + } + + if (result <= 0) + return result; + + return sd_scsi_to_pr_err(&sshdr, result); +} + +static int sd_pr_read_keys(struct block_device *bdev, struct pr_keys *keys_info) +{ + int result, i, data_offset, num_copy_keys; + u32 num_keys = keys_info->num_keys; + int data_len = num_keys * 8 + 8; + u8 *data; + + data = kzalloc(data_len, GFP_KERNEL); + if (!data) + return -ENOMEM; + + result = sd_pr_in_command(bdev, READ_KEYS, data, data_len); + if (result) + goto free_data; + + keys_info->generation = get_unaligned_be32(&data[0]); + keys_info->num_keys = get_unaligned_be32(&data[4]) / 8; + + data_offset = 8; + num_copy_keys = min(num_keys, keys_info->num_keys); + + for (i = 0; i < num_copy_keys; i++) { + keys_info->keys[i] = get_unaligned_be64(&data[data_offset]); + data_offset += 8; + } + +free_data: + kfree(data); + return result; +} + +static int sd_pr_read_reservation(struct block_device *bdev, + struct pr_held_reservation *rsv) +{ + struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk); + struct scsi_device *sdev = sdkp->device; + u8 data[24] = { }; + int result, len; + + result = sd_pr_in_command(bdev, READ_RESERVATION, data, sizeof(data)); + if (result) + return result; + + len = get_unaligned_be32(&data[4]); + if (!len) + return 0; + + /* Make sure we have at least the key and type */ + if (len < 14) { + sdev_printk(KERN_INFO, sdev, + "READ RESERVATION failed due to short return buffer of %d bytes\n", + len); + return -EINVAL; + } + + rsv->generation = get_unaligned_be32(&data[0]); + rsv->key = get_unaligned_be64(&data[8]); + rsv->type = scsi_pr_type_to_block(data[21] & 0x0f); + return 0; +} + +static int sd_pr_out_command(struct block_device *bdev, u8 sa, u64 key, + u64 sa_key, enum scsi_pr_type type, u8 flags) { struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk); struct scsi_device *sdev = sdkp->device; @@ -1783,7 +1881,7 @@ static int sd_pr_register(struct block_device *bdev, u64 old_key, u64 new_key, { if (flags & ~PR_FL_IGNORE_KEY) return -EOPNOTSUPP; - return sd_pr_command(bdev, (flags & PR_FL_IGNORE_KEY) ? 0x06 : 0x00, + return sd_pr_out_command(bdev, (flags & PR_FL_IGNORE_KEY) ? 0x06 : 0x00, old_key, new_key, 0, (1 << 0) /* APTPL */); } @@ -1793,24 +1891,26 @@ static int sd_pr_reserve(struct block_device *bdev, u64 key, enum pr_type type, { if (flags) return -EOPNOTSUPP; - return sd_pr_command(bdev, 0x01, key, 0, sd_pr_type(type), 0); + return sd_pr_out_command(bdev, 0x01, key, 0, + block_pr_type_to_scsi(type), 0); } static int sd_pr_release(struct block_device *bdev, u64 key, enum pr_type type) { - return sd_pr_command(bdev, 0x02, key, 0, sd_pr_type(type), 0); + return sd_pr_out_command(bdev, 0x02, key, 0, + block_pr_type_to_scsi(type), 0); } static int sd_pr_preempt(struct block_device *bdev, u64 old_key, u64 new_key, enum pr_type type, bool abort) { - return sd_pr_command(bdev, abort ? 0x05 : 0x04, old_key, new_key, - sd_pr_type(type), 0); + return sd_pr_out_command(bdev, abort ? 0x05 : 0x04, old_key, new_key, + block_pr_type_to_scsi(type), 0); } static int sd_pr_clear(struct block_device *bdev, u64 key) { - return sd_pr_command(bdev, 0x03, key, 0, 0, 0); + return sd_pr_out_command(bdev, 0x03, key, 0, 0, 0); } static const struct pr_ops sd_pr_ops = { @@ -1819,6 +1919,8 @@ static const struct pr_ops sd_pr_ops = { .pr_release = sd_pr_release, .pr_preempt = sd_pr_preempt, .pr_clear = sd_pr_clear, + .pr_read_keys = sd_pr_read_keys, + .pr_read_reservation = sd_pr_read_reservation, }; static void scsi_disk_free_disk(struct gendisk *disk) @@ -2608,9 +2710,8 @@ sd_do_mode_sense(struct scsi_disk *sdkp, int dbd, int modepage, if (sdkp->device->use_10_for_ms && len < 8) len = 8; - return scsi_mode_sense(sdkp->device, dbd, modepage, buffer, len, - SD_TIMEOUT, sdkp->max_retries, data, - sshdr); + return scsi_mode_sense(sdkp->device, dbd, modepage, 0, buffer, len, + SD_TIMEOUT, sdkp->max_retries, data, sshdr); } /* @@ -2867,7 +2968,7 @@ static void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer) if (sdkp->protection_type == 0) return; - res = scsi_mode_sense(sdp, 1, 0x0a, buffer, 36, SD_TIMEOUT, + res = scsi_mode_sense(sdp, 1, 0x0a, 0, buffer, 36, SD_TIMEOUT, sdkp->max_retries, &data, &sshdr); if (res < 0 || !data.header_length || @@ -3056,7 +3157,7 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer) return; } - if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY) < 0) { + if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY, 0) < 0) { struct scsi_vpd *vpd; sdev->no_report_opcodes = 1; @@ -3072,10 +3173,10 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer) rcu_read_unlock(); } - if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME_16) == 1) + if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME_16, 0) == 1) sdkp->ws16 = 1; - if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME) == 1) + if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME, 0) == 1) sdkp->ws10 = 1; } @@ -3087,9 +3188,9 @@ static void sd_read_security(struct scsi_disk *sdkp, unsigned char *buffer) return; if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, - SECURITY_PROTOCOL_IN) == 1 && + SECURITY_PROTOCOL_IN, 0) == 1 && scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, - SECURITY_PROTOCOL_OUT) == 1) + SECURITY_PROTOCOL_OUT, 0) == 1) sdkp->security = 1; } diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c index 22801c24ea19..abbd08933ac7 100644 --- a/drivers/scsi/sd_zbc.c +++ b/drivers/scsi/sd_zbc.c @@ -889,7 +889,7 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp) } max_append = min_t(u32, logical_to_sectors(sdkp->device, zone_blocks), - q->limits.max_segments << (PAGE_SHIFT - 9)); + q->limits.max_segments << PAGE_SECTORS_SHIFT); max_append = min_t(u32, max_append, queue_max_hw_sectors(q)); blk_queue_max_zone_append_sectors(q, max_append); diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index dcb73787c29d..89fa046c7158 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -71,7 +71,7 @@ static int sg_proc_init(void); #define SG_ALLOW_DIO_DEF 0 -#define SG_MAX_DEVS 32768 +#define SG_MAX_DEVS (1 << MINORBITS) /* SG_MAX_CDB_SIZE should be 260 (spc4r37 section 3.1.30) however the type * of sg_io_hdr::cmd_len can only represent 255. All SCSI commands greater diff --git a/drivers/scsi/smartpqi/Kconfig b/drivers/scsi/smartpqi/Kconfig index 973d240649ab..789460b0a342 100644 --- a/drivers/scsi/smartpqi/Kconfig +++ b/drivers/scsi/smartpqi/Kconfig @@ -1,7 +1,7 @@ # # Kernel configuration file for the SMARTPQI # -# Copyright (c) 2019-2022 Microchip Technology Inc. and its subsidiaries +# Copyright (c) 2019-2023 Microchip Technology Inc. and its subsidiaries # Copyright (c) 2017-2018 Microsemi Corporation # Copyright (c) 2016 Microsemi Corporation # Copyright (c) 2016 PMC-Sierra, Inc. diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h index 228838eb3686..f960b5095d09 100644 --- a/drivers/scsi/smartpqi/smartpqi.h +++ b/drivers/scsi/smartpqi/smartpqi.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* * driver for Microchip PQI-based storage controllers - * Copyright (c) 2019-2022 Microchip Technology Inc. and its subsidiaries + * Copyright (c) 2019-2023 Microchip Technology Inc. and its subsidiaries * Copyright (c) 2016-2018 Microsemi Corporation * Copyright (c) 2016 PMC-Sierra, Inc. * @@ -1108,6 +1108,7 @@ struct pqi_scsi_dev { u8 volume_offline : 1; u8 rescan : 1; u8 ignore_device : 1; + u8 erase_in_progress : 1; bool aio_enabled; /* only valid for physical disks */ bool in_remove; bool device_offline; @@ -1147,7 +1148,7 @@ struct pqi_scsi_dev { struct pqi_stream_data stream_data[NUM_STREAMS_PER_LUN]; atomic_t scsi_cmds_outstanding[PQI_MAX_LUNS_PER_DEVICE]; - atomic_t raid_bypass_cnt; + unsigned int raid_bypass_cnt; }; /* VPD inquiry pages */ @@ -1357,6 +1358,7 @@ struct pqi_ctrl_info { u32 max_write_raid_5_6; u32 max_write_raid_1_10_2drive; u32 max_write_raid_1_10_3drive; + int numa_node; struct list_head scsi_device_list; spinlock_t scsi_device_list_lock; diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index f4e0aa262164..19af36e9a16d 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* * driver for Microchip PQI-based storage controllers - * Copyright (c) 2019-2022 Microchip Technology Inc. and its subsidiaries + * Copyright (c) 2019-2023 Microchip Technology Inc. and its subsidiaries * Copyright (c) 2016-2018 Microsemi Corporation * Copyright (c) 2016 PMC-Sierra, Inc. * @@ -33,11 +33,11 @@ #define BUILD_TIMESTAMP #endif -#define DRIVER_VERSION "2.1.20-035" +#define DRIVER_VERSION "2.1.22-040" #define DRIVER_MAJOR 2 #define DRIVER_MINOR 1 -#define DRIVER_RELEASE 20 -#define DRIVER_REVISION 35 +#define DRIVER_RELEASE 22 +#define DRIVER_REVISION 40 #define DRIVER_NAME "Microchip SmartPQI Driver (v" \ DRIVER_VERSION BUILD_TIMESTAMP ")" @@ -519,6 +519,36 @@ static inline void pqi_clear_soft_reset_status(struct pqi_ctrl_info *ctrl_info) writeb(status, ctrl_info->soft_reset_status); } +static inline bool pqi_is_io_high_priority(struct pqi_scsi_dev *device, struct scsi_cmnd *scmd) +{ + bool io_high_prio; + int priority_class; + + io_high_prio = false; + + if (device->ncq_prio_enable) { + priority_class = + IOPRIO_PRIO_CLASS(req_get_ioprio(scsi_cmd_to_rq(scmd))); + if (priority_class == IOPRIO_CLASS_RT) { + /* Set NCQ priority for read/write commands. */ + switch (scmd->cmnd[0]) { + case WRITE_16: + case READ_16: + case WRITE_12: + case READ_12: + case WRITE_10: + case READ_10: + case WRITE_6: + case READ_6: + io_high_prio = true; + break; + } + } + } + + return io_high_prio; +} + static int pqi_map_single(struct pci_dev *pci_dev, struct pqi_sg_descriptor *sg_descriptor, void *buffer, size_t buffer_length, enum dma_data_direction data_direction) @@ -578,10 +608,6 @@ static int pqi_build_raid_path_request(struct pqi_ctrl_info *ctrl_info, cdb = request->cdb; switch (cmd) { - case TEST_UNIT_READY: - request->data_direction = SOP_READ_FLAG; - cdb[0] = TEST_UNIT_READY; - break; case INQUIRY: request->data_direction = SOP_READ_FLAG; cdb[0] = INQUIRY; @@ -708,7 +734,8 @@ static inline struct pqi_io_request *pqi_alloc_io_request(struct pqi_ctrl_info * } } - pqi_reinit_io_request(io_request); + if (io_request) + pqi_reinit_io_request(io_request); return io_request; } @@ -1588,6 +1615,7 @@ no_buffer: #define PQI_DEVICE_NCQ_PRIO_SUPPORTED 0x01 #define PQI_DEVICE_PHY_MAP_SUPPORTED 0x10 +#define PQI_DEVICE_ERASE_IN_PROGRESS 0x10 static int pqi_get_physical_device_info(struct pqi_ctrl_info *ctrl_info, struct pqi_scsi_dev *device, @@ -1636,6 +1664,8 @@ static int pqi_get_physical_device_info(struct pqi_ctrl_info *ctrl_info, ((get_unaligned_le32(&id_phys->misc_drive_flags) >> 16) & PQI_DEVICE_NCQ_PRIO_SUPPORTED); + device->erase_in_progress = !!(get_unaligned_le16(&id_phys->extra_physical_drive_flags) & PQI_DEVICE_ERASE_IN_PROGRESS); + return 0; } @@ -1681,7 +1711,7 @@ out: /* * Prevent adding drive to OS for some corner cases such as a drive - * undergoing a sanitize operation. Some OSes will continue to poll + * undergoing a sanitize (erase) operation. Some OSes will continue to poll * the drive until the sanitize completes, which can take hours, * resulting in long bootup delays. Commands such as TUR, READ_CAP * are allowed, but READ/WRITE cause check condition. So the OS @@ -1689,73 +1719,9 @@ out: * Note: devices that have completed sanitize must be re-enabled * using the management utility. */ -static bool pqi_keep_device_offline(struct pqi_ctrl_info *ctrl_info, - struct pqi_scsi_dev *device) +static inline bool pqi_keep_device_offline(struct pqi_scsi_dev *device) { - u8 scsi_status; - int rc; - enum dma_data_direction dir; - char *buffer; - int buffer_length = 64; - size_t sense_data_length; - struct scsi_sense_hdr sshdr; - struct pqi_raid_path_request request; - struct pqi_raid_error_info error_info; - bool offline = false; /* Assume keep online */ - - /* Do not check controllers. */ - if (pqi_is_hba_lunid(device->scsi3addr)) - return false; - - /* Do not check LVs. */ - if (pqi_is_logical_device(device)) - return false; - - buffer = kmalloc(buffer_length, GFP_KERNEL); - if (!buffer) - return false; /* Assume not offline */ - - /* Check for SANITIZE in progress using TUR */ - rc = pqi_build_raid_path_request(ctrl_info, &request, - TEST_UNIT_READY, RAID_CTLR_LUNID, buffer, - buffer_length, 0, &dir); - if (rc) - goto out; /* Assume not offline */ - - memcpy(request.lun_number, device->scsi3addr, sizeof(request.lun_number)); - - rc = pqi_submit_raid_request_synchronous(ctrl_info, &request.header, 0, &error_info); - - if (rc) - goto out; /* Assume not offline */ - - scsi_status = error_info.status; - sense_data_length = get_unaligned_le16(&error_info.sense_data_length); - if (sense_data_length == 0) - sense_data_length = - get_unaligned_le16(&error_info.response_data_length); - if (sense_data_length) { - if (sense_data_length > sizeof(error_info.data)) - sense_data_length = sizeof(error_info.data); - - /* - * Check for sanitize in progress: asc:0x04, ascq: 0x1b - */ - if (scsi_status == SAM_STAT_CHECK_CONDITION && - scsi_normalize_sense(error_info.data, - sense_data_length, &sshdr) && - sshdr.sense_key == NOT_READY && - sshdr.asc == 0x04 && - sshdr.ascq == 0x1b) { - device->device_offline = true; - offline = true; - goto out; /* Keep device offline */ - } - } - -out: - kfree(buffer); - return offline; + return device->erase_in_progress; } static int pqi_get_device_info_phys_logical(struct pqi_ctrl_info *ctrl_info, @@ -2499,10 +2465,6 @@ static int pqi_update_scsi_devices(struct pqi_ctrl_info *ctrl_info) if (!pqi_is_supported_device(device)) continue; - /* Do not present disks that the OS cannot fully probe */ - if (pqi_keep_device_offline(ctrl_info, device)) - continue; - /* Gather information about the device. */ rc = pqi_get_device_info(ctrl_info, device, id_phys); if (rc == -ENOMEM) { @@ -2525,6 +2487,10 @@ static int pqi_update_scsi_devices(struct pqi_ctrl_info *ctrl_info) continue; } + /* Do not present disks that the OS cannot fully probe. */ + if (pqi_keep_device_offline(device)) + continue; + pqi_assign_bus_target_lun(device); if (device->is_physical_device) { @@ -5504,15 +5470,19 @@ static void pqi_raid_io_complete(struct pqi_io_request *io_request, pqi_scsi_done(scmd); } -static int pqi_raid_submit_scsi_cmd_with_io_request( - struct pqi_ctrl_info *ctrl_info, struct pqi_io_request *io_request, +static int pqi_raid_submit_io(struct pqi_ctrl_info *ctrl_info, struct pqi_scsi_dev *device, struct scsi_cmnd *scmd, - struct pqi_queue_group *queue_group) + struct pqi_queue_group *queue_group, bool io_high_prio) { int rc; size_t cdb_length; + struct pqi_io_request *io_request; struct pqi_raid_path_request *request; + io_request = pqi_alloc_io_request(ctrl_info, scmd); + if (!io_request) + return SCSI_MLQUEUE_HOST_BUSY; + io_request->io_complete_callback = pqi_raid_io_complete; io_request->scmd = scmd; @@ -5522,6 +5492,7 @@ static int pqi_raid_submit_scsi_cmd_with_io_request( request->header.iu_type = PQI_REQUEST_IU_RAID_PATH_IO; put_unaligned_le32(scsi_bufflen(scmd), &request->buffer_length); request->task_attribute = SOP_TASK_ATTRIBUTE_SIMPLE; + request->command_priority = io_high_prio; put_unaligned_le16(io_request->index, &request->request_id); request->error_index = request->request_id; memcpy(request->lun_number, device->scsi3addr, sizeof(request->lun_number)); @@ -5587,14 +5558,11 @@ static inline int pqi_raid_submit_scsi_cmd(struct pqi_ctrl_info *ctrl_info, struct pqi_scsi_dev *device, struct scsi_cmnd *scmd, struct pqi_queue_group *queue_group) { - struct pqi_io_request *io_request; + bool io_high_prio; - io_request = pqi_alloc_io_request(ctrl_info, scmd); - if (!io_request) - return SCSI_MLQUEUE_HOST_BUSY; + io_high_prio = pqi_is_io_high_priority(device, scmd); - return pqi_raid_submit_scsi_cmd_with_io_request(ctrl_info, io_request, - device, scmd, queue_group); + return pqi_raid_submit_io(ctrl_info, device, scmd, queue_group, io_high_prio); } static bool pqi_raid_bypass_retry_needed(struct pqi_io_request *io_request) @@ -5639,44 +5607,13 @@ static void pqi_aio_io_complete(struct pqi_io_request *io_request, pqi_scsi_done(scmd); } -static inline bool pqi_is_io_high_priority(struct pqi_ctrl_info *ctrl_info, - struct pqi_scsi_dev *device, struct scsi_cmnd *scmd) -{ - bool io_high_prio; - int priority_class; - - io_high_prio = false; - - if (device->ncq_prio_enable) { - priority_class = - IOPRIO_PRIO_CLASS(req_get_ioprio(scsi_cmd_to_rq(scmd))); - if (priority_class == IOPRIO_CLASS_RT) { - /* Set NCQ priority for read/write commands. */ - switch (scmd->cmnd[0]) { - case WRITE_16: - case READ_16: - case WRITE_12: - case READ_12: - case WRITE_10: - case READ_10: - case WRITE_6: - case READ_6: - io_high_prio = true; - break; - } - } - } - - return io_high_prio; -} - static inline int pqi_aio_submit_scsi_cmd(struct pqi_ctrl_info *ctrl_info, struct pqi_scsi_dev *device, struct scsi_cmnd *scmd, struct pqi_queue_group *queue_group) { bool io_high_prio; - io_high_prio = pqi_is_io_high_priority(ctrl_info, device, scmd); + io_high_prio = pqi_is_io_high_priority(device, scmd); return pqi_aio_submit_io(ctrl_info, scmd, device->aio_handle, scmd->cmnd, scmd->cmd_len, queue_group, NULL, @@ -5694,10 +5631,10 @@ static int pqi_aio_submit_io(struct pqi_ctrl_info *ctrl_info, struct pqi_aio_path_request *request; struct pqi_scsi_dev *device; - device = scmd->device->hostdata; io_request = pqi_alloc_io_request(ctrl_info, scmd); if (!io_request) return SCSI_MLQUEUE_HOST_BUSY; + io_request->io_complete_callback = pqi_aio_io_complete; io_request->scmd = scmd; io_request->raid_bypass = raid_bypass; @@ -5712,6 +5649,7 @@ static int pqi_aio_submit_io(struct pqi_ctrl_info *ctrl_info, request->command_priority = io_high_prio; put_unaligned_le16(io_request->index, &request->request_id); request->error_index = request->request_id; + device = scmd->device->hostdata; if (!pqi_is_logical_device(device) && ctrl_info->multi_lun_device_supported) put_unaligned_le64(((scmd->device->lun) << 8), &request->lun_number); if (cdb_length > sizeof(request->cdb)) @@ -6052,7 +5990,7 @@ static int pqi_scsi_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scm rc = pqi_raid_bypass_submit_scsi_cmd(ctrl_info, device, scmd, queue_group); if (rc == 0 || rc == SCSI_MLQUEUE_HOST_BUSY) { raid_bypassed = true; - atomic_inc(&device->raid_bypass_cnt); + device->raid_bypass_cnt++; } } if (!raid_bypassed) @@ -6903,7 +6841,7 @@ static ssize_t pqi_lockup_action_store(struct device *dev, char *action_name; char action_name_buffer[32]; - strlcpy(action_name_buffer, buffer, sizeof(action_name_buffer)); + strscpy(action_name_buffer, buffer, sizeof(action_name_buffer)); action_name = strstrip(action_name_buffer); for (i = 0; i < ARRAY_SIZE(pqi_lockup_actions); i++) { @@ -7288,7 +7226,7 @@ static ssize_t pqi_raid_bypass_cnt_show(struct device *dev, struct scsi_device *sdev; struct pqi_scsi_dev *device; unsigned long flags; - int raid_bypass_cnt; + unsigned int raid_bypass_cnt; sdev = to_scsi_device(dev); ctrl_info = shost_to_hba(sdev->host); @@ -7304,7 +7242,7 @@ static ssize_t pqi_raid_bypass_cnt_show(struct device *dev, return -ENODEV; } - raid_bypass_cnt = atomic_read(&device->raid_bypass_cnt); + raid_bypass_cnt = device->raid_bypass_cnt; spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); @@ -7366,8 +7304,7 @@ static ssize_t pqi_sas_ncq_prio_enable_store(struct device *dev, return -ENODEV; } - if (!device->ncq_prio_support || - !device->is_physical_device) { + if (!device->ncq_prio_support) { spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); return -EINVAL; } @@ -7379,6 +7316,18 @@ static ssize_t pqi_sas_ncq_prio_enable_store(struct device *dev, return strlen(buf); } +static ssize_t pqi_numa_node_show(struct device *dev, + struct device_attribute *attr, char *buffer) +{ + struct scsi_device *sdev; + struct pqi_ctrl_info *ctrl_info; + + sdev = to_scsi_device(dev); + ctrl_info = shost_to_hba(sdev->host); + + return scnprintf(buffer, PAGE_SIZE, "%d\n", ctrl_info->numa_node); +} + static DEVICE_ATTR(lunid, 0444, pqi_lunid_show, NULL); static DEVICE_ATTR(unique_id, 0444, pqi_unique_id_show, NULL); static DEVICE_ATTR(path_info, 0444, pqi_path_info_show, NULL); @@ -7388,6 +7337,7 @@ static DEVICE_ATTR(raid_level, 0444, pqi_raid_level_show, NULL); static DEVICE_ATTR(raid_bypass_cnt, 0444, pqi_raid_bypass_cnt_show, NULL); static DEVICE_ATTR(sas_ncq_prio_enable, 0644, pqi_sas_ncq_prio_enable_show, pqi_sas_ncq_prio_enable_store); +static DEVICE_ATTR(numa_node, 0444, pqi_numa_node_show, NULL); static struct attribute *pqi_sdev_attrs[] = { &dev_attr_lunid.attr, @@ -7398,6 +7348,7 @@ static struct attribute *pqi_sdev_attrs[] = { &dev_attr_raid_level.attr, &dev_attr_raid_bypass_cnt.attr, &dev_attr_sas_ncq_prio_enable.attr, + &dev_attr_numa_node.attr, NULL }; @@ -7716,8 +7667,8 @@ static int pqi_enable_firmware_features(struct pqi_ctrl_info *ctrl_info, features_requested_iomem_addr + (le16_to_cpu(firmware_features->num_elements) * 2) + sizeof(__le16); - writew(PQI_FIRMWARE_FEATURE_MAXIMUM, - host_max_known_feature_iomem_addr); + writeb(PQI_FIRMWARE_FEATURE_MAXIMUM & 0xFF, host_max_known_feature_iomem_addr); + writeb((PQI_FIRMWARE_FEATURE_MAXIMUM & 0xFF00) >> 8, host_max_known_feature_iomem_addr + 1); } return pqi_config_table_update(ctrl_info, @@ -8560,7 +8511,7 @@ static int pqi_pci_init(struct pqi_ctrl_info *ctrl_info) ctrl_info->iomem_base = ioremap(pci_resource_start( ctrl_info->pci_dev, 0), - sizeof(struct pqi_ctrl_registers)); + pci_resource_len(ctrl_info->pci_dev, 0)); if (!ctrl_info->iomem_base) { dev_err(&ctrl_info->pci_dev->dev, "failed to map memory for controller registers\n"); @@ -9018,6 +8969,7 @@ static int pqi_pci_probe(struct pci_dev *pci_dev, "failed to allocate controller info block\n"); return -ENOMEM; } + ctrl_info->numa_node = node; ctrl_info->pci_dev = pci_dev; @@ -9929,6 +9881,18 @@ static const struct pci_device_id pqi_pci_id_table[] = { }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1cf2, 0x0804) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1cf2, 0x0805) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1cf2, 0x0806) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x1cf2, 0x5445) }, { @@ -9965,6 +9929,18 @@ static const struct pci_device_id pqi_pci_id_table[] = { }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1cf2, 0x54da) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1cf2, 0x54db) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1cf2, 0x54dc) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x1cf2, 0x0b27) }, { @@ -10017,6 +9993,10 @@ static const struct pci_device_id pqi_pci_id_table[] = { }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1014, 0x0718) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x1e93, 0x1000) }, { @@ -10029,6 +10009,50 @@ static const struct pci_device_id pqi_pci_id_table[] = { }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1e93, 0x1005) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f51, 0x1001) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f51, 0x1002) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f51, 0x1003) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f51, 0x1004) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f51, 0x1005) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f51, 0x1006) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f51, 0x1007) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f51, 0x1008) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f51, 0x1009) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f51, 0x100a) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, PCI_ANY_ID, PCI_ANY_ID) }, { 0 } diff --git a/drivers/scsi/smartpqi/smartpqi_sas_transport.c b/drivers/scsi/smartpqi/smartpqi_sas_transport.c index 13e8c539010e..a981d0377948 100644 --- a/drivers/scsi/smartpqi/smartpqi_sas_transport.c +++ b/drivers/scsi/smartpqi/smartpqi_sas_transport.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* * driver for Microchip PQI-based storage controllers - * Copyright (c) 2019-2022 Microchip Technology Inc. and its subsidiaries + * Copyright (c) 2019-2023 Microchip Technology Inc. and its subsidiaries * Copyright (c) 2016-2018 Microsemi Corporation * Copyright (c) 2016 PMC-Sierra, Inc. * @@ -92,25 +92,23 @@ static int pqi_sas_port_add_rphy(struct pqi_sas_port *pqi_sas_port, identify = &rphy->identify; identify->sas_address = pqi_sas_port->sas_address; + identify->phy_identifier = pqi_sas_port->device->phy_id; identify->initiator_port_protocols = SAS_PROTOCOL_ALL; identify->target_port_protocols = SAS_PROTOCOL_STP; - if (pqi_sas_port->device) { - identify->phy_identifier = pqi_sas_port->device->phy_id; - switch (pqi_sas_port->device->device_type) { - case SA_DEVICE_TYPE_SAS: - case SA_DEVICE_TYPE_SES: - case SA_DEVICE_TYPE_NVME: - identify->target_port_protocols = SAS_PROTOCOL_SSP; - break; - case SA_DEVICE_TYPE_EXPANDER_SMP: - identify->target_port_protocols = SAS_PROTOCOL_SMP; - break; - case SA_DEVICE_TYPE_SATA: - default: - break; - } + switch (pqi_sas_port->device->device_type) { + case SA_DEVICE_TYPE_SAS: + case SA_DEVICE_TYPE_SES: + case SA_DEVICE_TYPE_NVME: + identify->target_port_protocols = SAS_PROTOCOL_SSP; + break; + case SA_DEVICE_TYPE_EXPANDER_SMP: + identify->target_port_protocols = SAS_PROTOCOL_SMP; + break; + case SA_DEVICE_TYPE_SATA: + default: + break; } return sas_rphy_add(rphy); @@ -295,10 +293,12 @@ int pqi_add_sas_device(struct pqi_sas_node *pqi_sas_node, rc = pqi_sas_port_add_rphy(pqi_sas_port, rphy); if (rc) - goto free_sas_port; + goto free_sas_rphy; return 0; +free_sas_rphy: + sas_rphy_free(rphy); free_sas_port: pqi_free_sas_port(pqi_sas_port); device->sas_port = NULL; diff --git a/drivers/scsi/smartpqi/smartpqi_sis.c b/drivers/scsi/smartpqi/smartpqi_sis.c index 5811fb3c22a9..673437c7152b 100644 --- a/drivers/scsi/smartpqi/smartpqi_sis.c +++ b/drivers/scsi/smartpqi/smartpqi_sis.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* * driver for Microchip PQI-based storage controllers - * Copyright (c) 2019-2022 Microchip Technology Inc. and its subsidiaries + * Copyright (c) 2019-2023 Microchip Technology Inc. and its subsidiaries * Copyright (c) 2016-2018 Microsemi Corporation * Copyright (c) 2016 PMC-Sierra, Inc. * diff --git a/drivers/scsi/smartpqi/smartpqi_sis.h b/drivers/scsi/smartpqi/smartpqi_sis.h index 9dcbae96a5c6..0c97626d87d4 100644 --- a/drivers/scsi/smartpqi/smartpqi_sis.h +++ b/drivers/scsi/smartpqi/smartpqi_sis.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* * driver for Microchip PQI-based storage controllers - * Copyright (c) 2019-2022 Microchip Technology Inc. and its subsidiaries + * Copyright (c) 2019-2023 Microchip Technology Inc. and its subsidiaries * Copyright (c) 2016-2018 Microsemi Corporation * Copyright (c) 2016 PMC-Sierra, Inc. * diff --git a/drivers/scsi/snic/snic_disc.c b/drivers/scsi/snic/snic_disc.c index 8fbf3c1b1311..3e2e5783924d 100644 --- a/drivers/scsi/snic/snic_disc.c +++ b/drivers/scsi/snic/snic_disc.c @@ -214,7 +214,7 @@ snic_tgt_del(struct work_struct *work) scsi_flush_work(shost); /* Block IOs on child devices, stops new IOs */ - scsi_target_block(&tgt->dev); + scsi_block_targets(shost, &tgt->dev); /* Cleanup IOs */ snic_tgt_scsi_abort_io(tgt); diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index ce886c8c9dbe..07ef3db3d1a1 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -825,7 +825,7 @@ static int get_capabilities(struct scsi_cd *cd) scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr); /* ask for mode page 0x2a */ - rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, ms_len, + rc = scsi_mode_sense(cd->device, 0, 0x2a, 0, buffer, ms_len, SR_TIMEOUT, 3, &data, NULL); if (rc < 0 || data.length > ms_len || diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index ee36a9c15d9c..17491ba10439 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -1286,7 +1286,7 @@ static struct Scsi_Host *sym_attach(const struct scsi_host_template *tpnt, int u /* * Edit its name. */ - strlcpy(np->s.chip_name, dev->chip.name, sizeof(np->s.chip_name)); + strscpy(np->s.chip_name, dev->chip.name, sizeof(np->s.chip_name)); sprintf(np->s.inst_name, "sym%d", np->s.unit); if ((SYM_CONF_DMA_ADDRESSING_MODE > 0) && (np->features & FE_DAC) && diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 58498da9869a..bd5633667d01 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -338,10 +338,8 @@ static int virtscsi_rescan_hotunplug(struct virtio_scsi *vscsi) int result, inquiry_len, inq_result_len = 256; char *inq_result = kmalloc(inq_result_len, GFP_KERNEL); - if (!inq_result) { - kfree(inq_result); + if (!inq_result) return -ENOMEM; - } shost_for_each_device(sdev, shost) { inquiry_len = sdev->inquiry_len ? sdev->inquiry_len : 36; diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig index 3658fb0f0c5b..6f3098822969 100644 --- a/drivers/soc/tegra/Kconfig +++ b/drivers/soc/tegra/Kconfig @@ -125,6 +125,7 @@ config ARCH_TEGRA_234_SOC bool "NVIDIA Tegra234 SoC" depends on !CPU_BIG_ENDIAN select MAILBOX + select PINCTRL_TEGRA234 select TEGRA_BPMP select TEGRA_HSP_MBOX select TEGRA_IVC diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c index 557516c642c3..5b90c22ee3dc 100644 --- a/drivers/target/iscsi/iscsi_target_parameters.c +++ b/drivers/target/iscsi/iscsi_target_parameters.c @@ -726,8 +726,8 @@ static int iscsi_add_notunderstood_response( } INIT_LIST_HEAD(&extra_response->er_list); - strlcpy(extra_response->key, key, sizeof(extra_response->key)); - strlcpy(extra_response->value, NOTUNDERSTOOD, + strscpy(extra_response->key, key, sizeof(extra_response->key)); + strscpy(extra_response->value, NOTUNDERSTOOD, sizeof(extra_response->value)); list_add_tail(&extra_response->er_list, diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 6231fa4ef5c6..91a75a4a7cc1 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -1375,7 +1375,7 @@ void iscsit_collect_login_stats( if (conn->param_list) intrname = iscsi_find_param_from_key(INITIATORNAME, conn->param_list); - strlcpy(ls->last_intr_fail_name, + strscpy(ls->last_intr_fail_name, (intrname ? intrname->value : "Unknown"), sizeof(ls->last_intr_fail_name)); @@ -1414,7 +1414,7 @@ void iscsit_fill_cxn_timeout_err_stats(struct iscsit_session *sess) return; spin_lock_bh(&tiqn->sess_err_stats.lock); - strlcpy(tiqn->sess_err_stats.last_sess_fail_rem_name, + strscpy(tiqn->sess_err_stats.last_sess_fail_rem_name, sess->sess_ops->InitiatorName, sizeof(tiqn->sess_err_stats.last_sess_fail_rem_name)); tiqn->sess_err_stats.last_sess_failure_type = diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 74b67c346dfe..936e5ff1b209 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -649,7 +649,7 @@ static void dev_set_t10_wwn_model_alias(struct se_device *dev) * here without potentially breaking existing setups, so continue to * truncate one byte shorter than what can be carried in INQUIRY. */ - strlcpy(dev->t10_wwn.model, configname, INQUIRY_MODEL_LEN); + strscpy(dev->t10_wwn.model, configname, INQUIRY_MODEL_LEN); } static ssize_t emulate_model_alias_store(struct config_item *item, @@ -675,7 +675,7 @@ static ssize_t emulate_model_alias_store(struct config_item *item, if (flag) { dev_set_t10_wwn_model_alias(dev); } else { - strlcpy(dev->t10_wwn.model, dev->transport->inquiry_prod, + strscpy(dev->t10_wwn.model, dev->transport->inquiry_prod, sizeof(dev->t10_wwn.model)); } da->emulate_model_alias = flag; @@ -1426,7 +1426,7 @@ static ssize_t target_wwn_vendor_id_store(struct config_item *item, } BUILD_BUG_ON(sizeof(dev->t10_wwn.vendor) != INQUIRY_VENDOR_LEN + 1); - strlcpy(dev->t10_wwn.vendor, stripped, sizeof(dev->t10_wwn.vendor)); + strscpy(dev->t10_wwn.vendor, stripped, sizeof(dev->t10_wwn.vendor)); pr_debug("Target_Core_ConfigFS: Set emulated T10 Vendor Identification:" " %s\n", dev->t10_wwn.vendor); @@ -1482,7 +1482,7 @@ static ssize_t target_wwn_product_id_store(struct config_item *item, } BUILD_BUG_ON(sizeof(dev->t10_wwn.model) != INQUIRY_MODEL_LEN + 1); - strlcpy(dev->t10_wwn.model, stripped, sizeof(dev->t10_wwn.model)); + strscpy(dev->t10_wwn.model, stripped, sizeof(dev->t10_wwn.model)); pr_debug("Target_Core_ConfigFS: Set emulated T10 Model Identification: %s\n", dev->t10_wwn.model); @@ -1538,7 +1538,7 @@ static ssize_t target_wwn_revision_store(struct config_item *item, } BUILD_BUG_ON(sizeof(dev->t10_wwn.revision) != INQUIRY_REVISION_LEN + 1); - strlcpy(dev->t10_wwn.revision, stripped, sizeof(dev->t10_wwn.revision)); + strscpy(dev->t10_wwn.revision, stripped, sizeof(dev->t10_wwn.revision)); pr_debug("Target_Core_ConfigFS: Set emulated T10 Revision: %s\n", dev->t10_wwn.revision); diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 90f3f4926172..b7ac60f4a219 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -789,10 +789,10 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) xcopy_lun->lun_tpg = &xcopy_pt_tpg; /* Preload the default INQUIRY const values */ - strlcpy(dev->t10_wwn.vendor, "LIO-ORG", sizeof(dev->t10_wwn.vendor)); - strlcpy(dev->t10_wwn.model, dev->transport->inquiry_prod, + strscpy(dev->t10_wwn.vendor, "LIO-ORG", sizeof(dev->t10_wwn.vendor)); + strscpy(dev->t10_wwn.model, dev->transport->inquiry_prod, sizeof(dev->t10_wwn.model)); - strlcpy(dev->t10_wwn.revision, dev->transport->inquiry_rev, + strscpy(dev->t10_wwn.revision, dev->transport->inquiry_rev, sizeof(dev->t10_wwn.revision)); return dev; diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index ce0e000b74fc..4d447520bab8 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -896,7 +896,7 @@ static void fd_free_prot(struct se_device *dev) fd_dev->fd_prot_file = NULL; } -static struct sbc_ops fd_sbc_ops = { +static struct exec_cmd_ops fd_exec_cmd_ops = { .execute_rw = fd_execute_rw, .execute_sync_cache = fd_execute_sync_cache, .execute_write_same = fd_execute_write_same, @@ -906,7 +906,7 @@ static struct sbc_ops fd_sbc_ops = { static sense_reason_t fd_parse_cdb(struct se_cmd *cmd) { - return sbc_parse_cdb(cmd, &fd_sbc_ops); + return sbc_parse_cdb(cmd, &fd_exec_cmd_ops); } static const struct target_backend_ops fileio_ops = { diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 3c462d69daca..a3c5f3558a33 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -23,13 +23,16 @@ #include <linux/file.h> #include <linux/module.h> #include <linux/scatterlist.h> +#include <linux/pr.h> #include <scsi/scsi_proto.h> +#include <scsi/scsi_common.h> #include <asm/unaligned.h> #include <target/target_core_base.h> #include <target/target_core_backend.h> #include "target_core_iblock.h" +#include "target_core_pr.h" #define IBLOCK_MAX_BIO_PER_TASK 32 /* max # of bios to submit at a time */ #define IBLOCK_BIO_POOL_SIZE 128 @@ -309,7 +312,7 @@ static sector_t iblock_get_blocks(struct se_device *dev) return blocks_long; } -static void iblock_complete_cmd(struct se_cmd *cmd) +static void iblock_complete_cmd(struct se_cmd *cmd, blk_status_t blk_status) { struct iblock_req *ibr = cmd->priv; u8 status; @@ -317,7 +320,9 @@ static void iblock_complete_cmd(struct se_cmd *cmd) if (!refcount_dec_and_test(&ibr->pending)) return; - if (atomic_read(&ibr->ib_bio_err_cnt)) + if (blk_status == BLK_STS_RESV_CONFLICT) + status = SAM_STAT_RESERVATION_CONFLICT; + else if (atomic_read(&ibr->ib_bio_err_cnt)) status = SAM_STAT_CHECK_CONDITION; else status = SAM_STAT_GOOD; @@ -330,6 +335,7 @@ static void iblock_bio_done(struct bio *bio) { struct se_cmd *cmd = bio->bi_private; struct iblock_req *ibr = cmd->priv; + blk_status_t blk_status = bio->bi_status; if (bio->bi_status) { pr_err("bio error: %p, err: %d\n", bio, bio->bi_status); @@ -342,7 +348,7 @@ static void iblock_bio_done(struct bio *bio) bio_put(bio); - iblock_complete_cmd(cmd); + iblock_complete_cmd(cmd, blk_status); } static struct bio *iblock_get_bio(struct se_cmd *cmd, sector_t lba, u32 sg_num, @@ -758,7 +764,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, if (!sgl_nents) { refcount_set(&ibr->pending, 1); - iblock_complete_cmd(cmd); + iblock_complete_cmd(cmd, BLK_STS_OK); return 0; } @@ -816,7 +822,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, } iblock_submit_bios(&list); - iblock_complete_cmd(cmd); + iblock_complete_cmd(cmd, BLK_STS_OK); return 0; fail_put_bios: @@ -828,6 +834,258 @@ fail: return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } +static sense_reason_t iblock_execute_pr_out(struct se_cmd *cmd, u8 sa, u64 key, + u64 sa_key, u8 type, bool aptpl) +{ + struct se_device *dev = cmd->se_dev; + struct iblock_dev *ib_dev = IBLOCK_DEV(dev); + struct block_device *bdev = ib_dev->ibd_bd; + const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; + int ret; + + if (!ops) { + pr_err("Block device does not support pr_ops but iblock device has been configured for PR passthrough.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + switch (sa) { + case PRO_REGISTER: + case PRO_REGISTER_AND_IGNORE_EXISTING_KEY: + if (!ops->pr_register) { + pr_err("block device does not support pr_register.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + /* The block layer pr ops always enables aptpl */ + if (!aptpl) + pr_info("APTPL not set by initiator, but will be used.\n"); + + ret = ops->pr_register(bdev, key, sa_key, + sa == PRO_REGISTER ? 0 : PR_FL_IGNORE_KEY); + break; + case PRO_RESERVE: + if (!ops->pr_reserve) { + pr_err("block_device does not support pr_reserve.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + ret = ops->pr_reserve(bdev, key, scsi_pr_type_to_block(type), 0); + break; + case PRO_CLEAR: + if (!ops->pr_clear) { + pr_err("block_device does not support pr_clear.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + ret = ops->pr_clear(bdev, key); + break; + case PRO_PREEMPT: + case PRO_PREEMPT_AND_ABORT: + if (!ops->pr_clear) { + pr_err("block_device does not support pr_preempt.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + ret = ops->pr_preempt(bdev, key, sa_key, + scsi_pr_type_to_block(type), + sa == PRO_PREEMPT ? false : true); + break; + case PRO_RELEASE: + if (!ops->pr_clear) { + pr_err("block_device does not support pr_pclear.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + ret = ops->pr_release(bdev, key, scsi_pr_type_to_block(type)); + break; + default: + pr_err("Unknown PERSISTENT_RESERVE_OUT SA: 0x%02x\n", sa); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + if (!ret) + return TCM_NO_SENSE; + else if (ret == PR_STS_RESERVATION_CONFLICT) + return TCM_RESERVATION_CONFLICT; + else + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; +} + +static void iblock_pr_report_caps(unsigned char *param_data) +{ + u16 len = 8; + + put_unaligned_be16(len, ¶m_data[0]); + /* + * When using the pr_ops passthrough method we only support exporting + * the device through one target port because from the backend module + * level we can't see the target port config. As a result we only + * support registration directly from the I_T nexus the cmd is sent + * through and do not set ATP_C here. + * + * The block layer pr_ops do not support passing in initiators so + * we don't set SIP_C here. + */ + /* PTPL_C: Persistence across Target Power Loss bit */ + param_data[2] |= 0x01; + /* + * We are filling in the PERSISTENT RESERVATION TYPE MASK below, so + * set the TMV: Task Mask Valid bit. + */ + param_data[3] |= 0x80; + /* + * Change ALLOW COMMANDs to 0x20 or 0x40 later from Table 166 + */ + param_data[3] |= 0x10; /* ALLOW COMMANDs field 001b */ + /* + * PTPL_A: Persistence across Target Power Loss Active bit. The block + * layer pr ops always enables this so report it active. + */ + param_data[3] |= 0x01; + /* + * Setup the PERSISTENT RESERVATION TYPE MASK from Table 212 spc4r37. + */ + param_data[4] |= 0x80; /* PR_TYPE_EXCLUSIVE_ACCESS_ALLREG */ + param_data[4] |= 0x40; /* PR_TYPE_EXCLUSIVE_ACCESS_REGONLY */ + param_data[4] |= 0x20; /* PR_TYPE_WRITE_EXCLUSIVE_REGONLY */ + param_data[4] |= 0x08; /* PR_TYPE_EXCLUSIVE_ACCESS */ + param_data[4] |= 0x02; /* PR_TYPE_WRITE_EXCLUSIVE */ + param_data[5] |= 0x01; /* PR_TYPE_EXCLUSIVE_ACCESS_ALLREG */ +} + +static sense_reason_t iblock_pr_read_keys(struct se_cmd *cmd, + unsigned char *param_data) +{ + struct se_device *dev = cmd->se_dev; + struct iblock_dev *ib_dev = IBLOCK_DEV(dev); + struct block_device *bdev = ib_dev->ibd_bd; + const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; + int i, len, paths, data_offset; + struct pr_keys *keys; + sense_reason_t ret; + + if (!ops) { + pr_err("Block device does not support pr_ops but iblock device has been configured for PR passthrough.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + if (!ops->pr_read_keys) { + pr_err("Block device does not support read_keys.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + /* + * We don't know what's under us, but dm-multipath will register every + * path with the same key, so start off with enough space for 16 paths. + * which is not a lot of memory and should normally be enough. + */ + paths = 16; +retry: + len = 8 * paths; + keys = kzalloc(sizeof(*keys) + len, GFP_KERNEL); + if (!keys) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + + keys->num_keys = paths; + if (!ops->pr_read_keys(bdev, keys)) { + if (keys->num_keys > paths) { + kfree(keys); + paths *= 2; + goto retry; + } + } else { + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto free_keys; + } + + ret = TCM_NO_SENSE; + + put_unaligned_be32(keys->generation, ¶m_data[0]); + if (!keys->num_keys) { + put_unaligned_be32(0, ¶m_data[4]); + goto free_keys; + } + + put_unaligned_be32(8 * keys->num_keys, ¶m_data[4]); + + data_offset = 8; + for (i = 0; i < keys->num_keys; i++) { + if (data_offset + 8 > cmd->data_length) + break; + + put_unaligned_be64(keys->keys[i], ¶m_data[data_offset]); + data_offset += 8; + } + +free_keys: + kfree(keys); + return ret; +} + +static sense_reason_t iblock_pr_read_reservation(struct se_cmd *cmd, + unsigned char *param_data) +{ + struct se_device *dev = cmd->se_dev; + struct iblock_dev *ib_dev = IBLOCK_DEV(dev); + struct block_device *bdev = ib_dev->ibd_bd; + const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; + struct pr_held_reservation rsv = { }; + + if (!ops) { + pr_err("Block device does not support pr_ops but iblock device has been configured for PR passthrough.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + if (!ops->pr_read_reservation) { + pr_err("Block device does not support read_keys.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + if (ops->pr_read_reservation(bdev, &rsv)) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + + put_unaligned_be32(rsv.generation, ¶m_data[0]); + if (!block_pr_type_to_scsi(rsv.type)) { + put_unaligned_be32(0, ¶m_data[4]); + return TCM_NO_SENSE; + } + + put_unaligned_be32(16, ¶m_data[4]); + + if (cmd->data_length < 16) + return TCM_NO_SENSE; + put_unaligned_be64(rsv.key, ¶m_data[8]); + + if (cmd->data_length < 22) + return TCM_NO_SENSE; + param_data[21] = block_pr_type_to_scsi(rsv.type); + + return TCM_NO_SENSE; +} + +static sense_reason_t iblock_execute_pr_in(struct se_cmd *cmd, u8 sa, + unsigned char *param_data) +{ + sense_reason_t ret = TCM_NO_SENSE; + + switch (sa) { + case PRI_REPORT_CAPABILITIES: + iblock_pr_report_caps(param_data); + break; + case PRI_READ_KEYS: + ret = iblock_pr_read_keys(cmd, param_data); + break; + case PRI_READ_RESERVATION: + ret = iblock_pr_read_reservation(cmd, param_data); + break; + default: + pr_err("Unknown PERSISTENT_RESERVE_IN SA: 0x%02x\n", sa); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + return ret; +} + static sector_t iblock_get_alignment_offset_lbas(struct se_device *dev) { struct iblock_dev *ib_dev = IBLOCK_DEV(dev); @@ -868,17 +1126,19 @@ static unsigned int iblock_get_io_opt(struct se_device *dev) return bdev_io_opt(bd); } -static struct sbc_ops iblock_sbc_ops = { +static struct exec_cmd_ops iblock_exec_cmd_ops = { .execute_rw = iblock_execute_rw, .execute_sync_cache = iblock_execute_sync_cache, .execute_write_same = iblock_execute_write_same, .execute_unmap = iblock_execute_unmap, + .execute_pr_out = iblock_execute_pr_out, + .execute_pr_in = iblock_execute_pr_in, }; static sense_reason_t iblock_parse_cdb(struct se_cmd *cmd) { - return sbc_parse_cdb(cmd, &iblock_sbc_ops); + return sbc_parse_cdb(cmd, &iblock_exec_cmd_ops); } static bool iblock_get_write_cache(struct se_device *dev) @@ -889,6 +1149,7 @@ static bool iblock_get_write_cache(struct se_device *dev) static const struct target_backend_ops iblock_ops = { .name = "iblock", .inquiry_prod = "IBLOCK", + .transport_flags_changeable = TRANSPORT_FLAG_PASSTHROUGH_PGR, .inquiry_rev = IBLOCK_VERSION, .owner = THIS_MODULE, .attach_hba = iblock_attach_hba, diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index d19ec4e6a4c0..49d9167bb263 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -3538,6 +3538,37 @@ out_put_pr_reg: return ret; } +static sense_reason_t +target_try_pr_out_pt(struct se_cmd *cmd, u8 sa, u64 res_key, u64 sa_res_key, + u8 type, bool aptpl, bool all_tg_pt, bool spec_i_pt) +{ + struct exec_cmd_ops *ops = cmd->protocol_data; + + if (!cmd->se_sess || !cmd->se_lun) { + pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + } + + if (!ops->execute_pr_out) { + pr_err("SPC-3 PR: Device has been configured for PR passthrough but it's not supported by the backend.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + switch (sa) { + case PRO_REGISTER_AND_MOVE: + case PRO_REPLACE_LOST_RESERVATION: + pr_err("SPC-3 PR: PRO_REGISTER_AND_MOVE and PRO_REPLACE_LOST_RESERVATION are not supported by PR passthrough.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + if (spec_i_pt || all_tg_pt) { + pr_err("SPC-3 PR: SPEC_I_PT and ALL_TG_PT are not supported by PR passthrough.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + return ops->execute_pr_out(cmd, sa, res_key, sa_res_key, type, aptpl); +} + /* * See spc4r17 section 6.14 Table 170 */ @@ -3641,6 +3672,12 @@ target_scsi3_emulate_pr_out(struct se_cmd *cmd) return TCM_PARAMETER_LIST_LENGTH_ERROR; } + if (dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR) { + ret = target_try_pr_out_pt(cmd, sa, res_key, sa_res_key, type, + aptpl, all_tg_pt, spec_i_pt); + goto done; + } + /* * (core_scsi3_emulate_pro_* function parameters * are defined by spc4r17 Table 174: @@ -3682,6 +3719,7 @@ target_scsi3_emulate_pr_out(struct se_cmd *cmd) return TCM_INVALID_CDB_FIELD; } +done: if (!ret) target_complete_cmd(cmd, SAM_STAT_GOOD); return ret; @@ -4039,9 +4077,42 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd) return 0; } +static sense_reason_t target_try_pr_in_pt(struct se_cmd *cmd, u8 sa) +{ + struct exec_cmd_ops *ops = cmd->protocol_data; + unsigned char *buf; + sense_reason_t ret; + + if (cmd->data_length < 8) { + pr_err("PRIN SA SCSI Data Length: %u too small\n", + cmd->data_length); + return TCM_INVALID_CDB_FIELD; + } + + if (!ops->execute_pr_in) { + pr_err("SPC-3 PR: Device has been configured for PR passthrough but it's not supported by the backend.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + if (sa == PRI_READ_FULL_STATUS) { + pr_err("SPC-3 PR: PRI_READ_FULL_STATUS is not supported by PR passthrough.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + + ret = ops->execute_pr_in(cmd, sa, buf); + + transport_kunmap_data_sg(cmd); + return ret; +} + sense_reason_t target_scsi3_emulate_pr_in(struct se_cmd *cmd) { + u8 sa = cmd->t_task_cdb[1] & 0x1f; sense_reason_t ret; /* @@ -4060,7 +4131,12 @@ target_scsi3_emulate_pr_in(struct se_cmd *cmd) return TCM_RESERVATION_CONFLICT; } - switch (cmd->t_task_cdb[1] & 0x1f) { + if (cmd->se_dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR) { + ret = target_try_pr_in_pt(cmd, sa); + goto done; + } + + switch (sa) { case PRI_READ_KEYS: ret = core_scsi3_pri_read_keys(cmd); break; @@ -4079,6 +4155,7 @@ target_scsi3_emulate_pr_in(struct se_cmd *cmd) return TCM_INVALID_CDB_FIELD; } +done: if (!ret) target_complete_cmd(cmd, SAM_STAT_GOOD); return ret; diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index 6648c1c90e19..6f67cc09c2b5 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c @@ -643,14 +643,14 @@ static void rd_free_prot(struct se_device *dev) rd_release_prot_space(rd_dev); } -static struct sbc_ops rd_sbc_ops = { +static struct exec_cmd_ops rd_exec_cmd_ops = { .execute_rw = rd_execute_rw, }; static sense_reason_t rd_parse_cdb(struct se_cmd *cmd) { - return sbc_parse_cdb(cmd, &rd_sbc_ops); + return sbc_parse_cdb(cmd, &rd_exec_cmd_ops); } static const struct target_backend_ops rd_mcp_ops = { diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 7536ca797606..6a02561cc20c 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -192,7 +192,7 @@ EXPORT_SYMBOL(sbc_get_write_same_sectors); static sense_reason_t sbc_execute_write_same_unmap(struct se_cmd *cmd) { - struct sbc_ops *ops = cmd->protocol_data; + struct exec_cmd_ops *ops = cmd->protocol_data; sector_t nolb = sbc_get_write_same_sectors(cmd); sense_reason_t ret; @@ -271,7 +271,8 @@ static inline unsigned long long transport_lba_64(unsigned char *cdb) } static sense_reason_t -sbc_setup_write_same(struct se_cmd *cmd, unsigned char flags, struct sbc_ops *ops) +sbc_setup_write_same(struct se_cmd *cmd, unsigned char flags, + struct exec_cmd_ops *ops) { struct se_device *dev = cmd->se_dev; sector_t end_lba = dev->transport->get_blocks(dev) + 1; @@ -340,7 +341,7 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char flags, struct sbc_ops *op static sense_reason_t sbc_execute_rw(struct se_cmd *cmd) { - struct sbc_ops *ops = cmd->protocol_data; + struct exec_cmd_ops *ops = cmd->protocol_data; return ops->execute_rw(cmd, cmd->t_data_sg, cmd->t_data_nents, cmd->data_direction); @@ -566,7 +567,7 @@ out: static sense_reason_t sbc_compare_and_write(struct se_cmd *cmd) { - struct sbc_ops *ops = cmd->protocol_data; + struct exec_cmd_ops *ops = cmd->protocol_data; struct se_device *dev = cmd->se_dev; sense_reason_t ret; int rc; @@ -764,7 +765,7 @@ sbc_check_dpofua(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb) } sense_reason_t -sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) +sbc_parse_cdb(struct se_cmd *cmd, struct exec_cmd_ops *ops) { struct se_device *dev = cmd->se_dev; unsigned char *cdb = cmd->t_task_cdb; @@ -1076,7 +1077,7 @@ EXPORT_SYMBOL(sbc_get_device_type); static sense_reason_t sbc_execute_unmap(struct se_cmd *cmd) { - struct sbc_ops *ops = cmd->protocol_data; + struct exec_cmd_ops *ops = cmd->protocol_data; struct se_device *dev = cmd->se_dev; unsigned char *buf, *ptr = NULL; sector_t lba; diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 89c0d56294cc..50290abc07bc 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -1424,9 +1424,10 @@ static struct target_opcode_descriptor tcm_opcode_write_verify16 = { .update_usage_bits = set_dpofua_usage_bits, }; -static bool tcm_is_ws_enabled(struct se_cmd *cmd) +static bool tcm_is_ws_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { - struct sbc_ops *ops = cmd->protocol_data; + struct exec_cmd_ops *ops = cmd->protocol_data; struct se_device *dev = cmd->se_dev; return (dev->dev_attrib.emulate_tpws && !!ops->execute_unmap) || @@ -1451,7 +1452,8 @@ static struct target_opcode_descriptor tcm_opcode_write_same32 = { .update_usage_bits = set_dpofua_usage_bits32, }; -static bool tcm_is_caw_enabled(struct se_cmd *cmd) +static bool tcm_is_caw_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; @@ -1491,7 +1493,8 @@ static struct target_opcode_descriptor tcm_opcode_read_capacity16 = { 0xff, 0xff, 0x00, SCSI_CONTROL_MASK}, }; -static bool tcm_is_rep_ref_enabled(struct se_cmd *cmd) +static bool tcm_is_rep_ref_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; @@ -1502,7 +1505,6 @@ static bool tcm_is_rep_ref_enabled(struct se_cmd *cmd) } spin_unlock(&dev->t10_alua.lba_map_lock); return true; - } static struct target_opcode_descriptor tcm_opcode_read_report_refferals = { @@ -1537,9 +1539,10 @@ static struct target_opcode_descriptor tcm_opcode_sync_cache16 = { 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK}, }; -static bool tcm_is_unmap_enabled(struct se_cmd *cmd) +static bool tcm_is_unmap_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { - struct sbc_ops *ops = cmd->protocol_data; + struct exec_cmd_ops *ops = cmd->protocol_data; struct se_device *dev = cmd->se_dev; return ops->execute_unmap && dev->dev_attrib.emulate_tpu; @@ -1659,11 +1662,46 @@ static struct target_opcode_descriptor tcm_opcode_pri_read_resrv = { 0xff, SCSI_CONTROL_MASK}, }; -static bool tcm_is_pr_enabled(struct se_cmd *cmd) +static bool tcm_is_pr_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; - return dev->dev_attrib.emulate_pr; + if (!dev->dev_attrib.emulate_pr) + return false; + + if (!(dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)) + return true; + + switch (descr->opcode) { + case RESERVE: + case RESERVE_10: + case RELEASE: + case RELEASE_10: + /* + * The pr_ops which are used by the backend modules don't + * support these commands. + */ + return false; + case PERSISTENT_RESERVE_OUT: + switch (descr->service_action) { + case PRO_REGISTER_AND_MOVE: + case PRO_REPLACE_LOST_RESERVATION: + /* + * The backend modules don't have access to ports and + * I_T nexuses so they can't handle these type of + * requests. + */ + return false; + } + break; + case PERSISTENT_RESERVE_IN: + if (descr->service_action == PRI_READ_FULL_STATUS) + return false; + break; + } + + return true; } static struct target_opcode_descriptor tcm_opcode_pri_read_caps = { @@ -1788,20 +1826,13 @@ static struct target_opcode_descriptor tcm_opcode_pro_register_move = { .enabled = tcm_is_pr_enabled, }; -static bool tcm_is_scsi2_reservations_enabled(struct se_cmd *cmd) -{ - struct se_device *dev = cmd->se_dev; - - return dev->dev_attrib.emulate_pr; -} - static struct target_opcode_descriptor tcm_opcode_release = { .support = SCSI_SUPPORT_FULL, .opcode = RELEASE, .cdb_size = 6, .usage_bits = {RELEASE, 0x00, 0x00, 0x00, 0x00, SCSI_CONTROL_MASK}, - .enabled = tcm_is_scsi2_reservations_enabled, + .enabled = tcm_is_pr_enabled, }; static struct target_opcode_descriptor tcm_opcode_release10 = { @@ -1811,7 +1842,7 @@ static struct target_opcode_descriptor tcm_opcode_release10 = { .usage_bits = {RELEASE_10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, SCSI_CONTROL_MASK}, - .enabled = tcm_is_scsi2_reservations_enabled, + .enabled = tcm_is_pr_enabled, }; static struct target_opcode_descriptor tcm_opcode_reserve = { @@ -1820,7 +1851,7 @@ static struct target_opcode_descriptor tcm_opcode_reserve = { .cdb_size = 6, .usage_bits = {RESERVE, 0x00, 0x00, 0x00, 0x00, SCSI_CONTROL_MASK}, - .enabled = tcm_is_scsi2_reservations_enabled, + .enabled = tcm_is_pr_enabled, }; static struct target_opcode_descriptor tcm_opcode_reserve10 = { @@ -1830,7 +1861,7 @@ static struct target_opcode_descriptor tcm_opcode_reserve10 = { .usage_bits = {RESERVE_10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, SCSI_CONTROL_MASK}, - .enabled = tcm_is_scsi2_reservations_enabled, + .enabled = tcm_is_pr_enabled, }; static struct target_opcode_descriptor tcm_opcode_request_sense = { @@ -1849,7 +1880,8 @@ static struct target_opcode_descriptor tcm_opcode_inquiry = { 0xff, SCSI_CONTROL_MASK}, }; -static bool tcm_is_3pc_enabled(struct se_cmd *cmd) +static bool tcm_is_3pc_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; @@ -1910,8 +1942,8 @@ static struct target_opcode_descriptor tcm_opcode_report_target_pgs = { 0xff, 0xff, 0x00, SCSI_CONTROL_MASK}, }; - -static bool spc_rsoc_enabled(struct se_cmd *cmd) +static bool spc_rsoc_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; @@ -1931,7 +1963,8 @@ static struct target_opcode_descriptor tcm_opcode_report_supp_opcodes = { .enabled = spc_rsoc_enabled, }; -static bool tcm_is_set_tpg_enabled(struct se_cmd *cmd) +static bool tcm_is_set_tpg_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { struct t10_alua_tg_pt_gp *l_tg_pt_gp; struct se_lun *l_lun = cmd->se_lun; @@ -2118,7 +2151,7 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode) if (descr->serv_action_valid) return TCM_INVALID_CDB_FIELD; - if (!descr->enabled || descr->enabled(cmd)) + if (!descr->enabled || descr->enabled(descr, cmd)) *opcode = descr; break; case 0x2: @@ -2132,7 +2165,8 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode) */ if (descr->serv_action_valid && descr->service_action == requested_sa) { - if (!descr->enabled || descr->enabled(cmd)) + if (!descr->enabled || descr->enabled(descr, + cmd)) *opcode = descr; } else if (!descr->serv_action_valid) return TCM_INVALID_CDB_FIELD; @@ -2145,7 +2179,8 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode) * be returned in the one_command parameter data format. */ if (descr->service_action == requested_sa) - if (!descr->enabled || descr->enabled(cmd)) + if (!descr->enabled || descr->enabled(descr, + cmd)) *opcode = descr; break; } @@ -2202,7 +2237,7 @@ spc_emulate_report_supp_op_codes(struct se_cmd *cmd) for (i = 0; i < ARRAY_SIZE(tcm_supported_opcodes); i++) { descr = tcm_supported_opcodes[i]; - if (descr->enabled && !descr->enabled(cmd)) + if (descr->enabled && !descr->enabled(descr, cmd)) continue; response_length += spc_rsoc_encode_command_descriptor( @@ -2231,12 +2266,22 @@ spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) struct se_device *dev = cmd->se_dev; unsigned char *cdb = cmd->t_task_cdb; - if (!dev->dev_attrib.emulate_pr && - ((cdb[0] == PERSISTENT_RESERVE_IN) || - (cdb[0] == PERSISTENT_RESERVE_OUT) || - (cdb[0] == RELEASE || cdb[0] == RELEASE_10) || - (cdb[0] == RESERVE || cdb[0] == RESERVE_10))) { - return TCM_UNSUPPORTED_SCSI_OPCODE; + switch (cdb[0]) { + case RESERVE: + case RESERVE_10: + case RELEASE: + case RELEASE_10: + if (!dev->dev_attrib.emulate_pr) + return TCM_UNSUPPORTED_SCSI_OPCODE; + + if (dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR) + return TCM_UNSUPPORTED_SCSI_OPCODE; + break; + case PERSISTENT_RESERVE_IN: + case PERSISTENT_RESERVE_OUT: + if (!dev->dev_attrib.emulate_pr) + return TCM_UNSUPPORTED_SCSI_OPCODE; + break; } switch (cdb[0]) { diff --git a/drivers/ufs/core/ufs-fault-injection.c b/drivers/ufs/core/ufs-fault-injection.c index 7ac7c4e7ff83..5b1184aac585 100644 --- a/drivers/ufs/core/ufs-fault-injection.c +++ b/drivers/ufs/core/ufs-fault-injection.c @@ -54,7 +54,7 @@ static int ufs_fault_set(const char *val, const struct kernel_param *kp) if (!setup_fault_attr(attr, (char *)val)) return -EINVAL; - strlcpy(kp->arg, val, FAULT_INJ_STR_SIZE); + strscpy(kp->arg, val, FAULT_INJ_STR_SIZE); return 0; } diff --git a/drivers/ufs/core/ufs-hwmon.c b/drivers/ufs/core/ufs-hwmon.c index 4c6a872b7a7c..101d7082446f 100644 --- a/drivers/ufs/core/ufs-hwmon.c +++ b/drivers/ufs/core/ufs-hwmon.c @@ -146,7 +146,7 @@ static umode_t ufs_hwmon_is_visible(const void *_data, enum hwmon_sensor_types t return 0; } -static const struct hwmon_channel_info *ufs_hwmon_info[] = { +static const struct hwmon_channel_info *const ufs_hwmon_info[] = { HWMON_CHANNEL_INFO(temp, HWMON_T_ENABLE | HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_LCRIT), NULL }; diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c index 51b3c6ae781d..6fb0e007af63 100644 --- a/drivers/ufs/core/ufs-mcq.c +++ b/drivers/ufs/core/ufs-mcq.c @@ -12,21 +12,26 @@ #include <linux/module.h> #include <linux/platform_device.h> #include "ufshcd-priv.h" +#include <linux/delay.h> +#include <scsi/scsi_cmnd.h> +#include <linux/bitfield.h> +#include <linux/iopoll.h> #define MAX_QUEUE_SUP GENMASK(7, 0) #define UFS_MCQ_MIN_RW_QUEUES 2 #define UFS_MCQ_MIN_READ_QUEUES 0 -#define UFS_MCQ_NUM_DEV_CMD_QUEUES 1 #define UFS_MCQ_MIN_POLL_QUEUES 0 #define QUEUE_EN_OFFSET 31 #define QUEUE_ID_OFFSET 16 -#define MAX_DEV_CMD_ENTRIES 2 #define MCQ_CFG_MAC_MASK GENMASK(16, 8) #define MCQ_QCFG_SIZE 0x40 #define MCQ_ENTRY_SIZE_IN_DWORD 8 #define CQE_UCD_BA GENMASK_ULL(63, 7) +/* Max mcq register polling time in microseconds */ +#define MCQ_POLL_US 500000 + static int rw_queue_count_set(const char *val, const struct kernel_param *kp) { return param_set_uint_minmax(val, kp, UFS_MCQ_MIN_RW_QUEUES, @@ -108,8 +113,7 @@ struct ufs_hw_queue *ufshcd_mcq_req_to_hwq(struct ufs_hba *hba, u32 utag = blk_mq_unique_tag(req); u32 hwq = blk_mq_unique_tag_to_hwq(utag); - /* uhq[0] is used to serve device commands */ - return &hba->uhq[hwq + UFSHCD_MCQ_IO_QUEUE_OFFSET]; + return &hba->uhq[hwq]; } /** @@ -153,8 +157,7 @@ static int ufshcd_mcq_config_nr_queues(struct ufs_hba *hba) /* maxq is 0 based value */ hba_maxq = FIELD_GET(MAX_QUEUE_SUP, hba->mcq_capabilities) + 1; - tot_queues = UFS_MCQ_NUM_DEV_CMD_QUEUES + read_queues + poll_queues + - rw_queues; + tot_queues = read_queues + poll_queues + rw_queues; if (hba_maxq < tot_queues) { dev_err(hba->dev, "Total queues (%d) exceeds HC capacity (%d)\n", @@ -162,7 +165,7 @@ static int ufshcd_mcq_config_nr_queues(struct ufs_hba *hba) return -EOPNOTSUPP; } - rem = hba_maxq - UFS_MCQ_NUM_DEV_CMD_QUEUES; + rem = hba_maxq; if (rw_queues) { hba->nr_queues[HCTX_TYPE_DEFAULT] = rw_queues; @@ -188,7 +191,7 @@ static int ufshcd_mcq_config_nr_queues(struct ufs_hba *hba) for (i = 0; i < HCTX_MAX_TYPES; i++) host->nr_hw_queues += hba->nr_queues[i]; - hba->nr_hw_queues = host->nr_hw_queues + UFS_MCQ_NUM_DEV_CMD_QUEUES; + hba->nr_hw_queues = host->nr_hw_queues; return 0; } @@ -270,44 +273,57 @@ static int ufshcd_mcq_get_tag(struct ufs_hba *hba, } static void ufshcd_mcq_process_cqe(struct ufs_hba *hba, - struct ufs_hw_queue *hwq) + struct ufs_hw_queue *hwq) { struct cq_entry *cqe = ufshcd_mcq_cur_cqe(hwq); int tag = ufshcd_mcq_get_tag(hba, hwq, cqe); - ufshcd_compl_one_cqe(hba, tag, cqe); + if (cqe->command_desc_base_addr) { + ufshcd_compl_one_cqe(hba, tag, cqe); + /* After processed the cqe, mark it empty (invalid) entry */ + cqe->command_desc_base_addr = 0; + } } -unsigned long ufshcd_mcq_poll_cqe_nolock(struct ufs_hba *hba, - struct ufs_hw_queue *hwq) +void ufshcd_mcq_compl_all_cqes_lock(struct ufs_hba *hba, + struct ufs_hw_queue *hwq) { - unsigned long completed_reqs = 0; + unsigned long flags; + u32 entries = hwq->max_entries; - ufshcd_mcq_update_cq_tail_slot(hwq); - while (!ufshcd_mcq_is_cq_empty(hwq)) { + spin_lock_irqsave(&hwq->cq_lock, flags); + while (entries > 0) { ufshcd_mcq_process_cqe(hba, hwq); ufshcd_mcq_inc_cq_head_slot(hwq); - completed_reqs++; + entries--; } - if (completed_reqs) - ufshcd_mcq_update_cq_head(hwq); - - return completed_reqs; + ufshcd_mcq_update_cq_tail_slot(hwq); + hwq->cq_head_slot = hwq->cq_tail_slot; + spin_unlock_irqrestore(&hwq->cq_lock, flags); } -EXPORT_SYMBOL_GPL(ufshcd_mcq_poll_cqe_nolock); unsigned long ufshcd_mcq_poll_cqe_lock(struct ufs_hba *hba, struct ufs_hw_queue *hwq) { - unsigned long completed_reqs, flags; + unsigned long completed_reqs = 0; + unsigned long flags; spin_lock_irqsave(&hwq->cq_lock, flags); - completed_reqs = ufshcd_mcq_poll_cqe_nolock(hba, hwq); + ufshcd_mcq_update_cq_tail_slot(hwq); + while (!ufshcd_mcq_is_cq_empty(hwq)) { + ufshcd_mcq_process_cqe(hba, hwq); + ufshcd_mcq_inc_cq_head_slot(hwq); + completed_reqs++; + } + + if (completed_reqs) + ufshcd_mcq_update_cq_head(hwq); spin_unlock_irqrestore(&hwq->cq_lock, flags); return completed_reqs; } +EXPORT_SYMBOL_GPL(ufshcd_mcq_poll_cqe_lock); void ufshcd_mcq_make_queues_operational(struct ufs_hba *hba) { @@ -420,13 +436,243 @@ int ufshcd_mcq_init(struct ufs_hba *hba) hwq->max_entries = hba->nutrs; spin_lock_init(&hwq->sq_lock); spin_lock_init(&hwq->cq_lock); + mutex_init(&hwq->sq_mutex); } /* The very first HW queue serves device commands */ hba->dev_cmd_queue = &hba->uhq[0]; - /* Give dev_cmd_queue the minimal number of entries */ - hba->dev_cmd_queue->max_entries = MAX_DEV_CMD_ENTRIES; host->host_tagset = 1; return 0; } + +static int ufshcd_mcq_sq_stop(struct ufs_hba *hba, struct ufs_hw_queue *hwq) +{ + void __iomem *reg; + u32 id = hwq->id, val; + int err; + + if (hba->quirks & UFSHCD_QUIRK_MCQ_BROKEN_RTC) + return -ETIMEDOUT; + + writel(SQ_STOP, mcq_opr_base(hba, OPR_SQD, id) + REG_SQRTC); + reg = mcq_opr_base(hba, OPR_SQD, id) + REG_SQRTS; + err = read_poll_timeout(readl, val, val & SQ_STS, 20, + MCQ_POLL_US, false, reg); + if (err) + dev_err(hba->dev, "%s: failed. hwq-id=%d, err=%d\n", + __func__, id, err); + return err; +} + +static int ufshcd_mcq_sq_start(struct ufs_hba *hba, struct ufs_hw_queue *hwq) +{ + void __iomem *reg; + u32 id = hwq->id, val; + int err; + + if (hba->quirks & UFSHCD_QUIRK_MCQ_BROKEN_RTC) + return -ETIMEDOUT; + + writel(SQ_START, mcq_opr_base(hba, OPR_SQD, id) + REG_SQRTC); + reg = mcq_opr_base(hba, OPR_SQD, id) + REG_SQRTS; + err = read_poll_timeout(readl, val, !(val & SQ_STS), 20, + MCQ_POLL_US, false, reg); + if (err) + dev_err(hba->dev, "%s: failed. hwq-id=%d, err=%d\n", + __func__, id, err); + return err; +} + +/** + * ufshcd_mcq_sq_cleanup - Clean up submission queue resources + * associated with the pending command. + * @hba - per adapter instance. + * @task_tag - The command's task tag. + * + * Returns 0 for success; error code otherwise. + */ +int ufshcd_mcq_sq_cleanup(struct ufs_hba *hba, int task_tag) +{ + struct ufshcd_lrb *lrbp = &hba->lrb[task_tag]; + struct scsi_cmnd *cmd = lrbp->cmd; + struct ufs_hw_queue *hwq; + void __iomem *reg, *opr_sqd_base; + u32 nexus, id, val; + int err; + + if (hba->quirks & UFSHCD_QUIRK_MCQ_BROKEN_RTC) + return -ETIMEDOUT; + + if (task_tag != hba->nutrs - UFSHCD_NUM_RESERVED) { + if (!cmd) + return -EINVAL; + hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(cmd)); + } else { + hwq = hba->dev_cmd_queue; + } + + id = hwq->id; + + mutex_lock(&hwq->sq_mutex); + + /* stop the SQ fetching before working on it */ + err = ufshcd_mcq_sq_stop(hba, hwq); + if (err) + goto unlock; + + /* SQCTI = EXT_IID, IID, LUN, Task Tag */ + nexus = lrbp->lun << 8 | task_tag; + opr_sqd_base = mcq_opr_base(hba, OPR_SQD, id); + writel(nexus, opr_sqd_base + REG_SQCTI); + + /* SQRTCy.ICU = 1 */ + writel(SQ_ICU, opr_sqd_base + REG_SQRTC); + + /* Poll SQRTSy.CUS = 1. Return result from SQRTSy.RTC */ + reg = opr_sqd_base + REG_SQRTS; + err = read_poll_timeout(readl, val, val & SQ_CUS, 20, + MCQ_POLL_US, false, reg); + if (err) + dev_err(hba->dev, "%s: failed. hwq=%d, tag=%d err=%ld\n", + __func__, id, task_tag, + FIELD_GET(SQ_ICU_ERR_CODE_MASK, readl(reg))); + + if (ufshcd_mcq_sq_start(hba, hwq)) + err = -ETIMEDOUT; + +unlock: + mutex_unlock(&hwq->sq_mutex); + return err; +} + +/** + * ufshcd_mcq_nullify_sqe - Nullify the submission queue entry. + * Write the sqe's Command Type to 0xF. The host controller will not + * fetch any sqe with Command Type = 0xF. + * + * @utrd - UTP Transfer Request Descriptor to be nullified. + */ +static void ufshcd_mcq_nullify_sqe(struct utp_transfer_req_desc *utrd) +{ + u32 dword_0; + + dword_0 = le32_to_cpu(utrd->header.dword_0); + dword_0 &= ~UPIU_COMMAND_TYPE_MASK; + dword_0 |= FIELD_PREP(UPIU_COMMAND_TYPE_MASK, 0xF); + utrd->header.dword_0 = cpu_to_le32(dword_0); +} + +/** + * ufshcd_mcq_sqe_search - Search for the command in the submission queue + * If the command is in the submission queue and not issued to the device yet, + * nullify the sqe so the host controller will skip fetching the sqe. + * + * @hba - per adapter instance. + * @hwq - Hardware Queue to be searched. + * @task_tag - The command's task tag. + * + * Returns true if the SQE containing the command is present in the SQ + * (not fetched by the controller); returns false if the SQE is not in the SQ. + */ +static bool ufshcd_mcq_sqe_search(struct ufs_hba *hba, + struct ufs_hw_queue *hwq, int task_tag) +{ + struct ufshcd_lrb *lrbp = &hba->lrb[task_tag]; + struct utp_transfer_req_desc *utrd; + u32 mask = hwq->max_entries - 1; + __le64 cmd_desc_base_addr; + bool ret = false; + u64 addr, match; + u32 sq_head_slot; + + if (hba->quirks & UFSHCD_QUIRK_MCQ_BROKEN_RTC) + return true; + + mutex_lock(&hwq->sq_mutex); + + ufshcd_mcq_sq_stop(hba, hwq); + sq_head_slot = ufshcd_mcq_get_sq_head_slot(hwq); + if (sq_head_slot == hwq->sq_tail_slot) + goto out; + + cmd_desc_base_addr = lrbp->utr_descriptor_ptr->command_desc_base_addr; + addr = le64_to_cpu(cmd_desc_base_addr) & CQE_UCD_BA; + + while (sq_head_slot != hwq->sq_tail_slot) { + utrd = hwq->sqe_base_addr + + sq_head_slot * sizeof(struct utp_transfer_req_desc); + match = le64_to_cpu(utrd->command_desc_base_addr) & CQE_UCD_BA; + if (addr == match) { + ufshcd_mcq_nullify_sqe(utrd); + ret = true; + goto out; + } + sq_head_slot = (sq_head_slot + 1) & mask; + } + +out: + ufshcd_mcq_sq_start(hba, hwq); + mutex_unlock(&hwq->sq_mutex); + return ret; +} + +/** + * ufshcd_mcq_abort - Abort the command in MCQ. + * @cmd - The command to be aborted. + * + * Returns SUCCESS or FAILED error codes + */ +int ufshcd_mcq_abort(struct scsi_cmnd *cmd) +{ + struct Scsi_Host *host = cmd->device->host; + struct ufs_hba *hba = shost_priv(host); + int tag = scsi_cmd_to_rq(cmd)->tag; + struct ufshcd_lrb *lrbp = &hba->lrb[tag]; + struct ufs_hw_queue *hwq; + int err = FAILED; + + if (!ufshcd_cmd_inflight(lrbp->cmd)) { + dev_err(hba->dev, + "%s: skip abort. cmd at tag %d already completed.\n", + __func__, tag); + goto out; + } + + /* Skip task abort in case previous aborts failed and report failure */ + if (lrbp->req_abort_skip) { + dev_err(hba->dev, "%s: skip abort. tag %d failed earlier\n", + __func__, tag); + goto out; + } + + hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(cmd)); + + if (ufshcd_mcq_sqe_search(hba, hwq, tag)) { + /* + * Failure. The command should not be "stuck" in SQ for + * a long time which resulted in command being aborted. + */ + dev_err(hba->dev, "%s: cmd found in sq. hwq=%d, tag=%d\n", + __func__, hwq->id, tag); + goto out; + } + + /* + * The command is not in the submission queue, and it is not + * in the completion queue either. Query the device to see if + * the command is being processed in the device. + */ + if (ufshcd_try_to_abort_task(hba, tag)) { + dev_err(hba->dev, "%s: device abort failed %d\n", __func__, err); + lrbp->req_abort_skip = true; + goto out; + } + + err = SUCCESS; + if (ufshcd_cmd_inflight(lrbp->cmd)) + ufshcd_release_scsi_cmd(hba, lrbp); + +out: + return err; +} diff --git a/drivers/ufs/core/ufs-sysfs.c b/drivers/ufs/core/ufs-sysfs.c index 883f0e44b54e..6c72075750dd 100644 --- a/drivers/ufs/core/ufs-sysfs.c +++ b/drivers/ufs/core/ufs-sysfs.c @@ -168,7 +168,7 @@ static ssize_t auto_hibern8_show(struct device *dev, } pm_runtime_get_sync(hba->dev); - ufshcd_hold(hba, false); + ufshcd_hold(hba); ahit = ufshcd_readl(hba, REG_AUTO_HIBERNATE_IDLE_TIMER); ufshcd_release(hba); pm_runtime_put_sync(hba->dev); @@ -298,6 +298,37 @@ out: return res < 0 ? res : count; } +static ssize_t wb_flush_threshold_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", hba->vps->wb_flush_threshold); +} + +static ssize_t wb_flush_threshold_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + unsigned int wb_flush_threshold; + + if (kstrtouint(buf, 0, &wb_flush_threshold)) + return -EINVAL; + + /* The range of values for wb_flush_threshold is (0,10] */ + if (wb_flush_threshold > UFS_WB_BUF_REMAIN_PERCENT(100) || + wb_flush_threshold == 0) { + dev_err(dev, "The value of wb_flush_threshold is invalid!\n"); + return -EINVAL; + } + + hba->vps->wb_flush_threshold = wb_flush_threshold; + + return count; +} + static DEVICE_ATTR_RW(rpm_lvl); static DEVICE_ATTR_RO(rpm_target_dev_state); static DEVICE_ATTR_RO(rpm_target_link_state); @@ -307,6 +338,7 @@ static DEVICE_ATTR_RO(spm_target_link_state); static DEVICE_ATTR_RW(auto_hibern8); static DEVICE_ATTR_RW(wb_on); static DEVICE_ATTR_RW(enable_wb_buf_flush); +static DEVICE_ATTR_RW(wb_flush_threshold); static struct attribute *ufs_sysfs_ufshcd_attrs[] = { &dev_attr_rpm_lvl.attr, @@ -318,6 +350,7 @@ static struct attribute *ufs_sysfs_ufshcd_attrs[] = { &dev_attr_auto_hibern8.attr, &dev_attr_wb_on.attr, &dev_attr_enable_wb_buf_flush.attr, + &dev_attr_wb_flush_threshold.attr, NULL }; diff --git a/drivers/ufs/core/ufshcd-crypto.c b/drivers/ufs/core/ufshcd-crypto.c index 198360fe5e8e..f2c4422cab86 100644 --- a/drivers/ufs/core/ufshcd-crypto.c +++ b/drivers/ufs/core/ufshcd-crypto.c @@ -24,7 +24,7 @@ static int ufshcd_program_key(struct ufs_hba *hba, u32 slot_offset = hba->crypto_cfg_register + slot * sizeof(*cfg); int err = 0; - ufshcd_hold(hba, false); + ufshcd_hold(hba); if (hba->vops && hba->vops->program_key) { err = hba->vops->program_key(hba, cfg, slot); diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h index d53b93c21a0c..9566a95aeed9 100644 --- a/drivers/ufs/core/ufshcd-priv.h +++ b/drivers/ufs/core/ufshcd-priv.h @@ -71,22 +71,24 @@ void ufshcd_mcq_config_mac(struct ufs_hba *hba, u32 max_active_cmds); void ufshcd_mcq_select_mcq_mode(struct ufs_hba *hba); u32 ufshcd_mcq_read_cqis(struct ufs_hba *hba, int i); void ufshcd_mcq_write_cqis(struct ufs_hba *hba, u32 val, int i); -unsigned long ufshcd_mcq_poll_cqe_nolock(struct ufs_hba *hba, - struct ufs_hw_queue *hwq); struct ufs_hw_queue *ufshcd_mcq_req_to_hwq(struct ufs_hba *hba, struct request *req); unsigned long ufshcd_mcq_poll_cqe_lock(struct ufs_hba *hba, struct ufs_hw_queue *hwq); +void ufshcd_mcq_compl_all_cqes_lock(struct ufs_hba *hba, + struct ufs_hw_queue *hwq); +bool ufshcd_cmd_inflight(struct scsi_cmnd *cmd); +int ufshcd_mcq_sq_cleanup(struct ufs_hba *hba, int task_tag); +int ufshcd_mcq_abort(struct scsi_cmnd *cmd); +int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag); +void ufshcd_release_scsi_cmd(struct ufs_hba *hba, + struct ufshcd_lrb *lrbp); -#define UFSHCD_MCQ_IO_QUEUE_OFFSET 1 #define SD_ASCII_STD true #define SD_RAW false int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index, u8 **buf, bool ascii); -int ufshcd_hold(struct ufs_hba *hba, bool async); -void ufshcd_release(struct ufs_hba *hba); - int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd); int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba, @@ -366,10 +368,11 @@ static inline bool ufs_is_valid_unit_desc_lun(struct ufs_dev_info *dev_info, u8 static inline void ufshcd_inc_sq_tail(struct ufs_hw_queue *q) __must_hold(&q->sq_lock) { - u32 mask = q->max_entries - 1; u32 val; - q->sq_tail_slot = (q->sq_tail_slot + 1) & mask; + q->sq_tail_slot++; + if (q->sq_tail_slot == q->max_entries) + q->sq_tail_slot = 0; val = q->sq_tail_slot * sizeof(struct utp_transfer_req_desc); writel(val, q->mcq_sq_tail); } @@ -404,4 +407,12 @@ static inline struct cq_entry *ufshcd_mcq_cur_cqe(struct ufs_hw_queue *q) return cqe + q->cq_head_slot; } + +static inline u32 ufshcd_mcq_get_sq_head_slot(struct ufs_hw_queue *q) +{ + u32 val = readl(q->mcq_sq_head); + + return val / sizeof(struct utp_transfer_req_desc); +} + #endif /* _UFSHCD_PRIV_H_ */ diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index e7e79f515e14..983fae84d9e8 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -98,7 +98,7 @@ /* Polling time to wait for fDeviceInit */ #define FDEVICEINIT_COMPL_TIMEOUT 1500 /* millisecs */ -/* UFSHC 4.0 compliant HC support this mode, refer param_set_mcq_mode() */ +/* UFSHC 4.0 compliant HC support this mode. */ static bool use_mcq_mode = true; static bool is_mcq_supported(struct ufs_hba *hba) @@ -106,23 +106,7 @@ static bool is_mcq_supported(struct ufs_hba *hba) return hba->mcq_sup && use_mcq_mode; } -static int param_set_mcq_mode(const char *val, const struct kernel_param *kp) -{ - int ret; - - ret = param_set_bool(val, kp); - if (ret) - return ret; - - return 0; -} - -static const struct kernel_param_ops mcq_mode_ops = { - .set = param_set_mcq_mode, - .get = param_get_bool, -}; - -module_param_cb(use_mcq_mode, &mcq_mode_ops, &use_mcq_mode, 0644); +module_param(use_mcq_mode, bool, 0644); MODULE_PARM_DESC(use_mcq_mode, "Control MCQ mode for controllers starting from UFSHCI 4.0. 1 - enable MCQ, 0 - disable MCQ. MCQ is enabled by default"); #define ufshcd_toggle_vreg(_dev, _vreg, _on) \ @@ -173,7 +157,6 @@ EXPORT_SYMBOL_GPL(ufshcd_dump_regs); enum { UFSHCD_MAX_CHANNEL = 0, UFSHCD_MAX_ID = 1, - UFSHCD_NUM_RESERVED = 1, UFSHCD_CMD_PER_LUN = 32 - UFSHCD_NUM_RESERVED, UFSHCD_CAN_QUEUE = 32 - UFSHCD_NUM_RESERVED, }; @@ -301,7 +284,6 @@ static int ufshcd_setup_hba_vreg(struct ufs_hba *hba, bool on); static int ufshcd_setup_vreg(struct ufs_hba *hba, bool on); static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba, struct ufs_vreg *vreg); -static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag); static void ufshcd_wb_toggle_buf_flush_during_h8(struct ufs_hba *hba, bool enable); static void ufshcd_hba_vreg_set_lpm(struct ufs_hba *hba); @@ -1205,7 +1187,7 @@ static int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, bool timeout = false, do_last_check = false; ktime_t start; - ufshcd_hold(hba, false); + ufshcd_hold(hba); spin_lock_irqsave(hba->host->host_lock, flags); /* * Wait for all the outstanding tasks/transfer requests. @@ -1326,7 +1308,7 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba, u64 timeout_us) } /* let's not get into low power until clock scaling is completed */ - ufshcd_hold(hba, false); + ufshcd_hold(hba); out: return ret; @@ -1656,7 +1638,7 @@ static ssize_t ufshcd_clkscale_enable_store(struct device *dev, goto out; ufshcd_rpm_get_sync(hba); - ufshcd_hold(hba, false); + ufshcd_hold(hba); hba->clk_scaling.is_enabled = value; @@ -1739,7 +1721,7 @@ static void ufshcd_ungate_work(struct work_struct *work) spin_lock_irqsave(hba->host->host_lock, flags); if (hba->clk_gating.state == CLKS_ON) { spin_unlock_irqrestore(hba->host->host_lock, flags); - goto unblock_reqs; + return; } spin_unlock_irqrestore(hba->host->host_lock, flags); @@ -1762,25 +1744,21 @@ static void ufshcd_ungate_work(struct work_struct *work) } hba->clk_gating.is_suspended = false; } -unblock_reqs: - ufshcd_scsi_unblock_requests(hba); } /** * ufshcd_hold - Enable clocks that were gated earlier due to ufshcd_release. * Also, exit from hibern8 mode and set the link as active. * @hba: per adapter instance - * @async: This indicates whether caller should ungate clocks asynchronously. */ -int ufshcd_hold(struct ufs_hba *hba, bool async) +void ufshcd_hold(struct ufs_hba *hba) { - int rc = 0; bool flush_result; unsigned long flags; if (!ufshcd_is_clkgating_allowed(hba) || !hba->clk_gating.is_initialized) - goto out; + return; spin_lock_irqsave(hba->host->host_lock, flags); hba->clk_gating.active_reqs++; @@ -1797,15 +1775,10 @@ start: */ if (ufshcd_can_hibern8_during_gating(hba) && ufshcd_is_link_hibern8(hba)) { - if (async) { - rc = -EAGAIN; - hba->clk_gating.active_reqs--; - break; - } spin_unlock_irqrestore(hba->host->host_lock, flags); flush_result = flush_work(&hba->clk_gating.ungate_work); if (hba->clk_gating.is_suspended && !flush_result) - goto out; + return; spin_lock_irqsave(hba->host->host_lock, flags); goto start; } @@ -1827,21 +1800,14 @@ start: hba->clk_gating.state = REQ_CLKS_ON; trace_ufshcd_clk_gating(dev_name(hba->dev), hba->clk_gating.state); - if (queue_work(hba->clk_gating.clk_gating_workq, - &hba->clk_gating.ungate_work)) - ufshcd_scsi_block_requests(hba); + queue_work(hba->clk_gating.clk_gating_workq, + &hba->clk_gating.ungate_work); /* * fall through to check if we should wait for this * work to be done or not. */ fallthrough; case REQ_CLKS_ON: - if (async) { - rc = -EAGAIN; - hba->clk_gating.active_reqs--; - break; - } - spin_unlock_irqrestore(hba->host->host_lock, flags); flush_work(&hba->clk_gating.ungate_work); /* Make sure state is CLKS_ON before returning */ @@ -1853,8 +1819,6 @@ start: break; } spin_unlock_irqrestore(hba->host->host_lock, flags); -out: - return rc; } EXPORT_SYMBOL_GPL(ufshcd_hold); @@ -2086,7 +2050,7 @@ static void ufshcd_exit_clk_gating(struct ufs_hba *hba) ufshcd_remove_clk_gating_sysfs(hba); /* Ungate the clock if necessary. */ - ufshcd_hold(hba, false); + ufshcd_hold(hba); hba->clk_gating.is_initialized = false; ufshcd_release(hba); @@ -2336,18 +2300,20 @@ static inline int ufshcd_hba_capabilities(struct ufs_hba *hba) /* Read crypto capabilities */ err = ufshcd_hba_init_crypto_capabilities(hba); - if (err) + if (err) { dev_err(hba->dev, "crypto setup failed\n"); + return err; + } hba->mcq_sup = FIELD_GET(MASK_MCQ_SUPPORT, hba->capabilities); if (!hba->mcq_sup) - return err; + return 0; hba->mcq_capabilities = ufshcd_readl(hba, REG_MCQCAP); hba->ext_iid_sup = FIELD_GET(MASK_EXT_IID_SUPPORT, hba->mcq_capabilities); - return err; + return 0; } /** @@ -2482,7 +2448,7 @@ int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) if (hba->quirks & UFSHCD_QUIRK_BROKEN_UIC_CMD) return 0; - ufshcd_hold(hba, false); + ufshcd_hold(hba); mutex_lock(&hba->uic_cmd_mutex); ufshcd_add_delay_before_dme_cmd(hba); @@ -2533,7 +2499,7 @@ static void ufshcd_sgl_to_prdt(struct ufs_hba *hba, struct ufshcd_lrb *lrbp, int * 11b to indicate Dword granularity. A value of '3' * indicates 4 bytes, '7' indicates 8 bytes, etc." */ - WARN_ONCE(len > 256 * 1024, "len = %#x\n", len); + WARN_ONCE(len > SZ_256K, "len = %#x\n", len); prd->size = cpu_to_le32(len - 1); prd->addr = cpu_to_le64(sg->dma_address); prd->reserved = 0; @@ -2885,12 +2851,6 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) WARN_ONCE(tag < 0 || tag >= hba->nutrs, "Invalid tag %d\n", tag); - /* - * Allows the UFS error handler to wait for prior ufshcd_queuecommand() - * calls. - */ - rcu_read_lock(); - switch (hba->ufshcd_state) { case UFSHCD_STATE_OPERATIONAL: break; @@ -2936,16 +2896,9 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) hba->req_abort_count = 0; - err = ufshcd_hold(hba, true); - if (err) { - err = SCSI_MLQUEUE_HOST_BUSY; - goto out; - } - WARN_ON(ufshcd_is_clkgating_allowed(hba) && - (hba->clk_gating.state != CLKS_ON)); + ufshcd_hold(hba); lrbp = &hba->lrb[tag]; - WARN_ON(lrbp->cmd); lrbp->cmd = cmd; lrbp->task_tag = tag; lrbp->lun = ufshcd_scsi_to_upiu_lun(cmd->device->lun); @@ -2961,7 +2914,6 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) err = ufshcd_map_sg(hba, lrbp); if (err) { - lrbp->cmd = NULL; ufshcd_release(hba); goto out; } @@ -2972,8 +2924,6 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) ufshcd_send_command(hba, tag, hwq); out: - rcu_read_unlock(); - if (ufs_trigger_eh()) { unsigned long flags; @@ -2999,13 +2949,50 @@ static int ufshcd_compose_dev_cmd(struct ufs_hba *hba, } /* - * Clear all the requests from the controller for which a bit has been set in - * @mask and wait until the controller confirms that these requests have been - * cleared. + * Check with the block layer if the command is inflight + * @cmd: command to check. + * + * Returns true if command is inflight; false if not. + */ +bool ufshcd_cmd_inflight(struct scsi_cmnd *cmd) +{ + struct request *rq; + + if (!cmd) + return false; + + rq = scsi_cmd_to_rq(cmd); + if (!blk_mq_request_started(rq)) + return false; + + return true; +} + +/* + * Clear the pending command in the controller and wait until + * the controller confirms that the command has been cleared. + * @hba: per adapter instance + * @task_tag: The tag number of the command to be cleared. */ -static int ufshcd_clear_cmds(struct ufs_hba *hba, u32 mask) +static int ufshcd_clear_cmd(struct ufs_hba *hba, u32 task_tag) { + u32 mask = 1U << task_tag; unsigned long flags; + int err; + + if (is_mcq_enabled(hba)) { + /* + * MCQ mode. Clean up the MCQ resources similar to + * what the ufshcd_utrl_clear() does for SDB mode. + */ + err = ufshcd_mcq_sq_cleanup(hba, task_tag); + if (err) { + dev_err(hba->dev, "%s: failed tag=%d. err=%d\n", + __func__, task_tag, err); + return err; + } + return 0; + } /* clear outstanding transaction before retry */ spin_lock_irqsave(hba->host->host_lock, flags); @@ -3099,14 +3086,23 @@ retry: * not trigger any race conditions. */ hba->dev_cmd.complete = NULL; - err = ufshcd_get_tr_ocs(lrbp, hba->dev_cmd.cqe); + err = ufshcd_get_tr_ocs(lrbp, NULL); if (!err) err = ufshcd_dev_cmd_completion(hba, lrbp); } else { err = -ETIMEDOUT; dev_dbg(hba->dev, "%s: dev_cmd request timedout, tag %d\n", __func__, lrbp->task_tag); - if (ufshcd_clear_cmds(hba, 1U << lrbp->task_tag) == 0) { + + /* MCQ mode */ + if (is_mcq_enabled(hba)) { + err = ufshcd_clear_cmd(hba, lrbp->task_tag); + hba->dev_cmd.complete = NULL; + return err; + } + + /* SDB mode */ + if (ufshcd_clear_cmd(hba, lrbp->task_tag) == 0) { /* successfully cleared the command, retry if needed */ err = -EAGAIN; /* @@ -3180,13 +3176,12 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba, down_read(&hba->clk_scaling_lock); lrbp = &hba->lrb[tag]; - WARN_ON(lrbp->cmd); + lrbp->cmd = NULL; err = ufshcd_compose_dev_cmd(hba, lrbp, cmd_type, tag); if (unlikely(err)) goto out; hba->dev_cmd.complete = &wait; - hba->dev_cmd.cqe = NULL; ufshcd_add_query_upiu_trace(hba, UFS_QUERY_SEND, lrbp->ucd_req_ptr); @@ -3267,7 +3262,7 @@ int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode, BUG_ON(!hba); - ufshcd_hold(hba, false); + ufshcd_hold(hba); mutex_lock(&hba->dev_cmd.lock); ufshcd_init_query(hba, &request, &response, opcode, idn, index, selector); @@ -3341,7 +3336,7 @@ int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode, return -EINVAL; } - ufshcd_hold(hba, false); + ufshcd_hold(hba); mutex_lock(&hba->dev_cmd.lock); ufshcd_init_query(hba, &request, &response, opcode, idn, index, @@ -3437,7 +3432,7 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba, return -EINVAL; } - ufshcd_hold(hba, false); + ufshcd_hold(hba); mutex_lock(&hba->dev_cmd.lock); ufshcd_init_query(hba, &request, &response, opcode, idn, index, @@ -3779,7 +3774,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba) /* * Allocate memory for UTP Transfer descriptors - * UFSHCI requires 1024 byte alignment of UTRD + * UFSHCI requires 1KB alignment of UTRD */ utrdl_size = (sizeof(struct utp_transfer_req_desc) * hba->nutrs); hba->utrdl_base_addr = dmam_alloc_coherent(hba->dev, @@ -3787,7 +3782,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba) &hba->utrdl_dma_addr, GFP_KERNEL); if (!hba->utrdl_base_addr || - WARN_ON(hba->utrdl_dma_addr & (1024 - 1))) { + WARN_ON(hba->utrdl_dma_addr & (SZ_1K - 1))) { dev_err(hba->dev, "Transfer Descriptor Memory allocation failed\n"); goto out; @@ -3803,7 +3798,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba) goto skip_utmrdl; /* * Allocate memory for UTP Task Management descriptors - * UFSHCI requires 1024 byte alignment of UTMRD + * UFSHCI requires 1KB alignment of UTMRD */ utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs; hba->utmrdl_base_addr = dmam_alloc_coherent(hba->dev, @@ -3811,7 +3806,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba) &hba->utmrdl_dma_addr, GFP_KERNEL); if (!hba->utmrdl_base_addr || - WARN_ON(hba->utmrdl_dma_addr & (1024 - 1))) { + WARN_ON(hba->utmrdl_dma_addr & (SZ_1K - 1))) { dev_err(hba->dev, "Task Management Descriptor Memory allocation failed\n"); goto out; @@ -3868,10 +3863,8 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba) /* Configure UTRD with command descriptor base address */ cmd_desc_element_addr = (cmd_desc_dma_addr + (cmd_desc_size * i)); - utrdlp[i].command_desc_base_addr_lo = - cpu_to_le32(lower_32_bits(cmd_desc_element_addr)); - utrdlp[i].command_desc_base_addr_hi = - cpu_to_le32(upper_32_bits(cmd_desc_element_addr)); + utrdlp[i].command_desc_base_addr = + cpu_to_le64(cmd_desc_element_addr); /* Response upiu and prdt offset should be in double words */ if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN) { @@ -4255,7 +4248,7 @@ int ufshcd_uic_change_pwr_mode(struct ufs_hba *hba, u8 mode) uic_cmd.command = UIC_CMD_DME_SET; uic_cmd.argument1 = UIC_ARG_MIB(PA_PWRMODE); uic_cmd.argument3 = mode; - ufshcd_hold(hba, false); + ufshcd_hold(hba); ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd); ufshcd_release(hba); @@ -4362,7 +4355,7 @@ void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit) if (update && !pm_runtime_suspended(&hba->ufs_device_wlun->sdev_gendev)) { ufshcd_rpm_get_sync(hba); - ufshcd_hold(hba, false); + ufshcd_hold(hba); ufshcd_auto_hibern8_enable(hba); ufshcd_release(hba); ufshcd_rpm_put_sync(hba); @@ -4955,7 +4948,7 @@ static int ufshcd_verify_dev_init(struct ufs_hba *hba) int err = 0; int retries; - ufshcd_hold(hba, false); + ufshcd_hold(hba); mutex_lock(&hba->dev_cmd.lock); for (retries = NOP_OUT_RETRIES; retries > 0; retries--) { err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_NOP, @@ -5148,7 +5141,7 @@ static int ufshcd_slave_configure(struct scsi_device *sdev) blk_queue_update_dma_pad(q, PRDT_DATA_BYTE_COUNT_PAD - 1); if (hba->quirks & UFSHCD_QUIRK_4KB_DMA_ALIGNMENT) - blk_queue_update_dma_alignment(q, 4096 - 1); + blk_queue_update_dma_alignment(q, SZ_4K - 1); /* * Block runtime-pm until all consumers are added. * Refer ufshcd_setup_links(). @@ -5416,13 +5409,12 @@ static irqreturn_t ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status) } /* Release the resources allocated for processing a SCSI command. */ -static void ufshcd_release_scsi_cmd(struct ufs_hba *hba, - struct ufshcd_lrb *lrbp) +void ufshcd_release_scsi_cmd(struct ufs_hba *hba, + struct ufshcd_lrb *lrbp) { struct scsi_cmnd *cmd = lrbp->cmd; scsi_dma_unmap(cmd); - lrbp->cmd = NULL; /* Mark the command as completed. */ ufshcd_release(hba); ufshcd_clk_scaling_update_busy(hba); } @@ -5438,6 +5430,7 @@ void ufshcd_compl_one_cqe(struct ufs_hba *hba, int task_tag, { struct ufshcd_lrb *lrbp; struct scsi_cmnd *cmd; + enum utp_ocs ocs; lrbp = &hba->lrb[task_tag]; lrbp->compl_time_stamp = ktime_get(); @@ -5453,8 +5446,11 @@ void ufshcd_compl_one_cqe(struct ufs_hba *hba, int task_tag, } else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE || lrbp->command_type == UTP_CMD_TYPE_UFS_STORAGE) { if (hba->dev_cmd.complete) { - hba->dev_cmd.cqe = cqe; - ufshcd_add_command_trace(hba, task_tag, UFS_DEV_COMP); + if (cqe) { + ocs = le32_to_cpu(cqe->status) & MASK_OCS; + lrbp->utr_descriptor_ptr->header.dword_2 = + cpu_to_le32(ocs); + } complete(hba->dev_cmd.complete); ufshcd_clk_scaling_update_busy(hba); } @@ -5507,7 +5503,7 @@ static int ufshcd_poll(struct Scsi_Host *shost, unsigned int queue_num) struct ufs_hw_queue *hwq; if (is_mcq_enabled(hba)) { - hwq = &hba->uhq[queue_num + UFSHCD_MCQ_IO_QUEUE_OFFSET]; + hwq = &hba->uhq[queue_num]; return ufshcd_mcq_poll_cqe_lock(hba, hwq); } @@ -5532,6 +5528,57 @@ static int ufshcd_poll(struct Scsi_Host *shost, unsigned int queue_num) } /** + * ufshcd_mcq_compl_pending_transfer - MCQ mode function. It is + * invoked from the error handler context or ufshcd_host_reset_and_restore() + * to complete the pending transfers and free the resources associated with + * the scsi command. + * + * @hba: per adapter instance + * @force_compl: This flag is set to true when invoked + * from ufshcd_host_reset_and_restore() in which case it requires special + * handling because the host controller has been reset by ufshcd_hba_stop(). + */ +static void ufshcd_mcq_compl_pending_transfer(struct ufs_hba *hba, + bool force_compl) +{ + struct ufs_hw_queue *hwq; + struct ufshcd_lrb *lrbp; + struct scsi_cmnd *cmd; + unsigned long flags; + u32 hwq_num, utag; + int tag; + + for (tag = 0; tag < hba->nutrs; tag++) { + lrbp = &hba->lrb[tag]; + cmd = lrbp->cmd; + if (!ufshcd_cmd_inflight(cmd) || + test_bit(SCMD_STATE_COMPLETE, &cmd->state)) + continue; + + utag = blk_mq_unique_tag(scsi_cmd_to_rq(cmd)); + hwq_num = blk_mq_unique_tag_to_hwq(utag); + hwq = &hba->uhq[hwq_num]; + + if (force_compl) { + ufshcd_mcq_compl_all_cqes_lock(hba, hwq); + /* + * For those cmds of which the cqes are not present + * in the cq, complete them explicitly. + */ + if (cmd && !test_bit(SCMD_STATE_COMPLETE, &cmd->state)) { + spin_lock_irqsave(&hwq->cq_lock, flags); + set_host_byte(cmd, DID_REQUEUE); + ufshcd_release_scsi_cmd(hba, lrbp); + scsi_done(cmd); + spin_unlock_irqrestore(&hwq->cq_lock, flags); + } + } else { + ufshcd_mcq_poll_cqe_lock(hba, hwq); + } + } +} + +/** * ufshcd_transfer_req_compl - handle SCSI and query command completion * @hba: per adapter instance * @@ -6095,9 +6142,13 @@ out: } /* Complete requests that have door-bell cleared */ -static void ufshcd_complete_requests(struct ufs_hba *hba) +static void ufshcd_complete_requests(struct ufs_hba *hba, bool force_compl) { - ufshcd_transfer_req_compl(hba); + if (is_mcq_enabled(hba)) + ufshcd_mcq_compl_pending_transfer(hba, force_compl); + else + ufshcd_transfer_req_compl(hba); + ufshcd_tmc_handler(hba); } @@ -6241,22 +6292,22 @@ static void ufshcd_err_handling_prepare(struct ufs_hba *hba) ufshcd_setup_vreg(hba, true); ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq); ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq2); - ufshcd_hold(hba, false); + ufshcd_hold(hba); if (!ufshcd_is_clkgating_allowed(hba)) ufshcd_setup_clocks(hba, true); ufshcd_release(hba); pm_op = hba->is_sys_suspended ? UFS_SYSTEM_PM : UFS_RUNTIME_PM; ufshcd_vops_resume(hba, pm_op); } else { - ufshcd_hold(hba, false); + ufshcd_hold(hba); if (ufshcd_is_clkscaling_supported(hba) && hba->clk_scaling.is_enabled) ufshcd_suspend_clkscaling(hba); ufshcd_clk_scaling_allow(hba, false); } ufshcd_scsi_block_requests(hba); - /* Drain ufshcd_queuecommand() */ - synchronize_rcu(); + /* Wait for ongoing ufshcd_queuecommand() calls to finish. */ + blk_mq_wait_quiesce_done(&hba->host->tag_set); cancel_work_sync(&hba->eeh_work); } @@ -6338,18 +6389,36 @@ static bool ufshcd_abort_all(struct ufs_hba *hba) bool needs_reset = false; int tag, ret; - /* Clear pending transfer requests */ - for_each_set_bit(tag, &hba->outstanding_reqs, hba->nutrs) { - ret = ufshcd_try_to_abort_task(hba, tag); - dev_err(hba->dev, "Aborting tag %d / CDB %#02x %s\n", tag, - hba->lrb[tag].cmd ? hba->lrb[tag].cmd->cmnd[0] : -1, - ret ? "failed" : "succeeded"); - if (ret) { - needs_reset = true; - goto out; + if (is_mcq_enabled(hba)) { + struct ufshcd_lrb *lrbp; + int tag; + + for (tag = 0; tag < hba->nutrs; tag++) { + lrbp = &hba->lrb[tag]; + if (!ufshcd_cmd_inflight(lrbp->cmd)) + continue; + ret = ufshcd_try_to_abort_task(hba, tag); + dev_err(hba->dev, "Aborting tag %d / CDB %#02x %s\n", tag, + hba->lrb[tag].cmd ? hba->lrb[tag].cmd->cmnd[0] : -1, + ret ? "failed" : "succeeded"); + if (ret) { + needs_reset = true; + goto out; + } + } + } else { + /* Clear pending transfer requests */ + for_each_set_bit(tag, &hba->outstanding_reqs, hba->nutrs) { + ret = ufshcd_try_to_abort_task(hba, tag); + dev_err(hba->dev, "Aborting tag %d / CDB %#02x %s\n", tag, + hba->lrb[tag].cmd ? hba->lrb[tag].cmd->cmnd[0] : -1, + ret ? "failed" : "succeeded"); + if (ret) { + needs_reset = true; + goto out; + } } } - /* Clear pending task management requests */ for_each_set_bit(tag, &hba->outstanding_tasks, hba->nutmrs) { if (ufshcd_clear_tm_cmd(hba, tag)) { @@ -6360,7 +6429,7 @@ static bool ufshcd_abort_all(struct ufs_hba *hba) out: /* Complete the requests that are cleared by s/w */ - ufshcd_complete_requests(hba); + ufshcd_complete_requests(hba, false); return needs_reset; } @@ -6400,7 +6469,7 @@ static void ufshcd_err_handler(struct work_struct *work) spin_unlock_irqrestore(hba->host->host_lock, flags); ufshcd_err_handling_prepare(hba); /* Complete requests that have door-bell cleared by h/w */ - ufshcd_complete_requests(hba); + ufshcd_complete_requests(hba, false); spin_lock_irqsave(hba->host->host_lock, flags); again: needs_restore = false; @@ -6771,7 +6840,7 @@ static irqreturn_t ufshcd_handle_mcq_cq_events(struct ufs_hba *hba) ufshcd_mcq_write_cqis(hba, events, i); if (events & UFSHCD_MCQ_CQIS_TAIL_ENT_PUSH_STS) - ufshcd_mcq_poll_cqe_nolock(hba, hwq); + ufshcd_mcq_poll_cqe_lock(hba, hwq); } return IRQ_HANDLED; @@ -6901,7 +6970,7 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba, return PTR_ERR(req); req->end_io_data = &wait; - ufshcd_hold(hba, false); + ufshcd_hold(hba); spin_lock_irqsave(host->host_lock, flags); @@ -7037,7 +7106,6 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba, down_read(&hba->clk_scaling_lock); lrbp = &hba->lrb[tag]; - WARN_ON(lrbp->cmd); lrbp->cmd = NULL; lrbp->task_tag = tag; lrbp->lun = 0; @@ -7138,7 +7206,7 @@ int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba, cmd_type = DEV_CMD_TYPE_NOP; fallthrough; case UPIU_TRANSACTION_QUERY_REQ: - ufshcd_hold(hba, false); + ufshcd_hold(hba); mutex_lock(&hba->dev_cmd.lock); err = ufshcd_issue_devman_upiu_cmd(hba, req_upiu, rsp_upiu, desc_buff, buff_len, @@ -7204,12 +7272,11 @@ int ufshcd_advanced_rpmb_req_handler(struct ufs_hba *hba, struct utp_upiu_req *r u16 ehs_len; /* Protects use of hba->reserved_slot. */ - ufshcd_hold(hba, false); + ufshcd_hold(hba); mutex_lock(&hba->dev_cmd.lock); down_read(&hba->clk_scaling_lock); lrbp = &hba->lrb[tag]; - WARN_ON(lrbp->cmd); lrbp->cmd = NULL; lrbp->task_tag = tag; lrbp->lun = UFS_UPIU_RPMB_WLUN; @@ -7281,7 +7348,9 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd) unsigned long flags, pending_reqs = 0, not_cleared = 0; struct Scsi_Host *host; struct ufs_hba *hba; - u32 pos; + struct ufs_hw_queue *hwq; + struct ufshcd_lrb *lrbp; + u32 pos, not_cleared_mask = 0; int err; u8 resp = 0xF, lun; @@ -7296,6 +7365,20 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd) goto out; } + if (is_mcq_enabled(hba)) { + for (pos = 0; pos < hba->nutrs; pos++) { + lrbp = &hba->lrb[pos]; + if (ufshcd_cmd_inflight(lrbp->cmd) && + lrbp->lun == lun) { + ufshcd_clear_cmd(hba, pos); + hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(lrbp->cmd)); + ufshcd_mcq_poll_cqe_lock(hba, hwq); + } + } + err = 0; + goto out; + } + /* clear the commands that were pending for corresponding LUN */ spin_lock_irqsave(&hba->outstanding_lock, flags); for_each_set_bit(pos, &hba->outstanding_reqs, hba->nutrs) @@ -7304,17 +7387,20 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd) hba->outstanding_reqs &= ~pending_reqs; spin_unlock_irqrestore(&hba->outstanding_lock, flags); - if (ufshcd_clear_cmds(hba, pending_reqs) < 0) { - spin_lock_irqsave(&hba->outstanding_lock, flags); - not_cleared = pending_reqs & - ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); - hba->outstanding_reqs |= not_cleared; - spin_unlock_irqrestore(&hba->outstanding_lock, flags); + for_each_set_bit(pos, &pending_reqs, hba->nutrs) { + if (ufshcd_clear_cmd(hba, pos) < 0) { + spin_lock_irqsave(&hba->outstanding_lock, flags); + not_cleared = 1U << pos & + ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); + hba->outstanding_reqs |= not_cleared; + not_cleared_mask |= not_cleared; + spin_unlock_irqrestore(&hba->outstanding_lock, flags); - dev_err(hba->dev, "%s: failed to clear requests %#lx\n", - __func__, not_cleared); + dev_err(hba->dev, "%s: failed to clear request %d\n", + __func__, pos); + } } - __ufshcd_transfer_req_compl(hba, pending_reqs & ~not_cleared); + __ufshcd_transfer_req_compl(hba, pending_reqs & ~not_cleared_mask); out: hba->req_abort_count = 0; @@ -7352,7 +7438,7 @@ static void ufshcd_set_req_abort_skip(struct ufs_hba *hba, unsigned long bitmap) * * Returns zero on success, non-zero on failure */ -static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag) +int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag) { struct ufshcd_lrb *lrbp = &hba->lrb[tag]; int err = 0; @@ -7375,6 +7461,20 @@ static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag) */ dev_err(hba->dev, "%s: cmd at tag %d not pending in the device.\n", __func__, tag); + if (is_mcq_enabled(hba)) { + /* MCQ mode */ + if (ufshcd_cmd_inflight(lrbp->cmd)) { + /* sleep for max. 200us same delay as in SDB mode */ + usleep_range(100, 200); + continue; + } + /* command completed already */ + dev_err(hba->dev, "%s: cmd at tag=%d is cleared.\n", + __func__, tag); + goto out; + } + + /* Single Doorbell Mode */ reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); if (reg & (1 << tag)) { /* sleep for max. 200us to stabilize */ @@ -7411,7 +7511,7 @@ static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag) goto out; } - err = ufshcd_clear_cmds(hba, 1U << tag); + err = ufshcd_clear_cmd(hba, tag); if (err) dev_err(hba->dev, "%s: Failed clearing cmd at tag %d, err %d\n", __func__, tag, err); @@ -7439,14 +7539,17 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) WARN_ONCE(tag < 0, "Invalid tag %d\n", tag); - ufshcd_hold(hba, false); - reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); - /* If command is already aborted/completed, return FAILED. */ - if (!(test_bit(tag, &hba->outstanding_reqs))) { - dev_err(hba->dev, - "%s: cmd at tag %d already completed, outstanding=0x%lx, doorbell=0x%x\n", - __func__, tag, hba->outstanding_reqs, reg); - goto release; + ufshcd_hold(hba); + + if (!is_mcq_enabled(hba)) { + reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); + if (!test_bit(tag, &hba->outstanding_reqs)) { + /* If command is already aborted/completed, return FAILED. */ + dev_err(hba->dev, + "%s: cmd at tag %d already completed, outstanding=0x%lx, doorbell=0x%x\n", + __func__, tag, hba->outstanding_reqs, reg); + goto release; + } } /* Print Transfer Request of aborted task */ @@ -7471,7 +7574,8 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) } hba->req_abort_count++; - if (!(reg & (1 << tag))) { + if (!is_mcq_enabled(hba) && !(reg & (1 << tag))) { + /* only execute this code in single doorbell mode */ dev_err(hba->dev, "%s: cmd was completed, but without a notifying intr, tag = %d", __func__, tag); @@ -7497,6 +7601,12 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) goto release; } + if (is_mcq_enabled(hba)) { + /* MCQ mode. Branch off to handle abort for mcq mode */ + err = ufshcd_mcq_abort(cmd); + goto release; + } + /* Skip task abort in case previous aborts failed and report failure */ if (lrbp->req_abort_skip) { dev_err(hba->dev, "%s: skipping abort\n", __func__); @@ -7552,7 +7662,7 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba) ufshpb_toggle_state(hba, HPB_PRESENT, HPB_RESET); ufshcd_hba_stop(hba); hba->silence_err_logs = true; - ufshcd_complete_requests(hba); + ufshcd_complete_requests(hba, true); hba->silence_err_logs = false; /* scale up clocks to max frequency before full reinitialization */ @@ -8502,11 +8612,15 @@ err: static void ufshcd_config_mcq(struct ufs_hba *hba) { int ret; + u32 intrs; ret = ufshcd_mcq_vops_config_esi(hba); dev_info(hba->dev, "ESI %sconfigured\n", ret ? "is not " : ""); - ufshcd_enable_intr(hba, UFSHCD_ENABLE_MCQ_INTRS); + intrs = UFSHCD_ENABLE_MCQ_INTRS; + if (hba->quirks & UFSHCD_QUIRK_MCQ_BROKEN_INTR) + intrs &= ~MCQ_CQ_EVENT_STATUS; + ufshcd_enable_intr(hba, intrs); ufshcd_mcq_make_queues_operational(hba); ufshcd_mcq_config_mac(hba, hba->nutrs); @@ -8774,7 +8888,7 @@ static const struct scsi_host_template ufshcd_driver_template = { .cmd_per_lun = UFSHCD_CMD_PER_LUN, .can_queue = UFSHCD_CAN_QUEUE, .max_segment_size = PRDT_DATA_BYTE_COUNT_MAX, - .max_sectors = (1 << 20) / SECTOR_SIZE, /* 1 MiB */ + .max_sectors = SZ_1M / SECTOR_SIZE, .max_host_blocked = 1, .track_queue_depth = 1, .skip_settle_delay = 1, @@ -9184,7 +9298,8 @@ static int ufshcd_execute_start_stop(struct scsi_device *sdev, }; return scsi_execute_cmd(sdev, cdb, REQ_OP_DRV_IN, /*buffer=*/NULL, - /*bufflen=*/0, /*timeout=*/HZ, /*retries=*/0, &args); + /*bufflen=*/0, /*timeout=*/10 * HZ, /*retries=*/0, + &args); } /** @@ -9430,7 +9545,7 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) * If we can't transition into any of the low power modes * just gate the clocks. */ - ufshcd_hold(hba, false); + ufshcd_hold(hba); hba->clk_gating.is_suspended = true; if (ufshcd_is_clkscaling_supported(hba)) @@ -9775,28 +9890,6 @@ out: } #endif -static void ufshcd_wl_shutdown(struct device *dev) -{ - struct scsi_device *sdev = to_scsi_device(dev); - struct ufs_hba *hba; - - hba = shost_priv(sdev->host); - - down(&hba->host_sem); - hba->shutting_down = true; - up(&hba->host_sem); - - /* Turn on everything while shutting down */ - ufshcd_rpm_get_sync(hba); - scsi_device_quiesce(sdev); - shost_for_each_device(sdev, hba->host) { - if (sdev == hba->ufs_device_wlun) - continue; - scsi_device_quiesce(sdev); - } - __ufshcd_wl_suspend(hba, UFS_SHUTDOWN_PM); -} - /** * ufshcd_suspend - helper function for suspend operations * @hba: per adapter instance @@ -9981,25 +10074,34 @@ int ufshcd_runtime_resume(struct device *dev) EXPORT_SYMBOL(ufshcd_runtime_resume); #endif /* CONFIG_PM */ -/** - * ufshcd_shutdown - shutdown routine - * @hba: per adapter instance - * - * This function would turn off both UFS device and UFS hba - * regulators. It would also disable clocks. - * - * Returns 0 always to allow force shutdown even in case of errors. - */ -int ufshcd_shutdown(struct ufs_hba *hba) +static void ufshcd_wl_shutdown(struct device *dev) { + struct scsi_device *sdev = to_scsi_device(dev); + struct ufs_hba *hba = shost_priv(sdev->host); + + down(&hba->host_sem); + hba->shutting_down = true; + up(&hba->host_sem); + + /* Turn on everything while shutting down */ + ufshcd_rpm_get_sync(hba); + scsi_device_quiesce(sdev); + shost_for_each_device(sdev, hba->host) { + if (sdev == hba->ufs_device_wlun) + continue; + scsi_device_quiesce(sdev); + } + __ufshcd_wl_suspend(hba, UFS_SHUTDOWN_PM); + + /* + * Next, turn off the UFS controller and the UFS regulators. Disable + * clocks. + */ if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba)) ufshcd_suspend(hba); hba->is_powered = false; - /* allow force shutdown even in case of errors */ - return 0; } -EXPORT_SYMBOL(ufshcd_shutdown); /** * ufshcd_remove - de-allocate SCSI host and host memory space @@ -10226,6 +10328,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) host->max_channel = UFSHCD_MAX_CHANNEL; host->unique_id = host->host_no; host->max_cmd_len = UFS_CDB_SIZE; + host->queuecommand_may_block = !!(hba->caps & UFSHCD_CAP_CLK_GATING); hba->max_pwr_info.is_valid = false; diff --git a/drivers/ufs/core/ufshpb.c b/drivers/ufs/core/ufshpb.c index a46a7666c891..255f8b38d0c2 100644 --- a/drivers/ufs/core/ufshpb.c +++ b/drivers/ufs/core/ufshpb.c @@ -30,7 +30,7 @@ static struct kmem_cache *ufshpb_mctx_cache; static mempool_t *ufshpb_mctx_pool; static mempool_t *ufshpb_page_pool; /* A cache size of 2MB can cache ppn in the 1GB range. */ -static unsigned int ufshpb_host_map_kbytes = 2048; +static unsigned int ufshpb_host_map_kbytes = SZ_2K; static int tot_active_srgn_pages; static struct workqueue_struct *ufshpb_wq; @@ -2461,7 +2461,7 @@ static void ufshpb_hpb_lu_prepared(struct ufs_hba *hba) init_success = !ufshpb_check_hpb_reset_query(hba); - pool_size = PAGE_ALIGN(ufshpb_host_map_kbytes * 1024) / PAGE_SIZE; + pool_size = PAGE_ALIGN(ufshpb_host_map_kbytes * SZ_1K) / PAGE_SIZE; if (pool_size > tot_active_srgn_pages) { mempool_resize(ufshpb_mctx_pool, tot_active_srgn_pages); mempool_resize(ufshpb_page_pool, tot_active_srgn_pages); @@ -2527,7 +2527,7 @@ static int ufshpb_init_mem_wq(struct ufs_hba *hba) return -ENOMEM; } - pool_size = PAGE_ALIGN(ufshpb_host_map_kbytes * 1024) / PAGE_SIZE; + pool_size = PAGE_ALIGN(ufshpb_host_map_kbytes * SZ_1K) / PAGE_SIZE; dev_info(hba->dev, "%s:%d ufshpb_host_map_kbytes %u pool_size %u\n", __func__, __LINE__, ufshpb_host_map_kbytes, pool_size); diff --git a/drivers/ufs/core/ufshpb.h b/drivers/ufs/core/ufshpb.h index 0d6e6004d783..b428bbdd2799 100644 --- a/drivers/ufs/core/ufshpb.h +++ b/drivers/ufs/core/ufshpb.h @@ -25,7 +25,7 @@ /* hpb map & entries macro */ #define HPB_RGN_SIZE_UNIT 512 -#define HPB_ENTRY_BLOCK_SIZE 4096 +#define HPB_ENTRY_BLOCK_SIZE SZ_4K #define HPB_ENTRY_SIZE 0x8 #define PINNED_NOT_SET U32_MAX diff --git a/drivers/ufs/host/Kconfig b/drivers/ufs/host/Kconfig index 8793e3433580..16624ba08050 100644 --- a/drivers/ufs/host/Kconfig +++ b/drivers/ufs/host/Kconfig @@ -59,7 +59,7 @@ config SCSI_UFS_QCOM depends on SCSI_UFSHCD_PLATFORM && ARCH_QCOM depends on GENERIC_MSI_IRQ depends on RESET_CONTROLLER - select QCOM_SCM if SCSI_UFS_CRYPTO + select QCOM_INLINE_CRYPTO_ENGINE if SCSI_UFS_CRYPTO help This selects the QCOM specific additions to UFSHCD platform driver. UFS host on QCOM needs some vendor specific configuration before diff --git a/drivers/ufs/host/Makefile b/drivers/ufs/host/Makefile index d7c5bf7fa512..4573aead02eb 100644 --- a/drivers/ufs/host/Makefile +++ b/drivers/ufs/host/Makefile @@ -3,9 +3,7 @@ obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-dwc.o tc-dwc-g210.o obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o tc-dwc-g210.o obj-$(CONFIG_SCSI_UFS_CDNS_PLATFORM) += cdns-pltfrm.o -obj-$(CONFIG_SCSI_UFS_QCOM) += ufs_qcom.o -ufs_qcom-y += ufs-qcom.o -ufs_qcom-$(CONFIG_SCSI_UFS_CRYPTO) += ufs-qcom-ice.o +obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o obj-$(CONFIG_SCSI_UFS_EXYNOS) += ufs-exynos.o obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o diff --git a/drivers/ufs/host/cdns-pltfrm.c b/drivers/ufs/host/cdns-pltfrm.c index e05c0ae64eea..26761425a76c 100644 --- a/drivers/ufs/host/cdns-pltfrm.c +++ b/drivers/ufs/host/cdns-pltfrm.c @@ -328,7 +328,6 @@ static const struct dev_pm_ops cdns_ufs_dev_pm_ops = { static struct platform_driver cdns_ufs_pltfrm_driver = { .probe = cdns_ufs_pltfrm_probe, .remove = cdns_ufs_pltfrm_remove, - .shutdown = ufshcd_pltfrm_shutdown, .driver = { .name = "cdns-ufshcd", .pm = &cdns_ufs_dev_pm_ops, diff --git a/drivers/ufs/host/tc-dwc-g210-pci.c b/drivers/ufs/host/tc-dwc-g210-pci.c index 92b8ad4b58fe..f96fe5855841 100644 --- a/drivers/ufs/host/tc-dwc-g210-pci.c +++ b/drivers/ufs/host/tc-dwc-g210-pci.c @@ -33,15 +33,6 @@ static struct ufs_hba_variant_ops tc_dwc_g210_pci_hba_vops = { }; /** - * tc_dwc_g210_pci_shutdown - main function to put the controller in reset state - * @pdev: pointer to PCI device handle - */ -static void tc_dwc_g210_pci_shutdown(struct pci_dev *pdev) -{ - ufshcd_shutdown((struct ufs_hba *)pci_get_drvdata(pdev)); -} - -/** * tc_dwc_g210_pci_remove - de-allocate PCI/SCSI host and host memory space * data structure memory * @pdev: pointer to PCI handle @@ -137,7 +128,6 @@ static struct pci_driver tc_dwc_g210_pci_driver = { .id_table = tc_dwc_g210_pci_tbl, .probe = tc_dwc_g210_pci_probe, .remove = tc_dwc_g210_pci_remove, - .shutdown = tc_dwc_g210_pci_shutdown, .driver = { .pm = &tc_dwc_g210_pci_pm_ops }, diff --git a/drivers/ufs/host/tc-dwc-g210-pltfrm.c b/drivers/ufs/host/tc-dwc-g210-pltfrm.c index f15a84d0c176..4d5389dd9585 100644 --- a/drivers/ufs/host/tc-dwc-g210-pltfrm.c +++ b/drivers/ufs/host/tc-dwc-g210-pltfrm.c @@ -92,7 +92,6 @@ static const struct dev_pm_ops tc_dwc_g210_pltfm_pm_ops = { static struct platform_driver tc_dwc_g210_pltfm_driver = { .probe = tc_dwc_g210_pltfm_probe, .remove = tc_dwc_g210_pltfm_remove, - .shutdown = ufshcd_pltfrm_shutdown, .driver = { .name = "tc-dwc-g210-pltfm", .pm = &tc_dwc_g210_pltfm_pm_ops, diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c index 0bf5390739e1..3396e0388512 100644 --- a/drivers/ufs/host/ufs-exynos.c +++ b/drivers/ufs/host/ufs-exynos.c @@ -1306,7 +1306,7 @@ static int exynos_ufs_hce_enable_notify(struct ufs_hba *hba, * (ufshcd_async_scan()). Note: this callback may also be called * from other functions than ufshcd_init(). */ - hba->host->max_segment_size = 4096; + hba->host->max_segment_size = SZ_4K; if (ufs->drv_data->pre_hce_enable) { ret = ufs->drv_data->pre_hce_enable(ufs); @@ -1757,7 +1757,6 @@ static const struct dev_pm_ops exynos_ufs_pm_ops = { static struct platform_driver exynos_ufs_pltform = { .probe = exynos_ufs_probe, .remove = exynos_ufs_remove, - .shutdown = ufshcd_pltfrm_shutdown, .driver = { .name = "exynos-ufshc", .pm = &exynos_ufs_pm_ops, diff --git a/drivers/ufs/host/ufs-hisi.c b/drivers/ufs/host/ufs-hisi.c index 4c423eba8aa9..5b3060cd0ab8 100644 --- a/drivers/ufs/host/ufs-hisi.c +++ b/drivers/ufs/host/ufs-hisi.c @@ -335,29 +335,29 @@ static void ufs_hisi_pwr_change_pre_change(struct ufs_hba *hba) /* PA_TxSkip */ ufshcd_dme_set(hba, UIC_ARG_MIB(0x155c), 0x0); /*PA_PWRModeUserData0 = 8191, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b0), 8191); + ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b0), SZ_8K - 1); /*PA_PWRModeUserData1 = 65535, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b1), 65535); + ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b1), SZ_64K - 1); /*PA_PWRModeUserData2 = 32767, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b2), 32767); + ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b2), SZ_32K - 1); /*DME_FC0ProtectionTimeOutVal = 8191, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0xd041), 8191); + ufshcd_dme_set(hba, UIC_ARG_MIB(0xd041), SZ_8K - 1); /*DME_TC0ReplayTimeOutVal = 65535, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0xd042), 65535); + ufshcd_dme_set(hba, UIC_ARG_MIB(0xd042), SZ_64K - 1); /*DME_AFC0ReqTimeOutVal = 32767, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0xd043), 32767); + ufshcd_dme_set(hba, UIC_ARG_MIB(0xd043), SZ_32K - 1); /*PA_PWRModeUserData3 = 8191, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b3), 8191); + ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b3), SZ_8K - 1); /*PA_PWRModeUserData4 = 65535, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b4), 65535); + ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b4), SZ_64K - 1); /*PA_PWRModeUserData5 = 32767, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b5), 32767); + ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b5), SZ_32K - 1); /*DME_FC1ProtectionTimeOutVal = 8191, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0xd044), 8191); + ufshcd_dme_set(hba, UIC_ARG_MIB(0xd044), SZ_8K - 1); /*DME_TC1ReplayTimeOutVal = 65535, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0xd045), 65535); + ufshcd_dme_set(hba, UIC_ARG_MIB(0xd045), SZ_64K - 1); /*DME_AFC1ReqTimeOutVal = 32767, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0xd046), 32767); + ufshcd_dme_set(hba, UIC_ARG_MIB(0xd046), SZ_32K - 1); } static int ufs_hisi_pwr_change_notify(struct ufs_hba *hba, @@ -593,7 +593,6 @@ static const struct dev_pm_ops ufs_hisi_pm_ops = { static struct platform_driver ufs_hisi_pltform = { .probe = ufs_hisi_probe, .remove = ufs_hisi_remove, - .shutdown = ufshcd_pltfrm_shutdown, .driver = { .name = "ufshcd-hisi", .pm = &ufs_hisi_pm_ops, diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c index 73e217260390..e68b05976f9e 100644 --- a/drivers/ufs/host/ufs-mediatek.c +++ b/drivers/ufs/host/ufs-mediatek.c @@ -410,9 +410,6 @@ static int ufs_mtk_wait_link_state(struct ufs_hba *hba, u32 state, usleep_range(100, 200); } while (ktime_before(time_checked, timeout)); - if (val == state) - return 0; - return -ETIMEDOUT; } @@ -901,6 +898,8 @@ static int ufs_mtk_init(struct ufs_hba *hba) hba->caps |= UFSHCD_CAP_CLK_SCALING; hba->quirks |= UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL; + hba->quirks |= UFSHCD_QUIRK_MCQ_BROKEN_INTR; + hba->quirks |= UFSHCD_QUIRK_MCQ_BROKEN_RTC; hba->vps->wb_flush_threshold = UFS_WB_BUF_REMAIN_PERCENT(80); if (host->caps & UFS_MTK_CAP_DISABLE_AH8) @@ -1650,7 +1649,6 @@ static const struct dev_pm_ops ufs_mtk_pm_ops = { static struct platform_driver ufs_mtk_pltform = { .probe = ufs_mtk_probe, .remove = ufs_mtk_remove, - .shutdown = ufshcd_pltfrm_shutdown, .driver = { .name = "ufshcd-mtk", .pm = &ufs_mtk_pm_ops, diff --git a/drivers/ufs/host/ufs-qcom-ice.c b/drivers/ufs/host/ufs-qcom-ice.c deleted file mode 100644 index 453978877ae9..000000000000 --- a/drivers/ufs/host/ufs-qcom-ice.c +++ /dev/null @@ -1,244 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Qualcomm ICE (Inline Crypto Engine) support. - * - * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. - * Copyright 2019 Google LLC - */ - -#include <linux/delay.h> -#include <linux/platform_device.h> -#include <linux/firmware/qcom/qcom_scm.h> - -#include "ufs-qcom.h" - -#define AES_256_XTS_KEY_SIZE 64 - -/* QCOM ICE registers */ - -#define QCOM_ICE_REG_CONTROL 0x0000 -#define QCOM_ICE_REG_RESET 0x0004 -#define QCOM_ICE_REG_VERSION 0x0008 -#define QCOM_ICE_REG_FUSE_SETTING 0x0010 -#define QCOM_ICE_REG_PARAMETERS_1 0x0014 -#define QCOM_ICE_REG_PARAMETERS_2 0x0018 -#define QCOM_ICE_REG_PARAMETERS_3 0x001C -#define QCOM_ICE_REG_PARAMETERS_4 0x0020 -#define QCOM_ICE_REG_PARAMETERS_5 0x0024 - -/* QCOM ICE v3.X only */ -#define QCOM_ICE_GENERAL_ERR_STTS 0x0040 -#define QCOM_ICE_INVALID_CCFG_ERR_STTS 0x0030 -#define QCOM_ICE_GENERAL_ERR_MASK 0x0044 - -/* QCOM ICE v2.X only */ -#define QCOM_ICE_REG_NON_SEC_IRQ_STTS 0x0040 -#define QCOM_ICE_REG_NON_SEC_IRQ_MASK 0x0044 - -#define QCOM_ICE_REG_NON_SEC_IRQ_CLR 0x0048 -#define QCOM_ICE_REG_STREAM1_ERROR_SYNDROME1 0x0050 -#define QCOM_ICE_REG_STREAM1_ERROR_SYNDROME2 0x0054 -#define QCOM_ICE_REG_STREAM2_ERROR_SYNDROME1 0x0058 -#define QCOM_ICE_REG_STREAM2_ERROR_SYNDROME2 0x005C -#define QCOM_ICE_REG_STREAM1_BIST_ERROR_VEC 0x0060 -#define QCOM_ICE_REG_STREAM2_BIST_ERROR_VEC 0x0064 -#define QCOM_ICE_REG_STREAM1_BIST_FINISH_VEC 0x0068 -#define QCOM_ICE_REG_STREAM2_BIST_FINISH_VEC 0x006C -#define QCOM_ICE_REG_BIST_STATUS 0x0070 -#define QCOM_ICE_REG_BYPASS_STATUS 0x0074 -#define QCOM_ICE_REG_ADVANCED_CONTROL 0x1000 -#define QCOM_ICE_REG_ENDIAN_SWAP 0x1004 -#define QCOM_ICE_REG_TEST_BUS_CONTROL 0x1010 -#define QCOM_ICE_REG_TEST_BUS_REG 0x1014 - -/* BIST ("built-in self-test"?) status flags */ -#define QCOM_ICE_BIST_STATUS_MASK 0xF0000000 - -#define QCOM_ICE_FUSE_SETTING_MASK 0x1 -#define QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK 0x2 -#define QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK 0x4 - -#define qcom_ice_writel(host, val, reg) \ - writel((val), (host)->ice_mmio + (reg)) -#define qcom_ice_readl(host, reg) \ - readl((host)->ice_mmio + (reg)) - -static bool qcom_ice_supported(struct ufs_qcom_host *host) -{ - struct device *dev = host->hba->dev; - u32 regval = qcom_ice_readl(host, QCOM_ICE_REG_VERSION); - int major = regval >> 24; - int minor = (regval >> 16) & 0xFF; - int step = regval & 0xFFFF; - - /* For now this driver only supports ICE version 3. */ - if (major != 3) { - dev_warn(dev, "Unsupported ICE version: v%d.%d.%d\n", - major, minor, step); - return false; - } - - dev_info(dev, "Found QC Inline Crypto Engine (ICE) v%d.%d.%d\n", - major, minor, step); - - /* If fuses are blown, ICE might not work in the standard way. */ - regval = qcom_ice_readl(host, QCOM_ICE_REG_FUSE_SETTING); - if (regval & (QCOM_ICE_FUSE_SETTING_MASK | - QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK | - QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK)) { - dev_warn(dev, "Fuses are blown; ICE is unusable!\n"); - return false; - } - return true; -} - -int ufs_qcom_ice_init(struct ufs_qcom_host *host) -{ - struct ufs_hba *hba = host->hba; - struct device *dev = hba->dev; - struct platform_device *pdev = to_platform_device(dev); - struct resource *res; - int err; - - if (!(ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES) & - MASK_CRYPTO_SUPPORT)) - return 0; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ice"); - if (!res) { - dev_warn(dev, "ICE registers not found\n"); - goto disable; - } - - if (!qcom_scm_ice_available()) { - dev_warn(dev, "ICE SCM interface not found\n"); - goto disable; - } - - host->ice_mmio = devm_ioremap_resource(dev, res); - if (IS_ERR(host->ice_mmio)) { - err = PTR_ERR(host->ice_mmio); - return err; - } - - if (!qcom_ice_supported(host)) - goto disable; - - return 0; - -disable: - dev_warn(dev, "Disabling inline encryption support\n"); - hba->caps &= ~UFSHCD_CAP_CRYPTO; - return 0; -} - -static void qcom_ice_low_power_mode_enable(struct ufs_qcom_host *host) -{ - u32 regval; - - regval = qcom_ice_readl(host, QCOM_ICE_REG_ADVANCED_CONTROL); - /* - * Enable low power mode sequence - * [0]-0, [1]-0, [2]-0, [3]-E, [4]-0, [5]-0, [6]-0, [7]-0 - */ - regval |= 0x7000; - qcom_ice_writel(host, regval, QCOM_ICE_REG_ADVANCED_CONTROL); -} - -static void qcom_ice_optimization_enable(struct ufs_qcom_host *host) -{ - u32 regval; - - /* ICE Optimizations Enable Sequence */ - regval = qcom_ice_readl(host, QCOM_ICE_REG_ADVANCED_CONTROL); - regval |= 0xD807100; - /* ICE HPG requires delay before writing */ - udelay(5); - qcom_ice_writel(host, regval, QCOM_ICE_REG_ADVANCED_CONTROL); - udelay(5); -} - -int ufs_qcom_ice_enable(struct ufs_qcom_host *host) -{ - if (!(host->hba->caps & UFSHCD_CAP_CRYPTO)) - return 0; - qcom_ice_low_power_mode_enable(host); - qcom_ice_optimization_enable(host); - return ufs_qcom_ice_resume(host); -} - -/* Poll until all BIST bits are reset */ -static int qcom_ice_wait_bist_status(struct ufs_qcom_host *host) -{ - int count; - u32 reg; - - for (count = 0; count < 100; count++) { - reg = qcom_ice_readl(host, QCOM_ICE_REG_BIST_STATUS); - if (!(reg & QCOM_ICE_BIST_STATUS_MASK)) - break; - udelay(50); - } - if (reg) - return -ETIMEDOUT; - return 0; -} - -int ufs_qcom_ice_resume(struct ufs_qcom_host *host) -{ - int err; - - if (!(host->hba->caps & UFSHCD_CAP_CRYPTO)) - return 0; - - err = qcom_ice_wait_bist_status(host); - if (err) { - dev_err(host->hba->dev, "BIST status error (%d)\n", err); - return err; - } - return 0; -} - -/* - * Program a key into a QC ICE keyslot, or evict a keyslot. QC ICE requires - * vendor-specific SCM calls for this; it doesn't support the standard way. - */ -int ufs_qcom_ice_program_key(struct ufs_hba *hba, - const union ufs_crypto_cfg_entry *cfg, int slot) -{ - union ufs_crypto_cap_entry cap; - union { - u8 bytes[AES_256_XTS_KEY_SIZE]; - u32 words[AES_256_XTS_KEY_SIZE / sizeof(u32)]; - } key; - int i; - int err; - - if (!(cfg->config_enable & UFS_CRYPTO_CONFIGURATION_ENABLE)) - return qcom_scm_ice_invalidate_key(slot); - - /* Only AES-256-XTS has been tested so far. */ - cap = hba->crypto_cap_array[cfg->crypto_cap_idx]; - if (cap.algorithm_id != UFS_CRYPTO_ALG_AES_XTS || - cap.key_size != UFS_CRYPTO_KEY_SIZE_256) { - dev_err_ratelimited(hba->dev, - "Unhandled crypto capability; algorithm_id=%d, key_size=%d\n", - cap.algorithm_id, cap.key_size); - return -EINVAL; - } - - memcpy(key.bytes, cfg->crypto_key, AES_256_XTS_KEY_SIZE); - - /* - * The SCM call byte-swaps the 32-bit words of the key. So we have to - * do the same, in order for the final key be correct. - */ - for (i = 0; i < ARRAY_SIZE(key.words); i++) - __cpu_to_be32s(&key.words[i]); - - err = qcom_scm_ice_set_key(slot, key.bytes, AES_256_XTS_KEY_SIZE, - QCOM_SCM_ICE_CIPHER_AES_256_XTS, - cfg->data_unit_size); - memzero_explicit(&key, sizeof(key)); - return err; -} diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index 82d02e7f3b4f..8d6fd4c3324f 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -15,6 +15,8 @@ #include <linux/reset-controller.h> #include <linux/devfreq.h> +#include <soc/qcom/ice.h> + #include <ufs/ufshcd.h> #include "ufshcd-pltfrm.h" #include <ufs/unipro.h> @@ -55,6 +57,100 @@ static struct ufs_qcom_host *rcdev_to_ufs_host(struct reset_controller_dev *rcd) return container_of(rcd, struct ufs_qcom_host, rcdev); } +#ifdef CONFIG_SCSI_UFS_CRYPTO + +static inline void ufs_qcom_ice_enable(struct ufs_qcom_host *host) +{ + if (host->hba->caps & UFSHCD_CAP_CRYPTO) + qcom_ice_enable(host->ice); +} + +static int ufs_qcom_ice_init(struct ufs_qcom_host *host) +{ + struct ufs_hba *hba = host->hba; + struct device *dev = hba->dev; + struct qcom_ice *ice; + + ice = of_qcom_ice_get(dev); + if (ice == ERR_PTR(-EOPNOTSUPP)) { + dev_warn(dev, "Disabling inline encryption support\n"); + ice = NULL; + } + + if (IS_ERR_OR_NULL(ice)) + return PTR_ERR_OR_ZERO(ice); + + host->ice = ice; + hba->caps |= UFSHCD_CAP_CRYPTO; + + return 0; +} + +static inline int ufs_qcom_ice_resume(struct ufs_qcom_host *host) +{ + if (host->hba->caps & UFSHCD_CAP_CRYPTO) + return qcom_ice_resume(host->ice); + + return 0; +} + +static inline int ufs_qcom_ice_suspend(struct ufs_qcom_host *host) +{ + if (host->hba->caps & UFSHCD_CAP_CRYPTO) + return qcom_ice_suspend(host->ice); + + return 0; +} + +static int ufs_qcom_ice_program_key(struct ufs_hba *hba, + const union ufs_crypto_cfg_entry *cfg, + int slot) +{ + struct ufs_qcom_host *host = ufshcd_get_variant(hba); + union ufs_crypto_cap_entry cap; + bool config_enable = + cfg->config_enable & UFS_CRYPTO_CONFIGURATION_ENABLE; + + /* Only AES-256-XTS has been tested so far. */ + cap = hba->crypto_cap_array[cfg->crypto_cap_idx]; + if (cap.algorithm_id != UFS_CRYPTO_ALG_AES_XTS || + cap.key_size != UFS_CRYPTO_KEY_SIZE_256) + return -EINVAL; + + if (config_enable) + return qcom_ice_program_key(host->ice, + QCOM_ICE_CRYPTO_ALG_AES_XTS, + QCOM_ICE_CRYPTO_KEY_SIZE_256, + cfg->crypto_key, + cfg->data_unit_size, slot); + else + return qcom_ice_evict_key(host->ice, slot); +} + +#else + +#define ufs_qcom_ice_program_key NULL + +static inline void ufs_qcom_ice_enable(struct ufs_qcom_host *host) +{ +} + +static int ufs_qcom_ice_init(struct ufs_qcom_host *host) +{ + return 0; +} + +static inline int ufs_qcom_ice_resume(struct ufs_qcom_host *host) +{ + return 0; +} + +static inline int ufs_qcom_ice_suspend(struct ufs_qcom_host *host) +{ + return 0; +} +#endif + static int ufs_qcom_host_clk_get(struct device *dev, const char *name, struct clk **clk_out, bool optional) { @@ -607,7 +703,7 @@ static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op, ufs_qcom_disable_lane_clks(host); } - return 0; + return ufs_qcom_ice_suspend(host); } static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) @@ -853,7 +949,6 @@ static void ufs_qcom_set_caps(struct ufs_hba *hba) hba->caps |= UFSHCD_CAP_CLK_SCALING | UFSHCD_CAP_WB_WITH_CLK_SCALING; hba->caps |= UFSHCD_CAP_AUTO_BKOPS_SUSPEND; hba->caps |= UFSHCD_CAP_WB_EN; - hba->caps |= UFSHCD_CAP_CRYPTO; hba->caps |= UFSHCD_CAP_AGGR_POWER_COLLAPSE; hba->caps |= UFSHCD_CAP_RPM_AUTOSUSPEND; @@ -1556,7 +1651,7 @@ static irqreturn_t ufs_qcom_mcq_esi_handler(int irq, void *__hba) struct ufs_hw_queue *hwq = &hba->uhq[id]; ufshcd_mcq_write_cqis(hba, 0x1, id); - ufshcd_mcq_poll_cqe_nolock(hba, hwq); + ufshcd_mcq_poll_cqe_lock(hba, hwq); return IRQ_HANDLED; } @@ -1723,7 +1818,6 @@ static const struct dev_pm_ops ufs_qcom_pm_ops = { static struct platform_driver ufs_qcom_pltform = { .probe = ufs_qcom_probe, .remove = ufs_qcom_remove, - .shutdown = ufshcd_pltfrm_shutdown, .driver = { .name = "ufshcd-qcom", .pm = &ufs_qcom_pm_ops, diff --git a/drivers/ufs/host/ufs-qcom.h b/drivers/ufs/host/ufs-qcom.h index 39e774254fb2..6289ad5a42d0 100644 --- a/drivers/ufs/host/ufs-qcom.h +++ b/drivers/ufs/host/ufs-qcom.h @@ -7,6 +7,7 @@ #include <linux/reset-controller.h> #include <linux/reset.h> +#include <soc/qcom/ice.h> #include <ufs/ufshcd.h> #define MAX_UFS_QCOM_HOSTS 1 @@ -205,12 +206,13 @@ struct ufs_qcom_host { struct clk *tx_l1_sync_clk; bool is_lane_clks_enabled; +#ifdef CONFIG_SCSI_UFS_CRYPTO + struct qcom_ice *ice; +#endif + void __iomem *dev_ref_clk_ctrl_mmio; bool is_dev_ref_clk_enabled; struct ufs_hw_version hw_ver; -#ifdef CONFIG_SCSI_UFS_CRYPTO - void __iomem *ice_mmio; -#endif u32 dev_ref_clk_en_mask; @@ -248,28 +250,4 @@ static inline bool ufs_qcom_cap_qunipro(struct ufs_qcom_host *host) return host->caps & UFS_QCOM_CAP_QUNIPRO; } -/* ufs-qcom-ice.c */ - -#ifdef CONFIG_SCSI_UFS_CRYPTO -int ufs_qcom_ice_init(struct ufs_qcom_host *host); -int ufs_qcom_ice_enable(struct ufs_qcom_host *host); -int ufs_qcom_ice_resume(struct ufs_qcom_host *host); -int ufs_qcom_ice_program_key(struct ufs_hba *hba, - const union ufs_crypto_cfg_entry *cfg, int slot); -#else -static inline int ufs_qcom_ice_init(struct ufs_qcom_host *host) -{ - return 0; -} -static inline int ufs_qcom_ice_enable(struct ufs_qcom_host *host) -{ - return 0; -} -static inline int ufs_qcom_ice_resume(struct ufs_qcom_host *host) -{ - return 0; -} -#define ufs_qcom_ice_program_key NULL -#endif /* !CONFIG_SCSI_UFS_CRYPTO */ - #endif /* UFS_QCOM_H_ */ diff --git a/drivers/ufs/host/ufs-sprd.c b/drivers/ufs/host/ufs-sprd.c index 051f3f40d92c..2bad75dd6d58 100644 --- a/drivers/ufs/host/ufs-sprd.c +++ b/drivers/ufs/host/ufs-sprd.c @@ -444,7 +444,6 @@ static const struct dev_pm_ops ufs_sprd_pm_ops = { static struct platform_driver ufs_sprd_pltform = { .probe = ufs_sprd_probe, .remove = ufs_sprd_remove, - .shutdown = ufshcd_pltfrm_shutdown, .driver = { .name = "ufshcd-sprd", .pm = &ufs_sprd_pm_ops, diff --git a/drivers/ufs/host/ufshcd-pci.c b/drivers/ufs/host/ufshcd-pci.c index 9c911787f84c..cf3987773051 100644 --- a/drivers/ufs/host/ufshcd-pci.c +++ b/drivers/ufs/host/ufshcd-pci.c @@ -505,15 +505,6 @@ static int ufshcd_pci_restore(struct device *dev) #endif /** - * ufshcd_pci_shutdown - main function to put the controller in reset state - * @pdev: pointer to PCI device handle - */ -static void ufshcd_pci_shutdown(struct pci_dev *pdev) -{ - ufshcd_shutdown((struct ufs_hba *)pci_get_drvdata(pdev)); -} - -/** * ufshcd_pci_remove - de-allocate PCI/SCSI host and host memory space * data structure memory * @pdev: pointer to PCI handle @@ -608,6 +599,7 @@ static const struct pci_device_id ufshcd_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x54FF), (kernel_ulong_t)&ufs_intel_adl_hba_vops }, { PCI_VDEVICE(INTEL, 0x7E47), (kernel_ulong_t)&ufs_intel_mtl_hba_vops }, { PCI_VDEVICE(INTEL, 0xA847), (kernel_ulong_t)&ufs_intel_mtl_hba_vops }, + { PCI_VDEVICE(INTEL, 0x7747), (kernel_ulong_t)&ufs_intel_mtl_hba_vops }, { } /* terminate list */ }; @@ -618,7 +610,6 @@ static struct pci_driver ufshcd_pci_driver = { .id_table = ufshcd_pci_tbl, .probe = ufshcd_pci_probe, .remove = ufshcd_pci_remove, - .shutdown = ufshcd_pci_shutdown, .driver = { .pm = &ufshcd_pci_pm_ops }, diff --git a/drivers/ufs/host/ufshcd-pltfrm.c b/drivers/ufs/host/ufshcd-pltfrm.c index 5739ff007828..0b7430033047 100644 --- a/drivers/ufs/host/ufshcd-pltfrm.c +++ b/drivers/ufs/host/ufshcd-pltfrm.c @@ -190,12 +190,6 @@ out: return err; } -void ufshcd_pltfrm_shutdown(struct platform_device *pdev) -{ - ufshcd_shutdown((struct ufs_hba *)platform_get_drvdata(pdev)); -} -EXPORT_SYMBOL_GPL(ufshcd_pltfrm_shutdown); - static void ufshcd_init_lanes_per_dir(struct ufs_hba *hba) { struct device *dev = hba->dev; diff --git a/drivers/ufs/host/ufshcd-pltfrm.h b/drivers/ufs/host/ufshcd-pltfrm.h index 2e4ba2bfbcad..2df108f4ac13 100644 --- a/drivers/ufs/host/ufshcd-pltfrm.h +++ b/drivers/ufs/host/ufshcd-pltfrm.h @@ -31,7 +31,6 @@ int ufshcd_get_pwr_dev_param(const struct ufs_dev_params *dev_param, void ufshcd_init_pwr_dev_param(struct ufs_dev_params *dev_param); int ufshcd_pltfrm_init(struct platform_device *pdev, const struct ufs_hba_variant_ops *vops); -void ufshcd_pltfrm_shutdown(struct platform_device *pdev); int ufshcd_populate_vreg(struct device *dev, const char *name, struct ufs_vreg **out_vreg); diff --git a/drivers/usb/typec/ucsi/psy.c b/drivers/usb/typec/ucsi/psy.c index 56bf56517f75..384b42267f1f 100644 --- a/drivers/usb/typec/ucsi/psy.c +++ b/drivers/usb/typec/ucsi/psy.c @@ -27,8 +27,20 @@ static enum power_supply_property ucsi_psy_props[] = { POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_CURRENT_MAX, POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_SCOPE, }; +static int ucsi_psy_get_scope(struct ucsi_connector *con, + union power_supply_propval *val) +{ + u8 scope = POWER_SUPPLY_SCOPE_UNKNOWN; + struct device *dev = con->ucsi->dev; + + device_property_read_u8(dev, "scope", &scope); + val->intval = scope; + return 0; +} + static int ucsi_psy_get_online(struct ucsi_connector *con, union power_supply_propval *val) { @@ -194,6 +206,8 @@ static int ucsi_psy_get_prop(struct power_supply *psy, return ucsi_psy_get_current_max(con, val); case POWER_SUPPLY_PROP_CURRENT_NOW: return ucsi_psy_get_current_now(con, val); + case POWER_SUPPLY_PROP_SCOPE: + return ucsi_psy_get_scope(con, val); default: return -EINVAL; } diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig index 89e06c981e43..aba36f5be4ec 100644 --- a/drivers/vfio/Kconfig +++ b/drivers/vfio/Kconfig @@ -57,6 +57,7 @@ source "drivers/vfio/pci/Kconfig" source "drivers/vfio/platform/Kconfig" source "drivers/vfio/mdev/Kconfig" source "drivers/vfio/fsl-mc/Kconfig" +source "drivers/vfio/cdx/Kconfig" endif source "virt/lib/Kconfig" diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile index 70e7dcb302ef..66f418aef5a9 100644 --- a/drivers/vfio/Makefile +++ b/drivers/vfio/Makefile @@ -10,7 +10,8 @@ vfio-$(CONFIG_VFIO_VIRQFD) += virqfd.o obj-$(CONFIG_VFIO_IOMMU_TYPE1) += vfio_iommu_type1.o obj-$(CONFIG_VFIO_IOMMU_SPAPR_TCE) += vfio_iommu_spapr_tce.o -obj-$(CONFIG_VFIO_PCI) += pci/ -obj-$(CONFIG_VFIO_PLATFORM) += platform/ +obj-$(CONFIG_VFIO_PCI_CORE) += pci/ +obj-$(CONFIG_VFIO_PLATFORM_BASE) += platform/ obj-$(CONFIG_VFIO_MDEV) += mdev/ obj-$(CONFIG_VFIO_FSL_MC) += fsl-mc/ +obj-$(CONFIG_VFIO_CDX) += cdx/ diff --git a/drivers/vfio/cdx/Kconfig b/drivers/vfio/cdx/Kconfig new file mode 100644 index 000000000000..e6de0a0caa32 --- /dev/null +++ b/drivers/vfio/cdx/Kconfig @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# VFIO CDX configuration +# +# Copyright (C) 2022-2023, Advanced Micro Devices, Inc. +# + +config VFIO_CDX + tristate "VFIO support for CDX bus devices" + depends on CDX_BUS + select EVENTFD + help + Driver to enable VFIO support for the devices on CDX bus. + This is required to make use of CDX devices present in + the system using the VFIO framework. + + If you don't know what to do here, say N. diff --git a/drivers/vfio/cdx/Makefile b/drivers/vfio/cdx/Makefile new file mode 100644 index 000000000000..cd4a2e6fe609 --- /dev/null +++ b/drivers/vfio/cdx/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) 2022-2023, Advanced Micro Devices, Inc. +# + +obj-$(CONFIG_VFIO_CDX) += vfio-cdx.o + +vfio-cdx-objs := main.o diff --git a/drivers/vfio/cdx/main.c b/drivers/vfio/cdx/main.c new file mode 100644 index 000000000000..c376a69d2db2 --- /dev/null +++ b/drivers/vfio/cdx/main.c @@ -0,0 +1,234 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022-2023, Advanced Micro Devices, Inc. + */ + +#include <linux/vfio.h> +#include <linux/cdx/cdx_bus.h> + +#include "private.h" + +static int vfio_cdx_open_device(struct vfio_device *core_vdev) +{ + struct vfio_cdx_device *vdev = + container_of(core_vdev, struct vfio_cdx_device, vdev); + struct cdx_device *cdx_dev = to_cdx_device(core_vdev->dev); + int count = cdx_dev->res_count; + int i; + + vdev->regions = kcalloc(count, sizeof(struct vfio_cdx_region), + GFP_KERNEL_ACCOUNT); + if (!vdev->regions) + return -ENOMEM; + + for (i = 0; i < count; i++) { + struct resource *res = &cdx_dev->res[i]; + + vdev->regions[i].addr = res->start; + vdev->regions[i].size = resource_size(res); + vdev->regions[i].type = res->flags; + /* + * Only regions addressed with PAGE granularity may be + * MMAP'ed securely. + */ + if (!(vdev->regions[i].addr & ~PAGE_MASK) && + !(vdev->regions[i].size & ~PAGE_MASK)) + vdev->regions[i].flags |= + VFIO_REGION_INFO_FLAG_MMAP; + vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_READ; + if (!(cdx_dev->res[i].flags & IORESOURCE_READONLY)) + vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_WRITE; + } + + return 0; +} + +static void vfio_cdx_close_device(struct vfio_device *core_vdev) +{ + struct vfio_cdx_device *vdev = + container_of(core_vdev, struct vfio_cdx_device, vdev); + + kfree(vdev->regions); + cdx_dev_reset(core_vdev->dev); +} + +static int vfio_cdx_ioctl_get_info(struct vfio_cdx_device *vdev, + struct vfio_device_info __user *arg) +{ + unsigned long minsz = offsetofend(struct vfio_device_info, num_irqs); + struct cdx_device *cdx_dev = to_cdx_device(vdev->vdev.dev); + struct vfio_device_info info; + + if (copy_from_user(&info, arg, minsz)) + return -EFAULT; + + if (info.argsz < minsz) + return -EINVAL; + + info.flags = VFIO_DEVICE_FLAGS_CDX; + info.flags |= VFIO_DEVICE_FLAGS_RESET; + + info.num_regions = cdx_dev->res_count; + info.num_irqs = 0; + + return copy_to_user(arg, &info, minsz) ? -EFAULT : 0; +} + +static int vfio_cdx_ioctl_get_region_info(struct vfio_cdx_device *vdev, + struct vfio_region_info __user *arg) +{ + unsigned long minsz = offsetofend(struct vfio_region_info, offset); + struct cdx_device *cdx_dev = to_cdx_device(vdev->vdev.dev); + struct vfio_region_info info; + + if (copy_from_user(&info, arg, minsz)) + return -EFAULT; + + if (info.argsz < minsz) + return -EINVAL; + + if (info.index >= cdx_dev->res_count) + return -EINVAL; + + /* map offset to the physical address */ + info.offset = vfio_cdx_index_to_offset(info.index); + info.size = vdev->regions[info.index].size; + info.flags = vdev->regions[info.index].flags; + + return copy_to_user(arg, &info, minsz) ? -EFAULT : 0; +} + +static long vfio_cdx_ioctl(struct vfio_device *core_vdev, + unsigned int cmd, unsigned long arg) +{ + struct vfio_cdx_device *vdev = + container_of(core_vdev, struct vfio_cdx_device, vdev); + void __user *uarg = (void __user *)arg; + + switch (cmd) { + case VFIO_DEVICE_GET_INFO: + return vfio_cdx_ioctl_get_info(vdev, uarg); + case VFIO_DEVICE_GET_REGION_INFO: + return vfio_cdx_ioctl_get_region_info(vdev, uarg); + case VFIO_DEVICE_RESET: + return cdx_dev_reset(core_vdev->dev); + default: + return -ENOTTY; + } +} + +static int vfio_cdx_mmap_mmio(struct vfio_cdx_region region, + struct vm_area_struct *vma) +{ + u64 size = vma->vm_end - vma->vm_start; + u64 pgoff, base; + + pgoff = vma->vm_pgoff & + ((1U << (VFIO_CDX_OFFSET_SHIFT - PAGE_SHIFT)) - 1); + base = pgoff << PAGE_SHIFT; + + if (base + size > region.size) + return -EINVAL; + + vma->vm_pgoff = (region.addr >> PAGE_SHIFT) + pgoff; + vma->vm_page_prot = pgprot_device(vma->vm_page_prot); + + return io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, + size, vma->vm_page_prot); +} + +static int vfio_cdx_mmap(struct vfio_device *core_vdev, + struct vm_area_struct *vma) +{ + struct vfio_cdx_device *vdev = + container_of(core_vdev, struct vfio_cdx_device, vdev); + struct cdx_device *cdx_dev = to_cdx_device(core_vdev->dev); + unsigned int index; + + index = vma->vm_pgoff >> (VFIO_CDX_OFFSET_SHIFT - PAGE_SHIFT); + + if (index >= cdx_dev->res_count) + return -EINVAL; + + if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_MMAP)) + return -EINVAL; + + if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_READ) && + (vma->vm_flags & VM_READ)) + return -EPERM; + + if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_WRITE) && + (vma->vm_flags & VM_WRITE)) + return -EPERM; + + return vfio_cdx_mmap_mmio(vdev->regions[index], vma); +} + +static const struct vfio_device_ops vfio_cdx_ops = { + .name = "vfio-cdx", + .open_device = vfio_cdx_open_device, + .close_device = vfio_cdx_close_device, + .ioctl = vfio_cdx_ioctl, + .mmap = vfio_cdx_mmap, + .bind_iommufd = vfio_iommufd_physical_bind, + .unbind_iommufd = vfio_iommufd_physical_unbind, + .attach_ioas = vfio_iommufd_physical_attach_ioas, +}; + +static int vfio_cdx_probe(struct cdx_device *cdx_dev) +{ + struct vfio_cdx_device *vdev; + struct device *dev = &cdx_dev->dev; + int ret; + + vdev = vfio_alloc_device(vfio_cdx_device, vdev, dev, + &vfio_cdx_ops); + if (IS_ERR(vdev)) + return PTR_ERR(vdev); + + ret = vfio_register_group_dev(&vdev->vdev); + if (ret) + goto out_uninit; + + dev_set_drvdata(dev, vdev); + return 0; + +out_uninit: + vfio_put_device(&vdev->vdev); + return ret; +} + +static int vfio_cdx_remove(struct cdx_device *cdx_dev) +{ + struct device *dev = &cdx_dev->dev; + struct vfio_cdx_device *vdev = dev_get_drvdata(dev); + + vfio_unregister_group_dev(&vdev->vdev); + vfio_put_device(&vdev->vdev); + + return 0; +} + +static const struct cdx_device_id vfio_cdx_table[] = { + { CDX_DEVICE_DRIVER_OVERRIDE(CDX_ANY_ID, CDX_ANY_ID, + CDX_ID_F_VFIO_DRIVER_OVERRIDE) }, /* match all by default */ + {} +}; + +MODULE_DEVICE_TABLE(cdx, vfio_cdx_table); + +static struct cdx_driver vfio_cdx_driver = { + .probe = vfio_cdx_probe, + .remove = vfio_cdx_remove, + .match_id_table = vfio_cdx_table, + .driver = { + .name = "vfio-cdx", + .owner = THIS_MODULE, + }, + .driver_managed_dma = true, +}; + +module_driver(vfio_cdx_driver, cdx_driver_register, cdx_driver_unregister); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("VFIO for CDX devices - User Level meta-driver"); diff --git a/drivers/vfio/cdx/private.h b/drivers/vfio/cdx/private.h new file mode 100644 index 000000000000..8bdc117ea88e --- /dev/null +++ b/drivers/vfio/cdx/private.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022-2023, Advanced Micro Devices, Inc. + */ + +#ifndef VFIO_CDX_PRIVATE_H +#define VFIO_CDX_PRIVATE_H + +#define VFIO_CDX_OFFSET_SHIFT 40 + +static inline u64 vfio_cdx_index_to_offset(u32 index) +{ + return ((u64)(index) << VFIO_CDX_OFFSET_SHIFT); +} + +struct vfio_cdx_region { + u32 flags; + u32 type; + u64 addr; + resource_size_t size; +}; + +struct vfio_cdx_device { + struct vfio_device vdev; + struct vfio_cdx_region *regions; +}; + +#endif /* VFIO_CDX_PRIVATE_H */ diff --git a/drivers/vfio/fsl-mc/Kconfig b/drivers/vfio/fsl-mc/Kconfig index 597d338c5c8a..7d1d690348f0 100644 --- a/drivers/vfio/fsl-mc/Kconfig +++ b/drivers/vfio/fsl-mc/Kconfig @@ -1,6 +1,8 @@ +menu "VFIO support for FSL_MC bus devices" + depends on FSL_MC_BUS + config VFIO_FSL_MC tristate "VFIO support for QorIQ DPAA2 fsl-mc bus devices" - depends on FSL_MC_BUS select EVENTFD help Driver to enable support for the VFIO QorIQ DPAA2 fsl-mc @@ -8,3 +10,5 @@ config VFIO_FSL_MC fsl-mc bus devices using the VFIO framework. If you don't know what to do here, say N. + +endmenu diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c index 58f91b3bd670..ed4737de4528 100644 --- a/drivers/vfio/mdev/mdev_core.c +++ b/drivers/vfio/mdev/mdev_core.c @@ -72,12 +72,6 @@ int mdev_register_parent(struct mdev_parent *parent, struct device *dev, parent->nr_types = nr_types; atomic_set(&parent->available_instances, mdev_driver->max_instances); - if (!mdev_bus_compat_class) { - mdev_bus_compat_class = class_compat_register("mdev_bus"); - if (!mdev_bus_compat_class) - return -ENOMEM; - } - ret = parent_create_sysfs_files(parent); if (ret) return ret; @@ -251,13 +245,24 @@ int mdev_device_remove(struct mdev_device *mdev) static int __init mdev_init(void) { - return bus_register(&mdev_bus_type); + int ret; + + ret = bus_register(&mdev_bus_type); + if (ret) + return ret; + + mdev_bus_compat_class = class_compat_register("mdev_bus"); + if (!mdev_bus_compat_class) { + bus_unregister(&mdev_bus_type); + return -ENOMEM; + } + + return 0; } static void __exit mdev_exit(void) { - if (mdev_bus_compat_class) - class_compat_unregister(mdev_bus_compat_class); + class_compat_unregister(mdev_bus_compat_class); bus_unregister(&mdev_bus_type); } diff --git a/drivers/vfio/pci/Kconfig b/drivers/vfio/pci/Kconfig index f9d0c908e738..86bb7835cf3c 100644 --- a/drivers/vfio/pci/Kconfig +++ b/drivers/vfio/pci/Kconfig @@ -1,5 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only -if PCI && MMU +menu "VFIO support for PCI devices" + depends on PCI && MMU + config VFIO_PCI_CORE tristate select VFIO_VIRQFD @@ -7,9 +9,11 @@ config VFIO_PCI_CORE config VFIO_PCI_MMAP def_bool y if !S390 + depends on VFIO_PCI_CORE config VFIO_PCI_INTX def_bool y if !S390 + depends on VFIO_PCI_CORE config VFIO_PCI tristate "Generic VFIO support for any PCI device" @@ -59,4 +63,4 @@ source "drivers/vfio/pci/mlx5/Kconfig" source "drivers/vfio/pci/hisilicon/Kconfig" -endif +endmenu diff --git a/drivers/vfio/pci/hisilicon/Kconfig b/drivers/vfio/pci/hisilicon/Kconfig index 5daa0f45d2f9..cbf1c32f6ebf 100644 --- a/drivers/vfio/pci/hisilicon/Kconfig +++ b/drivers/vfio/pci/hisilicon/Kconfig @@ -1,13 +1,13 @@ # SPDX-License-Identifier: GPL-2.0-only config HISI_ACC_VFIO_PCI - tristate "VFIO PCI support for HiSilicon ACC devices" + tristate "VFIO support for HiSilicon ACC PCI devices" depends on ARM64 || (COMPILE_TEST && 64BIT) - depends on VFIO_PCI_CORE depends on PCI_MSI depends on CRYPTO_DEV_HISI_QM depends on CRYPTO_DEV_HISI_HPRE depends on CRYPTO_DEV_HISI_SEC2 depends on CRYPTO_DEV_HISI_ZIP + select VFIO_PCI_CORE help This provides generic PCI support for HiSilicon ACC devices using the VFIO framework. diff --git a/drivers/vfio/pci/mlx5/Kconfig b/drivers/vfio/pci/mlx5/Kconfig index 29ba9c504a75..7088edc4fb28 100644 --- a/drivers/vfio/pci/mlx5/Kconfig +++ b/drivers/vfio/pci/mlx5/Kconfig @@ -2,7 +2,7 @@ config MLX5_VFIO_PCI tristate "VFIO support for MLX5 PCI devices" depends on MLX5_CORE - depends on VFIO_PCI_CORE + select VFIO_PCI_CORE help This provides migration support for MLX5 devices using the VFIO framework. diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c index 948cdd464f4e..7e2e62ab0869 100644 --- a/drivers/vfio/pci/vfio_pci_config.c +++ b/drivers/vfio/pci/vfio_pci_config.c @@ -1566,8 +1566,8 @@ static int vfio_cap_init(struct vfio_pci_core_device *vdev) } if (!len) { - pci_info(pdev, "%s: hiding cap %#x@%#x\n", __func__, - cap, pos); + pci_dbg(pdev, "%s: hiding cap %#x@%#x\n", __func__, + cap, pos); *prev = next; pos = next; continue; @@ -1643,8 +1643,8 @@ static int vfio_ecap_init(struct vfio_pci_core_device *vdev) } if (!len) { - pci_info(pdev, "%s: hiding ecap %#x@%#x\n", - __func__, ecap, epos); + pci_dbg(pdev, "%s: hiding ecap %#x@%#x\n", + __func__, ecap, epos); /* If not the first in the chain, we can skip over it */ if (prev) { diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c index a5ab416cf476..20d7b69ea6ff 100644 --- a/drivers/vfio/pci/vfio_pci_core.c +++ b/drivers/vfio/pci/vfio_pci_core.c @@ -530,8 +530,11 @@ int vfio_pci_core_enable(struct vfio_pci_core_device *vdev) vdev->msix_bar = table & PCI_MSIX_TABLE_BIR; vdev->msix_offset = table & PCI_MSIX_TABLE_OFFSET; vdev->msix_size = ((flags & PCI_MSIX_FLAGS_QSIZE) + 1) * 16; - } else + vdev->has_dyn_msix = pci_msix_can_alloc_dyn(pdev); + } else { vdev->msix_bar = 0xFF; + vdev->has_dyn_msix = false; + } if (!vfio_vga_disabled() && vfio_pci_is_vga(pdev)) vdev->has_vga = true; @@ -882,6 +885,37 @@ int vfio_pci_core_register_dev_region(struct vfio_pci_core_device *vdev, } EXPORT_SYMBOL_GPL(vfio_pci_core_register_dev_region); +static int vfio_pci_info_atomic_cap(struct vfio_pci_core_device *vdev, + struct vfio_info_cap *caps) +{ + struct vfio_device_info_cap_pci_atomic_comp cap = { + .header.id = VFIO_DEVICE_INFO_CAP_PCI_ATOMIC_COMP, + .header.version = 1 + }; + struct pci_dev *pdev = pci_physfn(vdev->pdev); + u32 devcap2; + + pcie_capability_read_dword(pdev, PCI_EXP_DEVCAP2, &devcap2); + + if ((devcap2 & PCI_EXP_DEVCAP2_ATOMIC_COMP32) && + !pci_enable_atomic_ops_to_root(pdev, PCI_EXP_DEVCAP2_ATOMIC_COMP32)) + cap.flags |= VFIO_PCI_ATOMIC_COMP32; + + if ((devcap2 & PCI_EXP_DEVCAP2_ATOMIC_COMP64) && + !pci_enable_atomic_ops_to_root(pdev, PCI_EXP_DEVCAP2_ATOMIC_COMP64)) + cap.flags |= VFIO_PCI_ATOMIC_COMP64; + + if ((devcap2 & PCI_EXP_DEVCAP2_ATOMIC_COMP128) && + !pci_enable_atomic_ops_to_root(pdev, + PCI_EXP_DEVCAP2_ATOMIC_COMP128)) + cap.flags |= VFIO_PCI_ATOMIC_COMP128; + + if (!cap.flags) + return -ENODEV; + + return vfio_info_add_capability(caps, &cap.header, sizeof(cap)); +} + static int vfio_pci_ioctl_get_info(struct vfio_pci_core_device *vdev, struct vfio_device_info __user *arg) { @@ -920,6 +954,13 @@ static int vfio_pci_ioctl_get_info(struct vfio_pci_core_device *vdev, return ret; } + ret = vfio_pci_info_atomic_cap(vdev, &caps); + if (ret && ret != -ENODEV) { + pci_warn(vdev->pdev, + "Failed to setup AtomicOps info capability\n"); + return ret; + } + if (caps.size) { info.flags |= VFIO_DEVICE_FLAGS_CAPS; if (info.argsz < sizeof(info) + caps.size) { @@ -1111,7 +1152,7 @@ static int vfio_pci_ioctl_get_irq_info(struct vfio_pci_core_device *vdev, if (info.index == VFIO_PCI_INTX_IRQ_INDEX) info.flags |= (VFIO_IRQ_INFO_MASKABLE | VFIO_IRQ_INFO_AUTOMASKED); - else + else if (info.index != VFIO_PCI_MSIX_IRQ_INDEX || !vdev->has_dyn_msix) info.flags |= VFIO_IRQ_INFO_NORESIZE; return copy_to_user(arg, &info, minsz) ? -EFAULT : 0; @@ -2102,6 +2143,7 @@ int vfio_pci_core_init_dev(struct vfio_device *core_vdev) INIT_LIST_HEAD(&vdev->vma_list); INIT_LIST_HEAD(&vdev->sriov_pfs_item); init_rwsem(&vdev->memory_lock); + xa_init(&vdev->ctx); return 0; } diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c index bffb0741518b..cbb4bcbfbf83 100644 --- a/drivers/vfio/pci/vfio_pci_intrs.c +++ b/drivers/vfio/pci/vfio_pci_intrs.c @@ -48,6 +48,39 @@ static bool is_irq_none(struct vfio_pci_core_device *vdev) vdev->irq_type == VFIO_PCI_MSIX_IRQ_INDEX); } +static +struct vfio_pci_irq_ctx *vfio_irq_ctx_get(struct vfio_pci_core_device *vdev, + unsigned long index) +{ + return xa_load(&vdev->ctx, index); +} + +static void vfio_irq_ctx_free(struct vfio_pci_core_device *vdev, + struct vfio_pci_irq_ctx *ctx, unsigned long index) +{ + xa_erase(&vdev->ctx, index); + kfree(ctx); +} + +static struct vfio_pci_irq_ctx * +vfio_irq_ctx_alloc(struct vfio_pci_core_device *vdev, unsigned long index) +{ + struct vfio_pci_irq_ctx *ctx; + int ret; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL_ACCOUNT); + if (!ctx) + return NULL; + + ret = xa_insert(&vdev->ctx, index, ctx, GFP_KERNEL_ACCOUNT); + if (ret) { + kfree(ctx); + return NULL; + } + + return ctx; +} + /* * INTx */ @@ -55,14 +88,21 @@ static void vfio_send_intx_eventfd(void *opaque, void *unused) { struct vfio_pci_core_device *vdev = opaque; - if (likely(is_intx(vdev) && !vdev->virq_disabled)) - eventfd_signal(vdev->ctx[0].trigger, 1); + if (likely(is_intx(vdev) && !vdev->virq_disabled)) { + struct vfio_pci_irq_ctx *ctx; + + ctx = vfio_irq_ctx_get(vdev, 0); + if (WARN_ON_ONCE(!ctx)) + return; + eventfd_signal(ctx->trigger, 1); + } } /* Returns true if the INTx vfio_pci_irq_ctx.masked value is changed. */ bool vfio_pci_intx_mask(struct vfio_pci_core_device *vdev) { struct pci_dev *pdev = vdev->pdev; + struct vfio_pci_irq_ctx *ctx; unsigned long flags; bool masked_changed = false; @@ -77,7 +117,14 @@ bool vfio_pci_intx_mask(struct vfio_pci_core_device *vdev) if (unlikely(!is_intx(vdev))) { if (vdev->pci_2_3) pci_intx(pdev, 0); - } else if (!vdev->ctx[0].masked) { + goto out_unlock; + } + + ctx = vfio_irq_ctx_get(vdev, 0); + if (WARN_ON_ONCE(!ctx)) + goto out_unlock; + + if (!ctx->masked) { /* * Can't use check_and_mask here because we always want to * mask, not just when something is pending. @@ -87,10 +134,11 @@ bool vfio_pci_intx_mask(struct vfio_pci_core_device *vdev) else disable_irq_nosync(pdev->irq); - vdev->ctx[0].masked = true; + ctx->masked = true; masked_changed = true; } +out_unlock: spin_unlock_irqrestore(&vdev->irqlock, flags); return masked_changed; } @@ -105,6 +153,7 @@ static int vfio_pci_intx_unmask_handler(void *opaque, void *unused) { struct vfio_pci_core_device *vdev = opaque; struct pci_dev *pdev = vdev->pdev; + struct vfio_pci_irq_ctx *ctx; unsigned long flags; int ret = 0; @@ -117,7 +166,14 @@ static int vfio_pci_intx_unmask_handler(void *opaque, void *unused) if (unlikely(!is_intx(vdev))) { if (vdev->pci_2_3) pci_intx(pdev, 1); - } else if (vdev->ctx[0].masked && !vdev->virq_disabled) { + goto out_unlock; + } + + ctx = vfio_irq_ctx_get(vdev, 0); + if (WARN_ON_ONCE(!ctx)) + goto out_unlock; + + if (ctx->masked && !vdev->virq_disabled) { /* * A pending interrupt here would immediately trigger, * but we can avoid that overhead by just re-sending @@ -129,9 +185,10 @@ static int vfio_pci_intx_unmask_handler(void *opaque, void *unused) } else enable_irq(pdev->irq); - vdev->ctx[0].masked = (ret > 0); + ctx->masked = (ret > 0); } +out_unlock: spin_unlock_irqrestore(&vdev->irqlock, flags); return ret; @@ -146,18 +203,23 @@ void vfio_pci_intx_unmask(struct vfio_pci_core_device *vdev) static irqreturn_t vfio_intx_handler(int irq, void *dev_id) { struct vfio_pci_core_device *vdev = dev_id; + struct vfio_pci_irq_ctx *ctx; unsigned long flags; int ret = IRQ_NONE; + ctx = vfio_irq_ctx_get(vdev, 0); + if (WARN_ON_ONCE(!ctx)) + return ret; + spin_lock_irqsave(&vdev->irqlock, flags); if (!vdev->pci_2_3) { disable_irq_nosync(vdev->pdev->irq); - vdev->ctx[0].masked = true; + ctx->masked = true; ret = IRQ_HANDLED; - } else if (!vdev->ctx[0].masked && /* may be shared */ + } else if (!ctx->masked && /* may be shared */ pci_check_and_mask_intx(vdev->pdev)) { - vdev->ctx[0].masked = true; + ctx->masked = true; ret = IRQ_HANDLED; } @@ -171,27 +233,27 @@ static irqreturn_t vfio_intx_handler(int irq, void *dev_id) static int vfio_intx_enable(struct vfio_pci_core_device *vdev) { + struct vfio_pci_irq_ctx *ctx; + if (!is_irq_none(vdev)) return -EINVAL; if (!vdev->pdev->irq) return -ENODEV; - vdev->ctx = kzalloc(sizeof(struct vfio_pci_irq_ctx), GFP_KERNEL_ACCOUNT); - if (!vdev->ctx) + ctx = vfio_irq_ctx_alloc(vdev, 0); + if (!ctx) return -ENOMEM; - vdev->num_ctx = 1; - /* * If the virtual interrupt is masked, restore it. Devices * supporting DisINTx can be masked at the hardware level * here, non-PCI-2.3 devices will have to wait until the * interrupt is enabled. */ - vdev->ctx[0].masked = vdev->virq_disabled; + ctx->masked = vdev->virq_disabled; if (vdev->pci_2_3) - pci_intx(vdev->pdev, !vdev->ctx[0].masked); + pci_intx(vdev->pdev, !ctx->masked); vdev->irq_type = VFIO_PCI_INTX_IRQ_INDEX; @@ -202,41 +264,46 @@ static int vfio_intx_set_signal(struct vfio_pci_core_device *vdev, int fd) { struct pci_dev *pdev = vdev->pdev; unsigned long irqflags = IRQF_SHARED; + struct vfio_pci_irq_ctx *ctx; struct eventfd_ctx *trigger; unsigned long flags; int ret; - if (vdev->ctx[0].trigger) { + ctx = vfio_irq_ctx_get(vdev, 0); + if (WARN_ON_ONCE(!ctx)) + return -EINVAL; + + if (ctx->trigger) { free_irq(pdev->irq, vdev); - kfree(vdev->ctx[0].name); - eventfd_ctx_put(vdev->ctx[0].trigger); - vdev->ctx[0].trigger = NULL; + kfree(ctx->name); + eventfd_ctx_put(ctx->trigger); + ctx->trigger = NULL; } if (fd < 0) /* Disable only */ return 0; - vdev->ctx[0].name = kasprintf(GFP_KERNEL_ACCOUNT, "vfio-intx(%s)", - pci_name(pdev)); - if (!vdev->ctx[0].name) + ctx->name = kasprintf(GFP_KERNEL_ACCOUNT, "vfio-intx(%s)", + pci_name(pdev)); + if (!ctx->name) return -ENOMEM; trigger = eventfd_ctx_fdget(fd); if (IS_ERR(trigger)) { - kfree(vdev->ctx[0].name); + kfree(ctx->name); return PTR_ERR(trigger); } - vdev->ctx[0].trigger = trigger; + ctx->trigger = trigger; if (!vdev->pci_2_3) irqflags = 0; ret = request_irq(pdev->irq, vfio_intx_handler, - irqflags, vdev->ctx[0].name, vdev); + irqflags, ctx->name, vdev); if (ret) { - vdev->ctx[0].trigger = NULL; - kfree(vdev->ctx[0].name); + ctx->trigger = NULL; + kfree(ctx->name); eventfd_ctx_put(trigger); return ret; } @@ -246,7 +313,7 @@ static int vfio_intx_set_signal(struct vfio_pci_core_device *vdev, int fd) * disable_irq won't. */ spin_lock_irqsave(&vdev->irqlock, flags); - if (!vdev->pci_2_3 && vdev->ctx[0].masked) + if (!vdev->pci_2_3 && ctx->masked) disable_irq_nosync(pdev->irq); spin_unlock_irqrestore(&vdev->irqlock, flags); @@ -255,12 +322,17 @@ static int vfio_intx_set_signal(struct vfio_pci_core_device *vdev, int fd) static void vfio_intx_disable(struct vfio_pci_core_device *vdev) { - vfio_virqfd_disable(&vdev->ctx[0].unmask); - vfio_virqfd_disable(&vdev->ctx[0].mask); + struct vfio_pci_irq_ctx *ctx; + + ctx = vfio_irq_ctx_get(vdev, 0); + WARN_ON_ONCE(!ctx); + if (ctx) { + vfio_virqfd_disable(&ctx->unmask); + vfio_virqfd_disable(&ctx->mask); + } vfio_intx_set_signal(vdev, -1); vdev->irq_type = VFIO_PCI_NUM_IRQS; - vdev->num_ctx = 0; - kfree(vdev->ctx); + vfio_irq_ctx_free(vdev, ctx, 0); } /* @@ -284,11 +356,6 @@ static int vfio_msi_enable(struct vfio_pci_core_device *vdev, int nvec, bool msi if (!is_irq_none(vdev)) return -EINVAL; - vdev->ctx = kcalloc(nvec, sizeof(struct vfio_pci_irq_ctx), - GFP_KERNEL_ACCOUNT); - if (!vdev->ctx) - return -ENOMEM; - /* return the number of supported vectors if we can't get all: */ cmd = vfio_pci_memory_lock_and_enable(vdev); ret = pci_alloc_irq_vectors(pdev, 1, nvec, flag); @@ -296,12 +363,10 @@ static int vfio_msi_enable(struct vfio_pci_core_device *vdev, int nvec, bool msi if (ret > 0) pci_free_irq_vectors(pdev); vfio_pci_memory_unlock_and_restore(vdev, cmd); - kfree(vdev->ctx); return ret; } vfio_pci_memory_unlock_and_restore(vdev, cmd); - vdev->num_ctx = nvec; vdev->irq_type = msix ? VFIO_PCI_MSIX_IRQ_INDEX : VFIO_PCI_MSI_IRQ_INDEX; @@ -316,53 +381,91 @@ static int vfio_msi_enable(struct vfio_pci_core_device *vdev, int nvec, bool msi return 0; } -static int vfio_msi_set_vector_signal(struct vfio_pci_core_device *vdev, - int vector, int fd, bool msix) +/* + * vfio_msi_alloc_irq() returns the Linux IRQ number of an MSI or MSI-X device + * interrupt vector. If a Linux IRQ number is not available then a new + * interrupt is allocated if dynamic MSI-X is supported. + * + * Where is vfio_msi_free_irq()? Allocated interrupts are maintained, + * essentially forming a cache that subsequent allocations can draw from. + * Interrupts are freed using pci_free_irq_vectors() when MSI/MSI-X is + * disabled. + */ +static int vfio_msi_alloc_irq(struct vfio_pci_core_device *vdev, + unsigned int vector, bool msix) { struct pci_dev *pdev = vdev->pdev; - struct eventfd_ctx *trigger; - int irq, ret; + struct msi_map map; + int irq; u16 cmd; - if (vector < 0 || vector >= vdev->num_ctx) + irq = pci_irq_vector(pdev, vector); + if (WARN_ON_ONCE(irq == 0)) return -EINVAL; + if (irq > 0 || !msix || !vdev->has_dyn_msix) + return irq; - irq = pci_irq_vector(pdev, vector); + cmd = vfio_pci_memory_lock_and_enable(vdev); + map = pci_msix_alloc_irq_at(pdev, vector, NULL); + vfio_pci_memory_unlock_and_restore(vdev, cmd); - if (vdev->ctx[vector].trigger) { - irq_bypass_unregister_producer(&vdev->ctx[vector].producer); + return map.index < 0 ? map.index : map.virq; +} +static int vfio_msi_set_vector_signal(struct vfio_pci_core_device *vdev, + unsigned int vector, int fd, bool msix) +{ + struct pci_dev *pdev = vdev->pdev; + struct vfio_pci_irq_ctx *ctx; + struct eventfd_ctx *trigger; + int irq = -EINVAL, ret; + u16 cmd; + + ctx = vfio_irq_ctx_get(vdev, vector); + + if (ctx) { + irq_bypass_unregister_producer(&ctx->producer); + irq = pci_irq_vector(pdev, vector); cmd = vfio_pci_memory_lock_and_enable(vdev); - free_irq(irq, vdev->ctx[vector].trigger); + free_irq(irq, ctx->trigger); vfio_pci_memory_unlock_and_restore(vdev, cmd); - - kfree(vdev->ctx[vector].name); - eventfd_ctx_put(vdev->ctx[vector].trigger); - vdev->ctx[vector].trigger = NULL; + /* Interrupt stays allocated, will be freed at MSI-X disable. */ + kfree(ctx->name); + eventfd_ctx_put(ctx->trigger); + vfio_irq_ctx_free(vdev, ctx, vector); } if (fd < 0) return 0; - vdev->ctx[vector].name = kasprintf(GFP_KERNEL_ACCOUNT, - "vfio-msi%s[%d](%s)", - msix ? "x" : "", vector, - pci_name(pdev)); - if (!vdev->ctx[vector].name) + if (irq == -EINVAL) { + /* Interrupt stays allocated, will be freed at MSI-X disable. */ + irq = vfio_msi_alloc_irq(vdev, vector, msix); + if (irq < 0) + return irq; + } + + ctx = vfio_irq_ctx_alloc(vdev, vector); + if (!ctx) return -ENOMEM; + ctx->name = kasprintf(GFP_KERNEL_ACCOUNT, "vfio-msi%s[%d](%s)", + msix ? "x" : "", vector, pci_name(pdev)); + if (!ctx->name) { + ret = -ENOMEM; + goto out_free_ctx; + } + trigger = eventfd_ctx_fdget(fd); if (IS_ERR(trigger)) { - kfree(vdev->ctx[vector].name); - return PTR_ERR(trigger); + ret = PTR_ERR(trigger); + goto out_free_name; } /* - * The MSIx vector table resides in device memory which may be cleared - * via backdoor resets. We don't allow direct access to the vector - * table so even if a userspace driver attempts to save/restore around - * such a reset it would be unsuccessful. To avoid this, restore the - * cached value of the message prior to enabling. + * If the vector was previously allocated, refresh the on-device + * message data before enabling in case it had been cleared or + * corrupted (e.g. due to backdoor resets) since writing. */ cmd = vfio_pci_memory_lock_and_enable(vdev); if (msix) { @@ -372,37 +475,39 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_core_device *vdev, pci_write_msi_msg(irq, &msg); } - ret = request_irq(irq, vfio_msihandler, 0, - vdev->ctx[vector].name, trigger); + ret = request_irq(irq, vfio_msihandler, 0, ctx->name, trigger); vfio_pci_memory_unlock_and_restore(vdev, cmd); - if (ret) { - kfree(vdev->ctx[vector].name); - eventfd_ctx_put(trigger); - return ret; - } + if (ret) + goto out_put_eventfd_ctx; - vdev->ctx[vector].producer.token = trigger; - vdev->ctx[vector].producer.irq = irq; - ret = irq_bypass_register_producer(&vdev->ctx[vector].producer); + ctx->producer.token = trigger; + ctx->producer.irq = irq; + ret = irq_bypass_register_producer(&ctx->producer); if (unlikely(ret)) { dev_info(&pdev->dev, "irq bypass producer (token %p) registration fails: %d\n", - vdev->ctx[vector].producer.token, ret); + ctx->producer.token, ret); - vdev->ctx[vector].producer.token = NULL; + ctx->producer.token = NULL; } - vdev->ctx[vector].trigger = trigger; + ctx->trigger = trigger; return 0; + +out_put_eventfd_ctx: + eventfd_ctx_put(trigger); +out_free_name: + kfree(ctx->name); +out_free_ctx: + vfio_irq_ctx_free(vdev, ctx, vector); + return ret; } static int vfio_msi_set_block(struct vfio_pci_core_device *vdev, unsigned start, unsigned count, int32_t *fds, bool msix) { - int i, j, ret = 0; - - if (start >= vdev->num_ctx || start + count > vdev->num_ctx) - return -EINVAL; + unsigned int i, j; + int ret = 0; for (i = 0, j = start; i < count && !ret; i++, j++) { int fd = fds ? fds[i] : -1; @@ -410,8 +515,8 @@ static int vfio_msi_set_block(struct vfio_pci_core_device *vdev, unsigned start, } if (ret) { - for (--j; j >= (int)start; j--) - vfio_msi_set_vector_signal(vdev, j, -1, msix); + for (i = start; i < j; i++) + vfio_msi_set_vector_signal(vdev, i, -1, msix); } return ret; @@ -420,16 +525,16 @@ static int vfio_msi_set_block(struct vfio_pci_core_device *vdev, unsigned start, static void vfio_msi_disable(struct vfio_pci_core_device *vdev, bool msix) { struct pci_dev *pdev = vdev->pdev; - int i; + struct vfio_pci_irq_ctx *ctx; + unsigned long i; u16 cmd; - for (i = 0; i < vdev->num_ctx; i++) { - vfio_virqfd_disable(&vdev->ctx[i].unmask); - vfio_virqfd_disable(&vdev->ctx[i].mask); + xa_for_each(&vdev->ctx, i, ctx) { + vfio_virqfd_disable(&ctx->unmask); + vfio_virqfd_disable(&ctx->mask); + vfio_msi_set_vector_signal(vdev, i, -1, msix); } - vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix); - cmd = vfio_pci_memory_lock_and_enable(vdev); pci_free_irq_vectors(pdev); vfio_pci_memory_unlock_and_restore(vdev, cmd); @@ -442,8 +547,6 @@ static void vfio_msi_disable(struct vfio_pci_core_device *vdev, bool msix) pci_intx(pdev, 0); vdev->irq_type = VFIO_PCI_NUM_IRQS; - vdev->num_ctx = 0; - kfree(vdev->ctx); } /* @@ -463,14 +566,18 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_core_device *vdev, if (unmask) vfio_pci_intx_unmask(vdev); } else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) { + struct vfio_pci_irq_ctx *ctx = vfio_irq_ctx_get(vdev, 0); int32_t fd = *(int32_t *)data; + + if (WARN_ON_ONCE(!ctx)) + return -EINVAL; if (fd >= 0) return vfio_virqfd_enable((void *) vdev, vfio_pci_intx_unmask_handler, vfio_send_intx_eventfd, NULL, - &vdev->ctx[0].unmask, fd); + &ctx->unmask, fd); - vfio_virqfd_disable(&vdev->ctx[0].unmask); + vfio_virqfd_disable(&ctx->unmask); } return 0; @@ -543,7 +650,8 @@ static int vfio_pci_set_msi_trigger(struct vfio_pci_core_device *vdev, unsigned index, unsigned start, unsigned count, uint32_t flags, void *data) { - int i; + struct vfio_pci_irq_ctx *ctx; + unsigned int i; bool msix = (index == VFIO_PCI_MSIX_IRQ_INDEX) ? true : false; if (irq_is(vdev, index) && !count && (flags & VFIO_IRQ_SET_DATA_NONE)) { @@ -573,18 +681,19 @@ static int vfio_pci_set_msi_trigger(struct vfio_pci_core_device *vdev, return ret; } - if (!irq_is(vdev, index) || start + count > vdev->num_ctx) + if (!irq_is(vdev, index)) return -EINVAL; for (i = start; i < start + count; i++) { - if (!vdev->ctx[i].trigger) + ctx = vfio_irq_ctx_get(vdev, i); + if (!ctx) continue; if (flags & VFIO_IRQ_SET_DATA_NONE) { - eventfd_signal(vdev->ctx[i].trigger, 1); + eventfd_signal(ctx->trigger, 1); } else if (flags & VFIO_IRQ_SET_DATA_BOOL) { uint8_t *bools = data; if (bools[i - start]) - eventfd_signal(vdev->ctx[i].trigger, 1); + eventfd_signal(ctx->trigger, 1); } } return 0; diff --git a/drivers/vfio/platform/Kconfig b/drivers/vfio/platform/Kconfig index 331a5920f5ab..88fcde51f024 100644 --- a/drivers/vfio/platform/Kconfig +++ b/drivers/vfio/platform/Kconfig @@ -1,8 +1,14 @@ # SPDX-License-Identifier: GPL-2.0-only -config VFIO_PLATFORM - tristate "VFIO support for platform devices" +menu "VFIO support for platform devices" depends on ARM || ARM64 || COMPILE_TEST + +config VFIO_PLATFORM_BASE + tristate select VFIO_VIRQFD + +config VFIO_PLATFORM + tristate "Generic VFIO support for any platform device" + select VFIO_PLATFORM_BASE help Support for platform devices with VFIO. This is required to make use of platform devices present on the system using the VFIO @@ -10,10 +16,10 @@ config VFIO_PLATFORM If you don't know what to do here, say N. -if VFIO_PLATFORM config VFIO_AMBA tristate "VFIO support for AMBA devices" depends on ARM_AMBA || COMPILE_TEST + select VFIO_PLATFORM_BASE help Support for ARM AMBA devices with VFIO. This is required to make use of ARM AMBA devices present on the system using the VFIO @@ -21,5 +27,9 @@ config VFIO_AMBA If you don't know what to do here, say N. +menu "VFIO platform reset drivers" + depends on VFIO_PLATFORM_BASE + source "drivers/vfio/platform/reset/Kconfig" -endif +endmenu +endmenu diff --git a/drivers/vfio/platform/Makefile b/drivers/vfio/platform/Makefile index 3f3a24e7c4ef..ee4fb6a82ca8 100644 --- a/drivers/vfio/platform/Makefile +++ b/drivers/vfio/platform/Makefile @@ -1,13 +1,10 @@ # SPDX-License-Identifier: GPL-2.0 vfio-platform-base-y := vfio_platform_common.o vfio_platform_irq.o -vfio-platform-y := vfio_platform.o +obj-$(CONFIG_VFIO_PLATFORM_BASE) += vfio-platform-base.o +obj-$(CONFIG_VFIO_PLATFORM_BASE) += reset/ +vfio-platform-y := vfio_platform.o obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o -obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform-base.o -obj-$(CONFIG_VFIO_PLATFORM) += reset/ vfio-amba-y := vfio_amba.o - obj-$(CONFIG_VFIO_AMBA) += vfio-amba.o -obj-$(CONFIG_VFIO_AMBA) += vfio-platform-base.o -obj-$(CONFIG_VFIO_AMBA) += reset/ diff --git a/drivers/vfio/platform/reset/Kconfig b/drivers/vfio/platform/reset/Kconfig index 12f5f3d80387..dcc08dc145a5 100644 --- a/drivers/vfio/platform/reset/Kconfig +++ b/drivers/vfio/platform/reset/Kconfig @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only +if VFIO_PLATFORM config VFIO_PLATFORM_CALXEDAXGMAC_RESET tristate "VFIO support for calxeda xgmac reset" help @@ -21,3 +22,4 @@ config VFIO_PLATFORM_BCMFLEXRM_RESET Enables the VFIO platform driver to handle reset for Broadcom FlexRM If you don't know what to do here, say N. +endif diff --git a/drivers/video/fbdev/stifb.c b/drivers/video/fbdev/stifb.c index 66d82f6d17c7..c746deb79afc 100644 --- a/drivers/video/fbdev/stifb.c +++ b/drivers/video/fbdev/stifb.c @@ -71,9 +71,9 @@ #include <video/sticore.h> -/* REGION_BASE(fb_info, index) returns the virtual address for region <index> */ +/* REGION_BASE(fb_info, index) returns the physical address for region <index> */ #define REGION_BASE(fb_info, index) \ - F_EXTEND(fb_info->sti->glob_cfg->region_ptrs[index]) + F_EXTEND(fb_info->sti->regions_phys[index]) #define NGLEDEVDEPROM_CRT_REGION 1 diff --git a/drivers/video/sticore.c b/drivers/video/sticore.c index 7eb925f2ba9c..c3765ad6eedf 100644 --- a/drivers/video/sticore.c +++ b/drivers/video/sticore.c @@ -4,7 +4,7 @@ * core code for console driver using HP's STI firmware * * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> - * Copyright (C) 2001-2020 Helge Deller <deller@gmx.de> + * Copyright (C) 2001-2023 Helge Deller <deller@gmx.de> * Copyright (C) 2001-2002 Thomas Bogendoerfer <tsbogend@alpha.franken.de> * * TODO: @@ -41,6 +41,26 @@ static struct sti_struct *default_sti __read_mostly; static int num_sti_roms __read_mostly; static struct sti_struct *sti_roms[MAX_STI_ROMS] __read_mostly; +static void *store_sti_val(struct sti_struct *sti, void *ptr, unsigned long val) +{ + u32 *ptr32 = ptr; + + if (IS_ENABLED(CONFIG_64BIT) && sti->do_call64) { + /* used for 64-bit STI ROM */ + unsigned long *ptr64 = ptr; + + ptr64 = PTR_ALIGN(ptr64, sizeof(void *)); + *ptr64++ = val; + return ptr64; + } + + /* used for 32-bit STI ROM */ + *ptr32++ = val; + return ptr32; +} + +#define store_sti_ptr(sti, dest, ptr) \ + store_sti_val(sti, dest, STI_PTR(ptr)) /* The colour indices used by STI are * 0 - Black @@ -87,7 +107,7 @@ static int sti_init_graph(struct sti_struct *sti) memset(inptr, 0, sizeof(*inptr)); inptr->text_planes = 3; /* # of text planes (max 3 for STI) */ memset(inptr_ext, 0, sizeof(*inptr_ext)); - inptr->ext_ptr = STI_PTR(inptr_ext); + store_sti_ptr(sti, &inptr->ext_ptr, inptr_ext); outptr->errno = 0; ret = sti_call(sti, sti->init_graph, &default_init_flags, inptr, @@ -118,7 +138,7 @@ static void sti_inq_conf(struct sti_struct *sti) unsigned long flags; s32 ret; - outptr->ext_ptr = STI_PTR(&sti->sti_data->inq_outptr_ext); + store_sti_ptr(sti, &outptr->ext_ptr, &sti->sti_data->inq_outptr_ext); do { spin_lock_irqsave(&sti->lock, flags); @@ -138,9 +158,9 @@ void sti_putc(struct sti_struct *sti, int c, int y, int x, struct sti_cooked_font *font) { - struct sti_font_inptr *inptr = &sti->sti_data->font_inptr; + struct sti_font_inptr *inptr; struct sti_font_inptr inptr_default = { - .font_start_addr = STI_PTR(font->raw), + .font_start_addr = (void *)STI_PTR(font->raw), .index = c_index(sti, c), .fg_color = c_fg(sti, c), .bg_color = c_bg(sti, c), @@ -153,7 +173,14 @@ sti_putc(struct sti_struct *sti, int c, int y, int x, do { spin_lock_irqsave(&sti->lock, flags); - *inptr = inptr_default; + inptr = &inptr_default; + if (IS_ENABLED(CONFIG_64BIT) && !sti->do_call64) { + /* copy below 4G if calling 32-bit on LP64 kernel */ + inptr = &sti->sti_data->font_inptr; + *inptr = inptr_default; + /* skip first 4 bytes for 32-bit STI call */ + inptr = (void *)(((unsigned long)inptr) + sizeof(u32)); + } ret = sti_call(sti, sti->font_unpmv, &default_font_flags, inptr, outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); @@ -170,7 +197,7 @@ void sti_set(struct sti_struct *sti, int src_y, int src_x, int height, int width, u8 color) { - struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr; + struct sti_blkmv_inptr *inptr; struct sti_blkmv_inptr inptr_default = { .fg_color = color, .bg_color = color, @@ -187,7 +214,12 @@ sti_set(struct sti_struct *sti, int src_y, int src_x, do { spin_lock_irqsave(&sti->lock, flags); - *inptr = inptr_default; + inptr = &inptr_default; + if (IS_ENABLED(CONFIG_64BIT) && !sti->do_call64) { + /* copy below 4G if calling 32-bit on LP64 kernel */ + inptr = &sti->sti_data->blkmv_inptr; + *inptr = inptr_default; + } ret = sti_call(sti, sti->block_move, &clear_blkmv_flags, inptr, outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); @@ -198,7 +230,7 @@ void sti_clear(struct sti_struct *sti, int src_y, int src_x, int height, int width, int c, struct sti_cooked_font *font) { - struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr; + struct sti_blkmv_inptr *inptr; struct sti_blkmv_inptr inptr_default = { .fg_color = c_fg(sti, c), .bg_color = c_bg(sti, c), @@ -215,7 +247,12 @@ sti_clear(struct sti_struct *sti, int src_y, int src_x, do { spin_lock_irqsave(&sti->lock, flags); - *inptr = inptr_default; + inptr = &inptr_default; + if (IS_ENABLED(CONFIG_64BIT) && !sti->do_call64) { + /* copy below 4G if calling 32-bit on LP64 kernel */ + inptr = &sti->sti_data->blkmv_inptr; + *inptr = inptr_default; + } ret = sti_call(sti, sti->block_move, &clear_blkmv_flags, inptr, outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); @@ -231,7 +268,7 @@ sti_bmove(struct sti_struct *sti, int src_y, int src_x, int dst_y, int dst_x, int height, int width, struct sti_cooked_font *font) { - struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr; + struct sti_blkmv_inptr *inptr; struct sti_blkmv_inptr inptr_default = { .src_x = src_x * font->width, .src_y = src_y * font->height, @@ -246,7 +283,12 @@ sti_bmove(struct sti_struct *sti, int src_y, int src_x, do { spin_lock_irqsave(&sti->lock, flags); - *inptr = inptr_default; + inptr = &inptr_default; + if (IS_ENABLED(CONFIG_64BIT) && !sti->do_call64) { + /* copy below 4G if calling 32-bit on LP64 kernel */ + inptr = &sti->sti_data->blkmv_inptr; + *inptr = inptr_default; + } ret = sti_call(sti, sti->block_move, &default_blkmv_flags, inptr, outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); @@ -359,42 +401,31 @@ __setup("sti_font=", sti_font_setup); -static void sti_dump_globcfg(struct sti_glob_cfg *glob_cfg, - unsigned int sti_mem_request) +static void sti_dump_globcfg(struct sti_struct *sti) { - struct sti_glob_cfg_ext *cfg; + struct sti_glob_cfg *glob_cfg = sti->glob_cfg; + struct sti_glob_cfg_ext *cfg = &sti->sti_data->glob_cfg_ext; pr_debug("%d text planes\n" "%4d x %4d screen resolution\n" "%4d x %4d offscreen\n" - "%4d x %4d layout\n" - "regions at %08x %08x %08x %08x\n" - "regions at %08x %08x %08x %08x\n" - "reent_lvl %d\n" - "save_addr %08x\n", + "%4d x %4d layout\n", glob_cfg->text_planes, glob_cfg->onscreen_x, glob_cfg->onscreen_y, glob_cfg->offscreen_x, glob_cfg->offscreen_y, - glob_cfg->total_x, glob_cfg->total_y, - glob_cfg->region_ptrs[0], glob_cfg->region_ptrs[1], - glob_cfg->region_ptrs[2], glob_cfg->region_ptrs[3], - glob_cfg->region_ptrs[4], glob_cfg->region_ptrs[5], - glob_cfg->region_ptrs[6], glob_cfg->region_ptrs[7], - glob_cfg->reent_lvl, - glob_cfg->save_addr); + glob_cfg->total_x, glob_cfg->total_y); /* dump extended cfg */ - cfg = PTR_STI((unsigned long)glob_cfg->ext_ptr); pr_debug("monitor %d\n" "in friendly mode: %d\n" "power consumption %d watts\n" "freq ref %d\n" - "sti_mem_addr %08x (size=%d bytes)\n", + "sti_mem_addr %px (size=%d bytes)\n", cfg->curr_mon, cfg->friendly_boot, cfg->power, cfg->freq_ref, - cfg->sti_mem_addr, sti_mem_request); + cfg->sti_mem_addr, sti->sti_mem_request); } static void sti_dump_outptr(struct sti_struct *sti) @@ -414,7 +445,7 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, { struct sti_glob_cfg *glob_cfg; struct sti_glob_cfg_ext *glob_cfg_ext; - void *save_addr; + void *save_addr, *ptr; void *sti_mem_addr; int i, size; @@ -432,9 +463,7 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, save_addr = &sti->sti_data->save_addr; sti_mem_addr = &sti->sti_data->sti_mem_addr; - glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext); - glob_cfg->save_addr = STI_PTR(save_addr); - for (i=0; i<8; i++) { + for (i = 0; i < STI_REGION_MAX; i++) { unsigned long newhpa, len; if (sti->pd) { @@ -457,13 +486,10 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, REGION_OFFSET_TO_PHYS(sti->regions[i], newhpa); len = sti->regions[i].region_desc.length * 4096; - if (len) - glob_cfg->region_ptrs[i] = sti->regions_phys[i]; - pr_debug("region #%d: phys %08lx, region_ptr %08x, len=%lukB, " + pr_debug("region #%d: phys %08lx, len=%lukB, " "btlb=%d, sysonly=%d, cache=%d, last=%d\n", - i, sti->regions_phys[i], glob_cfg->region_ptrs[i], - len/1024, + i, sti->regions_phys[i], len / 1024, sti->regions[i].region_desc.btlb, sti->regions[i].region_desc.sys_only, sti->regions[i].region_desc.cache, @@ -474,11 +500,16 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, break; } - if (++i<8 && sti->regions[i].region) - pr_warn("future ptr (0x%8x) not yet supported !\n", - sti->regions[i].region); + ptr = &glob_cfg->region_ptrs; + for (i = 0; i < STI_REGION_MAX; i++) + ptr = store_sti_val(sti, ptr, sti->regions_phys[i]); + + *(s32 *)ptr = 0; /* set reent_lvl */ + ptr += sizeof(s32); + ptr = store_sti_ptr(sti, ptr, save_addr); + ptr = store_sti_ptr(sti, ptr, glob_cfg_ext); - glob_cfg_ext->sti_mem_addr = STI_PTR(sti_mem_addr); + store_sti_ptr(sti, &glob_cfg_ext->sti_mem_addr, sti_mem_addr); sti->glob_cfg = glob_cfg; @@ -802,10 +833,19 @@ static int sti_read_rom(int wordmode, struct sti_struct *sti, raw->alt_code_type == ALT_CODE_TYPE_PA_RISC_64 ? "and 64 " : ""); - sti->font_unpmv = address + (raw->font_unpmv & 0x03ffffff); - sti->block_move = address + (raw->block_move & 0x03ffffff); - sti->init_graph = address + (raw->init_graph & 0x03ffffff); - sti->inq_conf = address + (raw->inq_conf & 0x03ffffff); + if (IS_ENABLED(CONFIG_64BIT) && + raw->alt_code_type == ALT_CODE_TYPE_PA_RISC_64) { + sti->do_call64 = 1; + sti->font_unpmv = address + (raw->font_unp_addr & 0x03ffffff); + sti->block_move = address + (raw->block_move_addr & 0x03ffffff); + sti->init_graph = address + (raw->init_graph_addr & 0x03ffffff); + sti->inq_conf = address + (raw->inq_conf_addr & 0x03ffffff); + } else { + sti->font_unpmv = address + (raw->font_unpmv & 0x03ffffff); + sti->block_move = address + (raw->block_move & 0x03ffffff); + sti->init_graph = address + (raw->init_graph & 0x03ffffff); + sti->inq_conf = address + (raw->inq_conf & 0x03ffffff); + } sti->rom = cooked; sti->rom->raw = raw; @@ -818,7 +858,13 @@ static int sti_read_rom(int wordmode, struct sti_struct *sti, sti_font_convert_bytemode(sti, sti->font); sti_dump_font(sti->font); + pr_info(" using %d-bit STI ROM functions\n", + (IS_ENABLED(CONFIG_64BIT) && sti->do_call64) ? 64 : 32); + sti->sti_mem_request = raw->sti_mem_req; + pr_debug(" mem_request = %d, reentsize %d\n", + sti->sti_mem_request, raw->reentsize); + sti->graphics_id[0] = raw->graphics_id[0]; sti->graphics_id[1] = raw->graphics_id[1]; @@ -876,10 +922,12 @@ static struct sti_struct *sti_try_rom_generic(unsigned long address, spin_lock_init(&sti->lock); test_rom: - /* if we can't read the ROM, bail out early. Not being able - * to read the hpa is okay, for romless sti */ - if (pdc_add_valid(address)) + /* pdc_add_valid() works only on 32-bit kernels */ + if ((!IS_ENABLED(CONFIG_64BIT) || + (boot_cpu_data.pdc.capabilities & PDC_MODEL_OS32)) && + pdc_add_valid(address)) { goto out_err; + } sig = gsc_readl(address); @@ -949,7 +997,7 @@ test_rom: goto out_err; sti_inq_conf(sti); - sti_dump_globcfg(sti->glob_cfg, sti->sti_mem_request); + sti_dump_globcfg(sti); sti_dump_outptr(sti); pr_info(" graphics card name: %s\n", @@ -1135,14 +1183,15 @@ int sti_call(const struct sti_struct *sti, unsigned long func, unsigned long _glob_cfg = STI_PTR(glob_cfg); int ret; -#ifdef CONFIG_64BIT /* Check for overflow when using 32bit STI on 64bit kernel. */ - if (WARN_ONCE(_flags>>32 || _inptr>>32 || _outptr>>32 || _glob_cfg>>32, + if (WARN_ONCE(IS_ENABLED(CONFIG_64BIT) && !sti->do_call64 && + (upper_32_bits(_flags) || upper_32_bits(_inptr) || + upper_32_bits(_outptr) || upper_32_bits(_glob_cfg)), "Out of 32bit-range pointers!")) return -1; -#endif - ret = pdc_sti_call(func, _flags, _inptr, _outptr, _glob_cfg); + ret = pdc_sti_call(func, _flags, _inptr, _outptr, _glob_cfg, + sti->do_call64); return ret; } |