aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ar71xx/patches-3.10/406-mtd-m25p80-allow-to-specify-max-read-size.patch
blob: 8dfad61e63d43162de0c05d951349cec0b7296d6 (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
107
108
109
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -93,6 +93,7 @@ struct m25p {
 	u8			erase_opcode;
 	u8			*command;
 	bool			fast_read;
+	size_t			max_read_len;
 };
 
 static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
@@ -344,6 +345,7 @@ static int m25p80_read(struct mtd_info *
 	struct spi_transfer t[2];
 	struct spi_message m;
 	uint8_t opcode;
+	loff_t ofs;
 
 	pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
 			__func__, (u32)from, len);
@@ -359,19 +361,10 @@ static int m25p80_read(struct mtd_info *
 	t[0].len = m25p_cmdsz(flash) + (flash->fast_read ? 1 : 0);
 	spi_message_add_tail(&t[0], &m);
 
-	t[1].rx_buf = buf;
-	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;
-	}
-
 	/* FIXME switch to OPCODE_FAST_READ.  It's required for higher
 	 * clocks; and at this writing, every chip this driver handles
 	 * supports that opcode.
@@ -380,13 +373,43 @@ static int m25p80_read(struct mtd_info *
 	/* Set up the write data buffer. */
 	opcode = flash->fast_read ? OPCODE_FAST_READ : OPCODE_NORM_READ;
 	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].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) -
+		       (flash->fast_read ? 1 : 0);
+		if (done != readlen) {
+			mutex_unlock(&flash->lock);
+			return 1;
+		}
 
-	*retlen = m.actual_length - m25p_cmdsz(flash) -
-			(flash->fast_read ? 1 : 0);
+		ofs += done;
+		len -= done;
+	}
 
+	*retlen = ofs;
 	mutex_unlock(&flash->lock);
 
 	return 0;
@@ -1021,6 +1044,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 */
 };