From 73d127565b5a4b19bcaacabc505689ee039f16fd Mon Sep 17 00:00:00 2001 From: Daniel Schwierzeck Date: Sun, 11 Nov 2012 03:11:38 +0100 Subject: sf: factor out malloc from SPI flash drivers Signed-off-by: Daniel Schwierzeck --- a/drivers/mtd/spi/atmel.c +++ b/drivers/mtd/spi/atmel.c @@ -40,18 +40,6 @@ struct atmel_spi_flash_params { const char *name; }; -/* spi_flash needs to be first so upper layers can free() it */ -struct atmel_spi_flash { - struct spi_flash flash; - const struct atmel_spi_flash_params *params; -}; - -static inline struct atmel_spi_flash * -to_atmel_spi_flash(struct spi_flash *flash) -{ - return container_of(flash, struct atmel_spi_flash, flash); -} - static const struct atmel_spi_flash_params atmel_spi_flash_table[] = { { .idcode1 = 0x22, @@ -156,7 +144,8 @@ static int at45_wait_ready(struct spi_fl * Assemble the address part of a command for AT45 devices in * non-power-of-two page size mode. */ -static void at45_build_address(struct atmel_spi_flash *asf, u8 *cmd, u32 offset) +static void at45_build_address(const struct atmel_spi_flash_params *params, + u8 *cmd, u32 offset) { unsigned long page_addr; unsigned long byte_addr; @@ -167,7 +156,7 @@ static void at45_build_address(struct at * The "extra" space per page is the power-of-two page size * divided by 32. */ - page_shift = asf->params->l2_page_size; + page_shift = params->l2_page_size; page_size = (1 << page_shift) + (1 << (page_shift - 5)); page_shift++; page_addr = offset / page_size; @@ -181,11 +170,11 @@ static void at45_build_address(struct at static int dataflash_read_fast_at45(struct spi_flash *flash, u32 offset, size_t len, void *buf) { - struct atmel_spi_flash *asf = to_atmel_spi_flash(flash); + const struct atmel_spi_flash_params *params = flash->priv; u8 cmd[5]; cmd[0] = CMD_READ_ARRAY_FAST; - at45_build_address(asf, cmd + 1, offset); + at45_build_address(params, cmd + 1, offset); cmd[4] = 0x00; return spi_flash_read_common(flash, cmd, sizeof(cmd), buf, len); @@ -197,7 +186,7 @@ static int dataflash_read_fast_at45(stru static int dataflash_write_p2(struct spi_flash *flash, u32 offset, size_t len, const void *buf) { - struct atmel_spi_flash *asf = to_atmel_spi_flash(flash); + const struct atmel_spi_flash_params *params = flash->priv; unsigned long page_size; u32 addr = offset; size_t chunk_len; @@ -211,7 +200,7 @@ static int dataflash_write_p2(struct spi * the other is being programmed into main memory. */ - page_size = (1 << asf->params->l2_page_size); + page_size = (1 << params->l2_page_size); ret = spi_claim_bus(flash->spi); if (ret) { @@ -263,7 +252,7 @@ out: static int dataflash_write_at45(struct spi_flash *flash, u32 offset, size_t len, const void *buf) { - struct atmel_spi_flash *asf = to_atmel_spi_flash(flash); + const struct atmel_spi_flash_params *params = flash->priv; unsigned long page_addr; unsigned long byte_addr; unsigned long page_size; @@ -279,7 +268,7 @@ static int dataflash_write_at45(struct s * the other is being programmed into main memory. */ - page_shift = asf->params->l2_page_size; + page_shift = params->l2_page_size; page_size = (1 << page_shift) + (1 << (page_shift - 5)); page_shift++; page_addr = offset / page_size; @@ -338,7 +327,7 @@ out: */ static int dataflash_erase_p2(struct spi_flash *flash, u32 offset, size_t len) { - struct atmel_spi_flash *asf = to_atmel_spi_flash(flash); + const struct atmel_spi_flash_params *params = flash->priv; unsigned long page_size; size_t actual; @@ -351,7 +340,7 @@ static int dataflash_erase_p2(struct spi * when possible. */ - page_size = (1 << asf->params->l2_page_size); + page_size = (1 << params->l2_page_size); if (offset % page_size || len % page_size) { debug("SF: Erase offset/length not multiple of page size\n"); @@ -397,7 +386,7 @@ out: static int dataflash_erase_at45(struct spi_flash *flash, u32 offset, size_t len) { - struct atmel_spi_flash *asf = to_atmel_spi_flash(flash); + const struct atmel_spi_flash_params *params = flash->priv; unsigned long page_addr; unsigned long page_size; unsigned int page_shift; @@ -411,7 +400,7 @@ static int dataflash_erase_at45(struct s * when possible. */ - page_shift = asf->params->l2_page_size; + page_shift = params->l2_page_size; page_size = (1 << page_shift) + (1 << (page_shift - 5)); page_shift++; page_addr = offset / page_size; @@ -458,12 +447,12 @@ out: return ret; } -struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode) +int spi_flash_probe_atmel(struct spi_flash *flash, u8 *idcode) { const struct atmel_spi_flash_params *params; + struct spi_slave *spi = flash->spi; unsigned page_size; unsigned int family; - struct atmel_spi_flash *asf; unsigned int i; int ret; u8 status; @@ -477,18 +466,11 @@ struct spi_flash *spi_flash_probe_atmel( if (i == ARRAY_SIZE(atmel_spi_flash_table)) { debug("SF: Unsupported DataFlash ID %02x\n", idcode[1]); - return NULL; - } - - asf = malloc(sizeof(struct atmel_spi_flash)); - if (!asf) { - debug("SF: Failed to allocate memory\n"); - return NULL; + return 0; } - asf->params = params; - asf->flash.spi = spi; - asf->flash.name = params->name; + flash->priv = (void *)params; + flash->name = params->name; /* Assuming power-of-two page size initially. */ page_size = 1 << params->l2_page_size; @@ -503,48 +485,44 @@ struct spi_flash *spi_flash_probe_atmel( */ ret = spi_flash_cmd(spi, CMD_AT45_READ_STATUS, &status, 1); if (ret) - goto err; + return -1; debug("SF: AT45 status register: %02x\n", status); if (!(status & AT45_STATUS_P2_PAGE_SIZE)) { - asf->flash.read = dataflash_read_fast_at45; - asf->flash.write = dataflash_write_at45; - asf->flash.erase = dataflash_erase_at45; + flash->read = dataflash_read_fast_at45; + flash->write = dataflash_write_at45; + flash->erase = dataflash_erase_at45; page_size += 1 << (params->l2_page_size - 5); } else { - asf->flash.read = spi_flash_cmd_read_fast; - asf->flash.write = dataflash_write_p2; - asf->flash.erase = dataflash_erase_p2; + flash->read = spi_flash_cmd_read_fast; + flash->write = dataflash_write_p2; + flash->erase = dataflash_erase_p2; } - asf->flash.page_size = page_size; - asf->flash.sector_size = page_size; + flash->page_size = page_size; + flash->sector_size = page_size; break; case DF_FAMILY_AT26F: case DF_FAMILY_AT26DF: - asf->flash.read = spi_flash_cmd_read_fast; - asf->flash.write = spi_flash_cmd_write_multi; - asf->flash.erase = spi_flash_cmd_erase; - asf->flash.page_size = page_size; - asf->flash.sector_size = 4096; + flash->read = spi_flash_cmd_read_fast; + flash->write = spi_flash_cmd_write_multi; + flash->erase = spi_flash_cmd_erase; + flash->page_size = page_size; + flash->sector_size = 4096; /* clear SPRL# bit for locked flash */ - spi_flash_cmd_write_status(&asf->flash, 0); + spi_flash_cmd_write_status(flash, 0); break; default: debug("SF: Unsupported DataFlash family %u\n", family); - goto err; + return -1; } - asf->flash.size = page_size * params->pages_per_block + flash->size = page_size * params->pages_per_block * params->blocks_per_sector * params->nr_sectors; - return &asf->flash; - -err: - free(asf); - return NULL; + return 1; } --- a/drivers/mtd/spi/eon.c +++ b/drivers/mtd/spi/eon.c @@ -29,10 +29,9 @@ static const struct eon_spi_flash_params }, }; -struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode) +int spi_flash_probe_eon(struct spi_flash *flash, u8 *idcode) { const struct eon_spi_flash_params *params; - struct spi_flash *flash; unsigned int i; for (i = 0; i < ARRAY_SIZE(eon_spi_flash_table); ++i) { @@ -43,16 +42,10 @@ struct spi_flash *spi_flash_probe_eon(st if (i == ARRAY_SIZE(eon_spi_flash_table)) { debug("SF: Unsupported EON ID %02x\n", idcode[1]); - return NULL; + return 0; } - flash = malloc(sizeof(*flash)); - if (!flash) { - debug("SF: Failed to allocate memory\n"); - return NULL; - } - - flash->spi = spi; + flash->priv = (void *)params; flash->name = params->name; flash->write = spi_flash_cmd_write_multi; @@ -63,5 +56,5 @@ struct spi_flash *spi_flash_probe_eon(st flash->size = 256 * 16 * params->nr_sectors; - return flash; + return 1; } --- a/drivers/mtd/spi/macronix.c +++ b/drivers/mtd/spi/macronix.c @@ -79,10 +79,9 @@ static const struct macronix_spi_flash_p }, }; -struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode) +int spi_flash_probe_macronix(struct spi_flash *flash, u8 *idcode) { const struct macronix_spi_flash_params *params; - struct spi_flash *flash; unsigned int i; u16 id = idcode[2] | idcode[1] << 8; @@ -94,16 +93,10 @@ struct spi_flash *spi_flash_probe_macron if (i == ARRAY_SIZE(macronix_spi_flash_table)) { debug("SF: Unsupported Macronix ID %04x\n", id); - return NULL; + return 0; } - flash = malloc(sizeof(*flash)); - if (!flash) { - debug("SF: Failed to allocate memory\n"); - return NULL; - } - - flash->spi = spi; + flash->priv = (void *)params; flash->name = params->name; flash->write = spi_flash_cmd_write_multi; @@ -116,5 +109,5 @@ struct spi_flash *spi_flash_probe_macron /* Clear BP# bits for read-only flash */ spi_flash_cmd_write_status(flash, 0); - return flash; + return 1; } --- a/drivers/mtd/spi/ramtron.c +++ b/drivers/mtd/spi/ramtron.c @@ -69,17 +69,6 @@ struct ramtron_spi_fram_params { const char *name; /* name for display and/or matching */ }; -struct ramtron_spi_fram { - struct spi_flash flash; - const struct ramtron_spi_fram_params *params; -}; - -static inline struct ramtron_spi_fram *to_ramtron_spi_fram(struct spi_flash - *flash) -{ - return container_of(flash, struct ramtron_spi_fram, flash); -} - /* * table describing supported FRAM chips: * chips without RDID command must have the values 0xff for id1 and id2 @@ -155,18 +144,18 @@ static const struct ramtron_spi_fram_par static int ramtron_common(struct spi_flash *flash, u32 offset, size_t len, void *buf, u8 command) { - struct ramtron_spi_fram *sn = to_ramtron_spi_fram(flash); + const struct ramtron_spi_fram_params *params = flash->priv; u8 cmd[4]; int cmd_len; int ret; - if (sn->params->addr_len == 3 && sn->params->merge_cmd == 0) { + if (params->addr_len == 3 && params->merge_cmd == 0) { cmd[0] = command; cmd[1] = offset >> 16; cmd[2] = offset >> 8; cmd[3] = offset; cmd_len = 4; - } else if (sn->params->addr_len == 2 && sn->params->merge_cmd == 0) { + } else if (params->addr_len == 2 && params->merge_cmd == 0) { cmd[0] = command; cmd[1] = offset >> 8; cmd[2] = offset; @@ -230,10 +219,9 @@ static int ramtron_erase(struct spi_flas * nore: we are called here with idcode pointing to the first non-0x7f byte * already! */ -struct spi_flash *spi_fram_probe_ramtron(struct spi_slave *spi, u8 *idcode) +int spi_fram_probe_ramtron(struct spi_flash *flash, u8 *idcode) { const struct ramtron_spi_fram_params *params; - struct ramtron_spi_fram *sn; unsigned int i; #ifdef CONFIG_SPI_FRAM_RAMTRON_NON_JEDEC int ret; @@ -259,11 +247,11 @@ struct spi_flash *spi_fram_probe_ramtron */ ret = spi_flash_cmd(spi, CMD_READ_STATUS, &sr, 1); if (ret) - return NULL; + return 0; /* Bits 5,4,0 are fixed 0 for all devices */ if ((sr & 0x31) != 0x00) - return NULL; + return 0; /* now find the device */ for (i = 0; i < ARRAY_SIZE(ramtron_spi_fram_table); i++) { params = &ramtron_spi_fram_table[i]; @@ -281,23 +269,16 @@ struct spi_flash *spi_fram_probe_ramtron /* arriving here means no method has found a device we can handle */ debug("SF/ramtron: unsupported device id0=%02x id1=%02x id2=%02x\n", idcode[0], idcode[1], idcode[2]); - return NULL; + return 0; found: - sn = malloc(sizeof(*sn)); - if (!sn) { - debug("SF: Failed to allocate memory\n"); - return NULL; - } + flash->priv = (void *)params; + flash->name = params->name; - sn->params = params; - sn->flash.spi = spi; - sn->flash.name = params->name; - - sn->flash.write = ramtron_write; - sn->flash.read = ramtron_read; - sn->flash.erase = ramtron_erase; - sn->flash.size = params->size; + flash->write = ramtron_write; + flash->read = ramtron_read; + flash->erase = ramtron_erase; + flash->size = params->size; - return &sn->flash; + return 1; } --- a/drivers/mtd/spi/spansion.c +++ b/drivers/mtd/spi/spansion.c @@ -105,10 +105,9 @@ static const struct spansion_spi_flash_p }, }; -struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode) +int spi_flash_probe_spansion(struct spi_flash *flash, u8 *idcode) { const struct spansion_spi_flash_params *params; - struct spi_flash *flash; unsigned int i; unsigned short jedec, ext_jedec; @@ -125,16 +124,10 @@ struct spi_flash *spi_flash_probe_spansi if (i == ARRAY_SIZE(spansion_spi_flash_table)) { debug("SF: Unsupported SPANSION ID %04x %04x\n", jedec, ext_jedec); - return NULL; + return 0; } - flash = malloc(sizeof(*flash)); - if (!flash) { - debug("SF: Failed to allocate memory\n"); - return NULL; - } - - flash->spi = spi; + flash->priv = (void *)params; flash->name = params->name; flash->write = spi_flash_cmd_write_multi; @@ -144,5 +137,5 @@ struct spi_flash *spi_flash_probe_spansi flash->sector_size = 256 * params->pages_per_sector; flash->size = flash->sector_size * params->nr_sectors; - return flash; + return 1; } --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -296,7 +296,7 @@ int spi_flash_cmd_write_status(struct sp static struct { const u8 shift; const u8 idcode; - struct spi_flash *(*probe) (struct spi_slave *spi, u8 *idcode); + int (*probe) (struct spi_flash *flash, u8 *idcode); } flashes[] = { /* Keep it sorted by define name */ #ifdef CONFIG_SPI_FLASH_ATMEL @@ -343,7 +343,7 @@ struct spi_flash *spi_flash_probe(unsign unsigned int max_hz, unsigned int spi_mode) { struct spi_slave *spi; - struct spi_flash *flash = NULL; + struct spi_flash *flash; int ret, i, shift; u8 idcode[IDCODE_LEN], *idp; #ifdef CONFIG_NEEDS_MANUAL_RELOC @@ -379,6 +379,15 @@ struct spi_flash *spi_flash_probe(unsign print_buffer(0, idcode, 1, sizeof(idcode), 0); #endif + flash = malloc(sizeof(*flash)); + if (!flash) { + debug("SF: failed to alloc memory\n"); + goto err_malloc; + } + + memset(flash, 0, sizeof(*flash)); + flash->spi = spi; + /* count the number of continuation bytes */ for (shift = 0, idp = idcode; shift < IDCODE_CONT_LEN && *idp == 0x7f; @@ -389,12 +398,12 @@ struct spi_flash *spi_flash_probe(unsign for (i = 0; i < ARRAY_SIZE(flashes); ++i) if (flashes[i].shift == shift && flashes[i].idcode == *idp) { /* we have a match, call probe */ - flash = flashes[i].probe(spi, idp); - if (flash) + ret = flashes[i].probe(flash, idp); + if (ret) break; } - if (!flash) { + if (ret <= 0) { printf("SF: Unsupported manufacturer %02x\n", *idp); goto err_manufacturer_probe; } @@ -408,6 +417,8 @@ struct spi_flash *spi_flash_probe(unsign return flash; err_manufacturer_probe: + free(flash); +err_malloc: err_read_id: spi_release_bus(spi); err_claim_bus: --- a/drivers/mtd/spi/spi_flash_internal.h +++ b/drivers/mtd/spi/spi_flash_internal.h @@ -98,11 +98,11 @@ int spi_flash_cmd_wait_ready(struct spi_ int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len); /* Manufacturer-specific probe functions */ -struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode); -struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode); -struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode); -struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode); -struct spi_flash *spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode); -struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 *idcode); -struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode); -struct spi_flash *spi_fram_probe_ramtron(struct spi_slave *spi, u8 *idcode); +int spi_flash_probe_spansion(struct spi_flash *flash, u8 *idcode); +int spi_flash_probe_atmel(struct spi_flash *flash, u8 *idcode); +int spi_flash_probe_eon(struct spi_flash *flash, u8 *idcode); +int spi_flash_probe_macronix(struct spi_flash *flash, u8 *idcode); +int spi_flash_probe_sst(struct spi_flash *flash, u8 *idcode); +int spi_flash_probe_stmicro(struct spi_flash *flash, u8 *idcode); +int spi_flash_probe_winbond(struct spi_flash *flash, u8 *idcode); +int spi_fram_probe_ramtron(struct spi_flash *flash, u8 *idcode); --- a/drivers/mtd/spi/sst.c +++ b/drivers/mtd/spi/sst.c @@ -39,11 +39,6 @@ struct sst_spi_flash_params { const char *name; }; -struct sst_spi_flash { - struct spi_flash flash; - const struct sst_spi_flash_params *params; -}; - static const struct sst_spi_flash_params sst_spi_flash_table[] = { { .idcode1 = 0x8d, @@ -185,11 +180,9 @@ sst_write_wp(struct spi_flash *flash, u3 return ret; } -struct spi_flash * -spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode) +int spi_flash_probe_sst(struct spi_flash *flash, u8 *idcode) { const struct sst_spi_flash_params *params; - struct sst_spi_flash *stm; size_t i; for (i = 0; i < ARRAY_SIZE(sst_spi_flash_table); ++i) { @@ -200,31 +193,24 @@ spi_flash_probe_sst(struct spi_slave *sp if (i == ARRAY_SIZE(sst_spi_flash_table)) { debug("SF: Unsupported SST ID %02x\n", idcode[1]); - return NULL; - } - - stm = malloc(sizeof(*stm)); - if (!stm) { - debug("SF: Failed to allocate memory\n"); - return NULL; + return 0; } - stm->params = params; - stm->flash.spi = spi; - stm->flash.name = params->name; + flash->priv = (void *)params; + flash->name = params->name; - if (stm->params->flags & SST_FEAT_WP) - stm->flash.write = sst_write_wp; + if (params->flags & SST_FEAT_WP) + flash->write = sst_write_wp; else - stm->flash.write = spi_flash_cmd_write_multi; - stm->flash.erase = spi_flash_cmd_erase; - stm->flash.read = spi_flash_cmd_read_fast; - stm->flash.page_size = 256; - stm->flash.sector_size = 4096; - stm->flash.size = stm->flash.sector_size * params->nr_sectors; + flash->write = spi_flash_cmd_write_multi; + flash->erase = spi_flash_cmd_erase; + flash->read = spi_flash_cmd_read_fast; + flash->page_size = 256; + flash->sector_size = 4096; + flash->size = flash->sector_size * params->nr_sectors; /* Flash powers up read-only, so clear BP# bits */ - spi_flash_cmd_write_status(&stm->flash, 0); + spi_flash_cmd_write_status(flash, 0); - return &stm->flash; + return 1; } --- a/drivers/mtd/spi/stmicro.c +++ b/drivers/mtd/spi/stmicro.c @@ -112,10 +112,10 @@ static const struct stmicro_spi_flash_pa }, }; -struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode) +int spi_flash_probe_stmicro(struct spi_flash *flash, u8 * idcode) { const struct stmicro_spi_flash_params *params; - struct spi_flash *flash; + struct spi_slave *spi = flash->spi; unsigned int i; u16 id; @@ -123,13 +123,13 @@ struct spi_flash *spi_flash_probe_stmicr i = spi_flash_cmd(spi, CMD_M25PXX_RES, idcode, 4); if (i) - return NULL; + return 0; if ((idcode[3] & 0xf0) == 0x10) { idcode[0] = 0x20; idcode[1] = 0x20; idcode[2] = idcode[3] + 1; } else - return NULL; + return 0; } id = ((idcode[1] << 8) | idcode[2]); @@ -143,16 +143,10 @@ struct spi_flash *spi_flash_probe_stmicr if (i == ARRAY_SIZE(stmicro_spi_flash_table)) { debug("SF: Unsupported STMicro ID %04x\n", id); - return NULL; + return 0; } - flash = malloc(sizeof(*flash)); - if (!flash) { - debug("SF: Failed to allocate memory\n"); - return NULL; - } - - flash->spi = spi; + flash->priv = (void *)params; flash->name = params->name; flash->write = spi_flash_cmd_write_multi; @@ -162,5 +156,5 @@ struct spi_flash *spi_flash_probe_stmicr flash->sector_size = 256 * params->pages_per_sector; flash->size = flash->sector_size * params->nr_sectors; - return flash; + return 1; } --- a/drivers/mtd/spi/winbond.c +++ b/drivers/mtd/spi/winbond.c @@ -69,10 +69,9 @@ static const struct winbond_spi_flash_pa }, }; -struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode) +int spi_flash_probe_winbond(struct spi_flash *flash, u8 *idcode) { const struct winbond_spi_flash_params *params; - struct spi_flash *flash; unsigned int i; for (i = 0; i < ARRAY_SIZE(winbond_spi_flash_table); i++) { @@ -84,16 +83,10 @@ struct spi_flash *spi_flash_probe_winbon if (i == ARRAY_SIZE(winbond_spi_flash_table)) { debug("SF: Unsupported Winbond ID %02x%02x\n", idcode[1], idcode[2]); - return NULL; + return 0; } - flash = malloc(sizeof(*flash)); - if (!flash) { - debug("SF: Failed to allocate memory\n"); - return NULL; - } - - flash->spi = spi; + flash->priv = (void *)params; flash->name = params->name; flash->write = spi_flash_cmd_write_multi; @@ -103,5 +96,5 @@ struct spi_flash *spi_flash_probe_winbon flash->sector_size = 4096; flash->size = 4096 * 16 * params->nr_blocks; - return flash; + return 1; } --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -31,6 +31,7 @@ struct spi_flash { struct spi_slave *spi; const char *name; + void *priv; /* Total flash size */ u32 size;