[2/3] dm9601: manage eeprom to assure the chip for correct operation
diff mbox series

Message ID 1457609038-3636-1-git-send-email-josright123@gmail.com
State New, archived
Headers show
Series
  • [1/3] dm9601: enable EP3 interrupt
Related show

Commit Message

Joseph CHANG March 10, 2016, 11:23 a.m. UTC
Add to maintain variant eeprom adapters which may have not right
dm962x's format.

Signed-off-by: Joseph CHANG <josright123@gmail.com>
---
 drivers/net/usb/dm9601.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

Comments

Peter Korsgaard March 10, 2016, 6:36 p.m. UTC | #1
>>>>> "Joseph" == Joseph CHANG <josright123@gmail.com> writes:

 > Add to maintain variant eeprom adapters which may have not right
 > dm962x's format.

 > Signed-off-by: Joseph CHANG <josright123@gmail.com>

> +static void dm_render_begin(struct usbnet *dev)
 > +{
 > +	/* Render eeprom if need, WORD3 render, set D[15:14] 01b */
 > +	dm_eeprom_render(dev, 3, 0x4000, 0xc000);
 > +	/* Render eeprom if need, WORD7 render, clear D[10] */
 > +	dm_eeprom_render(dev, 7, 0x0000, 0x0400);
 > +	/* Render eeprom if need, WORD11 render, need 0x005a */
 > +	dm_eeprom_render(dev, 11, 0x005a, 0xffff);
 > +	/* Render eeprom if need, WORD12 render, need 0x0007 */
 > +	dm_eeprom_render(dev, 12, DM_EP3I_VAL, 0xffff);

With render I guess you mean something like fixup? I'm not sure we want
to do this automatically without an explicit action from the user.

How common are these adapters without valid eeprom? What happens if the
eeprom content isn't fixed?

Do we need to reset the device once the eeprom is updated?
Joseph Chang March 11, 2016, 10:56 a.m. UTC | #2
Yes, this is to fixup purpose.

My customer buy "net101 USB20" netcards,
It was manifactured by some company and in the market.
We find it can not work due to eeprom wrong.

This fixup make it correct.
I focus on the essential eeprom words only.
Yes, need to reset the device once the eeprom is updated.
(I don't know how to let the device reset by software ?
 Only un-plug and then plug the device.)

Best Regards,
Joseph CHANG
System Application Engineering Division
Davicom Semiconductor, Inc.
No. 6 Li-Hsin 6th Rd., Science-Based Park,
Hsin-Chu, Taiwan.
Tel: 886-3-5798797 Ex 8534
Fax: 886-3-5646929
Web: http://www.davicom.com.tw


-----Original Message-----
From: Peter Korsgaard [mailto:jacmet@gmail.com] On Behalf Of Peter Korsgaard
Sent: Friday, March 11, 2016 2:37 AM
To: Joseph CHANG
Cc: Peter Korsgaard; netdev@vger.kernel.org; linux-usb@vger.kernel.org;
linux-kernel@vger.kernel.org; Joseph Chang
Subject: Re: [PATCH 2/3] dm9601: manage eeprom to assure the chip for correct
operation

>>>>> "Joseph" == Joseph CHANG <josright123@gmail.com> writes:

 > Add to maintain variant eeprom adapters which may have not right
 > dm962x's format.

 > Signed-off-by: Joseph CHANG <josright123@gmail.com>

> +static void dm_render_begin(struct usbnet *dev)
 > +{
 > +	/* Render eeprom if need, WORD3 render, set D[15:14] 01b */
 > +	dm_eeprom_render(dev, 3, 0x4000, 0xc000);
 > +	/* Render eeprom if need, WORD7 render, clear D[10] */
 > +	dm_eeprom_render(dev, 7, 0x0000, 0x0400);
 > +	/* Render eeprom if need, WORD11 render, need 0x005a */
 > +	dm_eeprom_render(dev, 11, 0x005a, 0xffff);
 > +	/* Render eeprom if need, WORD12 render, need 0x0007 */
 > +	dm_eeprom_render(dev, 12, DM_EP3I_VAL, 0xffff);

With render I guess you mean something like fixup? I'm not sure we want
to do this automatically without an explicit action from the user.

How common are these adapters without valid eeprom? What happens if the
eeprom content isn't fixed?

Do we need to reset the device once the eeprom is updated?

Patch
diff mbox series

diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c
index 520de4f..50095df 100644
--- a/drivers/net/usb/dm9601.c
+++ b/drivers/net/usb/dm9601.c
@@ -60,6 +60,7 @@ 
 #define DM_TX_OVERHEAD	2	/* 2 byte header */
 #define DM_RX_OVERHEAD	7	/* 3 byte header + 4 byte crc tail */
 #define DM_TIMEOUT	1000
+#define	DM_EP3I_VAL	0x07
 
 static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data)
 {
@@ -193,6 +194,75 @@  static int dm_read_eeprom_word(struct usbnet *dev, u8 offset, void *value)
 	return dm_read_shared_word(dev, 0, offset, value);
 }
 
+static void dm_write_eeprom_word(struct usbnet *dev, u8 offset, __le16 data)
+{
+	dm_write_shared_word(dev, 0, offset, data);
+}
+
+static int dm_render_write(struct usbnet *dev, u8 wordoffset, u16 mask_word,
+			   u16 orset_word, u16 *pmd)
+{
+	u16 srom;
+
+	dm_read_eeprom_word(dev, wordoffset, &srom);
+	if ((srom & mask_word) == orset_word)
+		return 0;
+
+	srom &= ~mask_word;
+	srom |= orset_word;
+
+	dm_write_eeprom_word(dev, wordoffset, srom);
+	*pmd = srom;
+	return 1;
+}
+
+static void dm_render_report(struct usbnet *dev, u8 wordoffset, u16 md)
+{
+	int i = 0;
+	u16 srom;
+
+	do {
+		i++;
+		usleep_range(100, 200);
+		dm_read_eeprom_word(dev, wordoffset, &srom);
+		if (i == 8)
+			break;
+	} while (srom != md);
+
+	if (srom == md) {
+		netdev_info(dev->net, "set eeprom word%d 0x%04x\n",
+			    wordoffset, md);
+	} else {
+		netdev_info(dev->net, "warning - set eeprom word%d 0x%04x\n",
+			    wordoffset, md);
+		netdev_info(dev->net, "warning - fail as eeprom word%d 0x%04x\n",
+			    wordoffset, srom);
+	}
+}
+
+static void dm_eeprom_render(struct usbnet *dev, u8 wordoffset,
+			     u16 orset_word, u16 mask_word)
+{
+	u16 m;
+
+	if (!dm_render_write(dev, wordoffset, mask_word, orset_word, &m))
+		return;
+
+	dm_render_report(dev, wordoffset, m);
+}
+
+static void dm_render_begin(struct usbnet *dev)
+{
+	/* Render eeprom if need, WORD3 render, set D[15:14] 01b */
+	dm_eeprom_render(dev, 3, 0x4000, 0xc000);
+	/* Render eeprom if need, WORD7 render, clear D[10] */
+	dm_eeprom_render(dev, 7, 0x0000, 0x0400);
+	/* Render eeprom if need, WORD11 render, need 0x005a */
+	dm_eeprom_render(dev, 11, 0x005a, 0xffff);
+	/* Render eeprom if need, WORD12 render, need 0x0007 */
+	dm_eeprom_render(dev, 12, DM_EP3I_VAL, 0xffff);
+}
+
 
 
 static int dm9601_get_eeprom_len(struct net_device *dev)
@@ -420,6 +490,8 @@  static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)
 
 		/* Always return 8-bytes data to host per interrupt-interval */
 		dm_write_reg(dev, DM_USB_CTRL, USB_CTRL_EP3ACK);
+
+		dm_render_begin(dev);
 	}
 
 	/* power up phy */