From d7af6a485126a0d08a0a9a56721e42a3e78b5b53 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 13 Oct 2014 23:41:52 -0600 Subject: dm: spi: Add a uclass for SPI Add a uclass which provides access to SPI buses and includes operations required by SPI. For a time driver model will need to co-exist with the legacy SPI interface so some parts of the header file are changed depending on which is in use. The exports are adjusted also since some functions are not available with driver model. Boards must define CONFIG_DM_SPI to use driver model for SPI. Signed-off-by: Simon Glass Reviewed-by: Jagannadha Sutradharudu Teki (Discussed some follow-up comments which will address in future add-ons) --- common/exports.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'common') diff --git a/common/exports.c b/common/exports.c index b97ca48307d..88fcfc8cb6f 100644 --- a/common/exports.c +++ b/common/exports.c @@ -27,10 +27,12 @@ unsigned long get_version(void) # define i2c_write dummy # define i2c_read dummy #endif -#ifndef CONFIG_CMD_SPI +#if !defined(CONFIG_CMD_SPI) || defined(CONFIG_DM_SPI) # define spi_init dummy # define spi_setup_slave dummy # define spi_free_slave dummy +#endif +#ifndef CONFIG_CMD_SPI # define spi_claim_bus dummy # define spi_release_bus dummy # define spi_xfer dummy -- cgit v1.3.1 From ebe76a2df9f6b82f41ec61d36d45bce56d556f17 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 13 Oct 2014 23:41:54 -0600 Subject: dm: Remove spi_init() from board_r.c when using driver model Driver model does its own init, so we don't need this. There is still a call in board_f.c but it is only enabled by CONFIG_HARD_SPI. It is easy enough to disable that option when converting boards which use it to driver model. Signed-off-by: Simon Glass Reviewed-by: Jagannadha Sutradharudu Teki --- common/board_r.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common') diff --git a/common/board_r.c b/common/board_r.c index 7e1a76d97f7..3affb6362f4 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -354,7 +354,7 @@ static int initr_flash(void) } #endif -#ifdef CONFIG_PPC +#if defined(CONFIG_PPC) && !defined(CONFIG_DM_SPI) static int initr_spi(void) { /* PPC does this here */ -- cgit v1.3.1 From 843c9e8796a7a6ebe0c9dec54c6a64ac29949d8f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 13 Oct 2014 23:41:55 -0600 Subject: dm: Add spi.h header to a few files Some files are using SPI functions but not explitly including the SPI header file. Fix this, since driver model needs it. Signed-off-by: Simon Glass Reviewed-by: Jagannadha Sutradharudu Teki --- common/env_sf.c | 1 + drivers/dfu/dfu_sf.c | 1 + drivers/mtd/spi/sf_params.c | 1 + 3 files changed, 3 insertions(+) (limited to 'common') diff --git a/common/env_sf.c b/common/env_sf.c index 37ab13ae178..5e3729c2c2d 100644 --- a/common/env_sf.c +++ b/common/env_sf.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/dfu/dfu_sf.c b/drivers/dfu/dfu_sf.c index 91f6df220b1..c3d3c3bcd85 100644 --- a/drivers/dfu/dfu_sf.c +++ b/drivers/dfu/dfu_sf.c @@ -9,6 +9,7 @@ #include #include #include +#include #include static long dfu_get_medium_size_sf(struct dfu_entity *dfu) diff --git a/drivers/mtd/spi/sf_params.c b/drivers/mtd/spi/sf_params.c index 453edf01495..61545cacaab 100644 --- a/drivers/mtd/spi/sf_params.c +++ b/drivers/mtd/spi/sf_params.c @@ -7,6 +7,7 @@ */ #include +#include #include #include "sf_internal.h" -- cgit v1.3.1 From 1157a161b0a579c7021a10384b7042a75b0cb229 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 13 Oct 2014 23:41:56 -0600 Subject: dm: spi: Adjust cmd_spi to work with driver model Driver model uses a different way to find the SPI bus and slave from the numbered devices given on the command line. Adjust the code to suit. We use a generic SPI device, and attach it to the SPI bus before performing the transaction. Signed-off-by: Simon Glass Reviewed-by: Jagannadha Sutradharudu Teki --- common/cmd_spi.c | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) (limited to 'common') diff --git a/common/cmd_spi.c b/common/cmd_spi.c index be5709c6173..64c3ffcf423 100644 --- a/common/cmd_spi.c +++ b/common/cmd_spi.c @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -42,19 +43,38 @@ static uchar din[MAX_SPI_BYTES]; static int do_spi_xfer(int bus, int cs) { struct spi_slave *slave; - int rcode = 0; - + int ret = 0; + +#ifdef CONFIG_DM_SPI + char name[30], *str; + struct udevice *dev; + + snprintf(name, sizeof(name), "generic_%d:%d", bus, cs); + str = strdup(name); + ret = spi_get_bus_and_cs(bus, cs, 1000000, mode, "spi_generic_drv", + str, &dev, &slave); + if (ret) + return ret; +#else slave = spi_setup_slave(bus, cs, 1000000, mode); if (!slave) { printf("Invalid device %d:%d\n", bus, cs); return -EINVAL; } +#endif - spi_claim_bus(slave); - if (spi_xfer(slave, bitlen, dout, din, - SPI_XFER_BEGIN | SPI_XFER_END) != 0) { - printf("Error during SPI transaction\n"); - rcode = -EIO; + ret = spi_claim_bus(slave); + if (ret) + goto done; + ret = spi_xfer(slave, bitlen, dout, din, + SPI_XFER_BEGIN | SPI_XFER_END); +#ifndef CONFIG_DM_SPI + /* We don't get an error code in this case */ + if (ret) + ret = -EIO; +#endif + if (ret) { + printf("Error %d during SPI transaction\n", ret); } else { int j; @@ -62,10 +82,13 @@ static int do_spi_xfer(int bus, int cs) printf("%02X", din[j]); printf("\n"); } +done: spi_release_bus(slave); +#ifndef CONFIG_DM_SPI spi_free_slave(slave); +#endif - return rcode; + return ret; } /* -- cgit v1.3.1 From ff0960f9a018952cbaab59c0d87b6e0338c8f04c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 13 Oct 2014 23:42:04 -0600 Subject: sf: Tidy up public and private header files Since spi_flash.h is supposed to be the public API for SPI flash, move private things to sf_internal.h. Also tidy up a few comment nits. Signed-off-by: Simon Glass Reviewed-by: Jagannadha Sutradharudu Teki --- board/buffalo/lsxl/lsxl.c | 3 +- board/renesas/sh7752evb/sh7752evb.c | 1 + board/renesas/sh7753evb/sh7753evb.c | 1 + board/renesas/sh7757lcr/sh7757lcr.c | 1 + common/cmd_sf.c | 1 + drivers/mtd/spi/ramtron.c | 1 + drivers/mtd/spi/sf_internal.h | 67 +++++++++++++++++++++++++++++++++---- drivers/mtd/spi/spi_spl_load.c | 1 + include/spi_flash.h | 57 +++---------------------------- 9 files changed, 73 insertions(+), 60 deletions(-) (limited to 'common') diff --git a/board/buffalo/lsxl/lsxl.c b/board/buffalo/lsxl/lsxl.c index 659a124b227..c1cb07b2782 100644 --- a/board/buffalo/lsxl/lsxl.c +++ b/board/buffalo/lsxl/lsxl.c @@ -13,11 +13,12 @@ #include #include #include +#include +#include #include #include #include #include -#include #include "lsxl.h" diff --git a/board/renesas/sh7752evb/sh7752evb.c b/board/renesas/sh7752evb/sh7752evb.c index 5eedbf8ce66..3aad532367b 100644 --- a/board/renesas/sh7752evb/sh7752evb.c +++ b/board/renesas/sh7752evb/sh7752evb.c @@ -9,6 +9,7 @@ #include #include #include +#include #include int checkboard(void) diff --git a/board/renesas/sh7753evb/sh7753evb.c b/board/renesas/sh7753evb/sh7753evb.c index 42b920fb333..9f6494561c6 100644 --- a/board/renesas/sh7753evb/sh7753evb.c +++ b/board/renesas/sh7753evb/sh7753evb.c @@ -9,6 +9,7 @@ #include #include #include +#include #include int checkboard(void) diff --git a/board/renesas/sh7757lcr/sh7757lcr.c b/board/renesas/sh7757lcr/sh7757lcr.c index 1464f48b43a..ddcf275f6e7 100644 --- a/board/renesas/sh7757lcr/sh7757lcr.c +++ b/board/renesas/sh7757lcr/sh7757lcr.c @@ -9,6 +9,7 @@ #include #include #include +#include #include int checkboard(void) diff --git a/common/cmd_sf.c b/common/cmd_sf.c index c60e8d10df6..42d89d4f072 100644 --- a/common/cmd_sf.c +++ b/common/cmd_sf.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include diff --git a/drivers/mtd/spi/ramtron.c b/drivers/mtd/spi/ramtron.c index d50da37c89a..a23032cca58 100644 --- a/drivers/mtd/spi/ramtron.c +++ b/drivers/mtd/spi/ramtron.c @@ -35,6 +35,7 @@ #include #include +#include #include #include "sf_internal.h" diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 19d49146ebd..5b7670c9aaf 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -10,6 +10,36 @@ #ifndef _SF_INTERNAL_H_ #define _SF_INTERNAL_H_ +#include +#include + +/* Dual SPI flash memories - see SPI_COMM_DUAL_... */ +enum spi_dual_flash { + SF_SINGLE_FLASH = 0, + SF_DUAL_STACKED_FLASH = 1 << 0, + SF_DUAL_PARALLEL_FLASH = 1 << 1, +}; + +/* Enum list - Full read commands */ +enum spi_read_cmds { + ARRAY_SLOW = 1 << 0, + DUAL_OUTPUT_FAST = 1 << 1, + DUAL_IO_FAST = 1 << 2, + QUAD_OUTPUT_FAST = 1 << 3, + QUAD_IO_FAST = 1 << 4, +}; + +#define RD_EXTN (ARRAY_SLOW | DUAL_OUTPUT_FAST | DUAL_IO_FAST) +#define RD_FULL (RD_EXTN | QUAD_OUTPUT_FAST | QUAD_IO_FAST) + +/* sf param flags */ +enum { + SECT_4K = 1 << 0, + SECT_32K = 1 << 1, + E_FSR = 1 << 2, + WR_QPP = 1 << 3, +}; + #define SPI_FLASH_3B_ADDR_LEN 3 #define SPI_FLASH_CMD_LEN (1 + SPI_FLASH_3B_ADDR_LEN) #define SPI_FLASH_16MB_BOUN 0x1000000 @@ -30,12 +60,12 @@ #define CMD_WRITE_STATUS 0x01 #define CMD_PAGE_PROGRAM 0x02 #define CMD_WRITE_DISABLE 0x04 -#define CMD_READ_STATUS 0x05 +#define CMD_READ_STATUS 0x05 #define CMD_QUAD_PAGE_PROGRAM 0x32 #define CMD_READ_STATUS1 0x35 #define CMD_WRITE_ENABLE 0x06 -#define CMD_READ_CONFIG 0x35 -#define CMD_FLAG_STATUS 0x70 +#define CMD_READ_CONFIG 0x35 +#define CMD_FLAG_STATUS 0x70 /* Read commands */ #define CMD_READ_ARRAY_SLOW 0x03 @@ -57,7 +87,7 @@ /* Common status */ #define STATUS_WIP (1 << 0) #define STATUS_QEB_WINSPAN (1 << 1) -#define STATUS_QEB_MXIC (1 << 6) +#define STATUS_QEB_MXIC (1 << 6) #define STATUS_PEC (1 << 7) #ifdef CONFIG_SYS_SPI_ST_ENABLE_WP_PIN @@ -66,19 +96,42 @@ /* Flash timeout values */ #define SPI_FLASH_PROG_TIMEOUT (2 * CONFIG_SYS_HZ) -#define SPI_FLASH_PAGE_ERASE_TIMEOUT (5 * CONFIG_SYS_HZ) +#define SPI_FLASH_PAGE_ERASE_TIMEOUT (5 * CONFIG_SYS_HZ) #define SPI_FLASH_SECTOR_ERASE_TIMEOUT (10 * CONFIG_SYS_HZ) /* SST specific */ #ifdef CONFIG_SPI_FLASH_SST -# define SST_WP 0x01 /* Supports AAI word program */ +# define SST_WP 0x01 /* Supports AAI word program */ # define CMD_SST_BP 0x02 /* Byte Program */ -# define CMD_SST_AAI_WP 0xAD /* Auto Address Incr Word Program */ +# define CMD_SST_AAI_WP 0xAD /* Auto Address Incr Word Program */ int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, const void *buf); #endif +/** + * struct spi_flash_params - SPI/QSPI flash device params structure + * + * @name: Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO]) + * @jedec: Device jedec ID (0x[1byte_manuf_id][2byte_dev_id]) + * @ext_jedec: Device ext_jedec ID + * @sector_size: Sector size of this device + * @nr_sectors: No.of sectors on this device + * @e_rd_cmd: Enum list for read commands + * @flags: Important param, for flash specific behaviour + */ +struct spi_flash_params { + const char *name; + u32 jedec; + u16 ext_jedec; + u32 sector_size; + u32 nr_sectors; + u8 e_rd_cmd; + u16 flags; +}; + +extern const struct spi_flash_params spi_flash_params_table[]; + /* Send a single-byte command to the device and read the response */ int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len); diff --git a/drivers/mtd/spi/spi_spl_load.c b/drivers/mtd/spi/spi_spl_load.c index 59cca0f4d99..2e0c871219b 100644 --- a/drivers/mtd/spi/spi_spl_load.c +++ b/drivers/mtd/spi/spi_spl_load.c @@ -10,6 +10,7 @@ */ #include +#include #include #include diff --git a/include/spi_flash.h b/include/spi_flash.h index 408a5b401cd..223e4420a5e 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -15,9 +15,7 @@ #ifndef _SPI_FLASH_H_ #define _SPI_FLASH_H_ -#include #include -#include #ifndef CONFIG_SF_DEFAULT_SPEED # define CONFIG_SF_DEFAULT_SPEED 1000000 @@ -32,64 +30,19 @@ # define CONFIG_SF_DEFAULT_BUS 0 #endif -/* sf param flags */ -#define SECT_4K 1 << 1 -#define SECT_32K 1 << 2 -#define E_FSR 1 << 3 -#define WR_QPP 1 << 4 - -/* Enum list - Full read commands */ -enum spi_read_cmds { - ARRAY_SLOW = 1 << 0, - DUAL_OUTPUT_FAST = 1 << 1, - DUAL_IO_FAST = 1 << 2, - QUAD_OUTPUT_FAST = 1 << 3, - QUAD_IO_FAST = 1 << 4, -}; -#define RD_EXTN ARRAY_SLOW | DUAL_OUTPUT_FAST | DUAL_IO_FAST -#define RD_FULL RD_EXTN | QUAD_OUTPUT_FAST | QUAD_IO_FAST - -/* Dual SPI flash memories */ -enum spi_dual_flash { - SF_SINGLE_FLASH = 0, - SF_DUAL_STACKED_FLASH = 1 << 0, - SF_DUAL_PARALLEL_FLASH = 1 << 1, -}; - -/** - * struct spi_flash_params - SPI/QSPI flash device params structure - * - * @name: Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO]) - * @jedec: Device jedec ID (0x[1byte_manuf_id][2byte_dev_id]) - * @ext_jedec: Device ext_jedec ID - * @sector_size: Sector size of this device - * @nr_sectors: No.of sectors on this device - * @e_rd_cmd: Enum list for read commands - * @flags: Important param, for flash specific behaviour - */ -struct spi_flash_params { - const char *name; - u32 jedec; - u16 ext_jedec; - u32 sector_size; - u32 nr_sectors; - u8 e_rd_cmd; - u16 flags; -}; - -extern const struct spi_flash_params spi_flash_params_table[]; +struct spi_slave; /** * struct spi_flash - SPI flash structure * * @spi: SPI slave * @name: Name of SPI flash - * @dual_flash: Indicates dual flash memories - dual stacked, parallel + * @dual_flash: Indicates dual flash memories - dual stacked, parallel * @shift: Flash shift useful in dual parallel * @size: Total flash size * @page_size: Write (page) size * @sector_size: Sector size - * @erase_size: Erase size + * @erase_size: Erase size * @bank_read_cmd: Bank read cmd * @bank_write_cmd: Bank write cmd * @bank_curr: Current flash bank @@ -97,8 +50,8 @@ extern const struct spi_flash_params spi_flash_params_table[]; * @erase_cmd: Erase cmd 4K, 32K, 64K * @read_cmd: Read cmd - Array Fast, Extn read and quad read. * @write_cmd: Write cmd - page and quad program. - * @dummy_byte: Dummy cycles for read operation. - * @memory_map: Address of read-only SPI flash access + * @dummy_byte: Dummy cycles for read operation. + * @memory_map: Address of read-only SPI flash access * @read: Flash read ops: Read len bytes at offset into buf * Supported cmds: Fast Array Read * @write: Flash write ops: Write len bytes from buf into offset -- cgit v1.3.1 From fbb099183e3a53f77a975964cdf2e73d11e565af Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 13 Oct 2014 23:42:07 -0600 Subject: dm: Convert spi_flash_probe() and 'sf probe' to use driver model We want the SPI flash probing feature to operate as a standard driver. Add a driver for the basic probing feature used by most boards. This will be activated by device_probe() as with any other driver. The 'sf probe' command currently keeps track of the SPI slave that it last used. This doesn't work with driver model, since some other driver or system may have probed the device and have access to it too. On the other hand, if we try to probe a device twice the second probe is a nop with driver model. Fix this by searching for the matching device, removing it, and then probing it again. This should work as expected regardless of other device activity. Signed-off-by: Simon Glass Reviewed-by: Jagannadha Sutradharudu Teki --- common/cmd_sf.c | 25 ++++++++++++++++++ drivers/mtd/spi/sf_probe.c | 66 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 89 insertions(+), 2 deletions(-) (limited to 'common') diff --git a/common/cmd_sf.c b/common/cmd_sf.c index 42d89d4f072..95a6f89a845 100644 --- a/common/cmd_sf.c +++ b/common/cmd_sf.c @@ -8,11 +8,13 @@ #include #include +#include #include #include #include #include +#include static struct spi_flash *flash; @@ -81,7 +83,12 @@ static int do_spi_flash_probe(int argc, char * const argv[]) unsigned int speed = CONFIG_SF_DEFAULT_SPEED; unsigned int mode = CONFIG_SF_DEFAULT_MODE; char *endp; +#ifdef CONFIG_DM_SPI_FLASH + struct udevice *new, *bus_dev; + int ret; +#else struct spi_flash *new; +#endif if (argc >= 2) { cs = simple_strtoul(argv[1], &endp, 0); @@ -109,6 +116,23 @@ static int do_spi_flash_probe(int argc, char * const argv[]) return -1; } +#ifdef CONFIG_DM_SPI_FLASH + /* Remove the old device, otherwise probe will just be a nop */ + ret = spi_find_bus_and_cs(bus, cs, &bus_dev, &new); + if (!ret) { + device_remove(new); + device_unbind(new); + } + flash = NULL; + ret = spi_flash_probe_bus_cs(bus, cs, speed, mode, &new); + if (ret) { + printf("Failed to initialize SPI flash at %u:%u (error %d)\n", + bus, cs, ret); + return 1; + } + + flash = new->uclass_priv; +#else new = spi_flash_probe(bus, cs, speed, mode); if (!new) { printf("Failed to initialize SPI flash at %u:%u\n", bus, cs); @@ -118,6 +142,7 @@ static int do_spi_flash_probe(int argc, char * const argv[]) if (flash) spi_flash_free(flash); flash = new; +#endif return 0; } diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 212a825adae..26364269be1 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -131,13 +132,15 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode, flash->dual_flash = flash->spi->option; /* Assign spi_flash ops */ +#ifndef CONFIG_DM_SPI_FLASH flash->write = spi_flash_cmd_write_ops; -#ifdef CONFIG_SPI_FLASH_SST +#if defined(CONFIG_SPI_FLASH_SST) if (params->flags & SST_WP) flash->write = sst_write_wp; #endif flash->erase = spi_flash_cmd_erase_ops; flash->read = spi_flash_cmd_read_ops; +#endif /* Compute the flash size */ flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0; @@ -398,7 +401,8 @@ err_read_id: return ret; } -static struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus) +#ifndef CONFIG_DM_SPI_FLASH +struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus) { struct spi_flash *flash; @@ -443,3 +447,61 @@ void spi_flash_free(struct spi_flash *flash) spi_free_slave(flash->spi); free(flash); } + +#else /* defined CONFIG_DM_SPI_FLASH */ + +static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len, + void *buf) +{ + struct spi_flash *flash = dev->uclass_priv; + + return spi_flash_cmd_read_ops(flash, offset, len, buf); +} + +int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, + const void *buf) +{ + struct spi_flash *flash = dev->uclass_priv; + + return spi_flash_cmd_write_ops(flash, offset, len, buf); +} + +int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) +{ + struct spi_flash *flash = dev->uclass_priv; + + return spi_flash_cmd_erase_ops(flash, offset, len); +} + +int spi_flash_std_probe(struct udevice *dev) +{ + struct spi_slave *slave = dev_get_parentdata(dev); + struct spi_flash *flash; + + flash = dev->uclass_priv; + flash->dev = dev; + debug("%s: slave=%p, cs=%d\n", __func__, slave, slave->cs); + return spi_flash_probe_slave(slave, flash); +} + +static const struct dm_spi_flash_ops spi_flash_std_ops = { + .read = spi_flash_std_read, + .write = spi_flash_std_write, + .erase = spi_flash_std_erase, +}; + +static const struct udevice_id spi_flash_std_ids[] = { + { .compatible = "spi-flash" }, + { } +}; + +U_BOOT_DRIVER(spi_flash_std) = { + .name = "spi_flash_std", + .id = UCLASS_SPI_FLASH, + .of_match = spi_flash_std_ids, + .probe = spi_flash_std_probe, + .priv_auto_alloc_size = sizeof(struct spi_flash), + .ops = &spi_flash_std_ops, +}; + +#endif /* CONFIG_DM_SPI_FLASH */ -- cgit v1.3.1 From 84d6cbd3029e8b16e201f1129c300fae258c0f9c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 13 Oct 2014 23:42:14 -0600 Subject: 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: Simon Glass Acked-by: Jagannadha Sutradharudu Teki --- common/cros_ec.c | 30 ++++++++++ drivers/misc/cros_ec.c | 122 +++++++++++++++++++++++++++++++++++++---- drivers/misc/cros_ec_sandbox.c | 9 ++- include/cros_ec.h | 27 ++++++++- include/dm/uclass-id.h | 1 + 5 files changed, 174 insertions(+), 15 deletions(-) (limited to 'common') diff --git a/common/cros_ec.c b/common/cros_ec.c index b8ce1b581aa..bb299bccfff 100644 --- a/common/cros_ec.c +++ b/common/cros_ec.c @@ -10,25 +10,44 @@ #include #include +#include +#include + DECLARE_GLOBAL_DATA_PTR; +#ifndef CONFIG_DM_CROS_EC struct local_info { struct cros_ec_dev *cros_ec_dev; /* Pointer to cros_ec device */ int cros_ec_err; /* Error for cros_ec, 0 if ok */ }; static struct local_info local; +#endif 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; +#endif } 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); if (local.cros_ec_err) return -1; /* Will report in board_late_init() */ +#endif return 0; } @@ -40,5 +59,16 @@ int cros_ec_board_init(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; +#endif } diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c index 068373b9426..521edfd5de5 100644 --- a/drivers/misc/cros_ec.c +++ b/drivers/misc/cros_ec.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -24,6 +25,8 @@ #include #include #include +#include +#include #ifdef DEBUG_TRACE #define debug_trace(fmt, b...) debug(fmt, #b) @@ -38,7 +41,9 @@ enum { 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; @@ -204,6 +209,9 @@ static int send_command_proto3(struct cros_ec_dev *dev, 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; @@ -218,6 +226,10 @@ static int send_command_proto3(struct cros_ec_dev *dev, 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: @@ -235,6 +247,7 @@ static int send_command_proto3(struct cros_ec_dev *dev, debug("%s: Unsupported interface\n", __func__); rv = -1; } +#endif if (rv < 0) return rv; @@ -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, 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 */ @@ -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); } +#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: @@ -280,6 +301,7 @@ static int send_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version, default: ret = -1; } +#endif return ret; } @@ -990,6 +1012,7 @@ int cros_ec_get_ldo(struct cros_ec_dev *dev, uint8_t index, uint8_t *state) return 0; } +#ifndef CONFIG_DM_CROS_EC /** * Decode EC interface details from the device tree and allocate a suitable * device. @@ -1055,11 +1078,61 @@ static int cros_ec_decode_fdt(const void *blob, int node, 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; @@ -1108,11 +1181,14 @@ int cros_ec_init(const void *blob, struct cros_ec_dev **cros_ecp) 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__); @@ -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 */ - 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[]) { @@ -1147,15 +1227,10 @@ 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) { @@ -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[]) { - 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; @@ -1525,19 +1603,31 @@ static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 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]; @@ -1794,3 +1884,11 @@ U_BOOT_CMD( "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 diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c index 8a04af557d0..431cf26e59f 100644 --- a/drivers/misc/cros_ec_sandbox.c +++ b/drivers/misc/cros_ec_sandbox.c @@ -525,8 +525,13 @@ int cros_ec_sandbox_init(struct cros_ec_dev *dev, const void *blob) int node; int err; - state = &s_state; - err = cros_ec_decode_ec_flash(blob, &ec->ec_config); + node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_CROS_EC); + 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) return err; diff --git a/include/cros_ec.h b/include/cros_ec.h index 1e4d8db96b7..9e13146ecbb 100644 --- a/include/cros_ec.h +++ b/include/cros_ec.h @@ -14,6 +14,7 @@ #include #include +#ifndef CONFIG_DM_CROS_EC /* Which interface is the device on? */ enum cros_ec_interface_t { CROS_EC_IF_NONE, @@ -22,9 +23,13 @@ enum cros_ec_interface_t { 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 */ @@ -33,6 +38,7 @@ struct cros_ec_dev { 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 */ @@ -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); +#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); @@ -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_sandbox_packet(struct cros_ec_dev *dev, int out_bytes, int in_bytes); +#endif /** * Dump a block of data for a command. @@ -489,9 +512,11 @@ int cros_ec_get_error(void); * 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. diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index c92adb4df99..0ea7a6f09e6 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -26,6 +26,7 @@ enum uclass_id { UCLASS_SPI, /* SPI bus */ UCLASS_SPI_GENERIC, /* Generic SPI flash target */ UCLASS_SPI_FLASH, /* SPI flash */ + UCLASS_CROS_EC, /* Chrome OS EC */ UCLASS_COUNT, UCLASS_INVALID = -1, -- cgit v1.3.1