summaryrefslogtreecommitdiff
path: root/drivers/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/cros_ec.c2
-rw-r--r--drivers/misc/cros_ec_i2c.c110
-rw-r--r--drivers/misc/cros_ec_sandbox.c4
-rw-r--r--drivers/misc/i2c_eeprom_emul.c4
-rw-r--r--drivers/misc/tegra186_bpmp.c8
-rw-r--r--drivers/misc/tegra_car.c4
6 files changed, 110 insertions, 22 deletions
diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c
index 759bb46..3d449b2 100644
--- a/drivers/misc/cros_ec.c
+++ b/drivers/misc/cros_ec.c
@@ -998,7 +998,7 @@ int cros_ec_register(struct udevice *dev)
{
struct cros_ec_dev *cdev = dev_get_uclass_priv(dev);
const void *blob = gd->fdt_blob;
- int node = dev->of_offset;
+ int node = dev_of_offset(dev);
char id[MSG_BYTES];
cdev->dev = dev;
diff --git a/drivers/misc/cros_ec_i2c.c b/drivers/misc/cros_ec_i2c.c
index 3de18b2..6e09340 100644
--- a/drivers/misc/cros_ec_i2c.c
+++ b/drivers/misc/cros_ec_i2c.c
@@ -24,11 +24,96 @@
#define debug_trace(fmt, b...)
#endif
+/**
+ * Request format for protocol v3
+ * byte 0 0xda (EC_COMMAND_PROTOCOL_3)
+ * byte 1-8 struct ec_host_request
+ * byte 10- response data
+ */
+struct ec_host_request_i2c {
+ /* Always 0xda to backward compatible with v2 struct */
+ uint8_t command_protocol;
+ struct ec_host_request ec_request;
+} __packed;
+
+/*
+ * Response format for protocol v3
+ * byte 0 result code
+ * byte 1 packet_length
+ * byte 2-9 struct ec_host_response
+ * byte 10- response data
+ */
+struct ec_host_response_i2c {
+ uint8_t result;
+ uint8_t packet_length;
+ struct ec_host_response ec_response;
+} __packed;
+
+static int cros_ec_i2c_packet(struct udevice *udev, int out_bytes, int in_bytes)
+{
+ struct cros_ec_dev *dev = dev_get_uclass_priv(udev);
+ struct dm_i2c_chip *chip = dev_get_parent_platdata(udev);
+ struct ec_host_request_i2c *ec_request_i2c =
+ (struct ec_host_request_i2c *)dev->dout;
+ struct ec_host_response_i2c *ec_response_i2c =
+ (struct ec_host_response_i2c *)dev->din;
+ struct i2c_msg i2c_msg[2];
+ int ret;
+
+ i2c_msg[0].addr = chip->chip_addr;
+ i2c_msg[0].flags = 0;
+ i2c_msg[1].addr = chip->chip_addr;
+ i2c_msg[1].flags = I2C_M_RD;
+
+ /* one extra byte, to indicate v3 */
+ i2c_msg[0].len = out_bytes + 1;
+ i2c_msg[0].buf = dev->dout;
+
+ /* stitch on EC_COMMAND_PROTOCOL_3 */
+ memmove(&ec_request_i2c->ec_request, dev->dout, out_bytes);
+ ec_request_i2c->command_protocol = EC_COMMAND_PROTOCOL_3;
+
+ /* two extra bytes for v3 */
+ i2c_msg[1].len = in_bytes + 2;
+ i2c_msg[1].buf = dev->din;
+
+ ret = dm_i2c_xfer(udev, &i2c_msg[0], 2);
+ if (ret) {
+ printf("%s: Could not execute transfer: %d\n", __func__, ret);
+ return ret;
+ }
+
+ /* When we send a v3 request to v2 ec, ec won't recognize the 0xda
+ * (EC_COMMAND_PROTOCOL_3) and will return with status
+ * EC_RES_INVALID_COMMAND with zero data length
+ *
+ * In case of invalid command for v3 protocol the data length
+ * will be at least sizeof(struct ec_host_response)
+ */
+ if (ec_response_i2c->result == EC_RES_INVALID_COMMAND &&
+ ec_response_i2c->packet_length == 0)
+ return -EPROTONOSUPPORT;
+
+ if (ec_response_i2c->packet_length < sizeof(struct ec_host_response)) {
+ printf("%s: response of %u bytes too short; not a full hdr\n",
+ __func__, ec_response_i2c->packet_length);
+ return -EBADMSG;
+ }
+
+
+ /* drop result and packet_len */
+ memmove(dev->din, &ec_response_i2c->ec_response, in_bytes);
+
+ return in_bytes;
+}
+
static int cros_ec_i2c_command(struct udevice *udev, uint8_t cmd,
int cmd_version, const uint8_t *dout,
int dout_len, uint8_t **dinp, int din_len)
{
struct cros_ec_dev *dev = dev_get_uclass_priv(udev);
+ struct dm_i2c_chip *chip = dev_get_parent_platdata(udev);
+ struct i2c_msg i2c_msg[2];
/* version8, cmd8, arglen8, out8[dout_len], csum8 */
int out_bytes = dout_len + 4;
/* response8, arglen8, in8[din_len], checksum8 */
@@ -53,6 +138,11 @@ static int cros_ec_i2c_command(struct udevice *udev, uint8_t cmd,
assert(dout_len >= 0);
assert(dinp);
+ i2c_msg[0].addr = chip->chip_addr;
+ i2c_msg[0].len = out_bytes;
+ i2c_msg[0].buf = dev->dout;
+ i2c_msg[0].flags = 0;
+
/*
* Copy command and data into output buffer so we can do a single I2C
* burst transaction.
@@ -85,24 +175,21 @@ static int cros_ec_i2c_command(struct udevice *udev, uint8_t cmd,
*ptr++ = (uint8_t)
cros_ec_calc_checksum(dev->dout, dout_len + 3);
+ i2c_msg[1].addr = chip->chip_addr;
+ i2c_msg[1].len = in_bytes;
+ i2c_msg[1].buf = in_ptr;
+ i2c_msg[1].flags = I2C_M_RD;
+
/* Send output data */
cros_ec_dump_data("out", -1, dev->dout, out_bytes);
- ret = dm_i2c_write(udev, 0, dev->dout, out_bytes);
+
+ ret = dm_i2c_xfer(udev, &i2c_msg[0], 2);
if (ret) {
- debug("%s: Cannot complete I2C write to %s\n", __func__,
+ debug("%s: Could not execute transfer to %s\n", __func__,
udev->name);
ret = -1;
}
- if (!ret) {
- ret = dm_i2c_read(udev, 0, in_ptr, in_bytes);
- if (ret) {
- debug("%s: Cannot complete I2C read from %s\n",
- __func__, udev->name);
- ret = -1;
- }
- }
-
if (*in_ptr != EC_RES_SUCCESS) {
debug("%s: Received bad result code %d\n", __func__, *in_ptr);
return -(int)*in_ptr;
@@ -136,6 +223,7 @@ static int cros_ec_probe(struct udevice *dev)
static struct dm_cros_ec_ops cros_ec_ops = {
.command = cros_ec_i2c_command,
+ .packet = cros_ec_i2c_packet,
};
static const struct udevice_id cros_ec_ids[] = {
diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c
index c4fbca0..848c67b 100644
--- a/drivers/misc/cros_ec_sandbox.c
+++ b/drivers/misc/cros_ec_sandbox.c
@@ -522,7 +522,7 @@ int cros_ec_probe(struct udevice *dev)
int err;
memcpy(ec, &s_state, sizeof(*ec));
- err = cros_ec_decode_ec_flash(blob, dev->of_offset, &ec->ec_config);
+ err = cros_ec_decode_ec_flash(blob, dev_of_offset(dev), &ec->ec_config);
if (err)
return err;
@@ -531,7 +531,7 @@ int cros_ec_probe(struct udevice *dev)
keyb_dev;
device_find_next_child(&keyb_dev)) {
if (device_get_uclass_id(keyb_dev) == UCLASS_KEYBOARD) {
- node = keyb_dev->of_offset;
+ node = dev_of_offset(keyb_dev);
break;
}
}
diff --git a/drivers/misc/i2c_eeprom_emul.c b/drivers/misc/i2c_eeprom_emul.c
index 4410d03..02de8d7 100644
--- a/drivers/misc/i2c_eeprom_emul.c
+++ b/drivers/misc/i2c_eeprom_emul.c
@@ -115,9 +115,9 @@ static int sandbox_i2c_eeprom_ofdata_to_platdata(struct udevice *dev)
{
struct sandbox_i2c_flash_plat_data *plat = dev_get_platdata(dev);
- plat->size = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+ plat->size = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
"sandbox,size", 32);
- plat->filename = fdt_getprop(gd->fdt_blob, dev->of_offset,
+ plat->filename = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
"sandbox,filename", NULL);
if (!plat->filename) {
debug("%s: No filename for device '%s'\n", __func__,
diff --git a/drivers/misc/tegra186_bpmp.c b/drivers/misc/tegra186_bpmp.c
index f4ddbea3..bd8b960 100644
--- a/drivers/misc/tegra186_bpmp.c
+++ b/drivers/misc/tegra186_bpmp.c
@@ -112,19 +112,19 @@ static int tegra186_bpmp_bind(struct udevice *dev)
debug("%s(dev=%p)\n", __func__, dev);
ret = device_bind_driver_to_node(dev, "tegra186_clk", "tegra186_clk",
- dev->of_offset, &child);
+ dev_of_offset(dev), &child);
if (ret)
return ret;
ret = device_bind_driver_to_node(dev, "tegra186_reset",
- "tegra186_reset", dev->of_offset,
+ "tegra186_reset", dev_of_offset(dev),
&child);
if (ret)
return ret;
ret = device_bind_driver_to_node(dev, "tegra186_power_domain",
"tegra186_power_domain",
- dev->of_offset, &child);
+ dev_of_offset(dev), &child);
if (ret)
return ret;
@@ -141,7 +141,7 @@ static ulong tegra186_bpmp_get_shmem(struct udevice *dev, int index)
struct fdtdec_phandle_args args;
fdt_addr_t reg;
- ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
+ ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev),
"shmem", NULL, 0, index, &args);
if (ret < 0) {
error("fdtdec_parse_phandle_with_args() failed: %d\n", ret);
diff --git a/drivers/misc/tegra_car.c b/drivers/misc/tegra_car.c
index 0eb0096..5db3c37 100644
--- a/drivers/misc/tegra_car.c
+++ b/drivers/misc/tegra_car.c
@@ -22,12 +22,12 @@ static int tegra_car_bpmp_bind(struct udevice *dev)
debug("%s(dev=%p)\n", __func__, dev);
ret = device_bind_driver_to_node(dev, "tegra_car_clk", "tegra_car_clk",
- dev->of_offset, &child);
+ dev_of_offset(dev), &child);
if (ret)
return ret;
ret = device_bind_driver_to_node(dev, "tegra_car_reset",
- "tegra_car_reset", dev->of_offset,
+ "tegra_car_reset", dev_of_offset(dev),
&child);
if (ret)
return ret;