On Wed, May 05, 2010 at 08:45:53PM +0200, Sebastien Jan wrote:
> Low-level functions provide 16bits words read and write capability
> to ks8851 companion eeprom.
Please use the eeprom interface that was added already
> Signed-off-by: Sebastien Jan
> ---
> drivers/net/ks8851.c | 228
> ++
> drivers/net/ks8851.h | 14 +++-
> 2 files changed, 241 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c
> index a84e500..787f9df 100644
> --- a/drivers/net/ks8851.c
> +++ b/drivers/net/ks8851.c
> @@ -1044,6 +1044,234 @@ static const struct net_device_ops ks8851_netdev_ops
> = {
> .ndo_validate_addr = eth_validate_addr,
> };
>
> +/* Companion eeprom access */
> +
> +enum { /* EEPROM programming states */
> + EEPROM_CONTROL,
> + EEPROM_ADDRESS,
> + EEPROM_DATA,
> + EEPROM_COMPLETE
> +};
> +
> +/**
> + * ks8851_eeprom_read - read a 16bits word in ks8851 companion EEPROM
> + * @dev: The network device the PHY is on.
> + * @addr: EEPROM address to read
> + *
> + * eeprom_size: used to define the data coding length. Can be changed
> + * through debug-fs.
> + *
> + * Programs a read on the EEPROM using ks8851 EEPROM SW access feature.
> + * Warning: The READ feature is not supported on ks8851 revision 0.
> + *
> + * Rough programming model:
> + * - on period start: set clock high and read value on bus
> + * - on period / 2: set clock low and program value on bus
> + * - start on period / 2
> + */
> +unsigned int ks8851_eeprom_read(struct net_device *dev, unsigned int addr)
> +{
> + struct ks8851_net *ks = netdev_priv(dev);
> + int eepcr;
> + int ctrl = EEPROM_OP_READ;
> + int state = EEPROM_CONTROL;
> + int bit_count = EEPROM_OP_LEN - 1;
> + unsigned int data = 0;
> + int dummy;
> + unsigned int addr_len;
> +
> + addr_len = (ks->eeprom_size == 128) ? 6 : 8;
> +
> + /* start transaction: chip select high, authorize write */
> + mutex_lock(&ks->lock);
> + eepcr = EEPCR_EESA | EEPCR_EESRWA;
> + ks8851_wrreg16(ks, KS_EEPCR, eepcr);
> + eepcr |= EEPCR_EECS;
> + ks8851_wrreg16(ks, KS_EEPCR, eepcr);
> + mutex_unlock(&ks->lock);
> +
> + while (state != EEPROM_COMPLETE) {
> + /* falling clock period starts... */
> + /* set EED_IO pin for control and address */
> + eepcr &= ~EEPCR_EEDO;
> + switch (state) {
> + case EEPROM_CONTROL:
> + eepcr |= ((ctrl >> bit_count) & 1) << 2;
> + if (bit_count-- <= 0) {
> + bit_count = addr_len - 1;
> + state = EEPROM_ADDRESS;
> + }
> + break;
> + case EEPROM_ADDRESS:
> + eepcr |= ((addr >> bit_count) & 1) << 2;
> + bit_count--;
> + break;
> + case EEPROM_DATA:
> + /* Change to receive mode */
> + eepcr &= ~EEPCR_EESRWA;
> + break;
> + }
> +
> + /* lower clock */
> + eepcr &= ~EEPCR_EESCK;
> +
> + mutex_lock(&ks->lock);
> + ks8851_wrreg16(ks, KS_EEPCR, eepcr);
> + mutex_unlock(&ks->lock);
> +
> + /* waitread period / 2 */
> + udelay(EEPROM_SK_PERIOD / 2);
> +
> + /* rising clock period starts... */
> +
> + /* raise clock */
> + mutex_lock(&ks->lock);
> + eepcr |= EEPCR_EESCK;
> + ks8851_wrreg16(ks, KS_EEPCR, eepcr);
> + mutex_unlock(&ks->lock);
> +
> + /* Manage read */
> + switch (state) {
> + case EEPROM_ADDRESS:
> + if (bit_count < 0) {
> + bit_count = EEPROM_DATA_LEN - 1;
> + state = EEPROM_DATA;
> + }
> + break;
> + case EEPROM_DATA:
> + mutex_lock(&ks->lock);
> + dummy = ks8851_rdreg16(ks, KS_EEPCR);
> + mutex_unlock(&ks->lock);
> + data |= ((dummy >> EEPCR_EESB_OFFSET) & 1) << bit_count;
> + if (bit_count-- <= 0)
> + state = EEPROM_COMPLETE;
> + break;
> + }
> +
> + /* wait period / 2 */
> + udelay(EEPROM_SK_PERIOD / 2);
> + }
> +
> + /* close transaction */
> + mutex_lock(&ks->lock);
> + eepcr &= ~EEPCR_EECS;
> + ks8851_wrreg16(ks, KS_EEPCR, eepcr);
> + eepcr = 0;
> + ks8851_wrreg16(ks, KS_EEPCR, eepcr);
> + mutex_unlock(&ks->lock);
> +
> + return data;
> +}
> +
> +/**
> + * ks8851_eeprom_write - write a 16bits word in ks8851 companion EEPROM
> + * @dev: The network device the PHY is on.
> + * @op: operand (can be WR