#include <common.h>
#include <command.h>
+#include <dm.h>
#include <i2c.h>
#include <cros_ec.h>
#include <fdtdec.h>
#include <asm/errno.h>
#include <asm/io.h>
#include <asm-generic/gpio.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
#ifdef DEBUG_TRACE
#define debug_trace(fmt, b...) debug(fmt, #b)
CROS_EC_CMD_HASH_TIMEOUT_MS = 2000,
};
+#ifndef CONFIG_DM_CROS_EC
static struct cros_ec_dev static_dev, *last_dev;
+#endif
DECLARE_GLOBAL_DATA_PTR;
const void *dout, int dout_len,
uint8_t **dinp, int din_len)
{
+#ifdef CONFIG_DM_CROS_EC
+ struct dm_cros_ec_ops *ops;
+#endif
int out_bytes, in_bytes;
int rv;
if (in_bytes < 0)
return in_bytes;
+#ifdef CONFIG_DM_CROS_EC
+ ops = dm_cros_ec_get_ops(dev->dev);
+ rv = ops->packet(dev->dev, out_bytes, in_bytes);
+#else
switch (dev->interface) {
#ifdef CONFIG_CROS_EC_SPI
case CROS_EC_IF_SPI:
debug("%s: Unsupported interface\n", __func__);
rv = -1;
}
+#endif
if (rv < 0)
return rv;
const void *dout, int dout_len,
uint8_t **dinp, int din_len)
{
+#ifdef CONFIG_DM_CROS_EC
+ struct dm_cros_ec_ops *ops;
+#endif
int ret = -1;
/* Handle protocol version 3 support */
dout, dout_len, dinp, din_len);
}
+#ifdef CONFIG_DM_CROS_EC
+ ops = dm_cros_ec_get_ops(dev->dev);
+ ret = ops->command(dev->dev, cmd, cmd_version,
+ (const uint8_t *)dout, dout_len, dinp, din_len);
+#else
switch (dev->interface) {
#ifdef CONFIG_CROS_EC_SPI
case CROS_EC_IF_SPI:
default:
ret = -1;
}
+#endif
return ret;
}
return 0;
}
+#ifndef CONFIG_DM_CROS_EC
/**
* Decode EC interface details from the device tree and allocate a suitable
* device.
return 0;
}
+#endif
-int cros_ec_init(const void *blob, struct cros_ec_dev **cros_ecp)
+#ifdef CONFIG_DM_CROS_EC
+int cros_ec_register(struct udevice *dev)
{
+ struct cros_ec_dev *cdev = dev->uclass_priv;
+ const void *blob = gd->fdt_blob;
+ int node = dev->of_offset;
char id[MSG_BYTES];
+
+ cdev->dev = dev;
+ fdtdec_decode_gpio(blob, node, "ec-interrupt", &cdev->ec_int);
+ cdev->optimise_flash_write = fdtdec_get_bool(blob, node,
+ "optimise-flash-write");
+
+ /* we will poll the EC interrupt line */
+ fdtdec_setup_gpio(&cdev->ec_int);
+ if (fdt_gpio_isvalid(&cdev->ec_int)) {
+ gpio_request(cdev->ec_int.gpio, "cros-ec-irq");
+ gpio_direction_input(cdev->ec_int.gpio);
+ }
+
+ if (cros_ec_check_version(cdev)) {
+ debug("%s: Could not detect CROS-EC version\n", __func__);
+ return -CROS_EC_ERR_CHECK_VERSION;
+ }
+
+ if (cros_ec_read_id(cdev, id, sizeof(id))) {
+ debug("%s: Could not read KBC ID\n", __func__);
+ return -CROS_EC_ERR_READ_ID;
+ }
+
+ /* Remember this device for use by the cros_ec command */
+ debug("Google Chrome EC CROS-EC driver ready, id '%s'\n", id);
+
+ return 0;
+}
+#else
+int cros_ec_init(const void *blob, struct cros_ec_dev **cros_ecp)
+{
struct cros_ec_dev *dev;
+ char id[MSG_BYTES];
+#ifdef CONFIG_DM_CROS_EC
+ struct udevice *udev;
+ int ret;
+
+ ret = uclass_find_device(UCLASS_CROS_EC, 0, &udev);
+ if (!ret)
+ device_remove(udev);
+ ret = uclass_get_device(UCLASS_CROS_EC, 0, &udev);
+ if (ret)
+ return ret;
+ dev = udev->uclass_priv;
+ return 0;
+#else
int node = 0;
*cros_ecp = NULL;
default:
return 0;
}
+#endif
/* we will poll the EC interrupt line */
fdtdec_setup_gpio(&dev->ec_int);
- if (fdt_gpio_isvalid(&dev->ec_int))
+ if (fdt_gpio_isvalid(&dev->ec_int)) {
+ gpio_request(dev->ec_int.gpio, "cros-ec-irq");
gpio_direction_input(dev->ec_int.gpio);
+ }
if (cros_ec_check_version(dev)) {
debug("%s: Could not detect CROS-EC version\n", __func__);
}
/* Remember this device for use by the cros_ec command */
- last_dev = *cros_ecp = dev;
+ *cros_ecp = dev;
+#ifndef CONFIG_DM_CROS_EC
+ last_dev = dev;
+#endif
debug("Google Chrome EC CROS-EC driver ready, id '%s'\n", id);
return 0;
}
+#endif
int cros_ec_decode_region(int argc, char * const argv[])
{
return -1;
}
-int cros_ec_decode_ec_flash(const void *blob, struct fdt_cros_ec *config)
+int cros_ec_decode_ec_flash(const void *blob, int node,
+ struct fdt_cros_ec *config)
{
- int flash_node, node;
-
- node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_CROS_EC);
- if (node < 0) {
- debug("Failed to find chrome-ec node'\n");
- return -1;
- }
+ int flash_node;
flash_node = fdt_subnode_offset(blob, node, "flash");
if (flash_node < 0) {
static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- struct cros_ec_dev *dev = last_dev;
+ struct cros_ec_dev *dev;
+#ifdef CONFIG_DM_CROS_EC
+ struct udevice *udev;
+#endif
const char *cmd;
int ret = 0;
cmd = argv[1];
if (0 == strcmp("init", cmd)) {
+#ifndef CONFIG_DM_CROS_EC
ret = cros_ec_init(gd->fdt_blob, &dev);
if (ret) {
printf("Could not init cros_ec device (err %d)\n", ret);
return 1;
}
+#endif
return 0;
}
+#ifdef CONFIG_DM_CROS_EC
+ ret = uclass_get_device(UCLASS_CROS_EC, 0, &udev);
+ if (ret) {
+ printf("Cannot get cros-ec device (err=%d)\n", ret);
+ return 1;
+ }
+ dev = udev->uclass_priv;
+#else
/* Just use the last allocated device; there should be only one */
if (!last_dev) {
printf("No CROS-EC device available\n");
return 1;
}
+ dev = last_dev;
+#endif
if (0 == strcmp("id", cmd)) {
char id[MSG_BYTES];
"crosec i2c mw chip address[.0, .1, .2] value [count] - write to I2C passthru (fill)"
);
#endif
+
+#ifdef CONFIG_DM_CROS_EC
+UCLASS_DRIVER(cros_ec) = {
+ .id = UCLASS_CROS_EC,
+ .name = "cros_ec",
+ .per_device_auto_alloc_size = sizeof(struct cros_ec_dev),
+};
+#endif
#include <fdtdec.h>
#include <cros_ec_message.h>
+#ifndef CONFIG_DM_CROS_EC
/* Which interface is the device on? */
enum cros_ec_interface_t {
CROS_EC_IF_NONE,
CROS_EC_IF_LPC, /* Intel Low Pin Count interface */
CROS_EC_IF_SANDBOX,
};
+#endif
/* Our configuration information */
struct cros_ec_dev {
+#ifdef CONFIG_DM_CROS_EC
+ struct udevice *dev; /* Transport device */
+#else
enum cros_ec_interface_t interface;
struct spi_slave *spi; /* Our SPI slave, if using SPI */
int node; /* Our node */
unsigned int addr; /* Device address (for I2C) */
unsigned int bus_num; /* Bus number (for I2C) */
unsigned int max_frequency; /* Maximum interface frequency */
+#endif
struct fdt_gpio_state ec_int; /* GPIO used as EC interrupt line */
int protocol_version; /* Protocol version to use */
int optimise_flash_write; /* Don't write erased flash blocks */
*/
struct cros_ec_dev *board_get_cros_ec_dev(void);
+#ifdef CONFIG_DM_CROS_EC
+
+struct dm_cros_ec_ops {
+ int (*check_version)(struct udevice *dev);
+ int (*command)(struct udevice *dev, uint8_t cmd, int cmd_version,
+ const uint8_t *dout, int dout_len,
+ uint8_t **dinp, int din_len);
+ int (*packet)(struct udevice *dev, int out_bytes, int in_bytes);
+};
+
+#define dm_cros_ec_get_ops(dev) \
+ ((struct dm_cros_ec_ops *)(dev)->driver->ops)
+
+int cros_ec_register(struct udevice *dev);
+
+#else /* !CONFIG_DM_CROS_EC */
/* Internal interfaces */
int cros_ec_i2c_init(struct cros_ec_dev *dev, const void *blob);
int cros_ec_spi_packet(struct cros_ec_dev *dev, int out_bytes, int in_bytes);
int cros_ec_sandbox_packet(struct cros_ec_dev *dev, int out_bytes,
int in_bytes);
+#endif
/**
* Dump a block of data for a command.
* Returns information from the FDT about the Chrome EC flash
*
* @param blob FDT blob to use
+ * @param node Node offset to read from
* @param config Structure to use to return information
*/
-int cros_ec_decode_ec_flash(const void *blob, struct fdt_cros_ec *config);
+int cros_ec_decode_ec_flash(const void *blob, int node,
+ struct fdt_cros_ec *config);
/**
* Check the current keyboard state, in case recovery mode is requested.