diff options
Diffstat (limited to 'drivers/spi')
| -rw-r--r-- | drivers/spi/spi-airoha-snfi.c | 128 | ||||
| -rw-r--r-- | drivers/spi/spi-amlogic-spifc-a4.c | 4 | ||||
| -rw-r--r-- | drivers/spi/spi-cadence-quadspi.c | 5 | ||||
| -rw-r--r-- | drivers/spi/spi-dw-mmio.c | 4 | ||||
| -rw-r--r-- | drivers/spi/spi-intel-pci.c | 2 | ||||
| -rw-r--r-- | drivers/spi/spi-intel.c | 6 | ||||
| -rw-r--r-- | drivers/spi/spi-nxp-fspi.c | 32 | ||||
| -rw-r--r-- | drivers/spi/spi-rockchip-sfc.c | 12 | 
8 files changed, 151 insertions, 42 deletions
| diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c index dbe640986825..b78163eaed61 100644 --- a/drivers/spi/spi-airoha-snfi.c +++ b/drivers/spi/spi-airoha-snfi.c @@ -192,6 +192,14 @@  #define SPI_NAND_OP_RESET			0xff  #define SPI_NAND_OP_DIE_SELECT			0xc2 +/* SNAND FIFO commands */ +#define SNAND_FIFO_TX_BUSWIDTH_SINGLE		0x08 +#define SNAND_FIFO_TX_BUSWIDTH_DUAL		0x09 +#define SNAND_FIFO_TX_BUSWIDTH_QUAD		0x0a +#define SNAND_FIFO_RX_BUSWIDTH_SINGLE		0x0c +#define SNAND_FIFO_RX_BUSWIDTH_DUAL		0x0e +#define SNAND_FIFO_RX_BUSWIDTH_QUAD		0x0f +  #define SPI_NAND_CACHE_SIZE			(SZ_4K + SZ_256)  #define SPI_MAX_TRANSFER_SIZE			511 @@ -387,10 +395,26 @@ static int airoha_snand_set_mode(struct airoha_snand_ctrl *as_ctrl,  	return regmap_write(as_ctrl->regmap_ctrl, REG_SPI_CTRL_DUMMY, 0);  } -static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd, -				   const u8 *data, int len) +static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, +				   const u8 *data, int len, int buswidth)  {  	int i, data_len; +	u8 cmd; + +	switch (buswidth) { +	case 0: +	case 1: +		cmd = SNAND_FIFO_TX_BUSWIDTH_SINGLE; +		break; +	case 2: +		cmd = SNAND_FIFO_TX_BUSWIDTH_DUAL; +		break; +	case 4: +		cmd = SNAND_FIFO_TX_BUSWIDTH_QUAD; +		break; +	default: +		return -EINVAL; +	}  	for (i = 0; i < len; i += data_len) {  		int err; @@ -409,16 +433,32 @@ static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd,  	return 0;  } -static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl, u8 *data, -				  int len) +static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl, +				  u8 *data, int len, int buswidth)  {  	int i, data_len; +	u8 cmd; + +	switch (buswidth) { +	case 0: +	case 1: +		cmd = SNAND_FIFO_RX_BUSWIDTH_SINGLE; +		break; +	case 2: +		cmd = SNAND_FIFO_RX_BUSWIDTH_DUAL; +		break; +	case 4: +		cmd = SNAND_FIFO_RX_BUSWIDTH_QUAD; +		break; +	default: +		return -EINVAL; +	}  	for (i = 0; i < len; i += data_len) {  		int err;  		data_len = min(len - i, SPI_MAX_TRANSFER_SIZE); -		err = airoha_snand_set_fifo_op(as_ctrl, 0xc, data_len); +		err = airoha_snand_set_fifo_op(as_ctrl, cmd, data_len);  		if (err)  			return err; @@ -618,6 +658,10 @@ static int airoha_snand_dirmap_create(struct spi_mem_dirmap_desc *desc)  	if (desc->info.offset + desc->info.length > U32_MAX)  		return -EINVAL; +	/* continuous reading is not supported */ +	if (desc->info.length > SPI_NAND_CACHE_SIZE) +		return -E2BIG; +  	if (!airoha_snand_supports_op(desc->mem, &desc->info.op_tmpl))  		return -EOPNOTSUPP; @@ -654,13 +698,13 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,  	err = airoha_snand_nfi_config(as_ctrl);  	if (err) -		return err; +		goto error_dma_mode_off;  	dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,  				  DMA_FROM_DEVICE);  	err = dma_mapping_error(as_ctrl->dev, dma_addr);  	if (err) -		return err; +		goto error_dma_mode_off;  	/* set dma addr */  	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR, @@ -689,8 +733,9 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,  	if (err)  		goto error_dma_unmap; -	/* set read addr */ -	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL3, 0x0); +	/* set read addr: zero page offset + descriptor read offset */ +	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL3, +			   desc->info.offset);  	if (err)  		goto error_dma_unmap; @@ -760,6 +805,8 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,  error_dma_unmap:  	dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,  			 DMA_FROM_DEVICE); +error_dma_mode_off: +	airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);  	return err;  } @@ -824,7 +871,9 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,  	if (err)  		goto error_dma_unmap; -	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL2, 0x0); +	/* set write addr: zero page offset + descriptor write offset */ +	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL2, +			   desc->info.offset);  	if (err)  		goto error_dma_unmap; @@ -892,18 +941,35 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,  error_dma_unmap:  	dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,  			 DMA_TO_DEVICE); +	airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);  	return err;  }  static int airoha_snand_exec_op(struct spi_mem *mem,  				const struct spi_mem_op *op)  { -	u8 data[8], cmd, opcode = op->cmd.opcode;  	struct airoha_snand_ctrl *as_ctrl; +	int op_len, addr_len, dummy_len; +	u8 buf[20], *data;  	int i, err;  	as_ctrl = spi_controller_get_devdata(mem->spi->controller); +	op_len = op->cmd.nbytes; +	addr_len = op->addr.nbytes; +	dummy_len = op->dummy.nbytes; + +	if (op_len + dummy_len + addr_len > sizeof(buf)) +		return -EIO; + +	data = buf; +	for (i = 0; i < op_len; i++) +		*data++ = op->cmd.opcode >> (8 * (op_len - i - 1)); +	for (i = 0; i < addr_len; i++) +		*data++ = op->addr.val >> (8 * (addr_len - i - 1)); +	for (i = 0; i < dummy_len; i++) +		*data++ = 0xff; +  	/* switch to manual mode */  	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);  	if (err < 0) @@ -914,40 +980,40 @@ static int airoha_snand_exec_op(struct spi_mem *mem,  		return err;  	/* opcode */ -	err = airoha_snand_write_data(as_ctrl, 0x8, &opcode, sizeof(opcode)); +	data = buf; +	err = airoha_snand_write_data(as_ctrl, data, op_len, +				      op->cmd.buswidth);  	if (err)  		return err;  	/* addr part */ -	cmd = opcode == SPI_NAND_OP_GET_FEATURE ? 0x11 : 0x8; -	put_unaligned_be64(op->addr.val, data); - -	for (i = ARRAY_SIZE(data) - op->addr.nbytes; -	     i < ARRAY_SIZE(data); i++) { -		err = airoha_snand_write_data(as_ctrl, cmd, &data[i], -					      sizeof(data[0])); +	data += op_len; +	if (addr_len) { +		err = airoha_snand_write_data(as_ctrl, data, addr_len, +					      op->addr.buswidth);  		if (err)  			return err;  	}  	/* dummy */ -	data[0] = 0xff; -	for (i = 0; i < op->dummy.nbytes; i++) { -		err = airoha_snand_write_data(as_ctrl, 0x8, &data[0], -					      sizeof(data[0])); +	data += addr_len; +	if (dummy_len) { +		err = airoha_snand_write_data(as_ctrl, data, dummy_len, +					      op->dummy.buswidth);  		if (err)  			return err;  	}  	/* data */ -	if (op->data.dir == SPI_MEM_DATA_IN) { -		err = airoha_snand_read_data(as_ctrl, op->data.buf.in, -					     op->data.nbytes); -		if (err) -			return err; -	} else { -		err = airoha_snand_write_data(as_ctrl, 0x8, op->data.buf.out, -					      op->data.nbytes); +	if (op->data.nbytes) { +		if (op->data.dir == SPI_MEM_DATA_IN) +			err = airoha_snand_read_data(as_ctrl, op->data.buf.in, +						     op->data.nbytes, +						     op->data.buswidth); +		else +			err = airoha_snand_write_data(as_ctrl, op->data.buf.out, +						      op->data.nbytes, +						      op->data.buswidth);  		if (err)  			return err;  	} diff --git a/drivers/spi/spi-amlogic-spifc-a4.c b/drivers/spi/spi-amlogic-spifc-a4.c index 4338d00e56a6..35a7c4965e11 100644 --- a/drivers/spi/spi-amlogic-spifc-a4.c +++ b/drivers/spi/spi-amlogic-spifc-a4.c @@ -286,7 +286,7 @@ static int aml_sfc_set_bus_width(struct aml_sfc *sfc, u8 buswidth, u32 mask)  	for (i = 0; i <= LANE_MAX; i++) {  		if (buswidth == 1 << i) { -			conf = i << __bf_shf(mask); +			conf = i << __ffs(mask);  			return regmap_update_bits(sfc->regmap_base, SFC_SPI_CFG,  						  mask, conf);  		} @@ -566,7 +566,7 @@ static int aml_sfc_raw_io_op(struct aml_sfc *sfc, const struct spi_mem_op *op)  	if (!op->data.nbytes)  		goto end_xfer; -	conf = (op->data.nbytes >> RAW_SIZE_BW) << __bf_shf(RAW_EXT_SIZE); +	conf = (op->data.nbytes >> RAW_SIZE_BW) << __ffs(RAW_EXT_SIZE);  	ret = regmap_update_bits(sfc->regmap_base, SFC_SPI_CFG, RAW_EXT_SIZE, conf);  	if (ret)  		goto err_out; diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index 8fb13df8ff87..81017402bc56 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -1995,7 +1995,7 @@ static int cqspi_probe(struct platform_device *pdev)  	if (cqspi->use_direct_mode) {  		ret = cqspi_request_mmap_dma(cqspi);  		if (ret == -EPROBE_DEFER) -			goto probe_setup_failed; +			goto probe_dma_failed;  	}  	if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) { @@ -2019,9 +2019,10 @@ static int cqspi_probe(struct platform_device *pdev)  	return 0;  probe_setup_failed: -	cqspi_controller_enable(cqspi, 0);  	if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM)))  		pm_runtime_disable(dev); +probe_dma_failed: +	cqspi_controller_enable(cqspi, 0);  probe_reset_failed:  	if (cqspi->is_jh7110)  		cqspi_jh7110_disable_clk(pdev, cqspi); diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index f0f576fac77a..7a5197586919 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -358,7 +358,9 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)  	if (IS_ERR(dwsmmio->rstc))  		return PTR_ERR(dwsmmio->rstc); -	reset_control_deassert(dwsmmio->rstc); +	ret = reset_control_deassert(dwsmmio->rstc); +	if (ret) +		return dev_err_probe(&pdev->dev, ret, "Failed to deassert resets\n");  	dws->bus_num = pdev->id; diff --git a/drivers/spi/spi-intel-pci.c b/drivers/spi/spi-intel-pci.c index 4b63cb98df9c..7765fb27c37c 100644 --- a/drivers/spi/spi-intel-pci.c +++ b/drivers/spi/spi-intel-pci.c @@ -75,10 +75,12 @@ static const struct pci_device_id intel_spi_pci_ids[] = {  	{ PCI_VDEVICE(INTEL, 0x38a4), (unsigned long)&bxt_info },  	{ PCI_VDEVICE(INTEL, 0x43a4), (unsigned long)&cnl_info },  	{ PCI_VDEVICE(INTEL, 0x4b24), (unsigned long)&bxt_info }, +	{ PCI_VDEVICE(INTEL, 0x4d23), (unsigned long)&cnl_info },  	{ PCI_VDEVICE(INTEL, 0x4da4), (unsigned long)&bxt_info },  	{ PCI_VDEVICE(INTEL, 0x51a4), (unsigned long)&cnl_info },  	{ PCI_VDEVICE(INTEL, 0x54a4), (unsigned long)&cnl_info },  	{ PCI_VDEVICE(INTEL, 0x5794), (unsigned long)&cnl_info }, +	{ PCI_VDEVICE(INTEL, 0x7723), (unsigned long)&cnl_info },  	{ PCI_VDEVICE(INTEL, 0x7a24), (unsigned long)&cnl_info },  	{ PCI_VDEVICE(INTEL, 0x7aa4), (unsigned long)&cnl_info },  	{ PCI_VDEVICE(INTEL, 0x7e23), (unsigned long)&cnl_info }, diff --git a/drivers/spi/spi-intel.c b/drivers/spi/spi-intel.c index 13bbb2133507..1775ad39e633 100644 --- a/drivers/spi/spi-intel.c +++ b/drivers/spi/spi-intel.c @@ -132,6 +132,7 @@  #define FLCOMP_C0DEN_16M		0x05  #define FLCOMP_C0DEN_32M		0x06  #define FLCOMP_C0DEN_64M		0x07 +#define FLCOMP_C0DEN_128M		0x08  #define INTEL_SPI_TIMEOUT		5000 /* ms */  #define INTEL_SPI_FIFO_SZ		64 @@ -1347,7 +1348,12 @@ static int intel_spi_read_desc(struct intel_spi *ispi)  	case FLCOMP_C0DEN_64M:  		ispi->chip0_size = SZ_64M;  		break; +	case FLCOMP_C0DEN_128M: +		ispi->chip0_size = SZ_128M; +		break;  	default: +		dev_warn(ispi->dev, "unsupported C0DEN: %#lx\n", +			 flcomp & FLCOMP_C0DEN_MASK);  		return -EINVAL;  	} diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c index f9371f98a65b..b6c79e50d842 100644 --- a/drivers/spi/spi-nxp-fspi.c +++ b/drivers/spi/spi-nxp-fspi.c @@ -404,6 +404,10 @@ struct nxp_fspi {  #define FSPI_NEED_INIT		BIT(0)  #define FSPI_DTR_MODE		BIT(1)  	int flags; +	/* save the previous operation clock rate */ +	unsigned long pre_op_rate; +	/* the max clock rate fspi output to device */ +	unsigned long max_rate;  };  static inline int needs_ip_only(struct nxp_fspi *f) @@ -685,10 +689,13 @@ static void nxp_fspi_select_rx_sample_clk_source(struct nxp_fspi *f,  	 * change the mode back to mode 0.  	 */  	reg = fspi_readl(f, f->iobase + FSPI_MCR0); -	if (op_is_dtr) +	if (op_is_dtr) {  		reg |= FSPI_MCR0_RXCLKSRC(3); -	else	/*select mode 0 */ +		f->max_rate = 166000000; +	} else {	/*select mode 0 */  		reg &= ~FSPI_MCR0_RXCLKSRC(3); +		f->max_rate = 66000000; +	}  	fspi_writel(f, reg, f->iobase + FSPI_MCR0);  } @@ -719,6 +726,12 @@ static void nxp_fspi_dll_calibration(struct nxp_fspi *f)  				   0, POLL_TOUT, true);  	if (ret)  		dev_warn(f->dev, "DLL lock failed, please fix it!\n"); + +	/* +	 * For ERR050272, DLL lock status bit is not accurate, +	 * wait for 4us more as a workaround. +	 */ +	udelay(4);  }  /* @@ -780,11 +793,17 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,  	uint64_t size_kb;  	/* -	 * Return, if previously selected target device is same as current -	 * requested target device. Also the DTR or STR mode do not change. +	 * Return when following condition all meet, +	 * 1, if previously selected target device is same as current +	 *    requested target device. +	 * 2, the DTR or STR mode do not change. +	 * 3, previous operation max rate equals current one. +	 * +	 * For other case, need to re-config.  	 */  	if ((f->selected == spi_get_chipselect(spi, 0)) && -	    (!!(f->flags & FSPI_DTR_MODE) == op_is_dtr)) +	    (!!(f->flags & FSPI_DTR_MODE) == op_is_dtr) && +	    (f->pre_op_rate == op->max_freq))  		return;  	/* Reset FLSHxxCR0 registers */ @@ -802,6 +821,7 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,  	dev_dbg(f->dev, "Target device [CS:%x] selected\n", spi_get_chipselect(spi, 0));  	nxp_fspi_select_rx_sample_clk_source(f, op_is_dtr); +	rate = min(f->max_rate, op->max_freq);  	if (op_is_dtr) {  		f->flags |= FSPI_DTR_MODE; @@ -832,6 +852,8 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,  	else  		nxp_fspi_dll_override(f); +	f->pre_op_rate = op->max_freq; +  	f->selected = spi_get_chipselect(spi, 0);  } diff --git a/drivers/spi/spi-rockchip-sfc.c b/drivers/spi/spi-rockchip-sfc.c index 9eba5c0a60f2..b3c2b03b1153 100644 --- a/drivers/spi/spi-rockchip-sfc.c +++ b/drivers/spi/spi-rockchip-sfc.c @@ -704,7 +704,12 @@ static int rockchip_sfc_probe(struct platform_device *pdev)  			ret = -ENOMEM;  			goto err_dma;  		} -		sfc->dma_buffer = virt_to_phys(sfc->buffer); +		sfc->dma_buffer = dma_map_single(dev, sfc->buffer, +					    sfc->max_iosize, DMA_BIDIRECTIONAL); +		if (dma_mapping_error(dev, sfc->dma_buffer)) { +			ret = -ENOMEM; +			goto err_dma_map; +		}  	}  	ret = devm_spi_register_controller(dev, host); @@ -715,6 +720,9 @@ static int rockchip_sfc_probe(struct platform_device *pdev)  	return 0;  err_register: +	dma_unmap_single(dev, sfc->dma_buffer, sfc->max_iosize, +			 DMA_BIDIRECTIONAL); +err_dma_map:  	free_pages((unsigned long)sfc->buffer, get_order(sfc->max_iosize));  err_dma:  	pm_runtime_get_sync(dev); @@ -736,6 +744,8 @@ static void rockchip_sfc_remove(struct platform_device *pdev)  	struct spi_controller *host = sfc->host;  	spi_unregister_controller(host); +	dma_unmap_single(&pdev->dev, sfc->dma_buffer, sfc->max_iosize, +			 DMA_BIDIRECTIONAL);  	free_pages((unsigned long)sfc->buffer, get_order(sfc->max_iosize));  	clk_disable_unprepare(sfc->clk); | 
