/*
   This files contains card eeprom (93c46 or 93c56) programming routines,
   memory is addressed by 16 bits words.

   This is part of rtl8180 OpenSource driver.
   Copyright (C) Andrea Merello 2004  <andreamrl@tiscali.it>
   Released under the terms of GPL (General Public Licence)

   Parts of this driver are based on the GPL part of the
   official realtek driver.

   Parts of this driver are based on the rtl8180 driver skeleton
   from Patric Schenke & Andres Salomon.

   Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.

   We want to tanks the Authors of those projects and the Ndiswrapper
   project Authors.
*/

#include "r8180_93cx6.h"

static void eprom_cs(struct net_device *dev, short bit)
{
	if (bit)
		write_nic_byte(dev, EPROM_CMD,
			       (1<<EPROM_CS_SHIFT) | \
			       read_nic_byte(dev, EPROM_CMD)); //enable EPROM
	else
		write_nic_byte(dev, EPROM_CMD, read_nic_byte(dev, EPROM_CMD)\
			       &~(1<<EPROM_CS_SHIFT)); //disable EPROM

	force_pci_posting(dev);
	udelay(EPROM_DELAY);
}


static void eprom_ck_cycle(struct net_device *dev)
{
	write_nic_byte(dev, EPROM_CMD,
		       (1<<EPROM_CK_SHIFT) | read_nic_byte(dev, EPROM_CMD));
	force_pci_posting(dev);
	udelay(EPROM_DELAY);
	write_nic_byte(dev, EPROM_CMD,
		       read_nic_byte(dev, EPROM_CMD) & ~(1<<EPROM_CK_SHIFT));
	force_pci_posting(dev);
	udelay(EPROM_DELAY);
}


static void eprom_w(struct net_device *dev, short bit)
{
	if (bit)
		write_nic_byte(dev, EPROM_CMD, (1<<EPROM_W_SHIFT) | \
			       read_nic_byte(dev, EPROM_CMD));
	else
		write_nic_byte(dev, EPROM_CMD, read_nic_byte(dev, EPROM_CMD)\
			       &~(1<<EPROM_W_SHIFT));

	force_pci_posting(dev);
	udelay(EPROM_DELAY);
}


static short eprom_r(struct net_device *dev)
{
	short bit;

	bit = (read_nic_byte(dev, EPROM_CMD) & (1<<EPROM_R_SHIFT));
	udelay(EPROM_DELAY);

	if (bit)
		return 1;
	return 0;
}


static void eprom_send_bits_string(struct net_device *dev, short b[], int len)
{
	int i;

	for (i = 0; i < len; i++) {
		eprom_w(dev, b[i]);
		eprom_ck_cycle(dev);
	}
}


u32 eprom_read(struct net_device *dev, u32 addr)
{
	struct r8192_priv *priv = ieee80211_priv(dev);
	short read_cmd[] = {1, 1, 0};
	short addr_str[8];
	int i;
	int addr_len;
	u32 ret;

	ret = 0;
        //enable EPROM programming
	write_nic_byte(dev, EPROM_CMD,
		       (EPROM_CMD_PROGRAM<<EPROM_CMD_OPERATING_MODE_SHIFT));
	force_pci_posting(dev);
	udelay(EPROM_DELAY);

	if (priv->epromtype == EPROM_93c56) {
		addr_str[7] = addr & 1;
		addr_str[6] = addr & (1<<1);
		addr_str[5] = addr & (1<<2);
		addr_str[4] = addr & (1<<3);
		addr_str[3] = addr & (1<<4);
		addr_str[2] = addr & (1<<5);
		addr_str[1] = addr & (1<<6);
		addr_str[0] = addr & (1<<7);
		addr_len = 8;
	} else {
		addr_str[5] = addr & 1;
		addr_str[4] = addr & (1<<1);
		addr_str[3] = addr & (1<<2);
		addr_str[2] = addr & (1<<3);
		addr_str[1] = addr & (1<<4);
		addr_str[0] = addr & (1<<5);
		addr_len = 6;
	}
	eprom_cs(dev, 1);
	eprom_ck_cycle(dev);
	eprom_send_bits_string(dev, read_cmd, 3);
	eprom_send_bits_string(dev, addr_str, addr_len);

	//keep chip pin D to low state while reading.
	//I'm unsure if it is necessary, but anyway shouldn't hurt
	eprom_w(dev, 0);

	for (i = 0; i < 16; i++) {
		//eeprom needs a clk cycle between writing opcode&adr
		//and reading data. (eeprom outs a dummy 0)
		eprom_ck_cycle(dev);
		ret |= (eprom_r(dev)<<(15-i));
	}

	eprom_cs(dev, 0);
	eprom_ck_cycle(dev);

	//disable EPROM programming
	write_nic_byte(dev, EPROM_CMD,
		       (EPROM_CMD_NORMAL<<EPROM_CMD_OPERATING_MODE_SHIFT));
	return ret;
}
