aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/icplus.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy/icplus.c')
-rw-r--r--drivers/net/phy/icplus.c67
1 files changed, 54 insertions, 13 deletions
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
index bc2b58061507..f98edd66cdd2 100644
--- a/drivers/net/phy/icplus.c
+++ b/drivers/net/phy/icplus.c
@@ -49,6 +49,8 @@ MODULE_LICENSE("GPL");
#define IP101G_DIGITAL_IO_SPEC_CTRL 0x1d
#define IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32 BIT(2)
+#define IP101G_DEFAULT_PAGE 16
+
#define IP175C_PHY_ID 0x02430d80
#define IP1001_PHY_ID 0x02430d90
#define IP101A_PHY_ID 0x02430c54
@@ -211,23 +213,27 @@ static int ip101a_g_probe(struct phy_device *phydev)
static int ip101a_g_config_intr_pin(struct phy_device *phydev)
{
struct ip101a_g_phy_priv *priv = phydev->priv;
- int err;
+ int oldpage, err = 0;
+
+ oldpage = phy_select_page(phydev, IP101G_DEFAULT_PAGE);
+ if (oldpage < 0)
+ return oldpage;
/* configure the RXER/INTR_32 pin of the 32-pin IP101GR if needed: */
switch (priv->sel_intr32) {
case IP101GR_SEL_INTR32_RXER:
- err = phy_modify(phydev, IP101G_DIGITAL_IO_SPEC_CTRL,
- IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32, 0);
+ err = __phy_modify(phydev, IP101G_DIGITAL_IO_SPEC_CTRL,
+ IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32, 0);
if (err < 0)
- return err;
+ goto out;
break;
case IP101GR_SEL_INTR32_INTR:
- err = phy_modify(phydev, IP101G_DIGITAL_IO_SPEC_CTRL,
- IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32,
- IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32);
+ err = __phy_modify(phydev, IP101G_DIGITAL_IO_SPEC_CTRL,
+ IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32,
+ IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32);
if (err < 0)
- return err;
+ goto out;
break;
default:
@@ -241,7 +247,8 @@ static int ip101a_g_config_intr_pin(struct phy_device *phydev)
break;
}
- return 0;
+out:
+ return phy_restore_page(phydev, oldpage, err);
}
static int ip101a_config_init(struct phy_device *phydev)
@@ -263,8 +270,10 @@ static int ip101g_config_init(struct phy_device *phydev)
static int ip101a_g_ack_interrupt(struct phy_device *phydev)
{
- int err = phy_read(phydev, IP101A_G_IRQ_CONF_STATUS);
+ int err;
+ err = phy_read_paged(phydev, IP101G_DEFAULT_PAGE,
+ IP101A_G_IRQ_CONF_STATUS);
if (err < 0)
return err;
@@ -283,10 +292,12 @@ static int ip101a_g_config_intr(struct phy_device *phydev)
/* INTR pin used: Speed/link/duplex will cause an interrupt */
val = IP101A_G_IRQ_PIN_USED;
- err = phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, val);
+ err = phy_write_paged(phydev, IP101G_DEFAULT_PAGE,
+ IP101A_G_IRQ_CONF_STATUS, val);
} else {
val = IP101A_G_IRQ_ALL_MASK;
- err = phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, val);
+ err = phy_write_paged(phydev, IP101G_DEFAULT_PAGE,
+ IP101A_G_IRQ_CONF_STATUS, val);
if (err)
return err;
@@ -300,7 +311,8 @@ static irqreturn_t ip101a_g_handle_interrupt(struct phy_device *phydev)
{
int irq_status;
- irq_status = phy_read(phydev, IP101A_G_IRQ_CONF_STATUS);
+ irq_status = phy_read_paged(phydev, IP101G_DEFAULT_PAGE,
+ IP101A_G_IRQ_CONF_STATUS);
if (irq_status < 0) {
phy_error(phydev);
return IRQ_NONE;
@@ -316,6 +328,31 @@ static irqreturn_t ip101a_g_handle_interrupt(struct phy_device *phydev)
return IRQ_HANDLED;
}
+/* The IP101A doesn't really have a page register. We just pretend to have one
+ * so we can use the paged versions of the callbacks of the IP101G.
+ */
+static int ip101a_read_page(struct phy_device *phydev)
+{
+ return IP101G_DEFAULT_PAGE;
+}
+
+static int ip101a_write_page(struct phy_device *phydev, int page)
+{
+ WARN_ONCE(page != IP101G_DEFAULT_PAGE, "wrong page selected\n");
+
+ return 0;
+}
+
+static int ip101g_read_page(struct phy_device *phydev)
+{
+ return __phy_read(phydev, IP101G_PAGE_CONTROL);
+}
+
+static int ip101g_write_page(struct phy_device *phydev, int page)
+{
+ return __phy_write(phydev, IP101G_PAGE_CONTROL, page);
+}
+
static int ip101a_g_has_page_register(struct phy_device *phydev)
{
int oldval, val, ret;
@@ -390,6 +427,8 @@ static struct phy_driver icplus_driver[] = {
.name = "ICPlus IP101A",
.match_phy_device = ip101a_match_phy_device,
.probe = ip101a_g_probe,
+ .read_page = ip101a_read_page,
+ .write_page = ip101a_write_page,
.config_intr = ip101a_g_config_intr,
.handle_interrupt = ip101a_g_handle_interrupt,
.config_init = ip101a_config_init,
@@ -400,6 +439,8 @@ static struct phy_driver icplus_driver[] = {
.name = "ICPlus IP101G",
.match_phy_device = ip101g_match_phy_device,
.probe = ip101a_g_probe,
+ .read_page = ip101g_read_page,
+ .write_page = ip101g_write_page,
.config_intr = ip101a_g_config_intr,
.handle_interrupt = ip101a_g_handle_interrupt,
.config_init = ip101g_config_init,