Re: [RFC 0/5] rockchip_sfc: add support for Rockchip SFC
On 6/4/21 10:40 PM, Chris Morgan wrote: On Fri, Jun 04, 2021 at 09:42:18PM +0800, 林鼎强 wrote: Hi Chris: It's my honor to read about spi-rockchip-sfc driver from you, and your code has made a big difference to me. Recently, we happen to be willing to submit the spi-mem rk sfc drivers, and we have tried some of them in the internal process. Compared with the RK internal code, I have the following thoughts on your code: 1) Only support spi-nor, not support spi-nand 2) Only support rx_dual, tx_quad, not support tx_dual, tx_quad 3) Some of the code may be further simplified, such as "rockchip_sfc_register_all" 4) Some of the logic may be further simplified, such as "rockchip_sfc_init" 5) Doesn't support SFC ver4 ver5 althought witch is compatibled with lower version In order to support all these features, I adjust the drivers on the basis of your code witch is attach to these mail, these drivers have been test in linux 5.10 rk3568 board, and I'm still doing more strict tests. So I suggest that we complete it together, or we may consider transferring it to me for submission If I have the honor. I'm still unfamiliar with the community culture. I hope I didn't offend you. If I have, I'll say sorry in advance. Best wishes. I am absolutely fine with you taking this on, and will be happy to help you in any way I can. I only started working on support for this because I wanted it supported in both Linux and U-Boot mainline, and didn't see any progress being made (so I thought I would do it myself). Basically, my goal all along has been to ensure the Odroid Go Advance is fully supported in mainline Linux (and U-boot), and that requires we get the audio (done), SFC (in progress), crypto, battery, charger, and everything else (done) supported. I trust you are better able to develop/test this than I am, as I only have access to some technical documents and a single PX30 based device to test this on. Please CC me when you are ready to submit upstream to Linux and U-boot and I will happily test it on my hardware. If you don't have a U-boot driver in progress let me know and I can start working on one. Thank you. I'm glad to receive your reply and your understanding so soon. I'll talk about my plan directly. If there is no obvious objection,I'll go on with it. Firstly, I will submit the support for the my first version of Linux drivers next week which is base on your series submission. After browsing your submission, there will be the following changes: 1) [RFC,v4,1/8] change with the "Rob Herring" comment 2) [RFC,v4,2/8] update driver 3) All dt patches, make a little change to compatible with RK SDK [RFC,v4,8/8] arm64: dts: rockchip: Enable SFC for Odroid Go Advance [RFC,v4,7/8] arm64: dts: rockchip: Add SFC to RK3308 [RFC,v4,6/8] arm: dts: rockchip: Add SFC to RV1108 [RFC,v4,5/8] arm: dts: rockchip: Add SFC to RK3036 [RFC,v4,4/8] clk: rockchip: Add support for hclk_sfc on rk3036 [RFC,v4,3/8] arm64: dts: rockchip: Add SFC to PX30 [RFC,v4,2/8] spi: rockchip-sfc: add rockchip serial flash controller [RFC,v4,1/8] dt-bindings: rockchip-sfc: Bindings for Rockchip serial flash controller Secondly, Keep devolop uboot drivers base on your serieas submission https://patchwork.ozlabs.org/project/uboot/list//?series=245724 submit the code under uboot as soon as possible. Finally I'll keep focus on the new comments about all these linux patches,then fix it until they are merged. Best wishes. jon@rock-chips.com From: Kever Yang Date: 2021-06-02 09:27 To: Chris Morgan CC: u-boot; heiko.stuebner; vigneshr; jagan; sjg; Chris Morgan; 赵仪峰; 林鼎强 Subject: Re: [RFC 0/5] rockchip_sfc: add support for Rockchip SFC Hi Chris, On 2021/6/2 上午12:54, Chris Morgan wrote: On Tue, Jun 01, 2021 at 08:22:09PM +0800, Kever Yang wrote: Add Yifeng from rockchip. Hi Chris, First of all, I think you should remain the origin author info in the signed-off. Okay, I can do that. Please note that since I submitted this I was asked to redo the upstream linux proposed driver to use the spi-mem framework. I think for now honestly I'd like to abandon this patch and resubmit a little later with one that is more or less the same (using the spi-mem framework) as the Linux driver. This sounds better, then we can wait for driver with new framework. Thanks, - Kever https://patchwork.ozlabs.org/project/linux-mtd/patch/20210528170020.26219-2-macroalph...@gmail.com/ Hi Yifeng, Please help to review this driver. Thanks, - Kever On 2021/5/26 上午5:49, Chris Morgan wrote: From: Chris Morgan Requesting comments for a proposed patchset for adding the Rockchip serial flash controller to u-boot. The goal of these patches is to enable it for the Odroid Go Advance so that it may eventually boot exclusively from the SFC on mainline U-boot (I have tested this and it works). The specific help I need with this patch is: 1) I don't know the best way to upstream the XTX25F128B flash chip. This
[PATCH v6 4/5] mtd: spi-nor-ids: Add XTX XT25F128B
From: Chris Morgan Adds support for XT25F128B used on Odroid Go Advance. Unfortunately this chip uses a continuation code which I cannot seem to parse, so there are possibly going to be collisions with chips that use the same manufacturer/ID. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- (no changes since v1) drivers/mtd/spi/Kconfig | 6 ++ drivers/mtd/spi/spi-nor-ids.c | 8 2 files changed, 14 insertions(+) diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig index f8db8e5213..8c797d1e03 100644 --- a/drivers/mtd/spi/Kconfig +++ b/drivers/mtd/spi/Kconfig @@ -162,6 +162,12 @@ config SPI_FLASH_XMC Add support for various XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) SPI flash chips (XM25xxx) +config SPI_FLASH_XTX + bool "XTX SPI flash support" + help + Add support for various XTX (XTX Technology Limited) + SPI flash chips (XT25xxx). + endif config SPI_FLASH_USE_4K_SECTORS diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c index 2b57797954..bdecb3b837 100644 --- a/drivers/mtd/spi/spi-nor-ids.c +++ b/drivers/mtd/spi/spi-nor-ids.c @@ -336,6 +336,14 @@ const struct flash_info spi_nor_ids[] = { /* XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) */ { INFO("XM25QH64A", 0x207017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { INFO("XM25QH128A", 0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, +#endif +#ifdef CONFIG_SPI_FLASH_XTX + /* XTX Technology (Shenzhen) Limited */ + { + INFO("xt25f128b", 0x0b4018, 0, 64 * 1024, 256, +SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | +SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, #endif { }, }; -- 2.17.1
[PATCH v6 5/5] rockchip: px30: add support for SFC for Odroid Go Advance
From: Chris Morgan The Odroid Go Advance uses a Rockchip Serial Flash Controller with an XT25F128B SPI NOR flash chip. This adds support for both. Note that while both the controller and chip support quad mode, only two lines are connected to the chip. Changing the pinctrl to bus2 and setting tx and rx lines to 2 for this reason. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- (no changes since v1) arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi | 17 + arch/arm/dts/rk3326-odroid-go2.dts | 16 2 files changed, 33 insertions(+) diff --git a/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi b/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi index 00767d2abd..741e8dd935 100644 --- a/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi +++ b/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi @@ -7,6 +7,15 @@ chosen { u-boot,spl-boot-order = }; + + aliases { + i2c0 = + i2c1 = + mmc0 = + serial1 = + serial2 = + spi0 = + }; }; { @@ -57,6 +66,14 @@ u-boot,spl-fifo-mode; }; + { + u-boot,dm-pre-reloc; +}; + +_flash { + u-boot,dm-pre-reloc; +}; + { clock-frequency = <2400>; u-boot,dm-pre-reloc; diff --git a/arch/arm/dts/rk3326-odroid-go2.dts b/arch/arm/dts/rk3326-odroid-go2.dts index 8cd4688c49..6f91f5040b 100644 --- a/arch/arm/dts/rk3326-odroid-go2.dts +++ b/arch/arm/dts/rk3326-odroid-go2.dts @@ -617,6 +617,22 @@ status = "okay"; }; + { + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <_clk _cs _bus2>; + status = "okay"; + + spi_flash: xt25f128b@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10800>; + spi-rx-bus-width = <2>; + spi-tx-bus-width = <2>; + }; +}; + { status = "okay"; }; -- 2.17.1
[PATCH v6 1/5] spi: rockchip_sfc: add support for Rockchip SFC
From: Chris Morgan This patch adds support for the Rockchip serial flash controller found on the PX30 SoC. It should work for versions 3-5 of the SFC IP, however I am only able to test it on v3. This is adapted from the WIP SPI-MEM driver for the SFC on mainline Linux. Note that the main difference between this and earlier versions of the driver is that this one does not support DMA. In testing the performance difference (performing a dual mode read on a 128Mb chip) is negligible. DMA, if used, must also be disabled in SPL mode when using A-TF anyway. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- Changes in v6: - Fix dma transfer logic - Fix the error of the way to wait for dma transfer finished status Changes in v5: - Support dma transfer - Add CONFIG_IS_ENABLED(CLK) limitation - Support spinand devices - Support SFC ver4 ver5 - Using "rockchip, sfc" as compatible id - Get clock from the index to compatible with those case which's clock-names is not parsed Changes in v4: - None Changes in v3: - Added "rockchip_sfc_adjust_op_work()" function from proposed Linux driver to fix potential issue on hardware. Note I never noticed this issue while testing, so I cannot test if it fixed any specific issue for me. - Updated of-compatible string back to "rockchip,sfc" to match what is currently proposed for upstream driver. The hardware itself has multiple versions but a register is present in the hardware that is read by the driver to set version specific functionality. - Updated px30.dtsi and rk3266-odroid-go2.dts device-trees so that sfc nodes match what is in upstream. Changes in v2: - Resending due to glitch with patch file truncating final two lines on patch 1/5 and incorrect patch version number on patch 5/5. Changes in v1: - Reworked code to utilize spi-mem framework, and based it closely off of work in progress code for mainline Linux. - Removed DMA, as it didn't offer much performance benefit for booting (in my test cases), added complexity to the code, and interfered with A-TF. - Updated the names of the bindings to match the work in progress Linux code. - Moved alias to u-boot specific device-tree for Odroid Go Advance. Alias is updated with the spi0 node pointing to the SFC to help the sf command as well as facilitate booting from the SFC. - Note 2 below no longer applies, as rebasing this off of upstream code should allow the device to work for NAND, and by utilizing the spi-mem framework it no longer has to extract the parameters drivers/spi/Kconfig| 8 + drivers/spi/Makefile | 1 + drivers/spi/rockchip_sfc.c | 643 + 3 files changed, 652 insertions(+) create mode 100644 drivers/spi/rockchip_sfc.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 1494c91763..bef36f2931 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -312,6 +312,14 @@ config RENESAS_RPC_SPI on Renesas RCar Gen3 SoCs. This uses driver model and requires a device tree binding to operate. +config ROCKCHIP_SFC + bool "Rockchip SFC Driver" + help + Enable the Rockchip SFC Driver for SPI NOR flash. This device is + a limited purpose SPI controller for driving NOR flash on certain + Rockchip SoCs. This uses driver model and requires a device tree + binding to operate. + config ROCKCHIP_SPI bool "Rockchip SPI driver" help diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index cfe4fae1d4..f02e84b5f1 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -52,6 +52,7 @@ obj-$(CONFIG_PIC32_SPI) += pic32_spi.o obj-$(CONFIG_PL022_SPI) += pl022_spi.o obj-$(CONFIG_SPI_QUP) += spi-qup.o obj-$(CONFIG_RENESAS_RPC_SPI) += renesas_rpc_spi.o +obj-$(CONFIG_ROCKCHIP_SFC) += rockchip_sfc.o obj-$(CONFIG_ROCKCHIP_SPI) += rk_spi.o obj-$(CONFIG_SANDBOX_SPI) += sandbox_spi.o obj-$(CONFIG_SPI_SIFIVE) += spi-sifive.o diff --git a/drivers/spi/rockchip_sfc.c b/drivers/spi/rockchip_sfc.c new file mode 100644 index 00..2d86f136f2 --- /dev/null +++ b/drivers/spi/rockchip_sfc.c @@ -0,0 +1,643 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Rockchip Serial Flash Controller Driver + * + * Copyright (c) 2017-2021, Rockchip Inc. + * Author: Shawn Lin + *Chris Morgan + *Jon Lin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* System control */ +#define SFC_CTRL 0x0 +#define SFC_CTRL_PHASE_SEL_NEGETIVE BIT(1) +#define SFC_CTRL_CMD_BITS_SHIFT 8 +#define SFC_CTRL_ADDR_BITS_SHIFT 10 +#define SFC_CTRL_DATA_BITS_SHIFT 12 + +/* Interrupt mask */ +#define SFC_IMR0x4 +#define SFC_IMR_RX_FULL BIT(0) +#define SFC_IMR_RX_UFLOW BIT(1) +#define SFC_IMR_TX_OFLOW BIT(2) +#def
[PATCH v6 0/5] rockchip_sfc: add support for Rockchip SFC
Changes in v6: - Fix dma transfer logic - Fix the error of the way to wait for dma transfer finished status Changes in v5: - Support dma transfer - Add CONFIG_IS_ENABLED(CLK) limitation - Support spinand devices - Support SFC ver4 ver5 - Using "rockchip, sfc" as compatible id - Get clock from the index to compatible with those case which's clock-names is not parsed - px30 use "rockchip, sfc" as compatible id Changes in v4: - None Changes in v3: - Added "rockchip_sfc_adjust_op_work()" function from proposed Linux driver to fix potential issue on hardware. Note I never noticed this issue while testing, so I cannot test if it fixed any specific issue for me. - Updated of-compatible string back to "rockchip,sfc" to match what is currently proposed for upstream driver. The hardware itself has multiple versions but a register is present in the hardware that is read by the driver to set version specific functionality. - Updated px30.dtsi and rk3266-odroid-go2.dts device-trees so that sfc nodes match what is in upstream. Changes in v2: - Resending due to glitch with patch file truncating final two lines on patch 1/5 and incorrect patch version number on patch 5/5. Changes in v1: - Reworked code to utilize spi-mem framework, and based it closely off of work in progress code for mainline Linux. - Removed DMA, as it didn't offer much performance benefit for booting (in my test cases), added complexity to the code, and interfered with A-TF. - Updated the names of the bindings to match the work in progress Linux code. - Moved alias to u-boot specific device-tree for Odroid Go Advance. Alias is updated with the spi0 node pointing to the SFC to help the sf command as well as facilitate booting from the SFC. - Note 2 below no longer applies, as rebasing this off of upstream code should allow the device to work for NAND, and by utilizing the spi-mem framework it no longer has to extract the parameters Chris Morgan (5): spi: rockchip_sfc: add support for Rockchip SFC rockchip: px30: Add support for using SFC rockchip: px30: add the serial flash controller mtd: spi-nor-ids: Add XTX XT25F128B rockchip: px30: add support for SFC for Odroid Go Advance arch/arm/dts/px30.dtsi | 38 ++ arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi | 17 + arch/arm/dts/rk3326-odroid-go2.dts | 16 + arch/arm/mach-rockchip/px30/px30.c | 64 ++ drivers/mtd/spi/Kconfig| 6 + drivers/mtd/spi/spi-nor-ids.c | 8 + drivers/spi/Kconfig| 8 + drivers/spi/Makefile | 1 + drivers/spi/rockchip_sfc.c | 643 + 9 files changed, 801 insertions(+) create mode 100644 drivers/spi/rockchip_sfc.c -- 2.17.1
[PATCH v6 2/5] rockchip: px30: Add support for using SFC
From: Chris Morgan This patch adds support for setting the correct pin configuration for the Rockchip Serial Flash Controller found on the PX30. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- (no changes since v1) arch/arm/mach-rockchip/px30/px30.c | 64 ++ 1 file changed, 64 insertions(+) diff --git a/arch/arm/mach-rockchip/px30/px30.c b/arch/arm/mach-rockchip/px30/px30.c index 6fcef63c1b..be70d30cc8 100644 --- a/arch/arm/mach-rockchip/px30/px30.c +++ b/arch/arm/mach-rockchip/px30/px30.c @@ -51,6 +51,57 @@ struct mm_region *mem_map = px30_mem_map; #define QOS_PRIORITY_LEVEL(h, l) h) & 3) << 8) | ((l) & 3)) +/* GRF_GPIO1AL_IOMUX */ +enum { + GPIO1A3_SHIFT = 12, + GPIO1A3_MASK= 0xf << GPIO1A3_SHIFT, + GPIO1A3_GPIO= 0, + GPIO1A3_FLASH_D3, + GPIO1A3_EMMC_D3, + GPIO1A3_SFC_SIO3, + + GPIO1A2_SHIFT = 8, + GPIO1A2_MASK= 0xf << GPIO1A2_SHIFT, + GPIO1A2_GPIO= 0, + GPIO1A2_FLASH_D2, + GPIO1A2_EMMC_D2, + GPIO1A2_SFC_SIO2, + + GPIO1A1_SHIFT = 4, + GPIO1A1_MASK= 0xf << GPIO1A1_SHIFT, + GPIO1A1_GPIO= 0, + GPIO1A1_FLASH_D1, + GPIO1A1_EMMC_D1, + GPIO1A1_SFC_SIO1, + + GPIO1A0_SHIFT = 0, + GPIO1A0_MASK= 0xf << GPIO1A0_SHIFT, + GPIO1A0_GPIO= 0, + GPIO1A0_FLASH_D0, + GPIO1A0_EMMC_D0, + GPIO1A0_SFC_SIO0, +}; + +/* GRF_GPIO1AH_IOMUX */ +enum { + GPIO1A4_SHIFT = 0, + GPIO1A4_MASK= 0xf << GPIO1A4_SHIFT, + GPIO1A4_GPIO= 0, + GPIO1A4_FLASH_D4, + GPIO1A4_EMMC_D4, + GPIO1A4_SFC_CSN0, +}; + +/* GRF_GPIO1BL_IOMUX */ +enum { + GPIO1B1_SHIFT = 4, + GPIO1B1_MASK= 0xf << GPIO1B1_SHIFT, + GPIO1B1_GPIO= 0, + GPIO1B1_FLASH_RDY, + GPIO1B1_EMMC_CLKOUT, + GPIO1B1_SFC_CLK, +}; + /* GRF_GPIO1BH_IOMUX */ enum { GPIO1B7_SHIFT = 12, @@ -193,6 +244,19 @@ int arch_cpu_init(void) GPIO1D4_SDMMC_D2 << GPIO1D4_SHIFT); #endif +#ifdef CONFIG_ROCKCHIP_SFC + rk_clrsetreg(>gpio1al_iomux, +GPIO1A3_MASK | GPIO1A2_MASK | GPIO1A1_MASK | GPIO1A0_MASK, +GPIO1A3_SFC_SIO3 << GPIO1A3_SHIFT | +GPIO1A2_SFC_SIO2 << GPIO1A2_SHIFT | +GPIO1A1_SFC_SIO1 << GPIO1A1_SHIFT | +GPIO1A0_SFC_SIO0 << GPIO1A0_SHIFT); + rk_clrsetreg(>gpio1ah_iomux, GPIO1A4_MASK, +GPIO1A4_SFC_CSN0 << GPIO1A4_SHIFT); + rk_clrsetreg(>gpio1bl_iomux, GPIO1B1_MASK, +GPIO1B1_SFC_CLK << GPIO1B1_SHIFT); +#endif + #endif /* Enable PD_VO (default disable at reset) */ -- 2.17.1
[PATCH v6 3/5] rockchip: px30: add the serial flash controller
From: Chris Morgan Add the serial flash controller to the devicetree for the PX30. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- (no changes since v5) Changes in v5: - px30 use "rockchip, sfc" as compatible id arch/arm/dts/px30.dtsi | 38 ++ 1 file changed, 38 insertions(+) diff --git a/arch/arm/dts/px30.dtsi b/arch/arm/dts/px30.dtsi index b6c79e7ed3..aaa8ae2235 100644 --- a/arch/arm/dts/px30.dtsi +++ b/arch/arm/dts/px30.dtsi @@ -960,6 +960,18 @@ status = "disabled"; }; + sfc: sfc@ff3a { + compatible = "rockchip,sfc"; + reg = <0x0 0xff3a 0x0 0x4000>; + interrupts = ; + clocks = < SCLK_SFC>, < HCLK_SFC>; + clock-names = "clk_sfc", "hclk_sfc"; + pinctrl-names = "default"; + pinctrl-0 = <_clk _cs _bus4>; + power-domains = < PX30_PD_MMC_NAND>; + status = "disabled"; + }; + gpu: gpu@ff40 { compatible = "rockchip,px30-mali", "arm,mali-bifrost"; reg = <0x0 0xff40 0x0 0x4000>; @@ -1926,6 +1938,32 @@ }; }; + serial_flash { + sfc_bus4: sfc-bus4 { + rockchip,pins = + <1 RK_PA0 3 _pull_none>, + <1 RK_PA1 3 _pull_none>, + <1 RK_PA2 3 _pull_none>, + <1 RK_PA3 3 _pull_none>; + }; + + sfc_bus2: sfc-bus2 { + rockchip,pins = + <1 RK_PA0 3 _pull_none>, + <1 RK_PA1 3 _pull_none>; + }; + + sfc_cs: sfc-cs { + rockchip,pins = + <1 RK_PA4 3 _pull_none>; + }; + + sfc_clk: sfc-clk { + rockchip,pins = + <1 RK_PB1 3 _pull_none>; + }; + }; + lcdc { lcdc_rgb_dclk_pin: lcdc-rgb-dclk-pin { rockchip,pins = -- 2.17.1
[PATCH v5 5/5] rockchip: px30: add support for SFC for Odroid Go Advance
From: Chris Morgan The Odroid Go Advance uses a Rockchip Serial Flash Controller with an XT25F128B SPI NOR flash chip. This adds support for both. Note that while both the controller and chip support quad mode, only two lines are connected to the chip. Changing the pinctrl to bus2 and setting tx and rx lines to 2 for this reason. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- (no changes since v1) arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi | 17 + arch/arm/dts/rk3326-odroid-go2.dts | 16 2 files changed, 33 insertions(+) diff --git a/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi b/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi index 00767d2abd..741e8dd935 100644 --- a/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi +++ b/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi @@ -7,6 +7,15 @@ chosen { u-boot,spl-boot-order = }; + + aliases { + i2c0 = + i2c1 = + mmc0 = + serial1 = + serial2 = + spi0 = + }; }; { @@ -57,6 +66,14 @@ u-boot,spl-fifo-mode; }; + { + u-boot,dm-pre-reloc; +}; + +_flash { + u-boot,dm-pre-reloc; +}; + { clock-frequency = <2400>; u-boot,dm-pre-reloc; diff --git a/arch/arm/dts/rk3326-odroid-go2.dts b/arch/arm/dts/rk3326-odroid-go2.dts index 8cd4688c49..6f91f5040b 100644 --- a/arch/arm/dts/rk3326-odroid-go2.dts +++ b/arch/arm/dts/rk3326-odroid-go2.dts @@ -617,6 +617,22 @@ status = "okay"; }; + { + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <_clk _cs _bus2>; + status = "okay"; + + spi_flash: xt25f128b@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10800>; + spi-rx-bus-width = <2>; + spi-tx-bus-width = <2>; + }; +}; + { status = "okay"; }; -- 2.17.1
[PATCH v5 1/5] spi: rockchip_sfc: add support for Rockchip SFC
From: Chris Morgan This patch adds support for the Rockchip serial flash controller found on the PX30 SoC. It should work for versions 3-5 of the SFC IP, however I am only able to test it on v3. This is adapted from the WIP SPI-MEM driver for the SFC on mainline Linux. Note that the main difference between this and earlier versions of the driver is that this one does not support DMA. In testing the performance difference (performing a dual mode read on a 128Mb chip) is negligible. DMA, if used, must also be disabled in SPL mode when using A-TF anyway. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- Changes in v5: - Support dma transfer - Add CONFIG_IS_ENABLED(CLK) limitation - Support spinand devices - Support SFC ver4 ver5 - Using "rockchip, sfc" as compatible id - Get clock from the index to compatible with those case which's clock-names is not parsed Changes in v4: - None Changes in v3: - Added "rockchip_sfc_adjust_op_work()" function from proposed Linux driver to fix potential issue on hardware. Note I never noticed this issue while testing, so I cannot test if it fixed any specific issue for me. - Updated of-compatible string back to "rockchip,sfc" to match what is currently proposed for upstream driver. The hardware itself has multiple versions but a register is present in the hardware that is read by the driver to set version specific functionality. - Updated px30.dtsi and rk3266-odroid-go2.dts device-trees so that sfc nodes match what is in upstream. Changes in v2: - Resending due to glitch with patch file truncating final two lines on patch 1/5 and incorrect patch version number on patch 5/5. Changes in v1: - Reworked code to utilize spi-mem framework, and based it closely off of work in progress code for mainline Linux. - Removed DMA, as it didn't offer much performance benefit for booting (in my test cases), added complexity to the code, and interfered with A-TF. - Updated the names of the bindings to match the work in progress Linux code. - Moved alias to u-boot specific device-tree for Odroid Go Advance. Alias is updated with the spi0 node pointing to the SFC to help the sf command as well as facilitate booting from the SFC. - Note 2 below no longer applies, as rebasing this off of upstream code should allow the device to work for NAND, and by utilizing the spi-mem framework it no longer has to extract the parameters drivers/spi/Kconfig| 8 + drivers/spi/Makefile | 1 + drivers/spi/rockchip_sfc.c | 642 + 3 files changed, 651 insertions(+) create mode 100644 drivers/spi/rockchip_sfc.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 1494c91763..bef36f2931 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -312,6 +312,14 @@ config RENESAS_RPC_SPI on Renesas RCar Gen3 SoCs. This uses driver model and requires a device tree binding to operate. +config ROCKCHIP_SFC + bool "Rockchip SFC Driver" + help + Enable the Rockchip SFC Driver for SPI NOR flash. This device is + a limited purpose SPI controller for driving NOR flash on certain + Rockchip SoCs. This uses driver model and requires a device tree + binding to operate. + config ROCKCHIP_SPI bool "Rockchip SPI driver" help diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index cfe4fae1d4..f02e84b5f1 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -52,6 +52,7 @@ obj-$(CONFIG_PIC32_SPI) += pic32_spi.o obj-$(CONFIG_PL022_SPI) += pl022_spi.o obj-$(CONFIG_SPI_QUP) += spi-qup.o obj-$(CONFIG_RENESAS_RPC_SPI) += renesas_rpc_spi.o +obj-$(CONFIG_ROCKCHIP_SFC) += rockchip_sfc.o obj-$(CONFIG_ROCKCHIP_SPI) += rk_spi.o obj-$(CONFIG_SANDBOX_SPI) += sandbox_spi.o obj-$(CONFIG_SPI_SIFIVE) += spi-sifive.o diff --git a/drivers/spi/rockchip_sfc.c b/drivers/spi/rockchip_sfc.c new file mode 100644 index 00..918abb431d --- /dev/null +++ b/drivers/spi/rockchip_sfc.c @@ -0,0 +1,642 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Rockchip Serial Flash Controller Driver + * + * Copyright (c) 2017-2021, Rockchip Inc. + * Author: Shawn Lin + *Chris Morgan + *Jon Lin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* System control */ +#define SFC_CTRL 0x0 +#define SFC_CTRL_PHASE_SEL_NEGETIVE BIT(1) +#define SFC_CTRL_CMD_BITS_SHIFT 8 +#define SFC_CTRL_ADDR_BITS_SHIFT 10 +#define SFC_CTRL_DATA_BITS_SHIFT 12 + +/* Interrupt mask */ +#define SFC_IMR0x4 +#define SFC_IMR_RX_FULL BIT(0) +#define SFC_IMR_RX_UFLOW BIT(1) +#define SFC_IMR_TX_OFLOW BIT(2) +#define SFC_IMR_TX_EMPTY BIT(3) +#define SFC_IMR_TRAN_FINISH BIT(4) +#define SFC_IMR_BUS_ERR
[PATCH v5 0/5] rockchip_sfc: add support for Rockchip SFC
Changes in v5: - Support dma transfer - Add CONFIG_IS_ENABLED(CLK) limitation - Support spinand devices - Support SFC ver4 ver5 - Using "rockchip, sfc" as compatible id - Get clock from the index to compatible with those case which's clock-names is not parsed - px30 use "rockchip, sfc" as compatible id Changes in v4: - None Changes in v3: - Added "rockchip_sfc_adjust_op_work()" function from proposed Linux driver to fix potential issue on hardware. Note I never noticed this issue while testing, so I cannot test if it fixed any specific issue for me. - Updated of-compatible string back to "rockchip,sfc" to match what is currently proposed for upstream driver. The hardware itself has multiple versions but a register is present in the hardware that is read by the driver to set version specific functionality. - Updated px30.dtsi and rk3266-odroid-go2.dts device-trees so that sfc nodes match what is in upstream. Changes in v2: - Resending due to glitch with patch file truncating final two lines on patch 1/5 and incorrect patch version number on patch 5/5. Changes in v1: - Reworked code to utilize spi-mem framework, and based it closely off of work in progress code for mainline Linux. - Removed DMA, as it didn't offer much performance benefit for booting (in my test cases), added complexity to the code, and interfered with A-TF. - Updated the names of the bindings to match the work in progress Linux code. - Moved alias to u-boot specific device-tree for Odroid Go Advance. Alias is updated with the spi0 node pointing to the SFC to help the sf command as well as facilitate booting from the SFC. - Note 2 below no longer applies, as rebasing this off of upstream code should allow the device to work for NAND, and by utilizing the spi-mem framework it no longer has to extract the parameters Chris Morgan (5): spi: rockchip_sfc: add support for Rockchip SFC rockchip: px30: Add support for using SFC rockchip: px30: add the serial flash controller mtd: spi-nor-ids: Add XTX XT25F128B rockchip: px30: add support for SFC for Odroid Go Advance arch/arm/dts/px30.dtsi | 38 ++ arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi | 17 + arch/arm/dts/rk3326-odroid-go2.dts | 16 + arch/arm/mach-rockchip/px30/px30.c | 64 ++ drivers/mtd/spi/Kconfig| 6 + drivers/mtd/spi/spi-nor-ids.c | 8 + drivers/spi/Kconfig| 8 + drivers/spi/Makefile | 1 + drivers/spi/rockchip_sfc.c | 642 + 9 files changed, 800 insertions(+) create mode 100644 drivers/spi/rockchip_sfc.c -- 2.17.1
[PATCH v5 2/5] rockchip: px30: Add support for using SFC
From: Chris Morgan This patch adds support for setting the correct pin configuration for the Rockchip Serial Flash Controller found on the PX30. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- (no changes since v1) arch/arm/mach-rockchip/px30/px30.c | 64 ++ 1 file changed, 64 insertions(+) diff --git a/arch/arm/mach-rockchip/px30/px30.c b/arch/arm/mach-rockchip/px30/px30.c index 6fcef63c1b..be70d30cc8 100644 --- a/arch/arm/mach-rockchip/px30/px30.c +++ b/arch/arm/mach-rockchip/px30/px30.c @@ -51,6 +51,57 @@ struct mm_region *mem_map = px30_mem_map; #define QOS_PRIORITY_LEVEL(h, l) h) & 3) << 8) | ((l) & 3)) +/* GRF_GPIO1AL_IOMUX */ +enum { + GPIO1A3_SHIFT = 12, + GPIO1A3_MASK= 0xf << GPIO1A3_SHIFT, + GPIO1A3_GPIO= 0, + GPIO1A3_FLASH_D3, + GPIO1A3_EMMC_D3, + GPIO1A3_SFC_SIO3, + + GPIO1A2_SHIFT = 8, + GPIO1A2_MASK= 0xf << GPIO1A2_SHIFT, + GPIO1A2_GPIO= 0, + GPIO1A2_FLASH_D2, + GPIO1A2_EMMC_D2, + GPIO1A2_SFC_SIO2, + + GPIO1A1_SHIFT = 4, + GPIO1A1_MASK= 0xf << GPIO1A1_SHIFT, + GPIO1A1_GPIO= 0, + GPIO1A1_FLASH_D1, + GPIO1A1_EMMC_D1, + GPIO1A1_SFC_SIO1, + + GPIO1A0_SHIFT = 0, + GPIO1A0_MASK= 0xf << GPIO1A0_SHIFT, + GPIO1A0_GPIO= 0, + GPIO1A0_FLASH_D0, + GPIO1A0_EMMC_D0, + GPIO1A0_SFC_SIO0, +}; + +/* GRF_GPIO1AH_IOMUX */ +enum { + GPIO1A4_SHIFT = 0, + GPIO1A4_MASK= 0xf << GPIO1A4_SHIFT, + GPIO1A4_GPIO= 0, + GPIO1A4_FLASH_D4, + GPIO1A4_EMMC_D4, + GPIO1A4_SFC_CSN0, +}; + +/* GRF_GPIO1BL_IOMUX */ +enum { + GPIO1B1_SHIFT = 4, + GPIO1B1_MASK= 0xf << GPIO1B1_SHIFT, + GPIO1B1_GPIO= 0, + GPIO1B1_FLASH_RDY, + GPIO1B1_EMMC_CLKOUT, + GPIO1B1_SFC_CLK, +}; + /* GRF_GPIO1BH_IOMUX */ enum { GPIO1B7_SHIFT = 12, @@ -193,6 +244,19 @@ int arch_cpu_init(void) GPIO1D4_SDMMC_D2 << GPIO1D4_SHIFT); #endif +#ifdef CONFIG_ROCKCHIP_SFC + rk_clrsetreg(>gpio1al_iomux, +GPIO1A3_MASK | GPIO1A2_MASK | GPIO1A1_MASK | GPIO1A0_MASK, +GPIO1A3_SFC_SIO3 << GPIO1A3_SHIFT | +GPIO1A2_SFC_SIO2 << GPIO1A2_SHIFT | +GPIO1A1_SFC_SIO1 << GPIO1A1_SHIFT | +GPIO1A0_SFC_SIO0 << GPIO1A0_SHIFT); + rk_clrsetreg(>gpio1ah_iomux, GPIO1A4_MASK, +GPIO1A4_SFC_CSN0 << GPIO1A4_SHIFT); + rk_clrsetreg(>gpio1bl_iomux, GPIO1B1_MASK, +GPIO1B1_SFC_CLK << GPIO1B1_SHIFT); +#endif + #endif /* Enable PD_VO (default disable at reset) */ -- 2.17.1
[PATCH v5 4/5] mtd: spi-nor-ids: Add XTX XT25F128B
From: Chris Morgan Adds support for XT25F128B used on Odroid Go Advance. Unfortunately this chip uses a continuation code which I cannot seem to parse, so there are possibly going to be collisions with chips that use the same manufacturer/ID. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- (no changes since v1) drivers/mtd/spi/Kconfig | 6 ++ drivers/mtd/spi/spi-nor-ids.c | 8 2 files changed, 14 insertions(+) diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig index f8db8e5213..8c797d1e03 100644 --- a/drivers/mtd/spi/Kconfig +++ b/drivers/mtd/spi/Kconfig @@ -162,6 +162,12 @@ config SPI_FLASH_XMC Add support for various XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) SPI flash chips (XM25xxx) +config SPI_FLASH_XTX + bool "XTX SPI flash support" + help + Add support for various XTX (XTX Technology Limited) + SPI flash chips (XT25xxx). + endif config SPI_FLASH_USE_4K_SECTORS diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c index 2b57797954..bdecb3b837 100644 --- a/drivers/mtd/spi/spi-nor-ids.c +++ b/drivers/mtd/spi/spi-nor-ids.c @@ -336,6 +336,14 @@ const struct flash_info spi_nor_ids[] = { /* XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) */ { INFO("XM25QH64A", 0x207017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { INFO("XM25QH128A", 0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, +#endif +#ifdef CONFIG_SPI_FLASH_XTX + /* XTX Technology (Shenzhen) Limited */ + { + INFO("xt25f128b", 0x0b4018, 0, 64 * 1024, 256, +SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | +SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, #endif { }, }; -- 2.17.1
[PATCH v5 3/5] rockchip: px30: add the serial flash controller
From: Chris Morgan Add the serial flash controller to the devicetree for the PX30. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- Changes in v5: - px30 use "rockchip, sfc" as compatible id arch/arm/dts/px30.dtsi | 38 ++ 1 file changed, 38 insertions(+) diff --git a/arch/arm/dts/px30.dtsi b/arch/arm/dts/px30.dtsi index b6c79e7ed3..aaa8ae2235 100644 --- a/arch/arm/dts/px30.dtsi +++ b/arch/arm/dts/px30.dtsi @@ -960,6 +960,18 @@ status = "disabled"; }; + sfc: sfc@ff3a { + compatible = "rockchip,sfc"; + reg = <0x0 0xff3a 0x0 0x4000>; + interrupts = ; + clocks = < SCLK_SFC>, < HCLK_SFC>; + clock-names = "clk_sfc", "hclk_sfc"; + pinctrl-names = "default"; + pinctrl-0 = <_clk _cs _bus4>; + power-domains = < PX30_PD_MMC_NAND>; + status = "disabled"; + }; + gpu: gpu@ff40 { compatible = "rockchip,px30-mali", "arm,mali-bifrost"; reg = <0x0 0xff40 0x0 0x4000>; @@ -1926,6 +1938,32 @@ }; }; + serial_flash { + sfc_bus4: sfc-bus4 { + rockchip,pins = + <1 RK_PA0 3 _pull_none>, + <1 RK_PA1 3 _pull_none>, + <1 RK_PA2 3 _pull_none>, + <1 RK_PA3 3 _pull_none>; + }; + + sfc_bus2: sfc-bus2 { + rockchip,pins = + <1 RK_PA0 3 _pull_none>, + <1 RK_PA1 3 _pull_none>; + }; + + sfc_cs: sfc-cs { + rockchip,pins = + <1 RK_PA4 3 _pull_none>; + }; + + sfc_clk: sfc-clk { + rockchip,pins = + <1 RK_PB1 3 _pull_none>; + }; + }; + lcdc { lcdc_rgb_dclk_pin: lcdc-rgb-dclk-pin { rockchip,pins = -- 2.17.1
[PATCH v2 1/2] spi: rockchip_sfc: Impletment set_speed logic
Set clock related processing into set_speed logic. And Optimize printing format. Tested-by: Chris Morgan Signed-off-by: Jon Lin --- (no changes since v1) drivers/spi/rockchip_sfc.c | 83 ++ 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/drivers/spi/rockchip_sfc.c b/drivers/spi/rockchip_sfc.c index 4e2b861f22..2028b28e26 100644 --- a/drivers/spi/rockchip_sfc.c +++ b/drivers/spi/rockchip_sfc.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -116,6 +117,7 @@ /* Master trigger */ #define SFC_DMA_TRIGGER0x80 +#define SFC_DMA_TRIGGER_START 1 /* Src or Dst addr for master */ #define SFC_DMA_ADDR 0x84 @@ -163,14 +165,12 @@ #define SFC_DMA_TRANS_THRETHOLD(0x40) /* Maximum clock values from datasheet suggest keeping clock value under - * 150MHz. No minimum or average value is suggested, but the U-boot BSP driver - * has a minimum of 10MHz and a default of 80MHz which seems reasonable. + * 150MHz. No minimum or average value is suggested. */ -#define SFC_MIN_SPEED_HZ (10 * 1000 * 1000) -#define SFC_DEFAULT_SPEED_HZ (80 * 1000 * 1000) -#define SFC_MAX_SPEED_HZ (150 * 1000 * 1000) +#define SFC_MAX_SPEED (150 * 1000 * 1000) struct rockchip_sfc { + struct udevice *dev; void __iomem *regbase; struct clk hclk; struct clk clk; @@ -197,8 +197,6 @@ static int rockchip_sfc_reset(struct rockchip_sfc *sfc) /* Still need to clear the masked interrupt from RISR */ writel(0x, sfc->regbase + SFC_ICLR); - debug("reset\n"); - return err; } @@ -261,15 +259,11 @@ static int rockchip_sfc_probe(struct udevice *bus) #if CONFIG_IS_ENABLED(CLK) ret = clk_enable(>hclk); if (ret) - debug("Enable ahb clock fail %s: %d\n", bus->name, ret); + dev_dbg(sfc->dev, "sfc Enable ahb clock fail %s: %d\n", bus->name, ret); ret = clk_enable(>clk); if (ret) - debug("Enable clock fail for %s: %d\n", bus->name, ret); - - ret = clk_set_rate(>clk, SFC_DEFAULT_SPEED_HZ); - if (ret) - debug("Could not set sfc clock for %s: %d\n", bus->name, ret); + dev_dbg(sfc->dev, "sfc Enable clock fail for %s: %d\n", bus->name, ret); #endif ret = rockchip_sfc_init(sfc); @@ -278,7 +272,8 @@ static int rockchip_sfc_probe(struct udevice *bus) sfc->max_iosize = rockchip_sfc_get_max_iosize(sfc); sfc->version = rockchip_sfc_get_version(sfc); - sfc->speed = SFC_DEFAULT_SPEED_HZ; + sfc->max_freq = SFC_MAX_SPEED; + sfc->dev = bus; return 0; @@ -411,11 +406,11 @@ static int rockchip_sfc_xfer_setup(struct rockchip_sfc *sfc, ctrl |= SFC_CTRL_PHASE_SEL_NEGETIVE; cmd |= plat->cs << SFC_CMD_CS_SHIFT; - debug("addr.nbytes=%x(x%d) dummy.nbytes=%x(x%d)\n", - op->addr.nbytes, op->addr.buswidth, - op->dummy.nbytes, op->dummy.buswidth); - debug("ctrl=%x cmd=%x addr=%llx len=%x\n", - ctrl, cmd, op->addr.val, len); + dev_dbg(sfc->dev, "sfc addr.nbytes=%x(x%d) dummy.nbytes=%x(x%d)\n", + op->addr.nbytes, op->addr.buswidth, + op->dummy.nbytes, op->dummy.buswidth); + dev_dbg(sfc->dev, "sfc ctrl=%x cmd=%x addr=%llx len=%x\n", + ctrl, cmd, op->addr.val, len); writel(ctrl, sfc->regbase + SFC_CTRL); writel(cmd, sfc->regbase + SFC_CMD); @@ -492,7 +487,7 @@ static int rockchip_sfc_fifo_transfer_dma(struct rockchip_sfc *sfc, dma_addr_t d { writel(0x, sfc->regbase + SFC_ICLR); writel((u32)dma_buf, sfc->regbase + SFC_DMA_ADDR); - writel(0x1, sfc->regbase + SFC_DMA_TRIGGER); + writel(SFC_DMA_TRIGGER_START, sfc->regbase + SFC_DMA_TRIGGER); return len; } @@ -500,7 +495,7 @@ static int rockchip_sfc_fifo_transfer_dma(struct rockchip_sfc *sfc, dma_addr_t d static int rockchip_sfc_xfer_data_poll(struct rockchip_sfc *sfc, const struct spi_mem_op *op, u32 len) { - debug("xfer_poll len=%x\n", len); + dev_dbg(sfc->dev, "sfc xfer_poll len=%x\n", len); if (op->data.dir == SPI_MEM_DATA_OUT) return rockchip_sfc_write_fifo(sfc, op->data.buf.out, len); @@ -516,7 +511,7 @@ static int rockchip_sfc_xfer_data_dma(struct rockchip_sfc *sfc, void *dma_buf; int ret; - debug("xfer_dma len=%x\n", len); + dev_dbg(sfc->dev, "sfc xfer_dma len=%x\n", len); if (op->data.dir == SPI_MEM_DATA_OUT)
[PATCH v2 2/2] spi: rockchip_sfc: Using read_poll
Using read_poll logic. Tested-by: Chris Morgan Signed-off-by: Jon Lin --- Changes in v2: - Fix assigned but never used return error codes drivers/spi/rockchip_sfc.c | 67 -- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/drivers/spi/rockchip_sfc.c b/drivers/spi/rockchip_sfc.c index 2028b28e26..6dfae20699 100644 --- a/drivers/spi/rockchip_sfc.c +++ b/drivers/spi/rockchip_sfc.c @@ -286,33 +286,38 @@ err_init: return ret; } -static inline int rockchip_sfc_get_fifo_level(struct rockchip_sfc *sfc, int wr) +static int rockchip_sfc_wait_txfifo_ready(struct rockchip_sfc *sfc, u32 timeout_us) { - u32 fsr = readl(sfc->regbase + SFC_FSR); - int level; + int ret = 0; + u32 status; - if (wr) - level = (fsr & SFC_FSR_TXLV_MASK) >> SFC_FSR_TXLV_SHIFT; - else - level = (fsr & SFC_FSR_RXLV_MASK) >> SFC_FSR_RXLV_SHIFT; + ret = readl_poll_timeout(sfc->regbase + SFC_FSR, status, +status & SFC_FSR_TXLV_MASK, +timeout_us); + if (ret) { + dev_dbg(sfc->dev, "sfc wait tx fifo timeout\n"); + + return -ETIMEDOUT; + } - return level; + return (status & SFC_FSR_TXLV_MASK) >> SFC_FSR_TXLV_SHIFT; } -static int rockchip_sfc_wait_fifo_ready(struct rockchip_sfc *sfc, int wr, u32 timeout) +static int rockchip_sfc_wait_rxfifo_ready(struct rockchip_sfc *sfc, u32 timeout_us) { - unsigned long tbase = get_timer(0); - int level; + int ret = 0; + u32 status; - while (!(level = rockchip_sfc_get_fifo_level(sfc, wr))) { - if (get_timer(tbase) > timeout) { - debug("%s fifo timeout\n", wr ? "write" : "read"); - return -ETIMEDOUT; - } - udelay(1); + ret = readl_poll_timeout(sfc->regbase + SFC_FSR, status, +status & SFC_FSR_RXLV_MASK, +timeout_us); + if (ret) { + dev_dbg(sfc->dev, "sfc wait rx fifo timeout\n"); + + return -ETIMEDOUT; } - return level; + return (status & SFC_FSR_RXLV_MASK) >> SFC_FSR_RXLV_SHIFT; } static void rockchip_sfc_adjust_op_work(struct spi_mem_op *op) @@ -430,7 +435,7 @@ static int rockchip_sfc_write_fifo(struct rockchip_sfc *sfc, const u8 *buf, int dwords = len >> 2; while (dwords) { - tx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_CMD_DIR_WR, 1000); + tx_level = rockchip_sfc_wait_txfifo_ready(sfc, 1000); if (tx_level < 0) return tx_level; write_words = min_t(u32, tx_level, dwords); @@ -441,7 +446,7 @@ static int rockchip_sfc_write_fifo(struct rockchip_sfc *sfc, const u8 *buf, int /* write the rest non word aligned bytes */ if (bytes) { - tx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_CMD_DIR_WR, 1000); + tx_level = rockchip_sfc_wait_txfifo_ready(sfc, 1000); if (tx_level < 0) return tx_level; memcpy(, buf, bytes); @@ -462,7 +467,7 @@ static int rockchip_sfc_read_fifo(struct rockchip_sfc *sfc, u8 *buf, int len) /* word aligned access only */ dwords = len >> 2; while (dwords) { - rx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_CMD_DIR_RD, 1000); + rx_level = rockchip_sfc_wait_rxfifo_ready(sfc, 1000); if (rx_level < 0) return rx_level; read_words = min_t(u32, rx_level, dwords); @@ -473,7 +478,7 @@ static int rockchip_sfc_read_fifo(struct rockchip_sfc *sfc, u8 *buf, int len) /* read the rest non word aligned bytes */ if (bytes) { - rx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_CMD_DIR_RD, 1000); + rx_level = rockchip_sfc_wait_rxfifo_ready(sfc, 1000); if (rx_level < 0) return rx_level; tmp = readl(sfc->regbase + SFC_DATA); @@ -534,19 +539,17 @@ static int rockchip_sfc_xfer_data_dma(struct rockchip_sfc *sfc, static int rockchip_sfc_xfer_done(struct rockchip_sfc *sfc, u32 timeout_us) { - unsigned long tbase = get_timer(0); int ret = 0; - u32 timeout = timeout_us; - - while (readl(sfc->regbase + SFC_SR) & SFC_SR_IS_BUSY) { - if (get_timer(tbase) > timeout) { - printf("wait sfc idle timeout\n"); - rockchip_sfc_reset(sfc); + u32 status; - return -ETIMEDOUT; - } + ret = readl_poll_timeout(sfc->regbase + SFC_SR,
Re: [PATCH 3/3] rockchip: px30: Change sfc node to match upstream linux proposed
On 2021/8/19 1:13, Chris Morgan wrote: On Tue, Aug 17, 2021 at 09:41:01AM +0800, Jon Lin wrote: TX single line is more compatible for corresponding board Signed-off-by: Jon Lin --- There are still some bugs with this. Note that if you want for now you can just abandon this patch (or fix it, either way is fine). If you abandon it I'll make sure once the Linux driver is upstream the nodes match between it and U-Boot. Otherwise, you'll need to make the changes below to fix this. I had abandon it because I think it would be more accurate for you to deal with it arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi | 2 +- arch/arm/dts/rk3326-odroid-go2.dts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi b/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi index 741e8dd935..0990005a15 100644 --- a/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi +++ b/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi @@ -70,7 +70,7 @@ u-boot,dm-pre-reloc; }; -_flash { +&{/sfc@ff3a/flash@0} { u-boot,dm-pre-reloc; }; This causes the devicetree to fail to compile, since the node is not getting changed from spi_flash in the main dts file. diff --git a/arch/arm/dts/rk3326-odroid-go2.dts b/arch/arm/dts/rk3326-odroid-go2.dts index 6f91f5040b..57e7f409d8 100644 --- a/arch/arm/dts/rk3326-odroid-go2.dts +++ b/arch/arm/dts/rk3326-odroid-go2.dts @@ -629,7 +629,7 @@ The node should change here to just "flash@0" instead of "spi_flash: xt25f128b@0" to match upstream (proposed). Also note that on the upstream (proposed) the pinctrl values are in a different order, and the sfc_cs pinctrl is called the sfc_cs0. reg = <0>; spi-max-frequency = <10800>; spi-rx-bus-width = <2>; - spi-tx-bus-width = <2>; + spi-tx-bus-width = <1>; }; }; -- 2.17.1
[PATCH 1/2] spi: rockchip_sfc: Impletment set_speed logic
Set clock related processing into set_speed logic. And Optimize printing format. Tested-by: Chris Morgan Signed-off-by: Jon Lin --- drivers/spi/rockchip_sfc.c | 83 ++ 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/drivers/spi/rockchip_sfc.c b/drivers/spi/rockchip_sfc.c index 4e2b861f22..2028b28e26 100644 --- a/drivers/spi/rockchip_sfc.c +++ b/drivers/spi/rockchip_sfc.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -116,6 +117,7 @@ /* Master trigger */ #define SFC_DMA_TRIGGER0x80 +#define SFC_DMA_TRIGGER_START 1 /* Src or Dst addr for master */ #define SFC_DMA_ADDR 0x84 @@ -163,14 +165,12 @@ #define SFC_DMA_TRANS_THRETHOLD(0x40) /* Maximum clock values from datasheet suggest keeping clock value under - * 150MHz. No minimum or average value is suggested, but the U-boot BSP driver - * has a minimum of 10MHz and a default of 80MHz which seems reasonable. + * 150MHz. No minimum or average value is suggested. */ -#define SFC_MIN_SPEED_HZ (10 * 1000 * 1000) -#define SFC_DEFAULT_SPEED_HZ (80 * 1000 * 1000) -#define SFC_MAX_SPEED_HZ (150 * 1000 * 1000) +#define SFC_MAX_SPEED (150 * 1000 * 1000) struct rockchip_sfc { + struct udevice *dev; void __iomem *regbase; struct clk hclk; struct clk clk; @@ -197,8 +197,6 @@ static int rockchip_sfc_reset(struct rockchip_sfc *sfc) /* Still need to clear the masked interrupt from RISR */ writel(0x, sfc->regbase + SFC_ICLR); - debug("reset\n"); - return err; } @@ -261,15 +259,11 @@ static int rockchip_sfc_probe(struct udevice *bus) #if CONFIG_IS_ENABLED(CLK) ret = clk_enable(>hclk); if (ret) - debug("Enable ahb clock fail %s: %d\n", bus->name, ret); + dev_dbg(sfc->dev, "sfc Enable ahb clock fail %s: %d\n", bus->name, ret); ret = clk_enable(>clk); if (ret) - debug("Enable clock fail for %s: %d\n", bus->name, ret); - - ret = clk_set_rate(>clk, SFC_DEFAULT_SPEED_HZ); - if (ret) - debug("Could not set sfc clock for %s: %d\n", bus->name, ret); + dev_dbg(sfc->dev, "sfc Enable clock fail for %s: %d\n", bus->name, ret); #endif ret = rockchip_sfc_init(sfc); @@ -278,7 +272,8 @@ static int rockchip_sfc_probe(struct udevice *bus) sfc->max_iosize = rockchip_sfc_get_max_iosize(sfc); sfc->version = rockchip_sfc_get_version(sfc); - sfc->speed = SFC_DEFAULT_SPEED_HZ; + sfc->max_freq = SFC_MAX_SPEED; + sfc->dev = bus; return 0; @@ -411,11 +406,11 @@ static int rockchip_sfc_xfer_setup(struct rockchip_sfc *sfc, ctrl |= SFC_CTRL_PHASE_SEL_NEGETIVE; cmd |= plat->cs << SFC_CMD_CS_SHIFT; - debug("addr.nbytes=%x(x%d) dummy.nbytes=%x(x%d)\n", - op->addr.nbytes, op->addr.buswidth, - op->dummy.nbytes, op->dummy.buswidth); - debug("ctrl=%x cmd=%x addr=%llx len=%x\n", - ctrl, cmd, op->addr.val, len); + dev_dbg(sfc->dev, "sfc addr.nbytes=%x(x%d) dummy.nbytes=%x(x%d)\n", + op->addr.nbytes, op->addr.buswidth, + op->dummy.nbytes, op->dummy.buswidth); + dev_dbg(sfc->dev, "sfc ctrl=%x cmd=%x addr=%llx len=%x\n", + ctrl, cmd, op->addr.val, len); writel(ctrl, sfc->regbase + SFC_CTRL); writel(cmd, sfc->regbase + SFC_CMD); @@ -492,7 +487,7 @@ static int rockchip_sfc_fifo_transfer_dma(struct rockchip_sfc *sfc, dma_addr_t d { writel(0x, sfc->regbase + SFC_ICLR); writel((u32)dma_buf, sfc->regbase + SFC_DMA_ADDR); - writel(0x1, sfc->regbase + SFC_DMA_TRIGGER); + writel(SFC_DMA_TRIGGER_START, sfc->regbase + SFC_DMA_TRIGGER); return len; } @@ -500,7 +495,7 @@ static int rockchip_sfc_fifo_transfer_dma(struct rockchip_sfc *sfc, dma_addr_t d static int rockchip_sfc_xfer_data_poll(struct rockchip_sfc *sfc, const struct spi_mem_op *op, u32 len) { - debug("xfer_poll len=%x\n", len); + dev_dbg(sfc->dev, "sfc xfer_poll len=%x\n", len); if (op->data.dir == SPI_MEM_DATA_OUT) return rockchip_sfc_write_fifo(sfc, op->data.buf.out, len); @@ -516,7 +511,7 @@ static int rockchip_sfc_xfer_data_dma(struct rockchip_sfc *sfc, void *dma_buf; int ret; - debug("xfer_dma len=%x\n", len); + dev_dbg(sfc->dev, "sfc xfer_dma len=%x\n", len); if (op->data.dir == SPI_MEM_DATA_OUT) { dma_
[PATCH 2/2] spi: rockchip_sfc: Using read_poll
Using read_poll logic. Tested-by: Chris Morgan Signed-off-by: Jon Lin --- drivers/spi/rockchip_sfc.c | 67 -- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/drivers/spi/rockchip_sfc.c b/drivers/spi/rockchip_sfc.c index 2028b28e26..33c5344c70 100644 --- a/drivers/spi/rockchip_sfc.c +++ b/drivers/spi/rockchip_sfc.c @@ -286,33 +286,38 @@ err_init: return ret; } -static inline int rockchip_sfc_get_fifo_level(struct rockchip_sfc *sfc, int wr) +static int rockchip_sfc_wait_txfifo_ready(struct rockchip_sfc *sfc, u32 timeout_us) { - u32 fsr = readl(sfc->regbase + SFC_FSR); - int level; + int ret = 0; + u32 status; - if (wr) - level = (fsr & SFC_FSR_TXLV_MASK) >> SFC_FSR_TXLV_SHIFT; - else - level = (fsr & SFC_FSR_RXLV_MASK) >> SFC_FSR_RXLV_SHIFT; + ret = readl_poll_timeout(sfc->regbase + SFC_FSR, status, +status & SFC_FSR_TXLV_MASK, +timeout_us); + if (ret) { + dev_dbg(sfc->dev, "sfc wait tx fifo timeout\n"); + + ret = -ETIMEDOUT; + } - return level; + return (status & SFC_FSR_TXLV_MASK) >> SFC_FSR_TXLV_SHIFT; } -static int rockchip_sfc_wait_fifo_ready(struct rockchip_sfc *sfc, int wr, u32 timeout) +static int rockchip_sfc_wait_rxfifo_ready(struct rockchip_sfc *sfc, u32 timeout_us) { - unsigned long tbase = get_timer(0); - int level; + int ret = 0; + u32 status; - while (!(level = rockchip_sfc_get_fifo_level(sfc, wr))) { - if (get_timer(tbase) > timeout) { - debug("%s fifo timeout\n", wr ? "write" : "read"); - return -ETIMEDOUT; - } - udelay(1); + ret = readl_poll_timeout(sfc->regbase + SFC_FSR, status, +status & SFC_FSR_RXLV_MASK, +timeout_us); + if (ret) { + dev_dbg(sfc->dev, "sfc wait rx fifo timeout\n"); + + ret = -ETIMEDOUT; } - return level; + return (status & SFC_FSR_RXLV_MASK) >> SFC_FSR_RXLV_SHIFT; } static void rockchip_sfc_adjust_op_work(struct spi_mem_op *op) @@ -430,7 +435,7 @@ static int rockchip_sfc_write_fifo(struct rockchip_sfc *sfc, const u8 *buf, int dwords = len >> 2; while (dwords) { - tx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_CMD_DIR_WR, 1000); + tx_level = rockchip_sfc_wait_txfifo_ready(sfc, 1000); if (tx_level < 0) return tx_level; write_words = min_t(u32, tx_level, dwords); @@ -441,7 +446,7 @@ static int rockchip_sfc_write_fifo(struct rockchip_sfc *sfc, const u8 *buf, int /* write the rest non word aligned bytes */ if (bytes) { - tx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_CMD_DIR_WR, 1000); + tx_level = rockchip_sfc_wait_txfifo_ready(sfc, 1000); if (tx_level < 0) return tx_level; memcpy(, buf, bytes); @@ -462,7 +467,7 @@ static int rockchip_sfc_read_fifo(struct rockchip_sfc *sfc, u8 *buf, int len) /* word aligned access only */ dwords = len >> 2; while (dwords) { - rx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_CMD_DIR_RD, 1000); + rx_level = rockchip_sfc_wait_rxfifo_ready(sfc, 1000); if (rx_level < 0) return rx_level; read_words = min_t(u32, rx_level, dwords); @@ -473,7 +478,7 @@ static int rockchip_sfc_read_fifo(struct rockchip_sfc *sfc, u8 *buf, int len) /* read the rest non word aligned bytes */ if (bytes) { - rx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_CMD_DIR_RD, 1000); + rx_level = rockchip_sfc_wait_rxfifo_ready(sfc, 1000); if (rx_level < 0) return rx_level; tmp = readl(sfc->regbase + SFC_DATA); @@ -534,19 +539,17 @@ static int rockchip_sfc_xfer_data_dma(struct rockchip_sfc *sfc, static int rockchip_sfc_xfer_done(struct rockchip_sfc *sfc, u32 timeout_us) { - unsigned long tbase = get_timer(0); int ret = 0; - u32 timeout = timeout_us; - - while (readl(sfc->regbase + SFC_SR) & SFC_SR_IS_BUSY) { - if (get_timer(tbase) > timeout) { - printf("wait sfc idle timeout\n"); - rockchip_sfc_reset(sfc); + u32 status; - return -ETIMEDOUT; - } + ret = readl_poll_timeout(sfc->regbase + SFC_SR, status, +!(status & SFC_SR_I
Re: [PATCH v8 1/5] spi: rockchip_sfc: add support for Rockchip SFC
On 2021/8/14 0:48, Chris Morgan wrote: On Fri, Aug 13, 2021 at 09:53:03AM +0800, Jon Lin wrote: Here is the point, Can you take a try. diff --git a/drivers/spi/rockchip_sfc.c b/drivers/spi/rockchip_sfc.c index 8173724ecd..33c5344c70 100644 --- a/drivers/spi/rockchip_sfc.c +++ b/drivers/spi/rockchip_sfc.c @@ -591,7 +591,7 @@ static int rockchip_sfc_adjust_op_size(struct spi_slave *mem, struct spi_mem_op static int rockchip_sfc_set_speed(struct udevice *bus, uint speed) { - struct rockchip_sfc *sfc = dev_get_priv(bus); + struct rockchip_sfc *sfc = dev_get_plat(bus); int ret; if (speed > sfc->max_freq) @@ -609,7 +609,7 @@ static int rockchip_sfc_set_speed(struct udevice *bus, uint speed) } sfc->speed = speed; #else - dev_dbg(sfc->dev, "sfc failed, CLK not support\n", __func__); + dev_dbg(sfc->dev, "sfc failed, CLK not support\n"); #endif return 0; } This "works", but now I'm getting a MASSIVE performance regression. => sf test 0xc0 0x40 SPI flash test: 0 erase: 91154 ticks, 44 KiB/s 0.352 Mbps 1 check: 94878 ticks, 43 KiB/s 0.344 Mbps 2 write: 199305 ticks, 20 KiB/s 0.160 Mbps 3 read: 94808 ticks, 43 KiB/s 0.344 Mbps Test passed Reads used to be on the order of 5MB/s and writes, while slower, were still considerably faster. I try it with sf test too: => sf probe 4:0 5000 SF: Detected w25q256fw with page size 256 Bytes, erase size 4 KiB, total 32 MiB => sf test 0xc0 0x40 SPI flash test: 0 erase: 32778 ticks, 124 KiB/s 0.992 Mbps 1 check: 688 ticks, 5953 KiB/s 47.624 Mbps 2 write: 7760 ticks, 527 KiB/s 4.216 Mbps 3 read: 672 ticks, 6095 KiB/s 48.760 Mbps Test passed 0 erase: 32778 ticks, 124 KiB/s 0.992 Mbps 1 check: 688 ticks, 5953 KiB/s 47.624 Mbps 2 write: 7760 ticks, 527 KiB/s 4.216 Mbps 3 read: 672 ticks, 6095 KiB/s 48.760 Mbps => sf probe 4:0 1 SF: Detected w25q256fw with page size 256 Bytes, erase size 4 KiB, total 32 MiB => sf test 0xc0 0x40 SPI flash test: 0 erase: 32730 ticks, 125 KiB/s 1.000 Mbps 1 check: 355 ticks, 11538 KiB/s 92.304 Mbps 2 write: 7414 ticks, 552 KiB/s 4.416 Mbps 3 read: 340 ticks, 12047 KiB/s 96.376 Mbps Test passed 0 erase: 32730 ticks, 125 KiB/s 1.000 Mbps 1 check: 355 ticks, 11538 KiB/s 92.304 Mbps 2 write: 7414 ticks, 552 KiB/s 4.416 Mbps 3 read: 340 ticks, 12047 KiB/s 96.376 Mbps => with main feature: - dma enable - tx/rx single line If you need any more test, You can check with me further. I think you should first confirm the IO actual speed and the actual bottleneck. On 2021/8/13 3:13, Chris Morgan wrote: On Thu, Aug 12, 2021 at 09:15:14PM +0800, Jon Lin wrote: From: Chris Morgan This patch adds support for the Rockchip serial flash controller found on the PX30 SoC. It should work for versions 3-5 of the SFC IP, however I am only able to test it on v3. This is adapted from the WIP SPI-MEM driver for the SFC on mainline Linux. Note that the main difference between this and earlier versions of the driver is that this one does not support DMA. In testing the performance difference (performing a dual mode read on a 128Mb chip) is negligible. DMA, if used, must also be disabled in SPL mode when using A-TF anyway. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- I'll need to debug it further, but unfortunately this is not working for me. On my Odroid Go Advance I get a "Synchronous Abort" error when I attempt to do an "sf probe". This same sequence (boot, then do sf probe) has worked on all prior revisions without a crash. U-Boot TPL board init DDR3, 333MHz BW=32 Col=10 Bk=8 CS0 Row=15 CS=1 Die BW=16 Size=1024MB out U-Boot SPL 2021.10-rc1+ (Aug 12 2021 - 14:03:30 -0500) Trying to boot from MMC1 NOTICE: BL31: v2.5(release):v2.5-284-g87311b4c1 NOTICE: BL31: Built : 10:43:59, Aug 5 2021 U-Boot 2021.10-rc1+ (Aug 12 2021 - 14:03:30 -0500) Model: ODROID-GO Advance DRAM: 1022 MiB PMIC: RK8170 (on=0x80, off=0x04) MMC: dwmmc@ff37: 0 Loading Environment from FAT... Unable to read "uboot.env" from mmc0:1... In:serial@ff16 Out: serial@ff16 Err: serial@ff16 Model: ODROID-GO Advance Hit any key to stop autoboot: 0 switch to partitions #0, OK mmc0 is current device Scanning mmc 0:1... MMC Device 1 not found no mmc device at slot 1 starting USB... Bus usb@ff30: probe failed, error -2 No working controllers found USB is stopped. Please issue 'usb start' first. => sf probe "Synchronous Abort" handler, esr 0x9610 elr: 0022d730 lr : 0022d72c (reloc) elr: 3ff85730 lr : 3ff8572c x0 : x1 : 066ff300 x2 : 3ff85714 x3 : x4 : 3ffccd1d x5 : 006e x6 : 3ffba6d8 x7 : 0044 x8 : 000a x9 : 0008 x10: 0034 x11: 0003 x12: x13
Re: [PATCH v8 1/5] spi: rockchip_sfc: add support for Rockchip SFC
On 2021/8/16 23:22, Chris Morgan wrote: On Mon, Aug 16, 2021 at 09:00:59PM +0800, Jon Lin wrote: On 2021/8/14 0:48, Chris Morgan wrote: On Fri, Aug 13, 2021 at 09:53:03AM +0800, Jon Lin wrote: Here is the point, Can you take a try. diff --git a/drivers/spi/rockchip_sfc.c b/drivers/spi/rockchip_sfc.c index 8173724ecd..33c5344c70 100644 --- a/drivers/spi/rockchip_sfc.c +++ b/drivers/spi/rockchip_sfc.c @@ -591,7 +591,7 @@ static int rockchip_sfc_adjust_op_size(struct spi_slave *mem, struct spi_mem_op static int rockchip_sfc_set_speed(struct udevice *bus, uint speed) { - struct rockchip_sfc *sfc = dev_get_priv(bus); + struct rockchip_sfc *sfc = dev_get_plat(bus); int ret; if (speed > sfc->max_freq) @@ -609,7 +609,7 @@ static int rockchip_sfc_set_speed(struct udevice *bus, uint speed) } sfc->speed = speed; #else - dev_dbg(sfc->dev, "sfc failed, CLK not support\n", __func__); + dev_dbg(sfc->dev, "sfc failed, CLK not support\n"); #endif return 0; } This "works", but now I'm getting a MASSIVE performance regression. => sf test 0xc0 0x40 SPI flash test: 0 erase: 91154 ticks, 44 KiB/s 0.352 Mbps 1 check: 94878 ticks, 43 KiB/s 0.344 Mbps 2 write: 199305 ticks, 20 KiB/s 0.160 Mbps 3 read: 94808 ticks, 43 KiB/s 0.344 Mbps Test passed Reads used to be on the order of 5MB/s and writes, while slower, were still considerably faster. I try it with sf test too: => sf probe 4:0 5000 SF: Detected w25q256fw with page size 256 Bytes, erase size 4 KiB, total 32 MiB => sf test 0xc0 0x40 SPI flash test: 0 erase: 32778 ticks, 124 KiB/s 0.992 Mbps 1 check: 688 ticks, 5953 KiB/s 47.624 Mbps 2 write: 7760 ticks, 527 KiB/s 4.216 Mbps 3 read: 672 ticks, 6095 KiB/s 48.760 Mbps Test passed 0 erase: 32778 ticks, 124 KiB/s 0.992 Mbps 1 check: 688 ticks, 5953 KiB/s 47.624 Mbps 2 write: 7760 ticks, 527 KiB/s 4.216 Mbps 3 read: 672 ticks, 6095 KiB/s 48.760 Mbps => sf probe 4:0 1 SF: Detected w25q256fw with page size 256 Bytes, erase size 4 KiB, total 32 MiB => sf test 0xc0 0x40 SPI flash test: 0 erase: 32730 ticks, 125 KiB/s 1.000 Mbps 1 check: 355 ticks, 11538 KiB/s 92.304 Mbps 2 write: 7414 ticks, 552 KiB/s 4.416 Mbps 3 read: 340 ticks, 12047 KiB/s 96.376 Mbps Test passed 0 erase: 32730 ticks, 125 KiB/s 1.000 Mbps 1 check: 355 ticks, 11538 KiB/s 92.304 Mbps 2 write: 7414 ticks, 552 KiB/s 4.416 Mbps 3 read: 340 ticks, 12047 KiB/s 96.376 Mbps => with main feature: - dma enable - tx/rx single line I blame myself as I think I was using the wrong patch series for testing. Let's look at the possibility of rebasing if there are any more changes to be made as it looks like some of this has already been added to mainline. I went through my divergence from mainline a bit at a time and found the following. With just the patch applied from here (necessary to make the board boot): https://patchwork.ozlabs.org/project/uboot/cover/20210805164848.21001-1-macroalph...@gmail.com/ => sf test 0xc0 0x40 SPI flash test: 0 erase: 86593 ticks, 47 KiB/s 0.376 Mbps 1 check: 407 ticks, 10063 KiB/s 80.504 Mbps 2 write: 4800 ticks, 853 KiB/s 6.824 Mbps 3 read: 337 ticks, 12154 KiB/s 97.232 Mbps Test passed Modified the devicetree to match exactly what is proposed for the upstream Linux implementation (so there is no divergence at all in the devicetree, at least for the sfc node and flash node). => sf test 0xc0 0x40 SPI flash test: 0 erase: 88896 ticks, 46 KiB/s 0.368 Mbps 1 check: 408 ticks, 10039 KiB/s 80.312 Mbps 2 write: 4769 ticks, 858 KiB/s 6.864 Mbps 3 read: 337 ticks, 12154 KiB/s 97.232 Mbps Test passed Added the "sfc-no-dma" parameter so that we can boot entirely off of the SFC. => sf test 0xc0 0x40 SPI flash test: 0 erase: 89125 ticks, 45 KiB/s 0.360 Mbps 1 check: 407 ticks, 10063 KiB/s 80.504 Mbps 2 write: 4761 ticks, 860 KiB/s 6.880 Mbps 3 read: 337 ticks, 12154 KiB/s 97.232 Mbps Test passed So I assume I was doing something wrong in my testing. Again, since a good portion of this is now upstream, can we rebase if there are any more changes though? Thank you again for all your hard work on this. I've upstreamed the deference between [V8 RFC] with master branch. https://patchwork.ozlabs.org/project/uboot/patch/20210817093621.1.Id0647655ab4060f95c9a49fe834465bbe39b8d31@changeid/ So Chris please check it again. If you need any more test, You can check with me further. I think you should first confirm the IO actual speed and the actual bottleneck. On 2021/8/13 3:13, Chris Morgan wrote: On Thu, Aug 12, 2021 at 09:15:14PM +0800, Jon Lin wrote: From: Chris Morgan This patch adds support for the Rockchip serial flash controller found on the PX30 SoC. It should work for versions 3-5 of the SFC IP, however I am only able to test it on v3. This is adapted from the WIP SPI-MEM driver for the SFC
[PATCH 1/3] spi: rockchip_sfc: Impletment set_speed logic
Set clock related processing into set_speed logic. And Optimize printing format. Signed-off-by: Jon Lin --- drivers/spi/rockchip_sfc.c | 83 ++ 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/drivers/spi/rockchip_sfc.c b/drivers/spi/rockchip_sfc.c index 4e2b861f22..2028b28e26 100644 --- a/drivers/spi/rockchip_sfc.c +++ b/drivers/spi/rockchip_sfc.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -116,6 +117,7 @@ /* Master trigger */ #define SFC_DMA_TRIGGER0x80 +#define SFC_DMA_TRIGGER_START 1 /* Src or Dst addr for master */ #define SFC_DMA_ADDR 0x84 @@ -163,14 +165,12 @@ #define SFC_DMA_TRANS_THRETHOLD(0x40) /* Maximum clock values from datasheet suggest keeping clock value under - * 150MHz. No minimum or average value is suggested, but the U-boot BSP driver - * has a minimum of 10MHz and a default of 80MHz which seems reasonable. + * 150MHz. No minimum or average value is suggested. */ -#define SFC_MIN_SPEED_HZ (10 * 1000 * 1000) -#define SFC_DEFAULT_SPEED_HZ (80 * 1000 * 1000) -#define SFC_MAX_SPEED_HZ (150 * 1000 * 1000) +#define SFC_MAX_SPEED (150 * 1000 * 1000) struct rockchip_sfc { + struct udevice *dev; void __iomem *regbase; struct clk hclk; struct clk clk; @@ -197,8 +197,6 @@ static int rockchip_sfc_reset(struct rockchip_sfc *sfc) /* Still need to clear the masked interrupt from RISR */ writel(0x, sfc->regbase + SFC_ICLR); - debug("reset\n"); - return err; } @@ -261,15 +259,11 @@ static int rockchip_sfc_probe(struct udevice *bus) #if CONFIG_IS_ENABLED(CLK) ret = clk_enable(>hclk); if (ret) - debug("Enable ahb clock fail %s: %d\n", bus->name, ret); + dev_dbg(sfc->dev, "sfc Enable ahb clock fail %s: %d\n", bus->name, ret); ret = clk_enable(>clk); if (ret) - debug("Enable clock fail for %s: %d\n", bus->name, ret); - - ret = clk_set_rate(>clk, SFC_DEFAULT_SPEED_HZ); - if (ret) - debug("Could not set sfc clock for %s: %d\n", bus->name, ret); + dev_dbg(sfc->dev, "sfc Enable clock fail for %s: %d\n", bus->name, ret); #endif ret = rockchip_sfc_init(sfc); @@ -278,7 +272,8 @@ static int rockchip_sfc_probe(struct udevice *bus) sfc->max_iosize = rockchip_sfc_get_max_iosize(sfc); sfc->version = rockchip_sfc_get_version(sfc); - sfc->speed = SFC_DEFAULT_SPEED_HZ; + sfc->max_freq = SFC_MAX_SPEED; + sfc->dev = bus; return 0; @@ -411,11 +406,11 @@ static int rockchip_sfc_xfer_setup(struct rockchip_sfc *sfc, ctrl |= SFC_CTRL_PHASE_SEL_NEGETIVE; cmd |= plat->cs << SFC_CMD_CS_SHIFT; - debug("addr.nbytes=%x(x%d) dummy.nbytes=%x(x%d)\n", - op->addr.nbytes, op->addr.buswidth, - op->dummy.nbytes, op->dummy.buswidth); - debug("ctrl=%x cmd=%x addr=%llx len=%x\n", - ctrl, cmd, op->addr.val, len); + dev_dbg(sfc->dev, "sfc addr.nbytes=%x(x%d) dummy.nbytes=%x(x%d)\n", + op->addr.nbytes, op->addr.buswidth, + op->dummy.nbytes, op->dummy.buswidth); + dev_dbg(sfc->dev, "sfc ctrl=%x cmd=%x addr=%llx len=%x\n", + ctrl, cmd, op->addr.val, len); writel(ctrl, sfc->regbase + SFC_CTRL); writel(cmd, sfc->regbase + SFC_CMD); @@ -492,7 +487,7 @@ static int rockchip_sfc_fifo_transfer_dma(struct rockchip_sfc *sfc, dma_addr_t d { writel(0x, sfc->regbase + SFC_ICLR); writel((u32)dma_buf, sfc->regbase + SFC_DMA_ADDR); - writel(0x1, sfc->regbase + SFC_DMA_TRIGGER); + writel(SFC_DMA_TRIGGER_START, sfc->regbase + SFC_DMA_TRIGGER); return len; } @@ -500,7 +495,7 @@ static int rockchip_sfc_fifo_transfer_dma(struct rockchip_sfc *sfc, dma_addr_t d static int rockchip_sfc_xfer_data_poll(struct rockchip_sfc *sfc, const struct spi_mem_op *op, u32 len) { - debug("xfer_poll len=%x\n", len); + dev_dbg(sfc->dev, "sfc xfer_poll len=%x\n", len); if (op->data.dir == SPI_MEM_DATA_OUT) return rockchip_sfc_write_fifo(sfc, op->data.buf.out, len); @@ -516,7 +511,7 @@ static int rockchip_sfc_xfer_data_dma(struct rockchip_sfc *sfc, void *dma_buf; int ret; - debug("xfer_dma len=%x\n", len); + dev_dbg(sfc->dev, "sfc xfer_dma len=%x\n", len); if (op->data.dir == SPI_MEM_DATA_OUT) { dma_buf = (void *)op->dat
[PATCH 3/3] rockchip: px30: Change sfc node to match upstream linux proposed
TX single line is more compatible for corresponding board Signed-off-by: Jon Lin --- arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi | 2 +- arch/arm/dts/rk3326-odroid-go2.dts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi b/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi index 741e8dd935..0990005a15 100644 --- a/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi +++ b/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi @@ -70,7 +70,7 @@ u-boot,dm-pre-reloc; }; -_flash { +&{/sfc@ff3a/flash@0} { u-boot,dm-pre-reloc; }; diff --git a/arch/arm/dts/rk3326-odroid-go2.dts b/arch/arm/dts/rk3326-odroid-go2.dts index 6f91f5040b..57e7f409d8 100644 --- a/arch/arm/dts/rk3326-odroid-go2.dts +++ b/arch/arm/dts/rk3326-odroid-go2.dts @@ -629,7 +629,7 @@ reg = <0>; spi-max-frequency = <10800>; spi-rx-bus-width = <2>; - spi-tx-bus-width = <2>; + spi-tx-bus-width = <1>; }; }; -- 2.17.1
[PATCH 2/3] spi: rockchip_sfc: Using read_poll
Using read_poll logic. Signed-off-by: Jon Lin --- drivers/spi/rockchip_sfc.c | 67 -- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/drivers/spi/rockchip_sfc.c b/drivers/spi/rockchip_sfc.c index 2028b28e26..33c5344c70 100644 --- a/drivers/spi/rockchip_sfc.c +++ b/drivers/spi/rockchip_sfc.c @@ -286,33 +286,38 @@ err_init: return ret; } -static inline int rockchip_sfc_get_fifo_level(struct rockchip_sfc *sfc, int wr) +static int rockchip_sfc_wait_txfifo_ready(struct rockchip_sfc *sfc, u32 timeout_us) { - u32 fsr = readl(sfc->regbase + SFC_FSR); - int level; + int ret = 0; + u32 status; - if (wr) - level = (fsr & SFC_FSR_TXLV_MASK) >> SFC_FSR_TXLV_SHIFT; - else - level = (fsr & SFC_FSR_RXLV_MASK) >> SFC_FSR_RXLV_SHIFT; + ret = readl_poll_timeout(sfc->regbase + SFC_FSR, status, +status & SFC_FSR_TXLV_MASK, +timeout_us); + if (ret) { + dev_dbg(sfc->dev, "sfc wait tx fifo timeout\n"); + + ret = -ETIMEDOUT; + } - return level; + return (status & SFC_FSR_TXLV_MASK) >> SFC_FSR_TXLV_SHIFT; } -static int rockchip_sfc_wait_fifo_ready(struct rockchip_sfc *sfc, int wr, u32 timeout) +static int rockchip_sfc_wait_rxfifo_ready(struct rockchip_sfc *sfc, u32 timeout_us) { - unsigned long tbase = get_timer(0); - int level; + int ret = 0; + u32 status; - while (!(level = rockchip_sfc_get_fifo_level(sfc, wr))) { - if (get_timer(tbase) > timeout) { - debug("%s fifo timeout\n", wr ? "write" : "read"); - return -ETIMEDOUT; - } - udelay(1); + ret = readl_poll_timeout(sfc->regbase + SFC_FSR, status, +status & SFC_FSR_RXLV_MASK, +timeout_us); + if (ret) { + dev_dbg(sfc->dev, "sfc wait rx fifo timeout\n"); + + ret = -ETIMEDOUT; } - return level; + return (status & SFC_FSR_RXLV_MASK) >> SFC_FSR_RXLV_SHIFT; } static void rockchip_sfc_adjust_op_work(struct spi_mem_op *op) @@ -430,7 +435,7 @@ static int rockchip_sfc_write_fifo(struct rockchip_sfc *sfc, const u8 *buf, int dwords = len >> 2; while (dwords) { - tx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_CMD_DIR_WR, 1000); + tx_level = rockchip_sfc_wait_txfifo_ready(sfc, 1000); if (tx_level < 0) return tx_level; write_words = min_t(u32, tx_level, dwords); @@ -441,7 +446,7 @@ static int rockchip_sfc_write_fifo(struct rockchip_sfc *sfc, const u8 *buf, int /* write the rest non word aligned bytes */ if (bytes) { - tx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_CMD_DIR_WR, 1000); + tx_level = rockchip_sfc_wait_txfifo_ready(sfc, 1000); if (tx_level < 0) return tx_level; memcpy(, buf, bytes); @@ -462,7 +467,7 @@ static int rockchip_sfc_read_fifo(struct rockchip_sfc *sfc, u8 *buf, int len) /* word aligned access only */ dwords = len >> 2; while (dwords) { - rx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_CMD_DIR_RD, 1000); + rx_level = rockchip_sfc_wait_rxfifo_ready(sfc, 1000); if (rx_level < 0) return rx_level; read_words = min_t(u32, rx_level, dwords); @@ -473,7 +478,7 @@ static int rockchip_sfc_read_fifo(struct rockchip_sfc *sfc, u8 *buf, int len) /* read the rest non word aligned bytes */ if (bytes) { - rx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_CMD_DIR_RD, 1000); + rx_level = rockchip_sfc_wait_rxfifo_ready(sfc, 1000); if (rx_level < 0) return rx_level; tmp = readl(sfc->regbase + SFC_DATA); @@ -534,19 +539,17 @@ static int rockchip_sfc_xfer_data_dma(struct rockchip_sfc *sfc, static int rockchip_sfc_xfer_done(struct rockchip_sfc *sfc, u32 timeout_us) { - unsigned long tbase = get_timer(0); int ret = 0; - u32 timeout = timeout_us; - - while (readl(sfc->regbase + SFC_SR) & SFC_SR_IS_BUSY) { - if (get_timer(tbase) > timeout) { - printf("wait sfc idle timeout\n"); - rockchip_sfc_reset(sfc); + u32 status; - return -ETIMEDOUT; - } + ret = readl_poll_timeout(sfc->regbase + SFC_SR, status, +!(status & SFC_SR_IS_BU
[PATCH v3 2/2] spi: rockchip_sfc: Using read_poll
Using read_poll logic. Tested-by: Chris Morgan Signed-off-by: Jon Lin --- (no changes since v2) Changes in v2: - Fix assigned but never used return error codes drivers/spi/rockchip_sfc.c | 67 -- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/drivers/spi/rockchip_sfc.c b/drivers/spi/rockchip_sfc.c index 94222df5ce..e098ac 100644 --- a/drivers/spi/rockchip_sfc.c +++ b/drivers/spi/rockchip_sfc.c @@ -285,33 +285,38 @@ err_init: return ret; } -static inline int rockchip_sfc_get_fifo_level(struct rockchip_sfc *sfc, int wr) +static int rockchip_sfc_wait_txfifo_ready(struct rockchip_sfc *sfc, u32 timeout_us) { - u32 fsr = readl(sfc->regbase + SFC_FSR); - int level; + int ret = 0; + u32 status; - if (wr) - level = (fsr & SFC_FSR_TXLV_MASK) >> SFC_FSR_TXLV_SHIFT; - else - level = (fsr & SFC_FSR_RXLV_MASK) >> SFC_FSR_RXLV_SHIFT; + ret = readl_poll_timeout(sfc->regbase + SFC_FSR, status, +status & SFC_FSR_TXLV_MASK, +timeout_us); + if (ret) { + dev_dbg(sfc->dev, "sfc wait tx fifo timeout\n"); + + return -ETIMEDOUT; + } - return level; + return (status & SFC_FSR_TXLV_MASK) >> SFC_FSR_TXLV_SHIFT; } -static int rockchip_sfc_wait_fifo_ready(struct rockchip_sfc *sfc, int wr, u32 timeout) +static int rockchip_sfc_wait_rxfifo_ready(struct rockchip_sfc *sfc, u32 timeout_us) { - unsigned long tbase = get_timer(0); - int level; + int ret = 0; + u32 status; - while (!(level = rockchip_sfc_get_fifo_level(sfc, wr))) { - if (get_timer(tbase) > timeout) { - debug("%s fifo timeout\n", wr ? "write" : "read"); - return -ETIMEDOUT; - } - udelay(1); + ret = readl_poll_timeout(sfc->regbase + SFC_FSR, status, +status & SFC_FSR_RXLV_MASK, +timeout_us); + if (ret) { + dev_dbg(sfc->dev, "sfc wait rx fifo timeout\n"); + + return -ETIMEDOUT; } - return level; + return (status & SFC_FSR_RXLV_MASK) >> SFC_FSR_RXLV_SHIFT; } static void rockchip_sfc_adjust_op_work(struct spi_mem_op *op) @@ -429,7 +434,7 @@ static int rockchip_sfc_write_fifo(struct rockchip_sfc *sfc, const u8 *buf, int dwords = len >> 2; while (dwords) { - tx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_CMD_DIR_WR, 1000); + tx_level = rockchip_sfc_wait_txfifo_ready(sfc, 1000); if (tx_level < 0) return tx_level; write_words = min_t(u32, tx_level, dwords); @@ -440,7 +445,7 @@ static int rockchip_sfc_write_fifo(struct rockchip_sfc *sfc, const u8 *buf, int /* write the rest non word aligned bytes */ if (bytes) { - tx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_CMD_DIR_WR, 1000); + tx_level = rockchip_sfc_wait_txfifo_ready(sfc, 1000); if (tx_level < 0) return tx_level; memcpy(, buf, bytes); @@ -461,7 +466,7 @@ static int rockchip_sfc_read_fifo(struct rockchip_sfc *sfc, u8 *buf, int len) /* word aligned access only */ dwords = len >> 2; while (dwords) { - rx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_CMD_DIR_RD, 1000); + rx_level = rockchip_sfc_wait_rxfifo_ready(sfc, 1000); if (rx_level < 0) return rx_level; read_words = min_t(u32, rx_level, dwords); @@ -472,7 +477,7 @@ static int rockchip_sfc_read_fifo(struct rockchip_sfc *sfc, u8 *buf, int len) /* read the rest non word aligned bytes */ if (bytes) { - rx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_CMD_DIR_RD, 1000); + rx_level = rockchip_sfc_wait_rxfifo_ready(sfc, 1000); if (rx_level < 0) return rx_level; tmp = readl(sfc->regbase + SFC_DATA); @@ -533,19 +538,17 @@ static int rockchip_sfc_xfer_data_dma(struct rockchip_sfc *sfc, static int rockchip_sfc_xfer_done(struct rockchip_sfc *sfc, u32 timeout_us) { - unsigned long tbase = get_timer(0); int ret = 0; - u32 timeout = timeout_us; - - while (readl(sfc->regbase + SFC_SR) & SFC_SR_IS_BUSY) { - if (get_timer(tbase) > timeout) { - printf("wait sfc idle timeout\n"); - rockchip_sfc_reset(sfc); + u32 status; - return -ETIMEDOUT; - } + ret = readl_pol
[PATCH v3 1/2] spi: rockchip_sfc: Implement set_speed logic
Set clock related processing into set_speed logic. And Optimize printing format. Tested-by: Chris Morgan Signed-off-by: Jon Lin --- Changes in v3: - Remove useless headfile - Fix misspelling drivers/spi/rockchip_sfc.c | 82 ++ 1 file changed, 39 insertions(+), 43 deletions(-) diff --git a/drivers/spi/rockchip_sfc.c b/drivers/spi/rockchip_sfc.c index 4e2b861f22..94222df5ce 100644 --- a/drivers/spi/rockchip_sfc.c +++ b/drivers/spi/rockchip_sfc.c @@ -116,6 +116,7 @@ /* Master trigger */ #define SFC_DMA_TRIGGER0x80 +#define SFC_DMA_TRIGGER_START 1 /* Src or Dst addr for master */ #define SFC_DMA_ADDR 0x84 @@ -163,14 +164,12 @@ #define SFC_DMA_TRANS_THRETHOLD(0x40) /* Maximum clock values from datasheet suggest keeping clock value under - * 150MHz. No minimum or average value is suggested, but the U-boot BSP driver - * has a minimum of 10MHz and a default of 80MHz which seems reasonable. + * 150MHz. No minimum or average value is suggested. */ -#define SFC_MIN_SPEED_HZ (10 * 1000 * 1000) -#define SFC_DEFAULT_SPEED_HZ (80 * 1000 * 1000) -#define SFC_MAX_SPEED_HZ (150 * 1000 * 1000) +#define SFC_MAX_SPEED (150 * 1000 * 1000) struct rockchip_sfc { + struct udevice *dev; void __iomem *regbase; struct clk hclk; struct clk clk; @@ -197,8 +196,6 @@ static int rockchip_sfc_reset(struct rockchip_sfc *sfc) /* Still need to clear the masked interrupt from RISR */ writel(0x, sfc->regbase + SFC_ICLR); - debug("reset\n"); - return err; } @@ -261,15 +258,11 @@ static int rockchip_sfc_probe(struct udevice *bus) #if CONFIG_IS_ENABLED(CLK) ret = clk_enable(>hclk); if (ret) - debug("Enable ahb clock fail %s: %d\n", bus->name, ret); + dev_dbg(sfc->dev, "sfc Enable ahb clock fail %s: %d\n", bus->name, ret); ret = clk_enable(>clk); if (ret) - debug("Enable clock fail for %s: %d\n", bus->name, ret); - - ret = clk_set_rate(>clk, SFC_DEFAULT_SPEED_HZ); - if (ret) - debug("Could not set sfc clock for %s: %d\n", bus->name, ret); + dev_dbg(sfc->dev, "sfc Enable clock fail for %s: %d\n", bus->name, ret); #endif ret = rockchip_sfc_init(sfc); @@ -278,7 +271,8 @@ static int rockchip_sfc_probe(struct udevice *bus) sfc->max_iosize = rockchip_sfc_get_max_iosize(sfc); sfc->version = rockchip_sfc_get_version(sfc); - sfc->speed = SFC_DEFAULT_SPEED_HZ; + sfc->max_freq = SFC_MAX_SPEED; + sfc->dev = bus; return 0; @@ -411,11 +405,11 @@ static int rockchip_sfc_xfer_setup(struct rockchip_sfc *sfc, ctrl |= SFC_CTRL_PHASE_SEL_NEGETIVE; cmd |= plat->cs << SFC_CMD_CS_SHIFT; - debug("addr.nbytes=%x(x%d) dummy.nbytes=%x(x%d)\n", - op->addr.nbytes, op->addr.buswidth, - op->dummy.nbytes, op->dummy.buswidth); - debug("ctrl=%x cmd=%x addr=%llx len=%x\n", - ctrl, cmd, op->addr.val, len); + dev_dbg(sfc->dev, "sfc addr.nbytes=%x(x%d) dummy.nbytes=%x(x%d)\n", + op->addr.nbytes, op->addr.buswidth, + op->dummy.nbytes, op->dummy.buswidth); + dev_dbg(sfc->dev, "sfc ctrl=%x cmd=%x addr=%llx len=%x\n", + ctrl, cmd, op->addr.val, len); writel(ctrl, sfc->regbase + SFC_CTRL); writel(cmd, sfc->regbase + SFC_CMD); @@ -492,7 +486,7 @@ static int rockchip_sfc_fifo_transfer_dma(struct rockchip_sfc *sfc, dma_addr_t d { writel(0x, sfc->regbase + SFC_ICLR); writel((u32)dma_buf, sfc->regbase + SFC_DMA_ADDR); - writel(0x1, sfc->regbase + SFC_DMA_TRIGGER); + writel(SFC_DMA_TRIGGER_START, sfc->regbase + SFC_DMA_TRIGGER); return len; } @@ -500,7 +494,7 @@ static int rockchip_sfc_fifo_transfer_dma(struct rockchip_sfc *sfc, dma_addr_t d static int rockchip_sfc_xfer_data_poll(struct rockchip_sfc *sfc, const struct spi_mem_op *op, u32 len) { - debug("xfer_poll len=%x\n", len); + dev_dbg(sfc->dev, "sfc xfer_poll len=%x\n", len); if (op->data.dir == SPI_MEM_DATA_OUT) return rockchip_sfc_write_fifo(sfc, op->data.buf.out, len); @@ -516,7 +510,7 @@ static int rockchip_sfc_xfer_data_dma(struct rockchip_sfc *sfc, void *dma_buf; int ret; - debug("xfer_dma len=%x\n", len); + dev_dbg(sfc->dev, "sfc xfer_dma len=%x\n", len); if (op->data.dir == SPI_MEM_DATA_OUT) { dma_buf = (void *)op->dat
[PATCH v8 3/5] rockchip: px30: add the serial flash controller
From: Chris Morgan Add the serial flash controller to the devicetree for the PX30. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- (no changes since v5) Changes in v5: - px30 use "rockchip, sfc" as compatible id arch/arm/dts/px30.dtsi | 38 ++ 1 file changed, 38 insertions(+) diff --git a/arch/arm/dts/px30.dtsi b/arch/arm/dts/px30.dtsi index b6c79e7ed3..aaa8ae2235 100644 --- a/arch/arm/dts/px30.dtsi +++ b/arch/arm/dts/px30.dtsi @@ -960,6 +960,18 @@ status = "disabled"; }; + sfc: sfc@ff3a { + compatible = "rockchip,sfc"; + reg = <0x0 0xff3a 0x0 0x4000>; + interrupts = ; + clocks = < SCLK_SFC>, < HCLK_SFC>; + clock-names = "clk_sfc", "hclk_sfc"; + pinctrl-names = "default"; + pinctrl-0 = <_clk _cs _bus4>; + power-domains = < PX30_PD_MMC_NAND>; + status = "disabled"; + }; + gpu: gpu@ff40 { compatible = "rockchip,px30-mali", "arm,mali-bifrost"; reg = <0x0 0xff40 0x0 0x4000>; @@ -1926,6 +1938,32 @@ }; }; + serial_flash { + sfc_bus4: sfc-bus4 { + rockchip,pins = + <1 RK_PA0 3 _pull_none>, + <1 RK_PA1 3 _pull_none>, + <1 RK_PA2 3 _pull_none>, + <1 RK_PA3 3 _pull_none>; + }; + + sfc_bus2: sfc-bus2 { + rockchip,pins = + <1 RK_PA0 3 _pull_none>, + <1 RK_PA1 3 _pull_none>; + }; + + sfc_cs: sfc-cs { + rockchip,pins = + <1 RK_PA4 3 _pull_none>; + }; + + sfc_clk: sfc-clk { + rockchip,pins = + <1 RK_PB1 3 _pull_none>; + }; + }; + lcdc { lcdc_rgb_dclk_pin: lcdc-rgb-dclk-pin { rockchip,pins = -- 2.17.1
[RFC PATCH v8 2/6] spi: rockchip_sfc: add support for Rockchip SFC
From: Chris Morgan This patch adds support for the Rockchip serial flash controller found on the PX30 SoC. It should work for versions 3-5 of the SFC IP, however I am only able to test it on v3. This is adapted from the WIP SPI-MEM driver for the SFC on mainline Linux. Note that the main difference between this and earlier versions of the driver is that this one does not support DMA. In testing the performance difference (performing a dual mode read on a 128Mb chip) is negligible. DMA, if used, must also be disabled in SPL mode when using A-TF anyway. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- Changes in v8: - Move speed operation to set_speed logic - Use read_poll - Change debug to dev_dbg - Simply exec_op dma logic Changes in v7: - Make sfc-use-dma configurable Changes in v6: - Fix dma transfer logic - Fix the error of the way to wait for dma transfer finished status Changes in v5: - Support dma transfer - Add CONFIG_IS_ENABLED(CLK) limitation - Support spinand devices - Support SFC ver4 ver5 - Using "rockchip, sfc" as compatible id - Get clock from the index to compatible with those case which's clock-names is not parsed Changes in v4: - None Changes in v3: - Added "rockchip_sfc_adjust_op_work()" function from proposed Linux driver to fix potential issue on hardware. Note I never noticed this issue while testing, so I cannot test if it fixed any specific issue for me. - Updated of-compatible string back to "rockchip,sfc" to match what is currently proposed for upstream driver. The hardware itself has multiple versions but a register is present in the hardware that is read by the driver to set version specific functionality. - Updated px30.dtsi and rk3266-odroid-go2.dts device-trees so that sfc nodes match what is in upstream. Changes in v2: - Resending due to glitch with patch file truncating final two lines on patch 1/5 and incorrect patch version number on patch 5/5. Changes in v1: - Reworked code to utilize spi-mem framework, and based it closely off of work in progress code for mainline Linux. - Removed DMA, as it didn't offer much performance benefit for booting (in my test cases), added complexity to the code, and interfered with A-TF. - Updated the names of the bindings to match the work in progress Linux code. - Moved alias to u-boot specific device-tree for Odroid Go Advance. Alias is updated with the spi0 node pointing to the SFC to help the sf command as well as facilitate booting from the SFC. - Note 2 below no longer applies, as rebasing this off of upstream code should allow the device to work for NAND, and by utilizing the spi-mem framework it no longer has to extract the parameters drivers/spi/Kconfig| 8 + drivers/spi/Makefile | 1 + drivers/spi/rockchip_sfc.c | 646 + 3 files changed, 655 insertions(+) create mode 100644 drivers/spi/rockchip_sfc.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 5c2a60a214..e12699bec7 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -319,6 +319,14 @@ config RENESAS_RPC_SPI on Renesas RCar Gen3 SoCs. This uses driver model and requires a device tree binding to operate. +config ROCKCHIP_SFC + bool "Rockchip SFC Driver" + help + Enable the Rockchip SFC Driver for SPI NOR flash. This device is + a limited purpose SPI controller for driving NOR flash on certain + Rockchip SoCs. This uses driver model and requires a device tree + binding to operate. + config ROCKCHIP_SPI bool "Rockchip SPI driver" help diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 216e72c60f..d2f24bccef 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_PL022_SPI) += pl022_spi.o obj-$(CONFIG_SPI_QUP) += spi-qup.o obj-$(CONFIG_SPI_MXIC) += spi-mxic.o obj-$(CONFIG_RENESAS_RPC_SPI) += renesas_rpc_spi.o +obj-$(CONFIG_ROCKCHIP_SFC) += rockchip_sfc.o obj-$(CONFIG_ROCKCHIP_SPI) += rk_spi.o obj-$(CONFIG_SANDBOX_SPI) += sandbox_spi.o obj-$(CONFIG_SPI_SIFIVE) += spi-sifive.o diff --git a/drivers/spi/rockchip_sfc.c b/drivers/spi/rockchip_sfc.c new file mode 100644 index 00..8173724ecd --- /dev/null +++ b/drivers/spi/rockchip_sfc.c @@ -0,0 +1,646 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Rockchip Serial Flash Controller Driver + * + * Copyright (c) 2017-2021, Rockchip Inc. + * Author: Shawn Lin + *Chris Morgan + *Jon Lin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* System control */ +#define SFC_CTRL 0x0 +#define SFC_CTRL_PHASE_SEL_NEGETIVE BIT(1) +#define SFC_CTRL_CMD_BITS_SHIFT 8 +#define SFC_CTRL_ADDR_BITS_SHIFT 10 +#define SFC_CTRL_DATA_BITS_SHIFT 12 + +/* Interrupt mask */ +#define SFC_IMR
[RFC PATCH v8 0/6] rockchip_sfc: add support for Rockchip SFC
Changes in v8: - Move speed operation to set_speed logic - Use read_poll - Change debug to dev_dbg - Simply exec_op dma logic - Change to use tx single line to make a good compatible - Change spiflash dts node Changes in v7: - Make sfc-use-dma configurable - Make px30 SFC clock configurable Changes in v6: - Fix dma transfer logic - Fix the error of the way to wait for dma transfer finished status Changes in v5: - Support dma transfer - Add CONFIG_IS_ENABLED(CLK) limitation - Support spinand devices - Support SFC ver4 ver5 - Using "rockchip, sfc" as compatible id - Get clock from the index to compatible with those case which's clock-names is not parsed - px30 use "rockchip, sfc" as compatible id Changes in v4: - None Changes in v3: - Added "rockchip_sfc_adjust_op_work()" function from proposed Linux driver to fix potential issue on hardware. Note I never noticed this issue while testing, so I cannot test if it fixed any specific issue for me. - Updated of-compatible string back to "rockchip,sfc" to match what is currently proposed for upstream driver. The hardware itself has multiple versions but a register is present in the hardware that is read by the driver to set version specific functionality. - Updated px30.dtsi and rk3266-odroid-go2.dts device-trees so that sfc nodes match what is in upstream. Changes in v2: - Resending due to glitch with patch file truncating final two lines on patch 1/5 and incorrect patch version number on patch 5/5. Changes in v1: - Reworked code to utilize spi-mem framework, and based it closely off of work in progress code for mainline Linux. - Removed DMA, as it didn't offer much performance benefit for booting (in my test cases), added complexity to the code, and interfered with A-TF. - Updated the names of the bindings to match the work in progress Linux code. - Moved alias to u-boot specific device-tree for Odroid Go Advance. Alias is updated with the spi0 node pointing to the SFC to help the sf command as well as facilitate booting from the SFC. - Note 2 below no longer applies, as rebasing this off of upstream code should allow the device to work for NAND, and by utilizing the spi-mem framework it no longer has to extract the parameters Chris Morgan (4): spi: rockchip_sfc: add support for Rockchip SFC rockchip: px30: Add support for using SFC rockchip: px30: add the serial flash controller rockchip: px30: add support for SFC for Odroid Go Advance Jon Lin (1): rockchip: px30: Support configure SFC Tom Rini (1): CI: Update to LLVM-12 .azure-pipelines.yml | 4 +- .gitlab-ci.yml | 4 +- arch/arm/dts/px30.dtsi | 38 ++ arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi | 17 + arch/arm/dts/rk3326-odroid-go2.dts | 16 + arch/arm/mach-rockchip/px30/px30.c | 64 ++ drivers/clk/rockchip/clk_px30.c| 32 + drivers/spi/Kconfig| 8 + drivers/spi/Makefile | 1 + drivers/spi/rockchip_sfc.c | 646 + tools/docker/Dockerfile| 6 +- 11 files changed, 829 insertions(+), 7 deletions(-) create mode 100644 drivers/spi/rockchip_sfc.c -- 2.17.1
[RFC PATCH v8 1/6] CI: Update to LLVM-12
From: Tom Rini The current stable release of LLVM is 12, update to that. While at it, fix that we had not correctly upgraded to LLVM 11 previously. Signed-off-by: Tom Rini Signed-off-by: Jon Lin --- (no changes since v1) .azure-pipelines.yml| 4 ++-- .gitlab-ci.yml | 4 ++-- tools/docker/Dockerfile | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index c088e1ac99..0cf73025f7 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -2,7 +2,7 @@ variables: windows_vm: vs2017-win2016 ubuntu_vm: ubuntu-18.04 macos_vm: macOS-10.15 - ci_runner_image: trini/u-boot-gitlab-ci-runner:focal-20210609-06Jul2021 + ci_runner_image: trini/u-boot-gitlab-ci-runner:focal-20210723-04Aug2021 # Add '-u 0' options for Azure pipelines, otherwise we get "permission # denied" error when it tries to "useradd -m -u 1001 vsts_azpcontainer", # since our $(ci_runner_image) user is not root. @@ -183,7 +183,7 @@ jobs: TEST_PY_BD: "sandbox" sandbox_clang: TEST_PY_BD: "sandbox" - OVERRIDE: "-O clang-10" + OVERRIDE: "-O clang-12" sandbox_spl: TEST_PY_BD: "sandbox_spl" TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl" diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 86026a15f9..ffdeaae5a8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -2,7 +2,7 @@ # Grab our configured image. The source for this is found at: # https://source.denx.de/u-boot/gitlab-ci-runner -image: trini/u-boot-gitlab-ci-runner:focal-20210609-06Jul2021 +image: trini/u-boot-gitlab-ci-runner:focal-20210723-04Aug2021 # We run some tests in different order, to catch some failures quicker. stages: @@ -178,7 +178,7 @@ sandbox test.py: sandbox with clang test.py: variables: TEST_PY_BD: "sandbox" -OVERRIDE: "-O clang-10" +OVERRIDE: "-O clang-12" <<: *buildman_and_testpy_dfn sandbox_spl test.py: diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile index ced4457ab2..0195456dfe 100644 --- a/tools/docker/Dockerfile +++ b/tools/docker/Dockerfile @@ -2,7 +2,7 @@ # This Dockerfile is used to build an image containing basic stuff to be used # to build U-Boot and run our test suites. -FROM ubuntu:focal-20210609 +FROM ubuntu:focal-20210723 MAINTAINER Tom Rini LABEL Description=" This image is for building U-Boot inside a container" @@ -12,7 +12,7 @@ ENV DEBIAN_FRONTEND=noninteractive # Add LLVM repository RUN apt-get update && apt-get install -y gnupg2 wget xz-utils && rm -rf /var/lib/apt/lists/* RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - -RUN echo deb http://apt.llvm.org/focal/ llvm-toolchain-focal-11 main | tee /etc/apt/sources.list.d/llvm.list +RUN echo deb http://apt.llvm.org/focal/ llvm-toolchain-focal-12 main | tee /etc/apt/sources.list.d/llvm.list # Manually install the kernel.org "Crosstool" based toolchains for gcc-11.1.0 RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/11.1.0/x86_64-gcc-11.1.0-nolibc-aarch64-linux.tar.xz | tar -C /opt -xJ @@ -39,7 +39,7 @@ RUN apt-get update && apt-get install -y \ binutils-dev \ bison \ build-essential \ - clang-10 \ + clang-12 \ coreutils \ cpio \ cppcheck \ -- 2.17.1
[RFC PATCH v8 3/6] rockchip: px30: Add support for using SFC
From: Chris Morgan This patch adds support for setting the correct pin configuration for the Rockchip Serial Flash Controller found on the PX30. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin Reviewed-by: Kever Yang --- (no changes since v1) arch/arm/mach-rockchip/px30/px30.c | 64 ++ 1 file changed, 64 insertions(+) diff --git a/arch/arm/mach-rockchip/px30/px30.c b/arch/arm/mach-rockchip/px30/px30.c index 6fcef63c1b..be70d30cc8 100644 --- a/arch/arm/mach-rockchip/px30/px30.c +++ b/arch/arm/mach-rockchip/px30/px30.c @@ -51,6 +51,57 @@ struct mm_region *mem_map = px30_mem_map; #define QOS_PRIORITY_LEVEL(h, l) h) & 3) << 8) | ((l) & 3)) +/* GRF_GPIO1AL_IOMUX */ +enum { + GPIO1A3_SHIFT = 12, + GPIO1A3_MASK= 0xf << GPIO1A3_SHIFT, + GPIO1A3_GPIO= 0, + GPIO1A3_FLASH_D3, + GPIO1A3_EMMC_D3, + GPIO1A3_SFC_SIO3, + + GPIO1A2_SHIFT = 8, + GPIO1A2_MASK= 0xf << GPIO1A2_SHIFT, + GPIO1A2_GPIO= 0, + GPIO1A2_FLASH_D2, + GPIO1A2_EMMC_D2, + GPIO1A2_SFC_SIO2, + + GPIO1A1_SHIFT = 4, + GPIO1A1_MASK= 0xf << GPIO1A1_SHIFT, + GPIO1A1_GPIO= 0, + GPIO1A1_FLASH_D1, + GPIO1A1_EMMC_D1, + GPIO1A1_SFC_SIO1, + + GPIO1A0_SHIFT = 0, + GPIO1A0_MASK= 0xf << GPIO1A0_SHIFT, + GPIO1A0_GPIO= 0, + GPIO1A0_FLASH_D0, + GPIO1A0_EMMC_D0, + GPIO1A0_SFC_SIO0, +}; + +/* GRF_GPIO1AH_IOMUX */ +enum { + GPIO1A4_SHIFT = 0, + GPIO1A4_MASK= 0xf << GPIO1A4_SHIFT, + GPIO1A4_GPIO= 0, + GPIO1A4_FLASH_D4, + GPIO1A4_EMMC_D4, + GPIO1A4_SFC_CSN0, +}; + +/* GRF_GPIO1BL_IOMUX */ +enum { + GPIO1B1_SHIFT = 4, + GPIO1B1_MASK= 0xf << GPIO1B1_SHIFT, + GPIO1B1_GPIO= 0, + GPIO1B1_FLASH_RDY, + GPIO1B1_EMMC_CLKOUT, + GPIO1B1_SFC_CLK, +}; + /* GRF_GPIO1BH_IOMUX */ enum { GPIO1B7_SHIFT = 12, @@ -193,6 +244,19 @@ int arch_cpu_init(void) GPIO1D4_SDMMC_D2 << GPIO1D4_SHIFT); #endif +#ifdef CONFIG_ROCKCHIP_SFC + rk_clrsetreg(>gpio1al_iomux, +GPIO1A3_MASK | GPIO1A2_MASK | GPIO1A1_MASK | GPIO1A0_MASK, +GPIO1A3_SFC_SIO3 << GPIO1A3_SHIFT | +GPIO1A2_SFC_SIO2 << GPIO1A2_SHIFT | +GPIO1A1_SFC_SIO1 << GPIO1A1_SHIFT | +GPIO1A0_SFC_SIO0 << GPIO1A0_SHIFT); + rk_clrsetreg(>gpio1ah_iomux, GPIO1A4_MASK, +GPIO1A4_SFC_CSN0 << GPIO1A4_SHIFT); + rk_clrsetreg(>gpio1bl_iomux, GPIO1B1_MASK, +GPIO1B1_SFC_CLK << GPIO1B1_SHIFT); +#endif + #endif /* Enable PD_VO (default disable at reset) */ -- 2.17.1
[RFC PATCH v8 1/5] spi: rockchip_sfc: add support for Rockchip SFC
From: Chris Morgan This patch adds support for the Rockchip serial flash controller found on the PX30 SoC. It should work for versions 3-5 of the SFC IP, however I am only able to test it on v3. This is adapted from the WIP SPI-MEM driver for the SFC on mainline Linux. Note that the main difference between this and earlier versions of the driver is that this one does not support DMA. In testing the performance difference (performing a dual mode read on a 128Mb chip) is negligible. DMA, if used, must also be disabled in SPL mode when using A-TF anyway. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- Changes in v8: - Move speed operation to set_speed logic - Use read_poll - Change debug to dev_dbg - Simply exec_op dma logic Changes in v7: - Make sfc-use-dma configurable Changes in v6: - Fix dma transfer logic - Fix the error of the way to wait for dma transfer finished status Changes in v5: - Support dma transfer - Add CONFIG_IS_ENABLED(CLK) limitation - Support spinand devices - Support SFC ver4 ver5 - Using "rockchip, sfc" as compatible id - Get clock from the index to compatible with those case which's clock-names is not parsed Changes in v4: - None Changes in v3: - Added "rockchip_sfc_adjust_op_work()" function from proposed Linux driver to fix potential issue on hardware. Note I never noticed this issue while testing, so I cannot test if it fixed any specific issue for me. - Updated of-compatible string back to "rockchip,sfc" to match what is currently proposed for upstream driver. The hardware itself has multiple versions but a register is present in the hardware that is read by the driver to set version specific functionality. - Updated px30.dtsi and rk3266-odroid-go2.dts device-trees so that sfc nodes match what is in upstream. Changes in v2: - Resending due to glitch with patch file truncating final two lines on patch 1/5 and incorrect patch version number on patch 5/5. Changes in v1: - Reworked code to utilize spi-mem framework, and based it closely off of work in progress code for mainline Linux. - Removed DMA, as it didn't offer much performance benefit for booting (in my test cases), added complexity to the code, and interfered with A-TF. - Updated the names of the bindings to match the work in progress Linux code. - Moved alias to u-boot specific device-tree for Odroid Go Advance. Alias is updated with the spi0 node pointing to the SFC to help the sf command as well as facilitate booting from the SFC. - Note 2 below no longer applies, as rebasing this off of upstream code should allow the device to work for NAND, and by utilizing the spi-mem framework it no longer has to extract the parameters drivers/spi/Kconfig| 8 + drivers/spi/Makefile | 1 + drivers/spi/rockchip_sfc.c | 646 + 3 files changed, 655 insertions(+) create mode 100644 drivers/spi/rockchip_sfc.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 5c2a60a214..e12699bec7 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -319,6 +319,14 @@ config RENESAS_RPC_SPI on Renesas RCar Gen3 SoCs. This uses driver model and requires a device tree binding to operate. +config ROCKCHIP_SFC + bool "Rockchip SFC Driver" + help + Enable the Rockchip SFC Driver for SPI NOR flash. This device is + a limited purpose SPI controller for driving NOR flash on certain + Rockchip SoCs. This uses driver model and requires a device tree + binding to operate. + config ROCKCHIP_SPI bool "Rockchip SPI driver" help diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 216e72c60f..d2f24bccef 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_PL022_SPI) += pl022_spi.o obj-$(CONFIG_SPI_QUP) += spi-qup.o obj-$(CONFIG_SPI_MXIC) += spi-mxic.o obj-$(CONFIG_RENESAS_RPC_SPI) += renesas_rpc_spi.o +obj-$(CONFIG_ROCKCHIP_SFC) += rockchip_sfc.o obj-$(CONFIG_ROCKCHIP_SPI) += rk_spi.o obj-$(CONFIG_SANDBOX_SPI) += sandbox_spi.o obj-$(CONFIG_SPI_SIFIVE) += spi-sifive.o diff --git a/drivers/spi/rockchip_sfc.c b/drivers/spi/rockchip_sfc.c new file mode 100644 index 00..8173724ecd --- /dev/null +++ b/drivers/spi/rockchip_sfc.c @@ -0,0 +1,646 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Rockchip Serial Flash Controller Driver + * + * Copyright (c) 2017-2021, Rockchip Inc. + * Author: Shawn Lin + *Chris Morgan + *Jon Lin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* System control */ +#define SFC_CTRL 0x0 +#define SFC_CTRL_PHASE_SEL_NEGETIVE BIT(1) +#define SFC_CTRL_CMD_BITS_SHIFT 8 +#define SFC_CTRL_ADDR_BITS_SHIFT 10 +#define SFC_CTRL_DATA_BITS_SHIFT 12 + +/* Interrupt mask */ +#define SFC_IMR
[RFC PATCH v8 3/5] rockchip: px30: add the serial flash controller
From: Chris Morgan Add the serial flash controller to the devicetree for the PX30. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin Reviewed-by: Kever Yang --- (no changes since v5) Changes in v5: - px30 use "rockchip, sfc" as compatible id arch/arm/dts/px30.dtsi | 38 ++ 1 file changed, 38 insertions(+) diff --git a/arch/arm/dts/px30.dtsi b/arch/arm/dts/px30.dtsi index b6c79e7ed3..aaa8ae2235 100644 --- a/arch/arm/dts/px30.dtsi +++ b/arch/arm/dts/px30.dtsi @@ -960,6 +960,18 @@ status = "disabled"; }; + sfc: sfc@ff3a { + compatible = "rockchip,sfc"; + reg = <0x0 0xff3a 0x0 0x4000>; + interrupts = ; + clocks = < SCLK_SFC>, < HCLK_SFC>; + clock-names = "clk_sfc", "hclk_sfc"; + pinctrl-names = "default"; + pinctrl-0 = <_clk _cs _bus4>; + power-domains = < PX30_PD_MMC_NAND>; + status = "disabled"; + }; + gpu: gpu@ff40 { compatible = "rockchip,px30-mali", "arm,mali-bifrost"; reg = <0x0 0xff40 0x0 0x4000>; @@ -1926,6 +1938,32 @@ }; }; + serial_flash { + sfc_bus4: sfc-bus4 { + rockchip,pins = + <1 RK_PA0 3 _pull_none>, + <1 RK_PA1 3 _pull_none>, + <1 RK_PA2 3 _pull_none>, + <1 RK_PA3 3 _pull_none>; + }; + + sfc_bus2: sfc-bus2 { + rockchip,pins = + <1 RK_PA0 3 _pull_none>, + <1 RK_PA1 3 _pull_none>; + }; + + sfc_cs: sfc-cs { + rockchip,pins = + <1 RK_PA4 3 _pull_none>; + }; + + sfc_clk: sfc-clk { + rockchip,pins = + <1 RK_PB1 3 _pull_none>; + }; + }; + lcdc { lcdc_rgb_dclk_pin: lcdc-rgb-dclk-pin { rockchip,pins = -- 2.17.1
[RFC PATCH v8 4/5] rockchip: px30: add support for SFC for Odroid Go Advance
From: Chris Morgan The Odroid Go Advance uses a Rockchip Serial Flash Controller with an XT25F128B SPI NOR flash chip. This adds support for both. Note that while both the controller and chip support quad mode, only two lines are connected to the chip. Changing the pinctrl to bus2 and setting tx and rx lines to 2 for this reason. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- Changes in v8: - Change to use tx single line to make a good compatible - Change spiflash dts node arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi | 17 + arch/arm/dts/rk3326-odroid-go2.dts | 16 2 files changed, 33 insertions(+) diff --git a/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi b/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi index 00767d2abd..0990005a15 100644 --- a/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi +++ b/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi @@ -7,6 +7,15 @@ chosen { u-boot,spl-boot-order = }; + + aliases { + i2c0 = + i2c1 = + mmc0 = + serial1 = + serial2 = + spi0 = + }; }; { @@ -57,6 +66,14 @@ u-boot,spl-fifo-mode; }; + { + u-boot,dm-pre-reloc; +}; + +&{/sfc@ff3a/flash@0} { + u-boot,dm-pre-reloc; +}; + { clock-frequency = <2400>; u-boot,dm-pre-reloc; diff --git a/arch/arm/dts/rk3326-odroid-go2.dts b/arch/arm/dts/rk3326-odroid-go2.dts index 8cd4688c49..3866cc6612 100644 --- a/arch/arm/dts/rk3326-odroid-go2.dts +++ b/arch/arm/dts/rk3326-odroid-go2.dts @@ -617,6 +617,22 @@ status = "okay"; }; + { + pinctrl-0 = <_clk _cs _bus2>; + pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10800>; + spi-rx-bus-width = <2>; + spi-tx-bus-width = <1>; + }; +}; + { status = "okay"; }; -- 2.17.1
[RFC PATCH v8 0/5] rockchip_sfc: add support for Rockchip SFC
Changes in v8: - Move speed operation to set_speed logic - Use read_poll - Change debug to dev_dbg - Simply exec_op dma logic - Change to use tx single line to make a good compatible - Change spiflash dts node Changes in v7: - Make sfc-use-dma configurable - Make px30 SFC clock configurable Changes in v6: - Fix dma transfer logic - Fix the error of the way to wait for dma transfer finished status Changes in v5: - Support dma transfer - Add CONFIG_IS_ENABLED(CLK) limitation - Support spinand devices - Support SFC ver4 ver5 - Using "rockchip, sfc" as compatible id - Get clock from the index to compatible with those case which's clock-names is not parsed - px30 use "rockchip, sfc" as compatible id Changes in v4: - None Changes in v3: - Added "rockchip_sfc_adjust_op_work()" function from proposed Linux driver to fix potential issue on hardware. Note I never noticed this issue while testing, so I cannot test if it fixed any specific issue for me. - Updated of-compatible string back to "rockchip,sfc" to match what is currently proposed for upstream driver. The hardware itself has multiple versions but a register is present in the hardware that is read by the driver to set version specific functionality. - Updated px30.dtsi and rk3266-odroid-go2.dts device-trees so that sfc nodes match what is in upstream. Changes in v2: - Resending due to glitch with patch file truncating final two lines on patch 1/5 and incorrect patch version number on patch 5/5. Changes in v1: - Reworked code to utilize spi-mem framework, and based it closely off of work in progress code for mainline Linux. - Removed DMA, as it didn't offer much performance benefit for booting (in my test cases), added complexity to the code, and interfered with A-TF. - Updated the names of the bindings to match the work in progress Linux code. - Moved alias to u-boot specific device-tree for Odroid Go Advance. Alias is updated with the spi0 node pointing to the SFC to help the sf command as well as facilitate booting from the SFC. - Note 2 below no longer applies, as rebasing this off of upstream code should allow the device to work for NAND, and by utilizing the spi-mem framework it no longer has to extract the parameters Chris Morgan (4): spi: rockchip_sfc: add support for Rockchip SFC rockchip: px30: Add support for using SFC rockchip: px30: add the serial flash controller rockchip: px30: add support for SFC for Odroid Go Advance Jon Lin (1): rockchip: px30: Support configure SFC arch/arm/dts/px30.dtsi | 38 ++ arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi | 17 + arch/arm/dts/rk3326-odroid-go2.dts | 16 + arch/arm/mach-rockchip/px30/px30.c | 64 ++ drivers/clk/rockchip/clk_px30.c| 32 + drivers/spi/Kconfig| 8 + drivers/spi/Makefile | 1 + drivers/spi/rockchip_sfc.c | 646 + 8 files changed, 822 insertions(+) create mode 100644 drivers/spi/rockchip_sfc.c -- 2.17.1
[RFC PATCH v8 2/5] rockchip: px30: Add support for using SFC
From: Chris Morgan This patch adds support for setting the correct pin configuration for the Rockchip Serial Flash Controller found on the PX30. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin Reviewed-by: Kever Yang --- (no changes since v1) arch/arm/mach-rockchip/px30/px30.c | 64 ++ 1 file changed, 64 insertions(+) diff --git a/arch/arm/mach-rockchip/px30/px30.c b/arch/arm/mach-rockchip/px30/px30.c index 6fcef63c1b..be70d30cc8 100644 --- a/arch/arm/mach-rockchip/px30/px30.c +++ b/arch/arm/mach-rockchip/px30/px30.c @@ -51,6 +51,57 @@ struct mm_region *mem_map = px30_mem_map; #define QOS_PRIORITY_LEVEL(h, l) h) & 3) << 8) | ((l) & 3)) +/* GRF_GPIO1AL_IOMUX */ +enum { + GPIO1A3_SHIFT = 12, + GPIO1A3_MASK= 0xf << GPIO1A3_SHIFT, + GPIO1A3_GPIO= 0, + GPIO1A3_FLASH_D3, + GPIO1A3_EMMC_D3, + GPIO1A3_SFC_SIO3, + + GPIO1A2_SHIFT = 8, + GPIO1A2_MASK= 0xf << GPIO1A2_SHIFT, + GPIO1A2_GPIO= 0, + GPIO1A2_FLASH_D2, + GPIO1A2_EMMC_D2, + GPIO1A2_SFC_SIO2, + + GPIO1A1_SHIFT = 4, + GPIO1A1_MASK= 0xf << GPIO1A1_SHIFT, + GPIO1A1_GPIO= 0, + GPIO1A1_FLASH_D1, + GPIO1A1_EMMC_D1, + GPIO1A1_SFC_SIO1, + + GPIO1A0_SHIFT = 0, + GPIO1A0_MASK= 0xf << GPIO1A0_SHIFT, + GPIO1A0_GPIO= 0, + GPIO1A0_FLASH_D0, + GPIO1A0_EMMC_D0, + GPIO1A0_SFC_SIO0, +}; + +/* GRF_GPIO1AH_IOMUX */ +enum { + GPIO1A4_SHIFT = 0, + GPIO1A4_MASK= 0xf << GPIO1A4_SHIFT, + GPIO1A4_GPIO= 0, + GPIO1A4_FLASH_D4, + GPIO1A4_EMMC_D4, + GPIO1A4_SFC_CSN0, +}; + +/* GRF_GPIO1BL_IOMUX */ +enum { + GPIO1B1_SHIFT = 4, + GPIO1B1_MASK= 0xf << GPIO1B1_SHIFT, + GPIO1B1_GPIO= 0, + GPIO1B1_FLASH_RDY, + GPIO1B1_EMMC_CLKOUT, + GPIO1B1_SFC_CLK, +}; + /* GRF_GPIO1BH_IOMUX */ enum { GPIO1B7_SHIFT = 12, @@ -193,6 +244,19 @@ int arch_cpu_init(void) GPIO1D4_SDMMC_D2 << GPIO1D4_SHIFT); #endif +#ifdef CONFIG_ROCKCHIP_SFC + rk_clrsetreg(>gpio1al_iomux, +GPIO1A3_MASK | GPIO1A2_MASK | GPIO1A1_MASK | GPIO1A0_MASK, +GPIO1A3_SFC_SIO3 << GPIO1A3_SHIFT | +GPIO1A2_SFC_SIO2 << GPIO1A2_SHIFT | +GPIO1A1_SFC_SIO1 << GPIO1A1_SHIFT | +GPIO1A0_SFC_SIO0 << GPIO1A0_SHIFT); + rk_clrsetreg(>gpio1ah_iomux, GPIO1A4_MASK, +GPIO1A4_SFC_CSN0 << GPIO1A4_SHIFT); + rk_clrsetreg(>gpio1bl_iomux, GPIO1B1_MASK, +GPIO1B1_SFC_CLK << GPIO1B1_SHIFT); +#endif + #endif /* Enable PD_VO (default disable at reset) */ -- 2.17.1
[PATCH v8 2/5] rockchip: px30: Add support for using SFC
From: Chris Morgan This patch adds support for setting the correct pin configuration for the Rockchip Serial Flash Controller found on the PX30. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- (no changes since v1) arch/arm/mach-rockchip/px30/px30.c | 64 ++ 1 file changed, 64 insertions(+) diff --git a/arch/arm/mach-rockchip/px30/px30.c b/arch/arm/mach-rockchip/px30/px30.c index 6fcef63c1b..be70d30cc8 100644 --- a/arch/arm/mach-rockchip/px30/px30.c +++ b/arch/arm/mach-rockchip/px30/px30.c @@ -51,6 +51,57 @@ struct mm_region *mem_map = px30_mem_map; #define QOS_PRIORITY_LEVEL(h, l) h) & 3) << 8) | ((l) & 3)) +/* GRF_GPIO1AL_IOMUX */ +enum { + GPIO1A3_SHIFT = 12, + GPIO1A3_MASK= 0xf << GPIO1A3_SHIFT, + GPIO1A3_GPIO= 0, + GPIO1A3_FLASH_D3, + GPIO1A3_EMMC_D3, + GPIO1A3_SFC_SIO3, + + GPIO1A2_SHIFT = 8, + GPIO1A2_MASK= 0xf << GPIO1A2_SHIFT, + GPIO1A2_GPIO= 0, + GPIO1A2_FLASH_D2, + GPIO1A2_EMMC_D2, + GPIO1A2_SFC_SIO2, + + GPIO1A1_SHIFT = 4, + GPIO1A1_MASK= 0xf << GPIO1A1_SHIFT, + GPIO1A1_GPIO= 0, + GPIO1A1_FLASH_D1, + GPIO1A1_EMMC_D1, + GPIO1A1_SFC_SIO1, + + GPIO1A0_SHIFT = 0, + GPIO1A0_MASK= 0xf << GPIO1A0_SHIFT, + GPIO1A0_GPIO= 0, + GPIO1A0_FLASH_D0, + GPIO1A0_EMMC_D0, + GPIO1A0_SFC_SIO0, +}; + +/* GRF_GPIO1AH_IOMUX */ +enum { + GPIO1A4_SHIFT = 0, + GPIO1A4_MASK= 0xf << GPIO1A4_SHIFT, + GPIO1A4_GPIO= 0, + GPIO1A4_FLASH_D4, + GPIO1A4_EMMC_D4, + GPIO1A4_SFC_CSN0, +}; + +/* GRF_GPIO1BL_IOMUX */ +enum { + GPIO1B1_SHIFT = 4, + GPIO1B1_MASK= 0xf << GPIO1B1_SHIFT, + GPIO1B1_GPIO= 0, + GPIO1B1_FLASH_RDY, + GPIO1B1_EMMC_CLKOUT, + GPIO1B1_SFC_CLK, +}; + /* GRF_GPIO1BH_IOMUX */ enum { GPIO1B7_SHIFT = 12, @@ -193,6 +244,19 @@ int arch_cpu_init(void) GPIO1D4_SDMMC_D2 << GPIO1D4_SHIFT); #endif +#ifdef CONFIG_ROCKCHIP_SFC + rk_clrsetreg(>gpio1al_iomux, +GPIO1A3_MASK | GPIO1A2_MASK | GPIO1A1_MASK | GPIO1A0_MASK, +GPIO1A3_SFC_SIO3 << GPIO1A3_SHIFT | +GPIO1A2_SFC_SIO2 << GPIO1A2_SHIFT | +GPIO1A1_SFC_SIO1 << GPIO1A1_SHIFT | +GPIO1A0_SFC_SIO0 << GPIO1A0_SHIFT); + rk_clrsetreg(>gpio1ah_iomux, GPIO1A4_MASK, +GPIO1A4_SFC_CSN0 << GPIO1A4_SHIFT); + rk_clrsetreg(>gpio1bl_iomux, GPIO1B1_MASK, +GPIO1B1_SFC_CLK << GPIO1B1_SHIFT); +#endif + #endif /* Enable PD_VO (default disable at reset) */ -- 2.17.1
[PATCH v8 1/5] spi: rockchip_sfc: add support for Rockchip SFC
From: Chris Morgan This patch adds support for the Rockchip serial flash controller found on the PX30 SoC. It should work for versions 3-5 of the SFC IP, however I am only able to test it on v3. This is adapted from the WIP SPI-MEM driver for the SFC on mainline Linux. Note that the main difference between this and earlier versions of the driver is that this one does not support DMA. In testing the performance difference (performing a dual mode read on a 128Mb chip) is negligible. DMA, if used, must also be disabled in SPL mode when using A-TF anyway. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- Changes in v8: - Move speed operation to set_speed logic - Use read_poll - Change debug to dev_dbg - Simply exec_op dma logic Changes in v7: - Make sfc-use-dma configurable Changes in v6: - Fix dma transfer logic - Fix the error of the way to wait for dma transfer finished status Changes in v5: - Support dma transfer - Add CONFIG_IS_ENABLED(CLK) limitation - Support spinand devices - Support SFC ver4 ver5 - Using "rockchip, sfc" as compatible id - Get clock from the index to compatible with those case which's clock-names is not parsed Changes in v4: - None Changes in v3: - Added "rockchip_sfc_adjust_op_work()" function from proposed Linux driver to fix potential issue on hardware. Note I never noticed this issue while testing, so I cannot test if it fixed any specific issue for me. - Updated of-compatible string back to "rockchip,sfc" to match what is currently proposed for upstream driver. The hardware itself has multiple versions but a register is present in the hardware that is read by the driver to set version specific functionality. - Updated px30.dtsi and rk3266-odroid-go2.dts device-trees so that sfc nodes match what is in upstream. Changes in v2: - Resending due to glitch with patch file truncating final two lines on patch 1/5 and incorrect patch version number on patch 5/5. Changes in v1: - Reworked code to utilize spi-mem framework, and based it closely off of work in progress code for mainline Linux. - Removed DMA, as it didn't offer much performance benefit for booting (in my test cases), added complexity to the code, and interfered with A-TF. - Updated the names of the bindings to match the work in progress Linux code. - Moved alias to u-boot specific device-tree for Odroid Go Advance. Alias is updated with the spi0 node pointing to the SFC to help the sf command as well as facilitate booting from the SFC. - Note 2 below no longer applies, as rebasing this off of upstream code should allow the device to work for NAND, and by utilizing the spi-mem framework it no longer has to extract the parameters drivers/spi/Kconfig| 8 + drivers/spi/Makefile | 1 + drivers/spi/rockchip_sfc.c | 646 + 3 files changed, 655 insertions(+) create mode 100644 drivers/spi/rockchip_sfc.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 5c2a60a214..e12699bec7 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -319,6 +319,14 @@ config RENESAS_RPC_SPI on Renesas RCar Gen3 SoCs. This uses driver model and requires a device tree binding to operate. +config ROCKCHIP_SFC + bool "Rockchip SFC Driver" + help + Enable the Rockchip SFC Driver for SPI NOR flash. This device is + a limited purpose SPI controller for driving NOR flash on certain + Rockchip SoCs. This uses driver model and requires a device tree + binding to operate. + config ROCKCHIP_SPI bool "Rockchip SPI driver" help diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 216e72c60f..d2f24bccef 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_PL022_SPI) += pl022_spi.o obj-$(CONFIG_SPI_QUP) += spi-qup.o obj-$(CONFIG_SPI_MXIC) += spi-mxic.o obj-$(CONFIG_RENESAS_RPC_SPI) += renesas_rpc_spi.o +obj-$(CONFIG_ROCKCHIP_SFC) += rockchip_sfc.o obj-$(CONFIG_ROCKCHIP_SPI) += rk_spi.o obj-$(CONFIG_SANDBOX_SPI) += sandbox_spi.o obj-$(CONFIG_SPI_SIFIVE) += spi-sifive.o diff --git a/drivers/spi/rockchip_sfc.c b/drivers/spi/rockchip_sfc.c new file mode 100644 index 00..8173724ecd --- /dev/null +++ b/drivers/spi/rockchip_sfc.c @@ -0,0 +1,646 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Rockchip Serial Flash Controller Driver + * + * Copyright (c) 2017-2021, Rockchip Inc. + * Author: Shawn Lin + *Chris Morgan + *Jon Lin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* System control */ +#define SFC_CTRL 0x0 +#define SFC_CTRL_PHASE_SEL_NEGETIVE BIT(1) +#define SFC_CTRL_CMD_BITS_SHIFT 8 +#define SFC_CTRL_ADDR_BITS_SHIFT 10 +#define SFC_CTRL_DATA_BITS_SHIFT 12 + +/* Interrupt mask */ +#define SFC_IMR
[PATCH v8 0/5] rockchip_sfc: add support for Rockchip SFC
Changes in v8: - Move speed operation to set_speed logic - Use read_poll - Change debug to dev_dbg - Simply exec_op dma logic - Change to use tx single line to make a good compatible Changes in v7: - Make sfc-use-dma configurable - Make px30 SFC clock configurable Changes in v6: - Fix dma transfer logic - Fix the error of the way to wait for dma transfer finished status Changes in v5: - Support dma transfer - Add CONFIG_IS_ENABLED(CLK) limitation - Support spinand devices - Support SFC ver4 ver5 - Using "rockchip, sfc" as compatible id - Get clock from the index to compatible with those case which's clock-names is not parsed - px30 use "rockchip, sfc" as compatible id Changes in v4: - None Changes in v3: - Added "rockchip_sfc_adjust_op_work()" function from proposed Linux driver to fix potential issue on hardware. Note I never noticed this issue while testing, so I cannot test if it fixed any specific issue for me. - Updated of-compatible string back to "rockchip,sfc" to match what is currently proposed for upstream driver. The hardware itself has multiple versions but a register is present in the hardware that is read by the driver to set version specific functionality. - Updated px30.dtsi and rk3266-odroid-go2.dts device-trees so that sfc nodes match what is in upstream. Changes in v2: - Resending due to glitch with patch file truncating final two lines on patch 1/5 and incorrect patch version number on patch 5/5. Changes in v1: - Reworked code to utilize spi-mem framework, and based it closely off of work in progress code for mainline Linux. - Removed DMA, as it didn't offer much performance benefit for booting (in my test cases), added complexity to the code, and interfered with A-TF. - Updated the names of the bindings to match the work in progress Linux code. - Moved alias to u-boot specific device-tree for Odroid Go Advance. Alias is updated with the spi0 node pointing to the SFC to help the sf command as well as facilitate booting from the SFC. - Note 2 below no longer applies, as rebasing this off of upstream code should allow the device to work for NAND, and by utilizing the spi-mem framework it no longer has to extract the parameters Chris Morgan (4): spi: rockchip_sfc: add support for Rockchip SFC rockchip: px30: Add support for using SFC rockchip: px30: add the serial flash controller rockchip: px30: add support for SFC for Odroid Go Advance Jon Lin (1): rockchip: px30: Support configure SFC arch/arm/dts/px30.dtsi | 38 ++ arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi | 17 + arch/arm/dts/rk3326-odroid-go2.dts | 16 + arch/arm/mach-rockchip/px30/px30.c | 64 ++ drivers/clk/rockchip/clk_px30.c| 32 + drivers/spi/Kconfig| 8 + drivers/spi/Makefile | 1 + drivers/spi/rockchip_sfc.c | 646 + 8 files changed, 822 insertions(+) create mode 100644 drivers/spi/rockchip_sfc.c -- 2.17.1
[PATCH v8 4/5] rockchip: px30: add support for SFC for Odroid Go Advance
From: Chris Morgan The Odroid Go Advance uses a Rockchip Serial Flash Controller with an XT25F128B SPI NOR flash chip. This adds support for both. Note that while both the controller and chip support quad mode, only two lines are connected to the chip. Changing the pinctrl to bus2 and setting tx and rx lines to 2 for this reason. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- Changes in v8: - Change to use tx single line to make a good compatible arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi | 17 + arch/arm/dts/rk3326-odroid-go2.dts | 16 2 files changed, 33 insertions(+) diff --git a/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi b/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi index 00767d2abd..741e8dd935 100644 --- a/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi +++ b/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi @@ -7,6 +7,15 @@ chosen { u-boot,spl-boot-order = }; + + aliases { + i2c0 = + i2c1 = + mmc0 = + serial1 = + serial2 = + spi0 = + }; }; { @@ -57,6 +66,14 @@ u-boot,spl-fifo-mode; }; + { + u-boot,dm-pre-reloc; +}; + +_flash { + u-boot,dm-pre-reloc; +}; + { clock-frequency = <2400>; u-boot,dm-pre-reloc; diff --git a/arch/arm/dts/rk3326-odroid-go2.dts b/arch/arm/dts/rk3326-odroid-go2.dts index 8cd4688c49..57e7f409d8 100644 --- a/arch/arm/dts/rk3326-odroid-go2.dts +++ b/arch/arm/dts/rk3326-odroid-go2.dts @@ -617,6 +617,22 @@ status = "okay"; }; + { + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <_clk _cs _bus2>; + status = "okay"; + + spi_flash: xt25f128b@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10800>; + spi-rx-bus-width = <2>; + spi-tx-bus-width = <1>; + }; +}; + { status = "okay"; }; -- 2.17.1
[PATCH v8 5/5] rockchip: px30: Support configure SFC
Make px30 SFC clock configurable Signed-off-by: Jon Lin Reviewed-by: Jagan Teki --- (no changes since v7) Changes in v7: - Make px30 SFC clock configurable drivers/clk/rockchip/clk_px30.c | 32 1 file changed, 32 insertions(+) diff --git a/drivers/clk/rockchip/clk_px30.c b/drivers/clk/rockchip/clk_px30.c index 6b746f4c65..a49b6f19f4 100644 --- a/drivers/clk/rockchip/clk_px30.c +++ b/drivers/clk/rockchip/clk_px30.c @@ -581,6 +581,32 @@ static ulong px30_mmc_set_clk(struct px30_clk_priv *priv, return px30_mmc_get_clk(priv, clk_id); } +static ulong px30_sfc_get_clk(struct px30_clk_priv *priv, uint clk_id) +{ + struct px30_cru *cru = priv->cru; + u32 div, con; + + con = readl(>clksel_con[22]); + div = (con & SFC_DIV_CON_MASK) >> SFC_DIV_CON_SHIFT; + + return DIV_TO_RATE(priv->gpll_hz, div); +} + +static ulong px30_sfc_set_clk(struct px30_clk_priv *priv, + ulong clk_id, ulong set_rate) +{ + struct px30_cru *cru = priv->cru; + int src_clk_div; + + src_clk_div = DIV_ROUND_UP(priv->gpll_hz, set_rate); + rk_clrsetreg(>clksel_con[22], +SFC_PLL_SEL_MASK | SFC_DIV_CON_MASK, +0 << SFC_PLL_SEL_SHIFT | +(src_clk_div - 1) << SFC_DIV_CON_SHIFT); + + return px30_sfc_get_clk(priv, clk_id); +} + static ulong px30_pwm_get_clk(struct px30_clk_priv *priv, ulong clk_id) { struct px30_cru *cru = priv->cru; @@ -1192,6 +1218,9 @@ static ulong px30_clk_get_rate(struct clk *clk) case SCLK_EMMC_SAMPLE: rate = px30_mmc_get_clk(priv, clk->id); break; + case SCLK_SFC: + rate = px30_sfc_get_clk(priv, clk->id); + break; case SCLK_I2C0: case SCLK_I2C1: case SCLK_I2C2: @@ -1271,6 +1300,9 @@ static ulong px30_clk_set_rate(struct clk *clk, ulong rate) case SCLK_EMMC: ret = px30_mmc_set_clk(priv, clk->id, rate); break; + case SCLK_SFC: + ret = px30_sfc_set_clk(priv, clk->id, rate); + break; case SCLK_I2C0: case SCLK_I2C1: case SCLK_I2C2: -- 2.17.1
[RFC PATCH v8 4/6] rockchip: px30: add the serial flash controller
From: Chris Morgan Add the serial flash controller to the devicetree for the PX30. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin Reviewed-by: Kever Yang --- (no changes since v5) Changes in v5: - px30 use "rockchip, sfc" as compatible id arch/arm/dts/px30.dtsi | 38 ++ 1 file changed, 38 insertions(+) diff --git a/arch/arm/dts/px30.dtsi b/arch/arm/dts/px30.dtsi index b6c79e7ed3..aaa8ae2235 100644 --- a/arch/arm/dts/px30.dtsi +++ b/arch/arm/dts/px30.dtsi @@ -960,6 +960,18 @@ status = "disabled"; }; + sfc: sfc@ff3a { + compatible = "rockchip,sfc"; + reg = <0x0 0xff3a 0x0 0x4000>; + interrupts = ; + clocks = < SCLK_SFC>, < HCLK_SFC>; + clock-names = "clk_sfc", "hclk_sfc"; + pinctrl-names = "default"; + pinctrl-0 = <_clk _cs _bus4>; + power-domains = < PX30_PD_MMC_NAND>; + status = "disabled"; + }; + gpu: gpu@ff40 { compatible = "rockchip,px30-mali", "arm,mali-bifrost"; reg = <0x0 0xff40 0x0 0x4000>; @@ -1926,6 +1938,32 @@ }; }; + serial_flash { + sfc_bus4: sfc-bus4 { + rockchip,pins = + <1 RK_PA0 3 _pull_none>, + <1 RK_PA1 3 _pull_none>, + <1 RK_PA2 3 _pull_none>, + <1 RK_PA3 3 _pull_none>; + }; + + sfc_bus2: sfc-bus2 { + rockchip,pins = + <1 RK_PA0 3 _pull_none>, + <1 RK_PA1 3 _pull_none>; + }; + + sfc_cs: sfc-cs { + rockchip,pins = + <1 RK_PA4 3 _pull_none>; + }; + + sfc_clk: sfc-clk { + rockchip,pins = + <1 RK_PB1 3 _pull_none>; + }; + }; + lcdc { lcdc_rgb_dclk_pin: lcdc-rgb-dclk-pin { rockchip,pins = -- 2.17.1
[RFC PATCH v8 5/5] rockchip: px30: Support configure SFC
Make px30 SFC clock configurable Signed-off-by: Jon Lin Reviewed-by: Jagan Teki Reviewed-by: Kever Yang Reviewed-by: Philipp Tomsich --- (no changes since v7) Changes in v7: - Make px30 SFC clock configurable drivers/clk/rockchip/clk_px30.c | 32 1 file changed, 32 insertions(+) diff --git a/drivers/clk/rockchip/clk_px30.c b/drivers/clk/rockchip/clk_px30.c index 6b746f4c65..a49b6f19f4 100644 --- a/drivers/clk/rockchip/clk_px30.c +++ b/drivers/clk/rockchip/clk_px30.c @@ -581,6 +581,32 @@ static ulong px30_mmc_set_clk(struct px30_clk_priv *priv, return px30_mmc_get_clk(priv, clk_id); } +static ulong px30_sfc_get_clk(struct px30_clk_priv *priv, uint clk_id) +{ + struct px30_cru *cru = priv->cru; + u32 div, con; + + con = readl(>clksel_con[22]); + div = (con & SFC_DIV_CON_MASK) >> SFC_DIV_CON_SHIFT; + + return DIV_TO_RATE(priv->gpll_hz, div); +} + +static ulong px30_sfc_set_clk(struct px30_clk_priv *priv, + ulong clk_id, ulong set_rate) +{ + struct px30_cru *cru = priv->cru; + int src_clk_div; + + src_clk_div = DIV_ROUND_UP(priv->gpll_hz, set_rate); + rk_clrsetreg(>clksel_con[22], +SFC_PLL_SEL_MASK | SFC_DIV_CON_MASK, +0 << SFC_PLL_SEL_SHIFT | +(src_clk_div - 1) << SFC_DIV_CON_SHIFT); + + return px30_sfc_get_clk(priv, clk_id); +} + static ulong px30_pwm_get_clk(struct px30_clk_priv *priv, ulong clk_id) { struct px30_cru *cru = priv->cru; @@ -1192,6 +1218,9 @@ static ulong px30_clk_get_rate(struct clk *clk) case SCLK_EMMC_SAMPLE: rate = px30_mmc_get_clk(priv, clk->id); break; + case SCLK_SFC: + rate = px30_sfc_get_clk(priv, clk->id); + break; case SCLK_I2C0: case SCLK_I2C1: case SCLK_I2C2: @@ -1271,6 +1300,9 @@ static ulong px30_clk_set_rate(struct clk *clk, ulong rate) case SCLK_EMMC: ret = px30_mmc_set_clk(priv, clk->id, rate); break; + case SCLK_SFC: + ret = px30_sfc_set_clk(priv, clk->id, rate); + break; case SCLK_I2C0: case SCLK_I2C1: case SCLK_I2C2: -- 2.17.1
Re: [PATCH v8 1/5] spi: rockchip_sfc: add support for Rockchip SFC
Here is the point, Can you take a try. diff --git a/drivers/spi/rockchip_sfc.c b/drivers/spi/rockchip_sfc.c index 8173724ecd..33c5344c70 100644 --- a/drivers/spi/rockchip_sfc.c +++ b/drivers/spi/rockchip_sfc.c @@ -591,7 +591,7 @@ static int rockchip_sfc_adjust_op_size(struct spi_slave *mem, struct spi_mem_op static int rockchip_sfc_set_speed(struct udevice *bus, uint speed) { - struct rockchip_sfc *sfc = dev_get_priv(bus); + struct rockchip_sfc *sfc = dev_get_plat(bus); int ret; if (speed > sfc->max_freq) @@ -609,7 +609,7 @@ static int rockchip_sfc_set_speed(struct udevice *bus, uint speed) } sfc->speed = speed; #else - dev_dbg(sfc->dev, "sfc failed, CLK not support\n", __func__); + dev_dbg(sfc->dev, "sfc failed, CLK not support\n"); #endif return 0; } On 2021/8/13 3:13, Chris Morgan wrote: On Thu, Aug 12, 2021 at 09:15:14PM +0800, Jon Lin wrote: From: Chris Morgan This patch adds support for the Rockchip serial flash controller found on the PX30 SoC. It should work for versions 3-5 of the SFC IP, however I am only able to test it on v3. This is adapted from the WIP SPI-MEM driver for the SFC on mainline Linux. Note that the main difference between this and earlier versions of the driver is that this one does not support DMA. In testing the performance difference (performing a dual mode read on a 128Mb chip) is negligible. DMA, if used, must also be disabled in SPL mode when using A-TF anyway. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- I'll need to debug it further, but unfortunately this is not working for me. On my Odroid Go Advance I get a "Synchronous Abort" error when I attempt to do an "sf probe". This same sequence (boot, then do sf probe) has worked on all prior revisions without a crash. U-Boot TPL board init DDR3, 333MHz BW=32 Col=10 Bk=8 CS0 Row=15 CS=1 Die BW=16 Size=1024MB out U-Boot SPL 2021.10-rc1+ (Aug 12 2021 - 14:03:30 -0500) Trying to boot from MMC1 NOTICE: BL31: v2.5(release):v2.5-284-g87311b4c1 NOTICE: BL31: Built : 10:43:59, Aug 5 2021 U-Boot 2021.10-rc1+ (Aug 12 2021 - 14:03:30 -0500) Model: ODROID-GO Advance DRAM: 1022 MiB PMIC: RK8170 (on=0x80, off=0x04) MMC: dwmmc@ff37: 0 Loading Environment from FAT... Unable to read "uboot.env" from mmc0:1... In:serial@ff16 Out: serial@ff16 Err: serial@ff16 Model: ODROID-GO Advance Hit any key to stop autoboot: 0 switch to partitions #0, OK mmc0 is current device Scanning mmc 0:1... MMC Device 1 not found no mmc device at slot 1 starting USB... Bus usb@ff30: probe failed, error -2 No working controllers found USB is stopped. Please issue 'usb start' first. => sf probe "Synchronous Abort" handler, esr 0x9610 elr: 0022d730 lr : 0022d72c (reloc) elr: 3ff85730 lr : 3ff8572c x0 : x1 : 066ff300 x2 : 3ff85714 x3 : x4 : 3ffccd1d x5 : 006e x6 : 3ffba6d8 x7 : 0044 x8 : 000a x9 : 0008 x10: 0034 x11: 0003 x12: x13: ffd8 x14: 3df485d0 x15: 0002 x16: 3ff8ebe8 x17: 0001 x18: 3df53dd0 x19: 066ff300 x20: x21: 066ff300 x22: 3ffbdef8 x23: 1000 x24: 3df6f530 x25: 3df92e90 x26: 3ffeecc0 x27: x28: 0003 x29: 3df481c0 Code: f90013f5 2a0103f5 94003427 aa0003f4 (294c0013) Resetting CPU ... resetting ... Changes in v8: - Move speed operation to set_speed logic - Use read_poll - Change debug to dev_dbg - Simply exec_op dma logic Changes in v7: - Make sfc-use-dma configurable Changes in v6: - Fix dma transfer logic - Fix the error of the way to wait for dma transfer finished status Changes in v5: - Support dma transfer - Add CONFIG_IS_ENABLED(CLK) limitation - Support spinand devices - Support SFC ver4 ver5 - Using "rockchip, sfc" as compatible id - Get clock from the index to compatible with those case which's clock-names is not parsed Changes in v4: - None Changes in v3: - Added "rockchip_sfc_adjust_op_work()" function from proposed Linux driver to fix potential issue on hardware. Note I never noticed this issue while testing, so I cannot test if it fixed any specific issue for me. - Updated of-compatible string back to "rockchip,sfc" to match what is currently proposed for upstream driver. The hardware itself has multiple versions but a register is present in the hardware that is read by the driver to set version specific functionality. - Updated px30.dtsi and rk3266-odroid-go2.dts device-trees so that sfc nodes match what is in upstream. Changes in v2: - Resending due to glitch with patch file truncating final two lines on p
[PATCH v7 2/6] rockchip: px30: Add support for using SFC
From: Chris Morgan This patch adds support for setting the correct pin configuration for the Rockchip Serial Flash Controller found on the PX30. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- (no changes since v1) arch/arm/mach-rockchip/px30/px30.c | 64 ++ 1 file changed, 64 insertions(+) diff --git a/arch/arm/mach-rockchip/px30/px30.c b/arch/arm/mach-rockchip/px30/px30.c index 6fcef63c1b..be70d30cc8 100644 --- a/arch/arm/mach-rockchip/px30/px30.c +++ b/arch/arm/mach-rockchip/px30/px30.c @@ -51,6 +51,57 @@ struct mm_region *mem_map = px30_mem_map; #define QOS_PRIORITY_LEVEL(h, l) h) & 3) << 8) | ((l) & 3)) +/* GRF_GPIO1AL_IOMUX */ +enum { + GPIO1A3_SHIFT = 12, + GPIO1A3_MASK= 0xf << GPIO1A3_SHIFT, + GPIO1A3_GPIO= 0, + GPIO1A3_FLASH_D3, + GPIO1A3_EMMC_D3, + GPIO1A3_SFC_SIO3, + + GPIO1A2_SHIFT = 8, + GPIO1A2_MASK= 0xf << GPIO1A2_SHIFT, + GPIO1A2_GPIO= 0, + GPIO1A2_FLASH_D2, + GPIO1A2_EMMC_D2, + GPIO1A2_SFC_SIO2, + + GPIO1A1_SHIFT = 4, + GPIO1A1_MASK= 0xf << GPIO1A1_SHIFT, + GPIO1A1_GPIO= 0, + GPIO1A1_FLASH_D1, + GPIO1A1_EMMC_D1, + GPIO1A1_SFC_SIO1, + + GPIO1A0_SHIFT = 0, + GPIO1A0_MASK= 0xf << GPIO1A0_SHIFT, + GPIO1A0_GPIO= 0, + GPIO1A0_FLASH_D0, + GPIO1A0_EMMC_D0, + GPIO1A0_SFC_SIO0, +}; + +/* GRF_GPIO1AH_IOMUX */ +enum { + GPIO1A4_SHIFT = 0, + GPIO1A4_MASK= 0xf << GPIO1A4_SHIFT, + GPIO1A4_GPIO= 0, + GPIO1A4_FLASH_D4, + GPIO1A4_EMMC_D4, + GPIO1A4_SFC_CSN0, +}; + +/* GRF_GPIO1BL_IOMUX */ +enum { + GPIO1B1_SHIFT = 4, + GPIO1B1_MASK= 0xf << GPIO1B1_SHIFT, + GPIO1B1_GPIO= 0, + GPIO1B1_FLASH_RDY, + GPIO1B1_EMMC_CLKOUT, + GPIO1B1_SFC_CLK, +}; + /* GRF_GPIO1BH_IOMUX */ enum { GPIO1B7_SHIFT = 12, @@ -193,6 +244,19 @@ int arch_cpu_init(void) GPIO1D4_SDMMC_D2 << GPIO1D4_SHIFT); #endif +#ifdef CONFIG_ROCKCHIP_SFC + rk_clrsetreg(>gpio1al_iomux, +GPIO1A3_MASK | GPIO1A2_MASK | GPIO1A1_MASK | GPIO1A0_MASK, +GPIO1A3_SFC_SIO3 << GPIO1A3_SHIFT | +GPIO1A2_SFC_SIO2 << GPIO1A2_SHIFT | +GPIO1A1_SFC_SIO1 << GPIO1A1_SHIFT | +GPIO1A0_SFC_SIO0 << GPIO1A0_SHIFT); + rk_clrsetreg(>gpio1ah_iomux, GPIO1A4_MASK, +GPIO1A4_SFC_CSN0 << GPIO1A4_SHIFT); + rk_clrsetreg(>gpio1bl_iomux, GPIO1B1_MASK, +GPIO1B1_SFC_CLK << GPIO1B1_SHIFT); +#endif + #endif /* Enable PD_VO (default disable at reset) */ -- 2.17.1
[PATCH v7 5/6] rockchip: px30: add support for SFC for Odroid Go Advance
From: Chris Morgan The Odroid Go Advance uses a Rockchip Serial Flash Controller with an XT25F128B SPI NOR flash chip. This adds support for both. Note that while both the controller and chip support quad mode, only two lines are connected to the chip. Changing the pinctrl to bus2 and setting tx and rx lines to 2 for this reason. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- (no changes since v1) arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi | 17 + arch/arm/dts/rk3326-odroid-go2.dts | 16 2 files changed, 33 insertions(+) diff --git a/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi b/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi index 00767d2abd..741e8dd935 100644 --- a/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi +++ b/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi @@ -7,6 +7,15 @@ chosen { u-boot,spl-boot-order = }; + + aliases { + i2c0 = + i2c1 = + mmc0 = + serial1 = + serial2 = + spi0 = + }; }; { @@ -57,6 +66,14 @@ u-boot,spl-fifo-mode; }; + { + u-boot,dm-pre-reloc; +}; + +_flash { + u-boot,dm-pre-reloc; +}; + { clock-frequency = <2400>; u-boot,dm-pre-reloc; diff --git a/arch/arm/dts/rk3326-odroid-go2.dts b/arch/arm/dts/rk3326-odroid-go2.dts index 8cd4688c49..6f91f5040b 100644 --- a/arch/arm/dts/rk3326-odroid-go2.dts +++ b/arch/arm/dts/rk3326-odroid-go2.dts @@ -617,6 +617,22 @@ status = "okay"; }; + { + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <_clk _cs _bus2>; + status = "okay"; + + spi_flash: xt25f128b@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10800>; + spi-rx-bus-width = <2>; + spi-tx-bus-width = <2>; + }; +}; + { status = "okay"; }; -- 2.17.1
[PATCH v7 1/6] spi: rockchip_sfc: add support for Rockchip SFC
From: Chris Morgan This patch adds support for the Rockchip serial flash controller found on the PX30 SoC. It should work for versions 3-5 of the SFC IP, however I am only able to test it on v3. This is adapted from the WIP SPI-MEM driver for the SFC on mainline Linux. Note that the main difference between this and earlier versions of the driver is that this one does not support DMA. In testing the performance difference (performing a dual mode read on a 128Mb chip) is negligible. DMA, if used, must also be disabled in SPL mode when using A-TF anyway. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- Changes in v7: - Make sfc-use-dma configurable Changes in v6: - Fix dma transfer logic - Fix the error of the way to wait for dma transfer finished status Changes in v5: - Support dma transfer - Add CONFIG_IS_ENABLED(CLK) limitation - Support spinand devices - Support SFC ver4 ver5 - Using "rockchip, sfc" as compatible id - Get clock from the index to compatible with those case which's clock-names is not parsed Changes in v4: - None Changes in v3: - Added "rockchip_sfc_adjust_op_work()" function from proposed Linux driver to fix potential issue on hardware. Note I never noticed this issue while testing, so I cannot test if it fixed any specific issue for me. - Updated of-compatible string back to "rockchip,sfc" to match what is currently proposed for upstream driver. The hardware itself has multiple versions but a register is present in the hardware that is read by the driver to set version specific functionality. - Updated px30.dtsi and rk3266-odroid-go2.dts device-trees so that sfc nodes match what is in upstream. Changes in v2: - Resending due to glitch with patch file truncating final two lines on patch 1/5 and incorrect patch version number on patch 5/5. Changes in v1: - Reworked code to utilize spi-mem framework, and based it closely off of work in progress code for mainline Linux. - Removed DMA, as it didn't offer much performance benefit for booting (in my test cases), added complexity to the code, and interfered with A-TF. - Updated the names of the bindings to match the work in progress Linux code. - Moved alias to u-boot specific device-tree for Odroid Go Advance. Alias is updated with the spi0 node pointing to the SFC to help the sf command as well as facilitate booting from the SFC. - Note 2 below no longer applies, as rebasing this off of upstream code should allow the device to work for NAND, and by utilizing the spi-mem framework it no longer has to extract the parameters drivers/spi/Kconfig| 8 + drivers/spi/Makefile | 1 + drivers/spi/rockchip_sfc.c | 646 + 3 files changed, 655 insertions(+) create mode 100644 drivers/spi/rockchip_sfc.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 5c2a60a214..e12699bec7 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -319,6 +319,14 @@ config RENESAS_RPC_SPI on Renesas RCar Gen3 SoCs. This uses driver model and requires a device tree binding to operate. +config ROCKCHIP_SFC + bool "Rockchip SFC Driver" + help + Enable the Rockchip SFC Driver for SPI NOR flash. This device is + a limited purpose SPI controller for driving NOR flash on certain + Rockchip SoCs. This uses driver model and requires a device tree + binding to operate. + config ROCKCHIP_SPI bool "Rockchip SPI driver" help diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 216e72c60f..d2f24bccef 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_PL022_SPI) += pl022_spi.o obj-$(CONFIG_SPI_QUP) += spi-qup.o obj-$(CONFIG_SPI_MXIC) += spi-mxic.o obj-$(CONFIG_RENESAS_RPC_SPI) += renesas_rpc_spi.o +obj-$(CONFIG_ROCKCHIP_SFC) += rockchip_sfc.o obj-$(CONFIG_ROCKCHIP_SPI) += rk_spi.o obj-$(CONFIG_SANDBOX_SPI) += sandbox_spi.o obj-$(CONFIG_SPI_SIFIVE) += spi-sifive.o diff --git a/drivers/spi/rockchip_sfc.c b/drivers/spi/rockchip_sfc.c new file mode 100644 index 00..4e2b861f22 --- /dev/null +++ b/drivers/spi/rockchip_sfc.c @@ -0,0 +1,646 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Rockchip Serial Flash Controller Driver + * + * Copyright (c) 2017-2021, Rockchip Inc. + * Author: Shawn Lin + *Chris Morgan + *Jon Lin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* System control */ +#define SFC_CTRL 0x0 +#define SFC_CTRL_PHASE_SEL_NEGETIVE BIT(1) +#define SFC_CTRL_CMD_BITS_SHIFT 8 +#define SFC_CTRL_ADDR_BITS_SHIFT 10 +#define SFC_CTRL_DATA_BITS_SHIFT 12 + +/* Interrupt mask */ +#define SFC_IMR0x4 +#define SFC_IMR_RX_FULL BIT(0) +#define SFC_IMR_RX_UFLOW BIT(1) +#define SFC_IMR_TX_OF
[PATCH v7 0/6] rockchip_sfc: add support for Rockchip SFC
Changes in v7: - Make sfc-use-dma configurable - Remove SPI_NOR_HAS_TB and SPI_NOR_HAS_LOCK - Make px30 SFC clock configurable Changes in v6: - Fix dma transfer logic - Fix the error of the way to wait for dma transfer finished status Changes in v5: - Support dma transfer - Add CONFIG_IS_ENABLED(CLK) limitation - Support spinand devices - Support SFC ver4 ver5 - Using "rockchip, sfc" as compatible id - Get clock from the index to compatible with those case which's clock-names is not parsed - px30 use "rockchip, sfc" as compatible id Changes in v4: - None Changes in v3: - Added "rockchip_sfc_adjust_op_work()" function from proposed Linux driver to fix potential issue on hardware. Note I never noticed this issue while testing, so I cannot test if it fixed any specific issue for me. - Updated of-compatible string back to "rockchip,sfc" to match what is currently proposed for upstream driver. The hardware itself has multiple versions but a register is present in the hardware that is read by the driver to set version specific functionality. - Updated px30.dtsi and rk3266-odroid-go2.dts device-trees so that sfc nodes match what is in upstream. Changes in v2: - Resending due to glitch with patch file truncating final two lines on patch 1/5 and incorrect patch version number on patch 5/5. Changes in v1: - Reworked code to utilize spi-mem framework, and based it closely off of work in progress code for mainline Linux. - Removed DMA, as it didn't offer much performance benefit for booting (in my test cases), added complexity to the code, and interfered with A-TF. - Updated the names of the bindings to match the work in progress Linux code. - Moved alias to u-boot specific device-tree for Odroid Go Advance. Alias is updated with the spi0 node pointing to the SFC to help the sf command as well as facilitate booting from the SFC. - Note 2 below no longer applies, as rebasing this off of upstream code should allow the device to work for NAND, and by utilizing the spi-mem framework it no longer has to extract the parameters Chris Morgan (5): spi: rockchip_sfc: add support for Rockchip SFC rockchip: px30: Add support for using SFC rockchip: px30: add the serial flash controller mtd: spi-nor-ids: Add XTX XT25F128B rockchip: px30: add support for SFC for Odroid Go Advance Jon Lin (1): rockchip: px30: Support configure SFC arch/arm/dts/px30.dtsi | 38 ++ arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi | 17 + arch/arm/dts/rk3326-odroid-go2.dts | 16 + arch/arm/mach-rockchip/px30/px30.c | 64 ++ drivers/clk/rockchip/clk_px30.c| 32 + drivers/mtd/spi/Kconfig| 6 + drivers/mtd/spi/spi-nor-ids.c | 4 + drivers/spi/Kconfig| 8 + drivers/spi/Makefile | 1 + drivers/spi/rockchip_sfc.c | 646 + 10 files changed, 832 insertions(+) create mode 100644 drivers/spi/rockchip_sfc.c -- 2.17.1
[PATCH v7 3/6] rockchip: px30: add the serial flash controller
From: Chris Morgan Add the serial flash controller to the devicetree for the PX30. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- (no changes since v5) Changes in v5: - px30 use "rockchip, sfc" as compatible id arch/arm/dts/px30.dtsi | 38 ++ 1 file changed, 38 insertions(+) diff --git a/arch/arm/dts/px30.dtsi b/arch/arm/dts/px30.dtsi index b6c79e7ed3..aaa8ae2235 100644 --- a/arch/arm/dts/px30.dtsi +++ b/arch/arm/dts/px30.dtsi @@ -960,6 +960,18 @@ status = "disabled"; }; + sfc: sfc@ff3a { + compatible = "rockchip,sfc"; + reg = <0x0 0xff3a 0x0 0x4000>; + interrupts = ; + clocks = < SCLK_SFC>, < HCLK_SFC>; + clock-names = "clk_sfc", "hclk_sfc"; + pinctrl-names = "default"; + pinctrl-0 = <_clk _cs _bus4>; + power-domains = < PX30_PD_MMC_NAND>; + status = "disabled"; + }; + gpu: gpu@ff40 { compatible = "rockchip,px30-mali", "arm,mali-bifrost"; reg = <0x0 0xff40 0x0 0x4000>; @@ -1926,6 +1938,32 @@ }; }; + serial_flash { + sfc_bus4: sfc-bus4 { + rockchip,pins = + <1 RK_PA0 3 _pull_none>, + <1 RK_PA1 3 _pull_none>, + <1 RK_PA2 3 _pull_none>, + <1 RK_PA3 3 _pull_none>; + }; + + sfc_bus2: sfc-bus2 { + rockchip,pins = + <1 RK_PA0 3 _pull_none>, + <1 RK_PA1 3 _pull_none>; + }; + + sfc_cs: sfc-cs { + rockchip,pins = + <1 RK_PA4 3 _pull_none>; + }; + + sfc_clk: sfc-clk { + rockchip,pins = + <1 RK_PB1 3 _pull_none>; + }; + }; + lcdc { lcdc_rgb_dclk_pin: lcdc-rgb-dclk-pin { rockchip,pins = -- 2.17.1
[PATCH v7 6/6] rockchip: px30: Support configure SFC
Make px30 SFC clock configurable Signed-off-by: Jon Lin --- Changes in v7: - Make px30 SFC clock configurable drivers/clk/rockchip/clk_px30.c | 32 1 file changed, 32 insertions(+) diff --git a/drivers/clk/rockchip/clk_px30.c b/drivers/clk/rockchip/clk_px30.c index 6b746f4c65..a49b6f19f4 100644 --- a/drivers/clk/rockchip/clk_px30.c +++ b/drivers/clk/rockchip/clk_px30.c @@ -581,6 +581,32 @@ static ulong px30_mmc_set_clk(struct px30_clk_priv *priv, return px30_mmc_get_clk(priv, clk_id); } +static ulong px30_sfc_get_clk(struct px30_clk_priv *priv, uint clk_id) +{ + struct px30_cru *cru = priv->cru; + u32 div, con; + + con = readl(>clksel_con[22]); + div = (con & SFC_DIV_CON_MASK) >> SFC_DIV_CON_SHIFT; + + return DIV_TO_RATE(priv->gpll_hz, div); +} + +static ulong px30_sfc_set_clk(struct px30_clk_priv *priv, + ulong clk_id, ulong set_rate) +{ + struct px30_cru *cru = priv->cru; + int src_clk_div; + + src_clk_div = DIV_ROUND_UP(priv->gpll_hz, set_rate); + rk_clrsetreg(>clksel_con[22], +SFC_PLL_SEL_MASK | SFC_DIV_CON_MASK, +0 << SFC_PLL_SEL_SHIFT | +(src_clk_div - 1) << SFC_DIV_CON_SHIFT); + + return px30_sfc_get_clk(priv, clk_id); +} + static ulong px30_pwm_get_clk(struct px30_clk_priv *priv, ulong clk_id) { struct px30_cru *cru = priv->cru; @@ -1192,6 +1218,9 @@ static ulong px30_clk_get_rate(struct clk *clk) case SCLK_EMMC_SAMPLE: rate = px30_mmc_get_clk(priv, clk->id); break; + case SCLK_SFC: + rate = px30_sfc_get_clk(priv, clk->id); + break; case SCLK_I2C0: case SCLK_I2C1: case SCLK_I2C2: @@ -1271,6 +1300,9 @@ static ulong px30_clk_set_rate(struct clk *clk, ulong rate) case SCLK_EMMC: ret = px30_mmc_set_clk(priv, clk->id, rate); break; + case SCLK_SFC: + ret = px30_sfc_set_clk(priv, clk->id, rate); + break; case SCLK_I2C0: case SCLK_I2C1: case SCLK_I2C2: -- 2.17.1
[PATCH v7 4/6] mtd: spi-nor-ids: Add XTX XT25F128B
From: Chris Morgan Adds support for XT25F128B used on Odroid Go Advance. Unfortunately this chip uses a continuation code which I cannot seem to parse, so there are possibly going to be collisions with chips that use the same manufacturer/ID. Signed-off-by: Chris Morgan Signed-off-by: Jon Lin --- Changes in v7: - Remove SPI_NOR_HAS_TB and SPI_NOR_HAS_LOCK drivers/mtd/spi/Kconfig | 6 ++ drivers/mtd/spi/spi-nor-ids.c | 4 2 files changed, 10 insertions(+) diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig index 1b2ef37e92..b2291f7290 100644 --- a/drivers/mtd/spi/Kconfig +++ b/drivers/mtd/spi/Kconfig @@ -204,6 +204,12 @@ config SPI_FLASH_XMC Add support for various XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) SPI flash chips (XM25xxx) +config SPI_FLASH_XTX + bool "XTX SPI flash support" + help + Add support for various XTX (XTX Technology Limited) + SPI flash chips (XT25xxx). + endif config SPI_FLASH_USE_4K_SECTORS diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c index cb3a08872d..4aef1ddd6e 100644 --- a/drivers/mtd/spi/spi-nor-ids.c +++ b/drivers/mtd/spi/spi-nor-ids.c @@ -361,6 +361,10 @@ const struct flash_info spi_nor_ids[] = { { INFO("XM25QH64A", 0x207017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { INFO("XM25QH64C", 0x204017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { INFO("XM25QH128A", 0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, +#endif +#ifdef CONFIG_SPI_FLASH_XTX + /* XTX Technology (Shenzhen) Limited */ + { INFO("xt25f128b", 0x0b4018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, #endif { }, }; -- 2.17.1
[PATCH v3 2/2] nvme: Fix error in nvme_setup_prps
Consulting to "NVM Express® Base Specification, revision 2.0". If more PRP List pages are required, then the last entry of the PRP List contains the Page Base Address of the next PRP List page. The next PRP List page shall be memory page aligned. Signed-off-by: Jon Lin Reviewed-by: Shawn Lin --- (no changes since v1) drivers/nvme/nvme.c | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index 9623c896a1..22ded626a5 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -100,7 +100,7 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2, } nprps = DIV_ROUND_UP(length, page_size); - num_pages = DIV_ROUND_UP(nprps, prps_per_page); + num_pages = DIV_ROUND_UP(nprps + 1, prps_per_page); if (nprps > dev->prp_entry_num) { free(dev->prp_pool); @@ -119,10 +119,11 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2, prp_pool = dev->prp_pool; i = 0; while (nprps) { - if (i == ((page_size >> 3) - 1)) { - *(prp_pool + i) = cpu_to_le64((ulong)prp_pool + + if (i == prps_per_page) { + *(prp_pool + i) = *(prp_pool + i - 1); + *(prp_pool + i - 1) = cpu_to_le64((ulong)prp_pool + page_size); - i = 0; + i = 1; prp_pool += page_size; } *(prp_pool + i++) = cpu_to_le64(dma_addr); -- 2.17.1
[PATCH v3 1/2] nvme: Enable FUA
Most NVME devcies maintain data in internal cache for an uncertain times, and u-boot has no method to force NVME to flush cache. So this patch adds FUA to avoid data loss caused by power off after data programming. Signed-off-by: Jon Lin Reviewed-by: Stefan Agner --- Changes in v3: Only enable FUA when vwc is enabled drivers/nvme/nvme.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index 3c529a2fce..9623c896a1 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -762,6 +762,10 @@ static ulong nvme_blk_rw(struct udevice *udev, lbaint_t blknr, c.rw.appmask = 0; c.rw.metadata = 0; + /* Enable FUA for data integrity if vwc is enabled */ + if (dev->vwc) + c.rw.control |= NVME_RW_FUA; + while (total_lbas) { if (total_lbas < lbas) { lbas = (u16)total_lbas; -- 2.17.1
Re: [PATCH] nvme: Enable FUA
On 2021/9/27 20:28, Stefan Agner wrote: On 2021-09-26 11:12, Jon Lin wrote: Most NVME devcies maintain data in internal cache for an uncertain times, and u-boot has no method to force NVME to flush cache. So this patch adds FUA to avoid data loss caused by power off after data programming. Maybe worth mentioning that FUA stands for Force Unit Access and makes sure that data has been written to non-volatile storage before command completion. It seems to me that volatile cache needs to be explicitly enabled by the Volatile Write Cache feature. But I guess it could be already enabled by earlier firmware/on reboot? Setting the FUA bit will make certain that data land on non-volatile storage in any case. So: Reviewed-by: Stefan Agner Out of curiosity, has this been a problem in a real world situation? We are trying to interact with the host computer in the device u-boot stage, involving nvme upgrade and device reset. When the two progress are continuous, there are corresponding problems. -- Stefan Signed-off-by: Jon Lin --- drivers/nvme/nvme.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index f6465ea7f4..5d05cb6e9e 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -761,6 +761,9 @@ static ulong nvme_blk_rw(struct udevice *udev, lbaint_t blknr, c.rw.appmask = 0; c.rw.metadata = 0; + /* Always enable FUA for data integrity */ + c.rw.control |= NVME_RW_FUA; + while (total_lbas) { if (total_lbas < lbas) { lbas = (u16)total_lbas;
[PATCH v2 1/2] nvme: Enable FUA
Most NVME devcies maintain data in internal cache for an uncertain times, and u-boot has no method to force NVME to flush cache. So this patch adds FUA to avoid data loss caused by power off after data programming. Signed-off-by: Jon Lin Reviewed-by: Stefan Agner --- (no changes since v1) drivers/nvme/nvme.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index f6465ea7f4..5d05cb6e9e 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -761,6 +761,9 @@ static ulong nvme_blk_rw(struct udevice *udev, lbaint_t blknr, c.rw.appmask = 0; c.rw.metadata = 0; + /* Always enable FUA for data integrity */ + c.rw.control |= NVME_RW_FUA; + while (total_lbas) { if (total_lbas < lbas) { lbas = (u16)total_lbas; -- 2.17.1
[PATCH v2 2/2] nvme: Fix error in nvme_setup_prps
Consulting to "NVM Express® Base Specification, revision 2.0". If more PRP List pages are required, then the last entry of the PRP List contains the Page Base Address of the next PRP List page. The next PRP List page shall be memory page aligned. Signed-off-by: Jon Lin --- (no changes since v1) drivers/nvme/nvme.c | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index 5d05cb6e9e..07d6bea83c 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -100,7 +100,7 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2, } nprps = DIV_ROUND_UP(length, page_size); - num_pages = DIV_ROUND_UP(nprps, prps_per_page); + num_pages = DIV_ROUND_UP(nprps + 1, prps_per_page); if (nprps > dev->prp_entry_num) { free(dev->prp_pool); @@ -119,10 +119,11 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2, prp_pool = dev->prp_pool; i = 0; while (nprps) { - if (i == ((page_size >> 3) - 1)) { - *(prp_pool + i) = cpu_to_le64((ulong)prp_pool + + if (i == prps_per_page) { + *(prp_pool + i) = *(prp_pool + i - 1); + *(prp_pool + i - 1) = cpu_to_le64((ulong)prp_pool + page_size); - i = 0; + i = 1; prp_pool += page_size; } *(prp_pool + i++) = cpu_to_le64(dma_addr); -- 2.17.1
[PATCH] nvme: Enable FUA
Most NVME devcies maintain data in internal cache for an uncertain times, and u-boot has no method to force NVME to flush cache. So this patch adds FUA to avoid data loss caused by power off after data programming. Signed-off-by: Jon Lin --- drivers/nvme/nvme.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index f6465ea7f4..5d05cb6e9e 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -761,6 +761,9 @@ static ulong nvme_blk_rw(struct udevice *udev, lbaint_t blknr, c.rw.appmask = 0; c.rw.metadata = 0; + /* Always enable FUA for data integrity */ + c.rw.control |= NVME_RW_FUA; + while (total_lbas) { if (total_lbas < lbas) { lbas = (u16)total_lbas; -- 2.17.1
Re: [PATCH v3 1/2] nvme: Enable FUA
On 2021/11/19 9:14, Tom Rini wrote: On Fri, Nov 19, 2021 at 08:56:08AM +0800, Bin Meng wrote: Hi Tom, On Fri, Nov 19, 2021 at 3:14 AM Tom Rini wrote: On Tue, Oct 19, 2021 at 10:40:53AM +0800, Jon Lin wrote: Most NVME devcies maintain data in internal cache for an uncertain times, and u-boot has no method to force NVME to flush cache. So this patch adds FUA to avoid data loss caused by power off after data programming. Signed-off-by: Jon Lin Reviewed-by: Stefan Agner Applied to u-boot/next, thanks! I don't see my review comment being addressed. Please drop the patch until all things are clear. Missed your comments, sorry. Thanks to bin Meng and Tom. I'm not familiar with nvme protocol. I expect people with nvme experience to take over the patch and do the most reasonable treatment. Of course, I'll take some time to seriously ponder the nvme process to see if it can meet your requirements
Re: [PATCH v1 04/11] spi: rockchip-sfc: sanity check minimum freq
在 2022/3/14 16:53, Kever Yang 写道: + Jon Lin, Hi Jon, Please help to review this patch. Thanks, - Kever On 2022/2/22 09:31, Peter Geis wrote: The rockchip-sfc driver sanity checks the maximum frequency, but not the minimum frequency. This causes the probe to fail when a frequency isn't defined, such as with `sf probe 0`. Clamp the minimum frequency to the rockchip default clock rate. Signed-off-by: Peter Geis --- drivers/spi/rockchip_sfc.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/spi/rockchip_sfc.c b/drivers/spi/rockchip_sfc.c index 851a6482985b..d0d2dc70a417 100644 --- a/drivers/spi/rockchip_sfc.c +++ b/drivers/spi/rockchip_sfc.c @@ -164,6 +164,8 @@ /* DMA is only enabled for large data transmission */ #define SFC_DMA_TRANS_THRETHOLD (0x40) +#define SFC_MIN_SPEED (24 * 1000 * 1000) + /* Maximum clock values from datasheet suggest keeping clock value under * 150MHz. No minimum or average value is suggested. */ @@ -596,6 +598,9 @@ static int rockchip_sfc_set_speed(struct udevice *bus, uint speed) if (speed > sfc->max_freq) speed = sfc->max_freq; + if (speed < SFC_MIN_SPEED) + speed = SFC_MIN_SPEED; + if (speed == sfc->speed) return 0; As I know, spi-uclass.c set SPI_DEFAULT_SPEED_HZ as default value when detect the param speed is 0. And I think, For SF probe, error reporting can better remind users to use the correct speed configuration instead of directly using the default configuration.