From e830342ef389b46160f223e6882b1e85bd7de708 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Mon, 14 Jan 2013 20:01:37 +0100 Subject: mtd: docg3 fix missing bitreverse lib Fix missing dependency which can cause a build error such as: ERROR: "byte_rev_table" [drivers/mtd/devices/docg3.ko] undefined! Reported-by: Randy Dunlap Acked-by: Randy Dunlap Signed-off-by: Robert Jarzmik Signed-off-by: David Woodhouse --- drivers/mtd/devices/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mtd/devices') diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 27f80cd8aef..46dcb54c32e 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig @@ -272,6 +272,7 @@ config MTD_DOCG3 tristate "M-Systems Disk-On-Chip G3" select BCH select BCH_CONST_PARAMS + select BITREVERSE ---help--- This provides an MTD device driver for the M-Systems DiskOnChip G3 devices. -- cgit v1.2.3 From 972e1b7b450a93589b2a4c709e68f68da059aa5c Mon Sep 17 00:00:00 2001 From: Austin Boyle Date: Fri, 4 Jan 2013 13:02:28 +1300 Subject: mtd: m25p80: Flash protection support for STmicro chips This patch adds generic support for flash protection on STmicro chips. On chips with less than 3 protection bits, the unused bits are don't cares and so can be written anyway. The lock function will only change the protection bits if it would not unlock other areas. Similarly, the unlock function will not lock currently unlocked areas. Tested on the m25p64. Signed-off-by: Austin Boyle Signed-off-by: Artem Bityutskiy --- drivers/mtd/devices/m25p80.c | 96 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) (limited to 'drivers/mtd/devices') diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 4eeeb2d7f6e..069e34f909e 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -565,6 +565,96 @@ time_out: return ret; } +static int m25p80_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) +{ + struct m25p *flash = mtd_to_m25p(mtd); + uint32_t offset = ofs; + uint8_t status_old, status_new; + int res = 0; + + mutex_lock(&flash->lock); + /* Wait until finished previous command */ + if (wait_till_ready(flash)) { + res = 1; + goto err; + } + + status_old = read_sr(flash); + + if (offset < flash->mtd.size-(flash->mtd.size/2)) + status_new = status_old | SR_BP2 | SR_BP1 | SR_BP0; + else if (offset < flash->mtd.size-(flash->mtd.size/4)) + status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1; + else if (offset < flash->mtd.size-(flash->mtd.size/8)) + status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0; + else if (offset < flash->mtd.size-(flash->mtd.size/16)) + status_new = (status_old & ~(SR_BP0|SR_BP1)) | SR_BP2; + else if (offset < flash->mtd.size-(flash->mtd.size/32)) + status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0; + else if (offset < flash->mtd.size-(flash->mtd.size/64)) + status_new = (status_old & ~(SR_BP2|SR_BP0)) | SR_BP1; + else + status_new = (status_old & ~(SR_BP2|SR_BP1)) | SR_BP0; + + /* Only modify protection if it will not unlock other areas */ + if ((status_new&(SR_BP2|SR_BP1|SR_BP0)) > + (status_old&(SR_BP2|SR_BP1|SR_BP0))) { + write_enable(flash); + if (write_sr(flash, status_new) < 0) { + res = 1; + goto err; + } + } + +err: mutex_unlock(&flash->lock); + return res; +} + +static int m25p80_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) +{ + struct m25p *flash = mtd_to_m25p(mtd); + uint32_t offset = ofs; + uint8_t status_old, status_new; + int res = 0; + + mutex_lock(&flash->lock); + /* Wait until finished previous command */ + if (wait_till_ready(flash)) { + res = 1; + goto err; + } + + status_old = read_sr(flash); + + if (offset+len > flash->mtd.size-(flash->mtd.size/64)) + status_new = status_old & ~(SR_BP2|SR_BP1|SR_BP0); + else if (offset+len > flash->mtd.size-(flash->mtd.size/32)) + status_new = (status_old & ~(SR_BP2|SR_BP1)) | SR_BP0; + else if (offset+len > flash->mtd.size-(flash->mtd.size/16)) + status_new = (status_old & ~(SR_BP2|SR_BP0)) | SR_BP1; + else if (offset+len > flash->mtd.size-(flash->mtd.size/8)) + status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0; + else if (offset+len > flash->mtd.size-(flash->mtd.size/4)) + status_new = (status_old & ~(SR_BP0|SR_BP1)) | SR_BP2; + else if (offset+len > flash->mtd.size-(flash->mtd.size/2)) + status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0; + else + status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1; + + /* Only modify protection if it will not lock other areas */ + if ((status_new&(SR_BP2|SR_BP1|SR_BP0)) < + (status_old&(SR_BP2|SR_BP1|SR_BP0))) { + write_enable(flash); + if (write_sr(flash, status_new) < 0) { + res = 1; + goto err; + } + } + +err: mutex_unlock(&flash->lock); + return res; +} + /****************************************************************************/ /* @@ -899,6 +989,12 @@ static int m25p_probe(struct spi_device *spi) flash->mtd._erase = m25p80_erase; flash->mtd._read = m25p80_read; + /* flash protection support for STmicro chips */ + if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ST) { + flash->mtd._lock = m25p80_lock; + flash->mtd._unlock = m25p80_unlock; + } + /* sst flash chips use AAI word program */ if (JEDEC_MFR(info->jedec_id) == CFI_MFR_SST) flash->mtd._write = sst_write; -- cgit v1.2.3 From bf22433575ef30a4807f0620498017df0f27df67 Mon Sep 17 00:00:00 2001 From: Philip Avinash Date: Fri, 4 Jan 2013 13:26:50 +0530 Subject: mtd: devices: elm: Add support for ELM error correction The ELM hardware module can be used to speedup BCH 4/8/16 ECC scheme error correction. For now only 4 & 8 bit support is added Signed-off-by: Philip Avinash Signed-off-by: Artem Bityutskiy --- drivers/mtd/devices/Makefile | 4 +- drivers/mtd/devices/elm.c | 404 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 407 insertions(+), 1 deletion(-) create mode 100644 drivers/mtd/devices/elm.c (limited to 'drivers/mtd/devices') diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index 395733a30ef..369a1943ca2 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile @@ -17,8 +17,10 @@ obj-$(CONFIG_MTD_LART) += lart.o obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o obj-$(CONFIG_MTD_M25P80) += m25p80.o +obj-$(CONFIG_MTD_NAND_OMAP_BCH) += elm.o obj-$(CONFIG_MTD_SPEAR_SMI) += spear_smi.o obj-$(CONFIG_MTD_SST25L) += sst25l.o obj-$(CONFIG_MTD_BCM47XXSFLASH) += bcm47xxsflash.o -CFLAGS_docg3.o += -I$(src) \ No newline at end of file + +CFLAGS_docg3.o += -I$(src) diff --git a/drivers/mtd/devices/elm.c b/drivers/mtd/devices/elm.c new file mode 100644 index 00000000000..b93a349ae58 --- /dev/null +++ b/drivers/mtd/devices/elm.c @@ -0,0 +1,404 @@ +/* + * Error Location Module + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#define ELM_IRQSTATUS 0x018 +#define ELM_IRQENABLE 0x01c +#define ELM_LOCATION_CONFIG 0x020 +#define ELM_PAGE_CTRL 0x080 +#define ELM_SYNDROME_FRAGMENT_0 0x400 +#define ELM_SYNDROME_FRAGMENT_6 0x418 +#define ELM_LOCATION_STATUS 0x800 +#define ELM_ERROR_LOCATION_0 0x880 + +/* ELM Interrupt Status Register */ +#define INTR_STATUS_PAGE_VALID BIT(8) + +/* ELM Interrupt Enable Register */ +#define INTR_EN_PAGE_MASK BIT(8) + +/* ELM Location Configuration Register */ +#define ECC_BCH_LEVEL_MASK 0x3 + +/* ELM syndrome */ +#define ELM_SYNDROME_VALID BIT(16) + +/* ELM_LOCATION_STATUS Register */ +#define ECC_CORRECTABLE_MASK BIT(8) +#define ECC_NB_ERRORS_MASK 0x1f + +/* ELM_ERROR_LOCATION_0-15 Registers */ +#define ECC_ERROR_LOCATION_MASK 0x1fff + +#define ELM_ECC_SIZE 0x7ff + +#define SYNDROME_FRAGMENT_REG_SIZE 0x40 +#define ERROR_LOCATION_SIZE 0x100 + +struct elm_info { + struct device *dev; + void __iomem *elm_base; + struct completion elm_completion; + struct list_head list; + enum bch_ecc bch_type; +}; + +static LIST_HEAD(elm_devices); + +static void elm_write_reg(struct elm_info *info, int offset, u32 val) +{ + writel(val, info->elm_base + offset); +} + +static u32 elm_read_reg(struct elm_info *info, int offset) +{ + return readl(info->elm_base + offset); +} + +/** + * elm_config - Configure ELM module + * @dev: ELM device + * @bch_type: Type of BCH ecc + */ +void elm_config(struct device *dev, enum bch_ecc bch_type) +{ + u32 reg_val; + struct elm_info *info = dev_get_drvdata(dev); + + reg_val = (bch_type & ECC_BCH_LEVEL_MASK) | (ELM_ECC_SIZE << 16); + elm_write_reg(info, ELM_LOCATION_CONFIG, reg_val); + info->bch_type = bch_type; +} +EXPORT_SYMBOL(elm_config); + +/** + * elm_configure_page_mode - Enable/Disable page mode + * @info: elm info + * @index: index number of syndrome fragment vector + * @enable: enable/disable flag for page mode + * + * Enable page mode for syndrome fragment index + */ +static void elm_configure_page_mode(struct elm_info *info, int index, + bool enable) +{ + u32 reg_val; + + reg_val = elm_read_reg(info, ELM_PAGE_CTRL); + if (enable) + reg_val |= BIT(index); /* enable page mode */ + else + reg_val &= ~BIT(index); /* disable page mode */ + + elm_write_reg(info, ELM_PAGE_CTRL, reg_val); +} + +/** + * elm_load_syndrome - Load ELM syndrome reg + * @info: elm info + * @err_vec: elm error vectors + * @ecc: buffer with calculated ecc + * + * Load syndrome fragment registers with calculated ecc in reverse order. + */ +static void elm_load_syndrome(struct elm_info *info, + struct elm_errorvec *err_vec, u8 *ecc) +{ + int i, offset; + u32 val; + + for (i = 0; i < ERROR_VECTOR_MAX; i++) { + + /* Check error reported */ + if (err_vec[i].error_reported) { + elm_configure_page_mode(info, i, true); + offset = ELM_SYNDROME_FRAGMENT_0 + + SYNDROME_FRAGMENT_REG_SIZE * i; + + /* BCH8 */ + if (info->bch_type) { + + /* syndrome fragment 0 = ecc[9-12B] */ + val = cpu_to_be32(*(u32 *) &ecc[9]); + elm_write_reg(info, offset, val); + + /* syndrome fragment 1 = ecc[5-8B] */ + offset += 4; + val = cpu_to_be32(*(u32 *) &ecc[5]); + elm_write_reg(info, offset, val); + + /* syndrome fragment 2 = ecc[1-4B] */ + offset += 4; + val = cpu_to_be32(*(u32 *) &ecc[1]); + elm_write_reg(info, offset, val); + + /* syndrome fragment 3 = ecc[0B] */ + offset += 4; + val = ecc[0]; + elm_write_reg(info, offset, val); + } else { + /* syndrome fragment 0 = ecc[20-52b] bits */ + val = (cpu_to_be32(*(u32 *) &ecc[3]) >> 4) | + ((ecc[2] & 0xf) << 28); + elm_write_reg(info, offset, val); + + /* syndrome fragment 1 = ecc[0-20b] bits */ + offset += 4; + val = cpu_to_be32(*(u32 *) &ecc[0]) >> 12; + elm_write_reg(info, offset, val); + } + } + + /* Update ecc pointer with ecc byte size */ + ecc += info->bch_type ? BCH8_SIZE : BCH4_SIZE; + } +} + +/** + * elm_start_processing - start elm syndrome processing + * @info: elm info + * @err_vec: elm error vectors + * + * Set syndrome valid bit for syndrome fragment registers for which + * elm syndrome fragment registers are loaded. This enables elm module + * to start processing syndrome vectors. + */ +static void elm_start_processing(struct elm_info *info, + struct elm_errorvec *err_vec) +{ + int i, offset; + u32 reg_val; + + /* + * Set syndrome vector valid, so that ELM module + * will process it for vectors error is reported + */ + for (i = 0; i < ERROR_VECTOR_MAX; i++) { + if (err_vec[i].error_reported) { + offset = ELM_SYNDROME_FRAGMENT_6 + + SYNDROME_FRAGMENT_REG_SIZE * i; + reg_val = elm_read_reg(info, offset); + reg_val |= ELM_SYNDROME_VALID; + elm_write_reg(info, offset, reg_val); + } + } +} + +/** + * elm_error_correction - locate correctable error position + * @info: elm info + * @err_vec: elm error vectors + * + * On completion of processing by elm module, error location status + * register updated with correctable/uncorrectable error information. + * In case of correctable errors, number of errors located from + * elm location status register & read the positions from + * elm error location register. + */ +static void elm_error_correction(struct elm_info *info, + struct elm_errorvec *err_vec) +{ + int i, j, errors = 0; + int offset; + u32 reg_val; + + for (i = 0; i < ERROR_VECTOR_MAX; i++) { + + /* Check error reported */ + if (err_vec[i].error_reported) { + offset = ELM_LOCATION_STATUS + ERROR_LOCATION_SIZE * i; + reg_val = elm_read_reg(info, offset); + + /* Check correctable error or not */ + if (reg_val & ECC_CORRECTABLE_MASK) { + offset = ELM_ERROR_LOCATION_0 + + ERROR_LOCATION_SIZE * i; + + /* Read count of correctable errors */ + err_vec[i].error_count = reg_val & + ECC_NB_ERRORS_MASK; + + /* Update the error locations in error vector */ + for (j = 0; j < err_vec[i].error_count; j++) { + + reg_val = elm_read_reg(info, offset); + err_vec[i].error_loc[j] = reg_val & + ECC_ERROR_LOCATION_MASK; + + /* Update error location register */ + offset += 4; + } + + errors += err_vec[i].error_count; + } else { + err_vec[i].error_uncorrectable = true; + } + + /* Clearing interrupts for processed error vectors */ + elm_write_reg(info, ELM_IRQSTATUS, BIT(i)); + + /* Disable page mode */ + elm_configure_page_mode(info, i, false); + } + } +} + +/** + * elm_decode_bch_error_page - Locate error position + * @dev: device pointer + * @ecc_calc: calculated ECC bytes from GPMC + * @err_vec: elm error vectors + * + * Called with one or more error reported vectors & vectors with + * error reported is updated in err_vec[].error_reported + */ +void elm_decode_bch_error_page(struct device *dev, u8 *ecc_calc, + struct elm_errorvec *err_vec) +{ + struct elm_info *info = dev_get_drvdata(dev); + u32 reg_val; + + /* Enable page mode interrupt */ + reg_val = elm_read_reg(info, ELM_IRQSTATUS); + elm_write_reg(info, ELM_IRQSTATUS, reg_val & INTR_STATUS_PAGE_VALID); + elm_write_reg(info, ELM_IRQENABLE, INTR_EN_PAGE_MASK); + + /* Load valid ecc byte to syndrome fragment register */ + elm_load_syndrome(info, err_vec, ecc_calc); + + /* Enable syndrome processing for which syndrome fragment is updated */ + elm_start_processing(info, err_vec); + + /* Wait for ELM module to finish locating error correction */ + wait_for_completion(&info->elm_completion); + + /* Disable page mode interrupt */ + reg_val = elm_read_reg(info, ELM_IRQENABLE); + elm_write_reg(info, ELM_IRQENABLE, reg_val & ~INTR_EN_PAGE_MASK); + elm_error_correction(info, err_vec); +} +EXPORT_SYMBOL(elm_decode_bch_error_page); + +static irqreturn_t elm_isr(int this_irq, void *dev_id) +{ + u32 reg_val; + struct elm_info *info = dev_id; + + reg_val = elm_read_reg(info, ELM_IRQSTATUS); + + /* All error vectors processed */ + if (reg_val & INTR_STATUS_PAGE_VALID) { + elm_write_reg(info, ELM_IRQSTATUS, + reg_val & INTR_STATUS_PAGE_VALID); + complete(&info->elm_completion); + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static int elm_probe(struct platform_device *pdev) +{ + int ret = 0; + struct resource *res, *irq; + struct elm_info *info; + + info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); + if (!info) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + info->dev = &pdev->dev; + + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!irq) { + dev_err(&pdev->dev, "no irq resource defined\n"); + return -ENODEV; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "no memory resource defined\n"); + return -ENODEV; + } + + info->elm_base = devm_request_and_ioremap(&pdev->dev, res); + if (!info->elm_base) + return -EADDRNOTAVAIL; + + ret = devm_request_irq(&pdev->dev, irq->start, elm_isr, 0, + pdev->name, info); + if (ret) { + dev_err(&pdev->dev, "failure requesting irq %i\n", irq->start); + return ret; + } + + pm_runtime_enable(&pdev->dev); + if (pm_runtime_get_sync(&pdev->dev)) { + ret = -EINVAL; + pm_runtime_disable(&pdev->dev); + dev_err(&pdev->dev, "can't enable clock\n"); + return ret; + } + + init_completion(&info->elm_completion); + INIT_LIST_HEAD(&info->list); + list_add(&info->list, &elm_devices); + platform_set_drvdata(pdev, info); + return ret; +} + +static int elm_remove(struct platform_device *pdev) +{ + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); + platform_set_drvdata(pdev, NULL); + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id elm_of_match[] = { + { .compatible = "ti,am33xx-elm" }, + {}, +}; +MODULE_DEVICE_TABLE(of, elm_of_match); +#endif + +static struct platform_driver elm_driver = { + .driver = { + .name = "elm", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(elm_of_match), + }, + .probe = elm_probe, + .remove = elm_remove, +}; + +module_platform_driver(elm_driver); + +MODULE_DESCRIPTION("ELM driver for BCH error correction"); +MODULE_AUTHOR("Texas Instruments"); +MODULE_ALIAS("platform: elm"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 55bf75b7dd8ec875d048824f3cdecf8254e292e5 Mon Sep 17 00:00:00 2001 From: Michel Stempin Date: Sun, 6 Jan 2013 00:39:36 +0100 Subject: mtd: chips: Add support for GigaDevice GD25Q32/GD25Q64 SPI Flash in m25p80.c Add support for GigaDevice GD25Q32 32 Mbit (4 MB) SPI Flash (see datasheet: http://www.gigadevice.com/UserFiles/GD25Q32_Rev0.2(1).pdf) used in Hame MPR-A1 and clones, and for GigaDevice GD25Q64 64 Mbit (8 MB) SPI Flash used in Hame MPR-A2 devices (datasheet: http://www.gigadevice.com/UserFiles/GD25Q64.pdf). Signed-off-by: Michel Stempin Signed-off-by: Artem Bityutskiy --- drivers/mtd/devices/m25p80.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/mtd/devices') diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 069e34f909e..5b6b0728be2 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -732,6 +732,10 @@ static const struct spi_device_id m25p_ids[] = { /* Everspin */ { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2) }, + /* GigaDevice */ + { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) }, + { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) }, + /* Intel/Numonyx -- xxxs33b */ { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) }, -- cgit v1.2.3 From a2f74a7dacc1c17a0b146eb3112217874c5db436 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sun, 6 Jan 2013 21:28:50 +0100 Subject: mtd: bcm47xxsflash: add own struct for abstrating bus type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki --- drivers/mtd/devices/bcm47xxsflash.c | 37 ++++++++++++++++++++++++------------- drivers/mtd/devices/bcm47xxsflash.h | 15 +++++++++++++++ 2 files changed, 39 insertions(+), 13 deletions(-) create mode 100644 drivers/mtd/devices/bcm47xxsflash.h (limited to 'drivers/mtd/devices') diff --git a/drivers/mtd/devices/bcm47xxsflash.c b/drivers/mtd/devices/bcm47xxsflash.c index 4714584aa99..8fe1a097161 100644 --- a/drivers/mtd/devices/bcm47xxsflash.c +++ b/drivers/mtd/devices/bcm47xxsflash.c @@ -5,6 +5,8 @@ #include #include +#include "bcm47xxsflash.h" + MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Serial flash driver for BCMA bus"); @@ -13,26 +15,27 @@ static const char *probes[] = { "bcm47xxpart", NULL }; static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { - struct bcma_sflash *sflash = mtd->priv; + struct bcm47xxsflash *b47s = mtd->priv; /* Check address range */ if ((from + len) > mtd->size) return -EINVAL; - memcpy_fromio(buf, (void __iomem *)KSEG0ADDR(sflash->window + from), + memcpy_fromio(buf, (void __iomem *)KSEG0ADDR(b47s->window + from), len); return len; } -static void bcm47xxsflash_fill_mtd(struct bcma_sflash *sflash, - struct mtd_info *mtd) +static void bcm47xxsflash_fill_mtd(struct bcm47xxsflash *b47s) { - mtd->priv = sflash; + struct mtd_info *mtd = &b47s->mtd; + + mtd->priv = b47s; mtd->name = "bcm47xxsflash"; mtd->owner = THIS_MODULE; mtd->type = MTD_ROM; - mtd->size = sflash->size; + mtd->size = b47s->size; mtd->_read = bcm47xxsflash_read; /* TODO: implement writing support and verify/change following code */ @@ -43,16 +46,23 @@ static void bcm47xxsflash_fill_mtd(struct bcma_sflash *sflash, static int bcm47xxsflash_probe(struct platform_device *pdev) { struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev); + struct bcm47xxsflash *b47s; int err; - sflash->mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); - if (!sflash->mtd) { + b47s = kzalloc(sizeof(*b47s), GFP_KERNEL); + if (!b47s) { err = -ENOMEM; goto out; } - bcm47xxsflash_fill_mtd(sflash, sflash->mtd); + sflash->priv = b47s; + + b47s->window = sflash->window; + b47s->blocksize = sflash->blocksize; + b47s->numblocks = sflash->numblocks; + b47s->size = sflash->size; + bcm47xxsflash_fill_mtd(b47s); - err = mtd_device_parse_register(sflash->mtd, probes, NULL, NULL, 0); + err = mtd_device_parse_register(&b47s->mtd, probes, NULL, NULL, 0); if (err) { pr_err("Failed to register MTD device: %d\n", err); goto err_dev_reg; @@ -61,7 +71,7 @@ static int bcm47xxsflash_probe(struct platform_device *pdev) return 0; err_dev_reg: - kfree(sflash->mtd); + kfree(&b47s->mtd); out: return err; } @@ -69,9 +79,10 @@ out: static int bcm47xxsflash_remove(struct platform_device *pdev) { struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev); + struct bcm47xxsflash *b47s = sflash->priv; - mtd_device_unregister(sflash->mtd); - kfree(sflash->mtd); + mtd_device_unregister(&b47s->mtd); + kfree(b47s); return 0; } diff --git a/drivers/mtd/devices/bcm47xxsflash.h b/drivers/mtd/devices/bcm47xxsflash.h new file mode 100644 index 00000000000..ebf6f710e23 --- /dev/null +++ b/drivers/mtd/devices/bcm47xxsflash.h @@ -0,0 +1,15 @@ +#ifndef __BCM47XXSFLASH_H +#define __BCM47XXSFLASH_H + +#include + +struct bcm47xxsflash { + u32 window; + u32 blocksize; + u16 numblocks; + u32 size; + + struct mtd_info mtd; +}; + +#endif /* BCM47XXSFLASH */ -- cgit v1.2.3 From c80e572c029263687b8175f1ba71d425548cafcf Mon Sep 17 00:00:00 2001 From: Philip Avinash Date: Thu, 24 Jan 2013 12:23:30 +0530 Subject: mtd: devices: elm: Removes literals in elm DT node As part of removing generalized dependency, replace literal fields in DT compatible field with <52> for am335x platforms. Signed-off-by: Philip Avinash Acked-by: Peter Korsgaard Signed-off-by: Artem Bityutskiy --- drivers/mtd/devices/elm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd/devices') diff --git a/drivers/mtd/devices/elm.c b/drivers/mtd/devices/elm.c index b93a349ae58..2ec5da9ee24 100644 --- a/drivers/mtd/devices/elm.c +++ b/drivers/mtd/devices/elm.c @@ -380,7 +380,7 @@ static int elm_remove(struct platform_device *pdev) #ifdef CONFIG_OF static const struct of_device_id elm_of_match[] = { - { .compatible = "ti,am33xx-elm" }, + { .compatible = "ti,am3352-elm" }, {}, }; MODULE_DEVICE_TABLE(of, elm_of_match); -- cgit v1.2.3 From 60aca067b5308705a34dbb6548b459487f92da90 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Thu, 24 Jan 2013 17:39:54 +0100 Subject: mtd: bcm47xxsflash: write number of written bytes The callback assumes the number of read bytes is written to retlen. Signed-off-by: Hauke Mehrtens Signed-off-by: Artem Bityutskiy --- drivers/mtd/devices/bcm47xxsflash.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mtd/devices') diff --git a/drivers/mtd/devices/bcm47xxsflash.c b/drivers/mtd/devices/bcm47xxsflash.c index 8fe1a097161..61a45cbde37 100644 --- a/drivers/mtd/devices/bcm47xxsflash.c +++ b/drivers/mtd/devices/bcm47xxsflash.c @@ -23,6 +23,7 @@ static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len, memcpy_fromio(buf, (void __iomem *)KSEG0ADDR(b47s->window + from), len); + *retlen = len; return len; } -- cgit v1.2.3 From 2d13dc3bce8bff81668f793802de38ca12b775b8 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Thu, 24 Jan 2013 17:39:55 +0100 Subject: mtd: bcm47xxsflash: register this as normal driver When platform_driver_probe() is used and no device is registered for this driver -ENODEV is returned and and error message is shown. Not all BCM47xx SoC have a serial flash chip controller and chip and for them an error message was shown. Signed-off-by: Hauke Mehrtens Signed-off-by: Artem Bityutskiy --- drivers/mtd/devices/bcm47xxsflash.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/mtd/devices') diff --git a/drivers/mtd/devices/bcm47xxsflash.c b/drivers/mtd/devices/bcm47xxsflash.c index 61a45cbde37..729ca5fb53e 100644 --- a/drivers/mtd/devices/bcm47xxsflash.c +++ b/drivers/mtd/devices/bcm47xxsflash.c @@ -89,6 +89,7 @@ static int bcm47xxsflash_remove(struct platform_device *pdev) } static struct platform_driver bcma_sflash_driver = { + .probe = bcm47xxsflash_probe, .remove = bcm47xxsflash_remove, .driver = { .name = "bcma_sflash", @@ -100,7 +101,7 @@ static int __init bcm47xxsflash_init(void) { int err; - err = platform_driver_probe(&bcma_sflash_driver, bcm47xxsflash_probe); + err = platform_driver_register(&bcma_sflash_driver); if (err) pr_err("Failed to register BCMA serial flash driver: %d\n", err); -- cgit v1.2.3 From f1a7c9d350339e8a81cda9469ba9a591fb9c9a3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 4 Feb 2013 08:23:08 +0100 Subject: mtd: bcm47xxsflash: adjust names of bus-specific functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: Artem Bityutskiy --- drivers/mtd/devices/bcm47xxsflash.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers/mtd/devices') diff --git a/drivers/mtd/devices/bcm47xxsflash.c b/drivers/mtd/devices/bcm47xxsflash.c index 729ca5fb53e..95266285acb 100644 --- a/drivers/mtd/devices/bcm47xxsflash.c +++ b/drivers/mtd/devices/bcm47xxsflash.c @@ -44,7 +44,11 @@ static void bcm47xxsflash_fill_mtd(struct bcm47xxsflash *b47s) mtd->writebufsize = mtd->writesize = 1; } -static int bcm47xxsflash_probe(struct platform_device *pdev) +/************************************************** + * BCMA + **************************************************/ + +static int bcm47xxsflash_bcma_probe(struct platform_device *pdev) { struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev); struct bcm47xxsflash *b47s; @@ -77,7 +81,7 @@ out: return err; } -static int bcm47xxsflash_remove(struct platform_device *pdev) +static int bcm47xxsflash_bcma_remove(struct platform_device *pdev) { struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev); struct bcm47xxsflash *b47s = sflash->priv; @@ -89,14 +93,18 @@ static int bcm47xxsflash_remove(struct platform_device *pdev) } static struct platform_driver bcma_sflash_driver = { - .probe = bcm47xxsflash_probe, - .remove = bcm47xxsflash_remove, + .probe = bcm47xxsflash_bcma_probe, + .remove = bcm47xxsflash_bcma_remove, .driver = { .name = "bcma_sflash", .owner = THIS_MODULE, }, }; +/************************************************** + * Init + **************************************************/ + static int __init bcm47xxsflash_init(void) { int err; -- cgit v1.2.3