diff options
Diffstat (limited to 'drivers/memory/renesas-rpc-if.c')
| -rw-r--r-- | drivers/memory/renesas-rpc-if.c | 91 | 
1 files changed, 55 insertions, 36 deletions
| diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c index 2e545f473cc6..4316988d791a 100644 --- a/drivers/memory/renesas-rpc-if.c +++ b/drivers/memory/renesas-rpc-if.c @@ -164,25 +164,39 @@ static const struct regmap_access_table rpcif_volatile_table = {  /* - * Custom accessor functions to ensure SMRDR0 and SMWDR0 are always accessed - * with proper width. Requires SMENR_SPIDE to be correctly set before! + * Custom accessor functions to ensure SM[RW]DR[01] are always accessed with + * proper width.  Requires rpcif.xfer_size to be correctly set before!   */  static int rpcif_reg_read(void *context, unsigned int reg, unsigned int *val)  {  	struct rpcif *rpc = context; -	if (reg == RPCIF_SMRDR0 || reg == RPCIF_SMWDR0) { -		u32 spide = readl(rpc->base + RPCIF_SMENR) & RPCIF_SMENR_SPIDE(0xF); - -		if (spide == 0x8) { +	switch (reg) { +	case RPCIF_SMRDR0: +	case RPCIF_SMWDR0: +		switch (rpc->xfer_size) { +		case 1:  			*val = readb(rpc->base + reg);  			return 0; -		} else if (spide == 0xC) { + +		case 2:  			*val = readw(rpc->base + reg);  			return 0; -		} else if (spide != 0xF) { + +		case 4: +		case 8: +			*val = readl(rpc->base + reg); +			return 0; + +		default:  			return -EILSEQ;  		} + +	case RPCIF_SMRDR1: +	case RPCIF_SMWDR1: +		if (rpc->xfer_size != 8) +			return -EILSEQ; +		break;  	}  	*val = readl(rpc->base + reg); @@ -193,18 +207,34 @@ static int rpcif_reg_write(void *context, unsigned int reg, unsigned int val)  {  	struct rpcif *rpc = context; -	if (reg == RPCIF_SMRDR0 || reg == RPCIF_SMWDR0) { -		u32 spide = readl(rpc->base + RPCIF_SMENR) & RPCIF_SMENR_SPIDE(0xF); - -		if (spide == 0x8) { +	switch (reg) { +	case RPCIF_SMWDR0: +		switch (rpc->xfer_size) { +		case 1:  			writeb(val, rpc->base + reg);  			return 0; -		} else if (spide == 0xC) { + +		case 2:  			writew(val, rpc->base + reg);  			return 0; -		} else if (spide != 0xF) { + +		case 4: +		case 8: +			writel(val, rpc->base + reg); +			return 0; + +		default:  			return -EILSEQ;  		} + +	case RPCIF_SMWDR1: +		if (rpc->xfer_size != 8) +			return -EILSEQ; +		break; + +	case RPCIF_SMRDR0: +	case RPCIF_SMRDR1: +		return -EPERM;  	}  	writel(val, rpc->base + reg); @@ -229,8 +259,7 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev)  	rpc->dev = dev; -	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); -	rpc->base = devm_ioremap_resource(&pdev->dev, res); +	rpc->base = devm_platform_ioremap_resource_byname(pdev, "regs");  	if (IS_ERR(rpc->base))  		return PTR_ERR(rpc->base); @@ -458,7 +487,7 @@ int rpcif_manual_xfer(struct rpcif *rpc)  	case RPCIF_DATA_OUT:  		while (pos < rpc->xferlen) {  			u32 bytes_left = rpc->xferlen - pos; -			u32 nbytes, data[2]; +			u32 nbytes, data[2], *p = data;  			smcr = rpc->smcr | RPCIF_SMCR_SPIE; @@ -469,17 +498,12 @@ int rpcif_manual_xfer(struct rpcif *rpc)  			smenr |= RPCIF_SMENR_SPIDE(rpcif_bits_set(rpc, nbytes));  			regmap_write(rpc->regmap, RPCIF_SMENR, smenr); +			rpc->xfer_size = nbytes;  			memcpy(data, rpc->buffer + pos, nbytes); -			if (nbytes == 8) { -				regmap_write(rpc->regmap, RPCIF_SMWDR1, -					     data[0]); -				regmap_write(rpc->regmap, RPCIF_SMWDR0, -					     data[1]); -			} else { -				regmap_write(rpc->regmap, RPCIF_SMWDR0, -					     data[0]); -			} +			if (nbytes == 8) +				regmap_write(rpc->regmap, RPCIF_SMWDR1, *p++); +			regmap_write(rpc->regmap, RPCIF_SMWDR0, *p);  			regmap_write(rpc->regmap, RPCIF_SMCR, smcr);  			ret = wait_msg_xfer_end(rpc); @@ -521,7 +545,7 @@ int rpcif_manual_xfer(struct rpcif *rpc)  		}  		while (pos < rpc->xferlen) {  			u32 bytes_left = rpc->xferlen - pos; -			u32 nbytes, data[2]; +			u32 nbytes, data[2], *p = data;  			/* nbytes may only be 1, 2, 4, or 8 */  			nbytes = bytes_left >= max ? max : (1 << ilog2(bytes_left)); @@ -533,19 +557,14 @@ int rpcif_manual_xfer(struct rpcif *rpc)  			regmap_write(rpc->regmap, RPCIF_SMENR, smenr);  			regmap_write(rpc->regmap, RPCIF_SMCR,  				     rpc->smcr | RPCIF_SMCR_SPIE); +			rpc->xfer_size = nbytes;  			ret = wait_msg_xfer_end(rpc);  			if (ret)  				goto err_out; -			if (nbytes == 8) { -				regmap_read(rpc->regmap, RPCIF_SMRDR1, -					    &data[0]); -				regmap_read(rpc->regmap, RPCIF_SMRDR0, -					    &data[1]); -			} else { -				regmap_read(rpc->regmap, RPCIF_SMRDR0, -					    &data[0]); -			} +			if (nbytes == 8) +				regmap_read(rpc->regmap, RPCIF_SMRDR1, p++); +			regmap_read(rpc->regmap, RPCIF_SMRDR0, p);  			memcpy(rpc->buffer + pos, data, nbytes);  			pos += nbytes; | 
