aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/devices/Kconfig10
-rw-r--r--drivers/mtd/devices/Makefile1
-rw-r--r--drivers/mtd/devices/mchp23k256.c182
3 files changed, 193 insertions, 0 deletions
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
95 if you want to specify device partitioning or to use a device which 95 if you want to specify device partitioning or to use a device which
96 doesn't support the JEDEC ID instruction. 96 doesn't support the JEDEC ID instruction.
97 97
98config MTD_MCHP23K256
99 tristate "Microchip 23K256 SRAM"
100 depends on SPI_MASTER
101 help
102 This enables access to Microchip 23K256 SRAM chips, using SPI.
103
104 Set up your spi devices with the right board-specific
105 platform data, or a device tree description if you want to
106 specify device partitioning
107
98config MTD_SPEAR_SMI 108config MTD_SPEAR_SMI
99 tristate "SPEAR MTD NOR Support through SMI controller" 109 tristate "SPEAR MTD NOR Support through SMI controller"
100 depends on PLAT_SPEAR 110 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
12obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o 12obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o
13obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o 13obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
14obj-$(CONFIG_MTD_M25P80) += m25p80.o 14obj-$(CONFIG_MTD_M25P80) += m25p80.o
15obj-$(CONFIG_MTD_MCHP23K256) += mchp23k256.o
15obj-$(CONFIG_MTD_SPEAR_SMI) += spear_smi.o 16obj-$(CONFIG_MTD_SPEAR_SMI) += spear_smi.o
16obj-$(CONFIG_MTD_SST25L) += sst25l.o 17obj-$(CONFIG_MTD_SST25L) += sst25l.o
17obj-$(CONFIG_MTD_BCM47XXSFLASH) += bcm47xxsflash.o 18obj-$(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..e237db9f1bdb
--- /dev/null
+++ b/drivers/mtd/devices/mchp23k256.c
@@ -0,0 +1,182 @@
1/*
2 * mchp23k256.c
3 *
4 * Driver for Microchip 23k256 SPI RAM chips
5 *
6 * Copyright © 2016 Andrew Lunn <andrew@lunn.ch>
7 *
8 * This code is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 */
13#include <linux/device.h>
14#include <linux/module.h>
15#include <linux/mtd/mtd.h>
16#include <linux/mtd/partitions.h>
17#include <linux/mutex.h>
18#include <linux/sched.h>
19#include <linux/sizes.h>
20#include <linux/spi/flash.h>
21#include <linux/spi/spi.h>
22
23struct mchp23k256_flash {
24 struct spi_device *spi;
25 struct mutex lock;
26 struct mtd_info mtd;
27};
28
29#define MCHP23K256_CMD_WRITE_STATUS 0x01
30#define MCHP23K256_CMD_WRITE 0x02
31#define MCHP23K256_CMD_READ 0x03
32#define MCHP23K256_MODE_SEQ BIT(6)
33
34#define to_mchp23k256_flash(x) container_of(x, struct mchp23k256_flash, mtd)
35
36static int mchp23k256_write(struct mtd_info *mtd, loff_t to, size_t len,
37 size_t *retlen, const unsigned char *buf)
38{
39 struct mchp23k256_flash *flash = to_mchp23k256_flash(mtd);
40 struct spi_transfer transfer[2] = {};
41 struct spi_message message;
42 unsigned char command[3];
43
44 spi_message_init(&message);
45
46 command[0] = MCHP23K256_CMD_WRITE;
47 command[1] = to >> 8;
48 command[2] = to;
49
50 transfer[0].tx_buf = command;
51 transfer[0].len = sizeof(command);
52 spi_message_add_tail(&transfer[0], &message);
53
54 transfer[1].tx_buf = buf;
55 transfer[1].len = len;
56 spi_message_add_tail(&transfer[1], &message);
57
58 mutex_lock(&flash->lock);
59
60 spi_sync(flash->spi, &message);
61
62 if (retlen && message.actual_length > sizeof(command))
63 *retlen += message.actual_length - sizeof(command);
64
65 mutex_unlock(&flash->lock);
66 return 0;
67}
68
69static int mchp23k256_read(struct mtd_info *mtd, loff_t from, size_t len,
70 size_t *retlen, unsigned char *buf)
71{
72 struct mchp23k256_flash *flash = to_mchp23k256_flash(mtd);
73 struct spi_transfer transfer[2] = {};
74 struct spi_message message;
75 unsigned char command[3];
76
77 spi_message_init(&message);
78
79 memset(&transfer, 0, sizeof(transfer));
80 command[0] = MCHP23K256_CMD_READ;
81 command[1] = from >> 8;
82 command[2] = from;
83
84 transfer[0].tx_buf = command;
85 transfer[0].len = sizeof(command);
86 spi_message_add_tail(&transfer[0], &message);
87
88 transfer[1].rx_buf = buf;
89 transfer[1].len = len;
90 spi_message_add_tail(&transfer[1], &message);
91
92 mutex_lock(&flash->lock);
93
94 spi_sync(flash->spi, &message);
95
96 if (retlen && message.actual_length > sizeof(command))
97 *retlen += message.actual_length - sizeof(command);
98
99 mutex_unlock(&flash->lock);
100 return 0;
101}
102
103/*
104 * Set the device into sequential mode. This allows read/writes to the
105 * entire SRAM in a single operation
106 */
107static int mchp23k256_set_mode(struct spi_device *spi)
108{
109 struct spi_transfer transfer = {};
110 struct spi_message message;
111 unsigned char command[2];
112
113 spi_message_init(&message);
114
115 command[0] = MCHP23K256_CMD_WRITE_STATUS;
116 command[1] = MCHP23K256_MODE_SEQ;
117
118 transfer.tx_buf = command;
119 transfer.len = sizeof(command);
120 spi_message_add_tail(&transfer, &message);
121
122 return spi_sync(spi, &message);
123}
124
125static int mchp23k256_probe(struct spi_device *spi)
126{
127 struct mchp23k256_flash *flash;
128 struct flash_platform_data *data;
129 int err;
130
131 flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL);
132 if (!flash)
133 return -ENOMEM;
134
135 flash->spi = spi;
136 mutex_init(&flash->lock);
137 spi_set_drvdata(spi, flash);
138
139 err = mchp23k256_set_mode(spi);
140 if (err)
141 return err;
142
143 data = dev_get_platdata(&spi->dev);
144
145 flash->mtd.dev.parent = &spi->dev;
146 flash->mtd.type = MTD_RAM;
147 flash->mtd.flags = MTD_CAP_RAM;
148 flash->mtd.writesize = 1;
149 flash->mtd.size = SZ_32K;
150 flash->mtd._read = mchp23k256_read;
151 flash->mtd._write = mchp23k256_write;
152
153 err = mtd_device_parse_register(&flash->mtd, NULL, NULL,
154 data ? data->parts : NULL,
155 data ? data->nr_parts : 0);
156 if (err)
157 return err;
158
159 return 0;
160}
161
162static int mchp23k256_remove(struct spi_device *spi)
163{
164 struct mchp23k256_flash *flash = spi_get_drvdata(spi);
165
166 return mtd_device_unregister(&flash->mtd);
167}
168
169static struct spi_driver mchp23k256_driver = {
170 .driver = {
171 .name = "mchp23k256",
172 },
173 .probe = mchp23k256_probe,
174 .remove = mchp23k256_remove,
175};
176
177module_spi_driver(mchp23k256_driver);
178
179MODULE_DESCRIPTION("MTD SPI driver for MCHP23K256 RAM chips");
180MODULE_AUTHOR("Andrew Lunn <andre@lunn.ch>");
181MODULE_LICENSE("GPL v2");
182MODULE_ALIAS("spi:mchp23k256");