1 /****************************************************************************
2 * Driver for Solarflare Solarstorm network controllers and boards
3 * Copyright 2007-2008 Solarflare Communications Inc.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published
7 * by the Free Software Foundation, incorporated herein by reference.
10 #include <linux/rtnetlink.h>
12 #include "net_driver.h"
17 #include "falcon_io.h"
18 #include "workarounds.h"
20 /* Macros for unpacking the board revision */
21 /* The revision info is in host byte order. */
22 #define FALCON_BOARD_TYPE(_rev) (_rev >> 8)
23 #define FALCON_BOARD_MAJOR(_rev) ((_rev >> 4) & 0xf)
24 #define FALCON_BOARD_MINOR(_rev) (_rev & 0xf)
27 #define FALCON_BOARD_SFE4001 0x01
28 #define FALCON_BOARD_SFE4002 0x02
29 #define FALCON_BOARD_SFN4111T 0x51
30 #define FALCON_BOARD_SFN4112F 0x52
32 /* Blink support. If the PHY has no auto-blink mode so we hang it off a timer */
33 #define BLINK_INTERVAL (HZ/2)
35 static void blink_led_timer(unsigned long context
)
37 struct efx_nic
*efx
= (struct efx_nic
*)context
;
38 struct efx_blinker
*bl
= &efx
->board_info
.blinker
;
39 efx
->board_info
.set_id_led(efx
, bl
->state
);
40 bl
->state
= !bl
->state
;
42 mod_timer(&bl
->timer
, jiffies
+ BLINK_INTERVAL
);
45 static void board_blink(struct efx_nic
*efx
, bool blink
)
47 struct efx_blinker
*blinker
= &efx
->board_info
.blinker
;
49 /* The rtnl mutex serialises all ethtool ioctls, so
50 * nothing special needs doing here. */
52 blinker
->resubmit
= true;
53 blinker
->state
= false;
54 setup_timer(&blinker
->timer
, blink_led_timer
,
56 mod_timer(&blinker
->timer
, jiffies
+ BLINK_INTERVAL
);
58 blinker
->resubmit
= false;
59 if (blinker
->timer
.function
)
60 del_timer_sync(&blinker
->timer
);
61 efx
->board_info
.init_leds(efx
);
65 /*****************************************************************************
66 * Support for LM87 sensor chip used on several boards
68 #define LM87_REG_ALARMS1 0x41
69 #define LM87_REG_ALARMS2 0x42
70 #define LM87_IN_LIMITS(nr, _min, _max) \
71 0x2B + (nr) * 2, _max, 0x2C + (nr) * 2, _min
72 #define LM87_AIN_LIMITS(nr, _min, _max) \
73 0x3B + (nr), _max, 0x1A + (nr), _min
74 #define LM87_TEMP_INT_LIMITS(_min, _max) \
75 0x39, _max, 0x3A, _min
76 #define LM87_TEMP_EXT1_LIMITS(_min, _max) \
77 0x37, _max, 0x38, _min
79 #define LM87_ALARM_TEMP_INT 0x10
80 #define LM87_ALARM_TEMP_EXT1 0x20
82 #if defined(CONFIG_SENSORS_LM87) || defined(CONFIG_SENSORS_LM87_MODULE)
84 static int efx_init_lm87(struct efx_nic
*efx
, struct i2c_board_info
*info
,
87 struct i2c_client
*client
= i2c_new_device(&efx
->i2c_adap
, info
);
94 u8 reg
= *reg_values
++;
95 u8 value
= *reg_values
++;
96 rc
= i2c_smbus_write_byte_data(client
, reg
, value
);
101 efx
->board_info
.hwmon_client
= client
;
105 i2c_unregister_device(client
);
109 static void efx_fini_lm87(struct efx_nic
*efx
)
111 i2c_unregister_device(efx
->board_info
.hwmon_client
);
114 static int efx_check_lm87(struct efx_nic
*efx
, unsigned mask
)
116 struct i2c_client
*client
= efx
->board_info
.hwmon_client
;
117 s32 alarms1
, alarms2
;
119 /* If link is up then do not monitor temperature */
120 if (EFX_WORKAROUND_7884(efx
) && efx
->link_up
)
123 alarms1
= i2c_smbus_read_byte_data(client
, LM87_REG_ALARMS1
);
124 alarms2
= i2c_smbus_read_byte_data(client
, LM87_REG_ALARMS2
);
130 alarms2
&= mask
>> 8;
131 if (alarms1
|| alarms2
) {
133 "LM87 detected a hardware failure (status %02x:%02x)"
136 (alarms1
& LM87_ALARM_TEMP_INT
) ? " INTERNAL" : "",
137 (alarms1
& LM87_ALARM_TEMP_EXT1
) ? " EXTERNAL" : "");
144 #else /* !CONFIG_SENSORS_LM87 */
147 efx_init_lm87(struct efx_nic
*efx
, struct i2c_board_info
*info
,
148 const u8
*reg_values
)
152 static inline void efx_fini_lm87(struct efx_nic
*efx
)
155 static inline int efx_check_lm87(struct efx_nic
*efx
, unsigned mask
)
160 #endif /* CONFIG_SENSORS_LM87 */
162 /*****************************************************************************
163 * Support for the SFE4001 and SFN4111T NICs.
165 * The SFE4001 does not power-up fully at reset due to its high power
166 * consumption. We control its power via a PCA9539 I/O expander.
167 * Both boards have a MAX6647 temperature monitor which we expose to
170 * This also provides minimal support for reflashing the PHY, which is
171 * initiated by resetting it with the FLASH_CFG_1 pin pulled down.
172 * On SFE4001 rev A2 and later this is connected to the 3V3X output of
173 * the IO-expander; on the SFN4111T it is connected to Falcon's GPIO3.
174 * We represent reflash mode as PHY_MODE_SPECIAL and make it mutually
175 * exclusive with the network device being open.
178 /**************************************************************************
179 * Support for I2C IO Expander device on SFE40001
185 #define P0_INVERT 0x04
186 #define P0_CONFIG 0x06
188 #define P0_EN_1V0X_LBN 0
189 #define P0_EN_1V0X_WIDTH 1
190 #define P0_EN_1V2_LBN 1
191 #define P0_EN_1V2_WIDTH 1
192 #define P0_EN_2V5_LBN 2
193 #define P0_EN_2V5_WIDTH 1
194 #define P0_EN_3V3X_LBN 3
195 #define P0_EN_3V3X_WIDTH 1
196 #define P0_EN_5V_LBN 4
197 #define P0_EN_5V_WIDTH 1
198 #define P0_SHORTEN_JTAG_LBN 5
199 #define P0_SHORTEN_JTAG_WIDTH 1
200 #define P0_X_TRST_LBN 6
201 #define P0_X_TRST_WIDTH 1
202 #define P0_DSP_RESET_LBN 7
203 #define P0_DSP_RESET_WIDTH 1
207 #define P1_INVERT 0x05
208 #define P1_CONFIG 0x07
210 #define P1_AFE_PWD_LBN 0
211 #define P1_AFE_PWD_WIDTH 1
212 #define P1_DSP_PWD25_LBN 1
213 #define P1_DSP_PWD25_WIDTH 1
214 #define P1_RESERVED_LBN 2
215 #define P1_RESERVED_WIDTH 2
216 #define P1_SPARE_LBN 4
217 #define P1_SPARE_WIDTH 4
219 /* Temperature Sensor */
220 #define MAX664X_REG_RSL 0x02
221 #define MAX664X_REG_WLHO 0x0B
223 static void sfe4001_poweroff(struct efx_nic
*efx
)
225 struct i2c_client
*ioexp_client
= efx
->board_info
.ioexp_client
;
226 struct i2c_client
*hwmon_client
= efx
->board_info
.hwmon_client
;
228 /* Turn off all power rails and disable outputs */
229 i2c_smbus_write_byte_data(ioexp_client
, P0_OUT
, 0xff);
230 i2c_smbus_write_byte_data(ioexp_client
, P1_CONFIG
, 0xff);
231 i2c_smbus_write_byte_data(ioexp_client
, P0_CONFIG
, 0xff);
233 /* Clear any over-temperature alert */
234 i2c_smbus_read_byte_data(hwmon_client
, MAX664X_REG_RSL
);
237 static int sfe4001_poweron(struct efx_nic
*efx
)
239 struct i2c_client
*hwmon_client
= efx
->board_info
.hwmon_client
;
240 struct i2c_client
*ioexp_client
= efx
->board_info
.ioexp_client
;
245 /* Clear any previous over-temperature alert */
246 rc
= i2c_smbus_read_byte_data(hwmon_client
, MAX664X_REG_RSL
);
250 /* Enable port 0 and port 1 outputs on IO expander */
251 rc
= i2c_smbus_write_byte_data(ioexp_client
, P0_CONFIG
, 0x00);
254 rc
= i2c_smbus_write_byte_data(ioexp_client
, P1_CONFIG
,
255 0xff & ~(1 << P1_SPARE_LBN
));
259 /* If PHY power is on, turn it all off and wait 1 second to
260 * ensure a full reset.
262 rc
= i2c_smbus_read_byte_data(ioexp_client
, P0_OUT
);
265 out
= 0xff & ~((0 << P0_EN_1V2_LBN
) | (0 << P0_EN_2V5_LBN
) |
266 (0 << P0_EN_3V3X_LBN
) | (0 << P0_EN_5V_LBN
) |
267 (0 << P0_EN_1V0X_LBN
));
269 EFX_INFO(efx
, "power-cycling PHY\n");
270 rc
= i2c_smbus_write_byte_data(ioexp_client
, P0_OUT
, out
);
273 schedule_timeout_uninterruptible(HZ
);
276 for (i
= 0; i
< 20; ++i
) {
277 /* Turn on 1.2V, 2.5V, 3.3V and 5V power rails */
278 out
= 0xff & ~((1 << P0_EN_1V2_LBN
) | (1 << P0_EN_2V5_LBN
) |
279 (1 << P0_EN_3V3X_LBN
) | (1 << P0_EN_5V_LBN
) |
280 (1 << P0_X_TRST_LBN
));
281 if (efx
->phy_mode
& PHY_MODE_SPECIAL
)
282 out
|= 1 << P0_EN_3V3X_LBN
;
284 rc
= i2c_smbus_write_byte_data(ioexp_client
, P0_OUT
, out
);
289 /* Turn on 1V power rail */
290 out
&= ~(1 << P0_EN_1V0X_LBN
);
291 rc
= i2c_smbus_write_byte_data(ioexp_client
, P0_OUT
, out
);
295 EFX_INFO(efx
, "waiting for DSP boot (attempt %d)...\n", i
);
297 /* In flash config mode, DSP does not turn on AFE, so
298 * just wait 1 second.
300 if (efx
->phy_mode
& PHY_MODE_SPECIAL
) {
301 schedule_timeout_uninterruptible(HZ
);
305 for (j
= 0; j
< 10; ++j
) {
308 /* Check DSP has asserted AFE power line */
309 rc
= i2c_smbus_read_byte_data(ioexp_client
, P1_IN
);
312 if (rc
& (1 << P1_AFE_PWD_LBN
))
317 EFX_INFO(efx
, "timed out waiting for DSP boot\n");
320 sfe4001_poweroff(efx
);
324 static int sfn4111t_reset(struct efx_nic
*efx
)
328 /* GPIO 3 and the GPIO register are shared with I2C, so block that */
329 mutex_lock(&efx
->i2c_adap
.bus_lock
);
331 /* Pull RST_N (GPIO 2) low then let it up again, setting the
332 * FLASH_CFG_1 strap (GPIO 3) appropriately. Only change the
333 * output enables; the output levels should always be 0 (low)
334 * and we rely on external pull-ups. */
335 falcon_read(efx
, ®
, FR_AB_GPIO_CTL
);
336 EFX_SET_OWORD_FIELD(reg
, FRF_AB_GPIO2_OEN
, true);
337 falcon_write(efx
, ®
, FR_AB_GPIO_CTL
);
339 EFX_SET_OWORD_FIELD(reg
, FRF_AB_GPIO2_OEN
, false);
340 EFX_SET_OWORD_FIELD(reg
, FRF_AB_GPIO3_OEN
,
341 !!(efx
->phy_mode
& PHY_MODE_SPECIAL
));
342 falcon_write(efx
, ®
, FR_AB_GPIO_CTL
);
345 mutex_unlock(&efx
->i2c_adap
.bus_lock
);
351 static ssize_t
show_phy_flash_cfg(struct device
*dev
,
352 struct device_attribute
*attr
, char *buf
)
354 struct efx_nic
*efx
= pci_get_drvdata(to_pci_dev(dev
));
355 return sprintf(buf
, "%d\n", !!(efx
->phy_mode
& PHY_MODE_SPECIAL
));
358 static ssize_t
set_phy_flash_cfg(struct device
*dev
,
359 struct device_attribute
*attr
,
360 const char *buf
, size_t count
)
362 struct efx_nic
*efx
= pci_get_drvdata(to_pci_dev(dev
));
363 enum efx_phy_mode old_mode
, new_mode
;
367 old_mode
= efx
->phy_mode
;
368 if (count
== 0 || *buf
== '0')
369 new_mode
= old_mode
& ~PHY_MODE_SPECIAL
;
371 new_mode
= PHY_MODE_SPECIAL
;
372 if (old_mode
== new_mode
) {
374 } else if (efx
->state
!= STATE_RUNNING
|| netif_running(efx
->net_dev
)) {
377 /* Reset the PHY, reconfigure the MAC and enable/disable
378 * MAC stats accordingly. */
379 efx
->phy_mode
= new_mode
;
380 if (new_mode
& PHY_MODE_SPECIAL
)
381 efx_stats_disable(efx
);
382 if (efx
->board_info
.type
== FALCON_BOARD_SFE4001
)
383 err
= sfe4001_poweron(efx
);
385 err
= sfn4111t_reset(efx
);
386 efx_reconfigure_port(efx
);
387 if (!(new_mode
& PHY_MODE_SPECIAL
))
388 efx_stats_enable(efx
);
392 return err
? err
: count
;
395 static DEVICE_ATTR(phy_flash_cfg
, 0644, show_phy_flash_cfg
, set_phy_flash_cfg
);
397 static void sfe4001_fini(struct efx_nic
*efx
)
399 EFX_INFO(efx
, "%s\n", __func__
);
401 device_remove_file(&efx
->pci_dev
->dev
, &dev_attr_phy_flash_cfg
);
402 sfe4001_poweroff(efx
);
403 i2c_unregister_device(efx
->board_info
.ioexp_client
);
404 i2c_unregister_device(efx
->board_info
.hwmon_client
);
407 static int sfe4001_check_hw(struct efx_nic
*efx
)
411 /* If XAUI link is up then do not monitor */
412 if (EFX_WORKAROUND_7884(efx
) && efx
->mac_up
)
415 /* Check the powered status of the PHY. Lack of power implies that
416 * the MAX6647 has shut down power to it, probably due to a temp.
417 * alarm. Reading the power status rather than the MAX6647 status
418 * directly because the later is read-to-clear and would thus
419 * start to power up the PHY again when polled, causing us to blip
420 * the power undesirably.
421 * We know we can read from the IO expander because we did
422 * it during power-on. Assume failure now is bad news. */
423 status
= i2c_smbus_read_byte_data(efx
->board_info
.ioexp_client
, P1_IN
);
425 (status
& ((1 << P1_AFE_PWD_LBN
) | (1 << P1_DSP_PWD25_LBN
))) != 0)
428 /* Use board power control, not PHY power control */
429 sfe4001_poweroff(efx
);
430 efx
->phy_mode
= PHY_MODE_OFF
;
432 return (status
< 0) ? -EIO
: -ERANGE
;
435 static struct i2c_board_info sfe4001_hwmon_info
= {
436 I2C_BOARD_INFO("max6647", 0x4e),
439 /* This board uses an I2C expander to provider power to the PHY, which needs to
440 * be turned on before the PHY can be used.
441 * Context: Process context, rtnl lock held
443 static int sfe4001_init(struct efx_nic
*efx
)
447 #if defined(CONFIG_SENSORS_LM90) || defined(CONFIG_SENSORS_LM90_MODULE)
448 efx
->board_info
.hwmon_client
=
449 i2c_new_device(&efx
->i2c_adap
, &sfe4001_hwmon_info
);
451 efx
->board_info
.hwmon_client
=
452 i2c_new_dummy(&efx
->i2c_adap
, sfe4001_hwmon_info
.addr
);
454 if (!efx
->board_info
.hwmon_client
)
457 /* Raise board/PHY high limit from 85 to 90 degrees Celsius */
458 rc
= i2c_smbus_write_byte_data(efx
->board_info
.hwmon_client
,
459 MAX664X_REG_WLHO
, 90);
463 efx
->board_info
.ioexp_client
= i2c_new_dummy(&efx
->i2c_adap
, PCA9539
);
464 if (!efx
->board_info
.ioexp_client
) {
469 /* 10Xpress has fixed-function LED pins, so there is no board-specific
471 efx
->board_info
.blink
= tenxpress_phy_blink
;
473 efx
->board_info
.monitor
= sfe4001_check_hw
;
474 efx
->board_info
.fini
= sfe4001_fini
;
476 if (efx
->phy_mode
& PHY_MODE_SPECIAL
) {
477 /* PHY won't generate a 156.25 MHz clock and MAC stats fetch
479 efx_stats_disable(efx
);
481 rc
= sfe4001_poweron(efx
);
485 rc
= device_create_file(&efx
->pci_dev
->dev
, &dev_attr_phy_flash_cfg
);
489 EFX_INFO(efx
, "PHY is powered on\n");
493 sfe4001_poweroff(efx
);
495 i2c_unregister_device(efx
->board_info
.ioexp_client
);
497 i2c_unregister_device(efx
->board_info
.hwmon_client
);
501 static int sfn4111t_check_hw(struct efx_nic
*efx
)
505 /* If XAUI link is up then do not monitor */
506 if (EFX_WORKAROUND_7884(efx
) && efx
->mac_up
)
509 /* Test LHIGH, RHIGH, FAULT, EOT and IOT alarms */
510 status
= i2c_smbus_read_byte_data(efx
->board_info
.hwmon_client
,
519 static void sfn4111t_fini(struct efx_nic
*efx
)
521 EFX_INFO(efx
, "%s\n", __func__
);
523 device_remove_file(&efx
->pci_dev
->dev
, &dev_attr_phy_flash_cfg
);
524 i2c_unregister_device(efx
->board_info
.hwmon_client
);
527 static struct i2c_board_info sfn4111t_a0_hwmon_info
= {
528 I2C_BOARD_INFO("max6647", 0x4e),
531 static struct i2c_board_info sfn4111t_r5_hwmon_info
= {
532 I2C_BOARD_INFO("max6646", 0x4d),
535 static int sfn4111t_init(struct efx_nic
*efx
)
540 efx
->board_info
.hwmon_client
=
541 i2c_new_device(&efx
->i2c_adap
,
542 (efx
->board_info
.minor
< 5) ?
543 &sfn4111t_a0_hwmon_info
:
544 &sfn4111t_r5_hwmon_info
);
545 if (!efx
->board_info
.hwmon_client
)
548 efx
->board_info
.blink
= tenxpress_phy_blink
;
549 efx
->board_info
.monitor
= sfn4111t_check_hw
;
550 efx
->board_info
.fini
= sfn4111t_fini
;
552 rc
= device_create_file(&efx
->pci_dev
->dev
, &dev_attr_phy_flash_cfg
);
557 if (efx
->phy_mode
& PHY_MODE_SPECIAL
) {
558 /* PHY may not generate a 156.25 MHz clock and MAC
559 * stats fetch will fail. */
560 efx_stats_disable(efx
);
563 rc
= sft9001_wait_boot(efx
);
566 efx
->phy_mode
= PHY_MODE_SPECIAL
;
567 } while (rc
== -EINVAL
&& ++i
< 2);
569 device_remove_file(&efx
->pci_dev
->dev
, &dev_attr_phy_flash_cfg
);
571 i2c_unregister_device(efx
->board_info
.hwmon_client
);
575 /*****************************************************************************
576 * Support for the SFE4002
579 static u8 sfe4002_lm87_channel
= 0x03; /* use AIN not FAN inputs */
581 static const u8 sfe4002_lm87_regs
[] = {
582 LM87_IN_LIMITS(0, 0x83, 0x91), /* 2.5V: 1.8V +/- 5% */
583 LM87_IN_LIMITS(1, 0x51, 0x5a), /* Vccp1: 1.2V +/- 5% */
584 LM87_IN_LIMITS(2, 0xb6, 0xca), /* 3.3V: 3.3V +/- 5% */
585 LM87_IN_LIMITS(3, 0xb0, 0xc9), /* 5V: 4.6-5.2V */
586 LM87_IN_LIMITS(4, 0xb0, 0xe0), /* 12V: 11-14V */
587 LM87_IN_LIMITS(5, 0x44, 0x4b), /* Vccp2: 1.0V +/- 5% */
588 LM87_AIN_LIMITS(0, 0xa0, 0xb2), /* AIN1: 1.66V +/- 5% */
589 LM87_AIN_LIMITS(1, 0x91, 0xa1), /* AIN2: 1.5V +/- 5% */
590 LM87_TEMP_INT_LIMITS(10, 60), /* board */
591 LM87_TEMP_EXT1_LIMITS(10, 70), /* Falcon */
595 static struct i2c_board_info sfe4002_hwmon_info
= {
596 I2C_BOARD_INFO("lm87", 0x2e),
597 .platform_data
= &sfe4002_lm87_channel
,
600 /****************************************************************************/
601 /* LED allocations. Note that on rev A0 boards the schematic and the reality
602 * differ: red and green are swapped. Below is the fixed (A1) layout (there
603 * are only 3 A0 boards in existence, so no real reason to make this
606 #define SFE4002_FAULT_LED (2) /* Red */
607 #define SFE4002_RX_LED (0) /* Green */
608 #define SFE4002_TX_LED (1) /* Amber */
610 static void sfe4002_init_leds(struct efx_nic
*efx
)
612 /* Set the TX and RX LEDs to reflect status and activity, and the
614 xfp_set_led(efx
, SFE4002_TX_LED
,
615 QUAKE_LED_TXLINK
| QUAKE_LED_LINK_ACTSTAT
);
616 xfp_set_led(efx
, SFE4002_RX_LED
,
617 QUAKE_LED_RXLINK
| QUAKE_LED_LINK_ACTSTAT
);
618 xfp_set_led(efx
, SFE4002_FAULT_LED
, QUAKE_LED_OFF
);
621 static void sfe4002_set_id_led(struct efx_nic
*efx
, bool state
)
623 xfp_set_led(efx
, SFE4002_FAULT_LED
, state
? QUAKE_LED_ON
:
627 static int sfe4002_check_hw(struct efx_nic
*efx
)
629 /* A0 board rev. 4002s report a temperature fault the whole time
630 * (bad sensor) so we mask it out. */
631 unsigned alarm_mask
=
632 (efx
->board_info
.major
== 0 && efx
->board_info
.minor
== 0) ?
633 ~LM87_ALARM_TEMP_EXT1
: ~0;
635 return efx_check_lm87(efx
, alarm_mask
);
638 static int sfe4002_init(struct efx_nic
*efx
)
640 int rc
= efx_init_lm87(efx
, &sfe4002_hwmon_info
, sfe4002_lm87_regs
);
643 efx
->board_info
.monitor
= sfe4002_check_hw
;
644 efx
->board_info
.init_leds
= sfe4002_init_leds
;
645 efx
->board_info
.set_id_led
= sfe4002_set_id_led
;
646 efx
->board_info
.blink
= board_blink
;
647 efx
->board_info
.fini
= efx_fini_lm87
;
651 /*****************************************************************************
652 * Support for the SFN4112F
655 static u8 sfn4112f_lm87_channel
= 0x03; /* use AIN not FAN inputs */
657 static const u8 sfn4112f_lm87_regs
[] = {
658 LM87_IN_LIMITS(0, 0x83, 0x91), /* 2.5V: 1.8V +/- 5% */
659 LM87_IN_LIMITS(1, 0x51, 0x5a), /* Vccp1: 1.2V +/- 5% */
660 LM87_IN_LIMITS(2, 0xb6, 0xca), /* 3.3V: 3.3V +/- 5% */
661 LM87_IN_LIMITS(4, 0xb0, 0xe0), /* 12V: 11-14V */
662 LM87_IN_LIMITS(5, 0x44, 0x4b), /* Vccp2: 1.0V +/- 5% */
663 LM87_AIN_LIMITS(1, 0x91, 0xa1), /* AIN2: 1.5V +/- 5% */
664 LM87_TEMP_INT_LIMITS(10, 60), /* board */
665 LM87_TEMP_EXT1_LIMITS(10, 70), /* Falcon */
669 static struct i2c_board_info sfn4112f_hwmon_info
= {
670 I2C_BOARD_INFO("lm87", 0x2e),
671 .platform_data
= &sfn4112f_lm87_channel
,
674 #define SFN4112F_ACT_LED 0
675 #define SFN4112F_LINK_LED 1
677 static void sfn4112f_init_leds(struct efx_nic
*efx
)
679 xfp_set_led(efx
, SFN4112F_ACT_LED
,
680 QUAKE_LED_RXLINK
| QUAKE_LED_LINK_ACT
);
681 xfp_set_led(efx
, SFN4112F_LINK_LED
,
682 QUAKE_LED_RXLINK
| QUAKE_LED_LINK_STAT
);
685 static void sfn4112f_set_id_led(struct efx_nic
*efx
, bool state
)
687 xfp_set_led(efx
, SFN4112F_LINK_LED
,
688 state
? QUAKE_LED_ON
: QUAKE_LED_OFF
);
691 static int sfn4112f_check_hw(struct efx_nic
*efx
)
693 /* Mask out unused sensors */
694 return efx_check_lm87(efx
, ~0x48);
697 static int sfn4112f_init(struct efx_nic
*efx
)
699 int rc
= efx_init_lm87(efx
, &sfn4112f_hwmon_info
, sfn4112f_lm87_regs
);
702 efx
->board_info
.monitor
= sfn4112f_check_hw
;
703 efx
->board_info
.init_leds
= sfn4112f_init_leds
;
704 efx
->board_info
.set_id_led
= sfn4112f_set_id_led
;
705 efx
->board_info
.blink
= board_blink
;
706 efx
->board_info
.fini
= efx_fini_lm87
;
710 /* This will get expanded as board-specific details get moved out of the
712 struct falcon_board_data
{
714 const char *ref_model
;
715 const char *gen_type
;
716 int (*init
) (struct efx_nic
*nic
);
720 static struct falcon_board_data board_data
[] = {
721 { FALCON_BOARD_SFE4001
, "SFE4001", "10GBASE-T adapter", sfe4001_init
},
722 { FALCON_BOARD_SFE4002
, "SFE4002", "XFP adapter", sfe4002_init
},
723 { FALCON_BOARD_SFN4111T
, "SFN4111T", "100/1000/10GBASE-T adapter",
725 { FALCON_BOARD_SFN4112F
, "SFN4112F", "SFP+ adapter",
729 void falcon_probe_board(struct efx_nic
*efx
, u16 revision_info
)
731 struct falcon_board_data
*data
= NULL
;
734 efx
->board_info
.type
= FALCON_BOARD_TYPE(revision_info
);
735 efx
->board_info
.major
= FALCON_BOARD_MAJOR(revision_info
);
736 efx
->board_info
.minor
= FALCON_BOARD_MINOR(revision_info
);
738 for (i
= 0; i
< ARRAY_SIZE(board_data
); i
++)
739 if (board_data
[i
].type
== efx
->board_info
.type
)
740 data
= &board_data
[i
];
743 EFX_INFO(efx
, "board is %s rev %c%d\n",
744 (efx
->pci_dev
->subsystem_vendor
== EFX_VENDID_SFC
)
745 ? data
->ref_model
: data
->gen_type
,
746 'A' + efx
->board_info
.major
, efx
->board_info
.minor
);
747 efx
->board_info
.init
= data
->init
;
749 EFX_ERR(efx
, "unknown board type %d\n", efx
->board_info
.type
);