All of lore.kernel.org
 help / color / mirror / Atom feed
From: viktor.barna@celeno.com
To: linux-wireless@vger.kernel.org
Cc: Kalle Valo <kvalo@codeaurora.org>,
	"David S . Miller" <davem@davemloft.net>,
	Jakub Kicinski <kuba@kernel.org>,
	Aviad Brikman <aviad.brikman@celeno.com>,
	Eliav Farber <eliav.farber@gmail.com>,
	Maksym Kokhan <maksym.kokhan@celeno.com>,
	Oleksandr Savchenko <oleksandr.savchenko@celeno.com>,
	Shay Bar <shay.bar@celeno.com>,
	Viktor Barna <viktor.barna@celeno.com>
Subject: [RFC v2 24/96] cl8k: add e2p.c
Date: Tue, 24 May 2022 14:33:50 +0300	[thread overview]
Message-ID: <20220524113502.1094459-25-viktor.barna@celeno.com> (raw)
In-Reply-To: <20220524113502.1094459-1-viktor.barna@celeno.com>

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/e2p.c | 771 +++++++++++++++++++++++++
 1 file changed, 771 insertions(+)
 create mode 100644 drivers/net/wireless/celeno/cl8k/e2p.c

diff --git a/drivers/net/wireless/celeno/cl8k/e2p.c b/drivers/net/wireless/celeno/cl8k/e2p.c
new file mode 100644
index 000000000000..14e9a4498046
--- /dev/null
+++ b/drivers/net/wireless/celeno/cl8k/e2p.c
@@ -0,0 +1,771 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/* Copyright(c) 2019-2022, Celeno Communications Ltd. */
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+
+#include "chip.h"
+#include "reg/reg_access.h"
+#include "reg/reg_defs.h"
+#include "config.h"
+#include "utils.h"
+#include "e2p.h"
+#include "calib.h"
+#include "debug.h"
+
+#define EEPROM_VERSION 3
+
+#ifdef CONFIG_CL8K_EEPROM_STM24256
+/* EEPROM Parameters - Suitable for ST-M24256 */
+#define E2P_SIZE       0x8000              /* 32KB = 256Kbit */
+#define E2P_PAGE_SIZE  0x40                /* 64 Bytes */
+#define E2P_PAGE_MASK  (E2P_PAGE_SIZE - 1) /* 0x3F */
+#define E2P_PAGE_SHIFT 0x6
+#else
+/* EEPROM Parameters - Suitable for ATMEL AT24C16BN */
+#define E2P_SIZE       0x800               /* 2KB = 16Kbit */
+#define E2P_PAGE_SIZE  0x10                /* 16 Bytes */
+#define E2P_PAGE_MASK  (E2P_PAGE_SIZE - 1) /* 0xF */
+#define E2P_PAGE_SHIFT 0x4
+#endif
+
+#define PAGE_NUM(addr) ((addr) >> E2P_PAGE_SHIFT)
+#define PAGE_OFF(addr) ((addr) & E2P_PAGE_MASK)
+
+#define CH_LIST_SIZE_CL80X0         59
+#define CH_LIST_SIZE_CL80X6         105
+
+static const u8 chan_list_cl80x0[CH_LIST_SIZE_CL80X0] = {
+	36, 38, 40, 42, 44, 46, 48, 50,
+	52, 54, 56, 58, 60, 62, 64, 100,
+	102, 104, 106, 108, 110, 112, 114, 116,
+	118, 120, 122, 124, 126, 128, 132, 134,
+	136, 138, 140, 142, 144, 149, 151, 153,
+	155, 157, 159, 161, 165, 1, 2, 3,
+	4, 5, 6, 7, 8, 9, 10, 11,
+	12, 13, 14
+};
+
+static const u16 chan_list_cl80x6[CH_LIST_SIZE_CL80X6] = {
+	1, 2, 5, 9, 13, 17, 21, 25,
+	29, 33, 37, 41, 45, 49, 53, 57,
+	61, 65, 69, 73, 77, 81, 85, 89,
+	93, 97, 101, 105, 109, 113, 117, 121,
+	125, 129, 133, 137, 141, 145, 149, 153,
+	157, 161, 165, 169, 173, 177, 181, 185,
+	189, 193, 197, 201, 205, 209, 213, 217,
+	221, 225, 229, 233, 36, 38, 40, 42,
+	44, 46, 48, 50, 52, 54, 56, 58,
+	60, 62, 64, 100, 102, 104, 106, 108,
+	110, 112, 114, 116, 118, 120, 122, 124,
+	126, 128, 132, 134, 136, 138, 140, 142,
+	144, 149, 151, 153, 155, 157, 159, 161,
+	165
+};
+
+enum bit_num {
+	BIT0,
+	BIT1,
+	BIT2,
+	BIT3,
+	BIT4,
+	BIT5,
+	BIT6,
+	BIT7,
+};
+
+struct cl_e2p_work {
+	struct work_struct ws;
+	struct cl_chip *chip;
+};
+
+/*
+ * MACSYS_I2C:: PRERLO (0x0) - Clock Prescale register lo-byte
+ * Width: 8, Access: RW, Reset: 0xff.
+ */
+#define I2C_PRERLO (I2C_REG_BASE_ADDR + 0x0)
+
+/*
+ * MACSYS_I2C:: PRERHI (0x4) - Clock Prescale register lo-byte
+ * Width: 8, Access: RW, Reset: 0xff.
+ */
+#define I2C_PRERHI (I2C_REG_BASE_ADDR + 0x4)
+
+/*
+ * MACSYS_I2C:: CTR (0x8) - Control Register
+ * Width: 8, Access: RW, Reset: 0x00.
+ */
+#define I2C_CTR (I2C_REG_BASE_ADDR + 0x8)
+
+#define EN (BIT7) /* ‘1’ the core is enabled. */
+
+/*
+ * MACSYS_I2C:: TXR_RXR (0xC) - Transmit Register - Data
+ * Width: 8, Access: W, Reset: 0x00.
+ */
+#define I2C_TXD (I2C_REG_BASE_ADDR + 0xC)
+
+/* 7:0 TXD */
+#define TXD (BIT0) /* Next byte to transmit via I2C */
+
+#define TXD_MASK (0xFF << TXD)
+
+/*
+ * MACSYS_I2C:: TXR_RXR (0xC) - Transmit Register - Address
+ * Width: 8, Access: W, Reset: 0x00.
+ */
+#define I2C_TXADDR (I2C_REG_BASE_ADDR + 0xC)
+
+/*
+ * 7:1 TXADDR
+ * 0 RDWR
+ */
+#define TXADDR (BIT1) /* I2C Slave Address */
+#define RDWR   (BIT0) /* ‘1’ = reading from slave. ‘0’ = writing to slave. */
+
+#define TXADDR_MASK (0x7F << TXADDR)
+
+/*
+ * MACSYS_I2C:: TXR_RXR (0xC) - Receive Register
+ * Width: 8, Access: R, Reset: 0x00.
+ */
+#define I2C_RXD (I2C_REG_BASE_ADDR + 0xC)
+
+/* 7:0 RXD */
+#define RXD (BIT0) /* Last byte received via I2C. */
+#define RXD_MASK (0xFF << RXD)
+
+/*
+ * MACSYS_I2C:: CR_SR (0x10) - Command Register
+ * Width: 8, Access: WC, Reset: 0x00.
+ */
+#define I2C_CR (I2C_REG_BASE_ADDR + 0x10)
+
+/*
+ * 7 STA
+ * 6 STO
+ * 5 RD
+ * 4 WR
+ * 3 ACK
+ * 2:1 RES
+ * 0 IACK
+ */
+#define STA  (BIT7) /* Generate (repeated) start condition. */
+#define STO  (BIT6) /* Generate stop condition. */
+#define RD   (BIT5) /* Read from slave. */
+#define WR   (BIT4) /* Write to slave. */
+#define ACK  (BIT3) /* When a receiver, sent ACK (ACK = ‘0’) or NACK (NACK = ‘1’). */
+#define IACK (BIT0) /* Interrupt acknowledge, When set, clears a pending interrupt. */
+
+/*
+ * MACSYS_I2C:: CR_SR (0x10) - Status Register
+ * Width: 8, Access: R, Reset: 0x00.
+ */
+#define I2C_SR (I2C_REG_BASE_ADDR + 0x10)
+
+/*
+ * 7 RX_ACK - Received acknowledge from slave - ‘1’ = No acknowledge received.
+ * 6 BUSY - I2C bus busy - ‘1’ after START signal detected. ‘0’ after STOP signal detected.
+ * 5 AL - Arbitration lost - This bit is set when the core lost arbitration.
+ * 4:2 RES
+ * 1 TIP - Transfer in progress. ‘1’ when transferring data. ‘0’ when transfer complete.
+ * 0 IF - Set when interrupt is pending, cause a processor interrupt if the IEN bit is set.
+ */
+#define RX_ACK (BIT7)
+#define BUSY   (BIT6)
+#define AL     (BIT5)
+#define TIP    (BIT1)
+#define IF     (BIT0)
+
+#ifdef CONFIG_CL8K_EEPROM_STM24256
+#define I2C_EEPROM_ADDR(page) (0xA0 | (((page) >> 8) & 0xE)) /* [1-0-1-0-P2-P1-P0-0] */
+#else
+#define I2C_EEPROM_ADDR(page) (0xA0 | (((page) >> 3) & 0xE)) /* [1-0-1-0-P2-P1-P0-0] */
+#endif
+
+/* E2P_MAX_POLLS should not exceed 12 iterations (attemts) */
+#define E2P_MAX_POLLS 500
+#define E2P_INITIAL_DELAY 32
+
+static int i2c_poll_xfer_acked(struct cl_chip *chip)
+{
+	u32 val = cl_reg_read_chip(chip, I2C_SR);
+	int cnt = E2P_MAX_POLLS;
+	unsigned long delay = E2P_INITIAL_DELAY;
+
+	while ((val & BIT(TIP)) && cnt--) {
+		udelay(delay);
+		val = cl_reg_read_chip(chip, I2C_SR);
+		delay <<= 1;
+	}
+	++cnt;
+
+	while ((val & BIT(RX_ACK)) && cnt--) {
+		udelay(delay);
+		val = cl_reg_read_chip(chip, I2C_SR);
+		delay <<= 1;
+	}
+
+	if (cnt >= 0)
+		return 0;
+
+	cl_dbg_chip_err(chip, "ACK FAILED\n");
+	cl_dbg_chip_trace(chip, "I2C_POLL_XFER_ACKED: val=%Xh, cnt=%d.\n", val, cnt);
+
+	return -EBADE;
+}
+
+static int i2c_poll_xfer_no_acked(struct cl_chip *chip)
+{
+	u32 val = cl_reg_read_chip(chip, I2C_SR);
+	int cnt = E2P_MAX_POLLS;
+	unsigned long delay = E2P_INITIAL_DELAY;
+
+	while ((val & BIT(TIP)) && cnt--) {
+		udelay(delay);
+		val = cl_reg_read_chip(chip, I2C_SR);
+		delay <<= 1;
+	}
+
+	++cnt;
+
+	while (!(val & BIT(RX_ACK)) && cnt--) {
+		udelay(delay);
+		val = cl_reg_read_chip(chip, I2C_SR);
+		delay <<= 1;
+	}
+
+	if (cnt >= 0)
+		return 0;
+
+	cl_dbg_chip_err(chip, "NO ACK FAILED\n");
+	cl_dbg_chip_trace(chip, "I2C_POLL_XFER_NO_ACKED: val=%Xh, cnt=%d.\n", val, cnt);
+
+	return -EBADE;
+}
+
+static void i2c_write_start(struct cl_chip *chip, u16 page)
+{
+	u32 addr = I2C_EEPROM_ADDR(page) & TXADDR_MASK;
+
+	cl_reg_write_chip(chip, I2C_TXADDR, addr);
+	cl_reg_write_chip(chip, I2C_CR, BIT(STA) | BIT(WR));
+}
+
+static void i2c_write(struct cl_chip *chip, u8 data)
+{
+	cl_reg_write_chip(chip, I2C_TXD, data & TXD_MASK);
+	cl_reg_write_chip(chip, I2C_CR, BIT(WR));
+}
+
+static void i2c_write_stop(struct cl_chip *chip, u8 data)
+{
+	cl_reg_write_chip(chip, I2C_TXD, data & TXD_MASK);
+	cl_reg_write_chip(chip, I2C_CR, BIT(STO) | BIT(WR));
+}
+
+static void i2c_read_start(struct cl_chip *chip, u16 page)
+{
+	u32 addr = (I2C_EEPROM_ADDR(page) & TXADDR_MASK) | BIT(RDWR);
+
+	cl_reg_write_chip(chip, I2C_TXADDR, addr);
+	cl_reg_write_chip(chip, I2C_CR, BIT(STA) | BIT(WR));
+}
+
+static int i2c_read_stop(struct cl_chip *chip, u8 *data)
+{
+	int ret = 0;
+
+	cl_reg_write_chip(chip, I2C_CR, BIT(STO) | BIT(RD) | BIT(ACK));
+	ret = i2c_poll_xfer_no_acked(chip);
+	if (ret < 0)
+		return ret;
+	*data = cl_reg_read_chip(chip, I2C_RXD) & RXD_MASK;
+	return 0;
+}
+
+static void e2p_reg_set_bit(struct cl_chip *chip, u32 reg, u32 bit)
+{
+	u32 regval = cl_reg_read_chip(chip, reg);
+
+	regval |= bit;
+	cl_reg_write_chip(chip, reg, regval);
+}
+
+static void e2p_reg_clear_bit(struct cl_chip *chip, u32 reg, u32 bit)
+{
+	u32 regval = cl_reg_read_chip(chip, reg);
+
+	regval &= ~bit;
+	cl_reg_write_chip(chip, reg, regval);
+}
+
+/*
+ * helpers for cl_e2p_write_addr_bytes()
+ */
+static inline u16 cl_e2p_addrbyte_lo(u16 v)
+{
+	return v & 0xff;
+}
+
+static inline u16 cl_e2p_addrbyte_hi(u16 v)
+{
+	return (v >> 8) & 0xff;
+}
+
+/*
+ * Helper writing address byte(s) to the eeprom, some eeprom need two
+ * byte address cycles, some need only one.
+ */
+static int cl_e2p_write_addr_bytes(struct cl_chip *chip, u16 addr)
+{
+#ifdef CONFIG_CL8K_EEPROM_STM24256
+	int ret = 0;
+
+	/* Addr 8 msbits are 8 bits msb page */
+	i2c_write(chip, cl_e2p_addrbyte_hi(addr));
+
+	ret = i2c_poll_xfer_acked(chip);
+	if (ret)
+		return ret;
+#endif
+	/* Addr 8 lsbits are 4 bits page lsbits or`ed with 4 bits page offset */
+	i2c_write(chip, cl_e2p_addrbyte_lo(addr));
+
+	return i2c_poll_xfer_acked(chip);
+}
+
+static void e2p_enable(struct cl_chip *chip)
+{
+	/* Disable I2C Core */
+	e2p_reg_clear_bit(chip, I2C_CTR, BIT(EN));
+
+	/*
+	 * Set Pre-Scaler LO
+	 * pclk = 240MHz, desired SCL = 400KHz.
+	 * Prescale = [240e6 / (5*400e3) ] – 1 = 120 -1 = 119 = 77h
+	 */
+	cl_reg_write_chip(chip, I2C_PRERLO, 0x77);
+
+	/* Set Pre-Scaler HI */
+	cl_reg_write_chip(chip, I2C_PRERHI, 0x0);
+
+	/* Enable I2C Core */
+	e2p_reg_set_bit(chip, I2C_CTR, BIT(EN));
+}
+
+static int e2p_read_byte(struct cl_chip *chip, u16 addr, u8 *pbyte)
+{
+	int ret = 0;
+
+	if (addr > E2P_SIZE) {
+		cl_dbg_chip_err(chip, "Wrong addr or len\n");
+		return -EFAULT;
+	}
+
+	/* Clock in the address to read from. */
+	i2c_write_start(chip, PAGE_NUM(addr));
+	ret = i2c_poll_xfer_acked(chip);
+	if (ret)
+		return ret;
+
+	ret = cl_e2p_write_addr_bytes(chip, addr);
+	if (ret)
+		return ret;
+
+	/* Read single byte */
+	i2c_read_start(chip, PAGE_NUM(addr));
+	ret = i2c_poll_xfer_acked(chip);
+	if (ret)
+		return ret;
+
+	return i2c_read_stop(chip, pbyte);
+}
+
+static int e2p_write_page(struct cl_chip *chip, u16 addr, u8 *val, u16 num_of_bytes)
+{
+	/*
+	 * This is a write page (up to E2P_PAGE_SIZE bytes) operation indicating the offset
+	 * to write to.
+	 */
+	int i;
+	int ret = 0;
+
+	if (num_of_bytes > E2P_PAGE_SIZE)
+		return -EMSGSIZE;
+
+	/* Clock in the address to write to. */
+	i2c_write_start(chip, PAGE_NUM(addr));
+	ret = i2c_poll_xfer_acked(chip);
+	if (ret)
+		return ret;
+
+	ret = cl_e2p_write_addr_bytes(chip, addr);
+	if (ret)
+		return ret;
+
+	/* Clock in the data to write. */
+	for (i = 0; i < (num_of_bytes - 1); i++, val++) {
+		i2c_write(chip, *val);
+		ret = i2c_poll_xfer_acked(chip);
+		if (ret)
+			return ret;
+	}
+
+	/* Clock in the last data byte to write */
+	i2c_write_stop(chip, *val);
+	ret = i2c_poll_xfer_acked(chip);
+	if (ret)
+		return ret;
+
+	/* Wait for the write to finish */
+	mdelay(6);
+
+	return ret;
+}
+
+static int e2p_write_block(struct cl_chip *chip, u16 addr, u16 num_of_bytes, u8 *val)
+{
+	u16 bytes_on_curr_page = 0, bytes_left_to_write = num_of_bytes;
+	int ret = 0;
+
+	do {
+		bytes_on_curr_page = E2P_PAGE_SIZE - PAGE_OFF(addr);
+		bytes_on_curr_page = min(bytes_left_to_write, bytes_on_curr_page);
+		bytes_left_to_write -= bytes_on_curr_page;
+
+		ret = e2p_write_page(chip, addr, val, bytes_on_curr_page);
+		if (ret) {
+			cl_dbg_chip_err(chip,
+					"Error writing page %u offset %u, ret %d\n",
+					PAGE_NUM(addr), PAGE_OFF(addr), ret);
+			/* Written less bytes than num_of_bytes */
+			return 0;
+		}
+
+		addr += bytes_on_curr_page;
+		val += bytes_on_curr_page;
+	} while (bytes_left_to_write);
+
+	return num_of_bytes - bytes_left_to_write;
+}
+
+#ifdef CONFIG_CL8K_EEPROM_STM24256
+static void cl_e2p_init_calib_ch_bmp_per_bw(struct cl_hw *cl_hw, int data_elem_num,
+					    u16 channel_list[], int bw, int bmp_size,
+					    int bmp_addr, int eeprom_data_size, int data_addr)
+{
+	u8 chan_idx;
+	u8 chan_bmp[SIZE_CALIB_IQ_DCOC_20MHZ_BMP_TCV0] = {0};
+	u8 chan_bmp_prev[SIZE_CALIB_IQ_DCOC_20MHZ_BMP_TCV0] = {0};
+	struct eeprom_calib_data zero_calib = {0};
+	int i;
+
+	for (i = 0; i < data_elem_num; i++) {
+		chan_idx = cl_calib_dcoc_channel_bw_to_idx(cl_hw, channel_list[i], bw);
+		if (channel_list[i] && chan_idx != INVALID_CHAN_IDX)
+			chan_bmp[chan_idx / BITS_PER_BYTE] |= (BIT(chan_idx % BITS_PER_BYTE));
+	}
+
+	cl_e2p_read(cl_hw->chip, chan_bmp_prev, bmp_size, bmp_addr);
+	if (memcmp(chan_bmp, chan_bmp_prev, bmp_size))
+		for (i = 0; i < data_elem_num; i++)
+			cl_e2p_write(cl_hw->chip, (u8 *)&zero_calib,
+				     (u16)sizeof(struct eeprom_calib_data),
+				     data_addr + (i *
+				     (u16)sizeof(struct eeprom_calib_data)));
+
+	cl_e2p_write(cl_hw->chip, chan_bmp, bmp_size,
+		     bmp_addr);
+}
+
+static void cl_e2p_init_calib_ch_bmp(struct cl_hw *cl_hw)
+{
+	if (cl_hw->tcv_idx == 0) {
+		cl_e2p_init_calib_ch_bmp_per_bw(cl_hw, EEPROM_CALIB_DATA_ELEM_NUM_20MHZ_TCV0,
+						cl_hw->conf->ci_calib_eeprom_channels_20mhz,
+						CHNL_BW_20, SIZE_CALIB_IQ_DCOC_20MHZ_BMP_TCV0,
+						ADDR_CALIB_IQ_DCOC_CHANNEL_20MHZ_BMP_TCV0,
+						SIZE_CALIB_IQ_DCOC_DATA_20MHZ_TCV0,
+						ADDR_CALIB_IQ_DCOC_DATA_20MHZ_TCV0);
+
+		cl_e2p_init_calib_ch_bmp_per_bw(cl_hw, EEPROM_CALIB_DATA_ELEM_NUM_40MHZ_TCV0,
+						cl_hw->conf->ci_calib_eeprom_channels_40mhz,
+						CHNL_BW_40, SIZE_CALIB_IQ_DCOC_40MHZ_BMP_TCV0,
+						ADDR_CALIB_IQ_DCOC_CHANNEL_40MHZ_BMP_TCV0,
+						SIZE_CALIB_IQ_DCOC_DATA_40MHZ_TCV0,
+						ADDR_CALIB_IQ_DCOC_DATA_40MHZ_TCV0);
+
+		cl_e2p_init_calib_ch_bmp_per_bw(cl_hw, EEPROM_CALIB_DATA_ELEM_NUM_80MHZ_TCV0,
+						cl_hw->conf->ci_calib_eeprom_channels_80mhz,
+						CHNL_BW_80, SIZE_CALIB_IQ_DCOC_80MHZ_BMP_TCV0,
+						ADDR_CALIB_IQ_DCOC_CHANNEL_80MHZ_BMP_TCV0,
+						SIZE_CALIB_IQ_DCOC_DATA_80MHZ_TCV0,
+						ADDR_CALIB_IQ_DCOC_DATA_80MHZ_TCV0);
+
+		cl_e2p_init_calib_ch_bmp_per_bw(cl_hw, EEPROM_CALIB_DATA_ELEM_NUM_160MHZ_TCV0,
+						cl_hw->conf->ci_calib_eeprom_channels_160mhz,
+						CHNL_BW_160, SIZE_CALIB_IQ_DCOC_160MHZ_BMP_TCV0,
+						ADDR_CALIB_IQ_DCOC_CHANNEL_160MHZ_BMP_TCV0,
+						SIZE_CALIB_IQ_DCOC_DATA_160MHZ_TCV0,
+						ADDR_CALIB_IQ_DCOC_DATA_160MHZ_TCV0);
+	} else {
+		cl_e2p_init_calib_ch_bmp_per_bw(cl_hw, EEPROM_CALIB_DATA_ELEM_NUM_20MHZ_TCV1,
+						cl_hw->conf->ci_calib_eeprom_channels_20mhz,
+						CHNL_BW_20, SIZE_CALIB_IQ_DCOC_20MHZ_BMP_TCV1,
+						ADDR_CALIB_IQ_DCOC_CHANNEL_20MHZ_BMP_TCV1,
+						SIZE_CALIB_IQ_DCOC_DATA_20MHZ_TCV1,
+						ADDR_CALIB_IQ_DCOC_DATA_20MHZ_TCV1);
+
+		cl_e2p_init_calib_ch_bmp_per_bw(cl_hw, EEPROM_CALIB_DATA_ELEM_NUM_40MHZ_TCV1,
+						cl_hw->conf->ci_calib_eeprom_channels_40mhz,
+						CHNL_BW_40, SIZE_CALIB_IQ_DCOC_40MHZ_BMP_TCV1,
+						ADDR_CALIB_IQ_DCOC_CHANNEL_40MHZ_BMP_TCV1,
+						SIZE_CALIB_IQ_DCOC_DATA_40MHZ_TCV1,
+						ADDR_CALIB_IQ_DCOC_DATA_40MHZ_TCV1);
+
+		cl_e2p_init_calib_ch_bmp_per_bw(cl_hw, EEPROM_CALIB_DATA_ELEM_NUM_80MHZ_TCV1,
+						cl_hw->conf->ci_calib_eeprom_channels_80mhz,
+						CHNL_BW_80, SIZE_CALIB_IQ_DCOC_80MHZ_BMP_TCV1,
+						ADDR_CALIB_IQ_DCOC_CHANNEL_80MHZ_BMP_TCV1,
+						SIZE_CALIB_IQ_DCOC_DATA_80MHZ_TCV1,
+						ADDR_CALIB_IQ_DCOC_DATA_80MHZ_TCV1);
+
+		cl_e2p_init_calib_ch_bmp_per_bw(cl_hw, EEPROM_CALIB_DATA_ELEM_NUM_160MHZ_TCV1,
+						cl_hw->conf->ci_calib_eeprom_channels_160mhz,
+						CHNL_BW_160, SIZE_CALIB_IQ_DCOC_160MHZ_BMP_TCV1,
+						ADDR_CALIB_IQ_DCOC_CHANNEL_160MHZ_BMP_TCV1,
+						SIZE_CALIB_IQ_DCOC_DATA_160MHZ_TCV1,
+						ADDR_CALIB_IQ_DCOC_DATA_160MHZ_TCV1);
+	}
+}
+
+static void e2p_read_eeprom_handler(struct work_struct *ws)
+{
+	struct cl_e2p_work *e2p_work = container_of(ws, struct cl_e2p_work, ws);
+	struct cl_chip *chip = e2p_work->chip;
+	u8 *cache = (u8 *)chip->eeprom_cache;
+	u16 i;
+
+	if (chip->conf->ce_eeprom_mode == E2P_MODE_EEPROM)
+		for (i = EEPROM_BASIC_NUM_BYTES; i < EEPROM_NUM_BYTES; i++)
+			if (e2p_read_byte(chip, i, &cache[i]) < 0)
+				return;
+
+	if (chip->cl_hw_tcv0)
+		cl_e2p_init_calib_ch_bmp(chip->cl_hw_tcv0);
+	if (chip->cl_hw_tcv1)
+		cl_e2p_init_calib_ch_bmp(chip->cl_hw_tcv1);
+
+	chip->is_calib_eeprom_loaded = 1;
+}
+
+void cl_e2p_read_eeprom_start_work(struct cl_chip *chip)
+{
+	struct cl_e2p_work *e2p_work = kzalloc(sizeof(*e2p_work), GFP_ATOMIC);
+
+	if (!e2p_work)
+		return;
+
+	e2p_work->chip = chip;
+	INIT_WORK(&e2p_work->ws, e2p_read_eeprom_handler);
+	queue_work(chip->chip_workqueue, &e2p_work->ws);
+}
+#endif
+
+static int e2p_load_from_eeprom(struct cl_chip *chip)
+{
+	u8 *cache = (u8 *)chip->eeprom_cache;
+	u16 i;
+	int ret = 0;
+#ifdef CONFIG_CL8K_EEPROM_STM24256
+	u16 eeprom_load_len = EEPROM_BASIC_NUM_BYTES;
+#else
+	u16 eeprom_load_len = EEPROM_NUM_BYTES;
+#endif
+
+	for (i = 0; i < eeprom_load_len; i++) {
+		ret = e2p_read_byte(chip, i, &cache[i]);
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+
+static int e2p_eeprom_read_block(struct cl_chip *chip, u16 addr, u16 num_of_bytes, u8 *val)
+{
+	void *read_block = NULL;
+
+	if (!val)
+		return -EFAULT;
+
+	if (addr + num_of_bytes > EEPROM_NUM_BYTES)
+		return -ENXIO;
+
+	read_block = (u8 *)chip->eeprom_cache + addr;
+	memcpy(val, read_block, num_of_bytes);
+
+	return num_of_bytes;
+}
+
+static int e2p_eeprom_write_block(struct cl_chip *chip, u16 addr, u16 num_of_bytes, u8 *val)
+{
+	int bytes_written = -EIO;
+	void *write_block = NULL;
+
+	if (!val)
+		return -EFAULT;
+
+	if (addr + num_of_bytes > EEPROM_NUM_BYTES)
+		return -ENXIO;
+
+	bytes_written = e2p_write_block(chip, addr, num_of_bytes, val);
+	write_block = (u8 *)chip->eeprom_cache + addr;
+	memcpy(write_block, val, num_of_bytes);
+
+	return bytes_written;
+}
+
+static int e2p_load_from_bin(struct cl_chip *chip)
+{
+	char filename[CL_FILENAME_MAX];
+	size_t size = 0;
+	char *buf = NULL;
+	int ret = 0;
+
+	if (cl_chip_is_6g(chip))
+		snprintf(filename, sizeof(filename),
+			 "eeprom%u_cl80x6.bin", chip->idx);
+	else
+		snprintf(filename, sizeof(filename),
+			 "eeprom%u_cl80x0.bin", chip->idx);
+
+	size = cl_file_open_and_read(chip, filename,
+				     (char **)&buf);
+
+	if (size < EEPROM_BASIC_NUM_BYTES) {
+		cl_dbg_chip_err(chip,
+				"Invalid EEPROM size - %s (actual %zu) (min size %d)\n",
+				filename, size, EEPROM_BASIC_NUM_BYTES);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	if (size > EEPROM_NUM_BYTES) {
+		cl_dbg_chip_err(chip,
+				"Invalid EEPROM size - %s (actual %zu) (max size %d)\n",
+				filename, size, EEPROM_NUM_BYTES);
+		ret = -EFBIG;
+		goto err;
+	}
+
+	if (!buf) {
+		cl_dbg_chip_err(chip, "EEPROM data buffer is empty\n");
+
+		ret = -ENODATA;
+		goto err;
+	}
+
+	chip->eeprom_bin_size = size;
+	memcpy(chip->eeprom_cache, buf, size);
+
+err:
+	kfree(buf);
+
+	return ret;
+}
+
+static int e2p_bin_write_block(struct cl_chip *chip, u16 addr, u16 num_of_bytes, u8 *val)
+{
+	return -EOPNOTSUPP;
+}
+
+static int e2p_bin_read_block(struct cl_chip *chip, u16 addr, u16 num_of_bytes, u8 *val)
+{
+	u8 *base;
+	u16 *offset_addr;
+
+	if (!val)
+		return -EFAULT;
+
+	if (addr + num_of_bytes > chip->eeprom_bin_size)
+		return -ENXIO;
+
+	base = (u8 *)chip->eeprom_cache;
+	offset_addr = (u16 *)(base + addr);
+	memmove(val, offset_addr, num_of_bytes);
+
+	return num_of_bytes;
+}
+
+static int cl_e2p_init_bin(struct cl_chip *chip)
+{
+	int ret = 0;
+
+	ret = e2p_load_from_bin(chip);
+	if (ret)
+		return ret;
+
+	chip->eeprom_read_block = e2p_bin_read_block;
+	chip->eeprom_write_block = e2p_bin_write_block;
+
+	return ret;
+}
+
+static int cl_e2p_init_eeprom(struct cl_chip *chip)
+{
+	int ret = 0;
+
+	e2p_enable(chip);
+
+	ret = e2p_load_from_eeprom(chip);
+	if (ret)
+		return ret;
+
+	chip->eeprom_read_block = e2p_eeprom_read_block;
+	chip->eeprom_write_block = e2p_eeprom_write_block;
+
+	return ret;
+}
+
+int cl_e2p_init(struct cl_chip *chip)
+{
+	u8 eeprom_mode = chip->conf->ce_eeprom_mode;
+
+	chip->eeprom_cache = kzalloc(EEPROM_NUM_BYTES, GFP_KERNEL);
+	if (!chip->eeprom_cache)
+		return -ENOMEM;
+
+	if (eeprom_mode == E2P_MODE_BIN)
+		return cl_e2p_init_bin(chip);
+	else if (eeprom_mode == E2P_MODE_EEPROM)
+		return cl_e2p_init_eeprom(chip);
+
+	return -EINVAL;
+}
+
+void cl_e2p_close(struct cl_chip *chip)
+{
+	kfree(chip->eeprom_cache);
+}
+
+int cl_e2p_write(struct cl_chip *chip, u8 *data, u16 size, u16 addr)
+{
+	if (size != chip->eeprom_write_block(chip, addr, size, data)) {
+		cl_dbg_chip_err(chip, "Error writing eeprom addr 0x%x\n", addr);
+		return -EBADE;
+	}
+
+	return 0;
+}
+
+int cl_e2p_read(struct cl_chip *chip, u8 *data, u16 size, u16 addr)
+{
+	if (size != chip->eeprom_read_block(chip, addr, size, data)) {
+		cl_dbg_chip_err(chip, "Error reading eeprom addr 0x%x\n", addr);
+		return -EBADE;
+	}
+
+	return 0;
+}
-- 
2.36.1


  parent reply	other threads:[~2022-05-24 11:38 UTC|newest]

Thread overview: 125+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-24 11:33 [RFC v2 00/96] wireless: cl8k driver for Celeno IEEE 802.11ax devices viktor.barna
2022-05-24 11:33 ` [RFC v2 01/96] celeno: add Kconfig viktor.barna
2022-05-24 11:33 ` [RFC v2 02/96] celeno: add Makefile viktor.barna
2022-05-24 11:33 ` [RFC v2 03/96] cl8k: add Kconfig viktor.barna
2022-05-26 18:18   ` Johannes Berg
2022-05-27  6:09     ` Kalle Valo
2022-07-11 23:04       ` Viktor Barna
2022-07-13  7:32   ` Kalle Valo
2022-05-24 11:33 ` [RFC v2 04/96] cl8k: add Makefile viktor.barna
2022-05-26 18:24   ` Johannes Berg
2022-07-13  7:39   ` Kalle Valo
2022-05-24 11:33 ` [RFC v2 05/96] cl8k: add ampdu.c viktor.barna
2022-05-26 18:19   ` Johannes Berg
2022-05-26 18:22   ` Johannes Berg
2022-05-24 11:33 ` [RFC v2 06/96] cl8k: add ampdu.h viktor.barna
2022-05-24 11:33 ` [RFC v2 07/96] cl8k: add bf.c viktor.barna
2022-05-24 17:24   ` Jeff Johnson
2022-05-24 11:33 ` [RFC v2 08/96] cl8k: add bf.h viktor.barna
2022-05-24 11:33 ` [RFC v2 09/96] cl8k: add calib.c viktor.barna
2022-05-24 11:33 ` [RFC v2 10/96] cl8k: add calib.h viktor.barna
2022-05-24 11:33 ` [RFC v2 11/96] cl8k: add channel.c viktor.barna
2022-05-24 11:33 ` [RFC v2 12/96] cl8k: add channel.h viktor.barna
2022-05-24 11:33 ` [RFC v2 13/96] cl8k: add chip.c viktor.barna
2022-05-24 11:33 ` [RFC v2 14/96] cl8k: add chip.h viktor.barna
2022-05-24 11:33 ` [RFC v2 15/96] cl8k: add config.c viktor.barna
2022-05-24 11:33 ` [RFC v2 16/96] cl8k: add config.h viktor.barna
2022-05-25 18:31   ` Jeff Johnson
2022-05-24 11:33 ` [RFC v2 17/96] cl8k: add debug.c viktor.barna
2022-05-24 11:33 ` [RFC v2 18/96] cl8k: add debug.h viktor.barna
2022-05-24 11:33 ` [RFC v2 19/96] cl8k: add def.h viktor.barna
2022-05-25 18:39   ` Jeff Johnson
2022-05-24 11:33 ` [RFC v2 20/96] cl8k: add dfs.c viktor.barna
2022-05-24 11:33 ` [RFC v2 21/96] cl8k: add dfs.h viktor.barna
2022-05-24 11:33 ` [RFC v2 22/96] cl8k: add dsp.c viktor.barna
2022-05-24 11:33 ` [RFC v2 23/96] cl8k: add dsp.h viktor.barna
2022-05-24 11:33 ` viktor.barna [this message]
2022-05-24 11:33 ` [RFC v2 25/96] cl8k: add e2p.h viktor.barna
2022-05-24 11:33 ` [RFC v2 26/96] cl8k: add eeprom.h viktor.barna
2022-05-24 11:33 ` [RFC v2 27/96] cl8k: add ela.c viktor.barna
2022-05-24 11:33 ` [RFC v2 28/96] cl8k: add ela.h viktor.barna
2022-05-24 11:33 ` [RFC v2 29/96] cl8k: add enhanced_tim.c viktor.barna
2022-05-24 11:33 ` [RFC v2 30/96] cl8k: add enhanced_tim.h viktor.barna
2022-05-24 11:33 ` [RFC v2 31/96] cl8k: add fw.c viktor.barna
2022-05-24 11:33 ` [RFC v2 32/96] cl8k: add fw.h viktor.barna
2022-05-25 18:58   ` Jeff Johnson
2022-05-24 11:33 ` [RFC v2 33/96] cl8k: add hw.c viktor.barna
2022-05-24 11:34 ` [RFC v2 34/96] cl8k: add hw.h viktor.barna
2022-05-24 11:34 ` [RFC v2 35/96] cl8k: add ipc_shared.h viktor.barna
2022-05-24 11:34 ` [RFC v2 36/96] cl8k: add key.c viktor.barna
2022-05-26 19:38   ` Johannes Berg
2022-07-11 23:10     ` Viktor Barna
2022-05-24 11:34 ` [RFC v2 37/96] cl8k: add key.h viktor.barna
2022-05-24 11:34 ` [RFC v2 38/96] cl8k: add mac80211.c viktor.barna
2022-05-26 19:49   ` Johannes Berg
2022-07-11 23:13     ` Viktor Barna
2022-05-24 11:34 ` [RFC v2 39/96] cl8k: add mac80211.h viktor.barna
2022-05-26 19:52   ` Johannes Berg
2022-05-24 11:34 ` [RFC v2 40/96] cl8k: add mac_addr.c viktor.barna
2022-05-26 22:31   ` Jeff Johnson
2022-05-24 11:34 ` [RFC v2 41/96] cl8k: add mac_addr.h viktor.barna
2022-05-24 11:34 ` [RFC v2 42/96] cl8k: add main.c viktor.barna
2022-05-26 23:01   ` Jeff Johnson
2022-05-24 11:34 ` [RFC v2 43/96] cl8k: add main.h viktor.barna
2022-05-24 11:34 ` [RFC v2 44/96] cl8k: add maintenance.c viktor.barna
2022-05-24 11:34 ` [RFC v2 45/96] cl8k: add maintenance.h viktor.barna
2022-05-24 11:34 ` [RFC v2 46/96] cl8k: add motion_sense.c viktor.barna
2022-05-24 11:34 ` [RFC v2 47/96] cl8k: add motion_sense.h viktor.barna
2022-05-24 11:34 ` [RFC v2 48/96] cl8k: add pci.c viktor.barna
2022-05-24 11:34 ` [RFC v2 49/96] cl8k: add pci.h viktor.barna
2022-05-24 11:34 ` [RFC v2 50/96] cl8k: add phy.c viktor.barna
2022-06-01  0:27   ` Jeff Johnson
2022-07-11 23:16     ` Viktor Barna
2022-05-24 11:34 ` [RFC v2 51/96] cl8k: add phy.h viktor.barna
2022-05-24 11:34 ` [RFC v2 52/96] cl8k: add platform.c viktor.barna
2022-05-24 11:34 ` [RFC v2 53/96] cl8k: add platform.h viktor.barna
2022-05-24 11:34 ` [RFC v2 54/96] cl8k: add power.c viktor.barna
2022-05-24 11:34 ` [RFC v2 55/96] cl8k: add power.h viktor.barna
2022-05-24 11:34 ` [RFC v2 56/96] cl8k: add radio.c viktor.barna
2022-05-24 11:34 ` [RFC v2 57/96] cl8k: add radio.h viktor.barna
2022-05-24 11:34 ` [RFC v2 58/96] cl8k: add rates.c viktor.barna
2022-05-24 11:34 ` [RFC v2 59/96] cl8k: add rates.h viktor.barna
2022-05-26 19:54   ` Johannes Berg
2022-07-11 23:17     ` Viktor Barna
2022-07-12  7:17       ` Johannes Berg
2022-05-24 11:34 ` [RFC v2 60/96] cl8k: add recovery.c viktor.barna
2022-05-24 11:34 ` [RFC v2 61/96] cl8k: add recovery.h viktor.barna
2022-05-24 11:34 ` [RFC v2 62/96] cl8k: add regdom.c viktor.barna
2022-05-24 11:34 ` [RFC v2 63/96] cl8k: add regdom.h viktor.barna
2022-05-24 11:34 ` [RFC v2 64/96] cl8k: add reg/reg_access.h viktor.barna
2022-05-24 11:34 ` [RFC v2 65/96] cl8k: add reg/reg_defs.h viktor.barna
2022-05-24 11:34 ` [RFC v2 66/96] cl8k: add rfic.c viktor.barna
2022-05-24 11:34 ` [RFC v2 67/96] cl8k: add rfic.h viktor.barna
2022-06-02 20:40   ` Jeff Johnson
2022-07-11 23:18     ` Viktor Barna
2022-05-24 11:34 ` [RFC v2 68/96] cl8k: add rx.c viktor.barna
2022-05-24 11:34 ` [RFC v2 69/96] cl8k: add rx.h viktor.barna
2022-05-24 11:34 ` [RFC v2 70/96] cl8k: add scan.c viktor.barna
2022-05-24 11:34 ` [RFC v2 71/96] cl8k: add scan.h viktor.barna
2022-05-24 11:34 ` [RFC v2 72/96] cl8k: add sounding.c viktor.barna
2022-05-24 11:34 ` [RFC v2 73/96] cl8k: add sounding.h viktor.barna
2022-05-24 11:34 ` [RFC v2 74/96] cl8k: add sta.c viktor.barna
2022-05-24 11:34 ` [RFC v2 75/96] cl8k: add sta.h viktor.barna
2022-05-24 11:34 ` [RFC v2 76/96] cl8k: add stats.c viktor.barna
2022-06-02 20:59   ` Jeff Johnson
2022-07-11 23:20     ` Viktor Barna
2022-05-24 11:34 ` [RFC v2 77/96] cl8k: add stats.h viktor.barna
2022-05-24 11:34 ` [RFC v2 78/96] cl8k: add tcv.c viktor.barna
2022-05-24 11:34 ` [RFC v2 79/96] cl8k: add tcv.h viktor.barna
2022-05-24 11:34 ` [RFC v2 80/96] cl8k: add temperature.c viktor.barna
2022-05-24 11:34 ` [RFC v2 81/96] cl8k: add temperature.h viktor.barna
2022-05-24 11:34 ` [RFC v2 82/96] cl8k: add traffic.c viktor.barna
2022-05-24 11:34 ` [RFC v2 83/96] cl8k: add traffic.h viktor.barna
2022-05-24 11:34 ` [RFC v2 84/96] cl8k: add tx.c viktor.barna
2022-05-24 11:34 ` [RFC v2 85/96] cl8k: add tx.h viktor.barna
2022-05-24 11:34 ` [RFC v2 86/96] cl8k: add utils.c viktor.barna
2022-05-24 11:34 ` [RFC v2 87/96] cl8k: add utils.h viktor.barna
2022-05-24 11:34 ` [RFC v2 88/96] cl8k: add version.c viktor.barna
2022-05-24 11:34 ` [RFC v2 89/96] cl8k: add version.h viktor.barna
2022-05-24 11:34 ` [RFC v2 90/96] cl8k: add vif.c viktor.barna
2022-05-24 11:34 ` [RFC v2 91/96] cl8k: add vif.h viktor.barna
2022-05-24 11:34 ` [RFC v2 92/96] cl8k: add vns.c viktor.barna
2022-05-24 11:34 ` [RFC v2 93/96] cl8k: add vns.h viktor.barna
2022-05-24 11:35 ` [RFC v2 94/96] cl8k: add wrs.c viktor.barna
2022-05-24 11:35 ` [RFC v2 95/96] cl8k: add wrs.h viktor.barna
2022-05-24 11:35 ` [RFC v2 96/96] wireless: add Celeno vendor viktor.barna

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220524113502.1094459-25-viktor.barna@celeno.com \
    --to=viktor.barna@celeno.com \
    --cc=aviad.brikman@celeno.com \
    --cc=davem@davemloft.net \
    --cc=eliav.farber@gmail.com \
    --cc=kuba@kernel.org \
    --cc=kvalo@codeaurora.org \
    --cc=linux-wireless@vger.kernel.org \
    --cc=maksym.kokhan@celeno.com \
    --cc=oleksandr.savchenko@celeno.com \
    --cc=shay.bar@celeno.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.