From patchwork Tue Apr 11 21:30:12 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew Lunn X-Patchwork-Id: 749627 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3w2gGQ2LJvz9s8c for ; Wed, 12 Apr 2017 07:31:10 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="moja9WfB"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-Id:Date:Subject:To :From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=xSBTKr3LgnVEAEG7Z3AQ3Il5QjfACYijiJh2WjefDfA=; b=moja9WfBGhKCFX VPx1nTf1SOxZyt1mCpjTMEkWlXnSqInEfdyQGTG7Iy3DZWQx6Ym147G7JWjzXgVJ60264ISj43myI PVT2yx7mDjO0TDI1spkAW7oPUVnG4YsphdhmSy87YJFTYe6Fcu7oiP8vQtcyVzfDB9o2TEaJJp8P9 mhKhWemzfAhaW+LdWqateGseneWOruMal+tUP87p+S04hI6k6Ktt2zxFRdZQW97IpFYe4MXkPXqu6 vjigICTkctdxzGq7CdvjxbMw3mrw3C1bdrGdK2hztv84W1Jshd9h8/xIX9BQZ2udS7llBQEw5HS9D VK38GF3UGCvlN6jcG60A==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cy3NS-0000zU-OQ; Tue, 11 Apr 2017 21:31:06 +0000 Received: from vps0.lunn.ch ([178.209.37.122]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1cy3NP-0000xt-1k for linux-mtd@lists.infradead.org; Tue, 11 Apr 2017 21:31:05 +0000 Received: from andrew by vps0.lunn.ch with local (Exim 4.80) (envelope-from ) id 1cy3Mn-0002PQ-3O; Tue, 11 Apr 2017 23:30:25 +0200 From: Andrew Lunn To: dwmw2@infradead.org, boris.brezillon@free-electrons.com Subject: =?UTF-8?q?=5BPATCH=20v3=5D=20mtd=3A=20mchp23k256=3A=20Add=20driver=20for=20this=20SPI=20SRAM=20device?= Date: Tue, 11 Apr 2017 23:30:12 +0200 Message-Id: <1491946212-9226-1-git-send-email-andrew@lunn.ch> X-Mailer: git-send-email 1.7.10.4 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170411_143103_261131_0E8CEE27 X-CRM114-Status: GOOD ( 16.82 ) X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record -0.0 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Andrew Lunn , zajec5@gmail.com, linux-mtd@lists.infradead.org Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org The Microchip 23k256 is a 32K Byte SRAM connected via SPI. Signed-off-by: Andrew Lunn Reviewed-by: Boris Brezillon --- v3: Add Reviewed-by: No code changed v2: Remove multiple blank lines. Make MODULE_LICENSE() consistent with license text. Fix copyright year. drivers/mtd/devices/Kconfig | 10 +++ drivers/mtd/devices/Makefile | 1 + drivers/mtd/devices/mchp23k256.c | 183 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 194 insertions(+) create mode 100644 drivers/mtd/devices/mchp23k256.c diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 58329d2dacd1..6def5445e03e 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig @@ -95,6 +95,16 @@ config MTD_M25P80 if you want to specify device partitioning or to use a device which doesn't support the JEDEC ID instruction. +config MTD_MCHP23K256 + tristate "Microchip 23K256 SRAM" + depends on SPI_MASTER + help + This enables access to Microchip 23K256 SRAM chips, using SPI. + + Set up your spi devices with the right board-specific + platform data, or a device tree description if you want to + specify device partitioning + config MTD_SPEAR_SMI tristate "SPEAR MTD NOR Support through SMI controller" depends on PLAT_SPEAR diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index 7912d3a0ee34..f0f767624cc6 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile @@ -12,6 +12,7 @@ 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_MCHP23K256) += mchp23k256.o obj-$(CONFIG_MTD_SPEAR_SMI) += spear_smi.o obj-$(CONFIG_MTD_SST25L) += sst25l.o obj-$(CONFIG_MTD_BCM47XXSFLASH) += bcm47xxsflash.o diff --git a/drivers/mtd/devices/mchp23k256.c b/drivers/mtd/devices/mchp23k256.c new file mode 100644 index 000000000000..482a101fe887 --- /dev/null +++ b/drivers/mtd/devices/mchp23k256.c @@ -0,0 +1,183 @@ +/* + * mchp23k256.c + * + * Driver for Microchip 23k256 SPI RAM chips + * + * Copyright © 20016 Andrew Lunn + * + * This code is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct mchp23k256_flash { + struct spi_device *spi; + struct mutex lock; + struct mtd_info mtd; +}; + +#define MCHP23K256_CMD_WRITE_STATUS 0x01 +#define MCHP23K256_CMD_WRITE 0x02 +#define MCHP23K256_CMD_READ 0x03 +#define MCHP23K256_MODE_SEQ BIT(6) + +#define to_mchp23k256_flash(x) container_of(x, struct mchp23k256_flash, mtd) + +static int mchp23k256_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const unsigned char *buf) +{ + struct mchp23k256_flash *flash = to_mchp23k256_flash(mtd); + struct spi_transfer transfer[2] = {}; + struct spi_message message; + unsigned char command[3]; + + spi_message_init(&message); + + command[0] = MCHP23K256_CMD_WRITE; + command[1] = to >> 8; + command[2] = to; + + transfer[0].tx_buf = command; + transfer[0].len = sizeof(command); + spi_message_add_tail(&transfer[0], &message); + + transfer[1].tx_buf = buf; + transfer[1].len = len; + spi_message_add_tail(&transfer[1], &message); + + mutex_lock(&flash->lock); + + spi_sync(flash->spi, &message); + + if (retlen && message.actual_length > sizeof(command)) + *retlen += message.actual_length - sizeof(command); + + mutex_unlock(&flash->lock); + return 0; +} + +static int mchp23k256_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, unsigned char *buf) +{ + struct mchp23k256_flash *flash = to_mchp23k256_flash(mtd); + struct spi_transfer transfer[2] = {}; + struct spi_message message; + unsigned char command[3]; + + spi_message_init(&message); + + memset(&transfer, 0, sizeof(transfer)); + command[0] = MCHP23K256_CMD_READ; + command[1] = from >> 8; + command[2] = from; + + transfer[0].tx_buf = command; + transfer[0].len = sizeof(command); + spi_message_add_tail(&transfer[0], &message); + + transfer[1].rx_buf = buf; + transfer[1].len = len; + spi_message_add_tail(&transfer[1], &message); + + mutex_lock(&flash->lock); + + spi_sync(flash->spi, &message); + + if (retlen && message.actual_length > sizeof(command)) + *retlen += message.actual_length - sizeof(command); + + mutex_unlock(&flash->lock); + return 0; +} + +/* Set the device into sequential mode. This allows read/writes to + * the entire SRAM in a single operation + */ +static int mchp23k256_set_mode(struct spi_device *spi) +{ + struct spi_transfer transfer = {}; + struct spi_message message; + unsigned char command[2]; + + spi_message_init(&message); + + command[0] = MCHP23K256_CMD_WRITE_STATUS; + command[1] = MCHP23K256_MODE_SEQ; + + transfer.tx_buf = command; + transfer.len = sizeof(command); + spi_message_add_tail(&transfer, &message); + + return spi_sync(spi, &message); +} + + + +static int mchp23k256_probe(struct spi_device *spi) +{ + struct mchp23k256_flash *flash; + struct flash_platform_data *data; + int err; + + flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL); + if (!flash) + return -ENOMEM; + + flash->spi = spi; + mutex_init(&flash->lock); + spi_set_drvdata(spi, flash); + + err = mchp23k256_set_mode(spi); + if (err) + return err; + + data = dev_get_platdata(&spi->dev); + + flash->mtd.dev.parent = &spi->dev; + flash->mtd.type = MTD_RAM; + flash->mtd.flags = MTD_CAP_RAM; + flash->mtd.writesize = 1; + flash->mtd.size = SZ_32K; + flash->mtd._read = mchp23k256_read; + flash->mtd._write = mchp23k256_write; + + err = mtd_device_parse_register(&flash->mtd, NULL, NULL, + data ? data->parts : NULL, + data ? data->nr_parts : 0); + if (err) + return err; + + return 0; +} + +static int mchp23k256_remove(struct spi_device *spi) +{ + struct mchp23k256_flash *flash = spi_get_drvdata(spi); + + return mtd_device_unregister(&flash->mtd); +} + +static struct spi_driver mchp23k256_driver = { + .driver = { + .name = "mchp23k256", + }, + .probe = mchp23k256_probe, + .remove = mchp23k256_remove, +}; + +module_spi_driver(mchp23k256_driver); + +MODULE_DESCRIPTION("MTD SPI driver for MCHP23K256 RAM chips"); +MODULE_AUTHOR("Andrew Lunn "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:mchp23k256");