aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wimax_cmc/wimax_i2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wimax_cmc/wimax_i2c.c')
-rw-r--r--drivers/net/wimax_cmc/wimax_i2c.c854
1 files changed, 854 insertions, 0 deletions
diff --git a/drivers/net/wimax_cmc/wimax_i2c.c b/drivers/net/wimax_cmc/wimax_i2c.c
new file mode 100644
index 0000000..018bfd3
--- /dev/null
+++ b/drivers/net/wimax_cmc/wimax_i2c.c
@@ -0,0 +1,854 @@
+/**
+ * wimax_i2c.c
+ *
+ * EEPROM access functions
+ */
+#include "wimax_i2c.h"
+#include "firmware.h"
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <mach/gpio.h>
+#include <plat/gpio-cfg.h>
+#include <linux/vmalloc.h>
+#include <plat/gpio-cfg.h>
+#include <mach/regs-gpio.h>
+#include <mach/gpio-u1.h>
+#include <linux/slab.h>
+
+#define WIMAX_EN GPIO_WIMAX_EN
+#define I2C_SEL GPIO_WIMAX_I2C_CON
+#define EEPROM_SCL GPIO_CMC_SCL_18V
+#define EEPROM_SDA GPIO_CMC_SDA_18V
+
+
+#define MAX_WIMAXBOOTIMAGE_SIZE 6000
+#define MAX_BOOT_WRITE_LENGTH 128
+#define WIMAX_EEPROM_ADDRLEN 2
+
+
+struct boot_image_data g_wimax_image;
+
+static void wimax_i2c_reset(void);
+
+void dump_buffer(const char *desc, u_char *buffer, u_int len)
+{
+ char print_buf[256] = {0};
+ char chr[8] = {0};
+ int i;
+ /* dump packets */
+ u_char *b = buffer;
+ pr_debug("%s (%d) =>", desc, len);
+
+ for (i = 0; i < len; i++) {
+ sprintf(chr, " %02x", b[i]);
+ strcat(print_buf, chr);
+ if (((i + 1) != len) && (i % 16 == 15)) {
+ pr_debug("%s", print_buf);
+ memset(print_buf, 0x0, 256);
+ }
+ }
+ pr_debug("%s", print_buf);
+}
+void eeprom_poweron(void)
+{
+ mutex_init(&g_wimax_image.lock);
+ mutex_lock(&g_wimax_image.lock);
+
+ s3c_gpio_cfgpin(EEPROM_SCL, S3C_GPIO_SFN(1));
+ s3c_gpio_setpull(EEPROM_SCL, S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(EEPROM_SDA, S3C_GPIO_SFN(1));
+ s3c_gpio_setpull(EEPROM_SDA, S3C_GPIO_PULL_NONE);
+
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_HIGH);
+ gpio_set_value(EEPROM_SDA, GPIO_LEVEL_HIGH);
+
+ /* SEL = 1 to switch i2c-eeprom path to AP */
+ gpio_set_value(I2C_SEL, GPIO_LEVEL_HIGH);
+ usleep_range(10000, 10000);
+
+
+ /* power on */
+ gpio_set_value(WIMAX_EN, GPIO_LEVEL_HIGH);
+
+ msleep(100);
+
+ wimax_i2c_reset();
+ usleep_range(10000, 10000);
+}
+
+void eeprom_poweroff(void)
+{
+ /* power off */
+ gpio_set_value(WIMAX_EN, GPIO_LEVEL_LOW);
+
+ /* SEL = 0 to switch i2c-eeprom path to wimax */
+ gpio_set_value(I2C_SEL, GPIO_LEVEL_LOW);
+
+ msleep(100);
+
+ mutex_unlock(&g_wimax_image.lock);
+ mutex_destroy(&g_wimax_image.lock);
+}
+
+/* I2C functions for read/write EEPROM */
+#ifdef DRIVER_BIT_BANG
+void wimax_i2c_write_byte(char c, int len)
+{
+ int i;
+ char level;
+
+ /* 8 bits */
+ for (i = 0; i < len; i++) {
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_LOW);
+ udelay(1);
+ level = (c >> (len - i - 1)) & 0x1;
+ s3c_gpio_cfgpin(EEPROM_SDA, S3C_GPIO_SFN(1));
+ gpio_set_value(EEPROM_SDA, level);
+ udelay(2);
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_HIGH);
+ udelay(2);
+ }
+}
+
+char wimax_i2c_read_byte(int len)
+{
+ int j;
+ char val = 0;
+
+ /* 8 bits */
+ for (j = 0; j < len; j++) {
+ /* read data */
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_LOW);
+ s3c_gpio_cfgpin(EEPROM_SDA, S3C_GPIO_SFN(0));
+ udelay(2);
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_HIGH);
+ udelay(2);
+ val |= (gpio_get_value(EEPROM_SDA) << (len - j - 1));
+ }
+
+ return val;
+}
+
+void wimax_i2c_init(void)
+{
+ const int DEVICE_ADDRESS = 0x50;
+
+ s3c_gpio_cfgpin(EEPROM_SCL, S3C_GPIO_SFN(1));
+ s3c_gpio_cfgpin(EEPROM_SDA, S3C_GPIO_SFN(1));
+
+ /* initial */
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_HIGH);
+ gpio_set_value(EEPROM_SDA, GPIO_LEVEL_HIGH);
+ udelay(3);
+
+ /* start bit */
+ gpio_set_value(EEPROM_SDA, GPIO_LEVEL_LOW);
+ udelay(2);
+
+ /* send 7 bits address */
+ wimax_i2c_write_byte(DEVICE_ADDRESS, 7);
+}
+
+void wimax_i2c_deinit(void)
+{
+ /* stop */
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_LOW);
+ udelay(1);
+ s3c_gpio_cfgpin(EEPROM_SDA, S3C_GPIO_SFN(1));
+ gpio_set_value(EEPROM_SDA, GPIO_LEVEL_LOW);
+ udelay(1);
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_HIGH);
+ udelay(1);
+ gpio_set_value(EEPROM_SDA, GPIO_LEVEL_HIGH);
+
+ mdelay(10);
+
+}
+
+void wimax_i2c_reset(void)
+{
+ int i;
+
+ /* initial */
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_HIGH);
+ gpio_set_value(EEPROM_SDA, GPIO_LEVEL_HIGH);
+ udelay(3);
+
+ /* start bit */
+ s3c_gpio_cfgpin(EEPROM_SDA, S3C_GPIO_SFN(1));
+ gpio_set_value(EEPROM_SDA, GPIO_LEVEL_LOW);
+ udelay(3);
+
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_LOW);
+ udelay(1);
+ gpio_set_value(EEPROM_SDA, GPIO_LEVEL_HIGH);
+
+ /* 9 clocks */
+ for (i = 0; i < 9; i++) {
+ udelay(2);
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_HIGH);
+ udelay(2);
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_LOW);
+ }
+ udelay(2);
+
+ /* start bit & stop bit */
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_HIGH);
+ udelay(2);
+ gpio_set_value(EEPROM_SDA, GPIO_LEVEL_LOW);
+ udelay(2);
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_LOW);
+ udelay(2);
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_HIGH);
+ udelay(2);
+ gpio_set_value(EEPROM_SDA, GPIO_LEVEL_HIGH);
+ udelay(2);
+}
+
+void wimax_i2c_ack(void)
+{
+ /* ack */
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_LOW);
+ udelay(1);
+ s3c_gpio_cfgpin(EEPROM_SDA, S3C_GPIO_SFN(1));
+ gpio_set_value(EEPROM_SDA, GPIO_LEVEL_LOW);
+ udelay(1);
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_HIGH);
+ udelay(1);
+}
+
+void wimax_i2c_no_ack(void)
+{
+ /* no ack */
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_LOW);
+ udelay(1);
+ s3c_gpio_cfgpin(EEPROM_SDA, S3C_GPIO_SFN(1));
+ gpio_set_value(EEPROM_SDA, GPIO_LEVEL_HIGH);
+ udelay(1);
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_HIGH);
+ udelay(1);
+}
+
+int wimax_i2c_check_ack(void)
+{
+ char val;
+
+ /* ack */
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_LOW);
+ s3c_gpio_cfgpin(EEPROM_SDA, S3C_GPIO_SFN(0));
+ udelay(1);
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_HIGH);
+ udelay(2);
+ val = gpio_get_value(EEPROM_SDA);
+
+ if (val == 1) {
+ pr_debug("EEPROM ERROR: NO ACK!!");
+ return -1;
+ }
+
+ return 0;
+}
+
+int wimax_i2c_write_cmd(void)
+{
+ /* write cmd */
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_LOW);
+ s3c_gpio_cfgpin(EEPROM_SDA, S3C_GPIO_SFN(1));
+ gpio_set_value(EEPROM_SDA, GPIO_LEVEL_LOW); /* write cmd: 0 */
+ udelay(1);
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_HIGH);
+ udelay(2);
+
+ return wimax_i2c_check_ack();
+}
+
+int wimax_i2c_read_cmd(void)
+{
+ /* read cmd */
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_LOW);
+ s3c_gpio_cfgpin(EEPROM_SDA, S3C_GPIO_SFN(1));
+ gpio_set_value(EEPROM_SDA, GPIO_LEVEL_HIGH); /* read cmd: 1 */
+ udelay(1);
+ gpio_set_value(EEPROM_SCL, GPIO_LEVEL_HIGH);
+ udelay(2);
+
+ return wimax_i2c_check_ack();
+}
+
+int wimax_i2c_eeprom_address(short addr)
+{
+ char buf[2] = {0};
+
+ buf[0] = addr & 0xff;
+ buf[1] = (addr >> 8) & 0xff;
+
+ /* send 2 bytes address */
+ wimax_i2c_write_byte(buf[1], 8);
+ if (wimax_i2c_check_ack())
+ return -1;
+ wimax_i2c_write_byte(buf[0], 8);
+ return wimax_i2c_check_ack();
+}
+
+int wimax_i2c_write_buffer(char *data, int len)
+{
+ int i;
+ for (i = 0; i < len; i++) {
+ wimax_i2c_write_byte(data[i], 8); /* 1 byte data */
+ if (wimax_i2c_check_ack())
+ return -1;
+ }
+ return 0;
+}
+
+int wimax_i2c_write(u_short addr, u_char *data, int length)
+{
+ int ret = 0;
+
+ /* write buffer */
+ wimax_i2c_init();
+ ret = wimax_i2c_write_cmd();
+ ret |= wimax_i2c_eeprom_address(addr);
+ ret |= wimax_i2c_write_buffer(data, length);
+ wimax_i2c_deinit();
+ return ret;
+}
+
+int wimax_i2c_read(u_short addr, u_char *data, int length)
+{
+ int i = 0;
+ int ret = 0;
+
+ /* read buffer */
+ wimax_i2c_init();
+ ret = wimax_i2c_write_cmd();
+ ret |= wimax_i2c_eeprom_address(addr);
+
+ wimax_i2c_init();
+ ret |= wimax_i2c_read_cmd();
+
+ for (i = 0; i < length; i++) {
+ *(data + i) = wimax_i2c_read_byte(8); /* 1 byte data */
+ if ((i + 1) == length)
+ wimax_i2c_no_ack(); /* no ack end of data */
+ else
+ wimax_i2c_ack();
+ }
+ wimax_i2c_deinit();
+ return ret;
+}
+#else
+
+static struct i2c_client *pclient;
+
+void wimax_i2c_reset(void)
+{}
+
+int wimax_i2c_write(u_short addr, u_char *data, int length)
+{
+ int rc;
+ int len;
+ char data_buffer[MAX_BOOT_WRITE_LENGTH + WIMAX_EEPROM_ADDRLEN];
+ struct i2c_msg msg;
+ data_buffer[0] = (unsigned char)((addr >> 8) & 0xff);
+ data_buffer[1] = (unsigned char)(addr & 0xff);
+ while (length) {
+ len = (length > MAX_BOOT_WRITE_LENGTH) ?
+ MAX_BOOT_WRITE_LENGTH : length ;
+ memcpy(data_buffer+WIMAX_EEPROM_ADDRLEN, data, len);
+ msg.addr = pclient->addr;
+ msg.flags = 0; /*write*/
+ msg.len = (u16)length+WIMAX_EEPROM_ADDRLEN;
+ msg.buf = data_buffer;
+ rc = i2c_transfer(pclient->adapter, &msg, 1);
+ if (rc < 0)
+ return rc;
+ length -= len;
+ data += len;
+ }
+ return 0;
+}
+
+int wimax_i2c_read(u_short addr, u_char *data, int length)
+{
+ char data_buffer[MAX_BOOT_WRITE_LENGTH + WIMAX_EEPROM_ADDRLEN];
+ struct i2c_msg msgs[2];
+ data_buffer[0] = (unsigned char)((addr >> 8) & 0xff);
+ data_buffer[1] = (unsigned char)(addr & 0xff);
+ msgs[0].addr = pclient->addr;
+ msgs[0].flags = 0; /*write*/
+ msgs[0].len = WIMAX_EEPROM_ADDRLEN;
+ msgs[0].buf = data_buffer;
+ msgs[1].addr = pclient->addr;
+ msgs[1].flags = I2C_M_RD; /*read*/
+ msgs[1].len = length;
+ msgs[1].buf = data;
+ return i2c_transfer(pclient->adapter, msgs, 2);
+
+}
+
+static ssize_t eeprom_show(struct device *dev,
+ struct device_attribute *attr, char *buf){
+ pr_debug("Writing boot & revision to wimax eeprom");
+
+ eeprom_write_boot();
+ eeprom_write_rev();
+
+ return 0;
+
+}
+
+static ssize_t eeprom_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buffer, size_t count) {
+
+ if (strncmp(buffer, "wb00", 4) == 0) {
+ pr_debug("Write EEPROM!!");
+ eeprom_write_boot();
+ } else if (strncmp(buffer, "rb00", 4) == 0) {
+ pr_debug("Read Boot!!");
+ eeprom_read_boot();
+ } else if (strncmp(buffer, "re00", 4) == 0) {
+ pr_debug("Read EEPROM!!");
+ eeprom_read_all();
+ } else if (strncmp(buffer, "ee00", 4) == 0) {
+ pr_debug("Erase EEPROM!!");
+ eeprom_erase_all();
+ } else if (strncmp(buffer, "rcal", 4) == 0) {
+ pr_debug("Check Cal!!");
+ eeprom_check_cal();
+ } else if (strncmp(buffer, "ecer", 4) == 0) {
+ pr_debug("Erase Cert!!");
+ eeprom_erase_cert();
+ } else if (strncmp(buffer, "rcer", 4) == 0) {
+ pr_debug("Check Cert!!");
+ eeprom_check_cert();
+ } else if (strncmp(buffer, "wrev", 4) == 0) {
+ pr_debug("Write Rev!!");
+ eeprom_write_rev();
+ } else
+ pr_debug("Wrong option");
+
+ return count;
+}
+
+static DEVICE_ATTR(eeprom, 0664, eeprom_show, eeprom_store);
+
+int wmxeeprom_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ struct class *wimax_class;
+ struct device *dev_t;
+ int err;
+
+ pr_debug("[WMXEEPROM]: probe");
+
+ pclient = client;
+ wimax_class = class_create(THIS_MODULE, "wimax");
+ if (IS_ERR(wimax_class))
+ pr_err("%s: Class create failed", __func__);
+
+ dev_t = device_create(wimax_class, NULL, 0, "%s", "cmc732");
+ if (IS_ERR(dev_t))
+ pr_err("%s: Device create failed", __func__);
+
+ err = device_create_file(dev_t, &dev_attr_eeprom);
+ if (err < 0)
+ pr_err("%s: Device file create failed", __func__);
+
+ return 0;
+}
+
+int wmxeeprom_remove(struct i2c_client *client)
+{
+ pr_debug("[WMXEEPROM]: remvove");
+
+ return 0;
+}
+
+const struct i2c_device_id wmxeeprom_id[] = {
+ { "wmxeeprom", 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, wmxeeprom_id);
+static struct i2c_driver wmxeeprom_driver = {
+ .probe = wmxeeprom_probe,
+ .remove = wmxeeprom_remove,
+ .id_table = wmxeeprom_id,
+ .driver = {
+ .name = "wmxeeprom",
+ },
+};
+int wmxeeprom_init(void)
+{
+ return i2c_add_driver(&wmxeeprom_driver);
+}
+
+void wmxeeprom_exit(void)
+{
+ i2c_del_driver(&wmxeeprom_driver);
+}
+#endif
+
+int load_wimax_boot(void)
+{
+ struct file *fp;
+ int read_size = 0;
+
+ fp = klib_fopen(WIMAX_BOOTIMAGE_PATH, O_RDONLY, 0);
+
+ if (fp) {
+ pr_debug("LoadWiMAXBootImage ..");
+ g_wimax_image.data = vmalloc(MAX_WIMAXBOOTIMAGE_SIZE);
+ if (!g_wimax_image.data) {
+ pr_debug("Error: Memory alloc failure.");
+ klib_fclose(fp);
+ return -1;
+ }
+
+ memset(g_wimax_image.data, 0, MAX_WIMAXBOOTIMAGE_SIZE);
+ read_size = klib_flen_fcopy(g_wimax_image.data,
+ MAX_WIMAXBOOTIMAGE_SIZE, fp);
+ g_wimax_image.size = read_size;
+ g_wimax_image.address = 0;
+ g_wimax_image.offset = 0;
+ mutex_init(&g_wimax_image.lock);
+
+ klib_fclose(fp);
+ } else {
+ pr_debug("Error: WiMAX image file open failed");
+ return -1;
+ }
+
+ return 0;
+}
+
+int write_rev(void)
+{
+ u_int val;
+ int retry = 100;
+ int err;
+
+ pr_debug("HW REV: %d", system_rev);
+
+ /* swap */
+ val = be32_to_cpu(system_rev);
+
+ do {
+ err = wimax_i2c_write(0x7080, (char *)(&val), 4);
+ } while (err < 0 ? ((retry--) > 0) : 0);
+ if (retry < 0)
+ pr_debug("eeprom error");
+ return err ;
+}
+
+void erase_cert(void)
+{
+ char buf[256] = {0};
+ int len = 4;
+ int retry = 100;
+ int err;
+
+ do {
+ err = wimax_i2c_write(0x5800, buf, len);
+ } while (err < 0 ? ((retry--) > 0) : 0);
+ if (retry < 0)
+ pr_debug("eeprom error");
+}
+
+int check_cert(void)
+{
+ char buf[256] = {0};
+ int len = 16;
+ int retry = 100;
+ int err;
+
+ do {
+ err = wimax_i2c_read(0x5800, buf, len);
+ } while (err < 0 ? ((retry--) > 0) : 0);
+ if (retry < 0)
+ pr_debug("eeprom error");
+
+ dump_buffer("Certification", (u_char *)buf, (u_int)len);
+
+ /* check "Cert" */
+ if (buf[0] == 0x43 && buf[1] == 0x65 &&
+ buf[2] == 0x72 && buf[3] == 0x74)
+ return 0;
+
+ return -1;
+}
+
+int check_cal(void)
+{
+ char buf[256] = {0};
+ int i;
+ int len = 32;
+ int retry = 100;
+ int err;
+
+ do {
+ err = wimax_i2c_read(0x5400, buf, len);
+ } while (err < 0 ? ((retry--) > 0) : 0);
+ if (retry < 0)
+ pr_debug("eeprom error");
+
+ dump_buffer("Calibration", (u_char *)buf, (u_int)len);
+
+ /* at lease one buf[i] not equal 0xff means calibrated */
+ for (i = 0; i < len; i++)
+ if (buf[i] != 0xff)
+ return 0;
+
+ /* all 0xff means not calibrated */
+ return -1;
+}
+
+void eeprom_read_boot()
+{
+ char *buf = NULL;
+ int i, j;
+ int len;
+ u_int checksum = 0;
+ short addr = 0;
+ int retry = 1000;
+ int err;
+
+ eeprom_poweron();
+
+ buf = kmalloc(4096, GFP_KERNEL);
+ if (buf == NULL) {
+ pr_debug("eeprom_read_boot: MALLOC FAIL!!");
+ return;
+ }
+
+ addr = 0x0;
+ for (j = 0; j < 1; j++) { /* read 4K */
+ len = 4096;
+ do {
+ err = wimax_i2c_read(addr, buf, len);
+ } while (err < 0 ? ((retry--) > 0) : 0);
+
+ {
+ /* dump boot data */
+ char print_buf[256] = {0};
+ char chr[8] = {0};
+
+ /* dump packets with checksum */
+ u_char *b = (u_char *)buf;
+ pr_debug("EEPROM dump [0x%04x] = ", addr);
+
+ for (i = 0; i < len; i++) {
+ checksum += b[i];
+ sprintf(chr, " %02x", b[i]);
+ strcat(print_buf, chr);
+ if (((i + 1) != len) && (i % 16 == 15)) {
+ pr_debug("%s", print_buf);
+ memset(print_buf, 0x0, 256);
+ }
+ }
+ pr_debug("%s", print_buf);
+ }
+ addr += len;
+ }
+
+ pr_debug("Checksum: 0x%08x", checksum);
+
+ kfree(buf);
+
+ eeprom_poweroff();
+ if (retry < 0)
+ pr_debug("eeprom error");
+}
+
+void eeprom_read_all()
+{
+ char *buf = NULL;
+ int i, j;
+ int len;
+ u_int checksum = 0;
+ short addr = 0;
+ int retry = 1000;
+ int err;
+
+ eeprom_poweron();
+
+ /* allocate 4K buffer */
+ buf = kmalloc(4096, GFP_KERNEL);
+ if (buf == NULL) {
+ pr_debug("eeprom_read_all: MALLOC FAIL!!");
+ return;
+ }
+
+ addr = 0x0;
+
+ /* read 64K */
+ for (j = 0; j < 16; j++) {
+ len = 4096;
+ do {
+ err = wimax_i2c_read(addr, buf, len);
+ } while (err < 0 ? ((retry--) > 0) : 0);
+
+ {
+ /* dump EEPROM */
+ char print_buf[256] = {0};
+ char chr[8] = {0};
+
+ /* dump packets with checksum */
+ u_char *b = (u_char *)buf;
+ pr_debug("EEPROM dump [0x%04x] = ", addr);
+
+ for (i = 0; i < len; i++) {
+ checksum += b[i];
+ sprintf(chr, " %02x", b[i]);
+ strcat(print_buf, chr);
+ if (((i + 1) != len) && (i % 16 == 15)) {
+ pr_debug("%s", print_buf);
+ memset(print_buf, 0x0, 256);
+ }
+ }
+ pr_debug("%s", print_buf);
+ }
+ addr += len;
+ }
+
+ pr_debug("Checksum: 0x%08x", checksum);
+
+ /* free 4K buffer */
+ kfree(buf);
+
+ eeprom_poweroff();
+ if (retry < 0)
+ pr_debug("eeprom error");
+}
+
+void eeprom_erase_all()
+{
+ char buf[128] = {0};
+ int i;
+ int retry = 1000;
+ int err;
+
+ eeprom_poweron();
+
+ memset(buf, 0xff, 128);
+ for (i = 0; i < 512; i++) { /* clear all EEPROM */
+ pr_debug("ERASE [0x%04x]\n", i * 128);
+ do {
+ err = wimax_i2c_write(128 * i, buf, 128);
+ } while (err < 0 ? ((retry--) > 0) : 0);
+ }
+
+ eeprom_poweroff();
+ if (retry < 0)
+ pr_debug("eeprom error");
+}
+
+/* Write boot image to EEPROM */
+int eeprom_write_boot(void)
+{
+ u_char *buffer;
+ int retry = 1000;
+ int err = 0;
+ u_short ucsize = MAX_BOOT_WRITE_LENGTH;
+
+ if (load_wimax_boot() < 0) {
+ pr_debug("ERROR READ WIMAX BOOT IMAGE");
+ return -1;
+ }
+
+ eeprom_poweron();
+
+ g_wimax_image.offset = 0;
+
+ while (g_wimax_image.size > g_wimax_image.offset) {
+ buffer = (u_char *)(g_wimax_image.data + g_wimax_image.offset);
+ ucsize = MAX_BOOT_WRITE_LENGTH;
+
+ /* write buffer */
+ do {
+ err = wimax_i2c_write(
+ (u_short)g_wimax_image.offset, buffer, ucsize);
+ } while (err < 0 ? ((retry--) > 0) : 0);
+
+ g_wimax_image.offset += MAX_BOOT_WRITE_LENGTH;
+
+ if ((g_wimax_image.size - g_wimax_image.offset)
+ < MAX_BOOT_WRITE_LENGTH) {
+ buffer = (u_char *)(g_wimax_image.data +
+ g_wimax_image.offset);
+ ucsize = g_wimax_image.size - g_wimax_image.offset;
+
+ /* write last data */
+ do {
+ err = wimax_i2c_write(
+ (u_short)g_wimax_image.offset, buffer, ucsize);
+ } while (err < 0 ? ((retry--) > 0) : 0);
+
+ g_wimax_image.offset += MAX_BOOT_WRITE_LENGTH;
+ }
+ }
+
+ eeprom_poweroff();
+
+ if (g_wimax_image.data) {
+ pr_debug("Delete the Image Loaded");
+ vfree(g_wimax_image.data);
+ g_wimax_image.data = NULL;
+ }
+
+ if (retry < 0)
+ pr_debug("eeprom error");
+ else
+ pr_debug("EEPROM WRITING DONE.");
+
+ return err;
+}
+
+int eeprom_write_rev(void)
+{
+ int ret;
+
+ eeprom_poweron();
+ ret = write_rev(); /* write hw rev to eeprom */
+ eeprom_poweroff();
+
+ pr_debug("REV WRITING DONE.");
+ return ret;
+}
+
+void eeprom_erase_cert(void)
+{
+ eeprom_poweron();
+ erase_cert();
+ eeprom_poweroff();
+
+ pr_debug("ERASE CERT DONE.");
+}
+
+int eeprom_check_cert(void)
+{
+ int ret;
+
+ eeprom_poweron();
+ ret = check_cert(); /* check cert */
+ eeprom_poweroff();
+
+ pr_debug("CHECK CERT DONE. (ret: %d)", ret);
+
+ return ret;
+}
+
+int eeprom_check_cal(void)
+{
+ int ret;
+
+ eeprom_poweron();
+ ret = check_cal(); /* check cal */
+ eeprom_poweroff();
+
+ pr_debug("CHECK CAL DONE. (ret: %d)", ret);
+
+ return ret;
+}
+