summaryrefslogtreecommitdiffstats
path: root/target/linux/ar71xx/patches-3.14/406-mtd-m25p80-allow-to-specify-max-read-size.patch
blob: d229b7f8df14053260040ce52dc46906aa51c6ba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -115,6 +115,7 @@ struct m25p {
 	u8			program_opcode;
 	u8			*command;
 	enum read_type		flash_read;
+	size_t			max_read_len;
 };
 
 static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
@@ -517,6 +518,7 @@ static int m25p80_read(struct mtd_info *
 	struct spi_message m;
 	uint8_t opcode;
 	int dummy;
+	loff_t ofs;
 
 	pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
 			__func__, (u32)from, len);
@@ -534,29 +536,51 @@ static int m25p80_read(struct mtd_info *
 	t[0].len = m25p_cmdsz(flash) + dummy;
 	spi_message_add_tail(&t[0], &m);
 
-	t[1].rx_buf = buf;
-	t[1].rx_nbits = m25p80_rx_nbits(flash);
-	t[1].len = len;
 	spi_message_add_tail(&t[1], &m);
 
 	mutex_lock(&flash->lock);
 
-	/* Wait till previous write/erase is done. */
-	if (wait_till_ready(flash)) {
-		/* REVISIT status return?? */
-		mutex_unlock(&flash->lock);
-		return 1;
-	}
-
 	/* Set up the write data buffer. */
 	opcode = flash->read_opcode;
 	flash->command[0] = opcode;
-	m25p_addr2cmd(flash, from, flash->command);
+	ofs = 0;
+	while (len) {
+		size_t readlen;
+		size_t done;
+		int ret;
+
+		ret = wait_till_ready(flash);
+		if (ret) {
+			mutex_unlock(&flash->lock);
+			return 1;
+		}
+
+		if (flash->max_read_len > 0 &&
+		    flash->max_read_len < len)
+			readlen = flash->max_read_len;
+		else
+			readlen = len;
+
+		t[1].rx_buf = buf + ofs;
+		t[1].rx_nbits = m25p80_rx_nbits(flash);
+		t[1].len = readlen;
+
+		m25p_addr2cmd(flash, from + ofs, flash->command);
+
+		spi_sync(flash->spi, &m);
 
-	spi_sync(flash->spi, &m);
+		done = m.actual_length - m25p_cmdsz(flash) -
+		       dummy;
+		if (done != readlen) {
+			mutex_unlock(&flash->lock);
+			return 1;
+		}
 
-	*retlen = m.actual_length - m25p_cmdsz(flash) - dummy;
+		ofs += done;
+		len -= done;
+	}
 
+	*retlen = ofs;
 	mutex_unlock(&flash->lock);
 
 	return 0;
@@ -1193,6 +1217,12 @@ static int m25p_probe(struct spi_device
 		flash->mtd._unlock = m25p80_unlock;
 	}
 
+	if (data && data->max_read_len) {
+		flash->max_read_len = data->max_read_len;
+		dev_warn(&spi->dev, "max_read_len set to %d bytes\n",
+			flash->max_read_len);
+	}
+
 	/* sst flash chips use AAI word program */
 	if (info->flags & SST_WRITE)
 		flash->mtd._write = sst_write;
--- a/include/linux/spi/flash.h
+++ b/include/linux/spi/flash.h
@@ -25,6 +25,7 @@ struct flash_platform_data {
 
 	char		*type;
 
+	size_t		max_read_len;
 	/* we'll likely add more ... use JEDEC IDs, etc */
 };