Commit 2abe361c03b43e6dcf68f54e96b5c05156c49284

Authored by Andy Fleming
Committed by Ben Warren
1 parent 75b9d4ae0d

Add SGMII support to the tsec

Adds support for configuring the TBI to talk properly with the SerDes.

Signed-off-by: Andy Fleming <afleming@freescale.com>
Signed-off-by: Ben Warren <biggerbadderben@gmail.com>

Showing 2 changed files with 72 additions and 27 deletions Side-by-side Diff

... ... @@ -216,62 +216,81 @@
216 216 return (priv->link ? 0 : -1);
217 217 }
218 218  
219   -/* Write value to the device's PHY through the registers
220   - * specified in priv, modifying the register specified in regnum.
221   - * It will wait for the write to be done (or for a timeout to
222   - * expire) before exiting
223   - */
224   -void write_any_phy_reg(struct tsec_private *priv, uint phyid, uint regnum, uint value)
  219 +/* Writes the given phy's reg with value, using the specified MDIO regs */
  220 +static void tsec_local_mdio_write(volatile tsec_t *phyregs, uint addr,
  221 + uint reg, uint value)
225 222 {
226   - volatile tsec_t *regbase = priv->phyregs;
227 223 int timeout = 1000000;
228 224  
229   - regbase->miimadd = (phyid << 8) | regnum;
230   - regbase->miimcon = value;
  225 + phyregs->miimadd = (addr << 8) | reg;
  226 + phyregs->miimcon = value;
231 227 asm("sync");
232 228  
233 229 timeout = 1000000;
234   - while ((regbase->miimind & MIIMIND_BUSY) && timeout--) ;
  230 + while ((phyregs->miimind & MIIMIND_BUSY) && timeout--) ;
235 231 }
236 232  
237   -/* #define to provide old write_phy_reg functionality without duplicating code */
238   -#define write_phy_reg(priv, regnum, value) write_any_phy_reg(priv,priv->phyaddr,regnum,value)
239 233  
  234 +/* Provide the default behavior of writing the PHY of this ethernet device */
  235 +#define write_phy_reg(priv, regnum, value) tsec_local_mdio_write(priv->phyregs,priv->phyaddr,regnum,value)
  236 +
240 237 /* Reads register regnum on the device's PHY through the
241   - * registers specified in priv. It lowers and raises the read
  238 + * specified registers. It lowers and raises the read
242 239 * command, and waits for the data to become valid (miimind
243 240 * notvalid bit cleared), and the bus to cease activity (miimind
244 241 * busy bit cleared), and then returns the value
245 242 */
246   -uint read_any_phy_reg(struct tsec_private *priv, uint phyid, uint regnum)
  243 +uint tsec_local_mdio_read(volatile tsec_t *phyregs, uint phyid, uint regnum)
247 244 {
248 245 uint value;
249   - volatile tsec_t *regbase = priv->phyregs;
250 246  
251 247 /* Put the address of the phy, and the register
252 248 * number into MIIMADD */
253   - regbase->miimadd = (phyid << 8) | regnum;
  249 + phyregs->miimadd = (phyid << 8) | regnum;
254 250  
255 251 /* Clear the command register, and wait */
256   - regbase->miimcom = 0;
  252 + phyregs->miimcom = 0;
257 253 asm("sync");
258 254  
259 255 /* Initiate a read command, and wait */
260   - regbase->miimcom = MIIM_READ_COMMAND;
  256 + phyregs->miimcom = MIIM_READ_COMMAND;
261 257 asm("sync");
262 258  
263 259 /* Wait for the the indication that the read is done */
264   - while ((regbase->miimind & (MIIMIND_NOTVALID | MIIMIND_BUSY))) ;
  260 + while ((phyregs->miimind & (MIIMIND_NOTVALID | MIIMIND_BUSY))) ;
265 261  
266 262 /* Grab the value read from the PHY */
267   - value = regbase->miimstat;
  263 + value = phyregs->miimstat;
268 264  
269 265 return value;
270 266 }
271 267  
272 268 /* #define to provide old read_phy_reg functionality without duplicating code */
273   -#define read_phy_reg(priv,regnum) read_any_phy_reg(priv,priv->phyaddr,regnum)
  269 +#define read_phy_reg(priv,regnum) tsec_local_mdio_read(priv->phyregs,priv->phyaddr,regnum)
