spi: cadence_qspi: Enable apb linear mode for apb read & write operations
On versal platform, enable apb linear mode for apb read and write execute operations amd disable it when using dma reads. This is done by xilinx_pm_request() secure calls when CONFIG_ZYNQMP_FIRMWARE is enabled, else we use direct raw reads and writes in case of mini U-Boot. Signed-off-by: T Karthik Reddy <t.karthik.reddy@xilinx.com> Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com> Link: https://lore.kernel.org/r/20220512100535.16364-5-ashok.reddy.soma@xilinx.com Signed-off-by: Michal Simek <michal.simek@amd.com>
This commit is contained in:
		
							parent
							
								
									bf8dae5fcf
								
							
						
					
					
						commit
						248fe9f302
					
				|  | @ -58,6 +58,10 @@ struct rpu_regs { | ||||||
| 
 | 
 | ||||||
| #define VERSAL_CRP_BASEADDR	0xF1260000 | #define VERSAL_CRP_BASEADDR	0xF1260000 | ||||||
| 
 | 
 | ||||||
|  | #define VERSAL_SLCR_BASEADDR	0xF1060000 | ||||||
|  | #define VERSAL_AXI_MUX_SEL	(VERSAL_SLCR_BASEADDR + 0x504) | ||||||
|  | #define VERSAL_OSPI_LINEAR_MODE	BIT(1) | ||||||
|  | 
 | ||||||
| struct crp_regs { | struct crp_regs { | ||||||
| 	u32 reserved0[128]; | 	u32 reserved0[128]; | ||||||
| 	u32 boot_mode_usr; | 	u32 boot_mode_usr; | ||||||
|  |  | ||||||
|  | @ -33,6 +33,7 @@ int cadence_qspi_apb_dma_read(struct cadence_spi_plat *plat, | ||||||
| 	bytes_to_dma = n_rx - rx_rem; | 	bytes_to_dma = n_rx - rx_rem; | ||||||
| 
 | 
 | ||||||
| 	if (bytes_to_dma) { | 	if (bytes_to_dma) { | ||||||
|  | 		cadence_qspi_apb_enable_linear_mode(false); | ||||||
| 		reg = readl(plat->regbase + CQSPI_REG_CONFIG); | 		reg = readl(plat->regbase + CQSPI_REG_CONFIG); | ||||||
| 		reg |= CQSPI_REG_CONFIG_ENBL_DMA; | 		reg |= CQSPI_REG_CONFIG_ENBL_DMA; | ||||||
| 		writel(reg, plat->regbase + CQSPI_REG_CONFIG); | 		writel(reg, plat->regbase + CQSPI_REG_CONFIG); | ||||||
|  | @ -211,3 +212,26 @@ int cadence_spi_versal_flash_reset(struct udevice *dev) | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  | 
 | ||||||
|  | void cadence_qspi_apb_enable_linear_mode(bool enable) | ||||||
|  | { | ||||||
|  | 	if (CONFIG_IS_ENABLED(ZYNQMP_FIRMWARE)) { | ||||||
|  | 		if (enable) | ||||||
|  | 			/* ahb read mode */ | ||||||
|  | 			xilinx_pm_request(PM_IOCTL, PM_DEV_OSPI, | ||||||
|  | 					  IOCTL_OSPI_MUX_SELECT, | ||||||
|  | 					  PM_OSPI_MUX_SEL_LINEAR, 0, NULL); | ||||||
|  | 		else | ||||||
|  | 			/* DMA mode */ | ||||||
|  | 			xilinx_pm_request(PM_IOCTL, PM_DEV_OSPI, | ||||||
|  | 					  IOCTL_OSPI_MUX_SELECT, | ||||||
|  | 					  PM_OSPI_MUX_SEL_DMA, 0, NULL); | ||||||
|  | 	} else { | ||||||
|  | 		if (enable) | ||||||
|  | 			writel(readl(VERSAL_AXI_MUX_SEL) | | ||||||
|  | 			       VERSAL_OSPI_LINEAR_MODE, VERSAL_AXI_MUX_SEL); | ||||||
|  | 		else | ||||||
|  | 			writel(readl(VERSAL_AXI_MUX_SEL) & | ||||||
|  | 			       ~VERSAL_OSPI_LINEAR_MODE, VERSAL_AXI_MUX_SEL); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -18,7 +18,9 @@ | ||||||
| #include <linux/err.h> | #include <linux/err.h> | ||||||
| #include <linux/errno.h> | #include <linux/errno.h> | ||||||
| #include <linux/sizes.h> | #include <linux/sizes.h> | ||||||
|  | #include <zynqmp_firmware.h> | ||||||
| #include "cadence_qspi.h" | #include "cadence_qspi.h" | ||||||
|  | #include <dt-bindings/power/xlnx-versal-power.h> | ||||||
| 
 | 
 | ||||||
| #define NSEC_PER_SEC			1000000000L | #define NSEC_PER_SEC			1000000000L | ||||||
| 
 | 
 | ||||||
|  | @ -196,6 +198,11 @@ static int cadence_spi_probe(struct udevice *bus) | ||||||
| 	priv->regbase = plat->regbase; | 	priv->regbase = plat->regbase; | ||||||
| 	priv->ahbbase = plat->ahbbase; | 	priv->ahbbase = plat->ahbbase; | ||||||
| 
 | 
 | ||||||
|  | 	if (CONFIG_IS_ENABLED(ZYNQMP_FIRMWARE)) | ||||||
|  | 		xilinx_pm_request(PM_REQUEST_NODE, PM_DEV_OSPI, | ||||||
|  | 				  ZYNQMP_PM_CAPABILITY_ACCESS, ZYNQMP_PM_MAX_QOS, | ||||||
|  | 				  ZYNQMP_PM_REQUEST_ACK_NO, NULL); | ||||||
|  | 
 | ||||||
| 	if (plat->ref_clk_hz == 0) { | 	if (plat->ref_clk_hz == 0) { | ||||||
| 		ret = clk_get_by_index(bus, 0, &clk); | 		ret = clk_get_by_index(bus, 0, &clk); | ||||||
| 		if (ret) { | 		if (ret) { | ||||||
|  |  | ||||||
|  | @ -284,5 +284,6 @@ int cadence_qspi_apb_dma_read(struct cadence_spi_plat *plat, | ||||||
| int cadence_qspi_apb_wait_for_dma_cmplt(struct cadence_spi_plat *plat); | int cadence_qspi_apb_wait_for_dma_cmplt(struct cadence_spi_plat *plat); | ||||||
| int cadence_qspi_apb_exec_flash_cmd(void *reg_base, unsigned int reg); | int cadence_qspi_apb_exec_flash_cmd(void *reg_base, unsigned int reg); | ||||||
| int cadence_qspi_versal_flash_reset(struct udevice *dev); | int cadence_qspi_versal_flash_reset(struct udevice *dev); | ||||||
|  | void cadence_qspi_apb_enable_linear_mode(bool enable); | ||||||
| 
 | 
 | ||||||
| #endif /* __CADENCE_QSPI_H__ */ | #endif /* __CADENCE_QSPI_H__ */ | ||||||
|  |  | ||||||
|  | @ -38,6 +38,11 @@ | ||||||
| #include <malloc.h> | #include <malloc.h> | ||||||
| #include "cadence_qspi.h" | #include "cadence_qspi.h" | ||||||
| 
 | 
 | ||||||
|  | __weak void cadence_qspi_apb_enable_linear_mode(bool enable) | ||||||
|  | { | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void cadence_qspi_apb_controller_enable(void *reg_base) | void cadence_qspi_apb_controller_enable(void *reg_base) | ||||||
| { | { | ||||||
| 	unsigned int reg; | 	unsigned int reg; | ||||||
|  | @ -730,6 +735,9 @@ int cadence_qspi_apb_read_execute(struct cadence_spi_plat *plat, | ||||||
| 	void *buf = op->data.buf.in; | 	void *buf = op->data.buf.in; | ||||||
| 	size_t len = op->data.nbytes; | 	size_t len = op->data.nbytes; | ||||||
| 
 | 
 | ||||||
|  | 	if (CONFIG_IS_ENABLED(ARCH_VERSAL)) | ||||||
|  | 		cadence_qspi_apb_enable_linear_mode(true); | ||||||
|  | 
 | ||||||
| 	if (plat->use_dac_mode && (from + len < plat->ahbsize)) { | 	if (plat->use_dac_mode && (from + len < plat->ahbsize)) { | ||||||
| 		if (len < 256 || | 		if (len < 256 || | ||||||
| 		    dma_memcpy(buf, plat->ahbbase + from, len) < 0) { | 		    dma_memcpy(buf, plat->ahbbase + from, len) < 0) { | ||||||
|  | @ -897,6 +905,9 @@ int cadence_qspi_apb_write_execute(struct cadence_spi_plat *plat, | ||||||
| 	const void *buf = op->data.buf.out; | 	const void *buf = op->data.buf.out; | ||||||
| 	size_t len = op->data.nbytes; | 	size_t len = op->data.nbytes; | ||||||
| 
 | 
 | ||||||
|  | 	if (CONFIG_IS_ENABLED(ARCH_VERSAL)) | ||||||
|  | 		cadence_qspi_apb_enable_linear_mode(true); | ||||||
|  | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * Some flashes like the Cypress Semper flash expect a dummy 4-byte | 	 * Some flashes like the Cypress Semper flash expect a dummy 4-byte | ||||||
| 	 * address (all 0s) with the read status register command in DTR mode. | 	 * address (all 0s) with the read status register command in DTR mode. | ||||||
|  |  | ||||||
|  | @ -160,6 +160,12 @@ enum dll_reset_type { | ||||||
| 	PM_DLL_RESET_PULSE = 2, | 	PM_DLL_RESET_PULSE = 2, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | enum ospi_mux_select_type { | ||||||
|  | 	PM_OSPI_MUX_SEL_DMA, | ||||||
|  | 	PM_OSPI_MUX_SEL_LINEAR, | ||||||
|  | 	PM_OSPI_MUX_GET_MODE, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| enum pm_query_id { | enum pm_query_id { | ||||||
| 	PM_QID_INVALID = 0, | 	PM_QID_INVALID = 0, | ||||||
| 	PM_QID_CLOCK_GET_NAME = 1, | 	PM_QID_CLOCK_GET_NAME = 1, | ||||||
|  | @ -427,6 +433,7 @@ enum pm_gem_config_type { | ||||||
| #define ZYNQMP_PM_VERSION_INVALID	~0 | #define ZYNQMP_PM_VERSION_INVALID	~0 | ||||||
| 
 | 
 | ||||||
| #define PMUFW_V1_0	((1 << ZYNQMP_PM_VERSION_MAJOR_SHIFT) | 0) | #define PMUFW_V1_0	((1 << ZYNQMP_PM_VERSION_MAJOR_SHIFT) | 0) | ||||||
|  | #define PMIO_NODE_ID_BASE		0x1410801B | ||||||
| 
 | 
 | ||||||
| #define PMIO_NODE_ID_BASE		0x1410801B | #define PMIO_NODE_ID_BASE		0x1410801B | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue