808 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Renesas RPC-IF core driver4 *5 * Copyright (C) 2018-2019 Renesas Solutions Corp.6 * Copyright (C) 2019 Macronix International Co., Ltd.7 * Copyright (C) 2019-2020 Cogent Embedded, Inc.8 */9 10#include <linux/bitops.h>11#include <linux/clk.h>12#include <linux/io.h>13#include <linux/module.h>14#include <linux/platform_device.h>15#include <linux/of.h>16#include <linux/regmap.h>17#include <linux/reset.h>18 19#include <memory/renesas-rpc-if.h>20 21#define RPCIF_CMNCR 0x0000 /* R/W */22#define RPCIF_CMNCR_MD BIT(31)23#define RPCIF_CMNCR_MOIIO3(val) (((val) & 0x3) << 22)24#define RPCIF_CMNCR_MOIIO2(val) (((val) & 0x3) << 20)25#define RPCIF_CMNCR_MOIIO1(val) (((val) & 0x3) << 18)26#define RPCIF_CMNCR_MOIIO0(val) (((val) & 0x3) << 16)27#define RPCIF_CMNCR_MOIIO(val) (RPCIF_CMNCR_MOIIO0(val) | RPCIF_CMNCR_MOIIO1(val) | \28 RPCIF_CMNCR_MOIIO2(val) | RPCIF_CMNCR_MOIIO3(val))29#define RPCIF_CMNCR_IO3FV(val) (((val) & 0x3) << 14) /* documented for RZ/G2L */30#define RPCIF_CMNCR_IO2FV(val) (((val) & 0x3) << 12) /* documented for RZ/G2L */31#define RPCIF_CMNCR_IO0FV(val) (((val) & 0x3) << 8)32#define RPCIF_CMNCR_IOFV(val) (RPCIF_CMNCR_IO0FV(val) | RPCIF_CMNCR_IO2FV(val) | \33 RPCIF_CMNCR_IO3FV(val))34#define RPCIF_CMNCR_BSZ(val) (((val) & 0x3) << 0)35 36#define RPCIF_SSLDR 0x0004 /* R/W */37#define RPCIF_SSLDR_SPNDL(d) (((d) & 0x7) << 16)38#define RPCIF_SSLDR_SLNDL(d) (((d) & 0x7) << 8)39#define RPCIF_SSLDR_SCKDL(d) (((d) & 0x7) << 0)40 41#define RPCIF_DRCR 0x000C /* R/W */42#define RPCIF_DRCR_SSLN BIT(24)43#define RPCIF_DRCR_RBURST(v) ((((v) - 1) & 0x1F) << 16)44#define RPCIF_DRCR_RCF BIT(9)45#define RPCIF_DRCR_RBE BIT(8)46#define RPCIF_DRCR_SSLE BIT(0)47 48#define RPCIF_DRCMR 0x0010 /* R/W */49#define RPCIF_DRCMR_CMD(c) (((c) & 0xFF) << 16)50#define RPCIF_DRCMR_OCMD(c) (((c) & 0xFF) << 0)51 52#define RPCIF_DREAR 0x0014 /* R/W */53#define RPCIF_DREAR_EAV(c) (((c) & 0xF) << 16)54#define RPCIF_DREAR_EAC(c) (((c) & 0x7) << 0)55 56#define RPCIF_DROPR 0x0018 /* R/W */57 58#define RPCIF_DRENR 0x001C /* R/W */59#define RPCIF_DRENR_CDB(o) (u32)((((o) & 0x3) << 30))60#define RPCIF_DRENR_OCDB(o) (((o) & 0x3) << 28)61#define RPCIF_DRENR_ADB(o) (((o) & 0x3) << 24)62#define RPCIF_DRENR_OPDB(o) (((o) & 0x3) << 20)63#define RPCIF_DRENR_DRDB(o) (((o) & 0x3) << 16)64#define RPCIF_DRENR_DME BIT(15)65#define RPCIF_DRENR_CDE BIT(14)66#define RPCIF_DRENR_OCDE BIT(12)67#define RPCIF_DRENR_ADE(v) (((v) & 0xF) << 8)68#define RPCIF_DRENR_OPDE(v) (((v) & 0xF) << 4)69 70#define RPCIF_SMCR 0x0020 /* R/W */71#define RPCIF_SMCR_SSLKP BIT(8)72#define RPCIF_SMCR_SPIRE BIT(2)73#define RPCIF_SMCR_SPIWE BIT(1)74#define RPCIF_SMCR_SPIE BIT(0)75 76#define RPCIF_SMCMR 0x0024 /* R/W */77#define RPCIF_SMCMR_CMD(c) (((c) & 0xFF) << 16)78#define RPCIF_SMCMR_OCMD(c) (((c) & 0xFF) << 0)79 80#define RPCIF_SMADR 0x0028 /* R/W */81 82#define RPCIF_SMOPR 0x002C /* R/W */83#define RPCIF_SMOPR_OPD3(o) (((o) & 0xFF) << 24)84#define RPCIF_SMOPR_OPD2(o) (((o) & 0xFF) << 16)85#define RPCIF_SMOPR_OPD1(o) (((o) & 0xFF) << 8)86#define RPCIF_SMOPR_OPD0(o) (((o) & 0xFF) << 0)87 88#define RPCIF_SMENR 0x0030 /* R/W */89#define RPCIF_SMENR_CDB(o) (((o) & 0x3) << 30)90#define RPCIF_SMENR_OCDB(o) (((o) & 0x3) << 28)91#define RPCIF_SMENR_ADB(o) (((o) & 0x3) << 24)92#define RPCIF_SMENR_OPDB(o) (((o) & 0x3) << 20)93#define RPCIF_SMENR_SPIDB(o) (((o) & 0x3) << 16)94#define RPCIF_SMENR_DME BIT(15)95#define RPCIF_SMENR_CDE BIT(14)96#define RPCIF_SMENR_OCDE BIT(12)97#define RPCIF_SMENR_ADE(v) (((v) & 0xF) << 8)98#define RPCIF_SMENR_OPDE(v) (((v) & 0xF) << 4)99#define RPCIF_SMENR_SPIDE(v) (((v) & 0xF) << 0)100 101#define RPCIF_SMRDR0 0x0038 /* R */102#define RPCIF_SMRDR1 0x003C /* R */103#define RPCIF_SMWDR0 0x0040 /* W */104#define RPCIF_SMWDR1 0x0044 /* W */105 106#define RPCIF_CMNSR 0x0048 /* R */107#define RPCIF_CMNSR_SSLF BIT(1)108#define RPCIF_CMNSR_TEND BIT(0)109 110#define RPCIF_DRDMCR 0x0058 /* R/W */111#define RPCIF_DMDMCR_DMCYC(v) ((((v) - 1) & 0x1F) << 0)112 113#define RPCIF_DRDRENR 0x005C /* R/W */114#define RPCIF_DRDRENR_HYPE(v) (((v) & 0x7) << 12)115#define RPCIF_DRDRENR_ADDRE BIT(8)116#define RPCIF_DRDRENR_OPDRE BIT(4)117#define RPCIF_DRDRENR_DRDRE BIT(0)118 119#define RPCIF_SMDMCR 0x0060 /* R/W */120#define RPCIF_SMDMCR_DMCYC(v) ((((v) - 1) & 0x1F) << 0)121 122#define RPCIF_SMDRENR 0x0064 /* R/W */123#define RPCIF_SMDRENR_HYPE(v) (((v) & 0x7) << 12)124#define RPCIF_SMDRENR_ADDRE BIT(8)125#define RPCIF_SMDRENR_OPDRE BIT(4)126#define RPCIF_SMDRENR_SPIDRE BIT(0)127 128#define RPCIF_PHYADD 0x0070 /* R/W available on R-Car E3/D3/V3M and RZ/G2{E,L} */129#define RPCIF_PHYWR 0x0074 /* R/W available on R-Car E3/D3/V3M and RZ/G2{E,L} */130 131#define RPCIF_PHYCNT 0x007C /* R/W */132#define RPCIF_PHYCNT_CAL BIT(31)133#define RPCIF_PHYCNT_OCTA(v) (((v) & 0x3) << 22)134#define RPCIF_PHYCNT_EXDS BIT(21)135#define RPCIF_PHYCNT_OCT BIT(20)136#define RPCIF_PHYCNT_DDRCAL BIT(19)137#define RPCIF_PHYCNT_HS BIT(18)138#define RPCIF_PHYCNT_CKSEL(v) (((v) & 0x3) << 16) /* valid only for RZ/G2L */139#define RPCIF_PHYCNT_STRTIM(v) (((v) & 0x7) << 15 | ((v) & 0x8) << 24) /* valid for R-Car and RZ/G2{E,H,M,N} */140 141#define RPCIF_PHYCNT_WBUF2 BIT(4)142#define RPCIF_PHYCNT_WBUF BIT(2)143#define RPCIF_PHYCNT_PHYMEM(v) (((v) & 0x3) << 0)144#define RPCIF_PHYCNT_PHYMEM_MASK GENMASK(1, 0)145 146#define RPCIF_PHYOFFSET1 0x0080 /* R/W */147#define RPCIF_PHYOFFSET1_DDRTMG(v) (((v) & 0x3) << 28)148 149#define RPCIF_PHYOFFSET2 0x0084 /* R/W */150#define RPCIF_PHYOFFSET2_OCTTMG(v) (((v) & 0x7) << 8)151 152#define RPCIF_PHYINT 0x0088 /* R/W */153#define RPCIF_PHYINT_WPVAL BIT(1)154 155static const struct regmap_range rpcif_volatile_ranges[] = {156 regmap_reg_range(RPCIF_SMRDR0, RPCIF_SMRDR1),157 regmap_reg_range(RPCIF_SMWDR0, RPCIF_SMWDR1),158 regmap_reg_range(RPCIF_CMNSR, RPCIF_CMNSR),159};160 161static const struct regmap_access_table rpcif_volatile_table = {162 .yes_ranges = rpcif_volatile_ranges,163 .n_yes_ranges = ARRAY_SIZE(rpcif_volatile_ranges),164};165 166struct rpcif_info {167 enum rpcif_type type;168 u8 strtim;169};170 171struct rpcif_priv {172 struct device *dev;173 void __iomem *base;174 void __iomem *dirmap;175 struct regmap *regmap;176 struct reset_control *rstc;177 struct platform_device *vdev;178 size_t size;179 const struct rpcif_info *info;180 enum rpcif_data_dir dir;181 u8 bus_size;182 u8 xfer_size;183 void *buffer;184 u32 xferlen;185 u32 smcr;186 u32 smadr;187 u32 command; /* DRCMR or SMCMR */188 u32 option; /* DROPR or SMOPR */189 u32 enable; /* DRENR or SMENR */190 u32 dummy; /* DRDMCR or SMDMCR */191 u32 ddr; /* DRDRENR or SMDRENR */192};193 194static const struct rpcif_info rpcif_info_r8a7796 = {195 .type = RPCIF_RCAR_GEN3,196 .strtim = 6,197};198 199static const struct rpcif_info rpcif_info_gen3 = {200 .type = RPCIF_RCAR_GEN3,201 .strtim = 7,202};203 204static const struct rpcif_info rpcif_info_rz_g2l = {205 .type = RPCIF_RZ_G2L,206 .strtim = 7,207};208 209static const struct rpcif_info rpcif_info_gen4 = {210 .type = RPCIF_RCAR_GEN4,211 .strtim = 15,212};213 214/*215 * Custom accessor functions to ensure SM[RW]DR[01] are always accessed with216 * proper width. Requires rpcif_priv.xfer_size to be correctly set before!217 */218static int rpcif_reg_read(void *context, unsigned int reg, unsigned int *val)219{220 struct rpcif_priv *rpc = context;221 222 switch (reg) {223 case RPCIF_SMRDR0:224 case RPCIF_SMWDR0:225 switch (rpc->xfer_size) {226 case 1:227 *val = readb(rpc->base + reg);228 return 0;229 230 case 2:231 *val = readw(rpc->base + reg);232 return 0;233 234 case 4:235 case 8:236 *val = readl(rpc->base + reg);237 return 0;238 239 default:240 return -EILSEQ;241 }242 243 case RPCIF_SMRDR1:244 case RPCIF_SMWDR1:245 if (rpc->xfer_size != 8)246 return -EILSEQ;247 break;248 }249 250 *val = readl(rpc->base + reg);251 return 0;252}253 254static int rpcif_reg_write(void *context, unsigned int reg, unsigned int val)255{256 struct rpcif_priv *rpc = context;257 258 switch (reg) {259 case RPCIF_SMWDR0:260 switch (rpc->xfer_size) {261 case 1:262 writeb(val, rpc->base + reg);263 return 0;264 265 case 2:266 writew(val, rpc->base + reg);267 return 0;268 269 case 4:270 case 8:271 writel(val, rpc->base + reg);272 return 0;273 274 default:275 return -EILSEQ;276 }277 278 case RPCIF_SMWDR1:279 if (rpc->xfer_size != 8)280 return -EILSEQ;281 break;282 283 case RPCIF_SMRDR0:284 case RPCIF_SMRDR1:285 return -EPERM;286 }287 288 writel(val, rpc->base + reg);289 return 0;290}291 292static const struct regmap_config rpcif_regmap_config = {293 .reg_bits = 32,294 .val_bits = 32,295 .reg_stride = 4,296 .reg_read = rpcif_reg_read,297 .reg_write = rpcif_reg_write,298 .fast_io = true,299 .max_register = RPCIF_PHYINT,300 .volatile_table = &rpcif_volatile_table,301};302 303int rpcif_sw_init(struct rpcif *rpcif, struct device *dev)304{305 struct rpcif_priv *rpc = dev_get_drvdata(dev);306 307 rpcif->dev = dev;308 rpcif->dirmap = rpc->dirmap;309 rpcif->size = rpc->size;310 return 0;311}312EXPORT_SYMBOL(rpcif_sw_init);313 314static void rpcif_rzg2l_timing_adjust_sdr(struct rpcif_priv *rpc)315{316 regmap_write(rpc->regmap, RPCIF_PHYWR, 0xa5390000);317 regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000000);318 regmap_write(rpc->regmap, RPCIF_PHYWR, 0x00008080);319 regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000022);320 regmap_write(rpc->regmap, RPCIF_PHYWR, 0x00008080);321 regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000024);322 regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_CKSEL(3),323 RPCIF_PHYCNT_CKSEL(3));324 regmap_write(rpc->regmap, RPCIF_PHYWR, 0x00000030);325 regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000032);326}327 328int rpcif_hw_init(struct device *dev, bool hyperflash)329{330 struct rpcif_priv *rpc = dev_get_drvdata(dev);331 u32 dummy;332 int ret;333 334 ret = pm_runtime_resume_and_get(dev);335 if (ret)336 return ret;337 338 if (rpc->info->type == RPCIF_RZ_G2L) {339 ret = reset_control_reset(rpc->rstc);340 if (ret)341 return ret;342 usleep_range(200, 300);343 rpcif_rzg2l_timing_adjust_sdr(rpc);344 }345 346 regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_PHYMEM_MASK,347 RPCIF_PHYCNT_PHYMEM(hyperflash ? 3 : 0));348 349 /* DMA Transfer is not supported */350 regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_HS, 0);351 352 regmap_update_bits(rpc->regmap, RPCIF_PHYCNT,353 /* create mask with all affected bits set */354 RPCIF_PHYCNT_STRTIM(BIT(fls(rpc->info->strtim)) - 1),355 RPCIF_PHYCNT_STRTIM(rpc->info->strtim));356 357 regmap_update_bits(rpc->regmap, RPCIF_PHYOFFSET1, RPCIF_PHYOFFSET1_DDRTMG(3),358 RPCIF_PHYOFFSET1_DDRTMG(3));359 regmap_update_bits(rpc->regmap, RPCIF_PHYOFFSET2, RPCIF_PHYOFFSET2_OCTTMG(7),360 RPCIF_PHYOFFSET2_OCTTMG(4));361 362 if (hyperflash)363 regmap_update_bits(rpc->regmap, RPCIF_PHYINT,364 RPCIF_PHYINT_WPVAL, 0);365 366 if (rpc->info->type == RPCIF_RZ_G2L)367 regmap_update_bits(rpc->regmap, RPCIF_CMNCR,368 RPCIF_CMNCR_MOIIO(3) | RPCIF_CMNCR_IOFV(3) |369 RPCIF_CMNCR_BSZ(3),370 RPCIF_CMNCR_MOIIO(1) | RPCIF_CMNCR_IOFV(3) |371 RPCIF_CMNCR_BSZ(hyperflash ? 1 : 0));372 else373 regmap_update_bits(rpc->regmap, RPCIF_CMNCR,374 RPCIF_CMNCR_MOIIO(3) | RPCIF_CMNCR_BSZ(3),375 RPCIF_CMNCR_MOIIO(3) |376 RPCIF_CMNCR_BSZ(hyperflash ? 1 : 0));377 378 /* Set RCF after BSZ update */379 regmap_write(rpc->regmap, RPCIF_DRCR, RPCIF_DRCR_RCF);380 /* Dummy read according to spec */381 regmap_read(rpc->regmap, RPCIF_DRCR, &dummy);382 regmap_write(rpc->regmap, RPCIF_SSLDR, RPCIF_SSLDR_SPNDL(7) |383 RPCIF_SSLDR_SLNDL(7) | RPCIF_SSLDR_SCKDL(7));384 385 pm_runtime_put(dev);386 387 rpc->bus_size = hyperflash ? 2 : 1;388 389 return 0;390}391EXPORT_SYMBOL(rpcif_hw_init);392 393static int wait_msg_xfer_end(struct rpcif_priv *rpc)394{395 u32 sts;396 397 return regmap_read_poll_timeout(rpc->regmap, RPCIF_CMNSR, sts,398 sts & RPCIF_CMNSR_TEND, 0,399 USEC_PER_SEC);400}401 402static u8 rpcif_bits_set(struct rpcif_priv *rpc, u32 nbytes)403{404 if (rpc->bus_size == 2)405 nbytes /= 2;406 nbytes = clamp(nbytes, 1U, 4U);407 return GENMASK(3, 4 - nbytes);408}409 410static u8 rpcif_bit_size(u8 buswidth)411{412 return buswidth > 4 ? 2 : ilog2(buswidth);413}414 415void rpcif_prepare(struct device *dev, const struct rpcif_op *op, u64 *offs,416 size_t *len)417{418 struct rpcif_priv *rpc = dev_get_drvdata(dev);419 420 rpc->smcr = 0;421 rpc->smadr = 0;422 rpc->enable = 0;423 rpc->command = 0;424 rpc->option = 0;425 rpc->dummy = 0;426 rpc->ddr = 0;427 rpc->xferlen = 0;428 429 if (op->cmd.buswidth) {430 rpc->enable = RPCIF_SMENR_CDE |431 RPCIF_SMENR_CDB(rpcif_bit_size(op->cmd.buswidth));432 rpc->command = RPCIF_SMCMR_CMD(op->cmd.opcode);433 if (op->cmd.ddr)434 rpc->ddr = RPCIF_SMDRENR_HYPE(0x5);435 }436 if (op->ocmd.buswidth) {437 rpc->enable |= RPCIF_SMENR_OCDE |438 RPCIF_SMENR_OCDB(rpcif_bit_size(op->ocmd.buswidth));439 rpc->command |= RPCIF_SMCMR_OCMD(op->ocmd.opcode);440 }441 442 if (op->addr.buswidth) {443 rpc->enable |=444 RPCIF_SMENR_ADB(rpcif_bit_size(op->addr.buswidth));445 if (op->addr.nbytes == 4)446 rpc->enable |= RPCIF_SMENR_ADE(0xF);447 else448 rpc->enable |= RPCIF_SMENR_ADE(GENMASK(449 2, 3 - op->addr.nbytes));450 if (op->addr.ddr)451 rpc->ddr |= RPCIF_SMDRENR_ADDRE;452 453 if (offs && len)454 rpc->smadr = *offs;455 else456 rpc->smadr = op->addr.val;457 }458 459 if (op->dummy.buswidth) {460 rpc->enable |= RPCIF_SMENR_DME;461 rpc->dummy = RPCIF_SMDMCR_DMCYC(op->dummy.ncycles);462 }463 464 if (op->option.buswidth) {465 rpc->enable |= RPCIF_SMENR_OPDE(466 rpcif_bits_set(rpc, op->option.nbytes)) |467 RPCIF_SMENR_OPDB(rpcif_bit_size(op->option.buswidth));468 if (op->option.ddr)469 rpc->ddr |= RPCIF_SMDRENR_OPDRE;470 rpc->option = op->option.val;471 }472 473 rpc->dir = op->data.dir;474 if (op->data.buswidth) {475 u32 nbytes;476 477 rpc->buffer = op->data.buf.in;478 switch (op->data.dir) {479 case RPCIF_DATA_IN:480 rpc->smcr = RPCIF_SMCR_SPIRE;481 break;482 case RPCIF_DATA_OUT:483 rpc->smcr = RPCIF_SMCR_SPIWE;484 break;485 default:486 break;487 }488 if (op->data.ddr)489 rpc->ddr |= RPCIF_SMDRENR_SPIDRE;490 491 if (offs && len)492 nbytes = *len;493 else494 nbytes = op->data.nbytes;495 rpc->xferlen = nbytes;496 497 rpc->enable |= RPCIF_SMENR_SPIDB(rpcif_bit_size(op->data.buswidth));498 }499}500EXPORT_SYMBOL(rpcif_prepare);501 502int rpcif_manual_xfer(struct device *dev)503{504 struct rpcif_priv *rpc = dev_get_drvdata(dev);505 u32 smenr, smcr, pos = 0, max = rpc->bus_size == 2 ? 8 : 4;506 int ret = 0;507 508 ret = pm_runtime_resume_and_get(dev);509 if (ret < 0)510 return ret;511 512 regmap_update_bits(rpc->regmap, RPCIF_PHYCNT,513 RPCIF_PHYCNT_CAL, RPCIF_PHYCNT_CAL);514 regmap_update_bits(rpc->regmap, RPCIF_CMNCR,515 RPCIF_CMNCR_MD, RPCIF_CMNCR_MD);516 regmap_write(rpc->regmap, RPCIF_SMCMR, rpc->command);517 regmap_write(rpc->regmap, RPCIF_SMOPR, rpc->option);518 regmap_write(rpc->regmap, RPCIF_SMDMCR, rpc->dummy);519 regmap_write(rpc->regmap, RPCIF_SMDRENR, rpc->ddr);520 regmap_write(rpc->regmap, RPCIF_SMADR, rpc->smadr);521 smenr = rpc->enable;522 523 switch (rpc->dir) {524 case RPCIF_DATA_OUT:525 while (pos < rpc->xferlen) {526 u32 bytes_left = rpc->xferlen - pos;527 u32 nbytes, data[2], *p = data;528 529 smcr = rpc->smcr | RPCIF_SMCR_SPIE;530 531 /* nbytes may only be 1, 2, 4, or 8 */532 nbytes = bytes_left >= max ? max : (1 << ilog2(bytes_left));533 if (bytes_left > nbytes)534 smcr |= RPCIF_SMCR_SSLKP;535 536 smenr |= RPCIF_SMENR_SPIDE(rpcif_bits_set(rpc, nbytes));537 regmap_write(rpc->regmap, RPCIF_SMENR, smenr);538 rpc->xfer_size = nbytes;539 540 memcpy(data, rpc->buffer + pos, nbytes);541 if (nbytes == 8)542 regmap_write(rpc->regmap, RPCIF_SMWDR1, *p++);543 regmap_write(rpc->regmap, RPCIF_SMWDR0, *p);544 545 regmap_write(rpc->regmap, RPCIF_SMCR, smcr);546 ret = wait_msg_xfer_end(rpc);547 if (ret)548 goto err_out;549 550 pos += nbytes;551 smenr = rpc->enable &552 ~RPCIF_SMENR_CDE & ~RPCIF_SMENR_ADE(0xF);553 }554 break;555 case RPCIF_DATA_IN:556 /*557 * RPC-IF spoils the data for the commands without an address558 * phase (like RDID) in the manual mode, so we'll have to work559 * around this issue by using the external address space read560 * mode instead.561 */562 if (!(smenr & RPCIF_SMENR_ADE(0xF)) && rpc->dirmap) {563 u32 dummy;564 565 regmap_update_bits(rpc->regmap, RPCIF_CMNCR,566 RPCIF_CMNCR_MD, 0);567 regmap_write(rpc->regmap, RPCIF_DRCR,568 RPCIF_DRCR_RBURST(32) | RPCIF_DRCR_RBE);569 regmap_write(rpc->regmap, RPCIF_DRCMR, rpc->command);570 regmap_write(rpc->regmap, RPCIF_DREAR,571 RPCIF_DREAR_EAC(1));572 regmap_write(rpc->regmap, RPCIF_DROPR, rpc->option);573 regmap_write(rpc->regmap, RPCIF_DRENR,574 smenr & ~RPCIF_SMENR_SPIDE(0xF));575 regmap_write(rpc->regmap, RPCIF_DRDMCR, rpc->dummy);576 regmap_write(rpc->regmap, RPCIF_DRDRENR, rpc->ddr);577 memcpy_fromio(rpc->buffer, rpc->dirmap, rpc->xferlen);578 regmap_write(rpc->regmap, RPCIF_DRCR, RPCIF_DRCR_RCF);579 /* Dummy read according to spec */580 regmap_read(rpc->regmap, RPCIF_DRCR, &dummy);581 break;582 }583 while (pos < rpc->xferlen) {584 u32 bytes_left = rpc->xferlen - pos;585 u32 nbytes, data[2], *p = data;586 587 /* nbytes may only be 1, 2, 4, or 8 */588 nbytes = bytes_left >= max ? max : (1 << ilog2(bytes_left));589 590 regmap_write(rpc->regmap, RPCIF_SMADR,591 rpc->smadr + pos);592 smenr &= ~RPCIF_SMENR_SPIDE(0xF);593 smenr |= RPCIF_SMENR_SPIDE(rpcif_bits_set(rpc, nbytes));594 regmap_write(rpc->regmap, RPCIF_SMENR, smenr);595 regmap_write(rpc->regmap, RPCIF_SMCR,596 rpc->smcr | RPCIF_SMCR_SPIE);597 rpc->xfer_size = nbytes;598 ret = wait_msg_xfer_end(rpc);599 if (ret)600 goto err_out;601 602 if (nbytes == 8)603 regmap_read(rpc->regmap, RPCIF_SMRDR1, p++);604 regmap_read(rpc->regmap, RPCIF_SMRDR0, p);605 memcpy(rpc->buffer + pos, data, nbytes);606 607 pos += nbytes;608 }609 break;610 default:611 regmap_write(rpc->regmap, RPCIF_SMENR, rpc->enable);612 regmap_write(rpc->regmap, RPCIF_SMCR,613 rpc->smcr | RPCIF_SMCR_SPIE);614 ret = wait_msg_xfer_end(rpc);615 if (ret)616 goto err_out;617 }618 619exit:620 pm_runtime_put(dev);621 return ret;622 623err_out:624 if (reset_control_reset(rpc->rstc))625 dev_err(dev, "Failed to reset HW\n");626 rpcif_hw_init(dev, rpc->bus_size == 2);627 goto exit;628}629EXPORT_SYMBOL(rpcif_manual_xfer);630 631static void memcpy_fromio_readw(void *to,632 const void __iomem *from,633 size_t count)634{635 const int maxw = (IS_ENABLED(CONFIG_64BIT)) ? 8 : 4;636 u8 buf[2];637 638 if (count && ((unsigned long)from & 1)) {639 *(u16 *)buf = __raw_readw((void __iomem *)((unsigned long)from & ~1));640 *(u8 *)to = buf[1];641 from++;642 to++;643 count--;644 }645 while (count >= 2 && !IS_ALIGNED((unsigned long)from, maxw)) {646 *(u16 *)to = __raw_readw(from);647 from += 2;648 to += 2;649 count -= 2;650 }651 while (count >= maxw) {652#ifdef CONFIG_64BIT653 *(u64 *)to = __raw_readq(from);654#else655 *(u32 *)to = __raw_readl(from);656#endif657 from += maxw;658 to += maxw;659 count -= maxw;660 }661 while (count >= 2) {662 *(u16 *)to = __raw_readw(from);663 from += 2;664 to += 2;665 count -= 2;666 }667 if (count) {668 *(u16 *)buf = __raw_readw(from);669 *(u8 *)to = buf[0];670 }671}672 673ssize_t rpcif_dirmap_read(struct device *dev, u64 offs, size_t len, void *buf)674{675 struct rpcif_priv *rpc = dev_get_drvdata(dev);676 loff_t from = offs & (rpc->size - 1);677 size_t size = rpc->size - from;678 int ret;679 680 if (len > size)681 len = size;682 683 ret = pm_runtime_resume_and_get(dev);684 if (ret < 0)685 return ret;686 687 regmap_update_bits(rpc->regmap, RPCIF_CMNCR, RPCIF_CMNCR_MD, 0);688 regmap_write(rpc->regmap, RPCIF_DRCR, 0);689 regmap_write(rpc->regmap, RPCIF_DRCMR, rpc->command);690 regmap_write(rpc->regmap, RPCIF_DREAR,691 RPCIF_DREAR_EAV(offs >> 25) | RPCIF_DREAR_EAC(1));692 regmap_write(rpc->regmap, RPCIF_DROPR, rpc->option);693 regmap_write(rpc->regmap, RPCIF_DRENR,694 rpc->enable & ~RPCIF_SMENR_SPIDE(0xF));695 regmap_write(rpc->regmap, RPCIF_DRDMCR, rpc->dummy);696 regmap_write(rpc->regmap, RPCIF_DRDRENR, rpc->ddr);697 698 if (rpc->bus_size == 2)699 memcpy_fromio_readw(buf, rpc->dirmap + from, len);700 else701 memcpy_fromio(buf, rpc->dirmap + from, len);702 703 pm_runtime_put(dev);704 705 return len;706}707EXPORT_SYMBOL(rpcif_dirmap_read);708 709static int rpcif_probe(struct platform_device *pdev)710{711 struct device *dev = &pdev->dev;712 struct platform_device *vdev;713 struct device_node *flash;714 struct rpcif_priv *rpc;715 struct resource *res;716 const char *name;717 int ret;718 719 flash = of_get_next_child(dev->of_node, NULL);720 if (!flash) {721 dev_warn(dev, "no flash node found\n");722 return -ENODEV;723 }724 725 if (of_device_is_compatible(flash, "jedec,spi-nor")) {726 name = "rpc-if-spi";727 } else if (of_device_is_compatible(flash, "cfi-flash")) {728 name = "rpc-if-hyperflash";729 } else {730 of_node_put(flash);731 dev_warn(dev, "unknown flash type\n");732 return -ENODEV;733 }734 of_node_put(flash);735 736 rpc = devm_kzalloc(dev, sizeof(*rpc), GFP_KERNEL);737 if (!rpc)738 return -ENOMEM;739 740 rpc->base = devm_platform_ioremap_resource_byname(pdev, "regs");741 if (IS_ERR(rpc->base))742 return PTR_ERR(rpc->base);743 744 rpc->regmap = devm_regmap_init(dev, NULL, rpc, &rpcif_regmap_config);745 if (IS_ERR(rpc->regmap)) {746 dev_err(dev, "failed to init regmap for rpcif, error %ld\n",747 PTR_ERR(rpc->regmap));748 return PTR_ERR(rpc->regmap);749 }750 751 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirmap");752 rpc->dirmap = devm_ioremap_resource(dev, res);753 if (IS_ERR(rpc->dirmap))754 return PTR_ERR(rpc->dirmap);755 756 rpc->size = resource_size(res);757 rpc->info = of_device_get_match_data(dev);758 rpc->rstc = devm_reset_control_get_exclusive(dev, NULL);759 if (IS_ERR(rpc->rstc))760 return PTR_ERR(rpc->rstc);761 762 vdev = platform_device_alloc(name, pdev->id);763 if (!vdev)764 return -ENOMEM;765 vdev->dev.parent = dev;766 767 rpc->dev = dev;768 rpc->vdev = vdev;769 platform_set_drvdata(pdev, rpc);770 771 ret = platform_device_add(vdev);772 if (ret) {773 platform_device_put(vdev);774 return ret;775 }776 777 return 0;778}779 780static void rpcif_remove(struct platform_device *pdev)781{782 struct rpcif_priv *rpc = platform_get_drvdata(pdev);783 784 platform_device_unregister(rpc->vdev);785}786 787static const struct of_device_id rpcif_of_match[] = {788 { .compatible = "renesas,r8a7796-rpc-if", .data = &rpcif_info_r8a7796 },789 { .compatible = "renesas,rcar-gen3-rpc-if", .data = &rpcif_info_gen3 },790 { .compatible = "renesas,rcar-gen4-rpc-if", .data = &rpcif_info_gen4 },791 { .compatible = "renesas,rzg2l-rpc-if", .data = &rpcif_info_rz_g2l },792 {},793};794MODULE_DEVICE_TABLE(of, rpcif_of_match);795 796static struct platform_driver rpcif_driver = {797 .probe = rpcif_probe,798 .remove_new = rpcif_remove,799 .driver = {800 .name = "rpc-if",801 .of_match_table = rpcif_of_match,802 },803};804module_platform_driver(rpcif_driver);805 806MODULE_DESCRIPTION("Renesas RPC-IF core driver");807MODULE_LICENSE("GPL v2");808