mirror of
https://github.com/opnsense/src.git
synced 2026-02-18 18:20:26 -05:00
axgbe: validate contents of gpio expander
This commit is contained in:
parent
b11b1fd462
commit
6fd65fcb73
1 changed files with 116 additions and 66 deletions
|
|
@ -363,6 +363,9 @@ struct xgbe_phy_data {
|
|||
unsigned int sfp_gpio_address;
|
||||
unsigned int sfp_gpio_mask;
|
||||
unsigned int sfp_gpio_inputs;
|
||||
unsigned int sfp_gpio_outputs;
|
||||
unsigned int sfp_gpio_polarity;
|
||||
unsigned int sfp_gpio_configuration;
|
||||
unsigned int sfp_gpio_rx_los;
|
||||
unsigned int sfp_gpio_tx_fault;
|
||||
unsigned int sfp_gpio_mod_absent;
|
||||
|
|
@ -1458,6 +1461,109 @@ put_mux:
|
|||
xgbe_phy_sfp_put_mux(pdata);
|
||||
}
|
||||
|
||||
static int
|
||||
xgbe_read_gpio_expander(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
||||
uint8_t gpio_reg, gpio_ports[2];
|
||||
int ret = 0;
|
||||
|
||||
ret = xgbe_phy_sfp_get_mux(pdata);
|
||||
if (ret) {
|
||||
axgbe_error("I2C error setting SFP MUX\n");
|
||||
return (ret);
|
||||
}
|
||||
|
||||
gpio_reg = 2;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ret = xgbe_phy_i2c_read(pdata, phy_data->sfp_gpio_address, &gpio_reg,
|
||||
sizeof(gpio_reg), gpio_ports, sizeof(gpio_ports));
|
||||
if (ret) {
|
||||
axgbe_error("%s: I2C error reading GPIO expander register: %d\n",
|
||||
__func__, gpio_reg);
|
||||
goto put_mux;
|
||||
}
|
||||
|
||||
if (gpio_reg == 2)
|
||||
phy_data->sfp_gpio_outputs = (gpio_ports[1] << 8) | gpio_ports[0];
|
||||
else if (gpio_reg == 4)
|
||||
phy_data->sfp_gpio_polarity = (gpio_ports[1] << 8) | gpio_ports[0];
|
||||
else if (gpio_reg == 6)
|
||||
phy_data->sfp_gpio_configuration = (gpio_ports[1] << 8) | gpio_ports[0];
|
||||
|
||||
memset(gpio_ports, 0, sizeof(gpio_ports));
|
||||
gpio_reg += 2;
|
||||
}
|
||||
|
||||
put_mux:
|
||||
xgbe_phy_sfp_put_mux(pdata);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_log_gpio_expander(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
||||
|
||||
axgbe_printf(0, "%s: Input port registers: 0x%x\n", __func__, phy_data->sfp_gpio_inputs);
|
||||
axgbe_printf(0, "%s: Output port registers: 0x%x\n", __func__, phy_data->sfp_gpio_outputs);
|
||||
axgbe_printf(0, "%s: Polarity port registers: 0x%x\n", __func__, phy_data->sfp_gpio_polarity);
|
||||
axgbe_printf(0, "%s: Configuration port registers: 0x%x\n", __func__, phy_data->sfp_gpio_configuration);
|
||||
}
|
||||
|
||||
static int
|
||||
xgbe_phy_validate_gpio_expander(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
||||
uint8_t polarity[3];
|
||||
int ret = 0;
|
||||
|
||||
ret = xgbe_phy_get_comm_ownership(pdata);
|
||||
if (ret)
|
||||
return (ret);
|
||||
|
||||
ret = xgbe_read_gpio_expander(pdata);
|
||||
if (ret)
|
||||
goto put;
|
||||
|
||||
if (phy_data->sfp_gpio_polarity) {
|
||||
axgbe_printf(0, "GPIO polarity inverted - resetting\n");
|
||||
|
||||
ret = xgbe_phy_sfp_get_mux(pdata);
|
||||
if (ret) {
|
||||
axgbe_error("I2C error setting SFP MUX\n");
|
||||
goto put;
|
||||
}
|
||||
|
||||
polarity[0] = 4;
|
||||
polarity[1] = 0x0;
|
||||
polarity[2] = 0x0;
|
||||
|
||||
ret = xgbe_phy_i2c_write(pdata, phy_data->sfp_gpio_address,
|
||||
polarity, sizeof(polarity));
|
||||
if (ret) {
|
||||
axgbe_error("%s: I2C error writing address to GPIO polarity register\n",
|
||||
__func__);
|
||||
goto put_mux;
|
||||
}
|
||||
|
||||
ret = xgbe_read_gpio_expander(pdata);
|
||||
if (ret)
|
||||
goto put_mux;
|
||||
|
||||
xgbe_log_gpio_expander(pdata);
|
||||
|
||||
put_mux:
|
||||
xgbe_phy_sfp_put_mux(pdata);
|
||||
}
|
||||
|
||||
put:
|
||||
xgbe_phy_put_comm_ownership(pdata);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_phy_sfp_mod_absent(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
|
|
@ -1481,71 +1587,6 @@ xgbe_phy_sfp_reset(struct xgbe_phy_data *phy_data)
|
|||
phy_data->sfp_speed = XGBE_SFP_SPEED_UNKNOWN;
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_log_gpio_expander(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
||||
uint8_t gpio_reg, gpio_ports[2];
|
||||
unsigned int sfp_gpio_outputs;
|
||||
unsigned int sfp_gpio_polarity;
|
||||
unsigned int sfp_gpio_configuration;
|
||||
int ret;
|
||||
|
||||
axgbe_printf(0, "%s: Input port registers: 0x%x\n", __func__, phy_data->sfp_gpio_inputs);
|
||||
|
||||
ret = xgbe_phy_sfp_get_mux(pdata);
|
||||
if (ret) {
|
||||
axgbe_error("I2C error setting SFP MUX\n");
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_reg = 2;
|
||||
ret = xgbe_phy_i2c_read(pdata, phy_data->sfp_gpio_address, &gpio_reg,
|
||||
sizeof(gpio_reg), gpio_ports, sizeof(gpio_ports));
|
||||
if (ret) {
|
||||
axgbe_error("%s: I2C error reading GPIO Output register:0x%x\n",
|
||||
__func__, phy_data->sfp_gpio_address);
|
||||
goto put_mux;
|
||||
}
|
||||
|
||||
sfp_gpio_outputs = (gpio_ports[1] << 8) | gpio_ports[0];
|
||||
|
||||
axgbe_printf(0, "%s: Output port registers: 0x%x\n", __func__, sfp_gpio_outputs);
|
||||
|
||||
memset(gpio_ports, 0, 2);
|
||||
|
||||
gpio_reg = 4;
|
||||
ret = xgbe_phy_i2c_read(pdata, phy_data->sfp_gpio_address, &gpio_reg,
|
||||
sizeof(gpio_reg), gpio_ports, sizeof(gpio_ports));
|
||||
if (ret) {
|
||||
axgbe_error("%s: I2C error reading GPIO Polarity register:0x%x\n",
|
||||
__func__, phy_data->sfp_gpio_address);
|
||||
goto put_mux;
|
||||
}
|
||||
|
||||
sfp_gpio_polarity = (gpio_ports[1] << 8) | gpio_ports[0];
|
||||
|
||||
axgbe_printf(0, "%s: Polarity port registers: 0x%x\n", __func__, sfp_gpio_polarity);
|
||||
|
||||
memset(gpio_ports, 0, 2);
|
||||
|
||||
gpio_reg = 6;
|
||||
ret = xgbe_phy_i2c_read(pdata, phy_data->sfp_gpio_address, &gpio_reg,
|
||||
sizeof(gpio_reg), gpio_ports, sizeof(gpio_ports));
|
||||
if (ret) {
|
||||
axgbe_error("%s: I2C error reading GPIO Configuration register:0x%x\n",
|
||||
__func__, phy_data->sfp_gpio_address);
|
||||
goto put_mux;
|
||||
}
|
||||
|
||||
sfp_gpio_configuration = (gpio_ports[1] << 8) | gpio_ports[0];
|
||||
|
||||
axgbe_printf(0, "%s: Configuration port registers: 0x%x\n", __func__, sfp_gpio_configuration);
|
||||
|
||||
put_mux:
|
||||
xgbe_phy_sfp_put_mux(pdata);
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_phy_sfp_detect(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
|
|
@ -1569,7 +1610,11 @@ xgbe_phy_sfp_detect(struct xgbe_prv_data *pdata)
|
|||
if (ret) {
|
||||
/* Treat any error as if there isn't an SFP plugged in */
|
||||
axgbe_error("%s: eeprom read failed\n", __func__);
|
||||
xgbe_log_gpio_expander(pdata);
|
||||
ret = xgbe_read_gpio_expander(pdata);
|
||||
|
||||
if (!ret)
|
||||
xgbe_log_gpio_expander(pdata);
|
||||
|
||||
xgbe_phy_sfp_reset(phy_data);
|
||||
xgbe_phy_sfp_mod_absent(pdata);
|
||||
goto put;
|
||||
|
|
@ -3506,6 +3551,11 @@ xgbe_phy_start(struct xgbe_prv_data *pdata)
|
|||
switch (phy_data->port_mode) {
|
||||
case XGBE_PORT_MODE_SFP:
|
||||
axgbe_printf(3, "%s: calling phy detect\n", __func__);
|
||||
|
||||
/* Validate the contents of the GPIO expander */
|
||||
axgbe_printf(0, "Checking GPIO expander validity\n");
|
||||
xgbe_phy_validate_gpio_expander(pdata);
|
||||
|
||||
xgbe_phy_sfp_detect(pdata);
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
Loading…
Reference in a new issue