274 270  
  271 +#define TBIANA_SETTINGS ( \
  272 + TBIANA_ASYMMETRIC_PAUSE \
  273 + | TBIANA_SYMMETRIC_PAUSE \
  274 + | TBIANA_FULL_DUPLEX \
  275 + )
  276 +
  277 +#define TBICR_SETTINGS ( \
  278 + TBICR_PHY_RESET \
  279 + | TBICR_ANEG_ENABLE \
  280 + | TBICR_FULL_DUPLEX \
  281 + | TBICR_SPEED1_SET \
  282 + )
  283 +/* Configure the TBI for SGMII operation */
  284 +static void tsec_configure_serdes(struct tsec_private *priv)
  285 +{
  286 + tsec_local_mdio_write(priv->phyregs, CFG_TBIPA_VALUE, TBI_ANA,
  287 + TBIANA_SETTINGS);
  288 + tsec_local_mdio_write(priv->phyregs, CFG_TBIPA_VALUE, TBI_TBICON,
  289 + TBICON_CLK_SELECT);
  290 + tsec_local_mdio_write(priv->phyregs, CFG_TBIPA_VALUE, TBI_CR,
  291 + TBICR_SETTINGS);
  292 +}
  293 +
275 294 /* Discover which PHY is attached to the device, and configure it
276 295 * properly. If the PHY is not recognized, then return 0
277 296 * (failure). Otherwise, return 1
278 297  
... ... @@ -280,12 +299,12 @@
280 299 {
281 300 struct tsec_private *priv = (struct tsec_private *)dev->priv;
282 301 struct phy_info *curphy;
283   - volatile tsec_t *regs = (volatile tsec_t *)(TSEC_BASE_ADDR);
  302 + volatile tsec_t *phyregs = priv->phyregs;
  303 + volatile tsec_t *regs = priv->regs;
284 304  
285 305 /* Assign a Physical address to the TBI */
286 306 regs->tbipa = CFG_TBIPA_VALUE;
287   - regs = (volatile tsec_t *)(TSEC_BASE_ADDR + TSEC_SIZE);
288   - regs->tbipa = CFG_TBIPA_VALUE;
  307 + phyregs->tbipa = CFG_TBIPA_VALUE;
289 308 asm("sync");
290 309  
291 310 /* Reset MII (due to new addresses) */
... ... @@ -309,6 +328,9 @@
309 328 return 0;
310 329 }
311 330  
  331 + if (regs->ecntrl & ECNTRL_SGMII_MODE)
  332 + tsec_configure_serdes(priv);
  333 +
312 334 priv->phyinfo = curphy;
313 335  
314 336 phy_run_commands(priv, priv->phyinfo->config);
... ... @@ -1700,7 +1722,7 @@
1700 1722 return -1;
1701 1723 }
1702 1724  
1703   - ret = (unsigned short)read_any_phy_reg(priv, addr, reg);
  1725 + ret = (unsigned short)tsec_local_mdio_read(priv->phyregs, addr, reg);
1704 1726 *value = ret;
1705 1727  
1706 1728 return 0;
... ... @@ -1722,7 +1744,7 @@
1722 1744 return -1;
1723 1745 }
1724 1746  
1725   - write_any_phy_reg(priv, addr, reg, value);
  1747 + tsec_local_mdio_write(priv->phyregs, addr, reg, value);
1726 1748  
1727 1749 return 0;
1728 1750 }
... ... @@ -60,6 +60,27 @@
60 60  
61 61 #define PHY_AUTONEGOTIATE_TIMEOUT 5000 /* in ms */
62 62  
  63 +/* TBI register addresses */
  64 +#define TBI_CR 0x00
  65 +#define TBI_SR 0x01
  66 +#define TBI_ANA 0x04
  67 +#define TBI_ANLPBPA 0x05
  68 +#define TBI_ANEX 0x06
  69 +#define TBI_TBICON 0x11
  70 +
  71 +/* TBI MDIO register bit fields*/
  72 +#define TBICON_CLK_SELECT 0x0020
  73 +#define TBIANA_ASYMMETRIC_PAUSE 0x0100
  74 +#define TBIANA_SYMMETRIC_PAUSE 0x0080
  75 +#define TBIANA_HALF_DUPLEX 0x0040
  76 +#define TBIANA_FULL_DUPLEX 0x0020
  77 +#define TBICR_PHY_RESET 0x8000
  78 +#define TBICR_ANEG_ENABLE 0x1000
  79 +#define TBICR_RESTART_ANEG 0x0200
  80 +#define TBICR_FULL_DUPLEX 0x0100
  81 +#define TBICR_SPEED1_SET 0x0040
  82 +
  83 +
63 84 /* MAC register bits */
64 85 #define MACCFG1_SOFT_RESET 0x80000000
65 86 #define MACCFG1_RESET_RX_MC 0x00080000
... ... @@ -540,7 +561,9 @@
540 561  
541 562 /* This flag currently only has
542 563 * meaning if we're using the eTSEC */
543   -#define TSEC_REDUCED (1 << 1)
  564 +#define TSEC_REDUCED (1 << 1)
  565 +
  566 +#define TSEC_SGMII (1 << 2)
544 567  
545 568 struct tsec_private {
546 569 volatile tsec_t *regs;