summaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/linux/generic/files/drivers/net/phy/rtl8366_smi.c80
-rw-r--r--target/linux/generic/files/include/linux/rtl8366.h8
2 files changed, 77 insertions, 11 deletions
diff --git a/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c b/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c
index 28e1a8505d..281c453670 100644
--- a/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c
+++ b/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,28 +1161,87 @@ 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",
smi->gpio_sda, smi->gpio_sck);
@@ -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;
}
diff --git a/target/linux/generic/files/include/linux/rtl8366.h b/target/linux/generic/files/include/linux/rtl8366.h
index 654d42e609..22ce614d40 100644
--- a/target/linux/generic/files/include/linux/rtl8366.h
+++ b/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 */