All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ben Dooks <ben-linux@fluff.org>
To: Sebastien Jan <s-jan@ti.com>
Cc: netdev@vger.kernel.org, linux-omap@vger.kernel.org,
	Abraham Arce <x0066660@ti.com>, Ben Dooks <ben-linux@fluff.org>,
	Tristram.Ha@micrel.com
Subject: Re: [PATCH 2/4 v2] ks8851: Low level functions for read/write to companion eeprom
Date: Tue, 11 May 2010 02:16:38 +0100	[thread overview]
Message-ID: <20100511011638.GI2589@trinity.fluff.org> (raw)
In-Reply-To: <1273085155-1260-3-git-send-email-s-jan@ti.com>

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 <s-jan@ti.com>
> ---
>  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 WRITE, EWEN, EWDS)
> + * @addr: EEPROM address to write
> + * @data: data to write
> + *
> + * eeprom_size: used to define the data coding length. Can be changed
> + * through debug-fs.
> + *
> + * Programs a write on the EEPROM using ks8851 EEPROM SW access feature.
> + *
> + * Note that a write enable is required before writing data.
> + *
> + * Rough programming model:
> + *  - on period start: set clock high
> + *  - on period / 2: set clock low and program value on bus
> + *  - start on period / 2
> + */
> +void ks8851_eeprom_write(struct net_device *dev, unsigned int op,
> +					unsigned int addr, unsigned int data)
> +{
> +	struct ks8851_net *ks = netdev_priv(dev);
> +	int eepcr;
> +	int state = EEPROM_CONTROL;
> +	int bit_count = EEPROM_OP_LEN - 1;
> +	unsigned int addr_len;
> +
> +	addr_len = (ks->eeprom_size == 128) ? 6 : 8;
> +
> +	switch (op) {
> +	case EEPROM_OP_EWEN:
> +		addr = 0x30;
> +	break;
> +	case EEPROM_OP_EWDS:
> +		addr = 0;
> +		break;
> +	}
> +
> +	/* 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 |= ((op >> 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;
> +			if (bit_count-- <= 0) {
> +				if (op == EEPROM_OP_WRITE) {
> +					bit_count = EEPROM_DATA_LEN - 1;
> +					state = EEPROM_DATA;
> +				} else {
> +					state = EEPROM_COMPLETE;
> +				}
> +			}
> +			break;
> +		case EEPROM_DATA:
> +			eepcr |= ((data >> bit_count) & 1) << 2;
> +			if (bit_count-- <= 0)
> +				state = EEPROM_COMPLETE;
> +			break;
> +		}
> +
> +		/* lower clock  */
> +		eepcr &= ~EEPCR_EESCK;
> +
> +		mutex_lock(&ks->lock);
> +		ks8851_wrreg16(ks, KS_EEPCR, eepcr);
> +		mutex_unlock(&ks->lock);
> +
> +		/* wait period / 2 */
> +		udelay(EEPROM_SK_PERIOD / 2);
> +
> +		/* rising clock period starts... */
> +
> +		/* raise clock */
> +		eepcr |= EEPCR_EESCK;
> +		mutex_lock(&ks->lock);
> +		ks8851_wrreg16(ks, KS_EEPCR, eepcr);
> +		mutex_unlock(&ks->lock);
> +
> +		/* 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);
> +
> +}
> +
>  /* ethtool support */
>  
>  static void ks8851_get_drvinfo(struct net_device *dev,
> diff --git a/drivers/net/ks8851.h b/drivers/net/ks8851.h
> index f52c312..537fb06 100644
> --- a/drivers/net/ks8851.h
> +++ b/drivers/net/ks8851.h
> @@ -25,12 +25,24 @@
>  #define OBCR_ODS_16mA				(1 << 6)
>  
>  #define KS_EEPCR				0x22
> +#define EEPCR_EESRWA				(1 << 5)
>  #define EEPCR_EESA				(1 << 4)
> -#define EEPCR_EESB				(1 << 3)
> +#define EEPCR_EESB_OFFSET			3
> +#define EEPCR_EESB				(1 << EEPCR_EESB_OFFSET)
>  #define EEPCR_EEDO				(1 << 2)
>  #define EEPCR_EESCK				(1 << 1)
>  #define EEPCR_EECS				(1 << 0)
>  
> +#define EEPROM_OP_LEN				3	/* bits:*/
> +#define EEPROM_OP_READ				0x06
> +#define EEPROM_OP_EWEN				0x04
> +#define EEPROM_OP_WRITE				0x05
> +#define EEPROM_OP_EWDS				0x14
> +
> +#define EEPROM_DATA_LEN				16	/* 16 bits EEPROM */
> +#define EEPROM_WRITE_TIME			4	/* wrt ack time in ms */
> +#define EEPROM_SK_PERIOD			400	/* in us */
> +
>  #define KS_MBIR					0x24
>  #define MBIR_TXMBF				(1 << 12)
>  #define MBIR_TXMBFA				(1 << 11)
> -- 
> 1.6.3.3
> 

-- 
-- 
Ben

Q:      What's a light-year?
A:      One-third less calories than a regular year.


  parent reply	other threads:[~2010-05-11  1:16 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-05-05 18:45 [PATCH 0/4 v2] ks8851: support for read/write MAC address from eeprom Sebastien Jan
2010-05-05 18:45 ` [PATCH 1/4 v2] ks8851: Add caching of CCR register Sebastien Jan
2010-05-06  7:20   ` David Miller
2010-05-05 18:45 ` [PATCH 2/4 v2] ks8851: Low level functions for read/write to companion eeprom Sebastien Jan
2010-05-06  7:20   ` David Miller
2010-05-11  1:23     ` Ben Dooks
2010-05-11  5:59       ` David Miller
2010-05-11  1:16   ` Ben Dooks [this message]
2010-05-05 18:45 ` [PATCH 3/4 v2] ks8851: companion eeprom access through ethtool Sebastien Jan
2010-05-06  7:20   ` David Miller
2010-05-05 18:45 ` [PATCH 4/4 v2] ks8851: read/write MAC address on companion eeprom through debugfs Sebastien Jan
2010-05-06  7:25   ` David Miller
2010-05-06  8:01     ` Sebastien Jan

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=20100511011638.GI2589@trinity.fluff.org \
    --to=ben-linux@fluff.org \
    --cc=Tristram.Ha@micrel.com \
    --cc=linux-omap@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=s-jan@ti.com \
    --cc=x0066660@ti.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.