Search Linux Wireless

[RFC v1 067/256] cl8k: add e2p.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>
---
 drivers/net/wireless/celeno/cl8k/e2p.c | 664 +++++++++++++++++++++++++
 1 file changed, 664 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..0e51d88b042a
--- /dev/null
+++ b/drivers/net/wireless/celeno/cl8k/e2p.c
@@ -0,0 +1,664 @@
+// SPDX-License-Identifier: MIT
+/* Copyright(c) 2019-2021, Celeno Communications Ltd. */
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include "utils/utils.h"
+#include "utils/file.h"
+#include "chip.h"
+#include "e2p.h"
+#include "reg/reg_access.h"
+#include "config.h"
+
+#define EEPROM_VERSION 2
+
+/* 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
+
+#define PAGE_NUM(addr) ((addr) >> E2P_PAGE_SHIFT)
+#define PAGE_OFF(addr) ((addr) & E2P_PAGE_MASK)
+
+enum bit_num {
+       BIT0,
+       BIT1,
+       BIT2,
+       BIT3,
+       BIT4,
+       BIT5,
+       BIT6,
+       BIT7,
+       BIT8,
+       BIT9,
+       BIT10,
+       BIT11,
+       BIT12,
+       BIT13,
+       BIT14,
+       BIT15,
+       BIT16,
+       BIT17,
+       BIT18,
+       BIT19,
+       BIT20,
+       BIT21,
+       BIT22,
+       BIT23,
+       BIT24,
+       BIT25,
+       BIT26,
+       BIT27,
+       BIT28,
+       BIT29,
+       BIT30,
+       BIT31
+};
+
+/*
+ * 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)
+
+#define I2C_EEPROM_ADDR(page) (0xA0 | (((page) >> 3) & 0xE)) /* [1-0-1-0-P2-P1-P0-0] */
+
+/* E2P_MAX_POLLS should not exceed 12 iterations (attemts) */
+#define E2P_MAX_POLLS 10
+#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 -1;
+}
+
+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 -1;
+}
+
+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)
+{
+       cl_reg_write_chip(chip, I2C_CR, BIT(STO) | BIT(RD) | BIT(ACK));
+       if (i2c_poll_xfer_no_acked(chip) == -1)
+               return -1;
+       *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);
+}
+
+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)
+{
+       if (addr > E2P_SIZE) {
+               cl_dbg_chip_err(chip, "Wrong addr or len\n");
+               return -1;
+       }
+
+       /* Clock in the address to read from. */
+       i2c_write_start(chip, PAGE_NUM(addr));
+       if (i2c_poll_xfer_acked(chip) == -1)
+               return -1;
+
+       /* Addr 8 lsbits are 4 bits page lsbits or`ed with 4 bits page offset */
+       i2c_write(chip, addr);
+       if (i2c_poll_xfer_acked(chip) == -1)
+               return -1;
+
+       /* Read single byte */
+       i2c_read_start(chip, PAGE_NUM(addr));
+       if (i2c_poll_xfer_acked(chip) == -1)
+               return -1;
+
+       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 16 bytes) operation indicating the offset to write to. */
+       int i;
+
+       if (num_of_bytes > E2P_PAGE_SIZE)
+               return -1;
+
+       /* Clock in the address to write to. */
+       i2c_write_start(chip, PAGE_NUM(addr));
+       if (i2c_poll_xfer_acked(chip) == -1)
+               return -1;
+
+       /* Addr 8 lsbits are 4 bits page lsbits or`ed with 4 bits page offset */
+       i2c_write(chip, addr);
+       if (i2c_poll_xfer_acked(chip) == -1)
+               return -1;
+
+       /* Clock in the data to write. */
+       for (i = 0; i < (num_of_bytes - 1); i++, val++) {
+               i2c_write(chip, *val);
+               if (i2c_poll_xfer_acked(chip) == -1)
+                       return -1;
+       }
+
+       /* Clock in the last data byte to write */
+       i2c_write_stop(chip, *val);
+       if (i2c_poll_xfer_acked(chip) == -1)
+               return -1;
+
+       /* Make sure to wait before moving to another page */
+       mdelay(4);
+
+       return 0;
+}
+
+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;
+
+       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;
+
+               if (e2p_write_page(chip, addr, val, bytes_on_curr_page) == -1) {
+                       cl_dbg_chip_err(chip, "Error writing page %u offset %u\n",
+                                       PAGE_NUM(addr), PAGE_OFF(addr));
+                       /* 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;
+}
+
+static int e2p_load_dev(struct cl_chip *chip)
+{
+       u8 *cache = (u8 *)chip->eeprom_cache;
+       u16 i;
+
+       for (i = 0; i < EEPROM_NUM_BYTES; i++)
+               if (e2p_read_byte(chip, i, &cache[i]) == -1)
+                       return -1;
+
+       return 0;
+}
+
+static int e2p_dev_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_dev_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_bin(struct cl_chip *chip)
+{
+       char filename[CL_FILENAME_MAX];
+       size_t size = 0;
+
+       if (cl_chip_is_6g(chip))
+               snprintf(filename, sizeof(filename),
+                        "eeprom/eeprom%u_cl80x6.bin", chip->idx);
+       else
+               snprintf(filename, sizeof(filename),
+                        "eeprom/eeprom%u_cl80x0.bin", chip->idx);
+
+       size = cl_file_open_and_read(chip, filename,
+                                    (char **)&chip->eeprom_cache);
+
+       if (size != EEPROM_NUM_BYTES) {
+               cl_dbg_chip_err(chip,
+                               "Invalid EEPROM size - %s (actual %zu) (expected %d)\n",
+                               filename, size, EEPROM_NUM_BYTES);
+               return -1;
+       }
+
+       return 0;
+}
+
+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 > EEPROM_NUM_BYTES)
+               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)
+{
+       if (e2p_load_bin(chip))
+               return -1;
+
+       chip->eeprom_read_block = e2p_bin_read_block;
+       chip->eeprom_write_block = e2p_bin_write_block;
+
+       return 0;
+}
+
+static int cl_e2p_init_dev(struct cl_chip *chip)
+{
+       chip->eeprom_cache = kzalloc(EEPROM_NUM_BYTES, GFP_KERNEL);
+
+       if (!chip->eeprom_cache)
+               return -1;
+
+       e2p_enable(chip);
+
+       if (e2p_load_dev(chip))
+               return -1;
+
+       chip->eeprom_read_block = e2p_dev_read_block;
+       chip->eeprom_write_block = e2p_dev_write_block;
+
+       return 0;
+}
+
+int cl_e2p_init(struct cl_chip *chip)
+{
+       u8 mode = chip->conf->ce_eeprom_mode;
+
+       if (mode == E2P_MODE_BIN)
+               return cl_e2p_init_bin(chip);
+       else if (mode == E2P_MODE_EEPROM)
+               return cl_e2p_init_dev(chip);
+
+       return -1;
+}
+
+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 -1;
+       }
+
+       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 -1;
+       }
+
+       return 0;
+}
+
+int cl_e2p_write_version(struct cl_chip *chip)
+{
+       u8 version = EEPROM_VERSION;
+
+       if (chip->eeprom_cache->general.version != version)
+               return cl_e2p_write(chip, &version,
+                                   SIZE_GEN_VERSION, ADDR_GEN_VERSION);
+
+       return 0;
+}
+
+int cl_e2p_get_addr(struct wiphy *wiphy, struct wireless_dev *wdev,
+                   void *data, int data_len)
+{
+       struct cl_hw *cl_hw = WIPHY_TO_CL_HW(wiphy);
+       u16 addr = *(u16 *)data;
+       u16 len = *((u16 *)data + 1);
+       int reply_len;
+       struct cl_e2p_get_reply *reply = NULL;
+       struct cl_chip *chip = cl_hw->chip;
+       int ret = 0;
+       u32 end = EEPROM_NUM_BYTES;
+       u8 mode = chip->conf->ce_eeprom_mode;
+
+       reply_len = sizeof(struct cl_e2p_get_reply) + len;
+       reply = kzalloc(reply_len, GFP_KERNEL);
+
+       if (!reply)
+               return -ENOMEM;
+
+       reply->e2p_mode = mode;
+
+       cl_dbg_trace(cl_hw, "addr %u len %u\n", addr, len);
+
+       if (end < (addr + len)) {
+               cl_dbg_err(cl_hw,
+                          "size check failed: last addr = 0x%x, eeprom memory end"
+                          " = 0x%x, eeprom_mode = %u\n", (addr + len),
+                          end, mode);
+               ret = -EINVAL;
+               goto e2p_fail;
+       }
+
+       if (len != chip->eeprom_read_block(chip, addr, len, reply->e2p_data)) {
+               cl_dbg_err(cl_hw, "Error reading eeprom addr 0x%x: len %u\n",
+                          addr, len);
+               ret = -EXDEV;
+               goto e2p_fail;
+       }
+
+       ret = cl_vendor_reply(cl_hw, (void *)reply, reply_len);
+
+e2p_fail:
+       kfree(reply);
+
+       return ret;
+}
+
+int cl_e2p_set_addr(struct wiphy *wiphy, struct wireless_dev *wdev,
+                   const void *data, int data_len)
+{
+       struct cl_hw *cl_hw = WIPHY_TO_CL_HW(wiphy);
+       u16 addr = *(u16 *)data;
+       u16 len = *((u16 *)data + 1);
+       u8 *e2p_data = (u8 *)((u16 *)data + 2);
+       u32 end = EEPROM_NUM_BYTES;
+
+       cl_dbg_trace(cl_hw, "addr %u len %u\n", addr, len);
+
+       if (end < (addr + len)) {
+               cl_dbg_err(cl_hw, "Invalid E2P addr 0x%x, valid are: 0 - %u\n",
+                          addr, end);
+               return -EINVAL;
+       }
+
+       return cl_e2p_write(cl_hw->chip, e2p_data, len, addr);
+}
+
+int cl_e2p_set_wiring_id(struct wiphy *wiphy, struct wireless_dev *wdev,
+                        const void *data, int data_len)
+{
+       struct cl_hw *cl_hw = WIPHY_TO_CL_HW(wiphy);
+       struct cl_chip *chip = cl_hw->chip;
+       u8 wiring_id = *(u8 *)data;
+
+       return cl_fem_set_wiring_id(chip, wiring_id);
+}
+
+int cl_e2p_help(struct wiphy *wiphy, struct wireless_dev *wdev,
+               void *data, int data_len)
+{
+       struct cl_hw *cl_hw = WIPHY_TO_CL_HW(wiphy);
+       char *ret_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       int err = 0;
+
+       if (!ret_buf)
+               return -ENOMEM;
+
+       snprintf(ret_buf, PAGE_SIZE,
+                "usage:\n"
+                "get addr <address> - Read value from specified addr\n"
+                "get mac - Read MAC address\n"
+                "get serial_number - Read serial number\n"
+                "get pwr_table_id - Read power table IDs\n"
+                "get freq_offset - Read frequency offset\n"
+                "get wiring_id - Read wiring ID\n"
+                "get fem_lut- Read FEM look up table\n"
+                "get platform_id - Read platform ID\n"
+                "get calib <ant> <ch> - Read calibrated offset for a given antenna and channel\n"
+                "get hexdump - Read entire eeprom\n"
+                "get table - Read entire eeprom and print in format of table\n"
+                "set addr <address> <value> - Write value to specified address\n"
+                "set mac <macaddr> - Write MAC addr\n"
+                "set serial_number <32 characters> - Write serial number\n"
+                "set pwr_table_id <id tcv0> <id tcv1> - Write power table IDs\n"
+                "set wiring_id <0 - 255> - Write wiring-ID\n"
+                "set fem_lut <type_num> <lut_lna_bypass> <lut_tx> <lut_rx> <lut_off> -"
+                " Write FEM look up table\n"
+                "set platform_id <val> - Write platform-id to eeprom\n"
+                "set freq_offset <0 - 959> - Write frequency offset to eeprom\n"
+                "set calib <antenna> <channel> <power> <offset> <temperature (optional)> -"
+                " Write calibrated power and power offset for a given antenna and channel\n");
+
+       err = cl_vendor_reply(cl_hw, ret_buf, strlen(ret_buf));
+       kfree(ret_buf);
+
+       return err;
+}
+
--
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