2020-06-16 23:03:48 +03:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
|
|
|
/*
|
|
|
|
* Renesas RPC-IF core driver
|
|
|
|
*
|
|
|
|
* Copyright (C) 2018~2019 Renesas Solutions Corp.
|
|
|
|
* Copyright (C) 2019 Macronix International Co., Ltd.
|
|
|
|
* Copyright (C) 2019-2020 Cogent Embedded, Inc.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __RENESAS_RPC_IF_H
|
|
|
|
#define __RENESAS_RPC_IF_H
|
|
|
|
|
2020-11-26 22:11:45 +03:00
|
|
|
#include <linux/pm_runtime.h>
|
2020-06-16 23:03:48 +03:00
|
|
|
#include <linux/types.h>
|
|
|
|
|
|
|
|
enum rpcif_data_dir {
|
|
|
|
RPCIF_NO_DATA,
|
|
|
|
RPCIF_DATA_IN,
|
|
|
|
RPCIF_DATA_OUT,
|
|
|
|
};
|
|
|
|
|
2021-06-01 19:06:07 +03:00
|
|
|
struct rpcif_op {
|
2020-06-16 23:03:48 +03:00
|
|
|
struct {
|
|
|
|
u8 buswidth;
|
|
|
|
u8 opcode;
|
|
|
|
bool ddr;
|
|
|
|
} cmd, ocmd;
|
|
|
|
|
|
|
|
struct {
|
|
|
|
u8 nbytes;
|
|
|
|
u8 buswidth;
|
|
|
|
bool ddr;
|
|
|
|
u64 val;
|
|
|
|
} addr;
|
|
|
|
|
|
|
|
struct {
|
|
|
|
u8 ncycles;
|
|
|
|
u8 buswidth;
|
|
|
|
} dummy;
|
|
|
|
|
|
|
|
struct {
|
|
|
|
u8 nbytes;
|
|
|
|
u8 buswidth;
|
|
|
|
bool ddr;
|
|
|
|
u32 val;
|
|
|
|
} option;
|
|
|
|
|
|
|
|
struct {
|
|
|
|
u8 buswidth;
|
|
|
|
unsigned int nbytes;
|
|
|
|
enum rpcif_data_dir dir;
|
|
|
|
bool ddr;
|
|
|
|
union {
|
|
|
|
void *in;
|
|
|
|
const void *out;
|
|
|
|
} buf;
|
|
|
|
} data;
|
|
|
|
};
|
|
|
|
|
2021-06-01 19:06:07 +03:00
|
|
|
struct rpcif {
|
2020-06-16 23:03:48 +03:00
|
|
|
struct device *dev;
|
memory: renesas-rpc-if: Correct QSPI data transfer in Manual mode
commit fff53a551db50f5edecaa0b29a64056ab8d2bbca upstream.
This patch fixes 2 problems:
[1] The output warning logs and data loss when performing
mount/umount then remount the device with jffs2 format.
[2] The access width of SMWDR[0:1]/SMRDR[0:1] register is wrong.
This is the sample warning logs when performing mount/umount then
remount the device with jffs2 format:
jffs2: jffs2_scan_inode_node(): CRC failed on node at 0x031c51d4:
Read 0x00034e00, calculated 0xadb272a7
The reason for issue [1] is that the writing data seems to
get messed up.
Data is only completed when the number of bytes is divisible by 4.
If you only have 3 bytes of data left to write, 1 garbage byte
is inserted after the end of the write stream.
If you only have 2 bytes of data left to write, 2 bytes of '00'
are added into the write stream.
If you only have 1 byte of data left to write, 2 bytes of '00'
are added into the write stream. 1 garbage byte is inserted after
the end of the write stream.
To solve problem [1], data must be written continuously in serial
and the write stream ends when data is out.
Following HW manual 62.2.15, access to SMWDR0 register should be
in the same size as the transfer size specified in the SPIDE[3:0]
bits in the manual mode enable setting register (SMENR).
Be sure to access from address 0.
So, in 16-bit transfer (SPIDE[3:0]=b'1100), SMWDR0 should be
accessed by 16-bit width.
Similar to SMWDR1, SMDDR0/1 registers.
In current code, SMWDR0 register is accessed by regmap_write()
that only set up to do 32-bit width.
To solve problem [2], data must be written 16-bit or 8-bit when
transferring 1-byte or 2-byte.
Fixes: ca7d8b980b67 ("memory: add Renesas RPC-IF driver")
Cc: <stable@vger.kernel.org>
Signed-off-by: Duc Nguyen <duc.nguyen.ub@renesas.com>
[wsa: refactored to use regmap only via reg_read/reg_write]
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Tested-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Link: https://lore.kernel.org/r/20210922091007.5516-1-wsa+renesas@sang-engineering.com
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2021-09-22 12:10:06 +03:00
|
|
|
void __iomem *base;
|
2020-06-16 23:03:48 +03:00
|
|
|
void __iomem *dirmap;
|
|
|
|
struct regmap *regmap;
|
|
|
|
struct reset_control *rstc;
|
|
|
|
size_t size;
|
|
|
|
enum rpcif_data_dir dir;
|
|
|
|
u8 bus_size;
|
memory: renesas-rpc-if: Fix HF/OSPI data transfer in Manual Mode
[ Upstream commit 7e842d70fe599bc13594b650b2144c4b6e6d6bf1 ]
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: fff53a551db50f5e ("memory: renesas-rpc-if: Correct QSPI data transfer in Manual mode")
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Tested-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Tested-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Link: https://lore.kernel.org/r/cde9bfacf704c81865f57b15d1b48a4793da4286.1649681476.git.geert+renesas@glider.be
Link: https://lore.kernel.org/r/20220420070526.9367-1-krzysztof.kozlowski@linaro.org'
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2022-04-20 10:05:26 +03:00
|
|
|
u8 xfer_size;
|
2020-06-16 23:03:48 +03:00
|
|
|
void *buffer;
|
|
|
|
u32 xferlen;
|
|
|
|
u32 smcr;
|
|
|
|
u32 smadr;
|
|
|
|
u32 command; /* DRCMR or SMCMR */
|
|
|
|
u32 option; /* DROPR or SMOPR */
|
|
|
|
u32 enable; /* DRENR or SMENR */
|
|
|
|
u32 dummy; /* DRDMCR or SMDMCR */
|
|
|
|
u32 ddr; /* DRDRENR or SMDRENR */
|
|
|
|
};
|
|
|
|
|
2021-06-01 19:06:07 +03:00
|
|
|
int rpcif_sw_init(struct rpcif *rpc, struct device *dev);
|
2020-06-16 23:03:48 +03:00
|
|
|
void rpcif_hw_init(struct rpcif *rpc, bool hyperflash);
|
|
|
|
void rpcif_prepare(struct rpcif *rpc, const struct rpcif_op *op, u64 *offs,
|
|
|
|
size_t *len);
|
|
|
|
int rpcif_manual_xfer(struct rpcif *rpc);
|
|
|
|
ssize_t rpcif_dirmap_read(struct rpcif *rpc, u64 offs, size_t len, void *buf);
|
|
|
|
|
2020-11-26 22:11:45 +03:00
|
|
|
static inline void rpcif_enable_rpm(struct rpcif *rpc)
|
|
|
|
{
|
|
|
|
pm_runtime_enable(rpc->dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void rpcif_disable_rpm(struct rpcif *rpc)
|
|
|
|
{
|
|
|
|
pm_runtime_disable(rpc->dev);
|
|
|
|
}
|
|
|
|
|
2020-06-16 23:03:48 +03:00
|
|
|
#endif // __RENESAS_RPC_IF_H
|