Implement mtd read, erase, and write handlers. For erase operation address and size should be 4K aligned. For write operation address and size has to be 4bytes aligned. Cc: Rodrigo Vivi <rodrigo.vivi@xxxxxxxxx> Cc: Lucas De Marchi <lucas.demarchi@xxxxxxxxx> Signed-off-by: Tomas Winkler <tomas.winkler@xxxxxxxxx> Signed-off-by: Vitaly Lubart <vitaly.lubart@xxxxxxxxx> --- drivers/gpu/drm/i915/spi/intel_spi_drv.c | 138 +++++++++++++++++++++-- 1 file changed, 131 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/spi/intel_spi_drv.c b/drivers/gpu/drm/i915/spi/intel_spi_drv.c index bdf58e14fd6b..1e8a40339e6d 100644 --- a/drivers/gpu/drm/i915/spi/intel_spi_drv.c +++ b/drivers/gpu/drm/i915/spi/intel_spi_drv.c @@ -173,7 +173,6 @@ static int i915_spi_is_valid(struct i915_spi *spi) return 0; } -__maybe_unused static unsigned int spi_get_region(const struct i915_spi *spi, loff_t from) { unsigned int i; @@ -188,7 +187,6 @@ static unsigned int spi_get_region(const struct i915_spi *spi, loff_t from) return i; } -__maybe_unused static ssize_t spi_write(struct i915_spi *spi, u8 region, loff_t to, size_t len, const unsigned char *buf) { @@ -219,7 +217,6 @@ static ssize_t spi_write(struct i915_spi *spi, u8 region, return len; } -__maybe_unused static ssize_t spi_read(struct i915_spi *spi, u8 region, loff_t from, size_t len, unsigned char *buf) { @@ -261,7 +258,6 @@ static ssize_t spi_read(struct i915_spi *spi, u8 region, return len; } -__maybe_unused static ssize_t spi_erase(struct i915_spi *spi, u8 region, loff_t from, u64 len, u64 *fail_addr) { @@ -350,7 +346,63 @@ static int i915_spi_init(struct i915_spi *spi, struct device *device) static int i915_spi_erase(struct mtd_info *mtd, struct erase_info *info) { - dev_err(&mtd->dev, "erasing %lld %lld\n", info->addr, info->len); + struct i915_spi *spi; + unsigned int idx; + u8 region; + u64 addr; + ssize_t bytes; + loff_t from; + size_t len; + size_t total_len; + + if (!mtd || !info) + return -EINVAL; + + spi = mtd->priv; + + if (!IS_ALIGNED(info->addr, SZ_4K) || !IS_ALIGNED(info->len, SZ_4K)) { + dev_err(&mtd->dev, "unaligned erase %llx %llx\n", + info->addr, info->len); + info->fail_addr = MTD_FAIL_ADDR_UNKNOWN; + return -EINVAL; + } + + total_len = info->len; + addr = info->addr; + + while (total_len > 0) { + if (!IS_ALIGNED(addr, SZ_4K) || !IS_ALIGNED(total_len, SZ_4K)) { + dev_err(&mtd->dev, "unaligned erase %llx %zx\n", addr, total_len); + info->fail_addr = addr; + return -ERANGE; + } + + idx = spi_get_region(spi, addr); + if (idx >= spi->nregions) { + dev_err(&mtd->dev, "out of range"); + info->fail_addr = MTD_FAIL_ADDR_UNKNOWN; + return -ERANGE; + } + + from = addr - spi->regions[idx].offset; + region = spi->regions[idx].id; + len = total_len; + if (len > spi->regions[idx].size - from) + len = spi->regions[idx].size - from; + + dev_dbg(&mtd->dev, "erasing region[%d] %s from %llx len %zx\n", + region, spi->regions[idx].name, from, len); + + bytes = spi_erase(spi, region, from, len, &info->fail_addr); + if (bytes < 0) { + dev_dbg(&mtd->dev, "erase failed with %zd\n", bytes); + info->fail_addr += spi->regions[idx].offset; + return bytes; + } + + addr += len; + total_len -= len; + } return 0; } @@ -358,7 +410,43 @@ static int i915_spi_erase(struct mtd_info *mtd, struct erase_info *info) static int i915_spi_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { - dev_err(&mtd->dev, "read %lld %zd\n", from, len); + struct i915_spi *spi; + ssize_t ret; + unsigned int idx; + u8 region; + + if (!mtd) + return -EINVAL; + + spi = mtd->priv; + + if (!IS_ALIGNED(from, sizeof(u32))) { + dev_err(&mtd->dev, "unaligned read %lld %zd\n", from, len); + return -EINVAL; + } + + idx = spi_get_region(spi, from); + + dev_dbg(&mtd->dev, "reading region[%d] %s from %lld len %zd\n", + spi->regions[idx].id, spi->regions[idx].name, from, len); + + if (idx >= spi->nregions) { + dev_err(&mtd->dev, "out of ragnge"); + return -ERANGE; + } + + from -= spi->regions[idx].offset; + region = spi->regions[idx].id; + if (len > spi->regions[idx].size - from) + len = spi->regions[idx].size - from; + + ret = spi_read(spi, region, from, len, buf); + if (ret < 0) { + dev_dbg(&mtd->dev, "read failed with %zd\n", ret); + return ret; + } + + *retlen = ret; return 0; } @@ -366,7 +454,43 @@ static int i915_spi_read(struct mtd_info *mtd, loff_t from, size_t len, static int i915_spi_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { - dev_err(&mtd->dev, "writing %lld %zd\n", to, len); + struct i915_spi *spi; + ssize_t ret; + unsigned int idx; + u8 region; + + if (!mtd) + return -EINVAL; + + spi = mtd->priv; + + if (!(IS_ALIGNED(len, 4) && IS_ALIGNED(to, 4))) { + dev_err(&mtd->dev, "unaligned write %lld %zd\n", to, len); + return -EINVAL; + } + + idx = spi_get_region(spi, to); + + dev_dbg(&mtd->dev, "writing region[%d] %s to %lld len %zd\n", + spi->regions[idx].id, spi->regions[idx].name, to, len); + + if (idx >= spi->nregions) { + dev_err(&mtd->dev, "out of range"); + return -ERANGE; + } + + to -= spi->regions[idx].offset; + region = spi->regions[idx].id; + if (len > spi->regions[idx].size - to) + len = spi->regions[idx].size - to; + + ret = spi_write(spi, region, to, len, buf); + if (ret < 0) { + dev_dbg(&mtd->dev, "write failed with %zd\n", ret); + return ret; + } + + *retlen = ret; return 0; } -- 2.26.2 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx