diff options
Diffstat (limited to 'drivers/net/ethernet/atheros')
-rw-r--r-- | drivers/net/ethernet/atheros/atl1c/atl1c_hw.c | 189 | ||||
-rw-r--r-- | drivers/net/ethernet/atheros/atl1c/atl1c_hw.h | 65 | ||||
-rw-r--r-- | drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 4 |
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 | */ |
285 | int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data) | 285 | bool 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 | |||
300 | void 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 | |||
309 | void 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 | */ | ||
337 | int 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 | */ | ||
386 | int 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 | */ | ||
430 | int 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 | */ |
316 | int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data) | 441 | int 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; | 447 | int 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 */ |
454 | int 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); | |||
49 | int atl1c_check_eeprom_exist(struct atl1c_hw *hw); | 49 | int atl1c_check_eeprom_exist(struct atl1c_hw *hw); |
50 | int atl1c_restart_autoneg(struct atl1c_hw *hw); | 50 | int atl1c_restart_autoneg(struct atl1c_hw *hw); |
51 | int atl1c_phy_power_saving(struct atl1c_hw *hw); | 51 | int atl1c_phy_power_saving(struct atl1c_hw *hw); |
52 | bool atl1c_wait_mdio_idle(struct atl1c_hw *hw); | ||
53 | void atl1c_stop_phy_polling(struct atl1c_hw *hw); | ||
54 | void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel); | ||
55 | int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, | ||
56 | u16 reg, u16 *phy_data); | ||
57 | int atl1c_write_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, | ||
58 | u16 reg, u16 phy_data); | ||
59 | int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr, | ||
60 | u16 reg_addr, u16 *phy_data); | ||
61 | int 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); |