Search Linux Wireless

[RFC v1 023/256] cl8k: add bus/pci/pci.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Viktor Barna <viktor.barna@xxxxxxxxxx>

(Part of the split. Please, take a look at the cover letter for more
details).

Signed-off-by: Viktor Barna <viktor.barna@xxxxxxxxxx>
---
 .../net/wireless/celeno/cl8k/bus/pci/pci.c    | 210 ++++++++++++++++++
 1 file changed, 210 insertions(+)
 create mode 100644 drivers/net/wireless/celeno/cl8k/bus/pci/pci.c

diff --git a/drivers/net/wireless/celeno/cl8k/bus/pci/pci.c b/drivers/net/wireless/celeno/cl8k/bus/pci/pci.c
new file mode 100644
index 000000000000..a9c2eebaeb1f
--- /dev/null
+++ b/drivers/net/wireless/celeno/cl8k/bus/pci/pci.c
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: MIT
+/* Copyright(c) 2019-2021, Celeno Communications Ltd. */
+
+#include "chip.h"
+#include "hw.h"
+#include "bus/pci/msg_pci.h"
+#include "bus/pci/tx_pci.h"
+#include "bus/pci/rx_pci.h"
+#include "reg/reg_macsys_gcu.h"
+#include "main.h"
+#include "ela.h"
+#include "debug.h"
+
+struct cl_pci_db {
+       u8 device_cntr;
+       struct pci_dev *dev[CHIP_MAX];
+};
+
+static struct cl_pci_db pci_db;
+
+void cl_pci_get_celeno_device(void)
+{
+       /*
+        * Search the PCI for all Celeno devices.
+        * If there are two devices sort them in ascending order.
+        */
+       struct pci_dev *dev = NULL;
+
+       while ((dev = pci_get_device(CL_VENDOR_ID, PCI_ANY_ID, dev))) {
+               pci_db.dev[pci_db.device_cntr] = dev;
+               pci_db.device_cntr++;
+
+               if (pci_db.device_cntr == CHIP_MAX) {
+                       if (pci_db.dev[CHIP0]->device > pci_db.dev[CHIP1]->device)
+                               swap(pci_db.dev[CHIP0], pci_db.dev[CHIP1]);
+
+                       break;
+               }
+       }
+}
+
+static u8 cl_pci_chip_idx(struct pci_dev *pci_dev)
+{
+       if (pci_db.device_cntr == 0)
+               cl_pci_get_celeno_device();
+
+       if (pci_db.device_cntr == 1)
+               return CHIP0;
+
+       return (pci_db.dev[CHIP0] == pci_dev) ? CHIP0 : CHIP1;
+}
+
+static const struct cl_driver_ops drv_ops = {
+       .msg_fw_send = cl_msg_pci_msg_fw_send,
+       .pkt_fw_send = cl_tx_pci_pkt_fw_send,
+};
+
+static int cl_pci_probe(struct pci_dev *pci_dev,
+                       const struct pci_device_id *pci_id)
+{
+       u16 pci_cmd;
+       int ret;
+       u8 chip_idx = cl_pci_chip_idx(pci_dev);
+       u8 step_id;
+       struct cl_chip *chip = cl_chip_alloc(chip_idx);
+
+       if (!chip) {
+               pr_err("Chip [%u] alloc failed\n", chip_idx);
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       ret = cl_chip_config_read(chip);
+       if (ret) {
+               cl_chip_dealloc(chip);
+               return 0;
+       }
+
+       chip->pci_dev = pci_dev;
+       chip->dev = &pci_dev->dev;
+       chip->bus_type = CL_BUS_TYPE_PCI;
+
+       pci_set_drvdata(pci_dev, chip);
+
+       /* 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) {
+               cl_dbg_chip_err(chip, "pci_enable_device failed\n");
+               goto out;
+       }
+
+       if (!dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(32))) {
+               cl_dbg_chip_verbose(chip, "Using 32bit DMA\n");
+       } else {
+               cl_dbg_chip_verbose(chip, "No suitable DMA available\n");
+               goto out_disable_device;
+       }
+
+       pci_set_master(pci_dev);
+
+       ret = pci_request_regions(pci_dev, chip->pci_drv.name);
+       if (ret) {
+               cl_dbg_chip_verbose(chip, "pci_request_regions failed\n");
+               goto out_disable_device;
+       }
+
+       chip->pci_bar0_virt_addr = pci_ioremap_bar(pci_dev, 0);
+       if (!chip->pci_bar0_virt_addr) {
+               cl_dbg_chip_verbose(chip, "pci_ioremap_bar 0 failed\n");
+               ret = -ENOMEM;
+               goto out_release_regions;
+       }
+
+#ifdef CONFIG_PCI_MSI
+       if (chip->conf->ci_pci_msi_enable) {
+               ret = pci_enable_msi(pci_dev);
+               if (ret)
+                       cl_dbg_chip_err(chip, "pci_enable_msi failed (%d)\n", ret);
+       }
+#endif
+
+       step_id = macsys_gcu_chip_version_step_id_getf(chip);
+       if (step_id != 0xB) {
+               cl_dbg_chip_err(chip, "Invalid Step ID: 0x%X\n", step_id);
+               ret = -EOPNOTSUPP;
+               goto out_release_regions;
+       }
+
+       ret = cl_chip_init(chip);
+       if (ret)
+               goto out_chip_deinit;
+
+       ret = cl_main_init(chip, &drv_ops);
+       if (ret)
+               goto out_chip_deinit;
+
+       if (cl_ela_init(chip))
+               cl_dbg_chip_err(chip, "Non-critical: cl_ela_init failed\n");
+
+       return 0;
+
+out_chip_deinit:
+       cl_chip_deinit(chip);
+#ifdef CONFIG_PCI_MSI
+       if (chip->conf->ci_pci_msi_enable)
+               pci_disable_msi(pci_dev);
+#endif
+       iounmap(chip->pci_bar0_virt_addr);
+out_release_regions:
+       pci_release_regions(pci_dev);
+out_disable_device:
+       pci_disable_device(pci_dev);
+out:
+
+       return ret;
+}
+
+static void cl_pci_remove(struct pci_dev *pci_dev)
+{
+       struct cl_chip *chip = pci_get_drvdata(pci_dev);
+
+       if (!chip) {
+               pr_err("%s: failed to find chip\n", __func__);
+               return;
+       }
+
+       cl_ela_deinit(chip);
+
+       cl_main_deinit(chip);
+
+       cl_chip_deinit(chip);
+
+#ifdef CONFIG_PCI_MSI
+       if (chip->conf->ci_pci_msi_enable) {
+               pci_disable_msi(pci_dev);
+               pr_debug("pci_disable_msi\n");
+       }
+#endif
+
+       iounmap(chip->pci_bar0_virt_addr);
+       cl_chip_dealloc(chip);
+       pci_release_regions(pci_dev);
+       pci_disable_device(pci_dev);
+}
+
+static const struct pci_device_id cl_pci_id_table[] = {
+       { PCI_DEVICE(CL_VENDOR_ID, 0x8000) },
+       { PCI_DEVICE(CL_VENDOR_ID, 0x8001) },
+       { PCI_DEVICE(CL_VENDOR_ID, 0x8040) },
+       { PCI_DEVICE(CL_VENDOR_ID, 0x8060) },
+       { PCI_DEVICE(CL_VENDOR_ID, 0x8080) },
+       { PCI_DEVICE(CL_VENDOR_ID, 0x8046) },
+       { PCI_DEVICE(CL_VENDOR_ID, 0x8066) },
+       { PCI_DEVICE(CL_VENDOR_ID, 0x8086) },
+       { },
+};
+
+static struct pci_driver cl_pci_driver = {
+       .name = "cl_pci",
+       .id_table = cl_pci_id_table,
+       .probe = cl_pci_probe,
+       .remove = cl_pci_remove,
+};
+
+module_pci_driver(cl_pci_driver);
--
2.30.0

________________________________
The information transmitted is intended only for the person or entity to which it is addressed and may contain confidential and/or privileged material. Any retransmission, dissemination, copying or other use of, or taking of any action in reliance upon this information is prohibited. If you received this in error, please contact the sender and delete the material from any computer. Nothing contained herein shall be deemed as a representation, warranty or a commitment by Celeno. No warranties are expressed or implied, including, but not limited to, any implied warranties of non-infringement, merchantability and fitness for a particular purpose.
________________________________





[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux