struct i2c_gpio_private_data { struct gpio_desc *sda; struct gpio_desc *scl; struct i2c_adapter adap; struct i2c_algo_bit_data bit_data; struct i2c_gpio_platform_data pdata; #ifdef CONFIG_I2C_GPIO_FAULT_INJECTOR /* these must be protected by bus lock */ struct completion scl_irq_completion;
u64 scl_irq_data; #endif
};
/* * Toggle SDA by changing the output value of the pin. This is only * valid for pins configured as open drain (i.e. setting the value * high effectively turns off the output driver.)
*/ staticvoid i2c_gpio_setsda_val(void *data, int state)
{ struct i2c_gpio_private_data *priv = data;
gpiod_set_value_cansleep(priv->sda, state);
}
/* * Toggle SCL by changing the output value of the pin. This is used * for pins that are configured as open drain and for output-only * pins. The latter case will break the i2c protocol, but it will * often work in practice.
*/ staticvoid i2c_gpio_setscl_val(void *data, int state)
{ struct i2c_gpio_private_data *priv = data;
priv->scl_irq_data = duration; /* * Interrupt on falling SCL. This ensures that the controller under test * has really started the transfer. Interrupt on falling SDA did only * exercise 'bus busy' detection on some HW but not 'arbitration lost'. * Note that the interrupt latency may cause the first bits to be * transmitted correctly.
*/ return i2c_gpio_fi_act_on_scl_irq(priv, lose_arbitration_irq);
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_lose_arbitration, NULL, fops_lose_arbitration_set, "%llu\n");
priv->scl_irq_data = duration; /* * Interrupt on falling SCL. This ensures that the controller under test * has really started the transfer.
*/ return i2c_gpio_fi_act_on_scl_irq(priv, inject_panic_irq);
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_inject_panic, NULL, fops_inject_panic_set, "%llu\n");
if (fwnode) {
i2c_gpio_get_properties(dev, pdata);
} else { /* * If all platform data settings are zero it is OK * to not provide any platform data from the board.
*/ if (dev_get_platdata(dev))
memcpy(pdata, dev_get_platdata(dev), sizeof(*pdata));
}
/* * First get the GPIO pins; if it fails, we'll defer the probe. * If the SCL/SDA lines are marked "open drain" by platform data or * device tree then this means that something outside of our control is * marking these lines to be handled as open drain, and we should just * handle them as we handle any other output. Else we enforce open * drain as this is required for an I2C bus.
*/ if (pdata->sda_is_open_drain || pdata->sda_has_no_pullup)
gflags = GPIOD_OUT_HIGH; else
gflags = GPIOD_OUT_HIGH_OPEN_DRAIN;
priv->sda = i2c_gpio_get_desc(dev, "sda", 0, gflags); if (IS_ERR(priv->sda)) return PTR_ERR(priv->sda);
adap->nr = pdev->id;
ret = i2c_bit_add_numbered_bus(adap); if (ret) return ret;
platform_set_drvdata(pdev, priv);
/* * FIXME: using global GPIO numbers is not helpful. If/when we * get accessors to get the actual name of the GPIO line, * from the descriptor, then provide that instead.
*/
dev_info(dev, "using lines %u (SDA) and %u (SCL%s)\n",
desc_to_gpio(priv->sda), desc_to_gpio(priv->scl),
pdata->scl_is_output_only
? ", no clock stretching" : "");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.