aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/atheros
diff options
context:
space:
mode:
authorHuang, Xiong <xiong@qca.qualcomm.com>2012-04-25 16:27:10 -0400
committerDavid S. Miller <davem@davemloft.net>2012-04-26 05:03:32 -0400
commit929a5e9318f090e190b67343fb37533e58aec3a3 (patch)
tree2f6deb2debeddcf83ecf1889e8eaed60b30fabcb /drivers/net/ethernet/atheros
parent8f33ab913456654b2bfc75b90893dce9561cab9a (diff)
atl1c: refine phy-register read/write function
phy register is read/write via MDIO control module --- that module will be affected by the hibernate status, to access phy regs in hib stutus, slow frequency clk must be selected. To access phy extension register, the MDIO related registers are refined/updated, a _core function is re-wroted for both regular PHY regs and extension regs. existing PHY r/w function is revised based on the _core. PHY extension registers will be used for the comming patches. Signed-off-by: xiong <xiong@qca.qualcomm.com> Tested-by: Liu David <dwliu@qca.qualcomm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/atheros')
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_hw.c189
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_hw.h65
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_main.c4
3 files changed, 197 insertions, 61 deletions
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
index bd1667cbffa..a17b5311dce 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
@@ -278,33 +278,158 @@ void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value)
278} 278}
279 279
280/* 280/*
281 * Reads the value from a PHY register 281 * wait mdio module be idle
282 * hw - Struct containing variables accessed by shared code 282 * return true: idle
283 * reg_addr - address of the PHY register to read 283 * false: still busy
284 */ 284 */
285int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data) 285bool atl1c_wait_mdio_idle(struct atl1c_hw *hw)
286{ 286{
287 u32 val; 287 u32 val;
288 int i; 288 int i;
289 289
290 val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT | 290 for (i = 0; i < MDIO_MAX_AC_TO; i++) {
291 MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW | 291 AT_READ_REG(hw, REG_MDIO_CTRL, &val);
292 MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT; 292 if (!(val & (MDIO_CTRL_BUSY | MDIO_CTRL_START)))
293 break;
294 udelay(10);
295 }
296
297 return i != MDIO_MAX_AC_TO;
298}
299
300void atl1c_stop_phy_polling(struct atl1c_hw *hw)
301{
302 if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION))
303 return;
304
305 AT_WRITE_REG(hw, REG_MDIO_CTRL, 0);
306 atl1c_wait_mdio_idle(hw);
307}
308
309void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel)
310{
311 u32 val;
293 312
313 if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION))
314 return;
315
316 val = MDIO_CTRL_SPRES_PRMBL |
317 FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
318 FIELDX(MDIO_CTRL_REG, 1) |
319 MDIO_CTRL_START |
320 MDIO_CTRL_OP_READ;
321 AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
322 atl1c_wait_mdio_idle(hw);
323 val |= MDIO_CTRL_AP_EN;
324 val &= ~MDIO_CTRL_START;
294 AT_WRITE_REG(hw, REG_MDIO_CTRL, val); 325 AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
326 udelay(30);
327}
295 328
296 for (i = 0; i < MDIO_WAIT_TIMES; i++) { 329
297 udelay(2); 330/*
298 AT_READ_REG(hw, REG_MDIO_CTRL, &val); 331 * atl1c_read_phy_core
299 if (!(val & (MDIO_START | MDIO_BUSY))) 332 * core funtion to read register in PHY via MDIO control regsiter.
300 break; 333 * ext: extension register (see IEEE 802.3)
334 * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0)
335 * reg: reg to read
336 */
337int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev,
338 u16 reg, u16 *phy_data)
339{
340 u32 val;
341 u16 clk_sel = MDIO_CTRL_CLK_25_4;
342
343 atl1c_stop_phy_polling(hw);
344
345 *phy_data = 0;
346
347 /* only l2c_b2 & l1d_2 could use slow clock */
348 if ((hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) &&
349 hw->hibernate)
350 clk_sel = MDIO_CTRL_CLK_25_128;
351 if (ext) {
352 val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg);
353 AT_WRITE_REG(hw, REG_MDIO_EXTN, val);
354 val = MDIO_CTRL_SPRES_PRMBL |
355 FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
356 MDIO_CTRL_START |
357 MDIO_CTRL_MODE_EXT |
358 MDIO_CTRL_OP_READ;
359 } else {
360 val = MDIO_CTRL_SPRES_PRMBL |
361 FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
362 FIELDX(MDIO_CTRL_REG, reg) |
363 MDIO_CTRL_START |
364 MDIO_CTRL_OP_READ;
301 } 365 }
302 if (!(val & (MDIO_START | MDIO_BUSY))) { 366 AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
303 *phy_data = (u16)val; 367
304 return 0; 368 if (!atl1c_wait_mdio_idle(hw))
369 return -1;
370
371 AT_READ_REG(hw, REG_MDIO_CTRL, &val);
372 *phy_data = (u16)FIELD_GETX(val, MDIO_CTRL_DATA);
373
374 atl1c_start_phy_polling(hw, clk_sel);
375
376 return 0;
377}
378
379/*
380 * atl1c_write_phy_core
381 * core funtion to write to register in PHY via MDIO control regsiter.
382 * ext: extension register (see IEEE 802.3)
383 * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0)
384 * reg: reg to write
385 */
386int atl1c_write_phy_core(struct atl1c_hw *hw, bool ext, u8 dev,
387 u16 reg, u16 phy_data)
388{
389 u32 val;
390 u16 clk_sel = MDIO_CTRL_CLK_25_4;
391
392 atl1c_stop_phy_polling(hw);
393
394
395 /* only l2c_b2 & l1d_2 could use slow clock */
396 if ((hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) &&
397 hw->hibernate)
398 clk_sel = MDIO_CTRL_CLK_25_128;
399
400 if (ext) {
401 val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg);
402 AT_WRITE_REG(hw, REG_MDIO_EXTN, val);
403 val = MDIO_CTRL_SPRES_PRMBL |
404 FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
405 FIELDX(MDIO_CTRL_DATA, phy_data) |
406 MDIO_CTRL_START |
407 MDIO_CTRL_MODE_EXT;
408 } else {
409 val = MDIO_CTRL_SPRES_PRMBL |
410 FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
411 FIELDX(MDIO_CTRL_DATA, phy_data) |
412 FIELDX(MDIO_CTRL_REG, reg) |
413 MDIO_CTRL_START;
305 } 414 }
415 AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
306 416
307 return -1; 417 if (!atl1c_wait_mdio_idle(hw))
418 return -1;
419
420 atl1c_start_phy_polling(hw, clk_sel);
421
422 return 0;
423}
424
425/*
426 * Reads the value from a PHY register
427 * hw - Struct containing variables accessed by shared code
428 * reg_addr - address of the PHY register to read
429 */
430int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data)
431{
432 return atl1c_read_phy_core(hw, false, 0, reg_addr, phy_data);
308} 433}
309 434
310/* 435/*
@@ -315,27 +440,21 @@ int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data)
315 */ 440 */
316int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data) 441int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data)
317{ 442{
318 int i; 443 return atl1c_write_phy_core(hw, false, 0, reg_addr, phy_data);
319 u32 val; 444}
320
321 val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |
322 (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
323 MDIO_SUP_PREAMBLE | MDIO_START |
324 MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
325
326 AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
327
328 for (i = 0; i < MDIO_WAIT_TIMES; i++) {
329 udelay(2);
330 AT_READ_REG(hw, REG_MDIO_CTRL, &val);
331 if (!(val & (MDIO_START | MDIO_BUSY)))
332 break;
333 }
334 445
335 if (!(val & (MDIO_START | MDIO_BUSY))) 446/* read from PHY extension register */
336 return 0; 447int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
448 u16 reg_addr, u16 *phy_data)
449{
450 return atl1c_read_phy_core(hw, true, dev_addr, reg_addr, phy_data);
451}
337 452
338 return -1; 453/* write to PHY extension register */
454int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
455 u16 reg_addr, u16 phy_data)
456{
457 return atl1c_write_phy_core(hw, true, dev_addr, reg_addr, phy_data);
339} 458}
340 459
341/* 460/*
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
index 459e141f002..cb2d20b6998 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
@@ -49,6 +49,17 @@ int atl1c_phy_init(struct atl1c_hw *hw);
49int atl1c_check_eeprom_exist(struct atl1c_hw *hw); 49int atl1c_check_eeprom_exist(struct atl1c_hw *hw);
50int atl1c_restart_autoneg(struct atl1c_hw *hw); 50int atl1c_restart_autoneg(struct atl1c_hw *hw);
51int atl1c_phy_power_saving(struct atl1c_hw *hw); 51int atl1c_phy_power_saving(struct atl1c_hw *hw);
52bool atl1c_wait_mdio_idle(struct atl1c_hw *hw);
53void atl1c_stop_phy_polling(struct atl1c_hw *hw);
54void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel);
55int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev,
56 u16 reg, u16 *phy_data);
57int atl1c_write_phy_core(struct atl1c_hw *hw, bool ext, u8 dev,
58 u16 reg, u16 phy_data);
59int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
60 u16 reg_addr, u16 *phy_data);
61int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
62 u16 reg_addr, u16 phy_data);
52/* register definition */ 63/* register definition */
53#define REG_DEVICE_CAP 0x5C 64#define REG_DEVICE_CAP 0x5C
54#define DEVICE_CAP_MAX_PAYLOAD_MASK 0x7 65#define DEVICE_CAP_MAX_PAYLOAD_MASK 0x7
@@ -268,30 +279,36 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
268 279
269/* MDIO Control Register */ 280/* MDIO Control Register */
270#define REG_MDIO_CTRL 0x1414 281#define REG_MDIO_CTRL 0x1414
271#define MDIO_DATA_MASK 0xffff /* On MDIO write, the 16-bit 282#define MDIO_CTRL_MODE_EXT BIT(30)
272 * control data to write to PHY 283#define MDIO_CTRL_POST_READ BIT(29)
273 * MII management register */ 284#define MDIO_CTRL_AP_EN BIT(28)
274#define MDIO_DATA_SHIFT 0 /* On MDIO read, the 16-bit 285#define MDIO_CTRL_BUSY BIT(27)
275 * status data that was read 286#define MDIO_CTRL_CLK_SEL_MASK 0x7UL
276 * from the PHY MII management register */ 287#define MDIO_CTRL_CLK_SEL_SHIFT 24
277#define MDIO_REG_ADDR_MASK 0x1f /* MDIO register address */ 288#define MDIO_CTRL_CLK_25_4 0 /* 25MHz divide 4 */
278#define MDIO_REG_ADDR_SHIFT 16 289#define MDIO_CTRL_CLK_25_6 2
279#define MDIO_RW 0x200000 /* 1: read, 0: write */ 290#define MDIO_CTRL_CLK_25_8 3
280#define MDIO_SUP_PREAMBLE 0x400000 /* Suppress preamble */ 291#define MDIO_CTRL_CLK_25_10 4
281#define MDIO_START 0x800000 /* Write 1 to initiate the MDIO 292#define MDIO_CTRL_CLK_25_32 5
282 * master. And this bit is self 293#define MDIO_CTRL_CLK_25_64 6
283 * cleared after one cycle */ 294#define MDIO_CTRL_CLK_25_128 7
284#define MDIO_CLK_SEL_SHIFT 24 295#define MDIO_CTRL_START BIT(23)
285#define MDIO_CLK_25_4 0 296#define MDIO_CTRL_SPRES_PRMBL BIT(22)
286#define MDIO_CLK_25_6 2 297#define MDIO_CTRL_OP_READ BIT(21) /* 1:read, 0:write */
287#define MDIO_CLK_25_8 3 298#define MDIO_CTRL_REG_MASK 0x1FUL
288#define MDIO_CLK_25_10 4 299#define MDIO_CTRL_REG_SHIFT 16
289#define MDIO_CLK_25_14 5 300#define MDIO_CTRL_DATA_MASK 0xFFFFUL
290#define MDIO_CLK_25_20 6 301#define MDIO_CTRL_DATA_SHIFT 0
291#define MDIO_CLK_25_28 7 302#define MDIO_MAX_AC_TO 120 /* 1.2ms timeout for slow clk */
292#define MDIO_BUSY 0x8000000 303
293#define MDIO_AP_EN 0x10000000 304/* for extension reg access */
294#define MDIO_WAIT_TIMES 10 305#define REG_MDIO_EXTN 0x1448
306#define MDIO_EXTN_PORTAD_MASK 0x1FUL
307#define MDIO_EXTN_PORTAD_SHIFT 21
308#define MDIO_EXTN_DEVAD_MASK 0x1FUL
309#define MDIO_EXTN_DEVAD_SHIFT 16
310#define MDIO_EXTN_REG_MASK 0xFFFFUL
311#define MDIO_EXTN_REG_SHIFT 0
295 312
296/* BIST Control and Status Register0 (for the Packet Memory) */ 313/* BIST Control and Status Register0 (for the Packet Memory) */
297#define REG_BIST0_CTRL 0x141c 314#define REG_BIST0_CTRL 0x141c
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index a6c3f05e5db..1f82880904d 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -2270,7 +2270,7 @@ static int atl1c_open(struct net_device *netdev)
2270 u32 phy_data; 2270 u32 phy_data;
2271 2271
2272 AT_READ_REG(&adapter->hw, REG_MDIO_CTRL, &phy_data); 2272 AT_READ_REG(&adapter->hw, REG_MDIO_CTRL, &phy_data);
2273 phy_data |= MDIO_AP_EN; 2273 phy_data |= MDIO_CTRL_AP_EN;
2274 AT_WRITE_REG(&adapter->hw, REG_MDIO_CTRL, phy_data); 2274 AT_WRITE_REG(&adapter->hw, REG_MDIO_CTRL, phy_data);
2275 } 2275 }
2276 return 0; 2276 return 0;
@@ -2558,7 +2558,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev,
2558 adapter->mii.mdio_read = atl1c_mdio_read; 2558 adapter->mii.mdio_read = atl1c_mdio_read;
2559 adapter->mii.mdio_write = atl1c_mdio_write; 2559 adapter->mii.mdio_write = atl1c_mdio_write;
2560 adapter->mii.phy_id_mask = 0x1f; 2560 adapter->mii.phy_id_mask = 0x1f;
2561 adapter->mii.reg_num_mask = MDIO_REG_ADDR_MASK; 2561 adapter->mii.reg_num_mask = MDIO_CTRL_REG_MASK;
2562 netif_napi_add(netdev, &adapter->napi, atl1c_clean, 64); 2562 netif_napi_add(netdev, &adapter->napi, atl1c_clean, 64);
2563 setup_timer(&adapter->phy_config_timer, atl1c_phy_config, 2563 setup_timer(&adapter->phy_config_timer, atl1c_phy_config,
2564 (unsigned long)adapter); 2564 (unsigned long)adapter);