Skip to content
Snippets Groups Projects
Commit 84d6cbd3 authored by Simon Glass's avatar Simon Glass
Browse files

dm: cros_ec: Add support for driver model


Add support for driver model if enabled. This involves minimal changes
to the code, mostly just plumbing around the edges.

Signed-off-by: default avatarSimon Glass <sjg@chromium.org>
Acked-by: default avatarJagannadha Sutradharudu Teki <jagannadh.teki@gmail.com>
parent fda6fac3
No related branches found
No related tags found
No related merge requests found
...@@ -10,25 +10,44 @@ ...@@ -10,25 +10,44 @@
#include <common.h> #include <common.h>
#include <cros_ec.h> #include <cros_ec.h>
#include <dm.h>
#include <errno.h>
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
#ifndef CONFIG_DM_CROS_EC
struct local_info { struct local_info {
struct cros_ec_dev *cros_ec_dev; /* Pointer to cros_ec device */ struct cros_ec_dev *cros_ec_dev; /* Pointer to cros_ec device */
int cros_ec_err; /* Error for cros_ec, 0 if ok */ int cros_ec_err; /* Error for cros_ec, 0 if ok */
}; };
static struct local_info local; static struct local_info local;
#endif
struct cros_ec_dev *board_get_cros_ec_dev(void) struct cros_ec_dev *board_get_cros_ec_dev(void)
{ {
#ifdef CONFIG_DM_CROS_EC
struct udevice *dev;
int ret;
ret = uclass_get_device(UCLASS_CROS_EC, 0, &dev);
if (ret) {
debug("%s: Error %d\n", __func__, ret);
return NULL;
}
return dev->uclass_priv;
#else
return local.cros_ec_dev; return local.cros_ec_dev;
#endif
} }
static int board_init_cros_ec_devices(const void *blob) static int board_init_cros_ec_devices(const void *blob)
{ {
#ifndef CONFIG_DM_CROS_EC
local.cros_ec_err = cros_ec_init(blob, &local.cros_ec_dev); local.cros_ec_err = cros_ec_init(blob, &local.cros_ec_dev);
if (local.cros_ec_err) if (local.cros_ec_err)
return -1; /* Will report in board_late_init() */ return -1; /* Will report in board_late_init() */
#endif
return 0; return 0;
} }
...@@ -40,5 +59,16 @@ int cros_ec_board_init(void) ...@@ -40,5 +59,16 @@ int cros_ec_board_init(void)
int cros_ec_get_error(void) int cros_ec_get_error(void)
{ {
#ifdef CONFIG_DM_CROS_EC
struct udevice *dev;
int ret;
ret = uclass_get_device(UCLASS_CROS_EC, 0, &dev);
if (ret && ret != -ENODEV)
return ret;
return 0;
#else
return local.cros_ec_err; return local.cros_ec_err;
#endif
} }
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <common.h> #include <common.h>
#include <command.h> #include <command.h>
#include <dm.h>
#include <i2c.h> #include <i2c.h>
#include <cros_ec.h> #include <cros_ec.h>
#include <fdtdec.h> #include <fdtdec.h>
...@@ -24,6 +25,8 @@ ...@@ -24,6 +25,8 @@
#include <asm/errno.h> #include <asm/errno.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm-generic/gpio.h> #include <asm-generic/gpio.h>
#include <dm/device-internal.h>
#include <dm/uclass-internal.h>
#ifdef DEBUG_TRACE #ifdef DEBUG_TRACE
#define debug_trace(fmt, b...) debug(fmt, #b) #define debug_trace(fmt, b...) debug(fmt, #b)
...@@ -38,7 +41,9 @@ enum { ...@@ -38,7 +41,9 @@ enum {
CROS_EC_CMD_HASH_TIMEOUT_MS = 2000, CROS_EC_CMD_HASH_TIMEOUT_MS = 2000,
}; };
#ifndef CONFIG_DM_CROS_EC
static struct cros_ec_dev static_dev, *last_dev; static struct cros_ec_dev static_dev, *last_dev;
#endif
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
...@@ -204,6 +209,9 @@ static int send_command_proto3(struct cros_ec_dev *dev, ...@@ -204,6 +209,9 @@ static int send_command_proto3(struct cros_ec_dev *dev,
const void *dout, int dout_len, const void *dout, int dout_len,
uint8_t **dinp, int din_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 out_bytes, in_bytes;
int rv; int rv;
...@@ -218,6 +226,10 @@ static int send_command_proto3(struct cros_ec_dev *dev, ...@@ -218,6 +226,10 @@ static int send_command_proto3(struct cros_ec_dev *dev,
if (in_bytes < 0) if (in_bytes < 0)
return in_bytes; 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) { switch (dev->interface) {
#ifdef CONFIG_CROS_EC_SPI #ifdef CONFIG_CROS_EC_SPI
case CROS_EC_IF_SPI: case CROS_EC_IF_SPI:
...@@ -235,6 +247,7 @@ static int send_command_proto3(struct cros_ec_dev *dev, ...@@ -235,6 +247,7 @@ static int send_command_proto3(struct cros_ec_dev *dev,
debug("%s: Unsupported interface\n", __func__); debug("%s: Unsupported interface\n", __func__);
rv = -1; rv = -1;
} }
#endif
if (rv < 0) if (rv < 0)
return rv; return rv;
...@@ -246,6 +259,9 @@ static int send_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version, ...@@ -246,6 +259,9 @@ static int send_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
const void *dout, int dout_len, const void *dout, int dout_len,
uint8_t **dinp, int din_len) uint8_t **dinp, int din_len)
{ {
#ifdef CONFIG_DM_CROS_EC
struct dm_cros_ec_ops *ops;
#endif
int ret = -1; int ret = -1;
/* Handle protocol version 3 support */ /* Handle protocol version 3 support */
...@@ -254,6 +270,11 @@ static int send_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version, ...@@ -254,6 +270,11 @@ static int send_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
dout, dout_len, dinp, din_len); 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) { switch (dev->interface) {
#ifdef CONFIG_CROS_EC_SPI #ifdef CONFIG_CROS_EC_SPI
case CROS_EC_IF_SPI: case CROS_EC_IF_SPI:
...@@ -280,6 +301,7 @@ static int send_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version, ...@@ -280,6 +301,7 @@ static int send_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
default: default:
ret = -1; ret = -1;
} }
#endif
return ret; return ret;
} }
...@@ -990,6 +1012,7 @@ int cros_ec_get_ldo(struct cros_ec_dev *dev, uint8_t index, uint8_t *state) ...@@ -990,6 +1012,7 @@ int cros_ec_get_ldo(struct cros_ec_dev *dev, uint8_t index, uint8_t *state)
return 0; return 0;
} }
#ifndef CONFIG_DM_CROS_EC
/** /**
* Decode EC interface details from the device tree and allocate a suitable * Decode EC interface details from the device tree and allocate a suitable
* device. * device.
...@@ -1055,11 +1078,61 @@ static int cros_ec_decode_fdt(const void *blob, int node, ...@@ -1055,11 +1078,61 @@ static int cros_ec_decode_fdt(const void *blob, int node,
return 0; 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]; 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; 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; int node = 0;
*cros_ecp = NULL; *cros_ecp = NULL;
...@@ -1108,11 +1181,14 @@ int cros_ec_init(const void *blob, struct cros_ec_dev **cros_ecp) ...@@ -1108,11 +1181,14 @@ int cros_ec_init(const void *blob, struct cros_ec_dev **cros_ecp)
default: default:
return 0; return 0;
} }
#endif
/* we will poll the EC interrupt line */ /* we will poll the EC interrupt line */
fdtdec_setup_gpio(&dev->ec_int); 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); gpio_direction_input(dev->ec_int.gpio);
}
if (cros_ec_check_version(dev)) { if (cros_ec_check_version(dev)) {
debug("%s: Could not detect CROS-EC version\n", __func__); debug("%s: Could not detect CROS-EC version\n", __func__);
...@@ -1125,11 +1201,15 @@ int cros_ec_init(const void *blob, struct cros_ec_dev **cros_ecp) ...@@ -1125,11 +1201,15 @@ int cros_ec_init(const void *blob, struct cros_ec_dev **cros_ecp)
} }
/* Remember this device for use by the cros_ec command */ /* 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); debug("Google Chrome EC CROS-EC driver ready, id '%s'\n", id);
return 0; return 0;
} }
#endif
int cros_ec_decode_region(int argc, char * const argv[]) int cros_ec_decode_region(int argc, char * const argv[])
{ {
...@@ -1147,15 +1227,10 @@ int cros_ec_decode_region(int argc, char * const argv[]) ...@@ -1147,15 +1227,10 @@ int cros_ec_decode_region(int argc, char * const argv[])
return -1; 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; int flash_node;
node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_CROS_EC);
if (node < 0) {
debug("Failed to find chrome-ec node'\n");
return -1;
}
flash_node = fdt_subnode_offset(blob, node, "flash"); flash_node = fdt_subnode_offset(blob, node, "flash");
if (flash_node < 0) { if (flash_node < 0) {
...@@ -1516,7 +1591,10 @@ static int cros_ec_i2c_passthrough(struct cros_ec_dev *dev, int flag, ...@@ -1516,7 +1591,10 @@ static int cros_ec_i2c_passthrough(struct cros_ec_dev *dev, int flag,
static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 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; const char *cmd;
int ret = 0; int ret = 0;
...@@ -1525,19 +1603,31 @@ static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ...@@ -1525,19 +1603,31 @@ static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
cmd = argv[1]; cmd = argv[1];
if (0 == strcmp("init", cmd)) { if (0 == strcmp("init", cmd)) {
#ifndef CONFIG_DM_CROS_EC
ret = cros_ec_init(gd->fdt_blob, &dev); ret = cros_ec_init(gd->fdt_blob, &dev);
if (ret) { if (ret) {
printf("Could not init cros_ec device (err %d)\n", ret); printf("Could not init cros_ec device (err %d)\n", ret);
return 1; return 1;
} }
#endif
return 0; 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 */ /* Just use the last allocated device; there should be only one */
if (!last_dev) { if (!last_dev) {
printf("No CROS-EC device available\n"); printf("No CROS-EC device available\n");
return 1; return 1;
} }
dev = last_dev;
#endif
if (0 == strcmp("id", cmd)) { if (0 == strcmp("id", cmd)) {
char id[MSG_BYTES]; char id[MSG_BYTES];
...@@ -1794,3 +1884,11 @@ U_BOOT_CMD( ...@@ -1794,3 +1884,11 @@ U_BOOT_CMD(
"crosec i2c mw chip address[.0, .1, .2] value [count] - write to I2C passthru (fill)" "crosec i2c mw chip address[.0, .1, .2] value [count] - write to I2C passthru (fill)"
); );
#endif #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
...@@ -525,8 +525,13 @@ int cros_ec_sandbox_init(struct cros_ec_dev *dev, const void *blob) ...@@ -525,8 +525,13 @@ int cros_ec_sandbox_init(struct cros_ec_dev *dev, const void *blob)
int node; int node;
int err; int err;
state = &s_state; node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_CROS_EC);
err = cros_ec_decode_ec_flash(blob, &ec->ec_config); if (node < 0) {
debug("Failed to find chrome-ec node'\n");
return -1;
}
err = cros_ec_decode_ec_flash(blob, node, &ec->ec_config);
if (err) if (err)
return err; return err;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <fdtdec.h> #include <fdtdec.h>
#include <cros_ec_message.h> #include <cros_ec_message.h>
#ifndef CONFIG_DM_CROS_EC
/* Which interface is the device on? */ /* Which interface is the device on? */
enum cros_ec_interface_t { enum cros_ec_interface_t {
CROS_EC_IF_NONE, CROS_EC_IF_NONE,
...@@ -22,9 +23,13 @@ enum cros_ec_interface_t { ...@@ -22,9 +23,13 @@ enum cros_ec_interface_t {
CROS_EC_IF_LPC, /* Intel Low Pin Count interface */ CROS_EC_IF_LPC, /* Intel Low Pin Count interface */
CROS_EC_IF_SANDBOX, CROS_EC_IF_SANDBOX,
}; };
#endif
/* Our configuration information */ /* Our configuration information */
struct cros_ec_dev { struct cros_ec_dev {
#ifdef CONFIG_DM_CROS_EC
struct udevice *dev; /* Transport device */
#else
enum cros_ec_interface_t interface; enum cros_ec_interface_t interface;
struct spi_slave *spi; /* Our SPI slave, if using SPI */ struct spi_slave *spi; /* Our SPI slave, if using SPI */
int node; /* Our node */ int node; /* Our node */
...@@ -33,6 +38,7 @@ struct cros_ec_dev { ...@@ -33,6 +38,7 @@ struct cros_ec_dev {
unsigned int addr; /* Device address (for I2C) */ unsigned int addr; /* Device address (for I2C) */
unsigned int bus_num; /* Bus number (for I2C) */ unsigned int bus_num; /* Bus number (for I2C) */
unsigned int max_frequency; /* Maximum interface frequency */ unsigned int max_frequency; /* Maximum interface frequency */
#endif
struct fdt_gpio_state ec_int; /* GPIO used as EC interrupt line */ struct fdt_gpio_state ec_int; /* GPIO used as EC interrupt line */
int protocol_version; /* Protocol version to use */ int protocol_version; /* Protocol version to use */
int optimise_flash_write; /* Don't write erased flash blocks */ int optimise_flash_write; /* Don't write erased flash blocks */
...@@ -233,6 +239,22 @@ int cros_ec_flash_update_rw(struct cros_ec_dev *dev, ...@@ -233,6 +239,22 @@ int cros_ec_flash_update_rw(struct cros_ec_dev *dev,
*/ */
struct cros_ec_dev *board_get_cros_ec_dev(void); 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 */ /* Internal interfaces */
int cros_ec_i2c_init(struct cros_ec_dev *dev, const void *blob); int cros_ec_i2c_init(struct cros_ec_dev *dev, const void *blob);
...@@ -336,6 +358,7 @@ int cros_ec_spi_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version, ...@@ -336,6 +358,7 @@ int cros_ec_spi_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
int cros_ec_spi_packet(struct cros_ec_dev *dev, int out_bytes, int in_bytes); 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 cros_ec_sandbox_packet(struct cros_ec_dev *dev, int out_bytes,
int in_bytes); int in_bytes);
#endif
/** /**
* Dump a block of data for a command. * Dump a block of data for a command.
...@@ -489,9 +512,11 @@ int cros_ec_get_error(void); ...@@ -489,9 +512,11 @@ int cros_ec_get_error(void);
* Returns information from the FDT about the Chrome EC flash * Returns information from the FDT about the Chrome EC flash
* *
* @param blob FDT blob to use * @param blob FDT blob to use
* @param node Node offset to read from
* @param config Structure to use to return information * @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. * Check the current keyboard state, in case recovery mode is requested.
......
...@@ -26,6 +26,7 @@ enum uclass_id { ...@@ -26,6 +26,7 @@ enum uclass_id {
UCLASS_SPI, /* SPI bus */ UCLASS_SPI, /* SPI bus */
UCLASS_SPI_GENERIC, /* Generic SPI flash target */ UCLASS_SPI_GENERIC, /* Generic SPI flash target */
UCLASS_SPI_FLASH, /* SPI flash */ UCLASS_SPI_FLASH, /* SPI flash */
UCLASS_CROS_EC, /* Chrome OS EC */
UCLASS_COUNT, UCLASS_COUNT,
UCLASS_INVALID = -1, UCLASS_INVALID = -1,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment