Skip to content

Commit 7e842d7

Browse files
geertuarndb
authored andcommitted
memory: renesas-rpc-if: Fix HF/OSPI data transfer in Manual Mode
HyperFlash devices fail to probe: rpc-if-hyperflash rpc-if-hyperflash: probing of hyperbus device failed In HyperFlash or Octal-SPI Flash mode, the Transfer Data Enable bits (SPIDE) in the Manual Mode Enable Setting Register (SMENR) are derived from half of the transfer size, cfr. the rpcif_bits_set() helper function. However, rpcif_reg_{read,write}() does not take the bus size into account, and does not double all Manual Mode Data Register access sizes when communicating with a HyperFlash or Octal-SPI Flash device. Fix this, and avoid the back-and-forth conversion between transfer size and Transfer Data Enable bits, by explicitly storing the transfer size in struct rpcif, and using that value to determine access size in rpcif_reg_{read,write}(). Enforce that the "high" Manual Mode Read/Write Data Registers (SM[RW]DR1) are only used for 8-byte data accesses. While at it, forbid writing to the Manual Mode Read Data Registers, as they are read-only. Fixes: fff53a5 ("memory: renesas-rpc-if: Correct QSPI data transfer in Manual mode") Signed-off-by: Geert Uytterhoeven <[email protected]> Signed-off-by: Krzysztof Kozlowski <[email protected]> Tested-by: Lad Prabhakar <[email protected]> Tested-by: Wolfram Sang <[email protected]> Reviewed-by: Wolfram Sang <[email protected]> Link: https://lore.kernel.org/r/cde9bfacf704c81865f57b15d1b48a4793da4286.1649681476.git.geert+renesas@glider.be Link: https://lore.kernel.org/r/[email protected]' Signed-off-by: Arnd Bergmann <[email protected]>
1 parent 67e473a commit 7e842d7

File tree

2 files changed

+47
-14
lines changed

2 files changed

+47
-14
lines changed

drivers/memory/renesas-rpc-if.c

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -164,25 +164,39 @@ static const struct regmap_access_table rpcif_volatile_table = {
164164

165165

166166
/*
167-
* Custom accessor functions to ensure SMRDR0 and SMWDR0 are always accessed
168-
* with proper width. Requires SMENR_SPIDE to be correctly set before!
167+
* Custom accessor functions to ensure SM[RW]DR[01] are always accessed with
168+
* proper width. Requires rpcif.xfer_size to be correctly set before!
169169
*/
170170
static int rpcif_reg_read(void *context, unsigned int reg, unsigned int *val)
171171
{
172172
struct rpcif *rpc = context;
173173

174-
if (reg == RPCIF_SMRDR0 || reg == RPCIF_SMWDR0) {
175-
u32 spide = readl(rpc->base + RPCIF_SMENR) & RPCIF_SMENR_SPIDE(0xF);
176-
177-
if (spide == 0x8) {
174+
switch (reg) {
175+
case RPCIF_SMRDR0:
176+
case RPCIF_SMWDR0:
177+
switch (rpc->xfer_size) {
178+
case 1:
178179
*val = readb(rpc->base + reg);
179180
return 0;
180-
} else if (spide == 0xC) {
181+
182+
case 2:
181183
*val = readw(rpc->base + reg);
182184
return 0;
183-
} else if (spide != 0xF) {
185+
186+
case 4:
187+
case 8:
188+
*val = readl(rpc->base + reg);
189+
return 0;
190+
191+
default:
184192
return -EILSEQ;
185193
}
194+
195+
case RPCIF_SMRDR1:
196+
case RPCIF_SMWDR1:
197+
if (rpc->xfer_size != 8)
198+
return -EILSEQ;
199+
break;
186200
}
187201

188202
*val = readl(rpc->base + reg);
@@ -193,18 +207,34 @@ static int rpcif_reg_write(void *context, unsigned int reg, unsigned int val)
193207
{
194208
struct rpcif *rpc = context;
195209

196-
if (reg == RPCIF_SMRDR0 || reg == RPCIF_SMWDR0) {
197-
u32 spide = readl(rpc->base + RPCIF_SMENR) & RPCIF_SMENR_SPIDE(0xF);
198-
199-
if (spide == 0x8) {
210+
switch (reg) {
211+
case RPCIF_SMWDR0:
212+
switch (rpc->xfer_size) {
213+
case 1:
200214
writeb(val, rpc->base + reg);
201215
return 0;
202-
} else if (spide == 0xC) {
216+
217+
case 2:
203218
writew(val, rpc->base + reg);
204219
return 0;
205-
} else if (spide != 0xF) {
220+
221+
case 4:
222+
case 8:
223+
writel(val, rpc->base + reg);
224+
return 0;
225+
226+
default:
206227
return -EILSEQ;
207228
}
229+
230+
case RPCIF_SMWDR1:
231+
if (rpc->xfer_size != 8)
232+
return -EILSEQ;
233+
break;
234+
235+
case RPCIF_SMRDR0:
236+
case RPCIF_SMRDR1:
237+
return -EPERM;
208238
}
209239

210240
writel(val, rpc->base + reg);
@@ -469,6 +499,7 @@ int rpcif_manual_xfer(struct rpcif *rpc)
469499

470500
smenr |= RPCIF_SMENR_SPIDE(rpcif_bits_set(rpc, nbytes));
471501
regmap_write(rpc->regmap, RPCIF_SMENR, smenr);
502+
rpc->xfer_size = nbytes;
472503

473504
memcpy(data, rpc->buffer + pos, nbytes);
474505
if (nbytes == 8) {
@@ -533,6 +564,7 @@ int rpcif_manual_xfer(struct rpcif *rpc)
533564
regmap_write(rpc->regmap, RPCIF_SMENR, smenr);
534565
regmap_write(rpc->regmap, RPCIF_SMCR,
535566
rpc->smcr | RPCIF_SMCR_SPIE);
567+
rpc->xfer_size = nbytes;
536568
ret = wait_msg_xfer_end(rpc);
537569
if (ret)
538570
goto err_out;

include/memory/renesas-rpc-if.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ struct rpcif {
7272
enum rpcif_type type;
7373
enum rpcif_data_dir dir;
7474
u8 bus_size;
75+
u8 xfer_size;
7576
void *buffer;
7677
u32 xferlen;
7778
u32 smcr;

0 commit comments

Comments
 (0)