Browse Source

rtl8366_smi: implement a function for detecting whether the attached switch is RTL8366S or RTL8366RB

SVN-Revision: 27755
Felix Fietkau 14 years ago
parent
commit
5b32d62fcf

+ 69 - 11
target/linux/generic/files/drivers/net/phy/rtl8366_smi.c

@@ -15,6 +15,7 @@
 #include <linux/gpio.h>
 #include <linux/spinlock.h>
 #include <linux/skbuff.h>
+#include <linux/rtl8366.h>
 
 #ifdef CONFIG_RTL8366S_PHY_DEBUG_FS
 #include <linux/debugfs.h>
@@ -1160,27 +1161,86 @@ struct rtl8366_smi *rtl8366_smi_alloc(struct device *parent)
 }
 EXPORT_SYMBOL_GPL(rtl8366_smi_alloc);
 
-int rtl8366_smi_init(struct rtl8366_smi *smi)
+static int __rtl8366_smi_init(struct rtl8366_smi *smi, const char *name)
 {
 	int err;
 
-	if (!smi->ops)
-		return -EINVAL;
-
-	err = gpio_request(smi->gpio_sda, dev_name(smi->parent));
+	err = gpio_request(smi->gpio_sda, name);
 	if (err) {
-		dev_err(smi->parent, "gpio_request failed for %u, err=%d\n",
+		printk(KERN_ERR "rtl8366_smi: gpio_request failed for %u, err=%d\n",
 			smi->gpio_sda, err);
 		goto err_out;
 	}
 
-	err = gpio_request(smi->gpio_sck, dev_name(smi->parent));
+	err = gpio_request(smi->gpio_sck, name);
 	if (err) {
-		dev_err(smi->parent, "gpio_request failed for %u, err=%d\n",
+		printk(KERN_ERR "rtl8366_smi: gpio_request failed for %u, err=%d\n",
 			smi->gpio_sck, err);
 		goto err_free_sda;
 	}
 
+	spin_lock_init(&smi->lock);
+	return 0;
+
+ err_free_sda:
+	gpio_free(smi->gpio_sda);
+ err_out:
+	return err;
+}
+
+static void __rtl8366_smi_cleanup(struct rtl8366_smi *smi)
+{
+	gpio_free(smi->gpio_sck);
+	gpio_free(smi->gpio_sda);
+}
+
+enum rtl8366_type rtl8366_smi_detect(struct rtl8366_platform_data *pdata)
+{
+	static struct rtl8366_smi smi;
+	enum rtl8366_type type = RTL8366_TYPE_UNKNOWN;
+	u32 reg = 0;
+
+	memset(&smi, 0, sizeof(smi));
+	smi.gpio_sda = pdata->gpio_sda;
+	smi.gpio_sck = pdata->gpio_sck;
+
+	if (__rtl8366_smi_init(&smi, "rtl8366"))
+		goto out;
+
+	if (rtl8366_smi_read_reg(&smi, 0x5c, &reg))
+		goto cleanup;
+
+	switch(reg) {
+	case 0x6027:
+		printk("Found an RTL8366S switch\n");
+		type = RTL8366_TYPE_S;
+		break;
+	case 0x5937:
+		printk("Found an RTL8366RB switch\n");
+		type = RTL8366_TYPE_RB;
+		break;
+	default:
+		printk("Found an Unknown RTL8366 switch (id=0x%04x)\n", reg);
+		break;
+	}
+
+cleanup:
+	__rtl8366_smi_cleanup(&smi);
+out:
+	return type;
+}
+
+int rtl8366_smi_init(struct rtl8366_smi *smi)
+{
+	int err;
+
+	if (!smi->ops)
+		return -EINVAL;
+
+	err = __rtl8366_smi_init(smi, dev_name(smi->parent));
+	if (err)
+		goto err_out;
+
 	spin_lock_init(&smi->lock);
 
 	dev_info(smi->parent, "using GPIO pins %u (SDA) and %u (SCK)\n",
@@ -1218,9 +1278,7 @@ int rtl8366_smi_init(struct rtl8366_smi *smi)
 	return 0;
 
  err_free_sck:
-	gpio_free(smi->gpio_sck);
- err_free_sda:
-	gpio_free(smi->gpio_sda);
+	__rtl8366_smi_cleanup(smi);
  err_out:
 	return err;
 }

+ 8 - 0
target/linux/generic/files/include/linux/rtl8366.h

@@ -15,6 +15,12 @@
 #define RTL8366S_DRIVER_NAME	"rtl8366s"
 #define RTL8366RB_DRIVER_NAME	"rtl8366rb"
 
+enum rtl8366_type {
+	RTL8366_TYPE_UNKNOWN,
+	RTL8366_TYPE_S,
+	RTL8366_TYPE_RB,
+};
+
 struct rtl8366_initval {
 	unsigned	reg;
 	u16		val;
@@ -27,4 +33,6 @@ struct rtl8366_platform_data {
 	struct rtl8366_initval *initvals;
 };
 
+enum rtl8366_type rtl8366_smi_detect(struct rtl8366_platform_data *pdata);
+
 #endif /*  _RTL8366_H */