diff mbox series

[RFC,v1,042/256] cl8k: add chip.c

Message ID 20210617160223.160998-43-viktor.barna@celeno.com
State New
Headers show
Series wireless: cl8k driver for Celeno IEEE 802.11ax devices | expand

Commit Message

Viktor Barna June 17, 2021, 3:58 p.m. UTC
From: Viktor Barna <viktor.barna@celeno.com>

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

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

--
2.30.0
diff mbox series

Patch

diff --git a/drivers/net/wireless/celeno/cl8k/chip.c b/drivers/net/wireless/celeno/cl8k/chip.c
new file mode 100644
index 000000000000..5876b1da1857
--- /dev/null
+++ b/drivers/net/wireless/celeno/cl8k/chip.c
@@ -0,0 +1,241 @@ 
+// SPDX-License-Identifier: MIT
+/* Copyright(c) 2019-2021, Celeno Communications Ltd. */
+
+#include <linux/dmapool.h>
+#include "chip.h"
+#include "chip_config.h"
+#include "utils/utils.h"
+#include "reg/reg_access.h"
+#include "reg/reg_ipc.h"
+#include "temperature.h"
+#include "fem.h"
+#include "e2p.h"
+#include "ela.h"
+#include "utils/string.h"
+#include "main.h"
+#include "netlink.h"
+#include "data_rates.h"
+#ifdef CONFIG_CL_PCIE
+#include "bus/pci/irq.h"
+#endif
+
+#define CL_ALIGN_BOUND_64KB BIT(16)
+
+static void cl_chip_set_max_antennas(struct cl_chip *chip)
+{
+       switch (chip->pci_dev->device) {
+       case 0x8040:
+       case 0x8046:
+               chip->max_antennas = MAX_ANTENNAS_CL804X;
+               break;
+       case 0x8060:
+       case 0x8066:
+               chip->max_antennas = MAX_ANTENNAS_CL806X;
+               break;
+       case 0x8080:
+       case 0x8086:
+       default:
+               chip->max_antennas = MAX_ANTENNAS_CL808X;
+               break;
+       }
+
+       cl_dbg_chip_trace(chip, "max_antennas = %u\n", chip->max_antennas);
+}
+
+static int cl_chip_print_serial_number(struct cl_chip *chip)
+{
+       u8 serial_number[SIZE_GEN_SERIAL_NUMBER + 1] = {0};
+
+       if (cl_e2p_read(chip, (u8 *)&serial_number, SIZE_GEN_SERIAL_NUMBER, ADDR_GEN_SERIAL_NUMBER))
+               return -1;
+
+       if (strlen(serial_number) == 0)
+               CL_DBG_WARNING_CHIP(chip, "Serial-number in not set in EEPROM\n");
+       else
+               cl_dbg_chip_verbose(chip, "Serial-number = %s\n", serial_number);
+
+       return 0;
+}
+
+static int cl_chip_ring_indices_init(struct cl_chip *chip)
+{
+       struct cl_ring_indices *ring_indices = &chip->ring_indices;
+
+       ring_indices->pool = dma_pool_create("cl_ring_indices_pool", chip->dev,
+                                            (sizeof(struct cl_ipc_ring_indices) * TCV_MAX),
+                                            CL_ALIGN_BOUND_64KB, CL_ALIGN_BOUND_64KB);
+
+       if (!ring_indices->pool) {
+               cl_dbg_chip_err(chip, "ring_indices pool create failed !!!\n");
+               return -ENOMEM;
+       }
+
+       ring_indices->params = dma_pool_alloc(ring_indices->pool, GFP_KERNEL,
+                                             &ring_indices->dma_addr);
+       if (!ring_indices->params)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static void cl_chip_ring_indices_deinit(struct cl_chip *chip)
+{
+       if (chip->ring_indices.params) {
+               dma_pool_free(chip->ring_indices.pool,
+                             chip->ring_indices.params,
+                             chip->ring_indices.dma_addr);
+               chip->ring_indices.params = NULL;
+       }
+
+       dma_pool_destroy(chip->ring_indices.pool);
+       chip->ring_indices.pool = NULL;
+}
+
+struct cl_chip *cl_chip_alloc(u8 idx)
+{
+       struct cl_chip *chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+
+       if (!chip)
+               return NULL;
+
+       chip->idx = idx;
+       return chip;
+}
+
+void cl_chip_dealloc(struct cl_chip *chip)
+{
+       cl_chip_config_dealloc(chip);
+       kfree(chip);
+}
+
+int cl_chip_init(struct cl_chip *chip)
+{
+       int ret = 0;
+
+       chip->agc_table_entry = U8_MAX;
+
+       spin_lock_init(&chip->isr_lock);
+       spin_lock_init(&chip->spi_lock);
+
+       rwlock_init(&chip->cl_hw_lock);
+
+       cl_chip_set_max_antennas(chip);
+
+#ifdef CONFIG_CL_PCIE
+       ret = cl_irq_request(chip);
+       if (ret)
+               return ret;
+#endif
+       ipc_host_global_int_en_set(chip, 1);
+
+       cl_temperature_init(chip);
+
+       ret = cl_e2p_init(chip);
+       if (ret) {
+               cl_dbg_chip_err(chip, "cl_e2p_init failed %d\n", ret);
+               return ret;
+       }
+
+       ret = cl_fem_init(chip);
+       if (ret)
+               return ret;
+
+       ret = cl_chip_ring_indices_init(chip);
+       if (ret)
+               return ret;
+
+       cl_chip_print_serial_number(chip);
+
+       cl_wrs_tables_global_build();
+       cl_data_rates_inverse_build();
+
+       return ret;
+}
+
+void cl_chip_deinit(struct cl_chip *chip)
+{
+       cl_chip_ring_indices_deinit(chip);
+       cl_temperature_close(chip);
+       cl_e2p_close(chip);
+       ipc_host_global_int_en_set(chip, 0);
+
+#ifdef CONFIG_CL_PCIE
+       cl_irq_free(chip);
+#endif
+}
+
+bool cl_chip_is_enabled(struct cl_chip *chip)
+{
+       return cl_chip_is_tcv0_enabled(chip) || cl_chip_is_tcv1_enabled(chip);
+}
+
+bool cl_chip_is_both_enabled(struct cl_chip *chip)
+{
+       return cl_chip_is_tcv0_enabled(chip) && cl_chip_is_tcv1_enabled(chip);
+}
+
+bool cl_chip_is_tcv_enabled(struct cl_chip *chip, u8 tcv_idx)
+{
+       return chip->conf->ce_tcv_enabled[tcv_idx];
+}
+
+bool cl_chip_is_tcv0_enabled(struct cl_chip *chip)
+{
+       return chip->conf->ce_tcv_enabled[TCV0];
+}
+
+bool cl_chip_is_tcv1_enabled(struct cl_chip *chip)
+{
+       return chip->conf->ce_tcv_enabled[TCV1];
+}
+
+void cl_chip_set_hw(struct cl_chip *chip, struct cl_hw *cl_hw)
+{
+       if (cl_hw_is_tcv0(cl_hw))
+               chip->cl_hw_tcv0 = cl_hw;
+       else
+               chip->cl_hw_tcv1 = cl_hw;
+}
+
+void cl_chip_unset_hw(struct cl_chip *chip, struct cl_hw *cl_hw)
+{
+       if (cl_hw_is_tcv0(cl_hw))
+               chip->cl_hw_tcv0 = NULL;
+       else
+               chip->cl_hw_tcv1 = NULL;
+}
+
+bool cl_chip_is_8ant(struct cl_chip *chip)
+{
+       return chip->max_antennas == MAX_ANTENNAS_CL808X;
+}
+
+bool cl_chip_is_6ant(struct cl_chip *chip)
+{
+       return chip->max_antennas == MAX_ANTENNAS_CL806X;
+}
+
+bool cl_chip_is_4ant(struct cl_chip *chip)
+{
+       return chip->max_antennas == MAX_ANTENNAS_CL804X;
+}
+
+static u16 cl_chip_get_device_id(struct cl_chip *chip)
+{
+       u16 device_id = chip->pci_dev->device;
+
+       /* If device-id is default, set it accoridng to phy-dev. */
+       if (device_id == 0x8000 || device_id == 0x8001)
+               device_id = IS_PHY_ATHOS(chip) ? 0x8086 : 0x8080;
+
+       return device_id;
+}
+
+bool cl_chip_is_6g(struct cl_chip *chip)
+{
+       u16 device_id = cl_chip_get_device_id(chip);
+       u8 band = device_id & 0xf;
+
+       return (band == 6);
+}
+