/** ****************************************************************************** * * @file rwnx_v7.c - Support for v7 platform * * Copyright (C) RivieraWaves 2012-2019 * ****************************************************************************** */ #include "rwnx_v7.h" #include "rwnx_defs.h" #include "rwnx_irqs.h" #include "reg_access.h" #include "hal_desc.h" struct rwnx_v7 { u8 *pci_bar0_vaddr; u8 *pci_bar1_vaddr; }; static int rwnx_v7_platform_enable(struct rwnx_hw *rwnx_hw) { int ret; /* sched_setscheduler on ONESHOT threaded irq handler for BCNs ? */ ret = request_irq(rwnx_hw->plat->pci_dev->irq, rwnx_irq_hdlr, 0, "rwnx", rwnx_hw); return ret; } static int rwnx_v7_platform_disable(struct rwnx_hw *rwnx_hw) { free_irq(rwnx_hw->plat->pci_dev->irq, rwnx_hw); return 0; } static void rwnx_v7_platform_deinit(struct rwnx_plat *rwnx_plat) { #ifdef CONFIG_PCI struct rwnx_v7 *rwnx_v7 = (struct rwnx_v7 *)rwnx_plat->priv; pci_disable_device(rwnx_plat->pci_dev); iounmap(rwnx_v7->pci_bar0_vaddr); iounmap(rwnx_v7->pci_bar1_vaddr); pci_release_regions(rwnx_plat->pci_dev); pci_clear_master(rwnx_plat->pci_dev); pci_disable_msi(rwnx_plat->pci_dev); #endif kfree(rwnx_plat); } static u8 *rwnx_v7_get_address(struct rwnx_plat *rwnx_plat, int addr_name, unsigned int offset) { struct rwnx_v7 *rwnx_v7 = (struct rwnx_v7 *)rwnx_plat->priv; if (WARN(addr_name >= RWNX_ADDR_MAX, "Invalid address %d", addr_name)) return NULL; if (addr_name == RWNX_ADDR_CPU) return rwnx_v7->pci_bar0_vaddr + offset; else return rwnx_v7->pci_bar1_vaddr + offset; } static void rwnx_v7_ack_irq(struct rwnx_plat *rwnx_plat) { } static const u32 rwnx_v7_config_reg[] = { NXMAC_DEBUG_PORT_SEL_ADDR, SYSCTRL_DIAG_CONF_ADDR, SYSCTRL_PHYDIAG_CONF_ADDR, SYSCTRL_RIUDIAG_CONF_ADDR, RF_V7_DIAGPORT_CONF1_ADDR, }; static const u32 rwnx_v7_he_config_reg[] = { SYSCTRL_DIAG_CONF0, SYSCTRL_DIAG_CONF1, SYSCTRL_DIAG_CONF2, SYSCTRL_DIAG_CONF3, }; static int rwnx_v7_get_config_reg(struct rwnx_plat *rwnx_plat, const u32 **list) { u32 fpga_sign; if (!list) return 0; fpga_sign = RWNX_REG_READ(rwnx_plat, RWNX_ADDR_SYSTEM, SYSCTRL_SIGNATURE_ADDR); if (__FPGA_TYPE(fpga_sign) == 0xc0ca) { *list = rwnx_v7_he_config_reg; return ARRAY_SIZE(rwnx_v7_he_config_reg); } else { *list = rwnx_v7_config_reg; return ARRAY_SIZE(rwnx_v7_config_reg); } } /** * rwnx_v7_platform_init - Initialize the DINI platform * * @pci_dev PCI device * @rwnx_plat Pointer on struct rwnx_stat * to be populated * * @return 0 on success, < 0 otherwise * * Allocate and initialize a rwnx_plat structure for the dini platform. */ int rwnx_v7_platform_init(struct pci_dev *pci_dev, struct rwnx_plat **rwnx_plat) { struct rwnx_v7 *rwnx_v7; u16 pci_cmd; int ret = 0; *rwnx_plat = kzalloc(sizeof(struct rwnx_plat) + sizeof(struct rwnx_v7), GFP_KERNEL); if (!*rwnx_plat) return -ENOMEM; rwnx_v7 = (struct rwnx_v7 *)(*rwnx_plat)->priv; /* Hotplug fixups */ pci_read_config_word(pci_dev, PCI_COMMAND, &pci_cmd); pci_cmd |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR; pci_write_config_word(pci_dev, PCI_COMMAND, pci_cmd); pci_write_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES >> 2); ret = pci_enable_device(pci_dev); if (ret) { dev_err(&(pci_dev->dev), "pci_enable_device failed\n"); goto out_enable; } pci_set_master(pci_dev); ret = pci_request_regions(pci_dev, KBUILD_MODNAME); if (ret) { dev_err(&(pci_dev->dev), "pci_request_regions failed\n"); goto out_request; } #ifdef CONFIG_PCI if (pci_enable_msi(pci_dev)) { dev_err(&(pci_dev->dev), "pci_enable_msi failed\n"); goto out_msi; } #endif rwnx_v7->pci_bar0_vaddr = (u8 *)pci_ioremap_bar(pci_dev, 0); if (!rwnx_v7->pci_bar0_vaddr) { dev_err(&(pci_dev->dev), "pci_ioremap_bar(%d) failed\n", 0); ret = -ENOMEM; goto out_bar0; } rwnx_v7->pci_bar1_vaddr = (u8 *)pci_ioremap_bar(pci_dev, 1); if (!rwnx_v7->pci_bar1_vaddr) { dev_err(&(pci_dev->dev), "pci_ioremap_bar(%d) failed\n", 1); ret = -ENOMEM; goto out_bar1; } (*rwnx_plat)->enable = rwnx_v7_platform_enable; (*rwnx_plat)->disable = rwnx_v7_platform_disable; (*rwnx_plat)->deinit = rwnx_v7_platform_deinit; (*rwnx_plat)->get_address = rwnx_v7_get_address; (*rwnx_plat)->ack_irq = rwnx_v7_ack_irq; (*rwnx_plat)->get_config_reg = rwnx_v7_get_config_reg; return 0; out_bar1: iounmap(rwnx_v7->pci_bar0_vaddr); out_bar0: #ifdef CONFIG_PCI pci_disable_msi(pci_dev); out_msi: #endif pci_release_regions(pci_dev); out_request: #ifdef CONFIG_PCI pci_clear_master(pci_dev); #endif pci_disable_device(pci_dev); out_enable: kfree(*rwnx_plat); return ret; }