aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ar71xx/patches-3.3/406-mtd-m25p80-allow-to-specify-max-read-size.patch
blob: 8861c615fa613caea0c44628d131aa78fdc7512a (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
110
111
112
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -100,6 +100,7 @@ struct m25p {
 	u16			addr_width;
 	u8			erase_opcode;
 	u8			*command;
+	size_t			max_read_len;
 };
 
 static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
@@ -352,6 +353,7 @@ static int m25p80_read(struct mtd_info *
 	struct m25p *flash = mtd_to_m25p(mtd);
 	struct spi_transfer t[2];
 	struct spi_message m;
+	loff_t ofs;
 
 	pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
 			__func__, (u32)from, len);
@@ -374,8 +376,6 @@ static int m25p80_read(struct mtd_info *
 	t[0].len = m25p_cmdsz(flash) + FAST_READ_DUMMY_BYTE;
 	spi_message_add_tail(&t[0], &m);
 
-	t[1].rx_buf = buf;
-	t[1].len = len;
 	spi_message_add_tail(&t[1], &m);
 
 	/* Byte count starts at zero. */
@@ -383,13 +383,6 @@ static int m25p80_read(struct mtd_info *
 
 	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.
@@ -397,11 +390,44 @@ static int m25p80_read(struct mtd_info *
 
 	/* Set up the write data buffer. */
 	flash->command[0] = OPCODE_READ;
-	m25p_addr2cmd(flash, from, flash->command);
 
-	spi_sync(flash->spi, &m);
+	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);
 
-	*retlen = m.actual_length - m25p_cmdsz(flash) - FAST_READ_DUMMY_BYTE;
+		done = m.actual_length - m25p_cmdsz(flash) -
+		       FAST_READ_DUMMY_BYTE;
+		if (done != readlen) {
+			mutex_unlock(&flash->lock);
+			return 1;
+		}
+
+		ofs += done;
+		len -= done;
+	}
+
+	*retlen = ofs;
 
 	mutex_unlock(&flash->lock);
 
@@ -925,6 +951,12 @@ static int __devinit m25p_probe(struct s
 	flash->mtd.erase = m25p80_erase;
 	flash->mtd.read = m25p80_read;
 
+	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 (JEDEC_MFR(info->jedec_id) == CFI_MFR_SST)
 		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 */
 };