icplus.c (f7e290fbeb336421ba6237548b693c9afb4d75fa) | icplus.c (f2f1a847e74f61fb151e0f6f689a8485345ed1fc) |
---|---|
1/* 2 * Driver for ICPlus PHYs 3 * 4 * Copyright (c) 2007 Freescale Semiconductor, Inc. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; either version 2 of the License, or (at your --- 11 unchanged lines hidden (view full) --- 20#include <linux/etherdevice.h> 21#include <linux/skbuff.h> 22#include <linux/spinlock.h> 23#include <linux/mm.h> 24#include <linux/module.h> 25#include <linux/mii.h> 26#include <linux/ethtool.h> 27#include <linux/phy.h> | 1/* 2 * Driver for ICPlus PHYs 3 * 4 * Copyright (c) 2007 Freescale Semiconductor, Inc. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; either version 2 of the License, or (at your --- 11 unchanged lines hidden (view full) --- 20#include <linux/etherdevice.h> 21#include <linux/skbuff.h> 22#include <linux/spinlock.h> 23#include <linux/mm.h> 24#include <linux/module.h> 25#include <linux/mii.h> 26#include <linux/ethtool.h> 27#include <linux/phy.h> |
28#include <linux/property.h> |
|
28 29#include <asm/io.h> 30#include <asm/irq.h> 31#include <linux/uaccess.h> 32 33MODULE_DESCRIPTION("ICPlus IP175C/IP101A/IP101G/IC1001 PHY drivers"); 34MODULE_AUTHOR("Michael Barkowski"); 35MODULE_LICENSE("GPL"); --- 7 unchanged lines hidden (view full) --- 43#define IP101A_G_APS_ON BIT(1) /* IP101A/G APS Mode bit */ 44#define IP101A_G_IRQ_CONF_STATUS 0x11 /* Conf Info IRQ & Status Reg */ 45#define IP101A_G_IRQ_PIN_USED BIT(15) /* INTR pin used */ 46#define IP101A_G_IRQ_ALL_MASK BIT(11) /* IRQ's inactive */ 47#define IP101A_G_IRQ_SPEED_CHANGE BIT(2) 48#define IP101A_G_IRQ_DUPLEX_CHANGE BIT(1) 49#define IP101A_G_IRQ_LINK_CHANGE BIT(0) 50 | 29 30#include <asm/io.h> 31#include <asm/irq.h> 32#include <linux/uaccess.h> 33 34MODULE_DESCRIPTION("ICPlus IP175C/IP101A/IP101G/IC1001 PHY drivers"); 35MODULE_AUTHOR("Michael Barkowski"); 36MODULE_LICENSE("GPL"); --- 7 unchanged lines hidden (view full) --- 44#define IP101A_G_APS_ON BIT(1) /* IP101A/G APS Mode bit */ 45#define IP101A_G_IRQ_CONF_STATUS 0x11 /* Conf Info IRQ & Status Reg */ 46#define IP101A_G_IRQ_PIN_USED BIT(15) /* INTR pin used */ 47#define IP101A_G_IRQ_ALL_MASK BIT(11) /* IRQ's inactive */ 48#define IP101A_G_IRQ_SPEED_CHANGE BIT(2) 49#define IP101A_G_IRQ_DUPLEX_CHANGE BIT(1) 50#define IP101A_G_IRQ_LINK_CHANGE BIT(0) 51 |
52#define IP101G_DIGITAL_IO_SPEC_CTRL 0x1d 53#define IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32 BIT(2) 54 55/* The 32-pin IP101GR package can re-configure the mode of the RXER/INTR_32 pin 56 * (pin number 21). The hardware default is RXER (receive error) mode. But it 57 * can be configured to interrupt mode manually. 58 */ 59enum ip101gr_sel_intr32 { 60 IP101GR_SEL_INTR32_KEEP, 61 IP101GR_SEL_INTR32_INTR, 62 IP101GR_SEL_INTR32_RXER, 63}; 64 65struct ip101a_g_phy_priv { 66 enum ip101gr_sel_intr32 sel_intr32; 67}; 68 |
|
51static int ip175c_config_init(struct phy_device *phydev) 52{ 53 int err, i; 54 static int full_reset_performed; 55 56 if (full_reset_performed == 0) { 57 58 /* master reset */ --- 120 unchanged lines hidden (view full) --- 179static int ip175c_config_aneg(struct phy_device *phydev) 180{ 181 if (phydev->mdio.addr == 4) /* WAN port */ 182 genphy_config_aneg(phydev); 183 184 return 0; 185} 186 | 69static int ip175c_config_init(struct phy_device *phydev) 70{ 71 int err, i; 72 static int full_reset_performed; 73 74 if (full_reset_performed == 0) { 75 76 /* master reset */ --- 120 unchanged lines hidden (view full) --- 197static int ip175c_config_aneg(struct phy_device *phydev) 198{ 199 if (phydev->mdio.addr == 4) /* WAN port */ 200 genphy_config_aneg(phydev); 201 202 return 0; 203} 204 |
205static int ip101a_g_probe(struct phy_device *phydev) 206{ 207 struct device *dev = &phydev->mdio.dev; 208 struct ip101a_g_phy_priv *priv; 209 210 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 211 if (!priv) 212 return -ENOMEM; 213 214 /* Both functions (RX error and interrupt status) are sharing the same 215 * pin on the 32-pin IP101GR, so this is an exclusive choice. 216 */ 217 if (device_property_read_bool(dev, "icplus,select-rx-error") && 218 device_property_read_bool(dev, "icplus,select-interrupt")) { 219 dev_err(dev, 220 "RXER and INTR mode cannot be selected together\n"); 221 return -EINVAL; 222 } 223 224 if (device_property_read_bool(dev, "icplus,select-rx-error")) 225 priv->sel_intr32 = IP101GR_SEL_INTR32_RXER; 226 else if (device_property_read_bool(dev, "icplus,select-interrupt")) 227 priv->sel_intr32 = IP101GR_SEL_INTR32_INTR; 228 else 229 priv->sel_intr32 = IP101GR_SEL_INTR32_KEEP; 230 231 phydev->priv = priv; 232 233 return 0; 234} 235 |
|
187static int ip101a_g_config_init(struct phy_device *phydev) 188{ | 236static int ip101a_g_config_init(struct phy_device *phydev) 237{ |
189 int c; | 238 struct ip101a_g_phy_priv *priv = phydev->priv; 239 int err, c; |
190 191 c = ip1xx_reset(phydev); 192 if (c < 0) 193 return c; 194 | 240 241 c = ip1xx_reset(phydev); 242 if (c < 0) 243 return c; 244 |
245 /* configure the RXER/INTR_32 pin of the 32-pin IP101GR if needed: */ 246 switch (priv->sel_intr32) { 247 case IP101GR_SEL_INTR32_RXER: 248 err = phy_modify(phydev, IP101G_DIGITAL_IO_SPEC_CTRL, 249 IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32, 0); 250 if (err < 0) 251 return err; 252 break; 253 254 case IP101GR_SEL_INTR32_INTR: 255 err = phy_modify(phydev, IP101G_DIGITAL_IO_SPEC_CTRL, 256 IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32, 257 IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32); 258 if (err < 0) 259 return err; 260 break; 261 262 default: 263 /* Don't touch IP101G_DIGITAL_IO_SPEC_CTRL because it's not 264 * documented on IP101A and it's not clear whether this would 265 * cause problems. 266 * For the 32-pin IP101GR we simply keep the SEL_INTR32 267 * configuration as set by the bootloader when not configured 268 * to one of the special functions. 269 */ 270 break; 271 } 272 |
|
195 /* Enable Auto Power Saving mode */ 196 c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS); 197 c |= IP101A_G_APS_ON; 198 199 return phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c); 200} 201 202static int ip101a_g_config_intr(struct phy_device *phydev) --- 49 unchanged lines hidden (view full) --- 252 .config_init = &ip1001_config_init, 253 .suspend = genphy_suspend, 254 .resume = genphy_resume, 255}, { 256 .phy_id = 0x02430c54, 257 .name = "ICPlus IP101A/G", 258 .phy_id_mask = 0x0ffffff0, 259 .features = PHY_BASIC_FEATURES, | 273 /* Enable Auto Power Saving mode */ 274 c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS); 275 c |= IP101A_G_APS_ON; 276 277 return phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c); 278} 279 280static int ip101a_g_config_intr(struct phy_device *phydev) --- 49 unchanged lines hidden (view full) --- 330 .config_init = &ip1001_config_init, 331 .suspend = genphy_suspend, 332 .resume = genphy_resume, 333}, { 334 .phy_id = 0x02430c54, 335 .name = "ICPlus IP101A/G", 336 .phy_id_mask = 0x0ffffff0, 337 .features = PHY_BASIC_FEATURES, |
338 .probe = ip101a_g_probe, |
|
260 .config_intr = ip101a_g_config_intr, 261 .did_interrupt = ip101a_g_did_interrupt, 262 .ack_interrupt = ip101a_g_ack_interrupt, 263 .config_init = &ip101a_g_config_init, 264 .suspend = genphy_suspend, 265 .resume = genphy_resume, 266} }; 267 268module_phy_driver(icplus_driver); 269 270static struct mdio_device_id __maybe_unused icplus_tbl[] = { 271 { 0x02430d80, 0x0ffffff0 }, 272 { 0x02430d90, 0x0ffffff0 }, 273 { 0x02430c54, 0x0ffffff0 }, 274 { } 275}; 276 277MODULE_DEVICE_TABLE(mdio, icplus_tbl); | 339 .config_intr = ip101a_g_config_intr, 340 .did_interrupt = ip101a_g_did_interrupt, 341 .ack_interrupt = ip101a_g_ack_interrupt, 342 .config_init = &ip101a_g_config_init, 343 .suspend = genphy_suspend, 344 .resume = genphy_resume, 345} }; 346 347module_phy_driver(icplus_driver); 348 349static struct mdio_device_id __maybe_unused icplus_tbl[] = { 350 { 0x02430d80, 0x0ffffff0 }, 351 { 0x02430d90, 0x0ffffff0 }, 352 { 0x02430c54, 0x0ffffff0 }, 353 { } 354}; 355 356MODULE_DEVICE_TABLE(mdio, icplus_tbl); |