All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/22] sunxi: Allwinner T113s support
@ 2023-09-28 21:54 Andre Przywara
  2023-09-28 21:54 ` [PATCH v2 01/22] sunxi: remove CONFIG_SATAPWR Andre Przywara
                   ` (21 more replies)
  0 siblings, 22 replies; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

Hi,

this is an update to the Allwinner T113s support series. It addresses
some comments I got (many thanks to the reviewers!). Samuel had a mishap
where his email client ate his draft responses, so the put the gist of
his review comments in an IRC query. Most of the GPIO changes in this
series were triggered by his comments, many thanks!
The biggest change is that all low-level GPIO/pinctrl routines now live
in the GPIO driver file under drivers/gpio, that's a better place than
under board/sunxi. Also the GPIO header file saw some cleanup, many
definition are not (longer) needed outside of sunxi_gpio.c.
Based on origin/next. For a detailed changelog, see below.

===================
This series adds support for the new SoC series that covers the Allwinner
D1 siblings R528 and T113s (a version with co-packaged DRAM). They all
share the same die, although the D1 and D1s use RISC-V cores, which
requires more plumbing, to use the sunxi code across two architectures.
Getting the R528 support in should help a bit in sorting out what's new
peripheral code and what is architecture dependent. IIUC, Samuel has that
running, although with some hacks, the number of which this series tries
to reduce.

The most interesting part of this is the pincontroller rework, this
tackles two issues:
- For the first time in the history of mainline Allwinner support the
  pincontroller changed the register layout. The code here tries to
  abstract the differences away, so both variants can share the code
  peacefully.
- For the above mentioned reason, the pincontroller code is quite old,
  and is mostly spread out across arch/arm, in a pre-DM style, even
  though we have real DM support in U-Boot proper. We need the non-DM
  version for the (ARM-only?) legacy SPL, so can't get rid of that
  completely. This series also tries to modernise that code, and moves
  it into drivers/gpio, where it can be more easily shared with RISC-V.

The main feature is then of course the T113s support, of which the new
pinctroller is only one part. Apart from the new pincontroller and the
usual new SoC bits (like clock and pinmux support), this includes the
DRAM controller code.
With the basics in, we add support for the MangoPi MQ-R board, which
uses the T113s and seems to be a popular board. This should also serve
as a blueprint for supporting similar boards. The DTs are copied from
the kernel (as usual).

There are some bits missing, prominently PSCI support. There is a series
out there, which just needs some smaller fixes in some places. I expect
the PSCI support to go back-to-back with this series.

This series is based on top of current origin/next, so that should cover
some chunks of the v2024.01 merge window already.

A branch is available at:
https://source.denx.de/u-boot/custodians/u-boot-sunxi.git t113s-v2

Please have a look, review and test.

Cheers,
Andre

Changelog v2 .. v1:
- add review and test tags
- reorder pinctrl rework patches: first move shared code, then add in/out,
  then remove struct, then move headers
- move all GPIO routines into drivers/gpio/sunxi_gpio.c
- move private GPIO definitions from GPIO header file to sunxi_gpio.c
- use GPIO_NUM() instead of "% 32" directly
- define more MMIO addresses (PRCM, CPUCFG, R_PIO)
- do not enable 8-bit eMMC mode (Okhunjon)
- add eMMC pins to SPL pinmux setup (Okhunjon)
- drop patch [PATCH 13/20] sunxi: clock: h6: prepare for PRCM less SoCs
- update DT files from latest Linux kernel tree
- fix pin numbers for the UART pinmux setup
- let DRAM driver depend on ARCH_SUNXI

Andre Przywara (19):
  sunxi: remove CONFIG_SATAPWR
  net: sunxi_emac: chase DT nodes to find PHY regulator
  sunxi: remove CONFIG_MACPWR
  pinctrl: sunxi: move pinctrl code
  pinctrl: sunxi: add GPIO in/out wrappers
  pinctrl: sunxi: remove struct sunxi_gpio
  pinctrl: sunxi: remove GPIO_EXTRA_HEADER
  pinctrl: sunxi: move PIO_BASE into sunxi_gpio.h
  pinctrl: sunxi: add new D1 pinctrl support
  sunxi: introduce NCAT2 generation model
  pinctrl: sunxi: add Allwinner D1 pinctrl description
  sunxi: clock: D1/R528: Enable PLL LDO during PLL1 setup
  sunxi: clock: support D1/R528 PLL6 clock
  Kconfig: sunxi: prepare for using drivers/ram/sunxi
  sunxi: add R528/T113-s3/D1(s) DRAM initialisation code
  sunxi: add Allwinner R528/T113 SoC support
  sunxi: refactor serial base addresses to avoid asm/arch/cpu.h
  ARM: dts: sunxi: add Allwinner T113-s SoC .dtsi
  sunxi: add MangoPi MQ-R board support

Okhunjon Sobirjonov (1):
  sunxi: R528: add SMHC2 pin pull ups support

Samuel Holland (2):
  clk: sunxi: Add support for the D1 CCU
  riscv: dts: allwinner: Add the D1/D1s SoC devicetree

 arch/arm/Kconfig                              |    3 +-
 arch/arm/cpu/armv7/sunxi/sram.c               |    1 +
 arch/arm/cpu/armv8/fel_utils.S                |    1 +
 arch/arm/dts/Makefile                         |    2 +
 .../arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts |   35 +
 arch/arm/dts/sun8i-t113s.dtsi                 |   59 +
 arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi |  126 ++
 arch/arm/dts/sunxi-u-boot.dtsi                |    7 +
 arch/arm/include/asm/arch-sunxi/boot0.h       |    2 +
 arch/arm/include/asm/arch-sunxi/clock.h       |    3 +-
 .../include/asm/arch-sunxi/clock_sun50i_h6.h  |   12 +-
 arch/arm/include/asm/arch-sunxi/cpu.h         |    2 +
 arch/arm/include/asm/arch-sunxi/cpu_sun4i.h   |   17 -
 .../include/asm/arch-sunxi/cpu_sun50i_h6.h    |    7 -
 arch/arm/include/asm/arch-sunxi/cpu_sun9i.h   |    9 -
 .../include/asm/arch-sunxi/cpu_sunxi_ncat2.h  |   39 +
 arch/arm/include/asm/arch-sunxi/mmc.h         |    2 +-
 arch/arm/include/asm/arch-sunxi/prcm.h        |    2 +-
 arch/arm/include/asm/arch-sunxi/serial.h      |   32 +
 arch/arm/include/asm/arch-sunxi/timer.h       |    2 +-
 arch/arm/mach-sunxi/Kconfig                   |   44 +-
 arch/arm/mach-sunxi/Makefile                  |    2 +-
 arch/arm/mach-sunxi/board.c                   |   31 +-
 arch/arm/mach-sunxi/clock_sun50i_h6.c         |   45 +-
 arch/arm/mach-sunxi/cpu_info.c                |    2 +
 arch/arm/mach-sunxi/dram_suniv.c              |    2 +-
 arch/arm/mach-sunxi/gtbus_sun9i.c             |    1 +
 arch/arm/mach-sunxi/pinmux.c                  |   78 -
 arch/arm/mach-sunxi/spl_spi_sunxi.c           |    1 +
 arch/arm/mach-sunxi/timer.c                   |    1 +
 arch/riscv/dts/sun20i-common-regulators.dtsi  |   28 +
 arch/riscv/dts/sun20i-d1.dtsi                 |   66 +
 arch/riscv/dts/sun20i-d1s.dtsi                |   76 +
 arch/riscv/dts/sunxi-d1-t113.dtsi             |   15 +
 arch/riscv/dts/sunxi-d1s-t113.dtsi            |  927 +++++++++++
 board/sunxi/board.c                           |   34 +-
 board/sunxi/chip.c                            |    2 +-
 common/spl/Kconfig                            |    3 +-
 configs/A10-OLinuXino-Lime_defconfig          |    1 -
 configs/A20-OLinuXino-Lime2-eMMC_defconfig    |    1 -
 configs/A20-OLinuXino-Lime2_defconfig         |    1 -
 configs/A20-OLinuXino-Lime_defconfig          |    1 -
 configs/A20-OLinuXino_MICRO-eMMC_defconfig    |    1 -
 configs/A20-OLinuXino_MICRO_defconfig         |    1 -
 configs/A20-Olimex-SOM-EVB_defconfig          |    1 -
 configs/A20-Olimex-SOM204-EVB-eMMC_defconfig  |    1 -
 configs/A20-Olimex-SOM204-EVB_defconfig       |    1 -
 configs/Bananapi_M2_Ultra_defconfig           |    1 -
 configs/Bananapi_defconfig                    |    1 -
 configs/Bananapro_defconfig                   |    1 -
 configs/Cubieboard2_defconfig                 |    1 -
 configs/Cubieboard_defconfig                  |    1 -
 configs/Cubietruck_defconfig                  |    1 -
 configs/Itead_Ibox_A20_defconfig              |    1 -
 configs/Lamobo_R1_defconfig                   |    2 -
 configs/Linksprite_pcDuino3_Nano_defconfig    |    1 -
 configs/Linksprite_pcDuino3_defconfig         |    1 -
 configs/Mele_A1000_defconfig                  |    1 -
 configs/Orangepi_defconfig                    |    1 -
 configs/Orangepi_mini_defconfig               |    1 -
 configs/Sinovoip_BPI_M3_defconfig             |    1 -
 configs/bananapi_m1_plus_defconfig            |    1 -
 configs/bananapi_m2_plus_h3_defconfig         |    1 -
 configs/bananapi_m2_plus_h5_defconfig         |    1 -
 configs/i12-tvbox_defconfig                   |    1 -
 configs/jesurun_q5_defconfig                  |    1 -
 configs/mangopi_mq_r_defconfig                |   15 +
 configs/mixtile_loftq_defconfig               |    1 -
 configs/nanopi_m1_plus_defconfig              |    1 -
 configs/nanopi_neo_plus2_defconfig            |    1 -
 configs/nanopi_r1s_h5_defconfig               |    1 -
 configs/orangepi_pc2_defconfig                |    1 -
 configs/orangepi_plus2e_defconfig             |    1 -
 configs/orangepi_plus_defconfig               |    3 +-
 configs/orangepi_win_defconfig                |    1 -
 configs/pine_h64_defconfig                    |    1 -
 configs/zeropi_defconfig                      |    1 -
 drivers/Makefile                              |    1 +
 drivers/ata/ahci_sunxi.c                      |    9 +
 drivers/clk/sunxi/Kconfig                     |    7 +
 drivers/clk/sunxi/Makefile                    |    1 +
 drivers/clk/sunxi/clk_d1.c                    |   84 +
 drivers/clk/sunxi/clk_sunxi.c                 |    5 +
 drivers/gpio/axp_gpio.c                       |    1 +
 drivers/gpio/sunxi_gpio.c                     |  189 ++-
 drivers/i2c/mvtwsi.c                          |    3 +-
 drivers/i2c/sun6i_p2wi.c                      |    2 +-
 drivers/i2c/sun8i_rsb.c                       |    2 +-
 drivers/mmc/sunxi_mmc.c                       |    9 +-
 drivers/net/sun8i_emac.c                      |    9 +-
 drivers/net/sunxi_emac.c                      |   39 +
 drivers/pinctrl/sunxi/Kconfig                 |    5 +
 drivers/pinctrl/sunxi/pinctrl-sunxi.c         |   43 +-
 drivers/ram/Kconfig                           |    3 +-
 drivers/ram/Makefile                          |    3 +
 drivers/ram/sunxi/Kconfig                     |   73 +
 drivers/ram/sunxi/Makefile                    |    4 +
 drivers/ram/sunxi/dram_sun20i_d1.c            | 1432 +++++++++++++++++
 drivers/ram/sunxi/dram_sun20i_d1.h            |   73 +
 drivers/video/hitachi_tx18d42vm_lcd.c         |    1 +
 drivers/video/ssd2828.c                       |    1 -
 drivers/video/sunxi/sunxi_display.c           |    1 +
 drivers/video/sunxi/sunxi_lcd.c               |    1 +
 include/configs/sunxi-common.h                |    2 +-
 include/dt-bindings/clock/sun20i-d1-ccu.h     |  158 ++
 include/dt-bindings/clock/sun20i-d1-r-ccu.h   |   19 +
 include/dt-bindings/reset/sun20i-d1-ccu.h     |   79 +
 include/dt-bindings/reset/sun20i-d1-r-ccu.h   |   16 +
 .../arch-sunxi/gpio.h => include/sunxi_gpio.h |   83 +-
 109 files changed, 3809 insertions(+), 326 deletions(-)
 create mode 100644 arch/arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts
 create mode 100644 arch/arm/dts/sun8i-t113s.dtsi
 create mode 100644 arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi
 create mode 100644 arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
 create mode 100644 arch/arm/include/asm/arch-sunxi/serial.h
 delete mode 100644 arch/arm/mach-sunxi/pinmux.c
 create mode 100644 arch/riscv/dts/sun20i-common-regulators.dtsi
 create mode 100644 arch/riscv/dts/sun20i-d1.dtsi
 create mode 100644 arch/riscv/dts/sun20i-d1s.dtsi
 create mode 100644 arch/riscv/dts/sunxi-d1-t113.dtsi
 create mode 100644 arch/riscv/dts/sunxi-d1s-t113.dtsi
 create mode 100644 configs/mangopi_mq_r_defconfig
 create mode 100644 drivers/clk/sunxi/clk_d1.c
 create mode 100644 drivers/ram/sunxi/Kconfig
 create mode 100644 drivers/ram/sunxi/Makefile
 create mode 100644 drivers/ram/sunxi/dram_sun20i_d1.c
 create mode 100644 drivers/ram/sunxi/dram_sun20i_d1.h
 create mode 100644 include/dt-bindings/clock/sun20i-d1-ccu.h
 create mode 100644 include/dt-bindings/clock/sun20i-d1-r-ccu.h
 create mode 100644 include/dt-bindings/reset/sun20i-d1-ccu.h
 create mode 100644 include/dt-bindings/reset/sun20i-d1-r-ccu.h
 rename arch/arm/include/asm/arch-sunxi/gpio.h => include/sunxi_gpio.h (75%)

-- 
2.35.8


^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v2 01/22] sunxi: remove CONFIG_SATAPWR
  2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
@ 2023-09-28 21:54 ` Andre Przywara
  2023-10-19 23:51   ` Samuel Holland
  2023-09-28 21:54 ` [PATCH v2 02/22] net: sunxi_emac: chase DT nodes to find PHY regulator Andre Przywara
                   ` (20 subsequent siblings)
  21 siblings, 1 reply; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

The CONFIG_SATAPWR Kconfig symbol was used to point to a GPIO that
enables the power for a SATA harddisk.
In the DT this is described with the target-supply property in the AHCI
DT node, pointing to a (GPIO controlled) regulator. Since we need SATA
only in U-Boot proper, and use a DM driver for AHCI there, we should use
the DT instead of hardcoding this.

Add code to the sunxi AHCI driver to check the DT for that regulator and
enable it, at probe time. Then drop the current code from board.c, which
was doing that job before.
This allows us to remove the SATAPWR Kconfig definition and the
respective values from the defconfigs.
We also select the generic fixed regulator driver, which handles those
GPIO controlled regulators.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Sam Edwards <CFSworks@gmail.com>
---
 arch/arm/Kconfig                             |  2 ++
 arch/arm/mach-sunxi/Kconfig                  |  8 --------
 board/sunxi/board.c                          | 16 +---------------
 configs/A10-OLinuXino-Lime_defconfig         |  1 -
 configs/A20-OLinuXino-Lime2-eMMC_defconfig   |  1 -
 configs/A20-OLinuXino-Lime2_defconfig        |  1 -
 configs/A20-OLinuXino-Lime_defconfig         |  1 -
 configs/A20-OLinuXino_MICRO-eMMC_defconfig   |  1 -
 configs/A20-OLinuXino_MICRO_defconfig        |  1 -
 configs/A20-Olimex-SOM-EVB_defconfig         |  1 -
 configs/A20-Olimex-SOM204-EVB-eMMC_defconfig |  1 -
 configs/A20-Olimex-SOM204-EVB_defconfig      |  1 -
 configs/Cubieboard2_defconfig                |  1 -
 configs/Cubieboard_defconfig                 |  1 -
 configs/Cubietruck_defconfig                 |  1 -
 configs/Itead_Ibox_A20_defconfig             |  1 -
 configs/Lamobo_R1_defconfig                  |  1 -
 configs/Linksprite_pcDuino3_Nano_defconfig   |  1 -
 configs/Linksprite_pcDuino3_defconfig        |  1 -
 configs/Sinovoip_BPI_M3_defconfig            |  1 -
 configs/orangepi_plus_defconfig              |  2 +-
 drivers/ata/ahci_sunxi.c                     |  9 +++++++++
 22 files changed, 13 insertions(+), 41 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 71f820e443b..3fac92ebfcc 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1158,6 +1158,8 @@ config ARCH_SUNXI
 	imply CMD_GPT
 	imply CMD_UBI if MTD_RAW_NAND
 	imply DISTRO_DEFAULTS
+	imply DM_REGULATOR
+	imply DM_REGULATOR_FIXED
 	imply FAT_WRITE
 	imply FIT
 	imply OF_LIBFDT_OVERLAY
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 9d5df2c1027..1b24dfe4dd1 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -1008,14 +1008,6 @@ config VIDEO_LCD_TL059WV5C0
 
 endchoice
 
-config SATAPWR
-	string "SATA power pin"
-	default ""
-	help
-	  Set the pins used to power the SATA. This takes a string in the
-	  format understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of
-	  port H.
-
 config GMAC_TX_DELAY
 	int "GMAC Transmit Clock Delay Chain"
 	default 0
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index ebaa9431984..50a60e760d4 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -187,7 +187,7 @@ enum env_location env_get_location(enum env_operation op, int prio)
 /* add board specific code here */
 int board_init(void)
 {
-	__maybe_unused int id_pfr1, ret, satapwr_pin, macpwr_pin;
+	__maybe_unused int id_pfr1, ret, macpwr_pin;
 
 	gd->bd->bi_boot_params = (PHYS_SDRAM_0 + 0x100);
 
@@ -225,20 +225,6 @@ int board_init(void)
 		return ret;
 
 	/* strcmp() would look better, but doesn't get optimised away. */
-	if (CONFIG_SATAPWR[0]) {
-		satapwr_pin = sunxi_name_to_gpio(CONFIG_SATAPWR);
-		if (satapwr_pin >= 0) {
-			gpio_request(satapwr_pin, "satapwr");
-			gpio_direction_output(satapwr_pin, 1);
-
-			/*
-			 * Give the attached SATA device time to power-up
-			 * to avoid link timeouts
-			 */
-			mdelay(500);
-		}
-	}
-
 	if (CONFIG_MACPWR[0]) {
 		macpwr_pin = sunxi_name_to_gpio(CONFIG_MACPWR);
 		if (macpwr_pin >= 0) {
diff --git a/configs/A10-OLinuXino-Lime_defconfig b/configs/A10-OLinuXino-Lime_defconfig
index df4fdfaba41..57e91d0f017 100644
--- a/configs/A10-OLinuXino-Lime_defconfig
+++ b/configs/A10-OLinuXino-Lime_defconfig
@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=480
 CONFIG_DRAM_EMR1=4
 CONFIG_SYS_CLK_FREQ=912000000
 CONFIG_I2C1_ENABLE=y
-CONFIG_SATAPWR="PC3"
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL_I2C=y
diff --git a/configs/A20-OLinuXino-Lime2-eMMC_defconfig b/configs/A20-OLinuXino-Lime2-eMMC_defconfig
index be49e9323a1..44770ffb048 100644
--- a/configs/A20-OLinuXino-Lime2-eMMC_defconfig
+++ b/configs/A20-OLinuXino-Lime2-eMMC_defconfig
@@ -8,7 +8,6 @@ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_USB0_VBUS_PIN="PC17"
 CONFIG_USB0_VBUS_DET="PH5"
 CONFIG_I2C1_ENABLE=y
-CONFIG_SATAPWR="PC3"
 CONFIG_SPL_SPI_SUNXI=y
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/A20-OLinuXino-Lime2_defconfig b/configs/A20-OLinuXino-Lime2_defconfig
index 43cd28c3dd0..e10660c933c 100644
--- a/configs/A20-OLinuXino-Lime2_defconfig
+++ b/configs/A20-OLinuXino-Lime2_defconfig
@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
 CONFIG_USB0_VBUS_PIN="PC17"
 CONFIG_USB0_VBUS_DET="PH5"
 CONFIG_I2C1_ENABLE=y
-CONFIG_SATAPWR="PC3"
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL_I2C=y
diff --git a/configs/A20-OLinuXino-Lime_defconfig b/configs/A20-OLinuXino-Lime_defconfig
index 7c77f38fba6..4ed666a034a 100644
--- a/configs/A20-OLinuXino-Lime_defconfig
+++ b/configs/A20-OLinuXino-Lime_defconfig
@@ -5,7 +5,6 @@ CONFIG_SPL=y
 CONFIG_MACH_SUN7I=y
 CONFIG_DRAM_CLK=384
 CONFIG_I2C1_ENABLE=y
-CONFIG_SATAPWR="PC3"
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL_I2C=y
diff --git a/configs/A20-OLinuXino_MICRO-eMMC_defconfig b/configs/A20-OLinuXino_MICRO-eMMC_defconfig
index 02116995a3e..ca5869f43d9 100644
--- a/configs/A20-OLinuXino_MICRO-eMMC_defconfig
+++ b/configs/A20-OLinuXino_MICRO-eMMC_defconfig
@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_I2C1_ENABLE=y
 CONFIG_VIDEO_VGA=y
-CONFIG_SATAPWR="PB8"
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL_I2C=y
diff --git a/configs/A20-OLinuXino_MICRO_defconfig b/configs/A20-OLinuXino_MICRO_defconfig
index 895e8dbcbd2..db4270f9b27 100644
--- a/configs/A20-OLinuXino_MICRO_defconfig
+++ b/configs/A20-OLinuXino_MICRO_defconfig
@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
 CONFIG_MMC_SUNXI_SLOT_EXTRA=3
 CONFIG_I2C1_ENABLE=y
 CONFIG_VIDEO_VGA=y
-CONFIG_SATAPWR="PB8"
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL_I2C=y
diff --git a/configs/A20-Olimex-SOM-EVB_defconfig b/configs/A20-Olimex-SOM-EVB_defconfig
index 5bcc9f9f3c0..ac900477d1e 100644
--- a/configs/A20-Olimex-SOM-EVB_defconfig
+++ b/configs/A20-Olimex-SOM-EVB_defconfig
@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
 CONFIG_MMC_SUNXI_SLOT_EXTRA=3
 CONFIG_USB0_VBUS_PIN="PB9"
 CONFIG_USB0_VBUS_DET="PH5"
-CONFIG_SATAPWR="PC3"
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL_I2C=y
diff --git a/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig b/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
index e5881090dda..00a98140b37 100644
--- a/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
+++ b/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
@@ -8,7 +8,6 @@ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_USB0_VBUS_PIN="PC17"
 CONFIG_USB0_VBUS_DET="PH5"
 CONFIG_I2C1_ENABLE=y
-CONFIG_SATAPWR="PC3"
 CONFIG_GMAC_TX_DELAY=4
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/A20-Olimex-SOM204-EVB_defconfig b/configs/A20-Olimex-SOM204-EVB_defconfig
index 592a79a6c7e..f4ae3ae6d8b 100644
--- a/configs/A20-Olimex-SOM204-EVB_defconfig
+++ b/configs/A20-Olimex-SOM204-EVB_defconfig
@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
 CONFIG_USB0_VBUS_PIN="PC17"
 CONFIG_USB0_VBUS_DET="PH5"
 CONFIG_I2C1_ENABLE=y
-CONFIG_SATAPWR="PC3"
 CONFIG_GMAC_TX_DELAY=4
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/Cubieboard2_defconfig b/configs/Cubieboard2_defconfig
index 0c233687413..ef4f11b7c62 100644
--- a/configs/Cubieboard2_defconfig
+++ b/configs/Cubieboard2_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-cubieboard2"
 CONFIG_SPL=y
 CONFIG_MACH_SUN7I=y
 CONFIG_DRAM_CLK=480
-CONFIG_SATAPWR="PB8"
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL_I2C=y
diff --git a/configs/Cubieboard_defconfig b/configs/Cubieboard_defconfig
index 71743f7b8a1..ab3f65ad667 100644
--- a/configs/Cubieboard_defconfig
+++ b/configs/Cubieboard_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-cubieboard"
 CONFIG_SPL=y
 CONFIG_MACH_SUN4I=y
 CONFIG_DRAM_CLK=480
-CONFIG_SATAPWR="PB8"
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL_I2C=y
diff --git a/configs/Cubietruck_defconfig b/configs/Cubietruck_defconfig
index 184f305b19d..184143d7086 100644
--- a/configs/Cubietruck_defconfig
+++ b/configs/Cubietruck_defconfig
@@ -8,7 +8,6 @@ CONFIG_USB0_VBUS_PIN="PH17"
 CONFIG_USB0_VBUS_DET="PH22"
 CONFIG_USB0_ID_DET="PH19"
 CONFIG_VIDEO_VGA=y
-CONFIG_SATAPWR="PH12"
 CONFIG_GMAC_TX_DELAY=1
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/Itead_Ibox_A20_defconfig b/configs/Itead_Ibox_A20_defconfig
index 5d05f337982..d03fa62196b 100644
--- a/configs/Itead_Ibox_A20_defconfig
+++ b/configs/Itead_Ibox_A20_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-itead-ibox"
 CONFIG_SPL=y
 CONFIG_MACH_SUN7I=y
 CONFIG_DRAM_CLK=480
-CONFIG_SATAPWR="PB8"
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL_I2C=y
diff --git a/configs/Lamobo_R1_defconfig b/configs/Lamobo_R1_defconfig
index 5294608459b..9639cb6aad9 100644
--- a/configs/Lamobo_R1_defconfig
+++ b/configs/Lamobo_R1_defconfig
@@ -5,7 +5,6 @@ CONFIG_SPL=y
 CONFIG_MACH_SUN7I=y
 CONFIG_DRAM_CLK=432
 CONFIG_MACPWR="PH23"
-CONFIG_SATAPWR="PB3"
 CONFIG_GMAC_TX_DELAY=4
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/Linksprite_pcDuino3_Nano_defconfig b/configs/Linksprite_pcDuino3_Nano_defconfig
index e3e30a49490..9eb9a918aee 100644
--- a/configs/Linksprite_pcDuino3_Nano_defconfig
+++ b/configs/Linksprite_pcDuino3_Nano_defconfig
@@ -6,7 +6,6 @@ CONFIG_MACH_SUN7I=y
 CONFIG_DRAM_CLK=408
 CONFIG_DRAM_ZQ=122
 CONFIG_USB1_VBUS_PIN="PH11"
-CONFIG_SATAPWR="PH2"
 CONFIG_GMAC_TX_DELAY=3
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/Linksprite_pcDuino3_defconfig b/configs/Linksprite_pcDuino3_defconfig
index 1fda0db4c9d..7db10e685bc 100644
--- a/configs/Linksprite_pcDuino3_defconfig
+++ b/configs/Linksprite_pcDuino3_defconfig
@@ -5,7 +5,6 @@ CONFIG_SPL=y
 CONFIG_MACH_SUN7I=y
 CONFIG_DRAM_CLK=480
 CONFIG_DRAM_ZQ=122
-CONFIG_SATAPWR="PH2"
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL_I2C=y
diff --git a/configs/Sinovoip_BPI_M3_defconfig b/configs/Sinovoip_BPI_M3_defconfig
index 5642e52ec50..ad41dbd26a1 100644
--- a/configs/Sinovoip_BPI_M3_defconfig
+++ b/configs/Sinovoip_BPI_M3_defconfig
@@ -12,7 +12,6 @@ CONFIG_USB0_VBUS_PIN="AXP0-VBUS-ENABLE"
 CONFIG_USB0_ID_DET="PH11"
 CONFIG_USB1_VBUS_PIN="PD24"
 CONFIG_AXP_GPIO=y
-CONFIG_SATAPWR="PD25"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_CONSOLE_MUX=y
 CONFIG_PHY_REALTEK=y
diff --git a/configs/orangepi_plus_defconfig b/configs/orangepi_plus_defconfig
index 76de72aa228..ed585881d49 100644
--- a/configs/orangepi_plus_defconfig
+++ b/configs/orangepi_plus_defconfig
@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=672
 CONFIG_MACPWR="PD6"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_USB1_VBUS_PIN="PG13"
-CONFIG_SATAPWR="PG11"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL_I2C=y
 CONFIG_SPL_SYS_I2C_LEGACY=y
@@ -16,3 +15,4 @@ CONFIG_SUN8I_EMAC=y
 CONFIG_SY8106A_POWER=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_OHCI_HCD=y
+CONFIG_USB3_VBUS_PIN="PG11"
diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c
index 94a3379c532..9064774e661 100644
--- a/drivers/ata/ahci_sunxi.c
+++ b/drivers/ata/ahci_sunxi.c
@@ -7,6 +7,7 @@
 #include <asm/io.h>
 #include <asm/gpio.h>
 #include <linux/delay.h>
+#include <power/regulator.h>
 
 #define AHCI_PHYCS0R 0x00c0
 #define AHCI_PHYCS1R 0x00c4
@@ -74,6 +75,7 @@ static int sunxi_ahci_phy_init(u8 *reg_base)
 
 static int sunxi_sata_probe(struct udevice *dev)
 {
+	struct udevice *reg_dev;
 	ulong base;
 	u8 *reg;
 	int ret;
@@ -89,6 +91,13 @@ static int sunxi_sata_probe(struct udevice *dev)
 		debug("%s: Failed to init phy (err=%d)\n", __func__, ret);
 		return ret;
 	}
+
+	ret = device_get_supply_regulator(dev, "target-supply", &reg_dev);
+	if (ret == 0) {
+		regulator_set_enable(reg_dev, true);
+		mdelay(500);
+	}
+
 	ret = ahci_probe_scsi(dev, base);
 	if (ret) {
 		debug("%s: Failed to probe (err=%d)\n", __func__, ret);
-- 
2.35.8


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 02/22] net: sunxi_emac: chase DT nodes to find PHY regulator
  2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
  2023-09-28 21:54 ` [PATCH v2 01/22] sunxi: remove CONFIG_SATAPWR Andre Przywara
@ 2023-09-28 21:54 ` Andre Przywara
  2023-10-20  0:01   ` Samuel Holland
  2023-09-28 21:54 ` [PATCH v2 03/22] sunxi: remove CONFIG_MACPWR Andre Przywara
                   ` (19 subsequent siblings)
  21 siblings, 1 reply; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

At the moment the sun4i EMAC driver relies on hardcoded CONFIG_MACPWR
Kconfig symbols to enable potential PHY regulators. As we want to get rid
of those, we need to find the regulator by chasing up the DT.

The sun4i-emac binding puts the PHY regulator into the MDIO node, which
is the parent of the PHY device. U-Boot does not have (and does not
need) an MDIO driver, so we need to chase down the regulator through the
EMAC node: we follow the "phy-handle" property to find the PHY node,
then go up to its parent, where we find the "phy-supply" link to the
regulator. Let U-Boot find the associated regulator device, and put that
into the private device struct, so we can find and enable the regulator
at probe time, later.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Sam Edwards <CFSworks@gmail.com>
---
 drivers/net/sunxi_emac.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c
index 4c90d4b4981..f1f0e5bbbb2 100644
--- a/drivers/net/sunxi_emac.c
+++ b/drivers/net/sunxi_emac.c
@@ -17,6 +17,7 @@
 #include <net.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
+#include <power/regulator.h>
 
 /* EMAC register  */
 struct emac_regs {
@@ -165,6 +166,7 @@ struct emac_eth_dev {
 	struct phy_device *phydev;
 	int link_printed;
 	uchar rx_buf[EMAC_RX_BUFSIZE];
+	struct udevice *phy_reg;
 };
 
 struct emac_rxhdr {
@@ -572,6 +574,9 @@ static int sunxi_emac_eth_probe(struct udevice *dev)
 	if (ret)
 		return ret;
 
+	if (priv->phy_reg)
+		regulator_set_enable(priv->phy_reg, true);
+
 	return sunxi_emac_init_phy(priv, dev);
 }
 
@@ -585,9 +590,43 @@ static const struct eth_ops sunxi_emac_eth_ops = {
 static int sunxi_emac_eth_of_to_plat(struct udevice *dev)
 {
 	struct eth_pdata *pdata = dev_get_plat(dev);
+	struct emac_eth_dev *priv = dev_get_priv(dev);
+	struct ofnode_phandle_args args;
+	ofnode mdio_node;
+	int ret;
 
 	pdata->iobase = dev_read_addr(dev);
 
+	/* The PHY regulator is in the MDIO node, not the EMAC or PHY node. */
+	ret = dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0, &args);
+	if (ret) {
+		dev_err(dev, "failed to get PHY node\n");
+		return ret;
+	}
+
+	/*
+	 * U-Boot does not have (and does not need) a device driver for the
+	 * MDIO device, so just "pass through" that DT node to get to the
+	 * regulator phandle.
+	 * The PHY regulator is optional, though: ignore if we cannot find
+	 * a phy-supply property.
+	 */
+	mdio_node = ofnode_get_parent(args.node);
+	ret= ofnode_parse_phandle_with_args(mdio_node, "phy-supply", NULL, 0, 0,
+					    &args);
+	if (ret && ret != -ENOENT) {
+		dev_err(dev, "failed to get PHY supply node\n");
+		return ret;
+	}
+	if (!ret) {
+		ret = uclass_get_device_by_ofnode(UCLASS_REGULATOR, args.node,
+						  &priv->phy_reg);
+		if (ret) {
+			dev_err(dev, "failed to get PHY regulator node\n");
+			return ret;
+		}
+	}
+
 	return 0;
 }
 
-- 
2.35.8


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 03/22] sunxi: remove CONFIG_MACPWR
  2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
  2023-09-28 21:54 ` [PATCH v2 01/22] sunxi: remove CONFIG_SATAPWR Andre Przywara
  2023-09-28 21:54 ` [PATCH v2 02/22] net: sunxi_emac: chase DT nodes to find PHY regulator Andre Przywara
@ 2023-09-28 21:54 ` Andre Przywara
  2023-10-21  4:35   ` Samuel Holland
  2023-09-28 21:54 ` [PATCH v2 04/22] pinctrl: sunxi: move pinctrl code Andre Przywara
                   ` (18 subsequent siblings)
  21 siblings, 1 reply; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

The CONFIG_MACPWR Kconfig symbol is used to point to a GPIO that enables
the power for the Ethernet "MAC" (mostly PHY, really).
In the DT this is described with the phy-supply property in the MAC DT
node, pointing to a (GPIO controlled) regulator. Since we need Ethernet
only in U-Boot proper, and use a DM driver there, we should use the DT
instead of hardcoding this.

Add code to the sun8i_emac and sunxi_emac drivers to check the DT for
that regulator and enable it, at probe time. Then drop the current code
from board.c, which was doing that job before.
This allows us to remove the MACPWR Kconfig definition and the respective
values from the defconfigs.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Sam Edwards <CFSworks@gmail.com>
---
 arch/arm/mach-sunxi/Kconfig           |  7 -------
 board/sunxi/board.c                   | 12 +-----------
 configs/Bananapi_M2_Ultra_defconfig   |  1 -
 configs/Bananapi_defconfig            |  1 -
 configs/Bananapro_defconfig           |  1 -
 configs/Lamobo_R1_defconfig           |  1 -
 configs/Mele_A1000_defconfig          |  1 -
 configs/Orangepi_defconfig            |  1 -
 configs/Orangepi_mini_defconfig       |  1 -
 configs/bananapi_m1_plus_defconfig    |  1 -
 configs/bananapi_m2_plus_h3_defconfig |  1 -
 configs/bananapi_m2_plus_h5_defconfig |  1 -
 configs/i12-tvbox_defconfig           |  1 -
 configs/jesurun_q5_defconfig          |  1 -
 configs/mixtile_loftq_defconfig       |  1 -
 configs/nanopi_m1_plus_defconfig      |  1 -
 configs/nanopi_neo_plus2_defconfig    |  1 -
 configs/nanopi_r1s_h5_defconfig       |  1 -
 configs/orangepi_pc2_defconfig        |  1 -
 configs/orangepi_plus2e_defconfig     |  1 -
 configs/orangepi_plus_defconfig       |  1 -
 configs/orangepi_win_defconfig        |  1 -
 configs/pine_h64_defconfig            |  1 -
 configs/zeropi_defconfig              |  1 -
 drivers/net/sun8i_emac.c              |  9 +++++++--
 25 files changed, 8 insertions(+), 42 deletions(-)

diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 1b24dfe4dd1..d3ed62add99 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -695,13 +695,6 @@ config OLD_SUNXI_KERNEL_COMPAT
 	Set this to enable various workarounds for old kernels, this results in
 	sub-optimal settings for newer kernels, only enable if needed.
 
-config MACPWR
-	string "MAC power pin"
-	default ""
-	help
-	  Set the pin used to power the MAC. This takes a string in the format
-	  understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of port H.
-
 config MMC1_PINS_PH
 	bool "Pins for mmc1 are on Port H"
 	depends on MACH_SUN4I || MACH_SUN7I || MACH_SUN8I_R40
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 50a60e760d4..5cfb33468e5 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -187,7 +187,7 @@ enum env_location env_get_location(enum env_operation op, int prio)
 /* add board specific code here */
 int board_init(void)
 {
-	__maybe_unused int id_pfr1, ret, macpwr_pin;
+	__maybe_unused int id_pfr1, ret;
 
 	gd->bd->bi_boot_params = (PHYS_SDRAM_0 + 0x100);
 
@@ -224,15 +224,6 @@ int board_init(void)
 	if (ret)
 		return ret;
 
-	/* strcmp() would look better, but doesn't get optimised away. */
-	if (CONFIG_MACPWR[0]) {
-		macpwr_pin = sunxi_name_to_gpio(CONFIG_MACPWR);
-		if (macpwr_pin >= 0) {
-			gpio_request(macpwr_pin, "macpwr");
-			gpio_direction_output(macpwr_pin, 1);
-		}
-	}
-
 #if CONFIG_IS_ENABLED(DM_I2C)
 	/*
 	 * Temporary workaround for enabling I2C clocks until proper sunxi DM
@@ -240,7 +231,6 @@ int board_init(void)
 	 */
 	i2c_init_board();
 #endif
-
 	eth_init_board();
 
 	return 0;
diff --git a/configs/Bananapi_M2_Ultra_defconfig b/configs/Bananapi_M2_Ultra_defconfig
index a5fe76af568..2cc7bbbd8b7 100644
--- a/configs/Bananapi_M2_Ultra_defconfig
+++ b/configs/Bananapi_M2_Ultra_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-r40-bananapi-m2-ultra"
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_R40=y
 CONFIG_DRAM_CLK=576
-CONFIG_MACPWR="PA17"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_USB1_VBUS_PIN="PH23"
 CONFIG_USB2_VBUS_PIN="PH23"
diff --git a/configs/Bananapi_defconfig b/configs/Bananapi_defconfig
index 6c2a1f630e8..f4910ba13ac 100644
--- a/configs/Bananapi_defconfig
+++ b/configs/Bananapi_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-bananapi"
 CONFIG_SPL=y
 CONFIG_MACH_SUN7I=y
 CONFIG_DRAM_CLK=432
-CONFIG_MACPWR="PH23"
 CONFIG_VIDEO_COMPOSITE=y
 CONFIG_GMAC_TX_DELAY=3
 CONFIG_AHCI=y
diff --git a/configs/Bananapro_defconfig b/configs/Bananapro_defconfig
index 94fd74754ea..02be8971df9 100644
--- a/configs/Bananapro_defconfig
+++ b/configs/Bananapro_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-bananapro"
 CONFIG_SPL=y
 CONFIG_MACH_SUN7I=y
 CONFIG_DRAM_CLK=432
-CONFIG_MACPWR="PH23"
 CONFIG_USB1_VBUS_PIN="PH0"
 CONFIG_USB2_VBUS_PIN="PH1"
 CONFIG_VIDEO_COMPOSITE=y
diff --git a/configs/Lamobo_R1_defconfig b/configs/Lamobo_R1_defconfig
index 9639cb6aad9..66f57ab3c85 100644
--- a/configs/Lamobo_R1_defconfig
+++ b/configs/Lamobo_R1_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-lamobo-r1"
 CONFIG_SPL=y
 CONFIG_MACH_SUN7I=y
 CONFIG_DRAM_CLK=432
-CONFIG_MACPWR="PH23"
 CONFIG_GMAC_TX_DELAY=4
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/Mele_A1000_defconfig b/configs/Mele_A1000_defconfig
index f5b6d908cdc..9ac2e4839d9 100644
--- a/configs/Mele_A1000_defconfig
+++ b/configs/Mele_A1000_defconfig
@@ -3,7 +3,6 @@ CONFIG_ARCH_SUNXI=y
 CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-a1000"
 CONFIG_SPL=y
 CONFIG_MACH_SUN4I=y
-CONFIG_MACPWR="PH15"
 CONFIG_VIDEO_VGA=y
 CONFIG_VIDEO_COMPOSITE=y
 CONFIG_AHCI=y
diff --git a/configs/Orangepi_defconfig b/configs/Orangepi_defconfig
index c89a9a1f9dd..53edf525ec0 100644
--- a/configs/Orangepi_defconfig
+++ b/configs/Orangepi_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-orangepi"
 CONFIG_SPL=y
 CONFIG_MACH_SUN7I=y
 CONFIG_DRAM_CLK=432
-CONFIG_MACPWR="PH23"
 CONFIG_USB1_VBUS_PIN="PH26"
 CONFIG_USB2_VBUS_PIN="PH22"
 CONFIG_VIDEO_VGA=y
diff --git a/configs/Orangepi_mini_defconfig b/configs/Orangepi_mini_defconfig
index fe9ce808a1e..ccf32670170 100644
--- a/configs/Orangepi_mini_defconfig
+++ b/configs/Orangepi_mini_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-orangepi-mini"
 CONFIG_SPL=y
 CONFIG_MACH_SUN7I=y
 CONFIG_DRAM_CLK=432
-CONFIG_MACPWR="PH23"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=3
 CONFIG_USB1_VBUS_PIN="PH26"
 CONFIG_USB2_VBUS_PIN="PH22"
diff --git a/configs/bananapi_m1_plus_defconfig b/configs/bananapi_m1_plus_defconfig
index 0fbb619d623..a432a01f6b4 100644
--- a/configs/bananapi_m1_plus_defconfig
+++ b/configs/bananapi_m1_plus_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-bananapi-m1-plus"
 CONFIG_SPL=y
 CONFIG_MACH_SUN7I=y
 CONFIG_DRAM_CLK=432
-CONFIG_MACPWR="PH23"
 CONFIG_VIDEO_COMPOSITE=y
 CONFIG_GMAC_TX_DELAY=3
 CONFIG_AHCI=y
diff --git a/configs/bananapi_m2_plus_h3_defconfig b/configs/bananapi_m2_plus_h3_defconfig
index 26ced59fb02..a8f9b5044b0 100644
--- a/configs/bananapi_m2_plus_h3_defconfig
+++ b/configs/bananapi_m2_plus_h3_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-bananapi-m2-plus"
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=672
-CONFIG_MACPWR="PD6"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SUN8I_EMAC=y
diff --git a/configs/bananapi_m2_plus_h5_defconfig b/configs/bananapi_m2_plus_h5_defconfig
index fb6c945919a..1634f626190 100644
--- a/configs/bananapi_m2_plus_h5_defconfig
+++ b/configs/bananapi_m2_plus_h5_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-bananapi-m2-plus"
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I_H5=y
 CONFIG_DRAM_CLK=672
-CONFIG_MACPWR="PD6"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SUN8I_EMAC=y
diff --git a/configs/i12-tvbox_defconfig b/configs/i12-tvbox_defconfig
index 257dd89af45..37f0f53ae7d 100644
--- a/configs/i12-tvbox_defconfig
+++ b/configs/i12-tvbox_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-i12-tvbox"
 CONFIG_SPL=y
 CONFIG_MACH_SUN7I=y
 CONFIG_DRAM_CLK=384
-CONFIG_MACPWR="PH21"
 CONFIG_VIDEO_COMPOSITE=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL_I2C=y
diff --git a/configs/jesurun_q5_defconfig b/configs/jesurun_q5_defconfig
index 0ff666b2ee5..c99be7cea4e 100644
--- a/configs/jesurun_q5_defconfig
+++ b/configs/jesurun_q5_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-jesurun-q5"
 CONFIG_SPL=y
 CONFIG_MACH_SUN4I=y
 CONFIG_DRAM_CLK=312
-CONFIG_MACPWR="PH19"
 CONFIG_USB0_VBUS_PIN="PB9"
 CONFIG_VIDEO_COMPOSITE=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/mixtile_loftq_defconfig b/configs/mixtile_loftq_defconfig
index 0e4cdc44670..2f92228eb7b 100644
--- a/configs/mixtile_loftq_defconfig
+++ b/configs/mixtile_loftq_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun6i-a31-mixtile-loftq"
 CONFIG_SPL=y
 CONFIG_MACH_SUN6I=y
 CONFIG_DRAM_ZQ=251
-CONFIG_MACPWR="PA21"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_USB1_VBUS_PIN="PH24"
 CONFIG_USB2_VBUS_PIN=""
diff --git a/configs/nanopi_m1_plus_defconfig b/configs/nanopi_m1_plus_defconfig
index 76655d79ae0..078e98b644d 100644
--- a/configs/nanopi_m1_plus_defconfig
+++ b/configs/nanopi_m1_plus_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-nanopi-m1-plus"
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=408
-CONFIG_MACPWR="PD6"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SUN8I_EMAC=y
diff --git a/configs/nanopi_neo_plus2_defconfig b/configs/nanopi_neo_plus2_defconfig
index 924ff38f17c..85ff31c6fe5 100644
--- a/configs/nanopi_neo_plus2_defconfig
+++ b/configs/nanopi_neo_plus2_defconfig
@@ -6,7 +6,6 @@ CONFIG_MACH_SUN50I_H5=y
 CONFIG_DRAM_CLK=408
 CONFIG_DRAM_ZQ=3881977
 # CONFIG_DRAM_ODT_EN is not set
-CONFIG_MACPWR="PD6"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SUN8I_EMAC=y
diff --git a/configs/nanopi_r1s_h5_defconfig b/configs/nanopi_r1s_h5_defconfig
index 27cf172d72a..2a6f94afe40 100644
--- a/configs/nanopi_r1s_h5_defconfig
+++ b/configs/nanopi_r1s_h5_defconfig
@@ -6,7 +6,6 @@ CONFIG_MACH_SUN50I_H5=y
 CONFIG_DRAM_CLK=672
 CONFIG_DRAM_ZQ=3881977
 # CONFIG_DRAM_ODT_EN is not set
-CONFIG_MACPWR="PD6"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SUN8I_EMAC=y
diff --git a/configs/orangepi_pc2_defconfig b/configs/orangepi_pc2_defconfig
index 777af8c60ea..fb6fbaf787a 100644
--- a/configs/orangepi_pc2_defconfig
+++ b/configs/orangepi_pc2_defconfig
@@ -5,7 +5,6 @@ CONFIG_SPL=y
 CONFIG_MACH_SUN50I_H5=y
 CONFIG_DRAM_CLK=672
 CONFIG_DRAM_ZQ=3881977
-CONFIG_MACPWR="PD6"
 CONFIG_SPL_SPI_SUNXI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL_I2C=y
diff --git a/configs/orangepi_plus2e_defconfig b/configs/orangepi_plus2e_defconfig
index 138a6a72b8c..5e2cbc48ea2 100644
--- a/configs/orangepi_plus2e_defconfig
+++ b/configs/orangepi_plus2e_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-plus2e"
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=672
-CONFIG_MACPWR="PD6"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL_I2C=y
diff --git a/configs/orangepi_plus_defconfig b/configs/orangepi_plus_defconfig
index ed585881d49..092ce77a6c4 100644
--- a/configs/orangepi_plus_defconfig
+++ b/configs/orangepi_plus_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-plus"
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=672
-CONFIG_MACPWR="PD6"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_USB1_VBUS_PIN="PG13"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/orangepi_win_defconfig b/configs/orangepi_win_defconfig
index df11ad8c8fd..3ddaf050a48 100644
--- a/configs/orangepi_win_defconfig
+++ b/configs/orangepi_win_defconfig
@@ -3,7 +3,6 @@ CONFIG_ARCH_SUNXI=y
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-orangepi-win"
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I=y
-CONFIG_MACPWR="PD14"
 CONFIG_SPL_SPI_SUNXI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPI_FLASH_WINBOND=y
diff --git a/configs/pine_h64_defconfig b/configs/pine_h64_defconfig
index 6dac6098d04..4712b8e4694 100644
--- a/configs/pine_h64_defconfig
+++ b/configs/pine_h64_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-h6-pine-h64"
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I_H6=y
 CONFIG_SUNXI_DRAM_H6_LPDDR3=y
-CONFIG_MACPWR="PC16"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_USB3_VBUS_PIN="PL5"
 CONFIG_SPL_SPI_SUNXI=y
diff --git a/configs/zeropi_defconfig b/configs/zeropi_defconfig
index 11f3715e6dc..7901bffd159 100644
--- a/configs/zeropi_defconfig
+++ b/configs/zeropi_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-zeropi"
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=408
-CONFIG_MACPWR="PD6"
 # CONFIG_VIDEO_DE2 is not set
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_CONSOLE_MUX=y
diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
index 04c3274fbe1..7b60a60ad52 100644
--- a/drivers/net/sun8i_emac.c
+++ b/drivers/net/sun8i_emac.c
@@ -29,6 +29,7 @@
 #include <net.h>
 #include <reset.h>
 #include <wait_bit.h>
+#include <power/regulator.h>
 
 #define MDIO_CMD_MII_BUSY		BIT(0)
 #define MDIO_CMD_MII_WRITE		BIT(1)
@@ -167,9 +168,8 @@ struct emac_eth_dev {
 	struct clk ephy_clk;
 	struct reset_ctl tx_rst;
 	struct reset_ctl ephy_rst;
-#if CONFIG_IS_ENABLED(DM_GPIO)
 	struct gpio_desc reset_gpio;
-#endif
+	struct udevice *phy_reg;
 };
 
 
@@ -720,6 +720,9 @@ static int sun8i_emac_eth_probe(struct udevice *dev)
 
 	sun8i_emac_set_syscon(sun8i_pdata, priv);
 
+	if (priv->phy_reg)
+		regulator_set_enable(priv->phy_reg, true);
+
 	sun8i_mdio_init(dev->name, dev);
 	priv->bus = miiphy_get_dev_by_name(dev->name);
 
@@ -829,6 +832,8 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
 
 	priv->sysctl_reg = (void *)syscon_base + priv->variant->syscon_offset;
 
+	device_get_supply_regulator(dev, "phy-supply", &priv->phy_reg);
+
 	pdata->phy_interface = -1;
 	priv->phyaddr = -1;
 	priv->use_internal_phy = false;
-- 
2.35.8


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 04/22] pinctrl: sunxi: move pinctrl code
  2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
                   ` (2 preceding siblings ...)
  2023-09-28 21:54 ` [PATCH v2 03/22] sunxi: remove CONFIG_MACPWR Andre Przywara
@ 2023-09-28 21:54 ` Andre Przywara
  2023-10-19  0:18   ` Andre Przywara
  2023-10-21  8:21   ` Samuel Holland
  2023-09-28 21:54 ` [PATCH v2 05/22] pinctrl: sunxi: add GPIO in/out wrappers Andre Przywara
                   ` (17 subsequent siblings)
  21 siblings, 2 replies; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

Move the existing sunxi-specific low level pinctrl routines from
arch/arm/mach-sunxi into the existing GPIO code under drivers/gpio, so
that the common code can be shared outside of arch/arm.

This also takes the opportunity to move some definitions from our
header file into the driver C file, as they are private to the driver
and are not needed elsewhere.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arch/arm/include/asm/arch-sunxi/gpio.h |  20 +----
 arch/arm/mach-sunxi/Makefile           |   1 -
 arch/arm/mach-sunxi/pinmux.c           |  78 -------------------
 drivers/gpio/sunxi_gpio.c              | 102 ++++++++++++++++++++++++-
 4 files changed, 105 insertions(+), 96 deletions(-)
 delete mode 100644 arch/arm/mach-sunxi/pinmux.c

diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
index 6eaeece4e24..4bc9e8ffcc9 100644
--- a/arch/arm/include/asm/arch-sunxi/gpio.h
+++ b/arch/arm/include/asm/arch-sunxi/gpio.h
@@ -3,6 +3,9 @@
  * (C) Copyright 2007-2012
  * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
  * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * Definitions that are shared between the Allwinner pinctrl and GPIO drivers,
+ * also used by some non-DM SPL code directly.
  */
 
 #ifndef _SUNXI_GPIO_H
@@ -76,22 +79,6 @@ struct sunxi_gpio_reg {
 #define SUN50I_H6_GPIO_POW_MOD_SEL	0x340
 #define SUN50I_H6_GPIO_POW_MOD_VAL	0x348
 
-#define BANK_TO_GPIO(bank)	(((bank) < SUNXI_GPIO_L) ? \
-	&((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[bank] : \
-	&((struct sunxi_gpio_reg *)SUNXI_R_PIO_BASE)->gpio_bank[(bank) - SUNXI_GPIO_L])
-
-#define GPIO_BANK(pin)		((pin) >> 5)
-#define GPIO_NUM(pin)		((pin) & 0x1f)
-
-#define GPIO_CFG_INDEX(pin)	(((pin) & 0x1f) >> 3)
-#define GPIO_CFG_OFFSET(pin)	((((pin) & 0x1f) & 0x7) << 2)
-
-#define GPIO_DRV_INDEX(pin)	(((pin) & 0x1f) >> 4)
-#define GPIO_DRV_OFFSET(pin)	((((pin) & 0x1f) & 0xf) << 1)
-
-#define GPIO_PULL_INDEX(pin)	(((pin) & 0x1f) >> 4)
-#define GPIO_PULL_OFFSET(pin)	((((pin) & 0x1f) & 0xf) << 1)
-
 /* GPIO bank sizes */
 #define SUNXI_GPIOS_PER_BANK	32
 
@@ -217,6 +204,7 @@ struct sunxi_gpio_plat {
 	char			bank_name[3];
 };
 
+/* prototypes for the non-DM GPIO/pinctrl functions, used in the SPL */
 void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val);
 void sunxi_gpio_set_cfgpin(u32 pin, u32 val);
 int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset);
diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
index 58f807cb82d..671211e9322 100644
--- a/arch/arm/mach-sunxi/Makefile
+++ b/arch/arm/mach-sunxi/Makefile
@@ -10,7 +10,6 @@ obj-y	+= board.o
 obj-y	+= clock.o
 obj-y	+= cpu_info.o
 obj-y	+= dram_helpers.o
-obj-y	+= pinmux.o
 obj-$(CONFIG_SUN6I_PRCM)	+= prcm.o
 obj-$(CONFIG_AXP_PMIC_BUS)	+= pmic_bus.o
 obj-$(CONFIG_MACH_SUNIV)	+= clock_sun6i.o
diff --git a/arch/arm/mach-sunxi/pinmux.c b/arch/arm/mach-sunxi/pinmux.c
deleted file mode 100644
index c95fcee9f6c..00000000000
--- a/arch/arm/mach-sunxi/pinmux.c
+++ /dev/null
@@ -1,78 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * (C) Copyright 2007-2011
- * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
- * Tom Cubie <tangliang@allwinnertech.com>
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <asm/arch/gpio.h>
-
-void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val)
-{
-	u32 index = GPIO_CFG_INDEX(bank_offset);
-	u32 offset = GPIO_CFG_OFFSET(bank_offset);
-
-	clrsetbits_le32(&pio->cfg[index], 0xf << offset, val << offset);
-}
-
-void sunxi_gpio_set_cfgpin(u32 pin, u32 val)
-{
-	u32 bank = GPIO_BANK(pin);
-	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
-
-	sunxi_gpio_set_cfgbank(pio, pin, val);
-}
-
-int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset)
-{
-	u32 index = GPIO_CFG_INDEX(bank_offset);
-	u32 offset = GPIO_CFG_OFFSET(bank_offset);
-	u32 cfg;
-
-	cfg = readl(&pio->cfg[index]);
-	cfg >>= offset;
-
-	return cfg & 0xf;
-}
-
-int sunxi_gpio_get_cfgpin(u32 pin)
-{
-	u32 bank = GPIO_BANK(pin);
-	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
-
-	return sunxi_gpio_get_cfgbank(pio, pin);
-}
-
-void sunxi_gpio_set_drv(u32 pin, u32 val)
-{
-	u32 bank = GPIO_BANK(pin);
-	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
-
-	sunxi_gpio_set_drv_bank(pio, pin, val);
-}
-
-void sunxi_gpio_set_drv_bank(struct sunxi_gpio *pio, u32 bank_offset, u32 val)
-{
-	u32 index = GPIO_DRV_INDEX(bank_offset);
-	u32 offset = GPIO_DRV_OFFSET(bank_offset);
-
-	clrsetbits_le32(&pio->drv[index], 0x3 << offset, val << offset);
-}
-
-void sunxi_gpio_set_pull(u32 pin, u32 val)
-{
-	u32 bank = GPIO_BANK(pin);
-	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
-
-	sunxi_gpio_set_pull_bank(pio, pin, val);
-}
-
-void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val)
-{
-	u32 index = GPIO_PULL_INDEX(bank_offset);
-	u32 offset = GPIO_PULL_OFFSET(bank_offset);
-
-	clrsetbits_le32(&pio->pull[index], 0x3 << offset, val << offset);
-}
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
index f0b42e4fdb7..71c3168b755 100644
--- a/drivers/gpio/sunxi_gpio.c
+++ b/drivers/gpio/sunxi_gpio.c
@@ -18,6 +18,104 @@
 #include <asm/gpio.h>
 #include <dt-bindings/gpio/gpio.h>
 
+/*
+ * =======================================================================
+ * Low level GPIO/pin controller access functions, to be shared by non-DM
+ * SPL code and the DM pinctrl/GPIO drivers.
+ * The functions ending in "bank" take a base pointer to a GPIO bank, and
+ * the pin offset is relative to that bank.
+ * The functions without "bank" in their name take a linear GPIO number,
+ * covering all ports, and starting at 0 for PortA.
+ * =======================================================================
+ */
+
+#define BANK_TO_GPIO(bank)	(((bank) < SUNXI_GPIO_L) ? \
+	&((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[bank] : \
+	&((struct sunxi_gpio_reg *)SUNXI_R_PIO_BASE)->gpio_bank[(bank) - SUNXI_GPIO_L])
+
+#define GPIO_BANK(pin)		((pin) >> 5)
+#define GPIO_NUM(pin)		((pin) & 0x1f)
+
+#define GPIO_CFG_INDEX(pin)	(((pin) & 0x1f) >> 3)
+#define GPIO_CFG_OFFSET(pin)	((((pin) & 0x1f) & 0x7) << 2)
+
+#define GPIO_DRV_INDEX(pin)	(((pin) & 0x1f) >> 4)
+#define GPIO_DRV_OFFSET(pin)	((((pin) & 0x1f) & 0xf) << 1)
+
+#define GPIO_PULL_INDEX(pin)	(((pin) & 0x1f) >> 4)
+#define GPIO_PULL_OFFSET(pin)	((((pin) & 0x1f) & 0xf) << 1)
+
+void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val)
+{
+	u32 index = GPIO_CFG_INDEX(bank_offset);
+	u32 offset = GPIO_CFG_OFFSET(bank_offset);
+
+	clrsetbits_le32(&pio->cfg[index], 0xf << offset, val << offset);
+}
+
+void sunxi_gpio_set_cfgpin(u32 pin, u32 val)
+{
+	u32 bank = GPIO_BANK(pin);
+	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
+
+	sunxi_gpio_set_cfgbank(pio, pin, val);
+}
+
+int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset)
+{
+	u32 index = GPIO_CFG_INDEX(bank_offset);
+	u32 offset = GPIO_CFG_OFFSET(bank_offset);
+	u32 cfg;
+
+	cfg = readl(&pio->cfg[index]);
+	cfg >>= offset;
+
+	return cfg & 0xf;
+}
+
+int sunxi_gpio_get_cfgpin(u32 pin)
+{
+	u32 bank = GPIO_BANK(pin);
+	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
+
+	return sunxi_gpio_get_cfgbank(pio, pin);
+}
+
+void sunxi_gpio_set_drv(u32 pin, u32 val)
+{
+	u32 bank = GPIO_BANK(pin);
+	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
+
+	sunxi_gpio_set_drv_bank(pio, pin, val);
+}
+
+void sunxi_gpio_set_drv_bank(struct sunxi_gpio *pio, u32 bank_offset, u32 val)
+{
+	u32 index = GPIO_DRV_INDEX(bank_offset);
+	u32 offset = GPIO_DRV_OFFSET(bank_offset);
+
+	clrsetbits_le32(&pio->drv[index], 0x3 << offset, val << offset);
+}
+
+void sunxi_gpio_set_pull(u32 pin, u32 val)
+{
+	u32 bank = GPIO_BANK(pin);
+	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
+
+	sunxi_gpio_set_pull_bank(pio, pin, val);
+}
+
+void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val)
+{
+	u32 index = GPIO_PULL_INDEX(bank_offset);
+	u32 offset = GPIO_PULL_OFFSET(bank_offset);
+
+	clrsetbits_le32(&pio->pull[index], 0x3 << offset, val << offset);
+}
+
+
+/* =========== Non-DM code, used by the SPL. ============ */
+
 #if !CONFIG_IS_ENABLED(DM_GPIO)
 static int sunxi_gpio_output(u32 pin, u32 val)
 {
@@ -106,7 +204,9 @@ int sunxi_name_to_gpio(const char *name)
 		return -1;
 	return group * 32 + pin;
 }
-#endif /* DM_GPIO */
+#endif /* !DM_GPIO */
+
+/* =========== DM code, used by U-Boot proper. ============ */
 
 #if CONFIG_IS_ENABLED(DM_GPIO)
 /* TODO(sjg@chromium.org): Remove this function and use device tree */
-- 
2.35.8


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 05/22] pinctrl: sunxi: add GPIO in/out wrappers
  2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
                   ` (3 preceding siblings ...)
  2023-09-28 21:54 ` [PATCH v2 04/22] pinctrl: sunxi: move pinctrl code Andre Przywara
@ 2023-09-28 21:54 ` Andre Przywara
  2023-10-21  8:30   ` Samuel Holland
  2023-09-28 21:54 ` [PATCH v2 06/22] pinctrl: sunxi: remove struct sunxi_gpio Andre Przywara
                   ` (16 subsequent siblings)
  21 siblings, 1 reply; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

So far we were open-coding the pincontroller's GPIO output/input access
in each function using that.

Provide functions that wrap that nicely, and follow the existing pattern
(set/get_{bank,}), so users don't need to know about the internals, and
we can abstract the new D1 pinctrl more easily.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 drivers/gpio/sunxi_gpio.c | 55 ++++++++++++++++++---------------------
 1 file changed, 25 insertions(+), 30 deletions(-)

diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
index 71c3168b755..a4b336943b6 100644
--- a/drivers/gpio/sunxi_gpio.c
+++ b/drivers/gpio/sunxi_gpio.c
@@ -81,6 +81,19 @@ int sunxi_gpio_get_cfgpin(u32 pin)
 	return sunxi_gpio_get_cfgbank(pio, pin);
 }
 
+static void sunxi_gpio_set_output_bank(struct sunxi_gpio *pio,
+				       int pin, bool set)
+{
+	u32 mask = 1U << pin;
+
+	clrsetbits_le32(&pio->dat, set ? 0 : mask, set ? mask : 0);
+}
+
+static int sunxi_gpio_get_output_bank(struct sunxi_gpio *pio, int pin)
+{
+	return !!(readl(&pio->dat) & (1U << pin));
+}
+
 void sunxi_gpio_set_drv(u32 pin, u32 val)
 {
 	u32 bank = GPIO_BANK(pin);
@@ -117,35 +130,20 @@ void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val)
 /* =========== Non-DM code, used by the SPL. ============ */
 
 #if !CONFIG_IS_ENABLED(DM_GPIO)
-static int sunxi_gpio_output(u32 pin, u32 val)
+static void sunxi_gpio_set_output(u32 pin, bool set)
 {
-	u32 dat;
 	u32 bank = GPIO_BANK(pin);
-	u32 num = GPIO_NUM(pin);
 	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
 
-	dat = readl(&pio->dat);
-	if (val)
-		dat |= 0x1 << num;
-	else
-		dat &= ~(0x1 << num);
-
-	writel(dat, &pio->dat);
-
-	return 0;
+	sunxi_gpio_set_output_bank(pio, GPIO_NUM(pin), set);
 }
 
-static int sunxi_gpio_input(u32 pin)
+static int sunxi_gpio_get_output(u32 pin)
 {
-	u32 dat;
 	u32 bank = GPIO_BANK(pin);
-	u32 num = GPIO_NUM(pin);
 	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
 
-	dat = readl(&pio->dat);
-	dat >>= num;
-
-	return dat & 0x1;
+	return sunxi_gpio_get_output_bank(pio, GPIO_NUM(pin));
 }
 
 int gpio_request(unsigned gpio, const char *label)
@@ -168,18 +166,21 @@ int gpio_direction_input(unsigned gpio)
 int gpio_direction_output(unsigned gpio, int value)
 {
 	sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_OUTPUT);
+	sunxi_gpio_set_output(gpio, value);
 
-	return sunxi_gpio_output(gpio, value);
+	return 0;
 }
 
 int gpio_get_value(unsigned gpio)
 {
-	return sunxi_gpio_input(gpio);
+	return sunxi_gpio_get_output(gpio);
 }
 
 int gpio_set_value(unsigned gpio, int value)
 {
-	return sunxi_gpio_output(gpio, value);
+	sunxi_gpio_set_output(gpio, value);
+
+	return 0;
 }
 
 int sunxi_name_to_gpio(const char *name)
@@ -231,13 +232,8 @@ int sunxi_name_to_gpio(const char *name)
 static int sunxi_gpio_get_value(struct udevice *dev, unsigned offset)
 {
 	struct sunxi_gpio_plat *plat = dev_get_plat(dev);
-	u32 num = GPIO_NUM(offset);
-	unsigned dat;
-
-	dat = readl(&plat->regs->dat);
-	dat >>= num;
 
-	return dat & 0x1;
+	return sunxi_gpio_get_output_bank(plat->regs, offset) & 0x1;
 }
 
 static int sunxi_gpio_get_function(struct udevice *dev, unsigned offset)
@@ -275,9 +271,8 @@ static int sunxi_gpio_set_flags(struct udevice *dev, unsigned int offset,
 
 	if (flags & GPIOD_IS_OUT) {
 		u32 value = !!(flags & GPIOD_IS_OUT_ACTIVE);
-		u32 num = GPIO_NUM(offset);
 
-		clrsetbits_le32(&plat->regs->dat, 1 << num, value << num);
+		sunxi_gpio_set_output_bank(plat->regs, offset, value);
 		sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_OUTPUT);
 	} else if (flags & GPIOD_IS_IN) {
 		u32 pull = 0;
-- 
2.35.8


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 06/22] pinctrl: sunxi: remove struct sunxi_gpio
  2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
                   ` (4 preceding siblings ...)
  2023-09-28 21:54 ` [PATCH v2 05/22] pinctrl: sunxi: add GPIO in/out wrappers Andre Przywara
@ 2023-09-28 21:54 ` Andre Przywara
  2023-10-21  8:37   ` Samuel Holland
  2023-09-28 21:54 ` [PATCH v2 07/22] pinctrl: sunxi: remove GPIO_EXTRA_HEADER Andre Przywara
                   ` (15 subsequent siblings)
  21 siblings, 1 reply; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

So far every Allwinner SoC used the same basic pincontroller/GPIO
register frame, and just differed by the number of implemented banks and
pins, plus some special functionality from time to time. However the D1
and successors use a slightly different pinctrl register layout.
Use that opportunity to drop "struct sunxi_gpio", that described that
MMIO frame in a C struct. That approach is somewhat frowned upon in the
Linux world and rarely used there, though still popular with U-Boot.

Switching from a C struct to a "base address plus offset" approach allows
to switch between the two models more dynamically, without reverting to
preprocessor macros and #ifdef's.

Model the pinctrl MMIO register frame in the usual "base address +
offset" way, and replace a hard-to-parse CPP macro with a more readable
static function.
All the users get converted over. There are no functional changes at
this point, it just prepares the stages for the D1 and friends.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arch/arm/include/asm/arch-sunxi/gpio.h | 40 ++----------
 drivers/gpio/sunxi_gpio.c              | 88 ++++++++++++++++----------
 drivers/pinctrl/sunxi/pinctrl-sunxi.c  | 14 ++--
 3 files changed, 66 insertions(+), 76 deletions(-)

diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
index 4bc9e8ffcc9..e0fb5b5da63 100644
--- a/arch/arm/include/asm/arch-sunxi/gpio.h
+++ b/arch/arm/include/asm/arch-sunxi/gpio.h
@@ -31,13 +31,6 @@
 #define SUNXI_GPIO_H	7
 #define SUNXI_GPIO_I	8
 
-/*
- * This defines the number of GPIO banks for the _main_ GPIO controller.
- * You should fix up the padding in struct sunxi_gpio_reg below if you
- * change this.
- */
-#define SUNXI_GPIO_BANKS 9
-
 /*
  * sun6i/sun8i and later SoCs have an additional GPIO controller (R_PIO)
  * at a different register offset.
@@ -55,32 +48,11 @@
 #define SUNXI_GPIO_M	12
 #define SUNXI_GPIO_N	13
 
-struct sunxi_gpio {
-	u32 cfg[4];
-	u32 dat;
-	u32 drv[2];
-	u32 pull[2];
-};
-
-/* gpio interrupt control */
-struct sunxi_gpio_int {
-	u32 cfg[3];
-	u32 ctl;
-	u32 sta;
-	u32 deb;		/* interrupt debounce */
-};
-
-struct sunxi_gpio_reg {
-	struct sunxi_gpio gpio_bank[SUNXI_GPIO_BANKS];
-	u8 res[0xbc];
-	struct sunxi_gpio_int gpio_int;
-};
-
 #define SUN50I_H6_GPIO_POW_MOD_SEL	0x340
 #define SUN50I_H6_GPIO_POW_MOD_VAL	0x348
 
-/* GPIO bank sizes */
 #define SUNXI_GPIOS_PER_BANK	32
+#define SUNXI_PINCTRL_BANK_SIZE 0x24
 
 #define SUNXI_GPIO_NEXT(__gpio) \
 	((__gpio##_START) + SUNXI_GPIOS_PER_BANK)
@@ -200,19 +172,19 @@ enum sunxi_gpio_number {
 #define SUNXI_GPIO_AXP0_GPIO_COUNT	6
 
 struct sunxi_gpio_plat {
-	struct sunxi_gpio	*regs;
+	void			*regs;
 	char			bank_name[3];
 };
 
 /* prototypes for the non-DM GPIO/pinctrl functions, used in the SPL */
-void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val);
+void sunxi_gpio_set_cfgbank(void *bank_base, int pin_offset, u32 val);
 void sunxi_gpio_set_cfgpin(u32 pin, u32 val);
-int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset);
+int sunxi_gpio_get_cfgbank(void *bank_base, int pin_offset);
 int sunxi_gpio_get_cfgpin(u32 pin);
 void sunxi_gpio_set_drv(u32 pin, u32 val);
-void sunxi_gpio_set_drv_bank(struct sunxi_gpio *pio, u32 bank_offset, u32 val);
+void sunxi_gpio_set_drv_bank(void *bank_base, u32 pin_offset, u32 val);
 void sunxi_gpio_set_pull(u32 pin, u32 val);
-void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val);
+void sunxi_gpio_set_pull_bank(void *bank_base, int pin_offset, u32 val);
 int sunxi_name_to_gpio(const char *name);
 
 #if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
index a4b336943b6..fe3f6ed0938 100644
--- a/drivers/gpio/sunxi_gpio.c
+++ b/drivers/gpio/sunxi_gpio.c
@@ -29,45 +29,61 @@
  * =======================================================================
  */
 
-#define BANK_TO_GPIO(bank)	(((bank) < SUNXI_GPIO_L) ? \
-	&((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[bank] : \
-	&((struct sunxi_gpio_reg *)SUNXI_R_PIO_BASE)->gpio_bank[(bank) - SUNXI_GPIO_L])
-
 #define GPIO_BANK(pin)		((pin) >> 5)
 #define GPIO_NUM(pin)		((pin) & 0x1f)
 
+#define GPIO_CFG_REG_OFFSET	0x00
 #define GPIO_CFG_INDEX(pin)	(((pin) & 0x1f) >> 3)
 #define GPIO_CFG_OFFSET(pin)	((((pin) & 0x1f) & 0x7) << 2)
 
+#define GPIO_DAT_REG_OFFSET	0x10
+
+#define GPIO_DRV_REG_OFFSET	0x14
 #define GPIO_DRV_INDEX(pin)	(((pin) & 0x1f) >> 4)
 #define GPIO_DRV_OFFSET(pin)	((((pin) & 0x1f) & 0xf) << 1)
 
+#define GPIO_PULL_REG_OFFSET	0x1c
 #define GPIO_PULL_INDEX(pin)	(((pin) & 0x1f) >> 4)
 #define GPIO_PULL_OFFSET(pin)	((((pin) & 0x1f) & 0xf) << 1)
 
-void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val)
+static void* BANK_TO_GPIO(int bank)
+{
+	void *pio_base;
+
+	if (bank < SUNXI_GPIO_L) {
+		pio_base = (void *)(uintptr_t)SUNXI_PIO_BASE;
+	} else {
+		pio_base = (void *)(uintptr_t)SUNXI_R_PIO_BASE;
+		bank -= SUNXI_GPIO_L;
+	}
+
+	return pio_base + bank * SUNXI_PINCTRL_BANK_SIZE;
+}
+
+void sunxi_gpio_set_cfgbank(void *bank_base, int pin_offset, u32 val)
 {
-	u32 index = GPIO_CFG_INDEX(bank_offset);
-	u32 offset = GPIO_CFG_OFFSET(bank_offset);
+	u32 index = GPIO_CFG_INDEX(pin_offset);
+	u32 offset = GPIO_CFG_OFFSET(pin_offset);
 
-	clrsetbits_le32(&pio->cfg[index], 0xf << offset, val << offset);
+	clrsetbits_le32(bank_base + GPIO_CFG_REG_OFFSET + index * 4,
+			0xfU << offset, val << offset);
 }
 
 void sunxi_gpio_set_cfgpin(u32 pin, u32 val)
 {
 	u32 bank = GPIO_BANK(pin);
-	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
+	void *pio = BANK_TO_GPIO(bank);
 
-	sunxi_gpio_set_cfgbank(pio, pin, val);
+	sunxi_gpio_set_cfgbank(pio, GPIO_NUM(pin), val);
 }
 
-int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset)
+int sunxi_gpio_get_cfgbank(void *bank_base, int pin_offset)
 {
-	u32 index = GPIO_CFG_INDEX(bank_offset);
-	u32 offset = GPIO_CFG_OFFSET(bank_offset);
+	u32 index = GPIO_CFG_INDEX(pin_offset);
+	u32 offset = GPIO_CFG_OFFSET(pin_offset);
 	u32 cfg;
 
-	cfg = readl(&pio->cfg[index]);
+	cfg = readl(bank_base + GPIO_CFG_REG_OFFSET + index * 4);
 	cfg >>= offset;
 
 	return cfg & 0xf;
@@ -76,54 +92,56 @@ int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset)
 int sunxi_gpio_get_cfgpin(u32 pin)
 {
 	u32 bank = GPIO_BANK(pin);
-	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
+	void *bank_base = BANK_TO_GPIO(bank);
 
-	return sunxi_gpio_get_cfgbank(pio, pin);
+	return sunxi_gpio_get_cfgbank(bank_base, GPIO_NUM(pin));
 }
 
-static void sunxi_gpio_set_output_bank(struct sunxi_gpio *pio,
-				       int pin, bool set)
+static void sunxi_gpio_set_output_bank(void *bank_base, int pin, bool set)
 {
 	u32 mask = 1U << pin;
 
-	clrsetbits_le32(&pio->dat, set ? 0 : mask, set ? mask : 0);
+	clrsetbits_le32(bank_base + GPIO_DAT_REG_OFFSET,
+			set ? 0 : mask, set ? mask : 0);
 }
 
-static int sunxi_gpio_get_output_bank(struct sunxi_gpio *pio, int pin)
+static int sunxi_gpio_get_output_bank(void *bank_base, int pin)
 {
-	return !!(readl(&pio->dat) & (1U << pin));
+	return !!(readl(bank_base + GPIO_DAT_REG_OFFSET) & (1U << pin));
 }
 
 void sunxi_gpio_set_drv(u32 pin, u32 val)
 {
 	u32 bank = GPIO_BANK(pin);
-	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
+	void *bank_base = BANK_TO_GPIO(bank);
 
-	sunxi_gpio_set_drv_bank(pio, pin, val);
+	sunxi_gpio_set_drv_bank(bank_base, GPIO_NUM(pin), val);
 }
 
-void sunxi_gpio_set_drv_bank(struct sunxi_gpio *pio, u32 bank_offset, u32 val)
+void sunxi_gpio_set_drv_bank(void *bank_base, u32 pin_offset, u32 val)
 {
-	u32 index = GPIO_DRV_INDEX(bank_offset);
-	u32 offset = GPIO_DRV_OFFSET(bank_offset);
+	u32 index = GPIO_DRV_INDEX(pin_offset);
+	u32 offset = GPIO_DRV_OFFSET(pin_offset);
 
-	clrsetbits_le32(&pio->drv[index], 0x3 << offset, val << offset);
+	clrsetbits_le32(bank_base + GPIO_DRV_REG_OFFSET + index * 4,
+			0x3U << offset, val << offset);
 }
 
 void sunxi_gpio_set_pull(u32 pin, u32 val)
 {
 	u32 bank = GPIO_BANK(pin);
-	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
+	void *bank_base = BANK_TO_GPIO(bank);
 
-	sunxi_gpio_set_pull_bank(pio, pin, val);
+	sunxi_gpio_set_pull_bank(bank_base, GPIO_NUM(pin), val);
 }
 
-void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val)
+void sunxi_gpio_set_pull_bank(void *bank_base, int pin_offset, u32 val)
 {
-	u32 index = GPIO_PULL_INDEX(bank_offset);
-	u32 offset = GPIO_PULL_OFFSET(bank_offset);
+	u32 index = GPIO_PULL_INDEX(pin_offset);
+	u32 offset = GPIO_PULL_OFFSET(pin_offset);
 
-	clrsetbits_le32(&pio->pull[index], 0x3 << offset, val << offset);
+	clrsetbits_le32(bank_base + GPIO_PULL_REG_OFFSET + index * 4,
+			0x3U << offset, val << offset);
 }
 
 
@@ -133,7 +151,7 @@ void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val)
 static void sunxi_gpio_set_output(u32 pin, bool set)
 {
 	u32 bank = GPIO_BANK(pin);
-	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
+	void *pio = BANK_TO_GPIO(bank);
 
 	sunxi_gpio_set_output_bank(pio, GPIO_NUM(pin), set);
 }
@@ -141,7 +159,7 @@ static void sunxi_gpio_set_output(u32 pin, bool set)
 static int sunxi_gpio_get_output(u32 pin)
 {
 	u32 bank = GPIO_BANK(pin);
-	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
+	void *pio = BANK_TO_GPIO(bank);
 
 	return sunxi_gpio_get_output_bank(pio, GPIO_NUM(pin));
 }
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index e5102180902..946447e9136 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -35,7 +35,7 @@ struct sunxi_pinctrl_desc {
 };
 
 struct sunxi_pinctrl_plat {
-	struct sunxi_gpio __iomem *base;
+	void __iomem *base;
 };
 
 static int sunxi_pinctrl_get_pins_count(struct udevice *dev)
@@ -86,8 +86,8 @@ static int sunxi_pinctrl_pinmux_set(struct udevice *dev, uint pin_selector,
 	      sunxi_pinctrl_get_function_name(dev, func_selector),
 	      desc->functions[func_selector].mux);
 
-	sunxi_gpio_set_cfgbank(plat->base + bank, pin,
-			       desc->functions[func_selector].mux);
+	sunxi_gpio_set_cfgbank(plat->base + bank * SUNXI_PINCTRL_BANK_SIZE,
+			       pin, desc->functions[func_selector].mux);
 
 	return 0;
 }
@@ -102,7 +102,7 @@ static const struct pinconf_param sunxi_pinctrl_pinconf_params[] = {
 static int sunxi_pinctrl_pinconf_set_pull(struct sunxi_pinctrl_plat *plat,
 					  uint bank, uint pin, uint bias)
 {
-	struct sunxi_gpio *regs = &plat->base[bank];
+	void *regs = plat->base + bank * SUNXI_PINCTRL_BANK_SIZE;
 
 	sunxi_gpio_set_pull_bank(regs, pin, bias);
 
@@ -112,7 +112,7 @@ static int sunxi_pinctrl_pinconf_set_pull(struct sunxi_pinctrl_plat *plat,
 static int sunxi_pinctrl_pinconf_set_drive(struct sunxi_pinctrl_plat *plat,
 					   uint bank, uint pin, uint drive)
 {
-	struct sunxi_gpio *regs = &plat->base[bank];
+	void *regs = plat->base + bank * SUNXI_PINCTRL_BANK_SIZE;
 
 	if (drive < 10 || drive > 40)
 		return -EINVAL;
@@ -148,7 +148,7 @@ static int sunxi_pinctrl_get_pin_muxing(struct udevice *dev, uint pin_selector,
 	struct sunxi_pinctrl_plat *plat = dev_get_plat(dev);
 	int bank = pin_selector / SUNXI_GPIOS_PER_BANK;
 	int pin	 = pin_selector % SUNXI_GPIOS_PER_BANK;
-	int mux  = sunxi_gpio_get_cfgbank(plat->base + bank, pin);
+	int mux  = sunxi_gpio_get_cfgbank(plat->base + bank * SUNXI_PINCTRL_BANK_SIZE, pin);
 
 	switch (mux) {
 	case SUNXI_GPIO_INPUT:
@@ -206,7 +206,7 @@ static int sunxi_pinctrl_bind(struct udevice *dev)
 		if (!gpio_plat)
 			return -ENOMEM;
 
-		gpio_plat->regs = plat->base + i;
+		gpio_plat->regs = plat->base + i * SUNXI_PINCTRL_BANK_SIZE;
 		gpio_plat->bank_name[0] = 'P';
 		gpio_plat->bank_name[1] = 'A' + desc->first_bank + i;
 		gpio_plat->bank_name[2] = '\0';
-- 
2.35.8


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 07/22] pinctrl: sunxi: remove GPIO_EXTRA_HEADER
  2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
                   ` (5 preceding siblings ...)
  2023-09-28 21:54 ` [PATCH v2 06/22] pinctrl: sunxi: remove struct sunxi_gpio Andre Przywara
@ 2023-09-28 21:54 ` Andre Przywara
  2023-10-21  8:57   ` Samuel Holland
  2023-09-28 21:54 ` [PATCH v2 08/22] pinctrl: sunxi: move PIO_BASE into sunxi_gpio.h Andre Przywara
                   ` (14 subsequent siblings)
  21 siblings, 1 reply; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

U-Boot's generic GPIO_EXTRA_HEADER is a convenience symbol to allow code
to more easily include platform specific GPIO headers. This should not
be needed in a DM world anymore, since the generic GPIO framework
handles that nicely.
For Allwinner boards we still need to deal with non-DM GPIO in the SPL,
but this should become the exception, not the rule.

Make this more obvious by removing the definition of GPIO_EXTRA_HEADER,
and just force every legacy user of platform specific GPIO to include
the new sunxi_gpio.h header explicitly. Everyone doing so should feel
ashamed and should find a way to avoid it from now on.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arch/arm/Kconfig                                               | 1 -
 arch/arm/mach-sunxi/board.c                                    | 1 +
 arch/arm/mach-sunxi/dram_suniv.c                               | 2 +-
 arch/arm/mach-sunxi/spl_spi_sunxi.c                            | 1 +
 board/sunxi/board.c                                            | 1 +
 board/sunxi/chip.c                                             | 2 +-
 drivers/gpio/axp_gpio.c                                        | 1 +
 drivers/gpio/sunxi_gpio.c                                      | 1 +
 drivers/i2c/sun6i_p2wi.c                                       | 2 +-
 drivers/i2c/sun8i_rsb.c                                        | 2 +-
 drivers/mmc/sunxi_mmc.c                                        | 1 +
 drivers/pinctrl/sunxi/pinctrl-sunxi.c                          | 1 +
 drivers/video/hitachi_tx18d42vm_lcd.c                          | 1 +
 drivers/video/ssd2828.c                                        | 1 -
 drivers/video/sunxi/sunxi_display.c                            | 1 +
 drivers/video/sunxi/sunxi_lcd.c                                | 1 +
 arch/arm/include/asm/arch-sunxi/gpio.h => include/sunxi_gpio.h | 0
 17 files changed, 14 insertions(+), 6 deletions(-)
 rename arch/arm/include/asm/arch-sunxi/gpio.h => include/sunxi_gpio.h (100%)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 3fac92ebfcc..962b2bc3e5a 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1134,7 +1134,6 @@ config ARCH_SUNXI
 	select DM_MMC if MMC
 	select DM_SCSI if SCSI
 	select DM_SERIAL
-	select GPIO_EXTRA_HEADER
 	select OF_BOARD_SETUP
 	select OF_CONTROL
 	select OF_SEPARATE
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index 78597ad932c..4a1a0eacdba 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -17,6 +17,7 @@
 #include <i2c.h>
 #include <serial.h>
 #include <spl.h>
+#include <sunxi_gpio.h>
 #include <asm/cache.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
diff --git a/arch/arm/mach-sunxi/dram_suniv.c b/arch/arm/mach-sunxi/dram_suniv.c
index 3aa3ce76272..9e583e18553 100644
--- a/arch/arm/mach-sunxi/dram_suniv.c
+++ b/arch/arm/mach-sunxi/dram_suniv.c
@@ -13,10 +13,10 @@
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/dram.h>
-#include <asm/arch/gpio.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
 #include <hang.h>
+#include <sunxi_gpio.h>
 
 #define SDR_T_CAS			(0x2)
 #define SDR_T_RAS			(0x8)
diff --git a/arch/arm/mach-sunxi/spl_spi_sunxi.c b/arch/arm/mach-sunxi/spl_spi_sunxi.c
index 81159cfee61..c2410dd7bb1 100644
--- a/arch/arm/mach-sunxi/spl_spi_sunxi.c
+++ b/arch/arm/mach-sunxi/spl_spi_sunxi.c
@@ -13,6 +13,7 @@
 #include <linux/bitops.h>
 #include <linux/delay.h>
 #include <linux/libfdt.h>
+#include <sunxi_gpio.h>
 
 #ifdef CONFIG_SPL_OS_BOOT
 #error CONFIG_SPL_OS_BOOT is not supported yet
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 5cfb33468e5..7a1c708b9f2 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -38,6 +38,7 @@
 #include <asm/armv7.h>
 #endif
 #include <asm/gpio.h>
+#include <sunxi_gpio.h>
 #include <asm/io.h>
 #include <u-boot/crc.h>
 #include <env_internal.h>
diff --git a/board/sunxi/chip.c b/board/sunxi/chip.c
index cde04bebe96..eeee6319e79 100644
--- a/board/sunxi/chip.c
+++ b/board/sunxi/chip.c
@@ -12,7 +12,7 @@
 #include <w1-eeprom.h>
 #include <dm/device-internal.h>
 
-#include <asm/arch/gpio.h>
+#include <sunxi_gpio.h>
 
 #include <extension_board.h>
 
diff --git a/drivers/gpio/axp_gpio.c b/drivers/gpio/axp_gpio.c
index 49672193ffc..af6631697f5 100644
--- a/drivers/gpio/axp_gpio.c
+++ b/drivers/gpio/axp_gpio.c
@@ -14,6 +14,7 @@
 #include <dm/lists.h>
 #include <dm/root.h>
 #include <errno.h>
+#include <sunxi_gpio.h>
 
 static int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val);
 
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
index fe3f6ed0938..b52569104b7 100644
--- a/drivers/gpio/sunxi_gpio.c
+++ b/drivers/gpio/sunxi_gpio.c
@@ -17,6 +17,7 @@
 #include <asm/io.h>
 #include <asm/gpio.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <sunxi_gpio.h>
 
 /*
  * =======================================================================
diff --git a/drivers/i2c/sun6i_p2wi.c b/drivers/i2c/sun6i_p2wi.c
index d221323295d..b8e07a533ca 100644
--- a/drivers/i2c/sun6i_p2wi.c
+++ b/drivers/i2c/sun6i_p2wi.c
@@ -20,10 +20,10 @@
 #include <errno.h>
 #include <i2c.h>
 #include <reset.h>
+#include <sunxi_gpio.h>
 #include <time.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/p2wi.h>
 #include <asm/arch/prcm.h>
 #include <asm/arch/sys_proto.h>
diff --git a/drivers/i2c/sun8i_rsb.c b/drivers/i2c/sun8i_rsb.c
index 47fa05b6d1c..f36f2c7afac 100644
--- a/drivers/i2c/sun8i_rsb.c
+++ b/drivers/i2c/sun8i_rsb.c
@@ -14,10 +14,10 @@
 #include <dm.h>
 #include <errno.h>
 #include <i2c.h>
+#include <sunxi_gpio.h>
 #include <reset.h>
 #include <time.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/prcm.h>
 #include <asm/arch/rsb.h>
 
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index 23bc7da917a..03e33753fcf 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -27,6 +27,7 @@
 #include <asm/arch/cpu.h>
 #include <asm/arch/mmc.h>
 #include <linux/delay.h>
+#include <sunxi_gpio.h>
 
 #ifndef CCM_MMC_CTRL_MODE_SEL_NEW
 #define CCM_MMC_CTRL_MODE_SEL_NEW	0
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 946447e9136..fc80fe50b14 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -7,6 +7,7 @@
 #include <dm/pinctrl.h>
 #include <errno.h>
 #include <malloc.h>
+#include <sunxi_gpio.h>
 
 #include <asm/gpio.h>
 
diff --git a/drivers/video/hitachi_tx18d42vm_lcd.c b/drivers/video/hitachi_tx18d42vm_lcd.c
index 87c4d27438a..95984fe3d3d 100644
--- a/drivers/video/hitachi_tx18d42vm_lcd.c
+++ b/drivers/video/hitachi_tx18d42vm_lcd.c
@@ -10,6 +10,7 @@
 #include <linux/delay.h>
 
 #include <asm/gpio.h>
+#include <sunxi_gpio.h>
 #include <errno.h>
 
 /*
diff --git a/drivers/video/ssd2828.c b/drivers/video/ssd2828.c
index 4cdcbe7755a..948f5e74d0f 100644
--- a/drivers/video/ssd2828.c
+++ b/drivers/video/ssd2828.c
@@ -12,7 +12,6 @@
 #include <common.h>
 #include <malloc.h>
 #include <mipi_display.h>
-#include <asm/arch/gpio.h>
 #include <asm/gpio.h>
 #include <linux/delay.h>
 
diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c
index 9110a484821..8da44a1bb6d 100644
--- a/drivers/video/sunxi/sunxi_display.c
+++ b/drivers/video/sunxi/sunxi_display.c
@@ -31,6 +31,7 @@
 #include <malloc.h>
 #include <video.h>
 #include <dm/uclass-internal.h>
+#include <sunxi_gpio.h>
 #include "../videomodes.h"
 #include "../anx9804.h"
 #include "../hitachi_tx18d42vm_lcd.h"
diff --git a/drivers/video/sunxi/sunxi_lcd.c b/drivers/video/sunxi/sunxi_lcd.c
index 8b9c3b2bfa9..7a01cc343ca 100644
--- a/drivers/video/sunxi/sunxi_lcd.c
+++ b/drivers/video/sunxi/sunxi_lcd.c
@@ -17,6 +17,7 @@
 #include <asm/arch/lcdc.h>
 #include <asm/global_data.h>
 #include <asm/gpio.h>
+#include <sunxi_gpio.h>
 
 struct sunxi_lcd_priv {
 	struct display_timing timing;
diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/include/sunxi_gpio.h
similarity index 100%
rename from arch/arm/include/asm/arch-sunxi/gpio.h
rename to include/sunxi_gpio.h
-- 
2.35.8


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 08/22] pinctrl: sunxi: move PIO_BASE into sunxi_gpio.h
  2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
                   ` (6 preceding siblings ...)
  2023-09-28 21:54 ` [PATCH v2 07/22] pinctrl: sunxi: remove GPIO_EXTRA_HEADER Andre Przywara
@ 2023-09-28 21:54 ` Andre Przywara
  2023-09-28 21:54 ` [PATCH v2 09/22] pinctrl: sunxi: add new D1 pinctrl support Andre Przywara
                   ` (13 subsequent siblings)
  21 siblings, 0 replies; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

On the Allwinner platform we were describing a quite comprehensive
memory map in a per-SoC header unser arch/arm.
In the old days that was used by every driver, but nowadays it should
only be needed by SPL drivers (not using the DT). Many addresses in
there were never used, and some are not needed anymore.

To avoid a dependency on CPU specific headers in an arch specific
directory, move the definition of the pinctroller MMIO base address into
the sunxi_gpio.h header, because the SPL routines for GPIO should be the
only one needing this address.
This is a first step towards getting rid of cpu_sun[x]i.h completely,
and allows to remove the inclusion of that file from the sunxi_gpio.h
header.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arch/arm/include/asm/arch-sunxi/cpu_sun4i.h     |  2 --
 arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h |  2 --
 arch/arm/include/asm/arch-sunxi/cpu_sun9i.h     |  2 --
 include/sunxi_gpio.h                            | 12 +++++++++++-
 4 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
index f7ecc790dbf..d6fe51f24bc 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
@@ -91,7 +91,6 @@
 
 #define SUNXI_CCM_BASE			0x01c20000
 #define SUNXI_INTC_BASE			0x01c20400
-#define SUNXI_PIO_BASE			0x01c20800
 #define SUNXI_TIMER_BASE		0x01c20c00
 #ifndef CONFIG_SUNXI_GEN_SUN6I
 #define SUNXI_PWM_BASE			0x01c20e00
@@ -210,7 +209,6 @@ defined(CONFIG_MACH_SUN50I)
 
 #define SUNXI_R_TWI_BASE		0x01f02400
 #define SUNXI_R_UART_BASE		0x01f02800
-#define SUNXI_R_PIO_BASE		0x01f02c00
 #define SUN6I_P2WI_BASE			0x01f03400
 #define SUNXI_RSB_BASE			0x01f03400
 
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
index d9cf8ae0428..9b6bf843601 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
@@ -22,7 +22,6 @@
 #define SUNXI_SIDC_BASE			0x03006000
 #define SUNXI_SID_BASE			0x03006200
 #define SUNXI_TIMER_BASE		0x03009000
-#define SUNXI_PIO_BASE			0x0300B000
 #define SUNXI_PSI_BASE			0x0300C000
 
 #define SUNXI_GIC400_BASE		0x03020000
@@ -68,7 +67,6 @@
 #define SUNXI_R_CPUCFG_BASE		0x07000400
 #define SUNXI_PRCM_BASE			0x07010000
 #define SUNXI_R_WDOG_BASE		0x07020400
-#define SUNXI_R_PIO_BASE		0x07022000
 #define SUNXI_R_UART_BASE		0x07080000
 #define SUNXI_R_TWI_BASE		0x07081400
 
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
index 9c2d11b5901..20025be2319 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
@@ -81,7 +81,6 @@
 /* APB0 Module */
 #define SUNXI_CCM_BASE			(REGS_APB0_BASE + 0x0000)
 #define SUNXI_CCMMODULE_BASE		(REGS_APB0_BASE + 0x0400)
-#define SUNXI_PIO_BASE			(REGS_APB0_BASE + 0x0800)
 #define SUNXI_TIMER_BASE		(REGS_APB0_BASE + 0x0C00)
 #define SUNXI_PWM_BASE			(REGS_APB0_BASE + 0x1400)
 #define SUNXI_LRADC_BASE		(REGS_APB0_BASE + 0x1800)
@@ -102,7 +101,6 @@
 /* RCPUS Module */
 #define SUNXI_PRCM_BASE			(REGS_RCPUS_BASE + 0x1400)
 #define SUNXI_R_UART_BASE		(REGS_RCPUS_BASE + 0x2800)
-#define SUNXI_R_PIO_BASE		(REGS_RCPUS_BASE + 0x2c00)
 #define SUNXI_RSB_BASE			(REGS_RCPUS_BASE + 0x3400)
 
 /* Misc. */
diff --git a/include/sunxi_gpio.h b/include/sunxi_gpio.h
index e0fb5b5da63..c1fdf7ea1d7 100644
--- a/include/sunxi_gpio.h
+++ b/include/sunxi_gpio.h
@@ -12,7 +12,17 @@
 #define _SUNXI_GPIO_H
 
 #include <linux/types.h>
-#include <asm/arch/cpu.h>
+
+#if defined(CONFIG_MACH_SUN9I)
+#define SUNXI_PIO_BASE		0x06000800
+#define SUNXI_R_PIO_BASE	0x08002c00
+#elif defined(CONFIG_SUN50I_GEN_H6)
+#define SUNXI_PIO_BASE		0x0300b000
+#define SUNXI_R_PIO_BASE	0x07022000
+#else
+#define SUNXI_PIO_BASE		0x01c20800
+#define SUNXI_R_PIO_BASE	0x01f02c00
+#endif
 
 /*
  * sunxi has 9 banks of gpio, they are:
-- 
2.35.8


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 09/22] pinctrl: sunxi: add new D1 pinctrl support
  2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
                   ` (7 preceding siblings ...)
  2023-09-28 21:54 ` [PATCH v2 08/22] pinctrl: sunxi: move PIO_BASE into sunxi_gpio.h Andre Przywara
@ 2023-09-28 21:54 ` Andre Przywara
  2023-10-22  3:31   ` Samuel Holland
  2023-09-28 21:54 ` [PATCH v2 10/22] sunxi: introduce NCAT2 generation model Andre Przywara
                   ` (12 subsequent siblings)
  21 siblings, 1 reply; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

For the first time since at least the Allwinner A10 SoCs, the D1 (and
related cores) use a new pincontroller MMIO register layout, so we
cannot use our hardcoded, fixed offsets anymore.
Ideally this would all be handled by devicetree and DM drivers, but for
the DT-less SPL we still need the legacy interfaces.

Add a new Kconfig symbol to differenciate between the two generations of
pincontrollers, and just use that to just switch some basic symbols.
The rest is already abstracted enough, so works out of the box.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Sam Edwards <CFSworks@gmail.com>
Tested-by: Sam Edwards <CFSworks@gmail.com>
---
 arch/arm/mach-sunxi/Kconfig |  6 ++++++
 drivers/gpio/sunxi_gpio.c   | 17 +++++++++++++++--
 include/sunxi_gpio.h        | 10 ++++++++--
 3 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index d3ed62add99..d73c5e67050 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -158,6 +158,12 @@ config SUNXI_RVBAR_ALTERNATIVE
 config SUNXI_A64_TIMER_ERRATUM
 	bool
 
+config SUNXI_NEW_PINCTRL
+	bool
+	---help---
+	The Allwinner D1 and other new SoCs use a different register map
+	for the GPIO block, which we need to know about in the SPL.
+
 # Note only one of these may be selected at a time! But hidden choices are
 # not supported by Kconfig
 config SUNXI_GEN_SUN4I
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
index b52569104b7..c50996d0e12 100644
--- a/drivers/gpio/sunxi_gpio.c
+++ b/drivers/gpio/sunxi_gpio.c
@@ -40,10 +40,23 @@
 #define GPIO_DAT_REG_OFFSET	0x10
 
 #define GPIO_DRV_REG_OFFSET	0x14
-#define GPIO_DRV_INDEX(pin)	(((pin) & 0x1f) >> 4)
-#define GPIO_DRV_OFFSET(pin)	((((pin) & 0x1f) & 0xf) << 1)
+
+/*		Newer SoCs use a slightly different register layout */
+#ifdef CONFIG_SUNXI_NEW_PINCTRL
+/* pin drive strength: 4 bits per pin */
+#define GPIO_DRV_INDEX(pin)	((pin) / 8)
+#define GPIO_DRV_OFFSET(pin)	(((pin) % 8) * 4)
+
+#define GPIO_PULL_REG_OFFSET	0x24
+
+#else /* older generation pin controllers */
+/* pin drive strength: 2 bits per pin */
+#define GPIO_DRV_INDEX(pin)	((pin) / 16)
+#define GPIO_DRV_OFFSET(pin)	(((pin) % 16) * 2)
 
 #define GPIO_PULL_REG_OFFSET	0x1c
+#endif
+
 #define GPIO_PULL_INDEX(pin)	(((pin) & 0x1f) >> 4)
 #define GPIO_PULL_OFFSET(pin)	((((pin) & 0x1f) & 0xf) << 1)
 
diff --git a/include/sunxi_gpio.h b/include/sunxi_gpio.h
index c1fdf7ea1d7..30d8879dbd3 100644
--- a/include/sunxi_gpio.h
+++ b/include/sunxi_gpio.h
@@ -62,7 +62,6 @@
 #define SUN50I_H6_GPIO_POW_MOD_VAL	0x348
 
 #define SUNXI_GPIOS_PER_BANK	32
-#define SUNXI_PINCTRL_BANK_SIZE 0x24
 
 #define SUNXI_GPIO_NEXT(__gpio) \
 	((__gpio##_START) + SUNXI_GPIOS_PER_BANK)
@@ -102,7 +101,6 @@ enum sunxi_gpio_number {
 /* GPIO pin function config */
 #define SUNXI_GPIO_INPUT	0
 #define SUNXI_GPIO_OUTPUT	1
-#define SUNXI_GPIO_DISABLE	7
 
 #define SUN8I_H3_GPA_UART0	2
 #define SUN8I_H3_GPA_UART2	2
@@ -171,6 +169,14 @@ enum sunxi_gpio_number {
 
 #define SUN9I_GPN_R_RSB		3
 
+#ifdef CONFIG_SUNXI_NEW_PINCTRL
+	#define SUNXI_PINCTRL_BANK_SIZE	0x30
+	#define SUNXI_GPIO_DISABLE	0xf
+#else
+	#define SUNXI_PINCTRL_BANK_SIZE	0x24
+	#define SUNXI_GPIO_DISABLE	0x7
+#endif
+
 /* GPIO pin pull-up/down config */
 #define SUNXI_GPIO_PULL_DISABLE	0
 #define SUNXI_GPIO_PULL_UP	1
-- 
2.35.8


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 10/22] sunxi: introduce NCAT2 generation model
  2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
                   ` (8 preceding siblings ...)
  2023-09-28 21:54 ` [PATCH v2 09/22] pinctrl: sunxi: add new D1 pinctrl support Andre Przywara
@ 2023-09-28 21:54 ` Andre Przywara
  2023-10-22  3:40   ` Samuel Holland
  2023-09-28 21:54 ` [PATCH v2 11/22] pinctrl: sunxi: add Allwinner D1 pinctrl description Andre Przywara
                   ` (11 subsequent siblings)
  21 siblings, 1 reply; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

Allwinner seems to typically stick to a common MMIO memory map for
several SoCs, but from time to time does some breaking changes, which
also introduce new generations of some peripherals. The last time this
happened with the H6, which apart from re-organising the base addresses
also changed the clock controller significantly. We added a
CONFIG_SUN50I_GEN_H6 symbol back then to mark SoCs sharing those traits.

Now the Allwinner D1 changes the memory map again, and also extends the
pincontroller, among other peripherals.
To mark this generation of SoCs, add a CONFIG_SUNXI_GEN_NCAT2 symbol,
this name is reportedly used in the Allwinner BSP code, and prevents us
from inventing our own name.

Add this new symbol to some guards that were already checking for the H6
generation, since many features are shared between the two (like the
renovated clock controller).

This paves the way to introduce a first user of this generation.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arch/arm/include/asm/arch-sunxi/clock.h       |  2 +-
 arch/arm/include/asm/arch-sunxi/cpu.h         |  2 +
 .../include/asm/arch-sunxi/cpu_sunxi_ncat2.h  | 43 +++++++++++++++++++
 arch/arm/include/asm/arch-sunxi/mmc.h         |  2 +-
 arch/arm/include/asm/arch-sunxi/prcm.h        |  2 +-
 arch/arm/include/asm/arch-sunxi/timer.h       |  2 +-
 arch/arm/mach-sunxi/Kconfig                   | 12 +++++-
 arch/arm/mach-sunxi/Makefile                  |  1 +
 arch/arm/mach-sunxi/board.c                   | 22 ++++++----
 arch/arm/mach-sunxi/clock_sun50i_h6.c         |  7 ++-
 common/spl/Kconfig                            |  2 +-
 drivers/i2c/mvtwsi.c                          |  3 +-
 drivers/mmc/sunxi_mmc.c                       |  7 +--
 include/sunxi_gpio.h                          |  3 ++
 14 files changed, 90 insertions(+), 20 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h

diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h
index 2cfd5407423..3d34261b0e5 100644
--- a/arch/arm/include/asm/arch-sunxi/clock.h
+++ b/arch/arm/include/asm/arch-sunxi/clock.h
@@ -16,7 +16,7 @@
 /* clock control module regs definition */
 #if defined(CONFIG_MACH_SUN8I_A83T)
 #include <asm/arch/clock_sun8i_a83t.h>
-#elif defined(CONFIG_SUN50I_GEN_H6)
+#elif defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
 #include <asm/arch/clock_sun50i_h6.h>
 #elif defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) || \
       defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUNIV)
diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h b/arch/arm/include/asm/arch-sunxi/cpu.h
index b08f2023748..768c6572d6b 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu.h
@@ -10,6 +10,8 @@
 #include <asm/arch/cpu_sun9i.h>
 #elif defined(CONFIG_SUN50I_GEN_H6)
 #include <asm/arch/cpu_sun50i_h6.h>
+#elif defined(CONFIG_SUNXI_GEN_NCAT2)
+#include <asm/arch/cpu_sunxi_ncat2.h>
 #else
 #include <asm/arch/cpu_sun4i.h>
 #endif
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
new file mode 100644
index 00000000000..ca92c39927d
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
@@ -0,0 +1,43 @@
+/*
+ * (C) Copyright 2022 Arm Limited
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _SUNXI_CPU_SUNXI_NCAT2_H
+#define _SUNXI_CPU_SUNXI_NCAT2_H
+
+#define SUNXI_CCM_BASE			0x02001000
+#define SUNXI_TIMER_BASE		0x02050000
+
+#define SUNXI_UART0_BASE		0x02500000
+#define SUNXI_UART1_BASE		0x02500400
+#define SUNXI_UART2_BASE		0x02500800
+#define SUNXI_UART3_BASE		0x02500C00
+#define SUNXI_TWI0_BASE			0x02502000
+#define SUNXI_TWI1_BASE			0x02502400
+#define SUNXI_TWI2_BASE			0x02502800
+#define SUNXI_TWI3_BASE			0x02502C00
+
+#define SUNXI_SRAMC_BASE		0x03000000
+/* SID address space starts at 0x03006000, but e-fuse is at offset 0x200 */
+#define SUNXI_SIDC_BASE			0x03006000
+#define SUNXI_SID_BASE			0x03006200
+#define SUNXI_GIC400_BASE		0x03020000
+
+#define SUNXI_MMC0_BASE			0x04020000
+#define SUNXI_MMC1_BASE			0x04021000
+#define SUNXI_MMC2_BASE			0x04022000
+
+#define SUNXI_R_CPUCFG_BASE		0x07000400
+#define SUNXI_PRCM_BASE			0x07010000
+
+#define SUNXI_CPUCFG_BASE		0x09010000
+
+#ifndef __ASSEMBLY__
+void sunxi_board_init(void);
+void sunxi_reset(void);
+int sunxi_get_sid(unsigned int *sid);
+#endif
+
+#endif /* _SUNXI_CPU_SUNXI_NCAT2_H */
diff --git a/arch/arm/include/asm/arch-sunxi/mmc.h b/arch/arm/include/asm/arch-sunxi/mmc.h
index 5daacf10eb1..8ed3e0459c9 100644
--- a/arch/arm/include/asm/arch-sunxi/mmc.h
+++ b/arch/arm/include/asm/arch-sunxi/mmc.h
@@ -45,7 +45,7 @@ struct sunxi_mmc {
 	u32 chda;		/* 0x90 */
 	u32 cbda;		/* 0x94 */
 	u32 res2[26];
-#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
+#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
 	u32 res3[17];
 	u32 samp_dl;
 	u32 res4[46];
diff --git a/arch/arm/include/asm/arch-sunxi/prcm.h b/arch/arm/include/asm/arch-sunxi/prcm.h
index 5106076f5e9..c5418cfd28d 100644
--- a/arch/arm/include/asm/arch-sunxi/prcm.h
+++ b/arch/arm/include/asm/arch-sunxi/prcm.h
@@ -9,7 +9,7 @@
 #define _SUNXI_PRCM_H
 
 /* prcm regs definition */
-#if defined(CONFIG_SUN50I_GEN_H6)
+#if defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
 #include <asm/arch/prcm_sun50i.h>
 #else
 #include <asm/arch/prcm_sun6i.h>
diff --git a/arch/arm/include/asm/arch-sunxi/timer.h b/arch/arm/include/asm/arch-sunxi/timer.h
index bb5626d893b..e17db8588e2 100644
--- a/arch/arm/include/asm/arch-sunxi/timer.h
+++ b/arch/arm/include/asm/arch-sunxi/timer.h
@@ -76,7 +76,7 @@ struct sunxi_timer_reg {
 	struct sunxi_tgp tgp[4];
 	u8 res5[8];
 	u32 cpu_cfg;
-#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
+#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
 	u8 res3[16];
 	struct sunxi_wdog wdog[5];	/* We have 5 watchdogs */
 #endif
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index d73c5e67050..12eb51b2ea4 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -121,7 +121,7 @@ config AXP_PMIC_BUS
 config SUNXI_SRAM_ADDRESS
 	hex
 	default 0x10000 if MACH_SUN9I || MACH_SUN50I || MACH_SUN50I_H5
-	default 0x20000 if SUN50I_GEN_H6
+	default 0x20000 if SUN50I_GEN_H6 || SUNXI_GEN_NCAT2
 	default 0x0
 	---help---
 	Older Allwinner SoCs have their mask boot ROM mapped just below 4GB,
@@ -189,6 +189,14 @@ config SUN50I_GEN_H6
 	Select this for sunxi SoCs which have H6 like peripherals, clocks
 	and memory map.
 
+config SUNXI_GEN_NCAT2
+	bool
+	select MMC_SUNXI_HAS_NEW_MODE
+	select SUPPORT_SPL
+	---help---
+	Select this for sunxi SoCs which have D1 like peripherals, clocks
+	and memory map.
+
 config SUNXI_DRAM_DW
 	bool
 	---help---
@@ -810,6 +818,7 @@ config VIDEO_SUNXI
 	depends on !MACH_SUN9I
 	depends on !MACH_SUN50I
 	depends on !SUN50I_GEN_H6
+	depends on !SUNXI_GEN_NCAT2
 	select VIDEO
 	select DISPLAY
 	imply VIDEO_DT_SIMPLEFB
@@ -1023,6 +1032,7 @@ config SPL_STACK_R_ADDR
 	default 0x2fe00000 if MACH_SUN9I
 	default 0x4fe00000 if MACH_SUN50I
 	default 0x4fe00000 if SUN50I_GEN_H6
+	default 0x4fe00000 if SUNXI_GEN_NCAT2
 
 config SPL_SPI_SUNXI
 	bool "Support for SPI Flash on Allwinner SoCs in SPL"
diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
index 671211e9322..1d4c70ec352 100644
--- a/arch/arm/mach-sunxi/Makefile
+++ b/arch/arm/mach-sunxi/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_MACH_SUN8I)	+= clock_sun6i.o
 endif
 obj-$(CONFIG_MACH_SUN9I)	+= clock_sun9i.o gtbus_sun9i.o
 obj-$(CONFIG_SUN50I_GEN_H6)	+= clock_sun50i_h6.o
+obj-$(CONFIG_SUNXI_GEN_NCAT2)	+= clock_sun50i_h6.o
 ifndef CONFIG_ARM64
 obj-y	+= timer.o
 endif
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index 4a1a0eacdba..d572314f0da 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -176,13 +176,19 @@ static int gpio_init(void)
 #error Unsupported console port number. Please fix pin mux settings in board.c
 #endif
 
-#ifdef CONFIG_SUN50I_GEN_H6
-	/* Update PIO power bias configuration by copy hardware detected value */
-	val = readl(SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
-	writel(val, SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
-	val = readl(SUNXI_R_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
-	writel(val, SUNXI_R_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
-#endif
+	/*
+	 * Update PIO power bias configuration by copying the hardware
+	 * detected value.
+	 */
+	if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
+	    IS_ENABLED(CONFIG_SUN50I_GEN_NCAT2)) {
+		val = readl(SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
+		writel(val, SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
+	}
+	if (IS_ENABLED(CONFIG_SUN50I_GEN_H6)) {
+		val = readl(SUNXI_R_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
+		writel(val, SUNXI_R_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
+	}
 
 	return 0;
 }
@@ -481,7 +487,7 @@ void reset_cpu(void)
 		/* sun5i sometimes gets stuck without this */
 		writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode);
 	}
-#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
+#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
 #if defined(CONFIG_MACH_SUN50I_H6)
 	/* WDOG is broken for some H6 rev. use the R_WDOG instead */
 	static const struct sunxi_wdog *wdog =
diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
index 7926394cf76..767a39fa2ab 100644
--- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
@@ -18,8 +18,11 @@ void clock_init_safe(void)
 		setbits_le32(&prcm->res_cal_ctrl, 2);
 	}
 
-	clrbits_le32(&prcm->res_cal_ctrl, 1);
-	setbits_le32(&prcm->res_cal_ctrl, 1);
+	if (IS_ENABLED(CONFIG_MACH_SUN50I_H616) ||
+	    IS_ENABLED(CONFIG_MACH_SUN50I_H6)) {
+		clrbits_le32(&prcm->res_cal_ctrl, 1);
+		setbits_le32(&prcm->res_cal_ctrl, 1);
+	}
 
 	if (IS_ENABLED(CONFIG_MACH_SUN50I_H6)) {
 		/* set key field for ldo enable */
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 1c2fe78e3e0..cd59b9240c2 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -265,7 +265,7 @@ config SPL_TEXT_BASE
 	default 0x402F0400 if AM33XX
 	default 0x40301350 if OMAP54XX
 	default 0x10060 if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN9I
-	default 0x20060 if SUN50I_GEN_H6
+	default 0x20060 if SUN50I_GEN_H6 || SUNXI_GEN_NCAT2
 	default 0x00060 if ARCH_SUNXI
 	default 0xfffc0000 if ARCH_ZYNQMP
 	default 0x0
diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c
index 14cdb0f6635..c38330f758a 100644
--- a/drivers/i2c/mvtwsi.c
+++ b/drivers/i2c/mvtwsi.c
@@ -124,7 +124,8 @@ enum mvtwsi_ctrl_register_fields {
  * on other platforms, it is a normal r/w bit, which is cleared by writing 0.
  */
 
-#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
+#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || \
+    defined(CONFIG_SUNXI_GEN_NCAT2)
 #define	MVTWSI_CONTROL_CLEAR_IFLG	0x00000008
 #else
 #define	MVTWSI_CONTROL_CLEAR_IFLG	0x00000000
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index 03e33753fcf..519ef602145 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -57,6 +57,7 @@ static bool sunxi_mmc_can_calibrate(void)
 	return IS_ENABLED(CONFIG_MACH_SUN50I) ||
 	       IS_ENABLED(CONFIG_MACH_SUN50I_H5) ||
 	       IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
+	       IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2) ||
 	       IS_ENABLED(CONFIG_MACH_SUN8I_R40);
 }
 
@@ -191,7 +192,7 @@ static int mmc_config_clock(struct sunxi_mmc_priv *priv, struct mmc *mmc)
 	rval &= ~SUNXI_MMC_CLK_DIVIDER_MASK;
 	writel(rval, &priv->reg->clkcr);
 
-#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
+#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
 	/* A64 supports calibration of delays on MMC controller and we
 	 * have to set delay of zero before starting calibration.
 	 * Allwinner BSP driver sets a delay only in the case of
@@ -544,7 +545,7 @@ struct mmc *sunxi_mmc_init(int sdc_no)
 
 	/* config ahb clock */
 	debug("init mmc %d clock and io\n", sdc_no);
-#if !defined(CONFIG_SUN50I_GEN_H6)
+#if !defined(CONFIG_SUN50I_GEN_H6) && !defined(CONFIG_SUNXI_GEN_NCAT2)
 	setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MMC(sdc_no));
 
 #ifdef CONFIG_SUNXI_GEN_SUN6I
@@ -619,7 +620,7 @@ static unsigned get_mclk_offset(void)
 	if (IS_ENABLED(CONFIG_MACH_SUN9I_A80))
 		return 0x410;
 
-	if (IS_ENABLED(CONFIG_SUN50I_GEN_H6))
+	if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) || IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
 		return 0x830;
 
 	return 0x88;
diff --git a/include/sunxi_gpio.h b/include/sunxi_gpio.h
index 30d8879dbd3..db3742c0397 100644
--- a/include/sunxi_gpio.h
+++ b/include/sunxi_gpio.h
@@ -19,6 +19,9 @@
 #elif defined(CONFIG_SUN50I_GEN_H6)
 #define SUNXI_PIO_BASE		0x0300b000
 #define SUNXI_R_PIO_BASE	0x07022000
+#elif defined(CONFIG_SUNXI_GEN_NCAT2)
+#define SUNXI_PIO_BASE		0x02000000
+#define SUNXI_R_PIO_BASE	0x07022000
 #else
 #define SUNXI_PIO_BASE		0x01c20800
 #define SUNXI_R_PIO_BASE	0x01f02c00
-- 
2.35.8


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 11/22] pinctrl: sunxi: add Allwinner D1 pinctrl description
  2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
                   ` (9 preceding siblings ...)
  2023-09-28 21:54 ` [PATCH v2 10/22] sunxi: introduce NCAT2 generation model Andre Przywara
@ 2023-09-28 21:54 ` Andre Przywara
  2023-10-21  4:34   ` Samuel Holland
  2023-09-28 21:54 ` [PATCH v2 12/22] clk: sunxi: Add support for the D1 CCU Andre Przywara
                   ` (10 subsequent siblings)
  21 siblings, 1 reply; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

Apart from using the new pinctrl MMIO register layout, the Allwinner D1
and related SoCs still need to usual set of mux values hardcoded in
U-Boot's pinctrl driver.
Add the values we need so far to this list, so that DM based drivers
will just work without further ado.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 drivers/pinctrl/sunxi/Kconfig         |  4 ++++
 drivers/pinctrl/sunxi/pinctrl-sunxi.c | 28 +++++++++++++++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index 77da90836b6..c8f937d91e9 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -124,4 +124,8 @@ config PINCTRL_SUN50I_H616_R
 	default MACH_SUN50I_H616
 	select PINCTRL_SUNXI
 
+config PINCTRL_SUN20I_D1
+	bool "Support for the Allwinner D1/R528 PIO"
+	select PINCTRL_SUNXI
+
 endif
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index fc80fe50b14..66876d9954a 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -748,6 +748,28 @@ static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h616_r_pinctrl_desc
 	.num_banks	= 1,
 };
 
+static const struct sunxi_pinctrl_function sun20i_d1_pinctrl_functions[] = {
+	{ "emac",	8 },	/* PE0-PE15 */
+	{ "gpio_in",	0 },
+	{ "gpio_out",	1 },
+	{ "mmc0",	2 },	/* PF0-PF5 */
+	{ "mmc2",	3 },	/* PC1-PC7 */
+	{ "spi0",	2 },	/* PC2-PC7 */
+#if IS_ENABLED(CONFIG_UART0_PORT_F)
+	{ "uart0",	3 },	/* PF2,PF4 */
+#else
+	{ "uart0",	6 },	/* PB0-PB1, PB8-PB9, PE2-PE3 */
+#endif
+	{ "uart3",	7 },	/* PB6-PB7 */
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun20i_d1_pinctrl_desc = {
+	.functions	= sun20i_d1_pinctrl_functions,
+	.num_functions	= ARRAY_SIZE(sun20i_d1_pinctrl_functions),
+	.first_bank	= SUNXI_GPIO_A,
+	.num_banks	= 7,
+};
+
 static const struct udevice_id sunxi_pinctrl_ids[] = {
 #ifdef CONFIG_PINCTRL_SUNIV_F1C100S
 	{
@@ -904,6 +926,12 @@ static const struct udevice_id sunxi_pinctrl_ids[] = {
 		.compatible = "allwinner,sun50i-h616-r-pinctrl",
 		.data = (ulong)&sun50i_h616_r_pinctrl_desc,
 	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN20I_D1
+	{
+		.compatible = "allwinner,sun20i-d1-pinctrl",
+		.data = (ulong)&sun20i_d1_pinctrl_desc,
+	},
 #endif
 	{}
 };
-- 
2.35.8


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 12/22] clk: sunxi: Add support for the D1 CCU
  2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
                   ` (10 preceding siblings ...)
  2023-09-28 21:54 ` [PATCH v2 11/22] pinctrl: sunxi: add Allwinner D1 pinctrl description Andre Przywara
@ 2023-09-28 21:54 ` Andre Przywara
  2023-10-19 23:53   ` Samuel Holland
  2023-09-28 21:54 ` [PATCH v2 13/22] sunxi: clock: D1/R528: Enable PLL LDO during PLL1 setup Andre Przywara
                   ` (9 subsequent siblings)
  21 siblings, 1 reply; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

From: Samuel Holland <samuel@sholland.org>

Since the D1 CCU binding is defined, we can add support for its
gates/resets, following the pattern of the existing drivers.

Signed-off-by: Samuel Holland <samuel@sholland.org>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Acked-by: Sean Anderson <seanga2@gmail.com>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 drivers/clk/sunxi/Kconfig                 |   6 +
 drivers/clk/sunxi/Makefile                |   1 +
 drivers/clk/sunxi/clk_d1.c                |  84 ++++++++++++
 drivers/clk/sunxi/clk_sunxi.c             |   5 +
 include/dt-bindings/clock/sun20i-d1-ccu.h | 158 ++++++++++++++++++++++
 include/dt-bindings/reset/sun20i-d1-ccu.h |  79 +++++++++++
 6 files changed, 333 insertions(+)
 create mode 100644 drivers/clk/sunxi/clk_d1.c
 create mode 100644 include/dt-bindings/clock/sun20i-d1-ccu.h
 create mode 100644 include/dt-bindings/reset/sun20i-d1-ccu.h

diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
index bf11fad6eef..f65e482ba4c 100644
--- a/drivers/clk/sunxi/Kconfig
+++ b/drivers/clk/sunxi/Kconfig
@@ -87,6 +87,12 @@ config CLK_SUN8I_H3
 	  This enables common clock driver support for platforms based
 	  on Allwinner H3/H5 SoC.
 
+config CLK_SUN20I_D1
+	bool "Clock driver for Allwinner D1"
+	help
+	  This enables common clock driver support for platforms based
+	  on Allwinner D1 SoC.
+
 config CLK_SUN50I_H6
 	bool "Clock driver for Allwinner H6"
 	default MACH_SUN50I_H6
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 895da02ebea..90a277489dc 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_CLK_SUN8I_R40) += clk_r40.o
 obj-$(CONFIG_CLK_SUN8I_V3S) += clk_v3s.o
 obj-$(CONFIG_CLK_SUN9I_A80) += clk_a80.o
 obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o
+obj-$(CONFIG_CLK_SUN20I_D1) += clk_d1.o
 obj-$(CONFIG_CLK_SUN50I_H6) += clk_h6.o
 obj-$(CONFIG_CLK_SUN50I_H6_R) += clk_h6_r.o
 obj-$(CONFIG_CLK_SUN50I_H616) += clk_h616.o
diff --git a/drivers/clk/sunxi/clk_d1.c b/drivers/clk/sunxi/clk_d1.c
new file mode 100644
index 00000000000..9dae761de83
--- /dev/null
+++ b/drivers/clk/sunxi/clk_d1.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <clk/sunxi.h>
+#include <dt-bindings/clock/sun20i-d1-ccu.h>
+#include <dt-bindings/reset/sun20i-d1-ccu.h>
+#include <linux/bitops.h>
+
+static struct ccu_clk_gate d1_gates[] = {
+	[CLK_APB0]		= GATE_DUMMY,
+
+	[CLK_BUS_MMC0]		= GATE(0x84c, BIT(0)),
+	[CLK_BUS_MMC1]		= GATE(0x84c, BIT(1)),
+	[CLK_BUS_MMC2]		= GATE(0x84c, BIT(2)),
+	[CLK_BUS_UART0]		= GATE(0x90c, BIT(0)),
+	[CLK_BUS_UART1]		= GATE(0x90c, BIT(1)),
+	[CLK_BUS_UART2]		= GATE(0x90c, BIT(2)),
+	[CLK_BUS_UART3]		= GATE(0x90c, BIT(3)),
+	[CLK_BUS_UART4]		= GATE(0x90c, BIT(4)),
+	[CLK_BUS_UART5]		= GATE(0x90c, BIT(5)),
+	[CLK_BUS_I2C0]		= GATE(0x91c, BIT(0)),
+	[CLK_BUS_I2C1]		= GATE(0x91c, BIT(1)),
+	[CLK_BUS_I2C2]		= GATE(0x91c, BIT(2)),
+	[CLK_BUS_I2C3]		= GATE(0x91c, BIT(3)),
+	[CLK_SPI0]		= GATE(0x940, BIT(31)),
+	[CLK_SPI1]		= GATE(0x944, BIT(31)),
+	[CLK_BUS_SPI0]		= GATE(0x96c, BIT(0)),
+	[CLK_BUS_SPI1]		= GATE(0x96c, BIT(1)),
+
+	[CLK_BUS_EMAC]		= GATE(0x97c, BIT(0)),
+
+	[CLK_USB_OHCI0]		= GATE(0xa70, BIT(31)),
+	[CLK_USB_OHCI1]		= GATE(0xa74, BIT(31)),
+	[CLK_BUS_OHCI0]		= GATE(0xa8c, BIT(0)),
+	[CLK_BUS_OHCI1]		= GATE(0xa8c, BIT(1)),
+	[CLK_BUS_EHCI0]		= GATE(0xa8c, BIT(4)),
+	[CLK_BUS_EHCI1]		= GATE(0xa8c, BIT(5)),
+	[CLK_BUS_OTG]		= GATE(0xa8c, BIT(8)),
+	[CLK_BUS_LRADC]		= GATE(0xa9c, BIT(0)),
+
+	[CLK_RISCV]		= GATE(0xd04, BIT(31)),
+};
+
+static struct ccu_reset d1_resets[] = {
+	[RST_BUS_MMC0]		= RESET(0x84c, BIT(16)),
+	[RST_BUS_MMC1]		= RESET(0x84c, BIT(17)),
+	[RST_BUS_MMC2]		= RESET(0x84c, BIT(18)),
+	[RST_BUS_UART0]		= RESET(0x90c, BIT(16)),
+	[RST_BUS_UART1]		= RESET(0x90c, BIT(17)),
+	[RST_BUS_UART2]		= RESET(0x90c, BIT(18)),
+	[RST_BUS_UART3]		= RESET(0x90c, BIT(19)),
+	[RST_BUS_UART4]		= RESET(0x90c, BIT(20)),
+	[RST_BUS_UART5]		= RESET(0x90c, BIT(21)),
+	[RST_BUS_I2C0]		= RESET(0x91c, BIT(16)),
+	[RST_BUS_I2C1]		= RESET(0x91c, BIT(17)),
+	[RST_BUS_I2C2]		= RESET(0x91c, BIT(18)),
+	[RST_BUS_I2C3]		= RESET(0x91c, BIT(19)),
+	[RST_BUS_SPI0]		= RESET(0x96c, BIT(16)),
+	[RST_BUS_SPI1]		= RESET(0x96c, BIT(17)),
+
+	[RST_BUS_EMAC]		= RESET(0x97c, BIT(16)),
+
+	[RST_USB_PHY0]		= RESET(0xa70, BIT(30)),
+	[RST_USB_PHY1]		= RESET(0xa74, BIT(30)),
+	[RST_BUS_OHCI0]		= RESET(0xa8c, BIT(16)),
+	[RST_BUS_OHCI1]		= RESET(0xa8c, BIT(17)),
+	[RST_BUS_EHCI0]		= RESET(0xa8c, BIT(20)),
+	[RST_BUS_EHCI1]		= RESET(0xa8c, BIT(21)),
+	[RST_BUS_OTG]		= RESET(0xa8c, BIT(24)),
+	[RST_BUS_LRADC]		= RESET(0xa9c, BIT(16)),
+};
+
+const struct ccu_desc d1_ccu_desc = {
+	.gates	= d1_gates,
+	.resets	= d1_resets,
+	.num_gates = ARRAY_SIZE(d1_gates),
+	.num_resets = ARRAY_SIZE(d1_resets),
+};
diff --git a/drivers/clk/sunxi/clk_sunxi.c b/drivers/clk/sunxi/clk_sunxi.c
index ec02a2d0370..a0011a35d91 100644
--- a/drivers/clk/sunxi/clk_sunxi.c
+++ b/drivers/clk/sunxi/clk_sunxi.c
@@ -118,6 +118,7 @@ extern const struct ccu_desc a64_ccu_desc;
 extern const struct ccu_desc a80_ccu_desc;
 extern const struct ccu_desc a80_mmc_clk_desc;
 extern const struct ccu_desc a83t_ccu_desc;
+extern const struct ccu_desc d1_ccu_desc;
 extern const struct ccu_desc f1c100s_ccu_desc;
 extern const struct ccu_desc h3_ccu_desc;
 extern const struct ccu_desc h6_ccu_desc;
@@ -214,6 +215,10 @@ static const struct udevice_id sunxi_clk_ids[] = {
 #ifdef CONFIG_CLK_SUNIV_F1C100S
 	{ .compatible = "allwinner,suniv-f1c100s-ccu",
 	  .data = (ulong)&f1c100s_ccu_desc },
+#endif
+#ifdef CONFIG_CLK_SUN20I_D1
+	{ .compatible = "allwinner,sun20i-d1-ccu",
+	  .data = (ulong)&d1_ccu_desc },
 #endif
 	{ }
 };
diff --git a/include/dt-bindings/clock/sun20i-d1-ccu.h b/include/dt-bindings/clock/sun20i-d1-ccu.h
new file mode 100644
index 00000000000..e143b992976
--- /dev/null
+++ b/include/dt-bindings/clock/sun20i-d1-ccu.h
@@ -0,0 +1,158 @@
+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/*
+ * Copyright (C) 2020 huangzhenwei@allwinnertech.com
+ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN20I_D1_CCU_H_
+#define _DT_BINDINGS_CLK_SUN20I_D1_CCU_H_
+
+#define CLK_PLL_CPUX		0
+#define CLK_PLL_DDR0		1
+#define CLK_PLL_PERIPH0_4X	2
+#define CLK_PLL_PERIPH0_2X	3
+#define CLK_PLL_PERIPH0_800M	4
+#define CLK_PLL_PERIPH0		5
+#define CLK_PLL_PERIPH0_DIV3	6
+#define CLK_PLL_VIDEO0_4X	7
+#define CLK_PLL_VIDEO0_2X	8
+#define CLK_PLL_VIDEO0		9
+#define CLK_PLL_VIDEO1_4X	10
+#define CLK_PLL_VIDEO1_2X	11
+#define CLK_PLL_VIDEO1		12
+#define CLK_PLL_VE		13
+#define CLK_PLL_AUDIO0_4X	14
+#define CLK_PLL_AUDIO0_2X	15
+#define CLK_PLL_AUDIO0		16
+#define CLK_PLL_AUDIO1		17
+#define CLK_PLL_AUDIO1_DIV2	18
+#define CLK_PLL_AUDIO1_DIV5	19
+#define CLK_CPUX		20
+#define CLK_CPUX_AXI		21
+#define CLK_CPUX_APB		22
+#define CLK_PSI_AHB		23
+#define CLK_APB0		24
+#define CLK_APB1		25
+#define CLK_MBUS		26
+#define CLK_DE			27
+#define CLK_BUS_DE		28
+#define CLK_DI			29
+#define CLK_BUS_DI		30
+#define CLK_G2D			31
+#define CLK_BUS_G2D		32
+#define CLK_CE			33
+#define CLK_BUS_CE		34
+#define CLK_VE			35
+#define CLK_BUS_VE		36
+#define CLK_BUS_DMA		37
+#define CLK_BUS_MSGBOX0		38
+#define CLK_BUS_MSGBOX1		39
+#define CLK_BUS_MSGBOX2		40
+#define CLK_BUS_SPINLOCK	41
+#define CLK_BUS_HSTIMER		42
+#define CLK_AVS			43
+#define CLK_BUS_DBG		44
+#define CLK_BUS_PWM		45
+#define CLK_BUS_IOMMU		46
+#define CLK_DRAM		47
+#define CLK_MBUS_DMA		48
+#define CLK_MBUS_VE		49
+#define CLK_MBUS_CE		50
+#define CLK_MBUS_TVIN		51
+#define CLK_MBUS_CSI		52
+#define CLK_MBUS_G2D		53
+#define CLK_MBUS_RISCV		54
+#define CLK_BUS_DRAM		55
+#define CLK_MMC0		56
+#define CLK_MMC1		57
+#define CLK_MMC2		58
+#define CLK_BUS_MMC0		59
+#define CLK_BUS_MMC1		60
+#define CLK_BUS_MMC2		61
+#define CLK_BUS_UART0		62
+#define CLK_BUS_UART1		63
+#define CLK_BUS_UART2		64
+#define CLK_BUS_UART3		65
+#define CLK_BUS_UART4		66
+#define CLK_BUS_UART5		67
+#define CLK_BUS_I2C0		68
+#define CLK_BUS_I2C1		69
+#define CLK_BUS_I2C2		70
+#define CLK_BUS_I2C3		71
+#define CLK_SPI0		72
+#define CLK_SPI1		73
+#define CLK_BUS_SPI0		74
+#define CLK_BUS_SPI1		75
+#define CLK_EMAC_25M		76
+#define CLK_BUS_EMAC		77
+#define CLK_IR_TX		78
+#define CLK_BUS_IR_TX		79
+#define CLK_BUS_GPADC		80
+#define CLK_BUS_THS		81
+#define CLK_I2S0		82
+#define CLK_I2S1		83
+#define CLK_I2S2		84
+#define CLK_I2S2_ASRC		85
+#define CLK_BUS_I2S0		86
+#define CLK_BUS_I2S1		87
+#define CLK_BUS_I2S2		88
+#define CLK_SPDIF_TX		89
+#define CLK_SPDIF_RX		90
+#define CLK_BUS_SPDIF		91
+#define CLK_DMIC		92
+#define CLK_BUS_DMIC		93
+#define CLK_AUDIO_DAC		94
+#define CLK_AUDIO_ADC		95
+#define CLK_BUS_AUDIO		96
+#define CLK_USB_OHCI0		97
+#define CLK_USB_OHCI1		98
+#define CLK_BUS_OHCI0		99
+#define CLK_BUS_OHCI1		100
+#define CLK_BUS_EHCI0		101
+#define CLK_BUS_EHCI1		102
+#define CLK_BUS_OTG		103
+#define CLK_BUS_LRADC		104
+#define CLK_BUS_DPSS_TOP	105
+#define CLK_HDMI_24M		106
+#define CLK_HDMI_CEC_32K	107
+#define CLK_HDMI_CEC		108
+#define CLK_BUS_HDMI		109
+#define CLK_MIPI_DSI		110
+#define CLK_BUS_MIPI_DSI	111
+#define CLK_TCON_LCD0		112
+#define CLK_BUS_TCON_LCD0	113
+#define CLK_TCON_TV		114
+#define CLK_BUS_TCON_TV		115
+#define CLK_TVE			116
+#define CLK_BUS_TVE_TOP		117
+#define CLK_BUS_TVE		118
+#define CLK_TVD			119
+#define CLK_BUS_TVD_TOP		120
+#define CLK_BUS_TVD		121
+#define CLK_LEDC		122
+#define CLK_BUS_LEDC		123
+#define CLK_CSI_TOP		124
+#define CLK_CSI_MCLK		125
+#define CLK_BUS_CSI		126
+#define CLK_TPADC		127
+#define CLK_BUS_TPADC		128
+#define CLK_BUS_TZMA		129
+#define CLK_DSP			130
+#define CLK_BUS_DSP_CFG		131
+#define CLK_RISCV		132
+#define CLK_RISCV_AXI		133
+#define CLK_BUS_RISCV_CFG	134
+#define CLK_FANOUT_24M		135
+#define CLK_FANOUT_12M		136
+#define CLK_FANOUT_16M		137
+#define CLK_FANOUT_25M		138
+#define CLK_FANOUT_32K		139
+#define CLK_FANOUT_27M		140
+#define CLK_FANOUT_PCLK		141
+#define CLK_FANOUT0		142
+#define CLK_FANOUT1		143
+#define CLK_FANOUT2		144
+#define CLK_BUS_CAN0		145
+#define CLK_BUS_CAN1		146
+
+#endif /* _DT_BINDINGS_CLK_SUN20I_D1_CCU_H_ */
diff --git a/include/dt-bindings/reset/sun20i-d1-ccu.h b/include/dt-bindings/reset/sun20i-d1-ccu.h
new file mode 100644
index 00000000000..f8001cf50bf
--- /dev/null
+++ b/include/dt-bindings/reset/sun20i-d1-ccu.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/*
+ * Copyright (c) 2020 huangzhenwei@allwinnertech.com
+ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN20I_D1_CCU_H_
+#define _DT_BINDINGS_RST_SUN20I_D1_CCU_H_
+
+#define RST_MBUS		0
+#define RST_BUS_DE		1
+#define RST_BUS_DI		2
+#define RST_BUS_G2D		3
+#define RST_BUS_CE		4
+#define RST_BUS_VE		5
+#define RST_BUS_DMA		6
+#define RST_BUS_MSGBOX0		7
+#define RST_BUS_MSGBOX1		8
+#define RST_BUS_MSGBOX2		9
+#define RST_BUS_SPINLOCK	10
+#define RST_BUS_HSTIMER		11
+#define RST_BUS_DBG		12
+#define RST_BUS_PWM		13
+#define RST_BUS_DRAM		14
+#define RST_BUS_MMC0		15
+#define RST_BUS_MMC1		16
+#define RST_BUS_MMC2		17
+#define RST_BUS_UART0		18
+#define RST_BUS_UART1		19
+#define RST_BUS_UART2		20
+#define RST_BUS_UART3		21
+#define RST_BUS_UART4		22
+#define RST_BUS_UART5		23
+#define RST_BUS_I2C0		24
+#define RST_BUS_I2C1		25
+#define RST_BUS_I2C2		26
+#define RST_BUS_I2C3		27
+#define RST_BUS_SPI0		28
+#define RST_BUS_SPI1		29
+#define RST_BUS_EMAC		30
+#define RST_BUS_IR_TX		31
+#define RST_BUS_GPADC		32
+#define RST_BUS_THS		33
+#define RST_BUS_I2S0		34
+#define RST_BUS_I2S1		35
+#define RST_BUS_I2S2		36
+#define RST_BUS_SPDIF		37
+#define RST_BUS_DMIC		38
+#define RST_BUS_AUDIO		39
+#define RST_USB_PHY0		40
+#define RST_USB_PHY1		41
+#define RST_BUS_OHCI0		42
+#define RST_BUS_OHCI1		43
+#define RST_BUS_EHCI0		44
+#define RST_BUS_EHCI1		45
+#define RST_BUS_OTG		46
+#define RST_BUS_LRADC		47
+#define RST_BUS_DPSS_TOP	48
+#define RST_BUS_HDMI_SUB	49
+#define RST_BUS_HDMI_MAIN	50
+#define RST_BUS_MIPI_DSI	51
+#define RST_BUS_TCON_LCD0	52
+#define RST_BUS_TCON_TV		53
+#define RST_BUS_LVDS0		54
+#define RST_BUS_TVE		55
+#define RST_BUS_TVE_TOP		56
+#define RST_BUS_TVD		57
+#define RST_BUS_TVD_TOP		58
+#define RST_BUS_LEDC		59
+#define RST_BUS_CSI		60
+#define RST_BUS_TPADC		61
+#define RST_DSP			62
+#define RST_BUS_DSP_CFG		63
+#define RST_BUS_DSP_DBG		64
+#define RST_BUS_RISCV_CFG	65
+#define RST_BUS_CAN0		66
+#define RST_BUS_CAN1		67
+
+#endif /* _DT_BINDINGS_RST_SUN20I_D1_CCU_H_ */
-- 
2.35.8


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 13/22] sunxi: clock: D1/R528: Enable PLL LDO during PLL1 setup
  2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
                   ` (11 preceding siblings ...)
  2023-09-28 21:54 ` [PATCH v2 12/22] clk: sunxi: Add support for the D1 CCU Andre Przywara
@ 2023-09-28 21:54 ` Andre Przywara
  2023-09-28 21:54 ` [PATCH v2 14/22] sunxi: clock: support D1/R528 PLL6 clock Andre Przywara
                   ` (8 subsequent siblings)
  21 siblings, 0 replies; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

The D1/R528/T113s SoCs introduce a new "LDO enable" bit in the CPUX_PLL.
Just enable that when we program that PLL.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h |  1 +
 arch/arm/mach-sunxi/clock_sun50i_h6.c             | 12 +++++++-----
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
index 37df4410eaa..9895c2c220e 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
@@ -228,6 +228,7 @@ struct sunxi_ccm_reg {
 
 /* pll1 bit field */
 #define CCM_PLL1_CTRL_EN		BIT(31)
+#define CCM_PLL1_LDO_EN			BIT(30)
 #define CCM_PLL1_LOCK_EN		BIT(29)
 #define CCM_PLL1_LOCK			BIT(28)
 #define CCM_PLL1_OUT_EN			BIT(27)
diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
index 767a39fa2ab..d32e33465f5 100644
--- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
@@ -89,11 +89,13 @@ void clock_set_pll1(unsigned int clk)
 	writel(val, &ccm->cpu_axi_cfg);
 
 	/* clk = 24*n/p, p is ignored if clock is >288MHz */
-	writel(CCM_PLL1_CTRL_EN | CCM_PLL1_LOCK_EN | CCM_PLL1_CLOCK_TIME_2 |
-#ifdef CONFIG_MACH_SUN50I_H616
-	       CCM_PLL1_OUT_EN |
-#endif
-	       CCM_PLL1_CTRL_N(clk / 24000000), &ccm->pll1_cfg);
+	val = CCM_PLL1_CTRL_EN | CCM_PLL1_LOCK_EN | CCM_PLL1_CLOCK_TIME_2;
+	val |= CCM_PLL1_CTRL_N(clk / 24000000);
+	if (IS_ENABLED(CONFIG_MACH_SUN50I_H616))
+	       val |= CCM_PLL1_OUT_EN;
+	if (IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
+	       val |= CCM_PLL1_OUT_EN | CCM_PLL1_LDO_EN;
+	writel(val, &ccm->pll1_cfg);
 	while (!(readl(&ccm->pll1_cfg) & CCM_PLL1_LOCK)) {}
 
 	/* Switch CPU to PLL1 */
-- 
2.35.8


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 14/22] sunxi: clock: support D1/R528 PLL6 clock
  2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
                   ` (12 preceding siblings ...)
  2023-09-28 21:54 ` [PATCH v2 13/22] sunxi: clock: D1/R528: Enable PLL LDO during PLL1 setup Andre Przywara
@ 2023-09-28 21:54 ` Andre Przywara
  2023-09-28 21:54 ` [PATCH v2 15/22] Kconfig: sunxi: prepare for using drivers/ram/sunxi Andre Przywara
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

The PLL_PERIPH0 clock changed a bit in the D1/R528/T113s SoCs: there is
new P0 divider at bits [18:16], and the M divider is 1.

Add code to support this version of "PLL6".

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 .../include/asm/arch-sunxi/clock_sun50i_h6.h  |  2 ++
 arch/arm/mach-sunxi/clock_sun50i_h6.c         | 24 +++++++++++++------
 2 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
index 9895c2c220e..8471e11aa02 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
@@ -249,6 +249,8 @@ struct sunxi_ccm_reg {
 #define CCM_PLL6_CTRL_EN		BIT(31)
 #define CCM_PLL6_LOCK_EN		BIT(29)
 #define CCM_PLL6_LOCK			BIT(28)
+#define CCM_PLL6_CTRL_P0_SHIFT		16
+#define CCM_PLL6_CTRL_P0_MASK		(0x7 << CCM_PLL6_CTRL_P0_SHIFT)
 #define CCM_PLL6_CTRL_N_SHIFT		8
 #define CCM_PLL6_CTRL_N_MASK		(0xff << CCM_PLL6_CTRL_N_SHIFT)
 #define CCM_PLL6_CTRL_DIV1_SHIFT	0
diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
index d32e33465f5..daae994787e 100644
--- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
@@ -110,16 +110,26 @@ unsigned int clock_get_pll6(void)
 {
 	struct sunxi_ccm_reg *const ccm =
 		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
-	int m = IS_ENABLED(CONFIG_MACH_SUN50I_H6) ? 4 : 2;
-
 	uint32_t rval = readl(&ccm->pll6_cfg);
 	int n = ((rval & CCM_PLL6_CTRL_N_MASK) >> CCM_PLL6_CTRL_N_SHIFT) + 1;
-	int div1 = ((rval & CCM_PLL6_CTRL_DIV1_MASK) >>
-			CCM_PLL6_CTRL_DIV1_SHIFT) + 1;
 	int div2 = ((rval & CCM_PLL6_CTRL_DIV2_MASK) >>
-			CCM_PLL6_CTRL_DIV2_SHIFT) + 1;
-	/* The register defines PLL6-2X or PLL6-4X, not plain PLL6 */
-	return 24000000 / m * n / div1 / div2;
+		    CCM_PLL6_CTRL_DIV2_SHIFT) + 1;
+	int div1, m;
+
+	if (IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2)) {
+		div1 = ((rval & CCM_PLL6_CTRL_P0_MASK) >>
+			CCM_PLL6_CTRL_P0_SHIFT) + 1;
+		m = 1;
+	} else {
+		div1 = ((rval & CCM_PLL6_CTRL_DIV1_MASK) >>
+			CCM_PLL6_CTRL_DIV1_SHIFT) + 1;
+		if (IS_ENABLED(CONFIG_MACH_SUN50I_H6))
+			m = 4;
+		else
+			m = 2;
+	}
+
+	return 24000000U * n / m / div1 / div2;
 }
 
 int clock_twi_onoff(int port, int state)
-- 
2.35.8


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 15/22] Kconfig: sunxi: prepare for using drivers/ram/sunxi
  2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
                   ` (13 preceding siblings ...)
  2023-09-28 21:54 ` [PATCH v2 14/22] sunxi: clock: support D1/R528 PLL6 clock Andre Przywara
@ 2023-09-28 21:54 ` Andre Przywara
  2023-10-22  3:44   ` Samuel Holland
  2023-09-28 21:54 ` [PATCH v2 16/22] sunxi: add R528/T113-s3/D1(s) DRAM initialisation code Andre Przywara
                   ` (6 subsequent siblings)
  21 siblings, 1 reply; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

At the moment all Allwinner DRAM initialisation routines are stored in
arch/arm/mach-sunxi, even though those "drivers" are just a giant
collection of writel's, without any architectural dependency.

The R528/T113-s SoC (with ARM cores) and the D1/D1s Soc (with RISC-V
cores) share the same die, so should share the same DRAM init routines as
well.

To prepare for this, add a new sunxi directory inside drivers/ram, and
add some stub entries to prepare for the addition of the share DRAM code
for those SoCs.

The RISC-V D1(s) SoCs will probably use SPL_DM, so make this entry
depend on that already.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 drivers/ram/Kconfig       |  3 ++-
 drivers/ram/sunxi/Kconfig | 14 ++++++++++++++
 2 files changed, 16 insertions(+), 1 deletion(-)
 create mode 100644 drivers/ram/sunxi/Kconfig

diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig
index bf999645774..5b07e920301 100644
--- a/drivers/ram/Kconfig
+++ b/drivers/ram/Kconfig
@@ -109,8 +109,9 @@ config IMXRT_SDRAM
 
 source "drivers/ram/aspeed/Kconfig"
 source "drivers/ram/cadence/Kconfig"
+source "drivers/ram/octeon/Kconfig"
 source "drivers/ram/rockchip/Kconfig"
 source "drivers/ram/sifive/Kconfig"
 source "drivers/ram/stm32mp1/Kconfig"
-source "drivers/ram/octeon/Kconfig"
 source "drivers/ram/starfive/Kconfig"
+source "drivers/ram/sunxi/Kconfig"
diff --git a/drivers/ram/sunxi/Kconfig b/drivers/ram/sunxi/Kconfig
new file mode 100644
index 00000000000..261d7f57409
--- /dev/null
+++ b/drivers/ram/sunxi/Kconfig
@@ -0,0 +1,14 @@
+config DRAM_SUN20I_D1
+	bool "DM DRAM driver support for Allwinner D1"
+	depends on RAM && ARCH_SUNXI
+	default y
+	help
+	  This enables support for DRAM drivers using the driver model
+	  for Allwinner SoCs.
+
+config DRAM_SUN8I_R528
+	bool "DRAM driver support for Allwinner R528/T113s"
+	depends on ARCH_SUNXI
+	default y if MACH_SUN8I_R528
+	help
+	  Select this DRAM controller driver for the R528/T113s SoCs.
-- 
2.35.8


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 16/22] sunxi: add R528/T113-s3/D1(s) DRAM initialisation code
  2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
                   ` (14 preceding siblings ...)
  2023-09-28 21:54 ` [PATCH v2 15/22] Kconfig: sunxi: prepare for using drivers/ram/sunxi Andre Przywara
@ 2023-09-28 21:54 ` Andre Przywara
  2023-10-22  3:52   ` Samuel Holland
  2023-09-28 21:54 ` [PATCH v2 17/22] sunxi: add Allwinner R528/T113 SoC support Andre Przywara
                   ` (5 subsequent siblings)
  21 siblings, 1 reply; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

The Allwinner R528/T113-s/D1/D1s SoCs all share the same die, so use the
same DRAM initialisation code.
Make use of prior art here and lift some code from awboot[1], which
carried init code based on earlier decompilation efforts, but with a
GPL2 license tag.
This code has been heavily reworked and cleaned up, to match previous
DRAM routines for other SoCs, and also to be closer to U-Boot's coding
style and support routines.
The actual DRAM chip timing parameters are included in the main file,
since they cover all DRAM types, and are protected by a new Kconfig
CONFIG_SUNXI_DRAM_TYPE symbol, which allows the compiler to pick only
the relevant settings, at build time.

The relevant DRAM chips/board specific configuration parameters are
delivered via Kconfig, so this code here should work for all supported
SoCs and DRAM chips combinations.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Tested-by: Sam Edwards <CFSworks@gmail.com>
---
 drivers/Makefile                   |    1 +
 drivers/ram/Makefile               |    3 +
 drivers/ram/sunxi/Kconfig          |   59 ++
 drivers/ram/sunxi/Makefile         |    4 +
 drivers/ram/sunxi/dram_sun20i_d1.c | 1432 ++++++++++++++++++++++++++++
 drivers/ram/sunxi/dram_sun20i_d1.h |   73 ++
 6 files changed, 1572 insertions(+)
 create mode 100644 drivers/ram/sunxi/Makefile
 create mode 100644 drivers/ram/sunxi/dram_sun20i_d1.c
 create mode 100644 drivers/ram/sunxi/dram_sun20i_d1.h

diff --git a/drivers/Makefile b/drivers/Makefile
index efc2a4afb24..5a4bedf7305 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_$(SPL_)ALTERA_SDRAM) += ddr/altera/
 obj-$(CONFIG_ARCH_IMX8M) += ddr/imx/imx8m/
 obj-$(CONFIG_IMX8ULP_DRAM) += ddr/imx/imx8ulp/
 obj-$(CONFIG_ARCH_IMX9) += ddr/imx/imx9/
+obj-$(CONFIG_DRAM_SUN8I_R528) += ram/
 obj-$(CONFIG_SPL_DM_RESET) += reset/
 obj-$(CONFIG_SPL_MUSB_NEW) += usb/musb-new/
 obj-$(CONFIG_SPL_USB_GADGET) += usb/gadget/
diff --git a/drivers/ram/Makefile b/drivers/ram/Makefile
index 6eb1a241359..b4750ea11c4 100644
--- a/drivers/ram/Makefile
+++ b/drivers/ram/Makefile
@@ -23,6 +23,9 @@ obj-$(CONFIG_RAM_SIFIVE) += sifive/
 ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_SPL_STARFIVE_DDR) += starfive/
 endif
+
+obj-$(CONFIG_DRAM_SUN8I_R528) += sunxi/
+
 obj-$(CONFIG_ARCH_OCTEON) += octeon/
 
 obj-$(CONFIG_ARCH_RMOBILE) += renesas/
diff --git a/drivers/ram/sunxi/Kconfig b/drivers/ram/sunxi/Kconfig
index 261d7f57409..35eeda58efa 100644
--- a/drivers/ram/sunxi/Kconfig
+++ b/drivers/ram/sunxi/Kconfig
@@ -12,3 +12,62 @@ config DRAM_SUN8I_R528
 	default y if MACH_SUN8I_R528
 	help
 	  Select this DRAM controller driver for the R528/T113s SoCs.
+
+if DRAM_SUN20I_D1 || DRAM_SUN8I_R528
+
+config DRAM_SUNXI_ODT_EN
+	hex "DRAM ODT EN parameter"
+	default 0x1
+	help
+	  ODT EN value from vendor DRAM settings.
+
+config DRAM_SUNXI_TPR0
+	hex "DRAM TPR0 parameter"
+	default 0x0
+	help
+	  TPR0 value from vendor DRAM settings.
+
+config DRAM_SUNXI_TPR11
+	hex "DRAM TPR11 parameter"
+	default 0x0
+	help
+	  TPR11 value from vendor DRAM settings.
+
+config DRAM_SUNXI_TPR12
+	hex "DRAM TPR12 parameter"
+	default 0x0
+	help
+	  TPR12 value from vendor DRAM settings.
+
+config DRAM_SUNXI_TPR13
+	hex "DRAM TPR13 parameter"
+	default 0x0
+	help
+	  TPR13 value from vendor DRAM settings. It tells which features
+	  should be configured.
+
+choice
+	prompt "DRAM chip type"
+	default SUNXI_DRAM_TYPE_DDR3 if DRAM_SUN8I_R528 || DRAM_SUN20I_D1
+
+config SUNXI_DRAM_TYPE_DDR2
+        bool "DDR2 chips"
+
+config SUNXI_DRAM_TYPE_DDR3
+        bool "DDR3 chips"
+
+config SUNXI_DRAM_TYPE_LPDDR2
+        bool "LPDDR2 chips"
+
+config SUNXI_DRAM_TYPE_LPDDR3
+        bool "LPDDR3 chips"
+endchoice
+
+config SUNXI_DRAM_TYPE
+	int
+	default 2 if SUNXI_DRAM_TYPE_DDR2
+	default 3 if SUNXI_DRAM_TYPE_DDR3
+	default 6 if SUNXI_DRAM_TYPE_LPDDR2
+	default 7 if SUNXI_DRAM_TYPE_LPDDR3
+
+endif
diff --git a/drivers/ram/sunxi/Makefile b/drivers/ram/sunxi/Makefile
new file mode 100644
index 00000000000..d6fb2cf0b65
--- /dev/null
+++ b/drivers/ram/sunxi/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-$(CONFIG_DRAM_SUN20I_D1) += dram_sun20i_d1.o
+obj-$(CONFIG_DRAM_SUN8I_R528) += dram_sun20i_d1.o
diff --git a/drivers/ram/sunxi/dram_sun20i_d1.c b/drivers/ram/sunxi/dram_sun20i_d1.c
new file mode 100644
index 00000000000..c766fc24065
--- /dev/null
+++ b/drivers/ram/sunxi/dram_sun20i_d1.c
@@ -0,0 +1,1432 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Allwinner D1/D1s/R528/T113-sx DRAM initialisation
+ *
+ * As usual there is no documentation for the memory controller or PHY IP
+ * used here. The baseline of this code was lifted from awboot[1], which
+ * seems to be based on some form of de-compilation of some original Allwinner
+ * code bits (with a GPL2 license tag from the very beginning).
+ * This version here is a reworked version, to match the U-Boot coding style
+ * and style of the other Allwinner DRAM drivers.
+ *
+ * [1] https://github.com/szemzoa/awboot.git
+ */
+
+#include <asm/io.h>
+#include <common.h>
+#ifdef CONFIG_RAM
+  #include <dm.h>
+  #include <ram.h>
+#endif
+#include <linux/delay.h>
+
+#include "dram_sun20i_d1.h"
+
+#ifndef SUNXI_SID_BASE
+#define SUNXI_SID_BASE	0x3006200
+#endif
+
+#ifndef SUNXI_CCM_BASE
+#define SUNXI_CCM_BASE	0x2001000
+#endif
+
+static void sid_read_ldoB_cal(const dram_para_t *para)
+{
+	uint32_t reg;
+
+	reg = (readl(SUNXI_SID_BASE + 0x1c) & 0xff00) >> 8;
+
+	if (reg == 0)
+		return;
+
+	switch (para->dram_type) {
+	case SUNXI_DRAM_TYPE_DDR2:
+		break;
+	case SUNXI_DRAM_TYPE_DDR3:
+		if (reg > 0x20)
+			reg -= 0x16;
+		break;
+	default:
+		reg = 0;
+		break;
+	}
+
+	clrsetbits_le32(0x3000150, 0xff00, reg << 8);
+}
+
+static void dram_voltage_set(const dram_para_t *para)
+{
+	int vol;
+
+	switch (para->dram_type) {
+	case SUNXI_DRAM_TYPE_DDR2:
+		vol = 47;
+		break;
+	case SUNXI_DRAM_TYPE_DDR3:
+		vol = 25;
+		break;
+	default:
+		vol = 0;
+		break;
+	}
+
+	clrsetbits_le32(0x3000150, 0x20ff00, vol << 8);
+
+	udelay(1);
+
+	sid_read_ldoB_cal(para);
+}
+
+static void dram_enable_all_master(void)
+{
+	writel(~0, 0x3102020);
+	writel(0xff, 0x3102024);
+	writel(0xffff, 0x3102028);
+	udelay(10);
+}
+
+static void dram_disable_all_master(void)
+{
+	writel(1, 0x3102020);
+	writel(0, 0x3102024);
+	writel(0, 0x3102028);
+	udelay(10);
+}
+
+static void eye_delay_compensation(const dram_para_t *para)
+{
+	uint32_t delay;
+	unsigned long ptr;
+
+	// DATn0IOCR, n =  0...7
+	delay = (para->dram_tpr11 & 0xf) << 9;
+	delay |= (para->dram_tpr12 & 0xf) << 1;
+	for (ptr = 0x3103310; ptr < 0x3103334; ptr += 4)
+		setbits_le32(ptr, delay);
+
+	// DATn1IOCR, n =  0...7
+	delay = (para->dram_tpr11 & 0xf0) << 5;
+	delay |= (para->dram_tpr12 & 0xf0) >> 3;
+	for (ptr = 0x3103390; ptr != 0x31033b4; ptr += 4)
+		setbits_le32(ptr, delay);
+
+	// PGCR0: assert AC loopback FIFO reset
+	clrbits_le32(0x3103100, 0x04000000);
+
+	// ??
+
+	delay = (para->dram_tpr11 & 0xf0000) >> 7;
+	delay |= (para->dram_tpr12 & 0xf0000) >> 15;
+	setbits_le32(0x3103334, delay);
+	setbits_le32(0x3103338, delay);
+
+	delay = (para->dram_tpr11 & 0xf00000) >> 11;
+	delay |= (para->dram_tpr12 & 0xf00000) >> 19;
+	setbits_le32(0x31033b4, delay);
+	setbits_le32(0x31033b8, delay);
+
+	setbits_le32(0x310333c, (para->dram_tpr11 & 0xf0000) << 9);
+	setbits_le32(0x31033bc, (para->dram_tpr11 & 0xf00000) << 5);
+
+	// PGCR0: release AC loopback FIFO reset
+	setbits_le32(0x3103100, BIT(26));
+
+	udelay(1);
+
+	delay = (para->dram_tpr10 & 0xf0) << 4;
+	for (ptr = 0x3103240; ptr != 0x310327c; ptr += 4)
+		setbits_le32(ptr, delay);
+	for (ptr = 0x3103228; ptr != 0x3103240; ptr += 4)
+		setbits_le32(ptr, delay);
+
+	setbits_le32(0x3103218, (para->dram_tpr10 & 0x0f) << 8);
+	setbits_le32(0x310321c, (para->dram_tpr10 & 0x0f) << 8);
+
+	setbits_le32(0x3103280, (para->dram_tpr10 & 0xf00) >> 4);
+}
+
+/*
+ * Main purpose of the auto_set_timing routine seems to be to calculate all
+ * timing settings for the specific type of sdram used. Read together with
+ * an sdram datasheet for context on the various variables.
+ */
+static void mctl_set_timing_params(const dram_para_t *para,
+				   const dram_config_t *config)
+{
+	/* DRAM_TPR0 */
+	u8 tccd		= 2;
+	u8 tfaw;
+	u8 trrd;
+	u8 trcd;
+	u8 trc;
+
+	/* DRAM_TPR1 */
+	u8 txp;
+	u8 twtr;
+	u8 trtp		= 4;
+	u8 twr;
+	u8 trp;
+	u8 tras;
+
+	/* DRAM_TPR2 */
+	u16 trefi;
+	u16 trfc;
+
+	u8 tcksrx;
+	u8 tckesr;
+	u8 trd2wr;
+	u8 twr2rd;
+	u8 trasmax;
+	u8 twtp;
+	u8 tcke;
+	u8 tmod;
+	u8 tmrd;
+	u8 tmrw;
+
+	u8 tcl;
+	u8 tcwl;
+	u8 t_rdata_en;
+	u8 wr_latency;
+
+	u32 mr0;
+	u32 mr1;
+	u32 mr2;
+	u32 mr3;
+
+	u32 tdinit0;
+	u32 tdinit1;
+	u32 tdinit2;
+	u32 tdinit3;
+
+	switch (para->dram_type) {
+	case SUNXI_DRAM_TYPE_DDR2:
+		/* DRAM_TPR0 */
+		tfaw		= ns_to_t(50);
+		trrd		= ns_to_t(10);
+		trcd		= ns_to_t(20);
+		trc		= ns_to_t(65);
+
+		/* DRAM_TPR1 */
+		txp		= 2;
+		twtr		= ns_to_t(8);
+		twr		= ns_to_t(15);
+		trp		= ns_to_t(15);
+		tras		= ns_to_t(45);
+
+		/* DRAM_TRP2 */
+		trfc		= ns_to_t(328);
+		trefi		= ns_to_t(7800) / 32;
+
+		trasmax		= CONFIG_DRAM_CLK / 30;
+		if (CONFIG_DRAM_CLK < 409) {
+			t_rdata_en	= 1;
+			tcl		= 3;
+			mr0		= 0x06a3;
+		} else {
+			t_rdata_en	= 2;
+			tcl		= 4;
+			mr0		= 0x0e73;
+		}
+		tmrd		= 2;
+		twtp		= twr + 5;
+		tcksrx		= 5;
+		tckesr		= 4;
+		trd2wr		= 4;
+		tcke		= 3;
+		tmod		= 12;
+		wr_latency	= 1;
+		tmrw		= 0;
+		twr2rd		= twtr + 5;
+		tcwl		= 0;
+
+		mr1		= para->dram_mr1;
+		mr2		= 0;
+		mr3		= 0;
+
+		tdinit0		= 200 * CONFIG_DRAM_CLK + 1;
+		tdinit1		= 100 * CONFIG_DRAM_CLK / 1000 + 1;
+		tdinit2		= 200 * CONFIG_DRAM_CLK + 1;
+		tdinit3		= 1 * CONFIG_DRAM_CLK + 1;
+
+		break;
+	case SUNXI_DRAM_TYPE_DDR3:
+		trfc		= ns_to_t(350);
+		trefi		= ns_to_t(7800) / 32 + 1;	// XXX
+
+		twtr		= ns_to_t(8) + 2;		// + 2 ? XXX
+		/* Only used by trd2wr calculation, which gets discard below */
+//		twr		= max(ns_to_t(15), 2);
+		trrd		= max(ns_to_t(10), 2);
+		txp		= max(ns_to_t(10), 2);
+
+		if (CONFIG_DRAM_CLK <= 800) {
+			tfaw		= ns_to_t(50);
+			trcd		= ns_to_t(15);
+			trp		= ns_to_t(15);
+			trc		= ns_to_t(53);
+			tras		= ns_to_t(38);
+
+			mr0		= 0x1c70;
+			mr2		= 0x18;
+			tcl		= 6;
+			wr_latency	= 2;
+			tcwl		= 4;
+			t_rdata_en	= 4;
+		} else {
+			tfaw		= ns_to_t(35);
+			trcd		= ns_to_t(14);
+			trp		= ns_to_t(14);
+			trc		= ns_to_t(48);
+			tras		= ns_to_t(34);
+
+			mr0		= 0x1e14;
+			mr2		= 0x20;
+			tcl		= 7;
+			wr_latency	= 3;
+			tcwl		= 5;
+			t_rdata_en	= 5;
+		}
+
+		trasmax		= CONFIG_DRAM_CLK / 30;
+		twtp		= tcwl + 2 + twtr;		// WL+BL/2+tWTR
+		/* Gets overwritten below */
+//		trd2wr		= tcwl + 2 + twr;		// WL+BL/2+tWR
+		twr2rd		= tcwl + twtr;			// WL+tWTR
+
+		tdinit0		= 500 * CONFIG_DRAM_CLK + 1;	// 500 us
+		tdinit1		= 360 * CONFIG_DRAM_CLK / 1000 + 1;   // 360 ns
+		tdinit2		= 200 * CONFIG_DRAM_CLK + 1;	// 200 us
+		tdinit3		= 1 * CONFIG_DRAM_CLK + 1;	//   1 us
+
+		mr1		= para->dram_mr1;
+		mr3		= 0;
+		tcke		= 3;
+		tcksrx		= 5;
+		tckesr		= 4;
+		if (((config->dram_tpr13 & 0xc) == 0x04) || CONFIG_DRAM_CLK < 912)
+			trd2wr	   = 5;
+		else
+			trd2wr	   = 6;
+
+		tmod		= 12;
+		tmrd		= 4;
+		tmrw		= 0;
+
+		break;
+	case SUNXI_DRAM_TYPE_LPDDR2:
+		tfaw		= max(ns_to_t(50), 4);
+		trrd		= max(ns_to_t(10), 1);
+		trcd		= max(ns_to_t(24), 2);
+		trc		= ns_to_t(70);
+		txp		= ns_to_t(8);
+		if (txp < 2) {
+			txp++;
+			twtr	= 2;
+		} else {
+			twtr	= txp;
+		}
+		twr		= max(ns_to_t(15), 2);
+		trp		= ns_to_t(17);
+		tras		= ns_to_t(42);
+		trefi		= ns_to_t(3900) / 32;
+		trfc		= ns_to_t(210);
+
+		trasmax		= CONFIG_DRAM_CLK / 60;
+		mr3		= para->dram_mr3;
+		twtp		= twr + 5;
+		mr2		= 6;
+		mr1		= 5;
+		tcksrx		= 5;
+		tckesr		= 5;
+		trd2wr		= 10;
+		tcke		= 2;
+		tmod		= 5;
+		tmrd		= 5;
+		tmrw		= 3;
+		tcl		= 4;
+		wr_latency	= 1;
+		t_rdata_en	= 1;
+
+		tdinit0		= 200 * CONFIG_DRAM_CLK + 1;
+		tdinit1		= 100 * CONFIG_DRAM_CLK / 1000 + 1;
+		tdinit2		= 11 * CONFIG_DRAM_CLK + 1;
+		tdinit3		= 1 * CONFIG_DRAM_CLK + 1;
+		twr2rd		= twtr + 5;
+		tcwl		= 2;
+		mr1		= 195;
+		mr0		= 0;
+
+		break;
+	case SUNXI_DRAM_TYPE_LPDDR3:
+		tfaw		= max(ns_to_t(50), 4);
+		trrd		= max(ns_to_t(10), 1);
+		trcd		= max(ns_to_t(24), 2);
+		trc		= ns_to_t(70);
+		twtr		= max(ns_to_t(8), 2);
+		twr		= max(ns_to_t(15), 2);
+		trp		= ns_to_t(17);
+		tras		= ns_to_t(42);
+		trefi		= ns_to_t(3900) / 32;
+		trfc		= ns_to_t(210);
+		txp		= twtr;
+
+		trasmax		= CONFIG_DRAM_CLK / 60;
+		if (CONFIG_DRAM_CLK < 800) {
+			tcwl	   = 4;
+			wr_latency = 3;
+			t_rdata_en = 6;
+			mr2		   = 12;
+		} else {
+			tcwl	   = 3;
+			tcke	   = 6;
+			wr_latency = 2;
+			t_rdata_en = 5;
+			mr2		   = 10;
+		}
+		twtp		= tcwl + 5;
+		tcl		= 7;
+		mr3		= para->dram_mr3;
+		tcksrx		= 5;
+		tckesr		= 5;
+		trd2wr		= 13;
+		tcke		= 3;
+		tmod		= 12;
+		tdinit0		= 400 * CONFIG_DRAM_CLK + 1;
+		tdinit1		= 500 * CONFIG_DRAM_CLK / 1000 + 1;
+		tdinit2		= 11 * CONFIG_DRAM_CLK + 1;
+		tdinit3		= 1 * CONFIG_DRAM_CLK + 1;
+		tmrd		= 5;
+		tmrw		= 5;
+		twr2rd		= tcwl + twtr + 5;
+		mr1		= 195;
+		mr0		= 0;
+
+		break;
+	default:
+		trfc		= 128;
+		trp		= 6;
+		trefi		= 98;
+		txp		= 10;
+		twr		= 8;
+		twtr		= 3;
+		tras		= 14;
+		tfaw		= 16;
+		trc		= 20;
+		trcd		= 6;
+		trrd		= 3;
+
+		twr2rd		= 8;
+		tcksrx		= 4;
+		tckesr		= 3;
+		trd2wr		= 4;
+		trasmax		= 27;
+		twtp		= 12;
+		tcke		= 2;
+		tmod		= 6;
+		tmrd		= 2;
+		tmrw		= 0;
+		tcwl		= 3;
+		tcl		= 3;
+		wr_latency	= 1;
+		t_rdata_en	= 1;
+		mr3		= 0;
+		mr2		= 0;
+		mr1		= 0;
+		mr0		= 0;
+		tdinit3		= 0;
+		tdinit2		= 0;
+		tdinit1		= 0;
+		tdinit0		= 0;
+
+		break;
+	}
+
+	/* Set mode registers */
+	writel(mr0, 0x3103030);
+	writel(mr1, 0x3103034);
+	writel(mr2, 0x3103038);
+	writel(mr3, 0x310303c);
+	/* TODO: dram_odt_en is either 0x0 or 0x1, so right shift looks weird */
+	writel((para->dram_odt_en >> 4) & 0x3, 0x310302c);
+
+	/* Set dram timing DRAMTMG0 - DRAMTMG5 */
+	writel((twtp << 24) | (tfaw << 16) | (trasmax << 8) | (tras << 0),
+		0x3103058);
+	writel((txp << 16) | (trtp << 8) | (trc << 0),
+		0x310305c);
+	writel((tcwl << 24) | (tcl << 16) | (trd2wr << 8) | (twr2rd << 0),
+		0x3103060);
+	writel((tmrw << 16) | (tmrd << 12) | (tmod << 0),
+		0x3103064);
+	writel((trcd << 24) | (tccd << 16) | (trrd << 8) | (trp << 0),
+		0x3103068);
+	writel((tcksrx << 24) | (tcksrx << 16) | (tckesr << 8) | (tcke << 0),
+		0x310306c);
+
+	/* Set dual rank timing */
+	clrsetbits_le32(0x3103078, 0xf000ffff,
+			(CONFIG_DRAM_CLK < 800) ? 0xf0006610 : 0xf0007610);
+
+	/* Set phy interface time PITMG0, PTR3, PTR4 */
+	writel((0x2 << 24) | (t_rdata_en << 16) | BIT(8) | (wr_latency << 0),
+		0x3103080);
+	writel(((tdinit0 << 0) | (tdinit1 << 20)), 0x3103050);
+	writel(((tdinit2 << 0) | (tdinit3 << 20)), 0x3103054);
+
+	/* Set refresh timing and mode */
+	writel((trefi << 16) | (trfc << 0), 0x3103090);
+	writel((trefi << 15) & 0x0fff0000, 0x3103094);
+}
+
+// Purpose of this routine seems to be to initialize the PLL driving
+// the MBUS and sdram.
+//
+static int ccu_set_pll_ddr_clk(int index, const dram_para_t *para,
+			       const dram_config_t *config)
+{
+	unsigned int val, clk, n;
+
+	if (config->dram_tpr13 & BIT(6))
+		clk = para->dram_tpr9;
+	else
+		clk = para->dram_clk;
+
+	// set VCO clock divider
+	n = (clk * 2) / 24;
+
+	val = readl(SUNXI_CCM_BASE + 0x10);
+	val &= ~0x0007ff03;			// clear dividers
+	val |= (n - 1) << 8;			// set PLL division
+	val |= BIT(31) | BIT(30);		// enable PLL and LDO
+	writel(val | BIT(29), SUNXI_CCM_BASE + 0x10);
+
+	// wait for PLL to lock
+	while ((readl(SUNXI_CCM_BASE + 0x10) & BIT(28)) == 0)
+		;
+
+	udelay(20);
+
+	// enable PLL output
+	setbits_le32(SUNXI_CCM_BASE + 0x0, BIT(27));
+
+	// turn clock gate on
+	val = readl(SUNXI_CCM_BASE + 0x800);
+	val &= ~0x03000303;		// select DDR clk source, n=1, m=1
+	val |= BIT(31);			// turn clock on
+	writel(val, SUNXI_CCM_BASE + 0x800);
+
+	return n * 24;
+}
+
+/* Set up the PLL and clock gates for the DRAM controller and MBUS clocks. */
+static void mctl_sys_init(const dram_para_t *para, const dram_config_t *config)
+{
+	// assert MBUS reset
+	clrbits_le32(SUNXI_CCM_BASE + 0x540, BIT(30));
+
+	// turn off sdram clock gate, assert sdram reset
+	clrbits_le32(SUNXI_CCM_BASE + 0x80c, 0x10001);
+	clrsetbits_le32(SUNXI_CCM_BASE + 0x800, BIT(31) | BIT(30), BIT(27));
+	udelay(10);
+
+	// set ddr pll clock
+	ccu_set_pll_ddr_clk(0, para, config);
+	udelay(100);
+	dram_disable_all_master();
+
+	// release sdram reset
+	setbits_le32(SUNXI_CCM_BASE + 0x80c, BIT(16));
+
+	// release MBUS reset
+	setbits_le32(SUNXI_CCM_BASE + 0x540, BIT(30));
+	setbits_le32(SUNXI_CCM_BASE + 0x800, BIT(30));
+
+	udelay(5);
+
+	// turn on sdram clock gate
+	setbits_le32(SUNXI_CCM_BASE + 0x80c, BIT(0));
+
+	// turn dram clock gate on, trigger sdr clock update
+	setbits_le32(SUNXI_CCM_BASE + 0x800, BIT(31) | BIT(27));
+	udelay(5);
+
+	// mCTL clock enable
+	writel(0x8000, 0x310300c);
+	udelay(10);
+}
+
+// The main purpose of this routine seems to be to copy an address configuration
+// from the dram_para1 and dram_para2 fields to the PHY configuration registers
+// (0x3102000, 0x3102004).
+//
+static void mctl_com_init(const dram_para_t *para, const dram_config_t *config)
+{
+	uint32_t val, width;
+	unsigned long ptr;
+	int i;
+
+	// purpose ??
+	clrsetbits_le32(0x3102008, 0x3f00, 0x2000);
+
+	// set SDRAM type and word width
+	val  = readl(0x3102000) & ~0x00fff000;
+	val |= (para->dram_type & 0x7) << 16;		// DRAM type
+	val |= (~config->dram_para2 & 0x1) << 12;		// DQ width
+	val |= BIT(22);					// ??
+	if (para->dram_type == SUNXI_DRAM_TYPE_LPDDR2 ||
+	    para->dram_type == SUNXI_DRAM_TYPE_LPDDR3) {
+		val |= BIT(19);		// type 6 and 7 must use 1T
+	} else {
+		if (config->dram_tpr13 & BIT(5))
+			val |= BIT(19);
+	}
+	writel(val, 0x3102000);
+
+	// init rank / bank / row for single/dual or two different ranks
+	if ((config->dram_para2 & BIT(8)) &&
+	    ((config->dram_para2 & 0xf000) != 0x1000))
+		width = 32;
+	else
+		width = 16;
+
+	ptr = 0x3102000;
+	for (i = 0; i < width; i += 16) {
+		val = readl(ptr) & 0xfffff000;
+
+		val |= (config->dram_para2 >> 12) & 0x3; // rank
+		val |= ((config->dram_para1 >> (i + 12)) << 2) & 0x4; // bank - 2
+		val |= (((config->dram_para1 >> (i + 4)) - 1) << 4) & 0xff; // row - 1
+
+		// convert from page size to column addr width - 3
+		switch ((config->dram_para1 >> i) & 0xf) {
+		case 8: val |= 0xa00; break;
+		case 4: val |= 0x900; break;
+		case 2: val |= 0x800; break;
+		case 1: val |= 0x700; break;
+		default: val |= 0x600; break;
+		}
+		writel(val, ptr);
+		ptr += 4;
+	}
+
+	// set ODTMAP based on number of ranks in use
+	val = (readl(0x3102000) & 0x1) ? 0x303 : 0x201;
+	writel(val, 0x3103120);
+
+	// set mctl reg 3c4 to zero when using half DQ
+	if (config->dram_para2 & BIT(0))
+		writel(0, 0x31033c4);
+
+	// purpose ??
+	if (para->dram_tpr4) {
+                setbits_le32(0x3102000, (para->dram_tpr4 & 0x3) << 25);
+                setbits_le32(0x3102004, (para->dram_tpr4 & 0x7fc) << 10);
+	}
+}
+
+static const uint8_t ac_remapping_tables[][22] = {
+	[0] = { 0 },
+	[1] = {  1,  9,  3,  7,  8, 18,  4, 13,  5,  6, 10,
+		 2, 14, 12,  0,  0, 21, 17, 20, 19, 11, 22 },
+	[2] = {  4,  9,  3,  7,  8, 18,  1, 13,  2,  6, 10,
+		 5, 14, 12,  0,  0, 21, 17, 20, 19, 11, 22 },
+	[3] = {  1,  7,  8, 12, 10, 18,  4, 13,  5,  6,  3,
+		 2,  9,  0,  0,  0, 21, 17, 20, 19, 11, 22 },
+	[4] = {  4, 12, 10,  7,  8, 18,  1, 13,  2,  6,  3,
+		 5,  9,  0,  0,  0, 21, 17, 20, 19, 11, 22 },
+	[5] = { 13,  2,  7,  9, 12, 19,  5,  1,  6,  3,  4,
+		 8, 10,  0,  0,  0, 21, 22, 18, 17, 11, 20 },
+	[6] = {  3, 10,  7, 13,  9, 11,  1,  2,  4,  6,  8,
+		 5, 12,  0,  0,  0, 20,  1,  0, 21, 22, 17 },
+	[7] = {  3,  2,  4,  7,  9,  1, 17, 12, 18, 14, 13,
+		 8, 15,  6, 10,  5, 19, 22, 16, 21, 20, 11 },
+};
+
+/*
+ * This routine chooses one of several remapping tables for 22 lines.
+ * It is unclear which lines are being remapped. It seems to pick
+ * table cfg7 for the Nezha board.
+ */
+static void mctl_phy_ac_remapping(const dram_para_t *para,
+				  const dram_config_t *config)
+{
+	const uint8_t *cfg;
+	uint32_t fuse, val;
+
+	/*
+	 * It is unclear whether the LPDDRx types don't need any remapping,
+	 * or whether the original code just didn't provide tables.
+	 */
+	if (para->dram_type != SUNXI_DRAM_TYPE_DDR2 &&
+	    para->dram_type != SUNXI_DRAM_TYPE_DDR3)
+		return;
+
+	fuse = (readl(SUNXI_SID_BASE + 0x28) & 0xf00) >> 8;
+	debug("DDR efuse: 0x%x\n", fuse);
+
+	if (para->dram_type == SUNXI_DRAM_TYPE_DDR2) {
+		if (fuse == 15)
+			return;
+		cfg = ac_remapping_tables[6];
+	} else {
+		if (config->dram_tpr13 & 0xc0000) {
+			cfg = ac_remapping_tables[7];
+		} else {
+			switch (fuse) {
+			case 8: cfg = ac_remapping_tables[2]; break;
+			case 9: cfg = ac_remapping_tables[3]; break;
+			case 10: cfg = ac_remapping_tables[5]; break;
+			case 11: cfg = ac_remapping_tables[4]; break;
+			default:
+			case 12: cfg = ac_remapping_tables[1]; break;
+			case 13:
+			case 14: cfg = ac_remapping_tables[0]; break;
+			}
+		}
+	}
+
+	val = (cfg[4] << 25) | (cfg[3] << 20) | (cfg[2] << 15) |
+	      (cfg[1] << 10) | (cfg[0] << 5);
+	writel(val, 0x3102500);
+
+	val = (cfg[10] << 25) | (cfg[9] << 20) | (cfg[8] << 15) |
+	      (cfg[ 7] << 10) | (cfg[6] <<  5) | cfg[5];
+	writel(val, 0x3102504);
+
+	val = (cfg[15] << 20) | (cfg[14] << 15) | (cfg[13] << 10) |
+	      (cfg[12] <<  5) | cfg[11];
+	writel(val, 0x3102508);
+
+	val = (cfg[21] << 25) | (cfg[20] << 20) | (cfg[19] << 15) |
+	      (cfg[18] << 10) | (cfg[17] <<  5) | cfg[16];
+	writel(val, 0x310250c);
+
+	val = (cfg[4] << 25) | (cfg[3] << 20) | (cfg[2] << 15) |
+	      (cfg[1] << 10) | (cfg[0] <<  5) | 1;
+	writel(val, 0x3102500);
+}
+
+// Init the controller channel. The key part is placing commands in the main
+// command register (PIR, 0x3103000) and checking command status (PGSR0, 0x3103010).
+//
+static unsigned int mctl_channel_init(unsigned int ch_index,
+				      const dram_para_t *para,
+				      const dram_config_t *config)
+{
+	unsigned int val, dqs_gating_mode;
+
+	dqs_gating_mode = (config->dram_tpr13 & 0xc) >> 2;
+
+	// set DDR clock to half of CPU clock
+	clrsetbits_le32(0x310200c, 0xfff, (para->dram_clk / 2) - 1);
+
+	// MRCTRL0 nibble 3 undocumented
+	clrsetbits_le32(0x3103108, 0xf00, 0x300);
+
+	if (para->dram_odt_en)
+		val = 0;
+	else
+		val = BIT(5);
+
+	// DX0GCR0
+	if (para->dram_clk > 672)
+		clrsetbits_le32(0x3103344, 0xf63e, val);
+	else
+		clrsetbits_le32(0x3103344, 0xf03e, val);
+
+	// DX1GCR0
+	if (para->dram_clk > 672) {
+                setbits_le32(0x3103344, 0x400);
+		clrsetbits_le32(0x31033c4, 0xf63e, val);
+	} else {
+		clrsetbits_le32(0x31033c4, 0xf03e, val);
+	}
+
+	// 0x3103208 undocumented
+	setbits_le32(0x3103208, BIT(1));
+
+	eye_delay_compensation(para);
+
+	// set PLL SSCG ?
+	val = readl(0x3103108);
+	if (dqs_gating_mode == 1) {
+		clrsetbits_le32(0x3103108, 0xc0, 0);
+		clrbits_le32(0x31030bc, 0x107);
+	} else if (dqs_gating_mode == 2) {
+		clrsetbits_le32(0x3103108, 0xc0, 0x80);
+
+		clrsetbits_le32(0x31030bc, 0x107,
+				(((config->dram_tpr13 >> 16) & 0x1f) - 2) | 0x100);
+		clrsetbits_le32(0x310311c, BIT(31), BIT(27));
+	} else {
+		clrbits_le32(0x3103108, 0x40);
+		udelay(10);
+		setbits_le32(0x3103108, 0xc0);
+	}
+
+	if (para->dram_type == SUNXI_DRAM_TYPE_LPDDR2 ||
+	    para->dram_type == SUNXI_DRAM_TYPE_LPDDR3) {
+		if (dqs_gating_mode == 1)
+			clrsetbits_le32(0x310311c, 0x080000c0, 0x80000000);
+		else
+			clrsetbits_le32(0x310311c, 0x77000000, 0x22000000);
+	}
+
+	clrsetbits_le32(0x31030c0, 0x0fffffff,
+			(config->dram_para2 & BIT(12)) ? 0x03000001 : 0x01000007);
+
+	if (readl(0x70005d4) & BIT(16)) {
+		clrbits_le32(0x7010250, 0x2);
+		udelay(10);
+	}
+
+	// Set ZQ config
+	clrsetbits_le32(0x3103140, 0x3ffffff,
+			(para->dram_zq & 0x00ffffff) | BIT(25));
+
+	// Initialise DRAM controller
+	if (dqs_gating_mode == 1) {
+		//writel(0x52, 0x3103000); // prep PHY reset + PLL init + z-cal
+		writel(0x53, 0x3103000); // Go
+
+		while ((readl(0x3103010) & 0x1) == 0) {
+		} // wait for IDONE
+		udelay(10);
+
+		// 0x520 = prep DQS gating + DRAM init + d-cal
+		if (para->dram_type == SUNXI_DRAM_TYPE_DDR3)
+			writel(0x5a0, 0x3103000);		// + DRAM reset
+		else
+			writel(0x520, 0x3103000);
+	} else {
+		if ((readl(0x70005d4) & (1 << 16)) == 0) {
+			// prep DRAM init + PHY reset + d-cal + PLL init + z-cal
+			if (para->dram_type == SUNXI_DRAM_TYPE_DDR3)
+				writel(0x1f2, 0x3103000);	// + DRAM reset
+			else
+				writel(0x172, 0x3103000);
+		} else {
+			// prep PHY reset + d-cal + z-cal
+			writel(0x62, 0x3103000);
+		}
+	}
+
+	setbits_le32(0x3103000, 0x1);		 // GO
+
+	udelay(10);
+	while ((readl(0x3103010) & 0x1) == 0) {
+	} // wait for IDONE
+
+	if (readl(0x70005d4) & BIT(16)) {
+		clrsetbits_le32(0x310310c, 0x06000000, 0x04000000);
+		udelay(10);
+
+		setbits_le32(0x3103004, 0x1);
+
+		while ((readl(0x3103018) & 0x7) != 0x3) {
+		}
+
+		clrbits_le32(0x7010250, 0x1);
+		udelay(10);
+
+		clrbits_le32(0x3103004, 0x1);
+
+		while ((readl(0x3103018) & 0x7) != 0x1) {
+		}
+
+		udelay(15);
+
+		if (dqs_gating_mode == 1) {
+			clrbits_le32(0x3103108, 0xc0);
+			clrsetbits_le32(0x310310c, 0x06000000, 0x02000000);
+			udelay(1);
+			writel(0x401, 0x3103000);
+
+			while ((readl(0x3103010) & 0x1) == 0) {
+			}
+		}
+	}
+
+	// Check for training error
+	if (readl(0x3103010) & BIT(20)) {
+		printf("ZQ calibration error, check external 240 ohm resistor\n");
+		return 0;
+	}
+
+	// STATR = Zynq STAT? Wait for status 'normal'?
+	while ((readl(0x3103018) & 0x1) == 0) {
+	}
+
+	setbits_le32(0x310308c, BIT(31));
+	udelay(10);
+	clrbits_le32(0x310308c, BIT(31));
+	udelay(10);
+	setbits_le32(0x3102014, BIT(31));
+	udelay(10);
+
+	clrbits_le32(0x310310c, 0x06000000);
+
+	if (dqs_gating_mode == 1)
+		clrsetbits_le32(0x310311c, 0xc0, 0x40);
+
+	return 1;
+}
+
+static unsigned int calculate_rank_size(uint32_t regval)
+{
+	unsigned int bits;
+
+	bits = (regval >> 8) & 0xf;	/* page size - 3 */
+	bits += (regval >> 4) & 0xf;	/* row width - 1 */
+	bits += (regval >> 2) & 0x3;	/* bank count - 2 */
+	bits -= 14;			/* 1MB = 20 bits, minus above 6 = 14 */
+
+	return 1U << bits;
+}
+
+/*
+ * The below routine reads the dram config registers and extracts
+ * the number of address bits in each rank available. It then calculates
+ * total memory size in MB.
+ */
+static unsigned int DRAMC_get_dram_size(void)
+{
+	uint32_t val;
+	unsigned int size;
+
+	val = readl(0x3102000);		/* MC_WORK_MODE0 */
+	size = calculate_rank_size(val);
+	if ((val & 0x3) == 0)		/* single rank? */
+		return size;
+
+	val = readl(0x3102004);		/* MC_WORK_MODE1 */
+	if ((val & 0x3) == 0)		/* two identical ranks? */
+		return size * 2;
+
+	/* add sizes of both ranks */
+	return size + calculate_rank_size(val);
+}
+
+/*
+ * The below routine reads the command status register to extract
+ * DQ width and rank count. This follows the DQS training command in
+ * channel_init. If error bit 22 is reset, we have two ranks and full DQ.
+ * If there was an error, figure out whether it was half DQ, single rank,
+ * or both. Set bit 12 and 0 in dram_para2 with the results.
+ */
+static int dqs_gate_detect(dram_config_t *config)
+{
+	uint32_t dx0, dx1;
+
+	if ((readl(0x3103010) & BIT(22)) == 0) {
+		config->dram_para2 = (config->dram_para2 & ~0xf) | BIT(12);
+		debug("dual rank and full DQ\n");
+
+		return 1;
+	}
+
+	dx0 = (readl(0x3103348) & 0x3000000) >> 24;
+	if (dx0 == 0) {
+		config->dram_para2 = (config->dram_para2 & ~0xf) | 0x1001;
+		debug("dual rank and half DQ\n");
+
+		return 1;
+	}
+
+	if (dx0 == 2) {
+		dx1 = (readl(0x31033c8) & 0x3000000) >> 24;
+		if (dx1 == 2) {
+			config->dram_para2 = config->dram_para2 & ~0xf00f;
+			debug("single rank and full DQ\n");
+		} else {
+			config->dram_para2 = (config->dram_para2 & ~0xf00f) | BIT(0);
+			debug("single rank and half DQ\n");
+		}
+
+		return 1;
+	}
+
+	if ((config->dram_tpr13 & BIT(29)) == 0)
+		return 0;
+
+	debug("DX0 state: %d\n", dx0);
+	debug("DX1 state: %d\n", dx1);
+
+	return 0;
+}
+
+static int dramc_simple_wr_test(unsigned int mem_mb, int len)
+{
+	unsigned int  offs	= (mem_mb / 2) << 18; // half of memory size
+	unsigned int  patt1 = 0x01234567;
+	unsigned int  patt2 = 0xfedcba98;
+	unsigned int *addr, v1, v2, i;
+
+	addr = (unsigned int *)CFG_SYS_SDRAM_BASE;
+	for (i = 0; i != len; i++, addr++) {
+		writel(patt1 + i, (unsigned long)addr);
+		writel(patt2 + i, (unsigned long)(addr + offs));
+	}
+
+	addr = (unsigned int *)CFG_SYS_SDRAM_BASE;
+	for (i = 0; i != len; i++) {
+		v1 = readl((unsigned long)(addr + i));
+		v2 = patt1 + i;
+		if (v1 != v2) {
+			printf("DRAM: simple test FAIL\n");
+			printf("%x != %x at address %p\n", v1, v2, addr + i);
+			return 1;
+		}
+		v1 = readl((unsigned long)(addr + offs + i));
+		v2 = patt2 + i;
+		if (v1 != v2) {
+			printf("DRAM: simple test FAIL\n");
+			printf("%x != %x at address %p\n", v1, v2, addr + offs + i);
+			return 1;
+		}
+	}
+
+	debug("DRAM: simple test OK\n");
+	return 0;
+}
+
+// Set the Vref mode for the controller
+//
+static void mctl_vrefzq_init(const dram_para_t *para, const dram_config_t *config)
+{
+	if (config->dram_tpr13 & BIT(17))
+		return;
+
+	clrsetbits_le32(0x3103110, 0x7f7f7f7f, para->dram_tpr5);
+
+	// IOCVR1
+	if ((config->dram_tpr13 & BIT(16)) == 0)
+		clrsetbits_le32(0x3103114, 0x7f, para->dram_tpr6 & 0x7f);
+}
+
+// Perform an init of the controller. This is actually done 3 times. The first
+// time to establish the number of ranks and DQ width. The second time to
+// establish the actual ram size. The third time is final one, with the final
+// settings.
+//
+static int mctl_core_init(const dram_para_t *para, const dram_config_t *config)
+{
+	mctl_sys_init(para, config);
+
+	mctl_vrefzq_init(para, config);
+
+	mctl_com_init(para, config);
+
+	mctl_phy_ac_remapping(para, config);
+
+	mctl_set_timing_params(para, config);
+
+	return mctl_channel_init(0, para, config);
+}
+
+/*
+ * This routine sizes a DRAM device by cycling through address lines and
+ * figuring out if they are connected to a real address line, or if the
+ * address is a mirror.
+ * First the column and bank bit allocations are set to low values (2 and 9
+ * address lines). Then a maximum allocation (16 lines) is set for rows and
+ * this is tested.
+ * Next the BA2 line is checked. This seems to be placed above the column,
+ * BA0-1 and row addresses. Finally, the column address is allocated 13 lines
+ * and these are tested. The results are placed in dram_para1 and dram_para2.
+ */
+static int auto_scan_dram_size(const dram_para_t *para, dram_config_t *config)
+{
+	unsigned int rval, i, j, rank, maxrank, offs;
+	unsigned int shft;
+	unsigned long ptr, mc_work_mode, chk;
+
+	if (mctl_core_init(para, config) == 0) {
+		printf("DRAM initialisation error : 0\n");
+		return 0;
+	}
+
+	maxrank	= (config->dram_para2 & 0xf000) ? 2 : 1;
+	mc_work_mode = 0x3102000;
+	offs = 0;
+
+	/* write test pattern */
+	for (i = 0, ptr = CFG_SYS_SDRAM_BASE; i < 64; i++, ptr += 4)
+		writel((i & 0x1) ? ptr : ~ptr, ptr);
+
+	for (rank = 0; rank < maxrank;) {
+		/* set row mode */
+		clrsetbits_le32(mc_work_mode, 0xf0c, 0x6f0);
+		udelay(1);
+
+		// Scan per address line, until address wraps (i.e. see shadow)
+		for (i = 11; i < 17; i++) {
+			chk = CFG_SYS_SDRAM_BASE + (1U << (i + 11));
+			ptr = CFG_SYS_SDRAM_BASE;
+			for (j = 0; j < 64; j++) {
+				if (readl(chk) != ((j & 1) ? ptr : ~ptr))
+					break;
+				ptr += 4;
+				chk += 4;
+			}
+			if (j == 64)
+				break;
+		}
+		if (i > 16)
+			i = 16;
+		debug("rank %d row = %d\n", rank, i);
+
+		/* Store rows in para 1 */
+		shft = offs + 4;
+		rval = config->dram_para1;
+		rval &= ~(0xff << shft);
+		rval |= i << shft;
+		config->dram_para1 = rval;
+
+		if (rank == 1)		/* Set bank mode for rank0 */
+			clrsetbits_le32(0x3102000, 0xffc, 0x6a4);
+
+		/* Set bank mode for current rank */
+		clrsetbits_le32(mc_work_mode, 0xffc, 0x6a4);
+		udelay(1);
+
+		// Test if bit A23 is BA2 or mirror XXX A22?
+		chk = CFG_SYS_SDRAM_BASE + (1U << 22);
+		ptr = CFG_SYS_SDRAM_BASE;
+		for (i = 0, j = 0; i < 64; i++) {
+			if (readl(chk) != ((i & 1) ? ptr : ~ptr)) {
+				j = 1;
+				break;
+			}
+			ptr += 4;
+			chk += 4;
+		}
+
+		debug("rank %d bank = %d\n", rank, (j + 1) << 2); /* 4 or 8 */
+
+		/* Store banks in para 1 */
+		shft = 12 + offs;
+		rval = config->dram_para1;
+		rval &= ~(0xf << shft);
+		rval |= j << shft;
+		config->dram_para1 = rval;
+
+		if (rank == 1)		/* Set page mode for rank0 */
+			clrsetbits_le32(0x3102000, 0xffc, 0xaa0);
+
+		/* Set page mode for current rank */
+		clrsetbits_le32(mc_work_mode, 0xffc, 0xaa0);
+		udelay(1);
+
+		// Scan per address line, until address wraps (i.e. see shadow)
+		for (i = 9; i < 14; i++) {
+			chk = CFG_SYS_SDRAM_BASE + (1U << i);
+			ptr = CFG_SYS_SDRAM_BASE;
+			for (j = 0; j < 64; j++) {
+				if (readl(chk) != ((j & 1) ? ptr : ~ptr))
+					break;
+				ptr += 4;
+				chk += 4;
+			}
+			if (j == 64)
+				break;
+		}
+		if (i > 13)
+			i = 13;
+
+		unsigned int pgsize = (i == 9) ? 0 : (1 << (i - 10));
+		debug("rank %d page size = %d KB\n", rank, pgsize);
+
+		/* Store page size */
+		shft = offs;
+		rval = config->dram_para1;
+		rval &= ~(0xf << shft);
+		rval |= pgsize << shft;
+		config->dram_para1 = rval;
+
+		// Move to next rank
+		rank++;
+		if (rank != maxrank) {
+			if (rank == 1) {
+				/* MC_WORK_MODE */
+				clrsetbits_le32(0x3202000, 0xffc, 0x6f0);
+
+				/* MC_WORK_MODE2 */
+				clrsetbits_le32(0x3202004, 0xffc, 0x6f0);
+			}
+			/* store rank1 config in upper half of para1 */
+			offs += 16;
+			mc_work_mode += 4;	/* move to MC_WORK_MODE2 */
+		}
+	}
+	if (maxrank == 2) {
+		config->dram_para2 &= 0xfffff0ff;
+		/* note: rval is equal to para->dram_para1 here */
+		if ((rval & 0xffff) == (rval >> 16)) {
+			debug("rank1 config same as rank0\n");
+		} else {
+			config->dram_para2 |= BIT(8);
+			debug("rank1 config different from rank0\n");
+		}
+	}
+
+	return 1;
+}
+
+/*
+ * This routine sets up parameters with dqs_gating_mode equal to 1 and two
+ * ranks enabled. It then configures the core and tests for 1 or 2 ranks and
+ * full or half DQ width. It then resets the parameters to the original values.
+ * dram_para2 is updated with the rank and width findings.
+ */
+static int auto_scan_dram_rank_width(const dram_para_t *para,
+				     dram_config_t *config)
+{
+	unsigned int s1 = config->dram_tpr13;
+	unsigned int s2 = config->dram_para1;
+
+	config->dram_para1 = 0x00b000b0;
+	config->dram_para2 = (config->dram_para2 & ~0xf) | BIT(12);
+
+	/* set DQS probe mode */
+	config->dram_tpr13 = (config->dram_tpr13 & ~0x8) | BIT(2) | BIT(0);
+
+	mctl_core_init(para, config);
+
+	if (readl(0x3103010) & BIT(20))
+		return 0;
+
+	if (dqs_gate_detect(config) == 0)
+		return 0;
+
+	config->dram_tpr13 = s1;
+	config->dram_para1 = s2;
+
+	return 1;
+}
+
+/*
+ * This routine determines the SDRAM topology. It first establishes the number
+ * of ranks and the DQ width. Then it scans the SDRAM address lines to establish
+ * the size of each rank. It then updates dram_tpr13 to reflect that the sizes
+ * are now known: a re-init will not repeat the autoscan.
+ */
+static int auto_scan_dram_config(const dram_para_t *para,
+				 dram_config_t *config)
+{
+	if (((config->dram_tpr13 & BIT(14)) == 0) &&
+	    (auto_scan_dram_rank_width(para, config) == 0)) {
+		printf("ERROR: auto scan dram rank & width failed\n");
+		return 0;
+	}
+
+	if (((config->dram_tpr13 & BIT(0)) == 0) &&
+	    (auto_scan_dram_size(para, config) == 0)) {
+		printf("ERROR: auto scan dram size failed\n");
+		return 0;
+	}
+
+	if ((config->dram_tpr13 & BIT(15)) == 0)
+		config->dram_tpr13 |= BIT(14) | BIT(13) | BIT(1) | BIT(0);
+
+	return 1;
+}
+
+static int init_DRAM(int type, const dram_para_t *para)
+{
+	dram_config_t config = {
+		.dram_para1	= 0x000010d2,
+		.dram_para2	= 0,
+		.dram_tpr13	= CONFIG_DRAM_SUNXI_TPR13,
+	};
+	u32 rc, mem_size_mb;
+
+	debug("DRAM BOOT DRIVE INFO: %s\n", "V0.24");
+	debug("DRAM CLK = %d MHz\n", para->dram_clk);
+	debug("DRAM Type = %d (2:DDR2,3:DDR3)\n", para->dram_type);
+	if ((para->dram_odt_en & 0x1) == 0)
+		debug("DRAMC read ODT off\n");
+	else
+		debug("DRAMC ZQ value: 0x%x\n", para->dram_zq);
+
+	/* Test ZQ status */
+	if (config.dram_tpr13 & BIT(16)) {
+		debug("DRAM only have internal ZQ\n");
+		setbits_le32(0x3000160, BIT(8));
+		writel(0, 0x3000168);
+		udelay(10);
+	} else {
+		clrbits_le32(0x3000160, 0x3);
+		writel(config.dram_tpr13 & BIT(16), 0x7010254);
+		udelay(10);
+		clrsetbits_le32(0x3000160, 0x108, BIT(1));
+		udelay(10);
+		setbits_le32(0x3000160, BIT(0));
+		udelay(20);
+		debug("ZQ value = 0x%x\n", readl(0x300016c));
+	}
+
+	dram_voltage_set(para);
+
+	/* Set SDRAM controller auto config */
+	if ((config.dram_tpr13 & BIT(0)) == 0) {
+		if (auto_scan_dram_config(para, &config) == 0) {
+			printf("auto_scan_dram_config() FAILED\n");
+			return 0;
+		}
+	}
+
+	/* report ODT */
+	rc = para->dram_mr1;
+	if ((rc & 0x44) == 0)
+		debug("DRAM ODT off\n");
+	else
+		debug("DRAM ODT value: 0x%x\n", rc);
+
+	/* Init core, final run */
+	if (mctl_core_init(para, &config) == 0) {
+		printf("DRAM initialisation error: 1\n");
+		return 0;
+	}
+
+	/* Get SDRAM size */
+	/* TODO: who ever puts a negative number in the top half? */
+	rc = config.dram_para2;
+	if (rc & BIT(31)) {
+		rc = (rc >> 16) & ~BIT(15);
+	} else {
+		rc = DRAMC_get_dram_size();
+		debug("DRAM: size = %dMB\n", rc);
+		config.dram_para2 = (config.dram_para2 & 0xffffU) | rc << 16;
+	}
+	mem_size_mb = rc;
+
+	/* Purpose ?? */
+	if (config.dram_tpr13 & BIT(30)) {
+		rc = para->dram_tpr8;
+		if (rc == 0)
+			rc = 0x10000200;
+		writel(rc, 0x31030a0);
+		writel(0x40a, 0x310309c);
+		setbits_le32(0x3103004, BIT(0));
+		debug("Enable Auto SR\n");
+	} else {
+		clrbits_le32(0x31030a0, 0xffff);
+		clrbits_le32(0x3103004, 0x1);
+	}
+
+	/* Purpose ?? */
+	if (config.dram_tpr13 & BIT(9)) {
+		clrsetbits_le32(0x3103100, 0xf000, 0x5000);
+	} else {
+		if (para->dram_type != SUNXI_DRAM_TYPE_LPDDR2)
+			clrbits_le32(0x3103100, 0xf000);
+	}
+
+	setbits_le32(0x3103140, BIT(31));
+
+	/* CHECK: is that really writing to a different register? */
+	if (config.dram_tpr13 & BIT(8))
+		writel(readl(0x3103140) | 0x300, 0x31030b8);
+
+	if (config.dram_tpr13 & BIT(16))
+		clrbits_le32(0x3103108, BIT(13));
+	else
+		setbits_le32(0x3103108, BIT(13));
+
+	/* Purpose ?? */
+	if (para->dram_type == SUNXI_DRAM_TYPE_LPDDR3)
+		clrsetbits_le32(0x310307c, 0xf0000, 0x1000);
+
+	dram_enable_all_master();
+	if (config.dram_tpr13 & BIT(28)) {
+		if ((readl(0x70005d4) & BIT(16)) ||
+		    dramc_simple_wr_test(mem_size_mb, 4096))
+			return 0;
+	}
+
+	return mem_size_mb;
+}
+
+	static const dram_para_t para = {
+		.dram_clk	= CONFIG_DRAM_CLK,
+		.dram_type	= CONFIG_SUNXI_DRAM_TYPE,
+		.dram_zq	= CONFIG_DRAM_ZQ,
+		.dram_odt_en	= CONFIG_DRAM_SUNXI_ODT_EN,
+		.dram_mr0	= 0x1c70,
+		.dram_mr1	= 0x42,
+		.dram_mr2	= 0x18,
+		.dram_mr3	= 0,
+		.dram_tpr0	= 0x004a2195,
+		.dram_tpr1	= 0x02423190,
+		.dram_tpr2	= 0x0008b061,
+		.dram_tpr3	= 0xb4787896, // unused
+		.dram_tpr4	= 0,
+		.dram_tpr5	= 0x48484848,
+		.dram_tpr6	= 0x00000048,
+		.dram_tpr7	= 0x1620121e, // unused
+		.dram_tpr8	= 0,
+		.dram_tpr9	= 0, // clock?
+		.dram_tpr10	= 0,
+		.dram_tpr11	= CONFIG_DRAM_SUNXI_TPR11,
+		.dram_tpr12	= CONFIG_DRAM_SUNXI_TPR12,
+	};
+
+unsigned long sunxi_dram_init(void)
+{
+	return init_DRAM(0, &para) * 1024UL * 1024;
+};
+
+#ifdef CONFIG_RAM		/* using the driver model */
+struct sunxi_ram_priv {
+	size_t size;
+};
+
+static int sunxi_ram_probe(struct udevice *dev)
+{
+	struct sunxi_ram_priv *priv = dev_get_priv(dev);
+	unsigned long dram_size;
+
+	debug("%s: %s: probing\n", __func__, dev->name);
+
+	dram_size = sunxi_dram_init();
+	if (!dram_size) {
+		printf("DRAM init failed: %d\n", ret);
+		return -ENODEV;
+	}
+
+	priv->size = dram_size;
+
+	return 0;
+}
+
+static int sunxi_ram_get_info(struct udevice *dev, struct ram_info *info)
+{
+	struct sunxi_ram_priv *priv = dev_get_priv(dev);
+
+	debug("%s: %s: getting info\n", __func__, dev->name);
+
+	info->base = CFG_SYS_SDRAM_BASE;
+	info->size = priv->size;
+
+	return 0;
+}
+
+static struct ram_ops sunxi_ram_ops = {
+	.get_info = sunxi_ram_get_info,
+};
+
+static const struct udevice_id sunxi_ram_ids[] = {
+	{ .compatible = "allwinner,sun20i-d1-mbus" },
+	{ }
+};
+
+U_BOOT_DRIVER(sunxi_ram) = {
+	.name = "sunxi_ram",
+	.id = UCLASS_RAM,
+	.of_match = sunxi_ram_ids,
+	.ops = &sunxi_ram_ops,
+	.probe = sunxi_ram_probe,
+	.priv_auto = sizeof(struct sunxi_ram_priv),
+};
+#endif				/* CONFIG_RAM (using driver model) */
diff --git a/drivers/ram/sunxi/dram_sun20i_d1.h b/drivers/ram/sunxi/dram_sun20i_d1.h
new file mode 100644
index 00000000000..91383f6cf10
--- /dev/null
+++ b/drivers/ram/sunxi/dram_sun20i_d1.h
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier:	GPL-2.0+
+/*
+ * D1/R528/T113 DRAM controller register and constant defines
+ *
+ * (C) Copyright 2022 Arm Ltd.
+ * Based on H6 and H616 header, which are:
+ * (C) Copyright 2017  Icenowy Zheng <icenowy@aosc.io>
+ * (C) Copyright 2020  Jernej Skrabec <jernej.skrabec@siol.net>
+ *
+ */
+
+#ifndef _SUNXI_DRAM_SUN20I_D1_H
+#define _SUNXI_DRAM_SUN20I_D1_H
+
+enum sunxi_dram_type {
+	SUNXI_DRAM_TYPE_DDR2 = 2,
+	SUNXI_DRAM_TYPE_DDR3 = 3,
+	SUNXI_DRAM_TYPE_LPDDR2 = 6,
+	SUNXI_DRAM_TYPE_LPDDR3 = 7,
+};
+
+/*
+ * This structure contains a mixture of fixed configuration settings,
+ * variables that are used at runtime to communicate settings between
+ * different stages and functions, and unused values.
+ * This is copied from Allwinner's boot0 data structure, which can be
+ * found at offset 0x38 in any boot0 binary. To allow matching up some
+ * board specific settings, this struct is kept compatible, even though
+ * we don't need all members in our code.
+ */
+typedef struct dram_para {
+	/* normal configuration */
+	const u32	dram_clk;
+	const u32	dram_type;
+	const u32	dram_zq;
+	const u32	dram_odt_en;
+
+	/* timing configuration */
+	const u32	dram_mr0;
+	const u32	dram_mr1;
+	const u32	dram_mr2;
+	const u32	dram_mr3;
+	const u32	dram_tpr0;	//DRAMTMG0
+	const u32	dram_tpr1;	//DRAMTMG1
+	const u32	dram_tpr2;	//DRAMTMG2
+	const u32	dram_tpr3;	//DRAMTMG3
+	const u32	dram_tpr4;	//DRAMTMG4
+	const u32	dram_tpr5;	//DRAMTMG5
+	const u32	dram_tpr6;	//DRAMTMG8
+	const u32	dram_tpr7;
+	const u32	dram_tpr8;
+	const u32	dram_tpr9;
+	const u32	dram_tpr10;
+	const u32	dram_tpr11;
+	const u32	dram_tpr12;
+} dram_para_t;
+
+typedef struct dram_config {
+	/* control configuration */
+	u32	dram_para1;
+	u32	dram_para2;
+	/* contains a bitfield of DRAM setup settings */
+	u32	dram_tpr13;
+} dram_config_t;
+
+static inline int ns_to_t(int nanoseconds)
+{
+	const unsigned int ctrl_freq = CONFIG_DRAM_CLK / 2;
+
+	return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
+}
+
+#endif /* _SUNXI_DRAM_SUN20I_D1_H */
-- 
2.35.8


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 17/22] sunxi: add Allwinner R528/T113 SoC support
  2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
                   ` (15 preceding siblings ...)
  2023-09-28 21:54 ` [PATCH v2 16/22] sunxi: add R528/T113-s3/D1(s) DRAM initialisation code Andre Przywara
@ 2023-09-28 21:54 ` Andre Przywara
  2023-09-28 21:54 ` [PATCH v2 18/22] sunxi: R528: add SMHC2 pin pull ups support Andre Przywara
                   ` (4 subsequent siblings)
  21 siblings, 0 replies; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

This adds the remaining code bits to teach U-Boot about Allwinner's
newest SoC generation. This was introduced with the RISC-V based
Allwinner D1 SoC, which actually shares a die with the ARM cores versions
called R528 (BGA, without DRAM) and T113s (QFP, with embedded DRAM).

This adds the new Kconfig stanza, using the two newly introduced symbols
for the new SoC generation and pincontroller. It also adds the new symbols
to the relavent code places, to set all the hardcoded bits directly.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h |  9 +++++++--
 arch/arm/mach-sunxi/Kconfig                       | 11 +++++++++++
 arch/arm/mach-sunxi/board.c                       |  8 ++++++++
 arch/arm/mach-sunxi/clock_sun50i_h6.c             |  2 ++
 arch/arm/mach-sunxi/cpu_info.c                    |  2 ++
 common/spl/Kconfig                                |  1 +
 drivers/clk/sunxi/Kconfig                         |  1 +
 drivers/mmc/sunxi_mmc.c                           |  1 +
 drivers/pinctrl/sunxi/Kconfig                     |  1 +
 9 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
index 8471e11aa02..a84a57e5b41 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
@@ -266,7 +266,7 @@ struct sunxi_ccm_reg {
 #define CCM_CPU_AXI_AXI_MASK		0x3
 #define CCM_CPU_AXI_DEFAULT_FACTORS	0x301
 
-#ifdef CONFIG_MACH_SUN50I_H6
+#ifdef CONFIG_MACH_SUN50I_H6				/* H6 */
 #define CCM_PLL6_DEFAULT		0xa0006300
 
 /* psi_ahb1_ahb2 bit field */
@@ -277,7 +277,7 @@ struct sunxi_ccm_reg {
 
 /* apb1 bit field */
 #define CCM_APB1_DEFAULT		0x03000102
-#elif CONFIG_MACH_SUN50I_H616
+#elif CONFIG_MACH_SUN50I_H616				/* H616 */
 #define CCM_PLL6_DEFAULT		0xa8003100
 
 /* psi_ahb1_ahb2 bit field */
@@ -288,6 +288,11 @@ struct sunxi_ccm_reg {
 
 /* apb1 bit field */
 #define CCM_APB1_DEFAULT		0x03000102
+#elif CONFIG_MACH_SUN8I_R528				/* R528 */
+#define CCM_PLL6_DEFAULT		0xe8216300
+#define CCM_PSI_AHB1_AHB2_DEFAULT	0x03000002
+//#define CCM_AHB3_DEFAULT		0x03000002
+#define CCM_APB1_DEFAULT		0x03000102
 #endif
 
 /* apb2 bit field */
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 12eb51b2ea4..d03413be0ed 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -352,6 +352,15 @@ config MACH_SUN8I_R40
 	select SUNXI_DRAM_DW_32BIT
 	imply SPL_SYS_I2C_LEGACY
 
+config MACH_SUN8I_R528
+	bool "sun8i (Allwinner R528)"
+	select CPU_V7A
+	select SUNXI_GEN_NCAT2
+	select SUNXI_NEW_PINCTRL
+	select MMC_SUNXI_HAS_NEW_MODE
+	select SUPPORT_SPL
+	select DRAM_SUN8I_R528
+
 config MACH_SUN8I_V3S
 	bool "sun8i (Allwinner V3/V3s/S3/S3L)"
 	select CPU_V7A
@@ -662,6 +671,7 @@ config SYS_CLK_FREQ
 	default 1008000000 if MACH_SUN9I
 	default 888000000 if MACH_SUN50I_H6
 	default 1008000000 if MACH_SUN50I_H616
+	default 1008000000 if MACH_SUN8I_R528
 
 config SYS_CONFIG_NAME
 	default "suniv" if MACH_SUNIV
@@ -670,6 +680,7 @@ config SYS_CONFIG_NAME
 	default "sun6i" if MACH_SUN6I
 	default "sun7i" if MACH_SUN7I
 	default "sun8i" if MACH_SUN8I
+	default "sun8i" if MACH_SUN8I_R528
 	default "sun9i" if MACH_SUN9I
 	default "sun50i" if MACH_SUN50I
 	default "sun50i" if MACH_SUN50I_H6
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index d572314f0da..c2fadf75367 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -147,6 +147,10 @@ static int gpio_init(void)
 	sunxi_gpio_set_cfgpin(SUNXI_GPH(12), SUN9I_GPH_UART0);
 	sunxi_gpio_set_cfgpin(SUNXI_GPH(13), SUN9I_GPH_UART0);
 	sunxi_gpio_set_pull(SUNXI_GPH(13), SUNXI_GPIO_PULL_UP);
+#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUN8I_R528)
+	sunxi_gpio_set_cfgpin(SUNXI_GPE(2), 6);
+	sunxi_gpio_set_cfgpin(SUNXI_GPE(3), 6);
+	sunxi_gpio_set_pull(SUNXI_GPE(3), SUNXI_GPIO_PULL_UP);
 #elif CONFIG_CONS_INDEX == 2 && defined(CONFIG_MACH_SUNIV)
 	sunxi_gpio_set_cfgpin(SUNXI_GPA(2), SUNIV_GPE_UART0);
 	sunxi_gpio_set_cfgpin(SUNXI_GPA(3), SUNIV_GPE_UART0);
@@ -163,6 +167,10 @@ static int gpio_init(void)
 	sunxi_gpio_set_cfgpin(SUNXI_GPB(0), SUN8I_GPB_UART2);
 	sunxi_gpio_set_cfgpin(SUNXI_GPB(1), SUN8I_GPB_UART2);
 	sunxi_gpio_set_pull(SUNXI_GPB(1), SUNXI_GPIO_PULL_UP);
+#elif CONFIG_CONS_INDEX == 4 && defined(CONFIG_MACH_SUN8I_R528)
+	sunxi_gpio_set_cfgpin(SUNXI_GPB(6), 7);
+	sunxi_gpio_set_cfgpin(SUNXI_GPB(7), 7);
+	sunxi_gpio_set_pull(SUNXI_GPB(7), SUNXI_GPIO_PULL_UP);
 #elif CONFIG_CONS_INDEX == 5 && defined(CONFIG_MACH_SUN8I)
 	sunxi_gpio_set_cfgpin(SUNXI_GPL(2), SUN8I_GPL_R_UART);
 	sunxi_gpio_set_cfgpin(SUNXI_GPL(3), SUN8I_GPL_R_UART);
diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
index daae994787e..bea91c78bc5 100644
--- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
@@ -41,7 +41,9 @@ void clock_init_safe(void)
 			CCM_CPU_AXI_DEFAULT_FACTORS);
 
 	writel(CCM_PSI_AHB1_AHB2_DEFAULT, &ccm->psi_ahb1_ahb2_cfg);
+#ifdef CCM_AHB3_DEFAULT
 	writel(CCM_AHB3_DEFAULT, &ccm->ahb3_cfg);
+#endif
 	writel(CCM_APB1_DEFAULT, &ccm->apb1_cfg);
 
 	/*
diff --git a/arch/arm/mach-sunxi/cpu_info.c b/arch/arm/mach-sunxi/cpu_info.c
index 7eef178859b..7fecc3b88dd 100644
--- a/arch/arm/mach-sunxi/cpu_info.c
+++ b/arch/arm/mach-sunxi/cpu_info.c
@@ -93,6 +93,8 @@ int print_cpuinfo(void)
 	printf("CPU:   Allwinner R40 (SUN8I %04x)\n", sunxi_get_sram_id());
 #elif defined CONFIG_MACH_SUN8I_V3S
 	printf("CPU:   Allwinner V3s (SUN8I %04x)\n", sunxi_get_sram_id());
+#elif defined CONFIG_MACH_SUN8I_R528
+	puts("CPU:   Allwinner R528 (SUN8I)\n");
 #elif defined CONFIG_MACH_SUN9I
 	puts("CPU:   Allwinner A80 (SUN9I)\n");
 #elif defined CONFIG_MACH_SUN50I
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index cd59b9240c2..be901cb6d62 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -357,6 +357,7 @@ config SPL_STACK
 	default 0x91ffb8 if ARCH_MX6 && !MX6_OCRAM_256KB
 	default 0x118000 if MACH_SUN50I_H6
 	default 0x58000 if MACH_SUN50I_H616
+	default 0x40000 if MACH_SUN8I_R528
 	default 0x54000 if MACH_SUN50I || MACH_SUN50I_H5
 	default 0x18000 if MACH_SUN9I
 	default 0x8000 if ARCH_SUNXI
diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
index f65e482ba4c..8bdc0944896 100644
--- a/drivers/clk/sunxi/Kconfig
+++ b/drivers/clk/sunxi/Kconfig
@@ -89,6 +89,7 @@ config CLK_SUN8I_H3
 
 config CLK_SUN20I_D1
 	bool "Clock driver for Allwinner D1"
+	default MACH_SUN8I_R528
 	help
 	  This enables common clock driver support for platforms based
 	  on Allwinner D1 SoC.
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index 519ef602145..4d6351bf275 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -707,6 +707,7 @@ static const struct udevice_id sunxi_mmc_ids[] = {
 	{ .compatible = "allwinner,sun50i-h6-emmc" },
 	{ .compatible = "allwinner,sun50i-a100-mmc" },
 	{ .compatible = "allwinner,sun50i-a100-emmc" },
+	{ .compatible = "allwinner,sun20i-d1-mmc" },
 	{ /* sentinel */ }
 };
 
diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index c8f937d91e9..cbd61795986 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -126,6 +126,7 @@ config PINCTRL_SUN50I_H616_R
 
 config PINCTRL_SUN20I_D1
 	bool "Support for the Allwinner D1/R528 PIO"
+	default MACH_SUN8I_R528
 	select PINCTRL_SUNXI
 
 endif
-- 
2.35.8


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 18/22] sunxi: R528: add SMHC2 pin pull ups support
  2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
                   ` (16 preceding siblings ...)
  2023-09-28 21:54 ` [PATCH v2 17/22] sunxi: add Allwinner R528/T113 SoC support Andre Przywara
@ 2023-09-28 21:54 ` Andre Przywara
  2023-09-28 21:54 ` [PATCH v2 19/22] sunxi: refactor serial base addresses to avoid asm/arch/cpu.h Andre Przywara
                   ` (3 subsequent siblings)
  21 siblings, 0 replies; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

From: Okhunjon Sobirjonov <okhunjon72@gmail.com>

Add support for eMMC (SMHC2) pin pull ups for R528 boards.

The D1 and T113s (and even R329) SoCs do not support 8-bit eMMC anymore,
so it's just four data pins to cover here.

Signed-off-by: Okhunjon Sobirjonov <Okhunjon.Sobirjonov@Mec-electronics.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
[Andre: adjust commit message]
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 board/sunxi/board.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 7a1c708b9f2..39ecbe988f7 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -459,6 +459,13 @@ static void mmc_pinmux_setup(int sdc)
 			sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
 			sunxi_gpio_set_drv(pin, 2);
 		}
+#elif defined(CONFIG_MACH_SUN8I_R528)
+                /* SDC2: PC2-PC7 */
+                for (pin = SUNXI_GPC(2); pin <= SUNXI_GPC(7); pin++) {
+                        sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
+                        sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
+                        sunxi_gpio_set_drv(pin, 2);
+                }
 #else
 		puts("ERROR: No pinmux setup defined for MMC2!\n");
 #endif
-- 
2.35.8


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 19/22] sunxi: refactor serial base addresses to avoid asm/arch/cpu.h
  2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
                   ` (17 preceding siblings ...)
  2023-09-28 21:54 ` [PATCH v2 18/22] sunxi: R528: add SMHC2 pin pull ups support Andre Przywara
@ 2023-09-28 21:54 ` Andre Przywara
  2023-09-28 21:54 ` [PATCH v2 20/22] riscv: dts: allwinner: Add the D1/D1s SoC devicetree Andre Przywara
                   ` (2 subsequent siblings)
  21 siblings, 0 replies; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

At the moment we have each SoC's memory map defined in its own cpu.h,
which is included in include/configs/sunxi_common.h. This will be a
problem with the introduction of Allwinner RISC-V support.

Remove the inclusion of that header file from the common config header,
instead move the required serial base addresses (for the SPL) into a
separate header file. Then include the original cpu.h file only where
we really need it, which is only under arch/arm now.

This disentangles the architecture specific header files from the
generic code.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arch/arm/cpu/armv7/sunxi/sram.c               |  1 +
 arch/arm/cpu/armv8/fel_utils.S                |  1 +
 arch/arm/include/asm/arch-sunxi/boot0.h       |  2 ++
 arch/arm/include/asm/arch-sunxi/clock.h       |  1 +
 arch/arm/include/asm/arch-sunxi/cpu_sun4i.h   | 15 ---------
 .../include/asm/arch-sunxi/cpu_sun50i_h6.h    |  5 ---
 arch/arm/include/asm/arch-sunxi/cpu_sun9i.h   |  7 ----
 .../include/asm/arch-sunxi/cpu_sunxi_ncat2.h  |  4 ---
 arch/arm/include/asm/arch-sunxi/serial.h      | 32 +++++++++++++++++++
 arch/arm/mach-sunxi/gtbus_sun9i.c             |  1 +
 arch/arm/mach-sunxi/timer.c                   |  1 +
 include/configs/sunxi-common.h                |  2 +-
 12 files changed, 40 insertions(+), 32 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-sunxi/serial.h

diff --git a/arch/arm/cpu/armv7/sunxi/sram.c b/arch/arm/cpu/armv7/sunxi/sram.c
index 28564c2846a..28ff6a1b7c2 100644
--- a/arch/arm/cpu/armv7/sunxi/sram.c
+++ b/arch/arm/cpu/armv7/sunxi/sram.c
@@ -12,6 +12,7 @@
 #include <common.h>
 #include <init.h>
 #include <asm/io.h>
+#include <asm/arch/cpu.h>
 
 void sunxi_sram_init(void)
 {
diff --git a/arch/arm/cpu/armv8/fel_utils.S b/arch/arm/cpu/armv8/fel_utils.S
index 2fe38a1a047..939869b9ffa 100644
--- a/arch/arm/cpu/armv8/fel_utils.S
+++ b/arch/arm/cpu/armv8/fel_utils.S
@@ -10,6 +10,7 @@
 #include <config.h>
 #include <asm/system.h>
 #include <linux/linkage.h>
+#include <asm/arch/cpu.h>
 
 /*
  * We don't overwrite save_boot_params() here, to save the FEL state upon
diff --git a/arch/arm/include/asm/arch-sunxi/boot0.h b/arch/arm/include/asm/arch-sunxi/boot0.h
index 30f5680757a..cad25c50bc6 100644
--- a/arch/arm/include/asm/arch-sunxi/boot0.h
+++ b/arch/arm/include/asm/arch-sunxi/boot0.h
@@ -3,6 +3,8 @@
  * Configuration settings for the Allwinner A64 (sun50i) CPU
  */
 
+#include <asm/arch/cpu.h>
+
 #if defined(CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER) && !defined(CONFIG_SPL_BUILD)
 /* reserve space for BOOT0 header information */
 	b	reset
diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h
index 3d34261b0e5..fcc8966cb0b 100644
--- a/arch/arm/include/asm/arch-sunxi/clock.h
+++ b/arch/arm/include/asm/arch-sunxi/clock.h
@@ -9,6 +9,7 @@
 #define _SUNXI_CLOCK_H
 
 #include <linux/types.h>
+#include <asm/arch/cpu.h>
 
 #define CLK_GATE_OPEN			0x1
 #define CLK_GATE_CLOSE			0x0
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
index d6fe51f24bc..3daee2f574a 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
@@ -128,20 +128,6 @@ defined(CONFIG_MACH_SUN50I)
 #define SUNXI_CPUCFG_BASE		0x01c25c00
 #endif
 
-#ifdef CONFIG_MACH_SUNIV
-#define SUNXI_UART0_BASE		0x01c25000
-#define SUNXI_UART1_BASE		0x01c25400
-#define SUNXI_UART2_BASE		0x01c25800
-#else
-#define SUNXI_UART0_BASE		0x01c28000
-#define SUNXI_UART1_BASE		0x01c28400
-#define SUNXI_UART2_BASE		0x01c28800
-#endif
-#define SUNXI_UART3_BASE		0x01c28c00
-#define SUNXI_UART4_BASE		0x01c29000
-#define SUNXI_UART5_BASE		0x01c29400
-#define SUNXI_UART6_BASE		0x01c29800
-#define SUNXI_UART7_BASE		0x01c29c00
 #define SUNXI_PS2_0_BASE		0x01c2a000
 #define SUNXI_PS2_1_BASE		0x01c2a400
 
@@ -208,7 +194,6 @@ defined(CONFIG_MACH_SUN50I)
 #endif
 
 #define SUNXI_R_TWI_BASE		0x01f02400
-#define SUNXI_R_UART_BASE		0x01f02800
 #define SUN6I_P2WI_BASE			0x01f03400
 #define SUNXI_RSB_BASE			0x01f03400
 
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
index 9b6bf843601..15ee092d358 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
@@ -42,10 +42,6 @@
 #define SUNXI_DRAM_PHY0_BASE		0x04800000
 #endif
 
-#define SUNXI_UART0_BASE		0x05000000
-#define SUNXI_UART1_BASE		0x05000400
-#define SUNXI_UART2_BASE		0x05000800
-#define SUNXI_UART3_BASE		0x05000C00
 #define SUNXI_TWI0_BASE			0x05002000
 #define SUNXI_TWI1_BASE			0x05002400
 #define SUNXI_TWI2_BASE			0x05002800
@@ -67,7 +63,6 @@
 #define SUNXI_R_CPUCFG_BASE		0x07000400
 #define SUNXI_PRCM_BASE			0x07010000
 #define SUNXI_R_WDOG_BASE		0x07020400
-#define SUNXI_R_UART_BASE		0x07080000
 #define SUNXI_R_TWI_BASE		0x07081400
 
 #ifndef __ASSEMBLY__
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
index 20025be2319..2bf2675d5c1 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
@@ -86,12 +86,6 @@
 #define SUNXI_LRADC_BASE		(REGS_APB0_BASE + 0x1800)
 
 /* APB1 Module */
-#define SUNXI_UART0_BASE		(REGS_APB1_BASE + 0x0000)
-#define SUNXI_UART1_BASE		(REGS_APB1_BASE + 0x0400)
-#define SUNXI_UART2_BASE		(REGS_APB1_BASE + 0x0800)
-#define SUNXI_UART3_BASE		(REGS_APB1_BASE + 0x0C00)
-#define SUNXI_UART4_BASE		(REGS_APB1_BASE + 0x1000)
-#define SUNXI_UART5_BASE		(REGS_APB1_BASE + 0x1400)
 #define SUNXI_TWI0_BASE			(REGS_APB1_BASE + 0x2800)
 #define SUNXI_TWI1_BASE			(REGS_APB1_BASE + 0x2C00)
 #define SUNXI_TWI2_BASE			(REGS_APB1_BASE + 0x3000)
@@ -100,7 +94,6 @@
 
 /* RCPUS Module */
 #define SUNXI_PRCM_BASE			(REGS_RCPUS_BASE + 0x1400)
-#define SUNXI_R_UART_BASE		(REGS_RCPUS_BASE + 0x2800)
 #define SUNXI_RSB_BASE			(REGS_RCPUS_BASE + 0x3400)
 
 /* Misc. */
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
index ca92c39927d..908a582ae0f 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
@@ -10,10 +10,6 @@
 #define SUNXI_CCM_BASE			0x02001000
 #define SUNXI_TIMER_BASE		0x02050000
 
-#define SUNXI_UART0_BASE		0x02500000
-#define SUNXI_UART1_BASE		0x02500400
-#define SUNXI_UART2_BASE		0x02500800
-#define SUNXI_UART3_BASE		0x02500C00
 #define SUNXI_TWI0_BASE			0x02502000
 #define SUNXI_TWI1_BASE			0x02502400
 #define SUNXI_TWI2_BASE			0x02502800
diff --git a/arch/arm/include/asm/arch-sunxi/serial.h b/arch/arm/include/asm/arch-sunxi/serial.h
new file mode 100644
index 00000000000..9386287b65e
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/serial.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ *  hardcoded UART base addresses for early SPL use
+ *
+ *  Copyright (c) 2022  Arm Ltd.
+ */
+
+#ifndef SUNXI_SERIAL_MEMMAP_H
+#define SUNXI_SERIAL_MEMMAP_H
+
+#if defined(CONFIG_MACH_SUN9I)
+#define SUNXI_UART0_BASE		0x07000000
+#define SUNXI_R_UART_BASE		0x08002800
+#elif defined(CONFIG_SUN50I_GEN_H6)
+#define SUNXI_UART0_BASE		0x05000000
+#define SUNXI_R_UART_BASE		0x07080000
+#elif defined(CONFIG_MACH_SUNIV)
+#define SUNXI_UART0_BASE		0x01c25000
+#define SUNXI_R_UART_BASE		0
+#elif defined(CONFIG_SUNXI_GEN_NCAT2)
+#define SUNXI_UART0_BASE		0x02500000
+#define SUNXI_R_UART_BASE		0		// 0x07080000 (?>
+#else
+#define SUNXI_UART0_BASE		0x01c28000
+#define SUNXI_R_UART_BASE		0x01f02800
+#endif
+
+#define SUNXI_UART1_BASE		(SUNXI_UART0_BASE + 0x400)
+#define SUNXI_UART2_BASE		(SUNXI_UART0_BASE + 0x800)
+#define SUNXI_UART3_BASE		(SUNXI_UART0_BASE + 0xc00)
+
+#endif /* SUNXI_SERIAL_MEMMAP_H */
diff --git a/arch/arm/mach-sunxi/gtbus_sun9i.c b/arch/arm/mach-sunxi/gtbus_sun9i.c
index cf011c4cfa7..5624621b500 100644
--- a/arch/arm/mach-sunxi/gtbus_sun9i.c
+++ b/arch/arm/mach-sunxi/gtbus_sun9i.c
@@ -8,6 +8,7 @@
 
 #include <common.h>
 #include <asm/io.h>
+#include <asm/arch/cpu.h>
 #include <asm/arch/gtbus_sun9i.h>
 #include <asm/arch/sys_proto.h>
 
diff --git a/arch/arm/mach-sunxi/timer.c b/arch/arm/mach-sunxi/timer.c
index fc9d419a25e..9a6f6c06d8c 100644
--- a/arch/arm/mach-sunxi/timer.c
+++ b/arch/arm/mach-sunxi/timer.c
@@ -10,6 +10,7 @@
 #include <time.h>
 #include <asm/global_data.h>
 #include <asm/io.h>
+#include <asm/arch/cpu.h>
 #include <asm/arch/timer.h>
 #include <linux/delay.h>
 
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index d2d70f0fc23..b8ca77d031d 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -12,7 +12,6 @@
 #ifndef _SUNXI_COMMON_CONFIG_H
 #define _SUNXI_COMMON_CONFIG_H
 
-#include <asm/arch/cpu.h>
 #include <linux/stringify.h>
 
 /* Serial & console */
@@ -24,6 +23,7 @@
 #define CFG_SYS_NS16550_CLK		24000000
 #endif
 #if !CONFIG_IS_ENABLED(DM_SERIAL)
+#include <asm/arch/serial.h>
 # define CFG_SYS_NS16550_COM1		SUNXI_UART0_BASE
 # define CFG_SYS_NS16550_COM2		SUNXI_UART1_BASE
 # define CFG_SYS_NS16550_COM3		SUNXI_UART2_BASE
-- 
2.35.8


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 20/22] riscv: dts: allwinner: Add the D1/D1s SoC devicetree
  2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
                   ` (18 preceding siblings ...)
  2023-09-28 21:54 ` [PATCH v2 19/22] sunxi: refactor serial base addresses to avoid asm/arch/cpu.h Andre Przywara
@ 2023-09-28 21:54 ` Andre Przywara
  2023-09-28 21:54 ` [PATCH v2 21/22] ARM: dts: sunxi: add Allwinner T113-s SoC .dtsi Andre Przywara
  2023-09-28 21:54 ` [PATCH v2 22/22] sunxi: add MangoPi MQ-R board support Andre Przywara
  21 siblings, 0 replies; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

From: Samuel Holland <samuel@sholland.org>

D1 (aka D1-H), D1s (aka F133), R528, and T113 are a family of SoCs based
on a single die, or at a pair of dies derived from the same design.

D1 and D1s contain a single T-HEAD Xuantie C906 CPU, whereas R528 and
T113 contain a pair of Cortex-A7's. D1 and R528 are the full version of
the chip with a BGA package, whereas D1s and T113 are low-pin-count QFP
variants.

Because the original design supported both ARM and RISC-V CPUs, some
peripherals are duplicated. In addition, all variants except D1s contain
a HiFi 4 DSP with its own set of peripherals.

The devicetrees are organized to minimize duplication:
 - Common perhiperals are described in sunxi-d1s-t113.dtsi
 - DSP-related peripherals are described in sunxi-d1-t113.dtsi
 - RISC-V specific hardware is described in sun20i-d1s.dtsi
 - Functionality unique to the D1 variant is described in sun20i-d1.dtsi

The SOC_PERIPHERAL_IRQ macro handles the different #interrupt-cells
values between the ARM (GIC) and RISC-V (PLIC) versions of the SoC.

The files have been copied from a Linux v6.6-rc3 source tree.

Signed-off-by: Samuel Holland <samuel@sholland.org>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
---
 arch/riscv/dts/sun20i-common-regulators.dtsi |  28 +
 arch/riscv/dts/sun20i-d1.dtsi                |  66 ++
 arch/riscv/dts/sun20i-d1s.dtsi               |  76 ++
 arch/riscv/dts/sunxi-d1-t113.dtsi            |  15 +
 arch/riscv/dts/sunxi-d1s-t113.dtsi           | 927 +++++++++++++++++++
 include/dt-bindings/clock/sun20i-d1-r-ccu.h  |  19 +
 include/dt-bindings/reset/sun20i-d1-r-ccu.h  |  16 +
 7 files changed, 1147 insertions(+)
 create mode 100644 arch/riscv/dts/sun20i-common-regulators.dtsi
 create mode 100644 arch/riscv/dts/sun20i-d1.dtsi
 create mode 100644 arch/riscv/dts/sun20i-d1s.dtsi
 create mode 100644 arch/riscv/dts/sunxi-d1-t113.dtsi
 create mode 100644 arch/riscv/dts/sunxi-d1s-t113.dtsi
 create mode 100644 include/dt-bindings/clock/sun20i-d1-r-ccu.h
 create mode 100644 include/dt-bindings/reset/sun20i-d1-r-ccu.h

diff --git a/arch/riscv/dts/sun20i-common-regulators.dtsi b/arch/riscv/dts/sun20i-common-regulators.dtsi
new file mode 100644
index 00000000000..9b03fca2444
--- /dev/null
+++ b/arch/riscv/dts/sun20i-common-regulators.dtsi
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
+
+/ {
+	reg_vcc: vcc {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+	};
+
+	reg_vcc_3v3: vcc-3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc-3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&reg_vcc>;
+	};
+};
+
+&pio {
+	vcc-pb-supply = <&reg_vcc_3v3>;
+	vcc-pc-supply = <&reg_vcc_3v3>;
+	vcc-pd-supply = <&reg_vcc_3v3>;
+	vcc-pe-supply = <&reg_vcc_3v3>;
+	vcc-pf-supply = <&reg_vcc_3v3>;
+	vcc-pg-supply = <&reg_vcc_3v3>;
+};
diff --git a/arch/riscv/dts/sun20i-d1.dtsi b/arch/riscv/dts/sun20i-d1.dtsi
new file mode 100644
index 00000000000..97e7cbb3259
--- /dev/null
+++ b/arch/riscv/dts/sun20i-d1.dtsi
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
+
+#include "sun20i-d1s.dtsi"
+#include "sunxi-d1-t113.dtsi"
+
+/ {
+	soc {
+		lradc: keys@2009800 {
+			compatible = "allwinner,sun20i-d1-lradc",
+				     "allwinner,sun50i-r329-lradc";
+			reg = <0x2009800 0x400>;
+			interrupts = <SOC_PERIPHERAL_IRQ(61) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_LRADC>;
+			resets = <&ccu RST_BUS_LRADC>;
+			status = "disabled";
+		};
+
+		i2s0: i2s@2032000 {
+			compatible = "allwinner,sun20i-d1-i2s",
+				     "allwinner,sun50i-r329-i2s";
+			reg = <0x2032000 0x1000>;
+			interrupts = <SOC_PERIPHERAL_IRQ(26) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2S0>,
+				 <&ccu CLK_I2S0>;
+			clock-names = "apb", "mod";
+			resets = <&ccu RST_BUS_I2S0>;
+			dmas = <&dma 3>, <&dma 3>;
+			dma-names = "rx", "tx";
+			status = "disabled";
+			#sound-dai-cells = <0>;
+		};
+	};
+};
+
+&pio {
+	/omit-if-no-ref/
+	dmic_pb11_d0_pin: dmic-pb11-d0-pin {
+		pins = "PB11";
+		function = "dmic";
+	};
+
+	/omit-if-no-ref/
+	dmic_pe17_clk_pin: dmic-pe17-clk-pin {
+		pins = "PE17";
+		function = "dmic";
+	};
+
+	/omit-if-no-ref/
+	i2c0_pb10_pins: i2c0-pb10-pins {
+		pins = "PB10", "PB11";
+		function = "i2c0";
+	};
+
+	/omit-if-no-ref/
+	i2c2_pb0_pins: i2c2-pb0-pins {
+		pins = "PB0", "PB1";
+		function = "i2c2";
+	};
+
+	/omit-if-no-ref/
+	uart0_pb8_pins: uart0-pb8-pins {
+		pins = "PB8", "PB9";
+		function = "uart0";
+	};
+};
diff --git a/arch/riscv/dts/sun20i-d1s.dtsi b/arch/riscv/dts/sun20i-d1s.dtsi
new file mode 100644
index 00000000000..8275630af97
--- /dev/null
+++ b/arch/riscv/dts/sun20i-d1s.dtsi
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
+
+#define SOC_PERIPHERAL_IRQ(nr)	(nr + 16)
+
+#include "sunxi-d1s-t113.dtsi"
+
+/ {
+	cpus {
+		timebase-frequency = <24000000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			compatible = "thead,c906", "riscv";
+			device_type = "cpu";
+			reg = <0>;
+			clocks = <&ccu CLK_RISCV>;
+			d-cache-block-size = <64>;
+			d-cache-sets = <256>;
+			d-cache-size = <32768>;
+			i-cache-block-size = <64>;
+			i-cache-sets = <128>;
+			i-cache-size = <32768>;
+			mmu-type = "riscv,sv39";
+			operating-points-v2 = <&opp_table_cpu>;
+			riscv,isa = "rv64imafdc";
+			#cooling-cells = <2>;
+
+			cpu0_intc: interrupt-controller {
+				compatible = "riscv,cpu-intc";
+				interrupt-controller;
+				#address-cells = <0>;
+				#interrupt-cells = <1>;
+			};
+		};
+	};
+
+	opp_table_cpu: opp-table-cpu {
+		compatible = "operating-points-v2";
+
+		opp-408000000 {
+			opp-hz = /bits/ 64 <408000000>;
+			opp-microvolt = <900000 900000 1100000>;
+		};
+
+		opp-1080000000 {
+			opp-hz = /bits/ 64 <1008000000>;
+			opp-microvolt = <900000 900000 1100000>;
+		};
+	};
+
+	soc {
+		interrupt-parent = <&plic>;
+
+		riscv_wdt: watchdog@6011000 {
+			compatible = "allwinner,sun20i-d1-wdt";
+			reg = <0x6011000 0x20>;
+			interrupts = <SOC_PERIPHERAL_IRQ(131) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&dcxo>, <&rtc CLK_OSC32K>;
+			clock-names = "hosc", "losc";
+		};
+
+		plic: interrupt-controller@10000000 {
+			compatible = "allwinner,sun20i-d1-plic",
+				     "thead,c900-plic";
+			reg = <0x10000000 0x4000000>;
+			interrupts-extended = <&cpu0_intc 11>,
+					      <&cpu0_intc 9>;
+			interrupt-controller;
+			riscv,ndev = <175>;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+		};
+	};
+};
diff --git a/arch/riscv/dts/sunxi-d1-t113.dtsi b/arch/riscv/dts/sunxi-d1-t113.dtsi
new file mode 100644
index 00000000000..b7156123df5
--- /dev/null
+++ b/arch/riscv/dts/sunxi-d1-t113.dtsi
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
+
+/ {
+	soc {
+		dsp_wdt: watchdog@1700400 {
+			compatible = "allwinner,sun20i-d1-wdt";
+			reg = <0x1700400 0x20>;
+			interrupts = <SOC_PERIPHERAL_IRQ(122) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&dcxo>, <&rtc CLK_OSC32K>;
+			clock-names = "hosc", "losc";
+			status = "reserved";
+		};
+	};
+};
diff --git a/arch/riscv/dts/sunxi-d1s-t113.dtsi b/arch/riscv/dts/sunxi-d1s-t113.dtsi
new file mode 100644
index 00000000000..822f022eec2
--- /dev/null
+++ b/arch/riscv/dts/sunxi-d1s-t113.dtsi
@@ -0,0 +1,927 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
+
+#include <dt-bindings/clock/sun6i-rtc.h>
+#include <dt-bindings/clock/sun8i-de2.h>
+#include <dt-bindings/clock/sun8i-tcon-top.h>
+#include <dt-bindings/clock/sun20i-d1-ccu.h>
+#include <dt-bindings/clock/sun20i-d1-r-ccu.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/reset/sun8i-de2.h>
+#include <dt-bindings/reset/sun20i-d1-ccu.h>
+#include <dt-bindings/reset/sun20i-d1-r-ccu.h>
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	dcxo: dcxo-clk {
+		compatible = "fixed-clock";
+		clock-output-names = "dcxo";
+		#clock-cells = <0>;
+	};
+
+	de: display-engine {
+		compatible = "allwinner,sun20i-d1-display-engine";
+		allwinner,pipelines = <&mixer0>, <&mixer1>;
+		status = "disabled";
+	};
+
+	soc {
+		compatible = "simple-bus";
+		ranges;
+		dma-noncoherent;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		pio: pinctrl@2000000 {
+			compatible = "allwinner,sun20i-d1-pinctrl";
+			reg = <0x2000000 0x800>;
+			interrupts = <SOC_PERIPHERAL_IRQ(69) IRQ_TYPE_LEVEL_HIGH>,
+				     <SOC_PERIPHERAL_IRQ(71) IRQ_TYPE_LEVEL_HIGH>,
+				     <SOC_PERIPHERAL_IRQ(73) IRQ_TYPE_LEVEL_HIGH>,
+				     <SOC_PERIPHERAL_IRQ(75) IRQ_TYPE_LEVEL_HIGH>,
+				     <SOC_PERIPHERAL_IRQ(77) IRQ_TYPE_LEVEL_HIGH>,
+				     <SOC_PERIPHERAL_IRQ(79) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_APB0>,
+				 <&dcxo>,
+				 <&rtc CLK_OSC32K>;
+			clock-names = "apb", "hosc", "losc";
+			gpio-controller;
+			interrupt-controller;
+			#gpio-cells = <3>;
+			#interrupt-cells = <3>;
+
+			/omit-if-no-ref/
+			can0_pins: can0-pins {
+				pins = "PB2", "PB3";
+				function = "can0";
+			};
+
+			/omit-if-no-ref/
+			can1_pins: can1-pins {
+				pins = "PB4", "PB5";
+				function = "can1";
+			};
+
+			/omit-if-no-ref/
+			clk_pg11_pin: clk-pg11-pin {
+				pins = "PG11";
+				function = "clk";
+			};
+
+			/omit-if-no-ref/
+			dsi_4lane_pins: dsi-4lane-pins {
+				pins = "PD0", "PD1", "PD2", "PD3", "PD4", "PD5",
+				       "PD6", "PD7", "PD8", "PD9";
+				drive-strength = <30>;
+				function = "dsi";
+			};
+
+			/omit-if-no-ref/
+			lcd_rgb666_pins: lcd-rgb666-pins {
+				pins = "PD0", "PD1", "PD2", "PD3", "PD4", "PD5",
+				       "PD6", "PD7", "PD8", "PD9", "PD10", "PD11",
+				       "PD12", "PD13", "PD14", "PD15", "PD16", "PD17",
+				       "PD18", "PD19", "PD20", "PD21";
+				function = "lcd0";
+			};
+
+			/omit-if-no-ref/
+			mmc0_pins: mmc0-pins {
+				pins = "PF0", "PF1", "PF2", "PF3", "PF4", "PF5";
+				function = "mmc0";
+			};
+
+			/omit-if-no-ref/
+			mmc1_pins: mmc1-pins {
+				pins = "PG0", "PG1", "PG2", "PG3", "PG4", "PG5";
+				function = "mmc1";
+			};
+
+			/omit-if-no-ref/
+			mmc2_pins: mmc2-pins {
+				pins = "PC2", "PC3", "PC4", "PC5", "PC6", "PC7";
+				function = "mmc2";
+			};
+
+			/omit-if-no-ref/
+			rgmii_pe_pins: rgmii-pe-pins {
+				pins = "PE0", "PE1", "PE2", "PE3", "PE4",
+				       "PE5", "PE6", "PE7", "PE8", "PE9",
+				       "PE11", "PE12", "PE13", "PE14", "PE15";
+				function = "emac";
+			};
+
+			/omit-if-no-ref/
+			rmii_pe_pins: rmii-pe-pins {
+				pins = "PE0", "PE1", "PE2", "PE3", "PE4",
+				       "PE5", "PE6", "PE7", "PE8", "PE9";
+				function = "emac";
+			};
+
+			/omit-if-no-ref/
+			spi0_pins: spi0-pins {
+				pins = "PC2", "PC3", "PC4", "PC5";
+				function = "spi0";
+			};
+
+			/omit-if-no-ref/
+			uart1_pg6_pins: uart1-pg6-pins {
+				pins = "PG6", "PG7";
+				function = "uart1";
+			};
+
+			/omit-if-no-ref/
+			uart1_pg8_rts_cts_pins: uart1-pg8-rts-cts-pins {
+				pins = "PG8", "PG9";
+				function = "uart1";
+			};
+
+			/omit-if-no-ref/
+			uart3_pb_pins: uart3-pb-pins {
+				pins = "PB6", "PB7";
+				function = "uart3";
+			};
+		};
+
+		ccu: clock-controller@2001000 {
+			compatible = "allwinner,sun20i-d1-ccu";
+			reg = <0x2001000 0x1000>;
+			clocks = <&dcxo>,
+				 <&rtc CLK_OSC32K>,
+				 <&rtc CLK_IOSC>;
+			clock-names = "hosc", "losc", "iosc";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		gpadc: adc@2009000 {
+			compatible = "allwinner,sun20i-d1-gpadc";
+			reg = <0x2009000 0x400>;
+			clocks = <&ccu CLK_BUS_GPADC>;
+			resets = <&ccu RST_BUS_GPADC>;
+			interrupts = <SOC_PERIPHERAL_IRQ(57) IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+			#io-channel-cells = <1>;
+		};
+
+		dmic: dmic@2031000 {
+			compatible = "allwinner,sun20i-d1-dmic",
+				     "allwinner,sun50i-h6-dmic";
+			reg = <0x2031000 0x400>;
+			interrupts = <SOC_PERIPHERAL_IRQ(24) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_DMIC>,
+				 <&ccu CLK_DMIC>;
+			clock-names = "bus", "mod";
+			resets = <&ccu RST_BUS_DMIC>;
+			dmas = <&dma 8>;
+			dma-names = "rx";
+			status = "disabled";
+			#sound-dai-cells = <0>;
+		};
+
+		i2s1: i2s@2033000 {
+			compatible = "allwinner,sun20i-d1-i2s",
+				     "allwinner,sun50i-r329-i2s";
+			reg = <0x2033000 0x1000>;
+			interrupts = <SOC_PERIPHERAL_IRQ(27) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2S1>,
+				 <&ccu CLK_I2S1>;
+			clock-names = "apb", "mod";
+			resets = <&ccu RST_BUS_I2S1>;
+			dmas = <&dma 4>, <&dma 4>;
+			dma-names = "rx", "tx";
+			status = "disabled";
+			#sound-dai-cells = <0>;
+		};
+
+		i2s2: i2s@2034000 {
+			compatible = "allwinner,sun20i-d1-i2s",
+				     "allwinner,sun50i-r329-i2s";
+			reg = <0x2034000 0x1000>;
+			interrupts = <SOC_PERIPHERAL_IRQ(28) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2S2>,
+				 <&ccu CLK_I2S2>;
+			clock-names = "apb", "mod";
+			resets = <&ccu RST_BUS_I2S2>;
+			dmas = <&dma 5>, <&dma 5>;
+			dma-names = "rx", "tx";
+			status = "disabled";
+			#sound-dai-cells = <0>;
+		};
+
+		timer: timer@2050000 {
+			compatible = "allwinner,sun20i-d1-timer",
+				     "allwinner,sun8i-a23-timer";
+			reg = <0x2050000 0xa0>;
+			interrupts = <SOC_PERIPHERAL_IRQ(59) IRQ_TYPE_LEVEL_HIGH>,
+				     <SOC_PERIPHERAL_IRQ(60) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&dcxo>;
+		};
+
+		wdt: watchdog@20500a0 {
+			compatible = "allwinner,sun20i-d1-wdt-reset",
+				     "allwinner,sun20i-d1-wdt";
+			reg = <0x20500a0 0x20>;
+			interrupts = <SOC_PERIPHERAL_IRQ(63) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&dcxo>, <&rtc CLK_OSC32K>;
+			clock-names = "hosc", "losc";
+			status = "reserved";
+		};
+
+		uart0: serial@2500000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x2500000 0x400>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			interrupts = <SOC_PERIPHERAL_IRQ(2) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_UART0>;
+			resets = <&ccu RST_BUS_UART0>;
+			dmas = <&dma 14>, <&dma 14>;
+			dma-names = "tx", "rx";
+			status = "disabled";
+		};
+
+		uart1: serial@2500400 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x2500400 0x400>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			interrupts = <SOC_PERIPHERAL_IRQ(3) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_UART1>;
+			resets = <&ccu RST_BUS_UART1>;
+			dmas = <&dma 15>, <&dma 15>;
+			dma-names = "tx", "rx";
+			status = "disabled";
+		};
+
+		uart2: serial@2500800 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x2500800 0x400>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			interrupts = <SOC_PERIPHERAL_IRQ(4) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_UART2>;
+			resets = <&ccu RST_BUS_UART2>;
+			dmas = <&dma 16>, <&dma 16>;
+			dma-names = "tx", "rx";
+			status = "disabled";
+		};
+
+		uart3: serial@2500c00 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x2500c00 0x400>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			interrupts = <SOC_PERIPHERAL_IRQ(5) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_UART3>;
+			resets = <&ccu RST_BUS_UART3>;
+			dmas = <&dma 17>, <&dma 17>;
+			dma-names = "tx", "rx";
+			status = "disabled";
+		};
+
+		uart4: serial@2501000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x2501000 0x400>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			interrupts = <SOC_PERIPHERAL_IRQ(6) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_UART4>;
+			resets = <&ccu RST_BUS_UART4>;
+			dmas = <&dma 18>, <&dma 18>;
+			dma-names = "tx", "rx";
+			status = "disabled";
+		};
+
+		uart5: serial@2501400 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x2501400 0x400>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			interrupts = <SOC_PERIPHERAL_IRQ(7) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_UART5>;
+			resets = <&ccu RST_BUS_UART5>;
+			dmas = <&dma 19>, <&dma 19>;
+			dma-names = "tx", "rx";
+			status = "disabled";
+		};
+
+		i2c0: i2c@2502000 {
+			compatible = "allwinner,sun20i-d1-i2c",
+				     "allwinner,sun8i-v536-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x2502000 0x400>;
+			interrupts = <SOC_PERIPHERAL_IRQ(9) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2C0>;
+			resets = <&ccu RST_BUS_I2C0>;
+			dmas = <&dma 43>, <&dma 43>;
+			dma-names = "rx", "tx";
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		i2c1: i2c@2502400 {
+			compatible = "allwinner,sun20i-d1-i2c",
+				     "allwinner,sun8i-v536-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x2502400 0x400>;
+			interrupts = <SOC_PERIPHERAL_IRQ(10) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2C1>;
+			resets = <&ccu RST_BUS_I2C1>;
+			dmas = <&dma 44>, <&dma 44>;
+			dma-names = "rx", "tx";
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		i2c2: i2c@2502800 {
+			compatible = "allwinner,sun20i-d1-i2c",
+				     "allwinner,sun8i-v536-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x2502800 0x400>;
+			interrupts = <SOC_PERIPHERAL_IRQ(11) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2C2>;
+			resets = <&ccu RST_BUS_I2C2>;
+			dmas = <&dma 45>, <&dma 45>;
+			dma-names = "rx", "tx";
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		i2c3: i2c@2502c00 {
+			compatible = "allwinner,sun20i-d1-i2c",
+				     "allwinner,sun8i-v536-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x2502c00 0x400>;
+			interrupts = <SOC_PERIPHERAL_IRQ(12) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2C3>;
+			resets = <&ccu RST_BUS_I2C3>;
+			dmas = <&dma 46>, <&dma 46>;
+			dma-names = "rx", "tx";
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		can0: can@2504000 {
+			compatible = "allwinner,sun20i-d1-can";
+			reg = <0x02504000 0x400>;
+			interrupts = <SOC_PERIPHERAL_IRQ(21) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_CAN0>;
+			resets = <&ccu RST_BUS_CAN0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&can0_pins>;
+			status = "disabled";
+		};
+
+		can1: can@2504400 {
+			compatible = "allwinner,sun20i-d1-can";
+			reg = <0x02504400 0x400>;
+			interrupts = <SOC_PERIPHERAL_IRQ(22) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_CAN1>;
+			resets = <&ccu RST_BUS_CAN1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&can1_pins>;
+			status = "disabled";
+		};
+
+		syscon: syscon@3000000 {
+			compatible = "allwinner,sun20i-d1-system-control";
+			reg = <0x3000000 0x1000>;
+			ranges;
+			#address-cells = <1>;
+			#size-cells = <1>;
+		};
+
+		dma: dma-controller@3002000 {
+			compatible = "allwinner,sun20i-d1-dma";
+			reg = <0x3002000 0x1000>;
+			interrupts = <SOC_PERIPHERAL_IRQ(50) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_DMA>, <&ccu CLK_MBUS_DMA>;
+			clock-names = "bus", "mbus";
+			resets = <&ccu RST_BUS_DMA>;
+			dma-channels = <16>;
+			dma-requests = <48>;
+			#dma-cells = <1>;
+		};
+
+		sid: efuse@3006000 {
+			compatible = "allwinner,sun20i-d1-sid";
+			reg = <0x3006000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+		};
+
+		crypto: crypto@3040000 {
+			compatible = "allwinner,sun20i-d1-crypto";
+			reg = <0x3040000 0x800>;
+			interrupts = <SOC_PERIPHERAL_IRQ(52) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_CE>,
+				 <&ccu CLK_CE>,
+				 <&ccu CLK_MBUS_CE>,
+				 <&rtc CLK_IOSC>;
+			clock-names = "bus", "mod", "ram", "trng";
+			resets = <&ccu RST_BUS_CE>;
+		};
+
+		mbus: dram-controller@3102000 {
+			compatible = "allwinner,sun20i-d1-mbus";
+			reg = <0x3102000 0x1000>,
+			      <0x3103000 0x1000>;
+			reg-names = "mbus", "dram";
+			interrupts = <SOC_PERIPHERAL_IRQ(43) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_MBUS>,
+				 <&ccu CLK_DRAM>,
+				 <&ccu CLK_BUS_DRAM>;
+			clock-names = "mbus", "dram", "bus";
+			dma-ranges = <0 0x40000000 0x80000000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			#interconnect-cells = <1>;
+		};
+
+		mmc0: mmc@4020000 {
+			compatible = "allwinner,sun20i-d1-mmc";
+			reg = <0x4020000 0x1000>;
+			interrupts = <SOC_PERIPHERAL_IRQ(40) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
+			clock-names = "ahb", "mmc";
+			resets = <&ccu RST_BUS_MMC0>;
+			reset-names = "ahb";
+			cap-sd-highspeed;
+			max-frequency = <150000000>;
+			no-mmc;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		mmc1: mmc@4021000 {
+			compatible = "allwinner,sun20i-d1-mmc";
+			reg = <0x4021000 0x1000>;
+			interrupts = <SOC_PERIPHERAL_IRQ(41) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
+			clock-names = "ahb", "mmc";
+			resets = <&ccu RST_BUS_MMC1>;
+			reset-names = "ahb";
+			cap-sd-highspeed;
+			max-frequency = <150000000>;
+			no-mmc;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		mmc2: mmc@4022000 {
+			compatible = "allwinner,sun20i-d1-emmc",
+				     "allwinner,sun50i-a100-emmc";
+			reg = <0x4022000 0x1000>;
+			interrupts = <SOC_PERIPHERAL_IRQ(42) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>;
+			clock-names = "ahb", "mmc";
+			resets = <&ccu RST_BUS_MMC2>;
+			reset-names = "ahb";
+			cap-mmc-highspeed;
+			max-frequency = <150000000>;
+			mmc-ddr-1_8v;
+			mmc-ddr-3_3v;
+			no-sd;
+			no-sdio;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		spi0: spi@4025000 {
+			compatible = "allwinner,sun20i-d1-spi",
+				     "allwinner,sun50i-r329-spi";
+			reg = <0x04025000 0x1000>;
+			interrupts = <SOC_PERIPHERAL_IRQ(15) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
+			clock-names = "ahb", "mod";
+			dmas = <&dma 22>, <&dma 22>;
+			dma-names = "rx", "tx";
+			resets = <&ccu RST_BUS_SPI0>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		spi1: spi@4026000 {
+			compatible = "allwinner,sun20i-d1-spi-dbi",
+				     "allwinner,sun50i-r329-spi-dbi",
+				     "allwinner,sun50i-r329-spi";
+			reg = <0x04026000 0x1000>;
+			interrupts = <SOC_PERIPHERAL_IRQ(16) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>;
+			clock-names = "ahb", "mod";
+			dmas = <&dma 23>, <&dma 23>;
+			dma-names = "rx", "tx";
+			resets = <&ccu RST_BUS_SPI1>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		usb_otg: usb@4100000 {
+			compatible = "allwinner,sun20i-d1-musb",
+				     "allwinner,sun8i-a33-musb";
+			reg = <0x4100000 0x400>;
+			interrupts = <SOC_PERIPHERAL_IRQ(29) IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "mc";
+			clocks = <&ccu CLK_BUS_OTG>;
+			resets = <&ccu RST_BUS_OTG>;
+			extcon = <&usbphy 0>;
+			phys = <&usbphy 0>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		usbphy: phy@4100400 {
+			compatible = "allwinner,sun20i-d1-usb-phy";
+			reg = <0x4100400 0x100>,
+			      <0x4101800 0x100>,
+			      <0x4200800 0x100>;
+			reg-names = "phy_ctrl",
+				    "pmu0",
+				    "pmu1";
+			clocks = <&dcxo>,
+				 <&dcxo>;
+			clock-names = "usb0_phy",
+				      "usb1_phy";
+			resets = <&ccu RST_USB_PHY0>,
+				 <&ccu RST_USB_PHY1>;
+			reset-names = "usb0_reset",
+				      "usb1_reset";
+			status = "disabled";
+			#phy-cells = <1>;
+		};
+
+		ehci0: usb@4101000 {
+			compatible = "allwinner,sun20i-d1-ehci",
+				     "generic-ehci";
+			reg = <0x4101000 0x100>;
+			interrupts = <SOC_PERIPHERAL_IRQ(30) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_OHCI0>,
+				 <&ccu CLK_BUS_EHCI0>,
+				 <&ccu CLK_USB_OHCI0>;
+			resets = <&ccu RST_BUS_OHCI0>,
+				 <&ccu RST_BUS_EHCI0>;
+			phys = <&usbphy 0>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ohci0: usb@4101400 {
+			compatible = "allwinner,sun20i-d1-ohci",
+				     "generic-ohci";
+			reg = <0x4101400 0x100>;
+			interrupts = <SOC_PERIPHERAL_IRQ(31) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_OHCI0>,
+				 <&ccu CLK_USB_OHCI0>;
+			resets = <&ccu RST_BUS_OHCI0>;
+			phys = <&usbphy 0>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ehci1: usb@4200000 {
+			compatible = "allwinner,sun20i-d1-ehci",
+				     "generic-ehci";
+			reg = <0x4200000 0x100>;
+			interrupts = <SOC_PERIPHERAL_IRQ(33) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_OHCI1>,
+				 <&ccu CLK_BUS_EHCI1>,
+				 <&ccu CLK_USB_OHCI1>;
+			resets = <&ccu RST_BUS_OHCI1>,
+				 <&ccu RST_BUS_EHCI1>;
+			phys = <&usbphy 1>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ohci1: usb@4200400 {
+			compatible = "allwinner,sun20i-d1-ohci",
+				     "generic-ohci";
+			reg = <0x4200400 0x100>;
+			interrupts = <SOC_PERIPHERAL_IRQ(34) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_OHCI1>,
+				 <&ccu CLK_USB_OHCI1>;
+			resets = <&ccu RST_BUS_OHCI1>;
+			phys = <&usbphy 1>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		emac: ethernet@4500000 {
+			compatible = "allwinner,sun20i-d1-emac",
+				     "allwinner,sun50i-a64-emac";
+			reg = <0x4500000 0x10000>;
+			interrupts = <SOC_PERIPHERAL_IRQ(46) IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "macirq";
+			clocks = <&ccu CLK_BUS_EMAC>;
+			clock-names = "stmmaceth";
+			resets = <&ccu RST_BUS_EMAC>;
+			reset-names = "stmmaceth";
+			syscon = <&syscon>;
+			status = "disabled";
+
+			mdio: mdio {
+				compatible = "snps,dwmac-mdio";
+				#address-cells = <1>;
+				#size-cells = <0>;
+			};
+		};
+
+		display_clocks: clock-controller@5000000 {
+			compatible = "allwinner,sun20i-d1-de2-clk",
+				     "allwinner,sun50i-h5-de2-clk";
+			reg = <0x5000000 0x10000>;
+			clocks = <&ccu CLK_BUS_DE>, <&ccu CLK_DE>;
+			clock-names = "bus", "mod";
+			resets = <&ccu RST_BUS_DE>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		mixer0: mixer@5100000 {
+			compatible = "allwinner,sun20i-d1-de2-mixer-0";
+			reg = <0x5100000 0x100000>;
+			clocks = <&display_clocks CLK_BUS_MIXER0>,
+				 <&display_clocks CLK_MIXER0>;
+			clock-names = "bus", "mod";
+			resets = <&display_clocks RST_MIXER0>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				mixer0_out: port@1 {
+					reg = <1>;
+
+					mixer0_out_tcon_top_mixer0: endpoint {
+						remote-endpoint = <&tcon_top_mixer0_in_mixer0>;
+					};
+				};
+			};
+		};
+
+		mixer1: mixer@5200000 {
+			compatible = "allwinner,sun20i-d1-de2-mixer-1";
+			reg = <0x5200000 0x100000>;
+			clocks = <&display_clocks CLK_BUS_MIXER1>,
+				 <&display_clocks CLK_MIXER1>;
+			clock-names = "bus", "mod";
+			resets = <&display_clocks RST_MIXER1>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				mixer1_out: port@1 {
+					reg = <1>;
+
+					mixer1_out_tcon_top_mixer1: endpoint {
+						remote-endpoint = <&tcon_top_mixer1_in_mixer1>;
+					};
+				};
+			};
+		};
+
+		dsi: dsi@5450000 {
+			compatible = "allwinner,sun20i-d1-mipi-dsi",
+				     "allwinner,sun50i-a100-mipi-dsi";
+			reg = <0x5450000 0x1000>;
+			interrupts = <SOC_PERIPHERAL_IRQ(92) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_MIPI_DSI>,
+				 <&tcon_top CLK_TCON_TOP_DSI>;
+			clock-names = "bus", "mod";
+			resets = <&ccu RST_BUS_MIPI_DSI>;
+			phys = <&dphy>;
+			phy-names = "dphy";
+			status = "disabled";
+
+			port {
+				dsi_in_tcon_lcd0: endpoint {
+					remote-endpoint = <&tcon_lcd0_out_dsi>;
+				};
+			};
+		};
+
+		dphy: phy@5451000 {
+			compatible = "allwinner,sun20i-d1-mipi-dphy",
+				     "allwinner,sun50i-a100-mipi-dphy";
+			reg = <0x5451000 0x1000>;
+			interrupts = <SOC_PERIPHERAL_IRQ(92) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_MIPI_DSI>,
+				 <&ccu CLK_MIPI_DSI>;
+			clock-names = "bus", "mod";
+			resets = <&ccu RST_BUS_MIPI_DSI>;
+			#phy-cells = <0>;
+		};
+
+		tcon_top: tcon-top@5460000 {
+			compatible = "allwinner,sun20i-d1-tcon-top";
+			reg = <0x5460000 0x1000>;
+			clocks = <&ccu CLK_BUS_DPSS_TOP>,
+				 <&ccu CLK_TCON_TV>,
+				 <&ccu CLK_TVE>,
+				 <&ccu CLK_TCON_LCD0>;
+			clock-names = "bus", "tcon-tv0", "tve0", "dsi";
+			clock-output-names = "tcon-top-tv0", "tcon-top-dsi";
+			resets = <&ccu RST_BUS_DPSS_TOP>;
+			#clock-cells = <1>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				tcon_top_mixer0_in: port@0 {
+					reg = <0>;
+
+					tcon_top_mixer0_in_mixer0: endpoint {
+						remote-endpoint = <&mixer0_out_tcon_top_mixer0>;
+					};
+				};
+
+				tcon_top_mixer0_out: port@1 {
+					reg = <1>;
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					tcon_top_mixer0_out_tcon_lcd0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&tcon_lcd0_in_tcon_top_mixer0>;
+					};
+
+					tcon_top_mixer0_out_tcon_tv0: endpoint@2 {
+						reg = <2>;
+						remote-endpoint = <&tcon_tv0_in_tcon_top_mixer0>;
+					};
+				};
+
+				tcon_top_mixer1_in: port@2 {
+					reg = <2>;
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					tcon_top_mixer1_in_mixer1: endpoint@1 {
+						reg = <1>;
+						remote-endpoint = <&mixer1_out_tcon_top_mixer1>;
+					};
+				};
+
+				tcon_top_mixer1_out: port@3 {
+					reg = <3>;
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					tcon_top_mixer1_out_tcon_lcd0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&tcon_lcd0_in_tcon_top_mixer1>;
+					};
+
+					tcon_top_mixer1_out_tcon_tv0: endpoint@2 {
+						reg = <2>;
+						remote-endpoint = <&tcon_tv0_in_tcon_top_mixer1>;
+					};
+				};
+
+				tcon_top_hdmi_in: port@4 {
+					reg = <4>;
+
+					tcon_top_hdmi_in_tcon_tv0: endpoint {
+						remote-endpoint = <&tcon_tv0_out_tcon_top_hdmi>;
+					};
+				};
+
+				tcon_top_hdmi_out: port@5 {
+					reg = <5>;
+				};
+			};
+		};
+
+		tcon_lcd0: lcd-controller@5461000 {
+			compatible = "allwinner,sun20i-d1-tcon-lcd";
+			reg = <0x5461000 0x1000>;
+			interrupts = <SOC_PERIPHERAL_IRQ(90) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_TCON_LCD0>,
+				 <&ccu CLK_TCON_LCD0>;
+			clock-names = "ahb", "tcon-ch0";
+			clock-output-names = "tcon-pixel-clock";
+			resets = <&ccu RST_BUS_TCON_LCD0>,
+				 <&ccu RST_BUS_LVDS0>;
+			reset-names = "lcd", "lvds";
+			#clock-cells = <0>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				tcon_lcd0_in: port@0 {
+					reg = <0>;
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					tcon_lcd0_in_tcon_top_mixer0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&tcon_top_mixer0_out_tcon_lcd0>;
+					};
+
+					tcon_lcd0_in_tcon_top_mixer1: endpoint@1 {
+						reg = <1>;
+						remote-endpoint = <&tcon_top_mixer1_out_tcon_lcd0>;
+					};
+				};
+
+				tcon_lcd0_out: port@1 {
+					reg = <1>;
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					tcon_lcd0_out_dsi: endpoint@1 {
+						reg = <1>;
+						remote-endpoint = <&dsi_in_tcon_lcd0>;
+					};
+				};
+			};
+		};
+
+		tcon_tv0: lcd-controller@5470000 {
+			compatible = "allwinner,sun20i-d1-tcon-tv";
+			reg = <0x5470000 0x1000>;
+			interrupts = <SOC_PERIPHERAL_IRQ(91) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_TCON_TV>,
+				 <&tcon_top CLK_TCON_TOP_TV0>;
+			clock-names = "ahb", "tcon-ch1";
+			resets = <&ccu RST_BUS_TCON_TV>;
+			reset-names = "lcd";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				tcon_tv0_in: port@0 {
+					reg = <0>;
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					tcon_tv0_in_tcon_top_mixer0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&tcon_top_mixer0_out_tcon_tv0>;
+					};
+
+					tcon_tv0_in_tcon_top_mixer1: endpoint@1 {
+						reg = <1>;
+						remote-endpoint = <&tcon_top_mixer1_out_tcon_tv0>;
+					};
+				};
+
+				tcon_tv0_out: port@1 {
+					reg = <1>;
+
+					tcon_tv0_out_tcon_top_hdmi: endpoint {
+						remote-endpoint = <&tcon_top_hdmi_in_tcon_tv0>;
+					};
+				};
+			};
+		};
+
+		ppu: power-controller@7001000 {
+			compatible = "allwinner,sun20i-d1-ppu";
+			reg = <0x7001000 0x1000>;
+			clocks = <&r_ccu CLK_BUS_R_PPU>;
+			resets = <&r_ccu RST_BUS_R_PPU>;
+			#power-domain-cells = <1>;
+		};
+
+		r_ccu: clock-controller@7010000 {
+			compatible = "allwinner,sun20i-d1-r-ccu";
+			reg = <0x7010000 0x400>;
+			clocks = <&dcxo>,
+				 <&rtc CLK_OSC32K>,
+				 <&rtc CLK_IOSC>,
+				 <&ccu CLK_PLL_PERIPH0_DIV3>;
+			clock-names = "hosc", "losc", "iosc", "pll-periph";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		rtc: rtc@7090000 {
+			compatible = "allwinner,sun20i-d1-rtc",
+				     "allwinner,sun50i-r329-rtc";
+			reg = <0x7090000 0x400>;
+			interrupts = <SOC_PERIPHERAL_IRQ(144) IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&r_ccu CLK_BUS_R_RTC>,
+				 <&dcxo>,
+				 <&r_ccu CLK_R_AHB>;
+			clock-names = "bus", "hosc", "ahb";
+			#clock-cells = <1>;
+		};
+	};
+};
diff --git a/include/dt-bindings/clock/sun20i-d1-r-ccu.h b/include/dt-bindings/clock/sun20i-d1-r-ccu.h
new file mode 100644
index 00000000000..f95c170711e
--- /dev/null
+++ b/include/dt-bindings/clock/sun20i-d1-r-ccu.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN20I_D1_R_CCU_H_
+#define _DT_BINDINGS_CLK_SUN20I_D1_R_CCU_H_
+
+#define CLK_R_AHB		0
+
+#define CLK_BUS_R_TIMER		2
+#define CLK_BUS_R_TWD		3
+#define CLK_BUS_R_PPU		4
+#define CLK_R_IR_RX		5
+#define CLK_BUS_R_IR_RX		6
+#define CLK_BUS_R_RTC		7
+#define CLK_BUS_R_CPUCFG	8
+
+#endif /* _DT_BINDINGS_CLK_SUN20I_D1_R_CCU_H_ */
diff --git a/include/dt-bindings/reset/sun20i-d1-r-ccu.h b/include/dt-bindings/reset/sun20i-d1-r-ccu.h
new file mode 100644
index 00000000000..e20babc990a
--- /dev/null
+++ b/include/dt-bindings/reset/sun20i-d1-r-ccu.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN20I_D1_R_CCU_H_
+#define _DT_BINDINGS_RST_SUN20I_D1_R_CCU_H_
+
+#define RST_BUS_R_TIMER		0
+#define RST_BUS_R_TWD		1
+#define RST_BUS_R_PPU		2
+#define RST_BUS_R_IR_RX		3
+#define RST_BUS_R_RTC		4
+#define RST_BUS_R_CPUCFG	5
+
+#endif /* _DT_BINDINGS_RST_SUN20I_D1_R_CCU_H_ */
-- 
2.35.8


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 21/22] ARM: dts: sunxi: add Allwinner T113-s SoC .dtsi
  2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
                   ` (19 preceding siblings ...)
  2023-09-28 21:54 ` [PATCH v2 20/22] riscv: dts: allwinner: Add the D1/D1s SoC devicetree Andre Przywara
@ 2023-09-28 21:54 ` Andre Przywara
  2023-09-28 21:54 ` [PATCH v2 22/22] sunxi: add MangoPi MQ-R board support Andre Przywara
  21 siblings, 0 replies; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

The Allwinner T113-s SoC is apparently using the same (or at least a very
similar) die as the D1/D1s, but replaces the single RISC-V core with
two Arm Cortex-A7 cores.
Since the D1 core .dtsi already describes all common peripherals, we
just need a DT describing the ARM specific peripherals: the CPU cores,
the Generic Timer, the GIC and the PMU.
We include the core .dtsi directly from the riscv DT directory.

The ARM core version of the DT specifies the CPUX watchdog as
"reserved", which means it won't be recognised by U-Boot. Override this
in our generic sunxi-u-boot.dtsi, to let U-Boot pick up this watchdog,
so that the generic reset driver will work.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arch/arm/dts/sun8i-t113s.dtsi  | 59 ++++++++++++++++++++++++++++++++++
 arch/arm/dts/sunxi-u-boot.dtsi |  7 ++++
 2 files changed, 66 insertions(+)
 create mode 100644 arch/arm/dts/sun8i-t113s.dtsi

diff --git a/arch/arm/dts/sun8i-t113s.dtsi b/arch/arm/dts/sun8i-t113s.dtsi
new file mode 100644
index 00000000000..b94b69142af
--- /dev/null
+++ b/arch/arm/dts/sun8i-t113s.dtsi
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (C) 2022 Arm Ltd.
+
+#define SOC_PERIPHERAL_IRQ(nr) GIC_SPI nr
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <../../riscv/dts/sunxi-d1s-t113.dtsi>
+#include <../../riscv/dts/sunxi-d1-t113.dtsi>
+
+/ {
+	interrupt-parent = <&gic>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			compatible = "arm,cortex-a7";
+			device_type = "cpu";
+			reg = <0>;
+			clocks = <&ccu CLK_CPUX>;
+			clock-names = "cpu";
+		};
+
+		cpu1: cpu@1 {
+			compatible = "arm,cortex-a7";
+			device_type = "cpu";
+			reg = <1>;
+			clocks = <&ccu CLK_CPUX>;
+			clock-names = "cpu";
+		};
+	};
+
+	gic: interrupt-controller@1c81000 {
+		compatible = "arm,gic-400";
+		reg = <0x03021000 0x1000>,
+		      <0x03022000 0x2000>,
+		      <0x03024000 0x2000>,
+		      <0x03026000 0x2000>;
+		interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+	};
+
+	pmu {
+		compatible = "arm,cortex-a7-pmu";
+		interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>, <&cpu1>;
+	};
+};
diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi
index af419c7e590..a0c8abb7033 100644
--- a/arch/arm/dts/sunxi-u-boot.dtsi
+++ b/arch/arm/dts/sunxi-u-boot.dtsi
@@ -23,6 +23,13 @@
 	};
 };
 
+/* Let U-Boot be the firmware layer that controls the watchdog. */
+#ifdef CONFIG_MACH_SUN8I_R528
+&wdt {
+	status = "okay";
+};
+#endif
+
 &binman {
 	u-boot-sunxi-with-spl {
 		filename = "u-boot-sunxi-with-spl.bin";
-- 
2.35.8


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 22/22] sunxi: add MangoPi MQ-R board support
  2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
                   ` (20 preceding siblings ...)
  2023-09-28 21:54 ` [PATCH v2 21/22] ARM: dts: sunxi: add Allwinner T113-s SoC .dtsi Andre Przywara
@ 2023-09-28 21:54 ` Andre Przywara
  21 siblings, 0 replies; 43+ messages in thread
From: Andre Przywara @ 2023-09-28 21:54 UTC (permalink / raw)
  To: Jagan Teki, u-boot
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov, linux-sunxi, andre.przywara,
	andre.przywara

This copies the T113s specific DTs from the Linux kernel tree
(v6.4-rc1), and adds a defconfig to get the board booted.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arch/arm/dts/Makefile                         |   2 +
 .../arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts |  35 +++++
 arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi | 126 ++++++++++++++++++
 configs/mangopi_mq_r_defconfig                |  15 +++
 4 files changed, 178 insertions(+)
 create mode 100644 arch/arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts
 create mode 100644 arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi
 create mode 100644 configs/mangopi_mq_r_defconfig

diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index bde2176ec7f..0919cea55ef 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -754,6 +754,8 @@ dtb-$(CONFIG_MACH_SUN8I_V3S) += \
 	sun8i-s3-pinecube.dtb \
 	sun8i-v3-sl631-imx179.dtb \
 	sun8i-v3s-licheepi-zero.dtb
+dtb-$(CONFIG_MACH_SUN8I_R528) += \
+	sun8i-t113s-mangopi-mq-r-t113.dtb
 dtb-$(CONFIG_MACH_SUN50I_H5) += \
 	sun50i-h5-bananapi-m2-plus.dtb \
 	sun50i-h5-emlid-neutis-n5-devboard.dtb \
diff --git a/arch/arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts b/arch/arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts
new file mode 100644
index 00000000000..8b3a7538381
--- /dev/null
+++ b/arch/arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (C) 2022 Arm Ltd.
+
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/dts-v1/;
+
+#include "sun8i-t113s.dtsi"
+#include "sunxi-d1s-t113-mangopi-mq-r.dtsi"
+
+/ {
+	model = "MangoPi MQ-R-T113";
+	compatible = "widora,mangopi-mq-r-t113", "allwinner,sun8i-t113s";
+
+	aliases {
+		ethernet0 = &rtl8189ftv;
+	};
+};
+
+&cpu0 {
+	cpu-supply = <&reg_vcc_core>;
+};
+
+&cpu1 {
+	cpu-supply = <&reg_vcc_core>;
+};
+
+&mmc1 {
+	rtl8189ftv: wifi@1 {
+		reg = <1>;
+		interrupt-parent = <&pio>;
+		interrupts = <6 10 IRQ_TYPE_LEVEL_LOW>; /* PG10 = WL_WAKE_AP */
+		interrupt-names = "host-wake";
+	};
+};
diff --git a/arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi b/arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi
new file mode 100644
index 00000000000..a415c4a78a7
--- /dev/null
+++ b/arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (C) 2022 Arm Ltd.
+/*
+ * Common peripherals and configurations for MangoPi MQ-R boards.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+	aliases {
+		serial3 = &uart3;
+	};
+
+	chosen {
+		stdout-path = "serial3:115200n8";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led-0 {
+			color = <LED_COLOR_ID_BLUE>;
+			function = LED_FUNCTION_STATUS;
+			gpios = <&pio 3 22 GPIO_ACTIVE_LOW>; /* PD22 */
+		};
+	};
+
+	/* board wide 5V supply directly from the USB-C socket */
+	reg_vcc5v: regulator-5v {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc-5v";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	/* SY8008 DC/DC regulator on the board */
+	reg_3v3: regulator-3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc-3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&reg_vcc5v>;
+	};
+
+	/* SY8008 DC/DC regulator on the board, also supplying VDD-SYS */
+	reg_vcc_core: regulator-core {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc-core";
+		regulator-min-microvolt = <880000>;
+		regulator-max-microvolt = <880000>;
+		vin-supply = <&reg_vcc5v>;
+	};
+
+	/* XC6206 LDO on the board */
+	reg_avdd2v8: regulator-avdd {
+		compatible = "regulator-fixed";
+		regulator-name = "avdd2v8";
+		regulator-min-microvolt = <2800000>;
+		regulator-max-microvolt = <2800000>;
+		vin-supply = <&reg_3v3>;
+	};
+
+	wifi_pwrseq: wifi-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&pio 6 12 GPIO_ACTIVE_LOW>; /* PG12 */
+	};
+};
+
+&dcxo {
+	clock-frequency = <24000000>;
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&mmc0 {
+	pinctrl-0 = <&mmc0_pins>;
+	pinctrl-names = "default";
+	vmmc-supply = <&reg_3v3>;
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
+	disable-wp;
+	bus-width = <4>;
+	status = "okay";
+};
+
+&mmc1 {
+	pinctrl-0 = <&mmc1_pins>;
+	pinctrl-names = "default";
+	vmmc-supply = <&reg_3v3>;
+	non-removable;
+	bus-width = <4>;
+	mmc-pwrseq = <&wifi_pwrseq>;
+	status = "okay";
+};
+
+&ohci1 {
+	status = "okay";
+};
+
+&pio {
+	vcc-pb-supply = <&reg_3v3>;
+	vcc-pd-supply = <&reg_3v3>;
+	vcc-pe-supply = <&reg_avdd2v8>;
+	vcc-pf-supply = <&reg_3v3>;
+	vcc-pg-supply = <&reg_3v3>;
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pb_pins>;
+	status = "okay";
+};
+
+/* The USB-C socket has its CC pins pulled to GND, so is hardwired as a UFP. */
+&usb_otg {
+	dr_mode = "peripheral";
+	status = "okay";
+};
+
+&usbphy {
+	usb1_vbus-supply = <&reg_vcc5v>;
+	status = "okay";
+};
diff --git a/configs/mangopi_mq_r_defconfig b/configs/mangopi_mq_r_defconfig
new file mode 100644
index 00000000000..66ae639326f
--- /dev/null
+++ b/configs/mangopi_mq_r_defconfig
@@ -0,0 +1,15 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_DEFAULT_DEVICE_TREE="sun8i-t113s-mangopi-mq-r-t113"
+CONFIG_SPL=y
+CONFIG_MACH_SUN8I_R528=y
+CONFIG_DRAM_CLK=792
+CONFIG_DRAM_ZQ=8092667
+CONFIG_SUNXI_MINIMUM_DRAM_MB=128
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_DRAM_SUNXI_ODT_EN=0
+CONFIG_DRAM_SUNXI_TPR0=0x004a2195
+CONFIG_DRAM_SUNXI_TPR11=0x340000
+CONFIG_DRAM_SUNXI_TPR12=0x46
+CONFIG_DRAM_SUNXI_TPR13=0x34000100
+CONFIG_CONS_INDEX=4
-- 
2.35.8


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 04/22] pinctrl: sunxi: move pinctrl code
  2023-09-28 21:54 ` [PATCH v2 04/22] pinctrl: sunxi: move pinctrl code Andre Przywara
@ 2023-10-19  0:18   ` Andre Przywara
  2023-10-21  8:21   ` Samuel Holland
  1 sibling, 0 replies; 43+ messages in thread
From: Andre Przywara @ 2023-10-19  0:18 UTC (permalink / raw)
  To: Samuel Holland, linux-sunxi
  Cc: Jagan Teki, u-boot, Jernej Skrabec, Icenowy Zheng, Maxim Kiselev,
	Sam Edwards, Okhunjon Sobirjonov

On Thu, 28 Sep 2023 22:54:37 +0100
Andre Przywara <andre.przywara@arm.com> wrote:

Hi Samuel,

> Move the existing sunxi-specific low level pinctrl routines from
> arch/arm/mach-sunxi into the existing GPIO code under drivers/gpio, so
> that the common code can be shared outside of arch/arm.

I was wondering if you would find a moment to have a quick look at this
and the next few patches (04/22 till 09/22)?
I tried to address the ideas you brought up the other day on how to
best restructure the GPIO driver, to accommodate both the new D1
pinctrl device, as well as preparing to use the GPIO functionality from
outside of arch/arm.

Any feedback would be appreciated. If I get it still this week, I am
inclined to push the series into the currently open merge window still,
since I believe the other T113 patches are good to go.

Many thanks,
Andre

> 
> This also takes the opportunity to move some definitions from our
> header file into the driver C file, as they are private to the driver
> and are not needed elsewhere.
> 
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  arch/arm/include/asm/arch-sunxi/gpio.h |  20 +----
>  arch/arm/mach-sunxi/Makefile           |   1 -
>  arch/arm/mach-sunxi/pinmux.c           |  78 -------------------
>  drivers/gpio/sunxi_gpio.c              | 102 ++++++++++++++++++++++++-
>  4 files changed, 105 insertions(+), 96 deletions(-)
>  delete mode 100644 arch/arm/mach-sunxi/pinmux.c
> 
> diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
> index 6eaeece4e24..4bc9e8ffcc9 100644
> --- a/arch/arm/include/asm/arch-sunxi/gpio.h
> +++ b/arch/arm/include/asm/arch-sunxi/gpio.h
> @@ -3,6 +3,9 @@
>   * (C) Copyright 2007-2012
>   * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
>   * Tom Cubie <tangliang@allwinnertech.com>
> + *
> + * Definitions that are shared between the Allwinner pinctrl and GPIO drivers,
> + * also used by some non-DM SPL code directly.
>   */
>  
>  #ifndef _SUNXI_GPIO_H
> @@ -76,22 +79,6 @@ struct sunxi_gpio_reg {
>  #define SUN50I_H6_GPIO_POW_MOD_SEL	0x340
>  #define SUN50I_H6_GPIO_POW_MOD_VAL	0x348
>  
> -#define BANK_TO_GPIO(bank)	(((bank) < SUNXI_GPIO_L) ? \
> -	&((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[bank] : \
> -	&((struct sunxi_gpio_reg *)SUNXI_R_PIO_BASE)->gpio_bank[(bank) - SUNXI_GPIO_L])
> -
> -#define GPIO_BANK(pin)		((pin) >> 5)
> -#define GPIO_NUM(pin)		((pin) & 0x1f)
> -
> -#define GPIO_CFG_INDEX(pin)	(((pin) & 0x1f) >> 3)
> -#define GPIO_CFG_OFFSET(pin)	((((pin) & 0x1f) & 0x7) << 2)
> -
> -#define GPIO_DRV_INDEX(pin)	(((pin) & 0x1f) >> 4)
> -#define GPIO_DRV_OFFSET(pin)	((((pin) & 0x1f) & 0xf) << 1)
> -
> -#define GPIO_PULL_INDEX(pin)	(((pin) & 0x1f) >> 4)
> -#define GPIO_PULL_OFFSET(pin)	((((pin) & 0x1f) & 0xf) << 1)
> -
>  /* GPIO bank sizes */
>  #define SUNXI_GPIOS_PER_BANK	32
>  
> @@ -217,6 +204,7 @@ struct sunxi_gpio_plat {
>  	char			bank_name[3];
>  };
>  
> +/* prototypes for the non-DM GPIO/pinctrl functions, used in the SPL */
>  void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val);
>  void sunxi_gpio_set_cfgpin(u32 pin, u32 val);
>  int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset);
> diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
> index 58f807cb82d..671211e9322 100644
> --- a/arch/arm/mach-sunxi/Makefile
> +++ b/arch/arm/mach-sunxi/Makefile
> @@ -10,7 +10,6 @@ obj-y	+= board.o
>  obj-y	+= clock.o
>  obj-y	+= cpu_info.o
>  obj-y	+= dram_helpers.o
> -obj-y	+= pinmux.o
>  obj-$(CONFIG_SUN6I_PRCM)	+= prcm.o
>  obj-$(CONFIG_AXP_PMIC_BUS)	+= pmic_bus.o
>  obj-$(CONFIG_MACH_SUNIV)	+= clock_sun6i.o
> diff --git a/arch/arm/mach-sunxi/pinmux.c b/arch/arm/mach-sunxi/pinmux.c
> deleted file mode 100644
> index c95fcee9f6c..00000000000
> --- a/arch/arm/mach-sunxi/pinmux.c
> +++ /dev/null
> @@ -1,78 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0+
> -/*
> - * (C) Copyright 2007-2011
> - * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
> - * Tom Cubie <tangliang@allwinnertech.com>
> - */
> -
> -#include <common.h>
> -#include <asm/io.h>
> -#include <asm/arch/gpio.h>
> -
> -void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val)
> -{
> -	u32 index = GPIO_CFG_INDEX(bank_offset);
> -	u32 offset = GPIO_CFG_OFFSET(bank_offset);
> -
> -	clrsetbits_le32(&pio->cfg[index], 0xf << offset, val << offset);
> -}
> -
> -void sunxi_gpio_set_cfgpin(u32 pin, u32 val)
> -{
> -	u32 bank = GPIO_BANK(pin);
> -	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
> -
> -	sunxi_gpio_set_cfgbank(pio, pin, val);
> -}
> -
> -int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset)
> -{
> -	u32 index = GPIO_CFG_INDEX(bank_offset);
> -	u32 offset = GPIO_CFG_OFFSET(bank_offset);
> -	u32 cfg;
> -
> -	cfg = readl(&pio->cfg[index]);
> -	cfg >>= offset;
> -
> -	return cfg & 0xf;
> -}
> -
> -int sunxi_gpio_get_cfgpin(u32 pin)
> -{
> -	u32 bank = GPIO_BANK(pin);
> -	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
> -
> -	return sunxi_gpio_get_cfgbank(pio, pin);
> -}
> -
> -void sunxi_gpio_set_drv(u32 pin, u32 val)
> -{
> -	u32 bank = GPIO_BANK(pin);
> -	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
> -
> -	sunxi_gpio_set_drv_bank(pio, pin, val);
> -}
> -
> -void sunxi_gpio_set_drv_bank(struct sunxi_gpio *pio, u32 bank_offset, u32 val)
> -{
> -	u32 index = GPIO_DRV_INDEX(bank_offset);
> -	u32 offset = GPIO_DRV_OFFSET(bank_offset);
> -
> -	clrsetbits_le32(&pio->drv[index], 0x3 << offset, val << offset);
> -}
> -
> -void sunxi_gpio_set_pull(u32 pin, u32 val)
> -{
> -	u32 bank = GPIO_BANK(pin);
> -	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
> -
> -	sunxi_gpio_set_pull_bank(pio, pin, val);
> -}
> -
> -void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val)
> -{
> -	u32 index = GPIO_PULL_INDEX(bank_offset);
> -	u32 offset = GPIO_PULL_OFFSET(bank_offset);
> -
> -	clrsetbits_le32(&pio->pull[index], 0x3 << offset, val << offset);
> -}
> diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
> index f0b42e4fdb7..71c3168b755 100644
> --- a/drivers/gpio/sunxi_gpio.c
> +++ b/drivers/gpio/sunxi_gpio.c
> @@ -18,6 +18,104 @@
>  #include <asm/gpio.h>
>  #include <dt-bindings/gpio/gpio.h>
>  
> +/*
> + * =======================================================================
> + * Low level GPIO/pin controller access functions, to be shared by non-DM
> + * SPL code and the DM pinctrl/GPIO drivers.
> + * The functions ending in "bank" take a base pointer to a GPIO bank, and
> + * the pin offset is relative to that bank.
> + * The functions without "bank" in their name take a linear GPIO number,
> + * covering all ports, and starting at 0 for PortA.
> + * =======================================================================
> + */
> +
> +#define BANK_TO_GPIO(bank)	(((bank) < SUNXI_GPIO_L) ? \
> +	&((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[bank] : \
> +	&((struct sunxi_gpio_reg *)SUNXI_R_PIO_BASE)->gpio_bank[(bank) - SUNXI_GPIO_L])
> +
> +#define GPIO_BANK(pin)		((pin) >> 5)
> +#define GPIO_NUM(pin)		((pin) & 0x1f)
> +
> +#define GPIO_CFG_INDEX(pin)	(((pin) & 0x1f) >> 3)
> +#define GPIO_CFG_OFFSET(pin)	((((pin) & 0x1f) & 0x7) << 2)
> +
> +#define GPIO_DRV_INDEX(pin)	(((pin) & 0x1f) >> 4)
> +#define GPIO_DRV_OFFSET(pin)	((((pin) & 0x1f) & 0xf) << 1)
> +
> +#define GPIO_PULL_INDEX(pin)	(((pin) & 0x1f) >> 4)
> +#define GPIO_PULL_OFFSET(pin)	((((pin) & 0x1f) & 0xf) << 1)
> +
> +void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val)
> +{
> +	u32 index = GPIO_CFG_INDEX(bank_offset);
> +	u32 offset = GPIO_CFG_OFFSET(bank_offset);
> +
> +	clrsetbits_le32(&pio->cfg[index], 0xf << offset, val << offset);
> +}
> +
> +void sunxi_gpio_set_cfgpin(u32 pin, u32 val)
> +{
> +	u32 bank = GPIO_BANK(pin);
> +	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
> +
> +	sunxi_gpio_set_cfgbank(pio, pin, val);
> +}
> +
> +int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset)
> +{
> +	u32 index = GPIO_CFG_INDEX(bank_offset);
> +	u32 offset = GPIO_CFG_OFFSET(bank_offset);
> +	u32 cfg;
> +
> +	cfg = readl(&pio->cfg[index]);
> +	cfg >>= offset;
> +
> +	return cfg & 0xf;
> +}
> +
> +int sunxi_gpio_get_cfgpin(u32 pin)
> +{
> +	u32 bank = GPIO_BANK(pin);
> +	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
> +
> +	return sunxi_gpio_get_cfgbank(pio, pin);
> +}
> +
> +void sunxi_gpio_set_drv(u32 pin, u32 val)
> +{
> +	u32 bank = GPIO_BANK(pin);
> +	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
> +
> +	sunxi_gpio_set_drv_bank(pio, pin, val);
> +}
> +
> +void sunxi_gpio_set_drv_bank(struct sunxi_gpio *pio, u32 bank_offset, u32 val)
> +{
> +	u32 index = GPIO_DRV_INDEX(bank_offset);
> +	u32 offset = GPIO_DRV_OFFSET(bank_offset);
> +
> +	clrsetbits_le32(&pio->drv[index], 0x3 << offset, val << offset);
> +}
> +
> +void sunxi_gpio_set_pull(u32 pin, u32 val)
> +{
> +	u32 bank = GPIO_BANK(pin);
> +	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
> +
> +	sunxi_gpio_set_pull_bank(pio, pin, val);
> +}
> +
> +void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val)
> +{
> +	u32 index = GPIO_PULL_INDEX(bank_offset);
> +	u32 offset = GPIO_PULL_OFFSET(bank_offset);
> +
> +	clrsetbits_le32(&pio->pull[index], 0x3 << offset, val << offset);
> +}
> +
> +
> +/* =========== Non-DM code, used by the SPL. ============ */
> +
>  #if !CONFIG_IS_ENABLED(DM_GPIO)
>  static int sunxi_gpio_output(u32 pin, u32 val)
>  {
> @@ -106,7 +204,9 @@ int sunxi_name_to_gpio(const char *name)
>  		return -1;
>  	return group * 32 + pin;
>  }
> -#endif /* DM_GPIO */
> +#endif /* !DM_GPIO */
> +
> +/* =========== DM code, used by U-Boot proper. ============ */
>  
>  #if CONFIG_IS_ENABLED(DM_GPIO)
>  /* TODO(sjg@chromium.org): Remove this function and use device tree */


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 01/22] sunxi: remove CONFIG_SATAPWR
  2023-09-28 21:54 ` [PATCH v2 01/22] sunxi: remove CONFIG_SATAPWR Andre Przywara
@ 2023-10-19 23:51   ` Samuel Holland
  2023-10-21 23:27     ` Andre Przywara
  0 siblings, 1 reply; 43+ messages in thread
From: Samuel Holland @ 2023-10-19 23:51 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Jernej Skrabec, Icenowy Zheng, Maxim Kiselev, Sam Edwards,
	Okhunjon Sobirjonov, linux-sunxi, andre.przywara, Jagan Teki,
	u-boot

On 9/28/23 16:54, Andre Przywara wrote:
> The CONFIG_SATAPWR Kconfig symbol was used to point to a GPIO that
> enables the power for a SATA harddisk.
> In the DT this is described with the target-supply property in the AHCI
> DT node, pointing to a (GPIO controlled) regulator. Since we need SATA
> only in U-Boot proper, and use a DM driver for AHCI there, we should use
> the DT instead of hardcoding this.
> 
> Add code to the sunxi AHCI driver to check the DT for that regulator and
> enable it, at probe time. Then drop the current code from board.c, which
> was doing that job before.
> This allows us to remove the SATAPWR Kconfig definition and the
> respective values from the defconfigs.
> We also select the generic fixed regulator driver, which handles those
> GPIO controlled regulators.
> 
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> Reviewed-by: Sam Edwards <CFSworks@gmail.com>
> ---
>  arch/arm/Kconfig                             |  2 ++
>  arch/arm/mach-sunxi/Kconfig                  |  8 --------
>  board/sunxi/board.c                          | 16 +---------------
>  configs/A10-OLinuXino-Lime_defconfig         |  1 -
>  configs/A20-OLinuXino-Lime2-eMMC_defconfig   |  1 -
>  configs/A20-OLinuXino-Lime2_defconfig        |  1 -
>  configs/A20-OLinuXino-Lime_defconfig         |  1 -
>  configs/A20-OLinuXino_MICRO-eMMC_defconfig   |  1 -
>  configs/A20-OLinuXino_MICRO_defconfig        |  1 -
>  configs/A20-Olimex-SOM-EVB_defconfig         |  1 -
>  configs/A20-Olimex-SOM204-EVB-eMMC_defconfig |  1 -
>  configs/A20-Olimex-SOM204-EVB_defconfig      |  1 -
>  configs/Cubieboard2_defconfig                |  1 -
>  configs/Cubieboard_defconfig                 |  1 -
>  configs/Cubietruck_defconfig                 |  1 -
>  configs/Itead_Ibox_A20_defconfig             |  1 -
>  configs/Lamobo_R1_defconfig                  |  1 -
>  configs/Linksprite_pcDuino3_Nano_defconfig   |  1 -
>  configs/Linksprite_pcDuino3_defconfig        |  1 -
>  configs/Sinovoip_BPI_M3_defconfig            |  1 -
>  configs/orangepi_plus_defconfig              |  2 +-
>  drivers/ata/ahci_sunxi.c                     |  9 +++++++++
>  22 files changed, 13 insertions(+), 41 deletions(-)
> 
> [...]
> diff --git a/configs/orangepi_plus_defconfig b/configs/orangepi_plus_defconfig
> index 76de72aa228..ed585881d49 100644
> --- a/configs/orangepi_plus_defconfig
> +++ b/configs/orangepi_plus_defconfig
> @@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=672
>  CONFIG_MACPWR="PD6"
>  CONFIG_MMC_SUNXI_SLOT_EXTRA=2
>  CONFIG_USB1_VBUS_PIN="PG13"
> -CONFIG_SATAPWR="PG11"
>  # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
>  CONFIG_SPL_I2C=y
>  CONFIG_SPL_SYS_I2C_LEGACY=y
> @@ -16,3 +15,4 @@ CONFIG_SUN8I_EMAC=y
>  CONFIG_SY8106A_POWER=y
>  CONFIG_USB_EHCI_HCD=y
>  CONFIG_USB_OHCI_HCD=y
> +CONFIG_USB3_VBUS_PIN="PG11"

This change is unrelated to the purpose of this commit.

Regards,
Samuel



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 12/22] clk: sunxi: Add support for the D1 CCU
  2023-09-28 21:54 ` [PATCH v2 12/22] clk: sunxi: Add support for the D1 CCU Andre Przywara
@ 2023-10-19 23:53   ` Samuel Holland
  0 siblings, 0 replies; 43+ messages in thread
From: Samuel Holland @ 2023-10-19 23:53 UTC (permalink / raw)
  To: Andre Przywara, Jagan Teki, u-boot
  Cc: Jernej Skrabec, Icenowy Zheng, Maxim Kiselev, Sam Edwards,
	Okhunjon Sobirjonov, linux-sunxi, andre.przywara

On 9/28/23 16:54, Andre Przywara wrote:
> From: Samuel Holland <samuel@sholland.org>
> 
> Since the D1 CCU binding is defined, we can add support for its
> gates/resets, following the pattern of the existing drivers.
> 
> Signed-off-by: Samuel Holland <samuel@sholland.org>
> Reviewed-by: Andre Przywara <andre.przywara@arm.com>
> Acked-by: Sean Anderson <seanga2@gmail.com>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  drivers/clk/sunxi/Kconfig                 |   6 +
>  drivers/clk/sunxi/Makefile                |   1 +
>  drivers/clk/sunxi/clk_d1.c                |  84 ++++++++++++
>  drivers/clk/sunxi/clk_sunxi.c             |   5 +
>  include/dt-bindings/clock/sun20i-d1-ccu.h | 158 ++++++++++++++++++++++
>  include/dt-bindings/reset/sun20i-d1-ccu.h |  79 +++++++++++
>  6 files changed, 333 insertions(+)
>  create mode 100644 drivers/clk/sunxi/clk_d1.c
>  create mode 100644 include/dt-bindings/clock/sun20i-d1-ccu.h
>  create mode 100644 include/dt-bindings/reset/sun20i-d1-ccu.h
> 
> [...]
> diff --git a/drivers/clk/sunxi/clk_sunxi.c b/drivers/clk/sunxi/clk_sunxi.c
> index ec02a2d0370..a0011a35d91 100644
> --- a/drivers/clk/sunxi/clk_sunxi.c
> +++ b/drivers/clk/sunxi/clk_sunxi.c
> @@ -118,6 +118,7 @@ extern const struct ccu_desc a64_ccu_desc;
>  extern const struct ccu_desc a80_ccu_desc;
>  extern const struct ccu_desc a80_mmc_clk_desc;
>  extern const struct ccu_desc a83t_ccu_desc;
> +extern const struct ccu_desc d1_ccu_desc;
>  extern const struct ccu_desc f1c100s_ccu_desc;
>  extern const struct ccu_desc h3_ccu_desc;
>  extern const struct ccu_desc h6_ccu_desc;
> @@ -214,6 +215,10 @@ static const struct udevice_id sunxi_clk_ids[] = {
>  #ifdef CONFIG_CLK_SUNIV_F1C100S
>  	{ .compatible = "allwinner,suniv-f1c100s-ccu",
>  	  .data = (ulong)&f1c100s_ccu_desc },
> +#endif
> +#ifdef CONFIG_CLK_SUN20I_D1
> +	{ .compatible = "allwinner,sun20i-d1-ccu",
> +	  .data = (ulong)&d1_ccu_desc },

Please keep these entries sorted numerically. Otherwise, your changes
look good to me.

Regards,
Samuel


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 02/22] net: sunxi_emac: chase DT nodes to find PHY regulator
  2023-09-28 21:54 ` [PATCH v2 02/22] net: sunxi_emac: chase DT nodes to find PHY regulator Andre Przywara
@ 2023-10-20  0:01   ` Samuel Holland
  2023-10-21 23:33     ` Andre Przywara
  0 siblings, 1 reply; 43+ messages in thread
From: Samuel Holland @ 2023-10-20  0:01 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Jernej Skrabec, Icenowy Zheng, Maxim Kiselev, Sam Edwards,
	Okhunjon Sobirjonov, linux-sunxi, andre.przywara, Jagan Teki,
	u-boot

Hi Andre,

On 9/28/23 16:54, Andre Przywara wrote:
> At the moment the sun4i EMAC driver relies on hardcoded CONFIG_MACPWR
> Kconfig symbols to enable potential PHY regulators. As we want to get rid
> of those, we need to find the regulator by chasing up the DT.
> 
> The sun4i-emac binding puts the PHY regulator into the MDIO node, which
> is the parent of the PHY device. U-Boot does not have (and does not
> need) an MDIO driver, so we need to chase down the regulator through the
> EMAC node: we follow the "phy-handle" property to find the PHY node,
> then go up to its parent, where we find the "phy-supply" link to the
> regulator. Let U-Boot find the associated regulator device, and put that
> into the private device struct, so we can find and enable the regulator
> at probe time, later.

This does somewhat duplicate the logic from dm_eth_connect_phy_handle(),
and putting the regulator in a UCLASS_MDIO device's probe function would
work out cleanly (albeit with the usual DM overhead). But that can be a
later refactoring.

> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> Reviewed-by: Sam Edwards <CFSworks@gmail.com>
> ---
>  drivers/net/sunxi_emac.c | 39 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 39 insertions(+)
> 
> diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c
> index 4c90d4b4981..f1f0e5bbbb2 100644
> --- a/drivers/net/sunxi_emac.c
> +++ b/drivers/net/sunxi_emac.c
> @@ -17,6 +17,7 @@
>  #include <net.h>
>  #include <asm/io.h>
>  #include <asm/arch/clock.h>
> +#include <power/regulator.h>
>  
>  /* EMAC register  */
>  struct emac_regs {
> @@ -165,6 +166,7 @@ struct emac_eth_dev {
>  	struct phy_device *phydev;
>  	int link_printed;
>  	uchar rx_buf[EMAC_RX_BUFSIZE];
> +	struct udevice *phy_reg;
>  };
>  
>  struct emac_rxhdr {
> @@ -572,6 +574,9 @@ static int sunxi_emac_eth_probe(struct udevice *dev)
>  	if (ret)
>  		return ret;
>  
> +	if (priv->phy_reg)
> +		regulator_set_enable(priv->phy_reg, true);
> +
>  	return sunxi_emac_init_phy(priv, dev);
>  }
>  
> @@ -585,9 +590,43 @@ static const struct eth_ops sunxi_emac_eth_ops = {
>  static int sunxi_emac_eth_of_to_plat(struct udevice *dev)
>  {
>  	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct emac_eth_dev *priv = dev_get_priv(dev);
> +	struct ofnode_phandle_args args;
> +	ofnode mdio_node;
> +	int ret;
>  
>  	pdata->iobase = dev_read_addr(dev);
>  
> +	/* The PHY regulator is in the MDIO node, not the EMAC or PHY node. */
> +	ret = dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0, &args);

You can use dev_get_phy_node() here. Either way:

Reviewed-by: Samuel Holland <samuel@sholland.org>

> +	if (ret) {
> +		dev_err(dev, "failed to get PHY node\n");
> +		return ret;
> +	}
> +
> +	/*
> +	 * U-Boot does not have (and does not need) a device driver for the
> +	 * MDIO device, so just "pass through" that DT node to get to the
> +	 * regulator phandle.
> +	 * The PHY regulator is optional, though: ignore if we cannot find
> +	 * a phy-supply property.
> +	 */
> +	mdio_node = ofnode_get_parent(args.node);
> +	ret= ofnode_parse_phandle_with_args(mdio_node, "phy-supply", NULL, 0, 0,
> +					    &args);
> +	if (ret && ret != -ENOENT) {
> +		dev_err(dev, "failed to get PHY supply node\n");
> +		return ret;
> +	}
> +	if (!ret) {
> +		ret = uclass_get_device_by_ofnode(UCLASS_REGULATOR, args.node,
> +						  &priv->phy_reg);
> +		if (ret) {
> +			dev_err(dev, "failed to get PHY regulator node\n");
> +			return ret;
> +		}
> +	}
> +
>  	return 0;
>  }
>  


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 11/22] pinctrl: sunxi: add Allwinner D1 pinctrl description
  2023-09-28 21:54 ` [PATCH v2 11/22] pinctrl: sunxi: add Allwinner D1 pinctrl description Andre Przywara
@ 2023-10-21  4:34   ` Samuel Holland
  0 siblings, 0 replies; 43+ messages in thread
From: Samuel Holland @ 2023-10-21  4:34 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Jernej Skrabec, Icenowy Zheng, Maxim Kiselev, Sam Edwards,
	Okhunjon Sobirjonov, linux-sunxi, andre.przywara, Jagan Teki,
	u-boot

Hi Andre,

On 9/28/23 16:54, Andre Przywara wrote:
> Apart from using the new pinctrl MMIO register layout, the Allwinner D1
> and related SoCs still need to usual set of mux values hardcoded in
> U-Boot's pinctrl driver.
> Add the values we need so far to this list, so that DM based drivers
> will just work without further ado.
> 
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  drivers/pinctrl/sunxi/Kconfig         |  4 ++++
>  drivers/pinctrl/sunxi/pinctrl-sunxi.c | 28 +++++++++++++++++++++++++++
>  2 files changed, 32 insertions(+)
> 
> diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
> index 77da90836b6..c8f937d91e9 100644
> --- a/drivers/pinctrl/sunxi/Kconfig
> +++ b/drivers/pinctrl/sunxi/Kconfig
> @@ -124,4 +124,8 @@ config PINCTRL_SUN50I_H616_R
>  	default MACH_SUN50I_H616
>  	select PINCTRL_SUNXI
>  
> +config PINCTRL_SUN20I_D1
> +	bool "Support for the Allwinner D1/R528 PIO"
> +	select PINCTRL_SUNXI
> +
>  endif
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> index fc80fe50b14..66876d9954a 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> @@ -748,6 +748,28 @@ static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h616_r_pinctrl_desc
>  	.num_banks	= 1,
>  };
>  
> +static const struct sunxi_pinctrl_function sun20i_d1_pinctrl_functions[] = {

Please keep these sections (and the OF match data) sorted numerically.

> +	{ "emac",	8 },	/* PE0-PE15 */
> +	{ "gpio_in",	0 },
> +	{ "gpio_out",	1 },

My local patch had a few more entries. Feel free to add them:

+       { "i2c0",       4 },    /* PB10-PB11 */

> +	{ "mmc0",	2 },	/* PF0-PF5 */

+       { "mmc1",       2 },    /* PG0-PG5 */

> +	{ "mmc2",	3 },	/* PC1-PC7 */

Should be PC2-PC7. Everything else looks correct.

> +	{ "spi0",	2 },	/* PC2-PC7 */
> +#if IS_ENABLED(CONFIG_UART0_PORT_F)
> +	{ "uart0",	3 },	/* PF2,PF4 */
> +#else
> +	{ "uart0",	6 },	/* PB0-PB1, PB8-PB9, PE2-PE3 */
> +#endif

+       { "uart1",      2 },    /* PG6-PG7 */
+       { "uart2",      7 },    /* PB0-PB1 */

Regards,
Samuel

> +	{ "uart3",	7 },	/* PB6-PB7 */
> +};
> +
> +static const struct sunxi_pinctrl_desc __maybe_unused sun20i_d1_pinctrl_desc = {
> +	.functions	= sun20i_d1_pinctrl_functions,
> +	.num_functions	= ARRAY_SIZE(sun20i_d1_pinctrl_functions),
> +	.first_bank	= SUNXI_GPIO_A,
> +	.num_banks	= 7,
> +};
> +
>  static const struct udevice_id sunxi_pinctrl_ids[] = {
>  #ifdef CONFIG_PINCTRL_SUNIV_F1C100S
>  	{
> @@ -904,6 +926,12 @@ static const struct udevice_id sunxi_pinctrl_ids[] = {
>  		.compatible = "allwinner,sun50i-h616-r-pinctrl",
>  		.data = (ulong)&sun50i_h616_r_pinctrl_desc,
>  	},
> +#endif
> +#ifdef CONFIG_PINCTRL_SUN20I_D1
> +	{
> +		.compatible = "allwinner,sun20i-d1-pinctrl",
> +		.data = (ulong)&sun20i_d1_pinctrl_desc,
> +	},
>  #endif
>  	{}
>  };


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 03/22] sunxi: remove CONFIG_MACPWR
  2023-09-28 21:54 ` [PATCH v2 03/22] sunxi: remove CONFIG_MACPWR Andre Przywara
@ 2023-10-21  4:35   ` Samuel Holland
  0 siblings, 0 replies; 43+ messages in thread
From: Samuel Holland @ 2023-10-21  4:35 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Jernej Skrabec, Icenowy Zheng, Maxim Kiselev, Sam Edwards,
	Okhunjon Sobirjonov, linux-sunxi, andre.przywara, Jagan Teki,
	u-boot

Hi Andre,

On 9/28/23 16:54, Andre Przywara wrote:
> The CONFIG_MACPWR Kconfig symbol is used to point to a GPIO that enables
> the power for the Ethernet "MAC" (mostly PHY, really).
> In the DT this is described with the phy-supply property in the MAC DT
> node, pointing to a (GPIO controlled) regulator. Since we need Ethernet
> only in U-Boot proper, and use a DM driver there, we should use the DT
> instead of hardcoding this.
> 
> Add code to the sun8i_emac and sunxi_emac drivers to check the DT for
> that regulator and enable it, at probe time. Then drop the current code
> from board.c, which was doing that job before.
> This allows us to remove the MACPWR Kconfig definition and the respective
> values from the defconfigs.
> 
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> Reviewed-by: Sam Edwards <CFSworks@gmail.com>
> ---
>  arch/arm/mach-sunxi/Kconfig           |  7 -------
>  board/sunxi/board.c                   | 12 +-----------
>  configs/Bananapi_M2_Ultra_defconfig   |  1 -
>  configs/Bananapi_defconfig            |  1 -
>  configs/Bananapro_defconfig           |  1 -
>  configs/Lamobo_R1_defconfig           |  1 -
>  configs/Mele_A1000_defconfig          |  1 -
>  configs/Orangepi_defconfig            |  1 -
>  configs/Orangepi_mini_defconfig       |  1 -
>  configs/bananapi_m1_plus_defconfig    |  1 -
>  configs/bananapi_m2_plus_h3_defconfig |  1 -
>  configs/bananapi_m2_plus_h5_defconfig |  1 -
>  configs/i12-tvbox_defconfig           |  1 -
>  configs/jesurun_q5_defconfig          |  1 -
>  configs/mixtile_loftq_defconfig       |  1 -
>  configs/nanopi_m1_plus_defconfig      |  1 -
>  configs/nanopi_neo_plus2_defconfig    |  1 -
>  configs/nanopi_r1s_h5_defconfig       |  1 -
>  configs/orangepi_pc2_defconfig        |  1 -
>  configs/orangepi_plus2e_defconfig     |  1 -
>  configs/orangepi_plus_defconfig       |  1 -
>  configs/orangepi_win_defconfig        |  1 -
>  configs/pine_h64_defconfig            |  1 -
>  configs/zeropi_defconfig              |  1 -
>  drivers/net/sun8i_emac.c              |  9 +++++++--
>  25 files changed, 8 insertions(+), 42 deletions(-)
> 
> [...]
> diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
> index 04c3274fbe1..7b60a60ad52 100644
> --- a/drivers/net/sun8i_emac.c
> +++ b/drivers/net/sun8i_emac.c
> @@ -29,6 +29,7 @@
>  #include <net.h>
>  #include <reset.h>
>  #include <wait_bit.h>
> +#include <power/regulator.h>
>  
>  #define MDIO_CMD_MII_BUSY		BIT(0)
>  #define MDIO_CMD_MII_WRITE		BIT(1)
> @@ -167,9 +168,8 @@ struct emac_eth_dev {
>  	struct clk ephy_clk;
>  	struct reset_ctl tx_rst;
>  	struct reset_ctl ephy_rst;
> -#if CONFIG_IS_ENABLED(DM_GPIO)
>  	struct gpio_desc reset_gpio;
> -#endif

This is sort of an unrelated cleanup, and there are several more
instances of this in the same file. Maybe split this to a separate patch?

Regards,
Samuel

> +	struct udevice *phy_reg;
>  };
>  
>  
> @@ -720,6 +720,9 @@ static int sun8i_emac_eth_probe(struct udevice *dev)
>  
>  	sun8i_emac_set_syscon(sun8i_pdata, priv);
>  
> +	if (priv->phy_reg)
> +		regulator_set_enable(priv->phy_reg, true);
> +
>  	sun8i_mdio_init(dev->name, dev);
>  	priv->bus = miiphy_get_dev_by_name(dev->name);
>  
> @@ -829,6 +832,8 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
>  
>  	priv->sysctl_reg = (void *)syscon_base + priv->variant->syscon_offset;
>  
> +	device_get_supply_regulator(dev, "phy-supply", &priv->phy_reg);
> +
>  	pdata->phy_interface = -1;
>  	priv->phyaddr = -1;
>  	priv->use_internal_phy = false;


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 04/22] pinctrl: sunxi: move pinctrl code
  2023-09-28 21:54 ` [PATCH v2 04/22] pinctrl: sunxi: move pinctrl code Andre Przywara
  2023-10-19  0:18   ` Andre Przywara
@ 2023-10-21  8:21   ` Samuel Holland
  1 sibling, 0 replies; 43+ messages in thread
From: Samuel Holland @ 2023-10-21  8:21 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Jernej Skrabec, Icenowy Zheng, Maxim Kiselev, Sam Edwards,
	Okhunjon Sobirjonov, linux-sunxi, andre.przywara, Jagan Teki,
	u-boot

Hi Andre,

On 9/28/23 16:54, Andre Przywara wrote:
> Move the existing sunxi-specific low level pinctrl routines from
> arch/arm/mach-sunxi into the existing GPIO code under drivers/gpio, so
> that the common code can be shared outside of arch/arm.
> 
> This also takes the opportunity to move some definitions from our
> header file into the driver C file, as they are private to the driver
> and are not needed elsewhere.
> 
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  arch/arm/include/asm/arch-sunxi/gpio.h |  20 +----
>  arch/arm/mach-sunxi/Makefile           |   1 -
>  arch/arm/mach-sunxi/pinmux.c           |  78 -------------------
>  drivers/gpio/sunxi_gpio.c              | 102 ++++++++++++++++++++++++-
>  4 files changed, 105 insertions(+), 96 deletions(-)
>  delete mode 100644 arch/arm/mach-sunxi/pinmux.c

Many thanks! This works perfectly for D1.

Reviewed-by: Samuel Holland <samuel@sholland.org>
Tested-by: Samuel Holland <samuel@sholland.org>


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 05/22] pinctrl: sunxi: add GPIO in/out wrappers
  2023-09-28 21:54 ` [PATCH v2 05/22] pinctrl: sunxi: add GPIO in/out wrappers Andre Przywara
@ 2023-10-21  8:30   ` Samuel Holland
  2023-10-21 23:46     ` Andre Przywara
  0 siblings, 1 reply; 43+ messages in thread
From: Samuel Holland @ 2023-10-21  8:30 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Jernej Skrabec, Icenowy Zheng, Maxim Kiselev, Sam Edwards,
	Okhunjon Sobirjonov, linux-sunxi, andre.przywara, Jagan Teki,
	u-boot

Hi Andre,

On 9/28/23 16:54, Andre Przywara wrote:
> So far we were open-coding the pincontroller's GPIO output/input access
> in each function using that.
> 
> Provide functions that wrap that nicely, and follow the existing pattern
> (set/get_{bank,}), so users don't need to know about the internals, and
> we can abstract the new D1 pinctrl more easily.
> 
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  drivers/gpio/sunxi_gpio.c | 55 ++++++++++++++++++---------------------
>  1 file changed, 25 insertions(+), 30 deletions(-)
> 
> diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
> index 71c3168b755..a4b336943b6 100644
> --- a/drivers/gpio/sunxi_gpio.c
> +++ b/drivers/gpio/sunxi_gpio.c
> @@ -81,6 +81,19 @@ int sunxi_gpio_get_cfgpin(u32 pin)
>  	return sunxi_gpio_get_cfgbank(pio, pin);
>  }
>  
> +static void sunxi_gpio_set_output_bank(struct sunxi_gpio *pio,
> +				       int pin, bool set)
> +{
> +	u32 mask = 1U << pin;
> +
> +	clrsetbits_le32(&pio->dat, set ? 0 : mask, set ? mask : 0);
> +}
> +
> +static int sunxi_gpio_get_output_bank(struct sunxi_gpio *pio, int pin)

"get_output" is a bit misleading when this pin is an input, so maybe
"set_value" and "get_value" would be more accurate.

> +{
> +	return !!(readl(&pio->dat) & (1U << pin));
> +}
> +
>  void sunxi_gpio_set_drv(u32 pin, u32 val)
>  {
>  	u32 bank = GPIO_BANK(pin);
> @@ -117,35 +130,20 @@ void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val)
>  /* =========== Non-DM code, used by the SPL. ============ */
>  
>  #if !CONFIG_IS_ENABLED(DM_GPIO)
> -static int sunxi_gpio_output(u32 pin, u32 val)
> +static void sunxi_gpio_set_output(u32 pin, bool set)
>  {
> -	u32 dat;
>  	u32 bank = GPIO_BANK(pin);
> -	u32 num = GPIO_NUM(pin);
>  	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
>  
> -	dat = readl(&pio->dat);
> -	if (val)
> -		dat |= 0x1 << num;
> -	else
> -		dat &= ~(0x1 << num);
> -
> -	writel(dat, &pio->dat);
> -
> -	return 0;
> +	sunxi_gpio_set_output_bank(pio, GPIO_NUM(pin), set);
>  }
>  
> -static int sunxi_gpio_input(u32 pin)
> +static int sunxi_gpio_get_output(u32 pin)
>  {
> -	u32 dat;
>  	u32 bank = GPIO_BANK(pin);
> -	u32 num = GPIO_NUM(pin);
>  	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
>  
> -	dat = readl(&pio->dat);
> -	dat >>= num;
> -
> -	return dat & 0x1;
> +	return sunxi_gpio_get_output_bank(pio, GPIO_NUM(pin));
>  }
>  
>  int gpio_request(unsigned gpio, const char *label)
> @@ -168,18 +166,21 @@ int gpio_direction_input(unsigned gpio)
>  int gpio_direction_output(unsigned gpio, int value)
>  {
>  	sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_OUTPUT);
> +	sunxi_gpio_set_output(gpio, value);
>  
> -	return sunxi_gpio_output(gpio, value);
> +	return 0;
>  }
>  
>  int gpio_get_value(unsigned gpio)
>  {
> -	return sunxi_gpio_input(gpio);
> +	return sunxi_gpio_get_output(gpio);
>  }
>  
>  int gpio_set_value(unsigned gpio, int value)
>  {
> -	return sunxi_gpio_output(gpio, value);
> +	sunxi_gpio_set_output(gpio, value);
> +
> +	return 0;
>  }
>  
>  int sunxi_name_to_gpio(const char *name)
> @@ -231,13 +232,8 @@ int sunxi_name_to_gpio(const char *name)
>  static int sunxi_gpio_get_value(struct udevice *dev, unsigned offset)
>  {
>  	struct sunxi_gpio_plat *plat = dev_get_plat(dev);
> -	u32 num = GPIO_NUM(offset);
> -	unsigned dat;
> -
> -	dat = readl(&plat->regs->dat);
> -	dat >>= num;
>  
> -	return dat & 0x1;
> +	return sunxi_gpio_get_output_bank(plat->regs, offset) & 0x1;

You don't need the "& 0x1" anymore. Otherwise:

Reviewed-by: Samuel Holland <samuel@sholland.org>

>  }
>  
>  static int sunxi_gpio_get_function(struct udevice *dev, unsigned offset)
> @@ -275,9 +271,8 @@ static int sunxi_gpio_set_flags(struct udevice *dev, unsigned int offset,
>  
>  	if (flags & GPIOD_IS_OUT) {
>  		u32 value = !!(flags & GPIOD_IS_OUT_ACTIVE);
> -		u32 num = GPIO_NUM(offset);
>  
> -		clrsetbits_le32(&plat->regs->dat, 1 << num, value << num);
> +		sunxi_gpio_set_output_bank(plat->regs, offset, value);
>  		sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_OUTPUT);
>  	} else if (flags & GPIOD_IS_IN) {
>  		u32 pull = 0;


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 06/22] pinctrl: sunxi: remove struct sunxi_gpio
  2023-09-28 21:54 ` [PATCH v2 06/22] pinctrl: sunxi: remove struct sunxi_gpio Andre Przywara
@ 2023-10-21  8:37   ` Samuel Holland
  0 siblings, 0 replies; 43+ messages in thread
From: Samuel Holland @ 2023-10-21  8:37 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Jernej Skrabec, Icenowy Zheng, Maxim Kiselev, Sam Edwards,
	Okhunjon Sobirjonov, linux-sunxi, andre.przywara, Jagan Teki,
	u-boot

Hi Andre,

On 9/28/23 16:54, Andre Przywara wrote:
> So far every Allwinner SoC used the same basic pincontroller/GPIO
> register frame, and just differed by the number of implemented banks and
> pins, plus some special functionality from time to time. However the D1
> and successors use a slightly different pinctrl register layout.
> Use that opportunity to drop "struct sunxi_gpio", that described that
> MMIO frame in a C struct. That approach is somewhat frowned upon in the
> Linux world and rarely used there, though still popular with U-Boot.
> 
> Switching from a C struct to a "base address plus offset" approach allows
> to switch between the two models more dynamically, without reverting to
> preprocessor macros and #ifdef's.
> 
> Model the pinctrl MMIO register frame in the usual "base address +
> offset" way, and replace a hard-to-parse CPP macro with a more readable
> static function.
> All the users get converted over. There are no functional changes at
> this point, it just prepares the stages for the D1 and friends.
> 
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  arch/arm/include/asm/arch-sunxi/gpio.h | 40 ++----------
>  drivers/gpio/sunxi_gpio.c              | 88 ++++++++++++++++----------
>  drivers/pinctrl/sunxi/pinctrl-sunxi.c  | 14 ++--
>  3 files changed, 66 insertions(+), 76 deletions(-)
> 
> diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
> index 4bc9e8ffcc9..e0fb5b5da63 100644
> --- a/arch/arm/include/asm/arch-sunxi/gpio.h
> +++ b/arch/arm/include/asm/arch-sunxi/gpio.h
> @@ -31,13 +31,6 @@
>  #define SUNXI_GPIO_H	7
>  #define SUNXI_GPIO_I	8
>  
> -/*
> - * This defines the number of GPIO banks for the _main_ GPIO controller.
> - * You should fix up the padding in struct sunxi_gpio_reg below if you
> - * change this.
> - */
> -#define SUNXI_GPIO_BANKS 9
> -
>  /*
>   * sun6i/sun8i and later SoCs have an additional GPIO controller (R_PIO)
>   * at a different register offset.
> @@ -55,32 +48,11 @@
>  #define SUNXI_GPIO_M	12
>  #define SUNXI_GPIO_N	13
>  
> -struct sunxi_gpio {
> -	u32 cfg[4];
> -	u32 dat;
> -	u32 drv[2];
> -	u32 pull[2];
> -};
> -
> -/* gpio interrupt control */
> -struct sunxi_gpio_int {
> -	u32 cfg[3];
> -	u32 ctl;
> -	u32 sta;
> -	u32 deb;		/* interrupt debounce */
> -};
> -
> -struct sunxi_gpio_reg {
> -	struct sunxi_gpio gpio_bank[SUNXI_GPIO_BANKS];
> -	u8 res[0xbc];
> -	struct sunxi_gpio_int gpio_int;
> -};
> -
>  #define SUN50I_H6_GPIO_POW_MOD_SEL	0x340
>  #define SUN50I_H6_GPIO_POW_MOD_VAL	0x348
>  
> -/* GPIO bank sizes */
>  #define SUNXI_GPIOS_PER_BANK	32
> +#define SUNXI_PINCTRL_BANK_SIZE 0x24
>  
>  #define SUNXI_GPIO_NEXT(__gpio) \
>  	((__gpio##_START) + SUNXI_GPIOS_PER_BANK)
> @@ -200,19 +172,19 @@ enum sunxi_gpio_number {
>  #define SUNXI_GPIO_AXP0_GPIO_COUNT	6
>  
>  struct sunxi_gpio_plat {
> -	struct sunxi_gpio	*regs;
> +	void			*regs;
>  	char			bank_name[3];
>  };
>  
>  /* prototypes for the non-DM GPIO/pinctrl functions, used in the SPL */
> -void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val);
> +void sunxi_gpio_set_cfgbank(void *bank_base, int pin_offset, u32 val);
>  void sunxi_gpio_set_cfgpin(u32 pin, u32 val);
> -int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset);
> +int sunxi_gpio_get_cfgbank(void *bank_base, int pin_offset);
>  int sunxi_gpio_get_cfgpin(u32 pin);
>  void sunxi_gpio_set_drv(u32 pin, u32 val);
> -void sunxi_gpio_set_drv_bank(struct sunxi_gpio *pio, u32 bank_offset, u32 val);
> +void sunxi_gpio_set_drv_bank(void *bank_base, u32 pin_offset, u32 val);
>  void sunxi_gpio_set_pull(u32 pin, u32 val);
> -void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val);
> +void sunxi_gpio_set_pull_bank(void *bank_base, int pin_offset, u32 val);
>  int sunxi_name_to_gpio(const char *name);
>  
>  #if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO
> diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
> index a4b336943b6..fe3f6ed0938 100644
> --- a/drivers/gpio/sunxi_gpio.c
> +++ b/drivers/gpio/sunxi_gpio.c
> @@ -29,45 +29,61 @@
>   * =======================================================================
>   */
>  
> -#define BANK_TO_GPIO(bank)	(((bank) < SUNXI_GPIO_L) ? \
> -	&((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[bank] : \
> -	&((struct sunxi_gpio_reg *)SUNXI_R_PIO_BASE)->gpio_bank[(bank) - SUNXI_GPIO_L])
> -
>  #define GPIO_BANK(pin)		((pin) >> 5)
>  #define GPIO_NUM(pin)		((pin) & 0x1f)
>  
> +#define GPIO_CFG_REG_OFFSET	0x00
>  #define GPIO_CFG_INDEX(pin)	(((pin) & 0x1f) >> 3)
>  #define GPIO_CFG_OFFSET(pin)	((((pin) & 0x1f) & 0x7) << 2)
>  
> +#define GPIO_DAT_REG_OFFSET	0x10
> +
> +#define GPIO_DRV_REG_OFFSET	0x14
>  #define GPIO_DRV_INDEX(pin)	(((pin) & 0x1f) >> 4)
>  #define GPIO_DRV_OFFSET(pin)	((((pin) & 0x1f) & 0xf) << 1)
>  
> +#define GPIO_PULL_REG_OFFSET	0x1c
>  #define GPIO_PULL_INDEX(pin)	(((pin) & 0x1f) >> 4)
>  #define GPIO_PULL_OFFSET(pin)	((((pin) & 0x1f) & 0xf) << 1)

Now that we've ensured the *_bank functions only get called with pin
numbers in the range 0-31, we don't need the masking anymore. But this
can be a later cleanup.

Reviewed-by: Samuel Holland <samuel@sholland.org>
Tested-by: Samuel Holland <samuel@sholland.org>

>  
> -void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val)
> +static void* BANK_TO_GPIO(int bank)
> +{
> +	void *pio_base;
> +
> +	if (bank < SUNXI_GPIO_L) {
> +		pio_base = (void *)(uintptr_t)SUNXI_PIO_BASE;
> +	} else {
> +		pio_base = (void *)(uintptr_t)SUNXI_R_PIO_BASE;
> +		bank -= SUNXI_GPIO_L;
> +	}
> +
> +	return pio_base + bank * SUNXI_PINCTRL_BANK_SIZE;
> +}
> +
> +void sunxi_gpio_set_cfgbank(void *bank_base, int pin_offset, u32 val)
>  {
> -	u32 index = GPIO_CFG_INDEX(bank_offset);
> -	u32 offset = GPIO_CFG_OFFSET(bank_offset);
> +	u32 index = GPIO_CFG_INDEX(pin_offset);
> +	u32 offset = GPIO_CFG_OFFSET(pin_offset);
>  
> -	clrsetbits_le32(&pio->cfg[index], 0xf << offset, val << offset);
> +	clrsetbits_le32(bank_base + GPIO_CFG_REG_OFFSET + index * 4,
> +			0xfU << offset, val << offset);
>  }
>  
>  void sunxi_gpio_set_cfgpin(u32 pin, u32 val)
>  {
>  	u32 bank = GPIO_BANK(pin);
> -	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
> +	void *pio = BANK_TO_GPIO(bank);
>  
> -	sunxi_gpio_set_cfgbank(pio, pin, val);
> +	sunxi_gpio_set_cfgbank(pio, GPIO_NUM(pin), val);
>  }
>  
> -int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset)
> +int sunxi_gpio_get_cfgbank(void *bank_base, int pin_offset)
>  {
> -	u32 index = GPIO_CFG_INDEX(bank_offset);
> -	u32 offset = GPIO_CFG_OFFSET(bank_offset);
> +	u32 index = GPIO_CFG_INDEX(pin_offset);
> +	u32 offset = GPIO_CFG_OFFSET(pin_offset);
>  	u32 cfg;
>  
> -	cfg = readl(&pio->cfg[index]);
> +	cfg = readl(bank_base + GPIO_CFG_REG_OFFSET + index * 4);
>  	cfg >>= offset;
>  
>  	return cfg & 0xf;
> @@ -76,54 +92,56 @@ int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset)
>  int sunxi_gpio_get_cfgpin(u32 pin)
>  {
>  	u32 bank = GPIO_BANK(pin);
> -	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
> +	void *bank_base = BANK_TO_GPIO(bank);
>  
> -	return sunxi_gpio_get_cfgbank(pio, pin);
> +	return sunxi_gpio_get_cfgbank(bank_base, GPIO_NUM(pin));
>  }
>  
> -static void sunxi_gpio_set_output_bank(struct sunxi_gpio *pio,
> -				       int pin, bool set)
> +static void sunxi_gpio_set_output_bank(void *bank_base, int pin, bool set)
>  {
>  	u32 mask = 1U << pin;
>  
> -	clrsetbits_le32(&pio->dat, set ? 0 : mask, set ? mask : 0);
> +	clrsetbits_le32(bank_base + GPIO_DAT_REG_OFFSET,
> +			set ? 0 : mask, set ? mask : 0);
>  }
>  
> -static int sunxi_gpio_get_output_bank(struct sunxi_gpio *pio, int pin)
> +static int sunxi_gpio_get_output_bank(void *bank_base, int pin)
>  {
> -	return !!(readl(&pio->dat) & (1U << pin));
> +	return !!(readl(bank_base + GPIO_DAT_REG_OFFSET) & (1U << pin));
>  }
>  
>  void sunxi_gpio_set_drv(u32 pin, u32 val)
>  {
>  	u32 bank = GPIO_BANK(pin);
> -	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
> +	void *bank_base = BANK_TO_GPIO(bank);
>  
> -	sunxi_gpio_set_drv_bank(pio, pin, val);
> +	sunxi_gpio_set_drv_bank(bank_base, GPIO_NUM(pin), val);
>  }
>  
> -void sunxi_gpio_set_drv_bank(struct sunxi_gpio *pio, u32 bank_offset, u32 val)
> +void sunxi_gpio_set_drv_bank(void *bank_base, u32 pin_offset, u32 val)
>  {
> -	u32 index = GPIO_DRV_INDEX(bank_offset);
> -	u32 offset = GPIO_DRV_OFFSET(bank_offset);
> +	u32 index = GPIO_DRV_INDEX(pin_offset);
> +	u32 offset = GPIO_DRV_OFFSET(pin_offset);
>  
> -	clrsetbits_le32(&pio->drv[index], 0x3 << offset, val << offset);
> +	clrsetbits_le32(bank_base + GPIO_DRV_REG_OFFSET + index * 4,
> +			0x3U << offset, val << offset);
>  }
>  
>  void sunxi_gpio_set_pull(u32 pin, u32 val)
>  {
>  	u32 bank = GPIO_BANK(pin);
> -	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
> +	void *bank_base = BANK_TO_GPIO(bank);
>  
> -	sunxi_gpio_set_pull_bank(pio, pin, val);
> +	sunxi_gpio_set_pull_bank(bank_base, GPIO_NUM(pin), val);
>  }
>  
> -void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val)
> +void sunxi_gpio_set_pull_bank(void *bank_base, int pin_offset, u32 val)
>  {
> -	u32 index = GPIO_PULL_INDEX(bank_offset);
> -	u32 offset = GPIO_PULL_OFFSET(bank_offset);
> +	u32 index = GPIO_PULL_INDEX(pin_offset);
> +	u32 offset = GPIO_PULL_OFFSET(pin_offset);
>  
> -	clrsetbits_le32(&pio->pull[index], 0x3 << offset, val << offset);
> +	clrsetbits_le32(bank_base + GPIO_PULL_REG_OFFSET + index * 4,
> +			0x3U << offset, val << offset);
>  }
>  
>  
> @@ -133,7 +151,7 @@ void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val)
>  static void sunxi_gpio_set_output(u32 pin, bool set)
>  {
>  	u32 bank = GPIO_BANK(pin);
> -	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
> +	void *pio = BANK_TO_GPIO(bank);
>  
>  	sunxi_gpio_set_output_bank(pio, GPIO_NUM(pin), set);
>  }
> @@ -141,7 +159,7 @@ static void sunxi_gpio_set_output(u32 pin, bool set)
>  static int sunxi_gpio_get_output(u32 pin)
>  {
>  	u32 bank = GPIO_BANK(pin);
> -	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
> +	void *pio = BANK_TO_GPIO(bank);
>  
>  	return sunxi_gpio_get_output_bank(pio, GPIO_NUM(pin));
>  }
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> index e5102180902..946447e9136 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> @@ -35,7 +35,7 @@ struct sunxi_pinctrl_desc {
>  };
>  
>  struct sunxi_pinctrl_plat {
> -	struct sunxi_gpio __iomem *base;
> +	void __iomem *base;
>  };
>  
>  static int sunxi_pinctrl_get_pins_count(struct udevice *dev)
> @@ -86,8 +86,8 @@ static int sunxi_pinctrl_pinmux_set(struct udevice *dev, uint pin_selector,
>  	      sunxi_pinctrl_get_function_name(dev, func_selector),
>  	      desc->functions[func_selector].mux);
>  
> -	sunxi_gpio_set_cfgbank(plat->base + bank, pin,
> -			       desc->functions[func_selector].mux);
> +	sunxi_gpio_set_cfgbank(plat->base + bank * SUNXI_PINCTRL_BANK_SIZE,
> +			       pin, desc->functions[func_selector].mux);
>  
>  	return 0;
>  }
> @@ -102,7 +102,7 @@ static const struct pinconf_param sunxi_pinctrl_pinconf_params[] = {
>  static int sunxi_pinctrl_pinconf_set_pull(struct sunxi_pinctrl_plat *plat,
>  					  uint bank, uint pin, uint bias)
>  {
> -	struct sunxi_gpio *regs = &plat->base[bank];
> +	void *regs = plat->base + bank * SUNXI_PINCTRL_BANK_SIZE;
>  
>  	sunxi_gpio_set_pull_bank(regs, pin, bias);
>  
> @@ -112,7 +112,7 @@ static int sunxi_pinctrl_pinconf_set_pull(struct sunxi_pinctrl_plat *plat,
>  static int sunxi_pinctrl_pinconf_set_drive(struct sunxi_pinctrl_plat *plat,
>  					   uint bank, uint pin, uint drive)
>  {
> -	struct sunxi_gpio *regs = &plat->base[bank];
> +	void *regs = plat->base + bank * SUNXI_PINCTRL_BANK_SIZE;
>  
>  	if (drive < 10 || drive > 40)
>  		return -EINVAL;
> @@ -148,7 +148,7 @@ static int sunxi_pinctrl_get_pin_muxing(struct udevice *dev, uint pin_selector,
>  	struct sunxi_pinctrl_plat *plat = dev_get_plat(dev);
>  	int bank = pin_selector / SUNXI_GPIOS_PER_BANK;
>  	int pin	 = pin_selector % SUNXI_GPIOS_PER_BANK;
> -	int mux  = sunxi_gpio_get_cfgbank(plat->base + bank, pin);
> +	int mux  = sunxi_gpio_get_cfgbank(plat->base + bank * SUNXI_PINCTRL_BANK_SIZE, pin);
>  
>  	switch (mux) {
>  	case SUNXI_GPIO_INPUT:
> @@ -206,7 +206,7 @@ static int sunxi_pinctrl_bind(struct udevice *dev)
>  		if (!gpio_plat)
>  			return -ENOMEM;
>  
> -		gpio_plat->regs = plat->base + i;
> +		gpio_plat->regs = plat->base + i * SUNXI_PINCTRL_BANK_SIZE;
>  		gpio_plat->bank_name[0] = 'P';
>  		gpio_plat->bank_name[1] = 'A' + desc->first_bank + i;
>  		gpio_plat->bank_name[2] = '\0';


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 07/22] pinctrl: sunxi: remove GPIO_EXTRA_HEADER
  2023-09-28 21:54 ` [PATCH v2 07/22] pinctrl: sunxi: remove GPIO_EXTRA_HEADER Andre Przywara
@ 2023-10-21  8:57   ` Samuel Holland
  0 siblings, 0 replies; 43+ messages in thread
From: Samuel Holland @ 2023-10-21  8:57 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Jernej Skrabec, Icenowy Zheng, Maxim Kiselev, Sam Edwards,
	Okhunjon Sobirjonov, linux-sunxi, andre.przywara, Jagan Teki,
	u-boot

On 9/28/23 16:54, Andre Przywara wrote:
> U-Boot's generic GPIO_EXTRA_HEADER is a convenience symbol to allow code
> to more easily include platform specific GPIO headers. This should not
> be needed in a DM world anymore, since the generic GPIO framework
> handles that nicely.
> For Allwinner boards we still need to deal with non-DM GPIO in the SPL,
> but this should become the exception, not the rule.
> 
> Make this more obvious by removing the definition of GPIO_EXTRA_HEADER,
> and just force every legacy user of platform specific GPIO to include
> the new sunxi_gpio.h header explicitly. Everyone doing so should feel
> ashamed and should find a way to avoid it from now on.
> 
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  arch/arm/Kconfig                                               | 1 -
>  arch/arm/mach-sunxi/board.c                                    | 1 +
>  arch/arm/mach-sunxi/dram_suniv.c                               | 2 +-
>  arch/arm/mach-sunxi/spl_spi_sunxi.c                            | 1 +
>  board/sunxi/board.c                                            | 1 +
>  board/sunxi/chip.c                                             | 2 +-
>  drivers/gpio/axp_gpio.c                                        | 1 +
>  drivers/gpio/sunxi_gpio.c                                      | 1 +
>  drivers/i2c/sun6i_p2wi.c                                       | 2 +-
>  drivers/i2c/sun8i_rsb.c                                        | 2 +-
>  drivers/mmc/sunxi_mmc.c                                        | 1 +
>  drivers/pinctrl/sunxi/pinctrl-sunxi.c                          | 1 +
>  drivers/video/hitachi_tx18d42vm_lcd.c                          | 1 +
>  drivers/video/ssd2828.c                                        | 1 -
>  drivers/video/sunxi/sunxi_display.c                            | 1 +
>  drivers/video/sunxi/sunxi_lcd.c                                | 1 +
>  arch/arm/include/asm/arch-sunxi/gpio.h => include/sunxi_gpio.h | 0
>  17 files changed, 14 insertions(+), 6 deletions(-)
>  rename arch/arm/include/asm/arch-sunxi/gpio.h => include/sunxi_gpio.h (100%)

Tested-by: Samuel Holland <samuel@sholland.org>


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 01/22] sunxi: remove CONFIG_SATAPWR
  2023-10-19 23:51   ` Samuel Holland
@ 2023-10-21 23:27     ` Andre Przywara
  2023-10-22  3:34       ` Samuel Holland
  0 siblings, 1 reply; 43+ messages in thread
From: Andre Przywara @ 2023-10-21 23:27 UTC (permalink / raw)
  To: Samuel Holland
  Cc: Jernej Skrabec, Icenowy Zheng, Maxim Kiselev, Sam Edwards,
	Okhunjon Sobirjonov, linux-sunxi, andre.przywara, Jagan Teki,
	u-boot

On Thu, 19 Oct 2023 18:51:30 -0500
Samuel Holland <samuel@sholland.org> wrote:

Hi Samuel,

thanks for having a look!

> On 9/28/23 16:54, Andre Przywara wrote:
> > The CONFIG_SATAPWR Kconfig symbol was used to point to a GPIO that
> > enables the power for a SATA harddisk.
> > In the DT this is described with the target-supply property in the AHCI
> > DT node, pointing to a (GPIO controlled) regulator. Since we need SATA
> > only in U-Boot proper, and use a DM driver for AHCI there, we should use
> > the DT instead of hardcoding this.
> > 
> > Add code to the sunxi AHCI driver to check the DT for that regulator and
> > enable it, at probe time. Then drop the current code from board.c, which
> > was doing that job before.
> > This allows us to remove the SATAPWR Kconfig definition and the
> > respective values from the defconfigs.
> > We also select the generic fixed regulator driver, which handles those
> > GPIO controlled regulators.
> > 
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > Reviewed-by: Sam Edwards <CFSworks@gmail.com>
> > ---
> >  arch/arm/Kconfig                             |  2 ++
> >  arch/arm/mach-sunxi/Kconfig                  |  8 --------
> >  board/sunxi/board.c                          | 16 +---------------
> >  configs/A10-OLinuXino-Lime_defconfig         |  1 -
> >  configs/A20-OLinuXino-Lime2-eMMC_defconfig   |  1 -
> >  configs/A20-OLinuXino-Lime2_defconfig        |  1 -
> >  configs/A20-OLinuXino-Lime_defconfig         |  1 -
> >  configs/A20-OLinuXino_MICRO-eMMC_defconfig   |  1 -
> >  configs/A20-OLinuXino_MICRO_defconfig        |  1 -
> >  configs/A20-Olimex-SOM-EVB_defconfig         |  1 -
> >  configs/A20-Olimex-SOM204-EVB-eMMC_defconfig |  1 -
> >  configs/A20-Olimex-SOM204-EVB_defconfig      |  1 -
> >  configs/Cubieboard2_defconfig                |  1 -
> >  configs/Cubieboard_defconfig                 |  1 -
> >  configs/Cubietruck_defconfig                 |  1 -
> >  configs/Itead_Ibox_A20_defconfig             |  1 -
> >  configs/Lamobo_R1_defconfig                  |  1 -
> >  configs/Linksprite_pcDuino3_Nano_defconfig   |  1 -
> >  configs/Linksprite_pcDuino3_defconfig        |  1 -
> >  configs/Sinovoip_BPI_M3_defconfig            |  1 -
> >  configs/orangepi_plus_defconfig              |  2 +-
> >  drivers/ata/ahci_sunxi.c                     |  9 +++++++++
> >  22 files changed, 13 insertions(+), 41 deletions(-)
> > 
> > [...]
> > diff --git a/configs/orangepi_plus_defconfig b/configs/orangepi_plus_defconfig
> > index 76de72aa228..ed585881d49 100644
> > --- a/configs/orangepi_plus_defconfig
> > +++ b/configs/orangepi_plus_defconfig
> > @@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=672
> >  CONFIG_MACPWR="PD6"
> >  CONFIG_MMC_SUNXI_SLOT_EXTRA=2
> >  CONFIG_USB1_VBUS_PIN="PG13"
> > -CONFIG_SATAPWR="PG11"
> >  # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
> >  CONFIG_SPL_I2C=y
> >  CONFIG_SPL_SYS_I2C_LEGACY=y
> > @@ -16,3 +15,4 @@ CONFIG_SUN8I_EMAC=y
> >  CONFIG_SY8106A_POWER=y
> >  CONFIG_USB_EHCI_HCD=y
> >  CONFIG_USB_OHCI_HCD=y
> > +CONFIG_USB3_VBUS_PIN="PG11"  
> 
> This change is unrelated to the purpose of this commit.

I added this line after your suggestion last December:
https://lore.kernel.org/u-boot/bb2ef69f-23e1-9936-e824-6b86924b9c8a@sholland.org/

In short: this is an H3 board without native SATA, so having this
symbol set here enables SATA operation for now, until we get full DT
regulator support in phy-sun4i-usb.c.

Cheers,
Andre

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 02/22] net: sunxi_emac: chase DT nodes to find PHY regulator
  2023-10-20  0:01   ` Samuel Holland
@ 2023-10-21 23:33     ` Andre Przywara
  0 siblings, 0 replies; 43+ messages in thread
From: Andre Przywara @ 2023-10-21 23:33 UTC (permalink / raw)
  To: Samuel Holland
  Cc: Jernej Skrabec, Icenowy Zheng, Maxim Kiselev, Sam Edwards,
	Okhunjon Sobirjonov, linux-sunxi, andre.przywara, Jagan Teki,
	u-boot

On Thu, 19 Oct 2023 19:01:30 -0500
Samuel Holland <samuel@sholland.org> wrote:

Hi,

> Hi Andre,
> 
> On 9/28/23 16:54, Andre Przywara wrote:
> > At the moment the sun4i EMAC driver relies on hardcoded CONFIG_MACPWR
> > Kconfig symbols to enable potential PHY regulators. As we want to get rid
> > of those, we need to find the regulator by chasing up the DT.
> > 
> > The sun4i-emac binding puts the PHY regulator into the MDIO node, which
> > is the parent of the PHY device. U-Boot does not have (and does not
> > need) an MDIO driver, so we need to chase down the regulator through the
> > EMAC node: we follow the "phy-handle" property to find the PHY node,
> > then go up to its parent, where we find the "phy-supply" link to the
> > regulator. Let U-Boot find the associated regulator device, and put that
> > into the private device struct, so we can find and enable the regulator
> > at probe time, later.  
> 
> This does somewhat duplicate the logic from dm_eth_connect_phy_handle(),
> and putting the regulator in a UCLASS_MDIO device's probe function would
> work out cleanly (albeit with the usual DM overhead). But that can be a
> later refactoring.

Thanks for the suggestion, I will have a look later, there is more
cleanup possible in this file, it seems.
For now I like to accept this "...can be a later refactoring" ;-)

> 
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > Reviewed-by: Sam Edwards <CFSworks@gmail.com>
> > ---
> >  drivers/net/sunxi_emac.c | 39 +++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 39 insertions(+)
> > 
> > diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c
> > index 4c90d4b4981..f1f0e5bbbb2 100644
> > --- a/drivers/net/sunxi_emac.c
> > +++ b/drivers/net/sunxi_emac.c
> > @@ -17,6 +17,7 @@
> >  #include <net.h>
> >  #include <asm/io.h>
> >  #include <asm/arch/clock.h>
> > +#include <power/regulator.h>
> >  
> >  /* EMAC register  */
> >  struct emac_regs {
> > @@ -165,6 +166,7 @@ struct emac_eth_dev {
> >  	struct phy_device *phydev;
> >  	int link_printed;
> >  	uchar rx_buf[EMAC_RX_BUFSIZE];
> > +	struct udevice *phy_reg;
> >  };
> >  
> >  struct emac_rxhdr {
> > @@ -572,6 +574,9 @@ static int sunxi_emac_eth_probe(struct udevice *dev)
> >  	if (ret)
> >  		return ret;
> >  
> > +	if (priv->phy_reg)
> > +		regulator_set_enable(priv->phy_reg, true);
> > +
> >  	return sunxi_emac_init_phy(priv, dev);
> >  }
> >  
> > @@ -585,9 +590,43 @@ static const struct eth_ops sunxi_emac_eth_ops = {
> >  static int sunxi_emac_eth_of_to_plat(struct udevice *dev)
> >  {
> >  	struct eth_pdata *pdata = dev_get_plat(dev);
> > +	struct emac_eth_dev *priv = dev_get_priv(dev);
> > +	struct ofnode_phandle_args args;
> > +	ofnode mdio_node;
> > +	int ret;
> >  
> >  	pdata->iobase = dev_read_addr(dev);
> >  
> > +	/* The PHY regulator is in the MDIO node, not the EMAC or PHY node. */
> > +	ret = dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0, &args);  
> 
> You can use dev_get_phy_node() here. Either way:

Right, doesn't save too much, but isn't complicated either. I have
changed that.

> Reviewed-by: Samuel Holland <samuel@sholland.org>

Thanks!
Andre

> 
> > +	if (ret) {
> > +		dev_err(dev, "failed to get PHY node\n");
> > +		return ret;
> > +	}
> > +
> > +	/*
> > +	 * U-Boot does not have (and does not need) a device driver for the
> > +	 * MDIO device, so just "pass through" that DT node to get to the
> > +	 * regulator phandle.
> > +	 * The PHY regulator is optional, though: ignore if we cannot find
> > +	 * a phy-supply property.
> > +	 */
> > +	mdio_node = ofnode_get_parent(args.node);
> > +	ret= ofnode_parse_phandle_with_args(mdio_node, "phy-supply", NULL, 0, 0,
> > +					    &args);
> > +	if (ret && ret != -ENOENT) {
> > +		dev_err(dev, "failed to get PHY supply node\n");
> > +		return ret;
> > +	}
> > +	if (!ret) {
> > +		ret = uclass_get_device_by_ofnode(UCLASS_REGULATOR, args.node,
> > +						  &priv->phy_reg);
> > +		if (ret) {
> > +			dev_err(dev, "failed to get PHY regulator node\n");
> > +			return ret;
> > +		}
> > +	}
> > +
> >  	return 0;
> >  }
> >    
> 


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 05/22] pinctrl: sunxi: add GPIO in/out wrappers
  2023-10-21  8:30   ` Samuel Holland
@ 2023-10-21 23:46     ` Andre Przywara
  0 siblings, 0 replies; 43+ messages in thread
From: Andre Przywara @ 2023-10-21 23:46 UTC (permalink / raw)
  To: Samuel Holland
  Cc: Jernej Skrabec, Icenowy Zheng, Maxim Kiselev, Sam Edwards,
	Okhunjon Sobirjonov, linux-sunxi, andre.przywara, Jagan Teki,
	u-boot

On Sat, 21 Oct 2023 03:30:48 -0500
Samuel Holland <samuel@sholland.org> wrote:

> Hi Andre,
> 
> On 9/28/23 16:54, Andre Przywara wrote:
> > So far we were open-coding the pincontroller's GPIO output/input access
> > in each function using that.
> > 
> > Provide functions that wrap that nicely, and follow the existing pattern
> > (set/get_{bank,}), so users don't need to know about the internals, and
> > we can abstract the new D1 pinctrl more easily.
> > 
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> >  drivers/gpio/sunxi_gpio.c | 55 ++++++++++++++++++---------------------
> >  1 file changed, 25 insertions(+), 30 deletions(-)
> > 
> > diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
> > index 71c3168b755..a4b336943b6 100644
> > --- a/drivers/gpio/sunxi_gpio.c
> > +++ b/drivers/gpio/sunxi_gpio.c
> > @@ -81,6 +81,19 @@ int sunxi_gpio_get_cfgpin(u32 pin)
> >  	return sunxi_gpio_get_cfgbank(pio, pin);
> >  }
> >  
> > +static void sunxi_gpio_set_output_bank(struct sunxi_gpio *pio,
> > +				       int pin, bool set)
> > +{
> > +	u32 mask = 1U << pin;
> > +
> > +	clrsetbits_le32(&pio->dat, set ? 0 : mask, set ? mask : 0);
> > +}
> > +
> > +static int sunxi_gpio_get_output_bank(struct sunxi_gpio *pio, int pin)  
> 
> "get_output" is a bit misleading when this pin is an input, so maybe
> "set_value" and "get_value" would be more accurate.

Good point, changed that.

> 
> > +{
> > +	return !!(readl(&pio->dat) & (1U << pin));
> > +}
> > +
> >  void sunxi_gpio_set_drv(u32 pin, u32 val)
> >  {
> >  	u32 bank = GPIO_BANK(pin);
> > @@ -117,35 +130,20 @@ void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val)
> >  /* =========== Non-DM code, used by the SPL. ============ */
> >  
> >  #if !CONFIG_IS_ENABLED(DM_GPIO)
> > -static int sunxi_gpio_output(u32 pin, u32 val)
> > +static void sunxi_gpio_set_output(u32 pin, bool set)
> >  {
> > -	u32 dat;
> >  	u32 bank = GPIO_BANK(pin);
> > -	u32 num = GPIO_NUM(pin);
> >  	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
> >  
> > -	dat = readl(&pio->dat);
> > -	if (val)
> > -		dat |= 0x1 << num;
> > -	else
> > -		dat &= ~(0x1 << num);
> > -
> > -	writel(dat, &pio->dat);
> > -
> > -	return 0;
> > +	sunxi_gpio_set_output_bank(pio, GPIO_NUM(pin), set);
> >  }
> >  
> > -static int sunxi_gpio_input(u32 pin)
> > +static int sunxi_gpio_get_output(u32 pin)
> >  {
> > -	u32 dat;
> >  	u32 bank = GPIO_BANK(pin);
> > -	u32 num = GPIO_NUM(pin);
> >  	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
> >  
> > -	dat = readl(&pio->dat);
> > -	dat >>= num;
> > -
> > -	return dat & 0x1;
> > +	return sunxi_gpio_get_output_bank(pio, GPIO_NUM(pin));
> >  }
> >  
> >  int gpio_request(unsigned gpio, const char *label)
> > @@ -168,18 +166,21 @@ int gpio_direction_input(unsigned gpio)
> >  int gpio_direction_output(unsigned gpio, int value)
> >  {
> >  	sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_OUTPUT);
> > +	sunxi_gpio_set_output(gpio, value);
> >  
> > -	return sunxi_gpio_output(gpio, value);
> > +	return 0;
> >  }
> >  
> >  int gpio_get_value(unsigned gpio)
> >  {
> > -	return sunxi_gpio_input(gpio);
> > +	return sunxi_gpio_get_output(gpio);
> >  }
> >  
> >  int gpio_set_value(unsigned gpio, int value)
> >  {
> > -	return sunxi_gpio_output(gpio, value);
> > +	sunxi_gpio_set_output(gpio, value);
> > +
> > +	return 0;
> >  }
> >  
> >  int sunxi_name_to_gpio(const char *name)
> > @@ -231,13 +232,8 @@ int sunxi_name_to_gpio(const char *name)
> >  static int sunxi_gpio_get_value(struct udevice *dev, unsigned offset)
> >  {
> >  	struct sunxi_gpio_plat *plat = dev_get_plat(dev);
> > -	u32 num = GPIO_NUM(offset);
> > -	unsigned dat;
> > -
> > -	dat = readl(&plat->regs->dat);
> > -	dat >>= num;
> >  
> > -	return dat & 0x1;
> > +	return sunxi_gpio_get_output_bank(plat->regs, offset) & 0x1;  
> 
> You don't need the "& 0x1" anymore. Otherwise:

Ah, correct, we have a !! in the callee now. Fixed.

> Reviewed-by: Samuel Holland <samuel@sholland.org>

Thanks!
Andre

> 
> >  }
> >  
> >  static int sunxi_gpio_get_function(struct udevice *dev, unsigned offset)
> > @@ -275,9 +271,8 @@ static int sunxi_gpio_set_flags(struct udevice *dev, unsigned int offset,
> >  
> >  	if (flags & GPIOD_IS_OUT) {
> >  		u32 value = !!(flags & GPIOD_IS_OUT_ACTIVE);
> > -		u32 num = GPIO_NUM(offset);
> >  
> > -		clrsetbits_le32(&plat->regs->dat, 1 << num, value << num);
> > +		sunxi_gpio_set_output_bank(plat->regs, offset, value);
> >  		sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_OUTPUT);
> >  	} else if (flags & GPIOD_IS_IN) {
> >  		u32 pull = 0;  
> 


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 09/22] pinctrl: sunxi: add new D1 pinctrl support
  2023-09-28 21:54 ` [PATCH v2 09/22] pinctrl: sunxi: add new D1 pinctrl support Andre Przywara
@ 2023-10-22  3:31   ` Samuel Holland
  0 siblings, 0 replies; 43+ messages in thread
From: Samuel Holland @ 2023-10-22  3:31 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Jernej Skrabec, Icenowy Zheng, Maxim Kiselev, Sam Edwards,
	Okhunjon Sobirjonov, linux-sunxi, andre.przywara, Jagan Teki,
	u-boot

Hi Andre,

On 9/28/23 16:54, Andre Przywara wrote:
> For the first time since at least the Allwinner A10 SoCs, the D1 (and
> related cores) use a new pincontroller MMIO register layout, so we
> cannot use our hardcoded, fixed offsets anymore.
> Ideally this would all be handled by devicetree and DM drivers, but for
> the DT-less SPL we still need the legacy interfaces.
> 
> Add a new Kconfig symbol to differenciate between the two generations of
> pincontrollers, and just use that to just switch some basic symbols.
> The rest is already abstracted enough, so works out of the box.
> 
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> Reviewed-by: Sam Edwards <CFSworks@gmail.com>
> Tested-by: Sam Edwards <CFSworks@gmail.com>
> ---
>  arch/arm/mach-sunxi/Kconfig |  6 ++++++
>  drivers/gpio/sunxi_gpio.c   | 17 +++++++++++++++--
>  include/sunxi_gpio.h        | 10 ++++++++--
>  3 files changed, 29 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
> index d3ed62add99..d73c5e67050 100644
> --- a/arch/arm/mach-sunxi/Kconfig
> +++ b/arch/arm/mach-sunxi/Kconfig
> @@ -158,6 +158,12 @@ config SUNXI_RVBAR_ALTERNATIVE
>  config SUNXI_A64_TIMER_ERRATUM
>  	bool
>  
> +config SUNXI_NEW_PINCTRL

Please put this in drivers/gpio/Kconfig so it can be selected on RISC-V
(ARCH_SUNXI=n). With that:

Tested-by: Samuel Holland <samuel@sholland.org>

Regards,
Samuel

> +	bool
> +	---help---
> +	The Allwinner D1 and other new SoCs use a different register map
> +	for the GPIO block, which we need to know about in the SPL.
> +
>  # Note only one of these may be selected at a time! But hidden choices are
>  # not supported by Kconfig
>  config SUNXI_GEN_SUN4I
> diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
> index b52569104b7..c50996d0e12 100644
> --- a/drivers/gpio/sunxi_gpio.c
> +++ b/drivers/gpio/sunxi_gpio.c
> @@ -40,10 +40,23 @@
>  #define GPIO_DAT_REG_OFFSET	0x10
>  
>  #define GPIO_DRV_REG_OFFSET	0x14
> -#define GPIO_DRV_INDEX(pin)	(((pin) & 0x1f) >> 4)
> -#define GPIO_DRV_OFFSET(pin)	((((pin) & 0x1f) & 0xf) << 1)
> +
> +/*		Newer SoCs use a slightly different register layout */
> +#ifdef CONFIG_SUNXI_NEW_PINCTRL
> +/* pin drive strength: 4 bits per pin */
> +#define GPIO_DRV_INDEX(pin)	((pin) / 8)
> +#define GPIO_DRV_OFFSET(pin)	(((pin) % 8) * 4)
> +
> +#define GPIO_PULL_REG_OFFSET	0x24
> +
> +#else /* older generation pin controllers */
> +/* pin drive strength: 2 bits per pin */
> +#define GPIO_DRV_INDEX(pin)	((pin) / 16)
> +#define GPIO_DRV_OFFSET(pin)	(((pin) % 16) * 2)
>  
>  #define GPIO_PULL_REG_OFFSET	0x1c
> +#endif
> +
>  #define GPIO_PULL_INDEX(pin)	(((pin) & 0x1f) >> 4)
>  #define GPIO_PULL_OFFSET(pin)	((((pin) & 0x1f) & 0xf) << 1)
>  
> diff --git a/include/sunxi_gpio.h b/include/sunxi_gpio.h
> index c1fdf7ea1d7..30d8879dbd3 100644
> --- a/include/sunxi_gpio.h
> +++ b/include/sunxi_gpio.h
> @@ -62,7 +62,6 @@
>  #define SUN50I_H6_GPIO_POW_MOD_VAL	0x348
>  
>  #define SUNXI_GPIOS_PER_BANK	32
> -#define SUNXI_PINCTRL_BANK_SIZE 0x24
>  
>  #define SUNXI_GPIO_NEXT(__gpio) \
>  	((__gpio##_START) + SUNXI_GPIOS_PER_BANK)
> @@ -102,7 +101,6 @@ enum sunxi_gpio_number {
>  /* GPIO pin function config */
>  #define SUNXI_GPIO_INPUT	0
>  #define SUNXI_GPIO_OUTPUT	1
> -#define SUNXI_GPIO_DISABLE	7
>  
>  #define SUN8I_H3_GPA_UART0	2
>  #define SUN8I_H3_GPA_UART2	2
> @@ -171,6 +169,14 @@ enum sunxi_gpio_number {
>  
>  #define SUN9I_GPN_R_RSB		3
>  
> +#ifdef CONFIG_SUNXI_NEW_PINCTRL
> +	#define SUNXI_PINCTRL_BANK_SIZE	0x30
> +	#define SUNXI_GPIO_DISABLE	0xf
> +#else
> +	#define SUNXI_PINCTRL_BANK_SIZE	0x24
> +	#define SUNXI_GPIO_DISABLE	0x7
> +#endif
> +
>  /* GPIO pin pull-up/down config */
>  #define SUNXI_GPIO_PULL_DISABLE	0
>  #define SUNXI_GPIO_PULL_UP	1


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 01/22] sunxi: remove CONFIG_SATAPWR
  2023-10-21 23:27     ` Andre Przywara
@ 2023-10-22  3:34       ` Samuel Holland
  0 siblings, 0 replies; 43+ messages in thread
From: Samuel Holland @ 2023-10-22  3:34 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Jernej Skrabec, Icenowy Zheng, Maxim Kiselev, Sam Edwards,
	Okhunjon Sobirjonov, linux-sunxi, andre.przywara, Jagan Teki,
	u-boot

On 10/21/23 18:27, Andre Przywara wrote:
> On Thu, 19 Oct 2023 18:51:30 -0500
> Samuel Holland <samuel@sholland.org> wrote:
> 
> Hi Samuel,
> 
> thanks for having a look!
> 
>> On 9/28/23 16:54, Andre Przywara wrote:
>>> The CONFIG_SATAPWR Kconfig symbol was used to point to a GPIO that
>>> enables the power for a SATA harddisk.
>>> In the DT this is described with the target-supply property in the AHCI
>>> DT node, pointing to a (GPIO controlled) regulator. Since we need SATA
>>> only in U-Boot proper, and use a DM driver for AHCI there, we should use
>>> the DT instead of hardcoding this.
>>>
>>> Add code to the sunxi AHCI driver to check the DT for that regulator and
>>> enable it, at probe time. Then drop the current code from board.c, which
>>> was doing that job before.
>>> This allows us to remove the SATAPWR Kconfig definition and the
>>> respective values from the defconfigs.
>>> We also select the generic fixed regulator driver, which handles those
>>> GPIO controlled regulators.
>>>
>>> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
>>> Reviewed-by: Sam Edwards <CFSworks@gmail.com>
>>> ---
>>>  arch/arm/Kconfig                             |  2 ++
>>>  arch/arm/mach-sunxi/Kconfig                  |  8 --------
>>>  board/sunxi/board.c                          | 16 +---------------
>>>  configs/A10-OLinuXino-Lime_defconfig         |  1 -
>>>  configs/A20-OLinuXino-Lime2-eMMC_defconfig   |  1 -
>>>  configs/A20-OLinuXino-Lime2_defconfig        |  1 -
>>>  configs/A20-OLinuXino-Lime_defconfig         |  1 -
>>>  configs/A20-OLinuXino_MICRO-eMMC_defconfig   |  1 -
>>>  configs/A20-OLinuXino_MICRO_defconfig        |  1 -
>>>  configs/A20-Olimex-SOM-EVB_defconfig         |  1 -
>>>  configs/A20-Olimex-SOM204-EVB-eMMC_defconfig |  1 -
>>>  configs/A20-Olimex-SOM204-EVB_defconfig      |  1 -
>>>  configs/Cubieboard2_defconfig                |  1 -
>>>  configs/Cubieboard_defconfig                 |  1 -
>>>  configs/Cubietruck_defconfig                 |  1 -
>>>  configs/Itead_Ibox_A20_defconfig             |  1 -
>>>  configs/Lamobo_R1_defconfig                  |  1 -
>>>  configs/Linksprite_pcDuino3_Nano_defconfig   |  1 -
>>>  configs/Linksprite_pcDuino3_defconfig        |  1 -
>>>  configs/Sinovoip_BPI_M3_defconfig            |  1 -
>>>  configs/orangepi_plus_defconfig              |  2 +-
>>>  drivers/ata/ahci_sunxi.c                     |  9 +++++++++
>>>  22 files changed, 13 insertions(+), 41 deletions(-)
>>>
>>> [...]
>>> diff --git a/configs/orangepi_plus_defconfig b/configs/orangepi_plus_defconfig
>>> index 76de72aa228..ed585881d49 100644
>>> --- a/configs/orangepi_plus_defconfig
>>> +++ b/configs/orangepi_plus_defconfig
>>> @@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=672
>>>  CONFIG_MACPWR="PD6"
>>>  CONFIG_MMC_SUNXI_SLOT_EXTRA=2
>>>  CONFIG_USB1_VBUS_PIN="PG13"
>>> -CONFIG_SATAPWR="PG11"
>>>  # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
>>>  CONFIG_SPL_I2C=y
>>>  CONFIG_SPL_SYS_I2C_LEGACY=y
>>> @@ -16,3 +15,4 @@ CONFIG_SUN8I_EMAC=y
>>>  CONFIG_SY8106A_POWER=y
>>>  CONFIG_USB_EHCI_HCD=y
>>>  CONFIG_USB_OHCI_HCD=y
>>> +CONFIG_USB3_VBUS_PIN="PG11"  
>>
>> This change is unrelated to the purpose of this commit.
> 
> I added this line after your suggestion last December:
> https://lore.kernel.org/u-boot/bb2ef69f-23e1-9936-e824-6b86924b9c8a@sholland.org/
> 
> In short: this is an H3 board without native SATA, so having this
> symbol set here enables SATA operation for now, until we get full DT
> regulator support in phy-sun4i-usb.c.

Ah right, sorry for the confusion. Maybe this deserves mentioning in the
commit message. Either way:

Reviewed-by: Samuel Holland <samuel@sholland.org>


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 10/22] sunxi: introduce NCAT2 generation model
  2023-09-28 21:54 ` [PATCH v2 10/22] sunxi: introduce NCAT2 generation model Andre Przywara
@ 2023-10-22  3:40   ` Samuel Holland
  0 siblings, 0 replies; 43+ messages in thread
From: Samuel Holland @ 2023-10-22  3:40 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Jernej Skrabec, Icenowy Zheng, Maxim Kiselev, Sam Edwards,
	Okhunjon Sobirjonov, linux-sunxi, andre.przywara, Jagan Teki,
	u-boot

Hi Andre,

On 9/28/23 16:54, Andre Przywara wrote:
> Allwinner seems to typically stick to a common MMIO memory map for
> several SoCs, but from time to time does some breaking changes, which
> also introduce new generations of some peripherals. The last time this
> happened with the H6, which apart from re-organising the base addresses
> also changed the clock controller significantly. We added a
> CONFIG_SUN50I_GEN_H6 symbol back then to mark SoCs sharing those traits.
> 
> Now the Allwinner D1 changes the memory map again, and also extends the
> pincontroller, among other peripherals.
> To mark this generation of SoCs, add a CONFIG_SUNXI_GEN_NCAT2 symbol,
> this name is reportedly used in the Allwinner BSP code, and prevents us
> from inventing our own name.
> 
> Add this new symbol to some guards that were already checking for the H6
> generation, since many features are shared between the two (like the
> renovated clock controller).
> 
> This paves the way to introduce a first user of this generation.
> 
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  arch/arm/include/asm/arch-sunxi/clock.h       |  2 +-
>  arch/arm/include/asm/arch-sunxi/cpu.h         |  2 +
>  .../include/asm/arch-sunxi/cpu_sunxi_ncat2.h  | 43 +++++++++++++++++++
>  arch/arm/include/asm/arch-sunxi/mmc.h         |  2 +-
>  arch/arm/include/asm/arch-sunxi/prcm.h        |  2 +-
>  arch/arm/include/asm/arch-sunxi/timer.h       |  2 +-
>  arch/arm/mach-sunxi/Kconfig                   | 12 +++++-
>  arch/arm/mach-sunxi/Makefile                  |  1 +
>  arch/arm/mach-sunxi/board.c                   | 22 ++++++----
>  arch/arm/mach-sunxi/clock_sun50i_h6.c         |  7 ++-
>  common/spl/Kconfig                            |  2 +-
>  drivers/i2c/mvtwsi.c                          |  3 +-
>  drivers/mmc/sunxi_mmc.c                       |  7 +--
>  include/sunxi_gpio.h                          |  3 ++
>  14 files changed, 90 insertions(+), 20 deletions(-)
>  create mode 100644 arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
> 
> diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h
> index 2cfd5407423..3d34261b0e5 100644
> --- a/arch/arm/include/asm/arch-sunxi/clock.h
> +++ b/arch/arm/include/asm/arch-sunxi/clock.h
> @@ -16,7 +16,7 @@
>  /* clock control module regs definition */
>  #if defined(CONFIG_MACH_SUN8I_A83T)
>  #include <asm/arch/clock_sun8i_a83t.h>
> -#elif defined(CONFIG_SUN50I_GEN_H6)
> +#elif defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
>  #include <asm/arch/clock_sun50i_h6.h>
>  #elif defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) || \
>        defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUNIV)
> diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h b/arch/arm/include/asm/arch-sunxi/cpu.h
> index b08f2023748..768c6572d6b 100644
> --- a/arch/arm/include/asm/arch-sunxi/cpu.h
> +++ b/arch/arm/include/asm/arch-sunxi/cpu.h
> @@ -10,6 +10,8 @@
>  #include <asm/arch/cpu_sun9i.h>
>  #elif defined(CONFIG_SUN50I_GEN_H6)
>  #include <asm/arch/cpu_sun50i_h6.h>
> +#elif defined(CONFIG_SUNXI_GEN_NCAT2)
> +#include <asm/arch/cpu_sunxi_ncat2.h>
>  #else
>  #include <asm/arch/cpu_sun4i.h>
>  #endif
> diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
> new file mode 100644
> index 00000000000..ca92c39927d
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
> @@ -0,0 +1,43 @@
> +/*
> + * (C) Copyright 2022 Arm Limited
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#ifndef _SUNXI_CPU_SUNXI_NCAT2_H
> +#define _SUNXI_CPU_SUNXI_NCAT2_H
> +
> +#define SUNXI_CCM_BASE			0x02001000
> +#define SUNXI_TIMER_BASE		0x02050000
> +
> +#define SUNXI_UART0_BASE		0x02500000
> +#define SUNXI_UART1_BASE		0x02500400
> +#define SUNXI_UART2_BASE		0x02500800
> +#define SUNXI_UART3_BASE		0x02500C00
> +#define SUNXI_TWI0_BASE			0x02502000
> +#define SUNXI_TWI1_BASE			0x02502400
> +#define SUNXI_TWI2_BASE			0x02502800
> +#define SUNXI_TWI3_BASE			0x02502C00
> +
> +#define SUNXI_SRAMC_BASE		0x03000000
> +/* SID address space starts at 0x03006000, but e-fuse is at offset 0x200 */
> +#define SUNXI_SIDC_BASE			0x03006000
> +#define SUNXI_SID_BASE			0x03006200
> +#define SUNXI_GIC400_BASE		0x03020000
> +
> +#define SUNXI_MMC0_BASE			0x04020000
> +#define SUNXI_MMC1_BASE			0x04021000
> +#define SUNXI_MMC2_BASE			0x04022000
> +
> +#define SUNXI_R_CPUCFG_BASE		0x07000400
> +#define SUNXI_PRCM_BASE			0x07010000
> +
> +#define SUNXI_CPUCFG_BASE		0x09010000
> +
> +#ifndef __ASSEMBLY__
> +void sunxi_board_init(void);
> +void sunxi_reset(void);
> +int sunxi_get_sid(unsigned int *sid);
> +#endif
> +
> +#endif /* _SUNXI_CPU_SUNXI_NCAT2_H */
> diff --git a/arch/arm/include/asm/arch-sunxi/mmc.h b/arch/arm/include/asm/arch-sunxi/mmc.h
> index 5daacf10eb1..8ed3e0459c9 100644
> --- a/arch/arm/include/asm/arch-sunxi/mmc.h
> +++ b/arch/arm/include/asm/arch-sunxi/mmc.h
> @@ -45,7 +45,7 @@ struct sunxi_mmc {
>  	u32 chda;		/* 0x90 */
>  	u32 cbda;		/* 0x94 */
>  	u32 res2[26];
> -#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
> +#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
>  	u32 res3[17];
>  	u32 samp_dl;
>  	u32 res4[46];
> diff --git a/arch/arm/include/asm/arch-sunxi/prcm.h b/arch/arm/include/asm/arch-sunxi/prcm.h
> index 5106076f5e9..c5418cfd28d 100644
> --- a/arch/arm/include/asm/arch-sunxi/prcm.h
> +++ b/arch/arm/include/asm/arch-sunxi/prcm.h
> @@ -9,7 +9,7 @@
>  #define _SUNXI_PRCM_H
>  
>  /* prcm regs definition */
> -#if defined(CONFIG_SUN50I_GEN_H6)
> +#if defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
>  #include <asm/arch/prcm_sun50i.h>
>  #else
>  #include <asm/arch/prcm_sun6i.h>
> diff --git a/arch/arm/include/asm/arch-sunxi/timer.h b/arch/arm/include/asm/arch-sunxi/timer.h
> index bb5626d893b..e17db8588e2 100644
> --- a/arch/arm/include/asm/arch-sunxi/timer.h
> +++ b/arch/arm/include/asm/arch-sunxi/timer.h
> @@ -76,7 +76,7 @@ struct sunxi_timer_reg {
>  	struct sunxi_tgp tgp[4];
>  	u8 res5[8];
>  	u32 cpu_cfg;
> -#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
> +#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
>  	u8 res3[16];
>  	struct sunxi_wdog wdog[5];	/* We have 5 watchdogs */
>  #endif
> diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
> index d73c5e67050..12eb51b2ea4 100644
> --- a/arch/arm/mach-sunxi/Kconfig
> +++ b/arch/arm/mach-sunxi/Kconfig
> @@ -121,7 +121,7 @@ config AXP_PMIC_BUS
>  config SUNXI_SRAM_ADDRESS
>  	hex
>  	default 0x10000 if MACH_SUN9I || MACH_SUN50I || MACH_SUN50I_H5
> -	default 0x20000 if SUN50I_GEN_H6
> +	default 0x20000 if SUN50I_GEN_H6 || SUNXI_GEN_NCAT2
>  	default 0x0
>  	---help---
>  	Older Allwinner SoCs have their mask boot ROM mapped just below 4GB,
> @@ -189,6 +189,14 @@ config SUN50I_GEN_H6
>  	Select this for sunxi SoCs which have H6 like peripherals, clocks
>  	and memory map.
>  
> +config SUNXI_GEN_NCAT2
> +	bool
> +	select MMC_SUNXI_HAS_NEW_MODE
> +	select SUPPORT_SPL
> +	---help---
> +	Select this for sunxi SoCs which have D1 like peripherals, clocks
> +	and memory map.


This will eventually need to go in board/sunxi/Kconfig, so it can be
selected by D1 (ARCH_SUNXI=n). For now:

Tested-by: Samuel Holland <samuel@sholland.org>


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 15/22] Kconfig: sunxi: prepare for using drivers/ram/sunxi
  2023-09-28 21:54 ` [PATCH v2 15/22] Kconfig: sunxi: prepare for using drivers/ram/sunxi Andre Przywara
@ 2023-10-22  3:44   ` Samuel Holland
  0 siblings, 0 replies; 43+ messages in thread
From: Samuel Holland @ 2023-10-22  3:44 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Jernej Skrabec, Icenowy Zheng, Maxim Kiselev, Sam Edwards,
	Okhunjon Sobirjonov, linux-sunxi, andre.przywara, Jagan Teki,
	u-boot

Hi Andre,

On 9/28/23 16:54, Andre Przywara wrote:
> At the moment all Allwinner DRAM initialisation routines are stored in
> arch/arm/mach-sunxi, even though those "drivers" are just a giant
> collection of writel's, without any architectural dependency.
> 
> The R528/T113-s SoC (with ARM cores) and the D1/D1s Soc (with RISC-V
> cores) share the same die, so should share the same DRAM init routines as
> well.
> 
> To prepare for this, add a new sunxi directory inside drivers/ram, and
> add some stub entries to prepare for the addition of the share DRAM code
> for those SoCs.
> 
> The RISC-V D1(s) SoCs will probably use SPL_DM, so make this entry
> depend on that already.
> 
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  drivers/ram/Kconfig       |  3 ++-
>  drivers/ram/sunxi/Kconfig | 14 ++++++++++++++
>  2 files changed, 16 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/ram/sunxi/Kconfig
> 
> diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig
> index bf999645774..5b07e920301 100644
> --- a/drivers/ram/Kconfig
> +++ b/drivers/ram/Kconfig
> @@ -109,8 +109,9 @@ config IMXRT_SDRAM
>  
>  source "drivers/ram/aspeed/Kconfig"
>  source "drivers/ram/cadence/Kconfig"
> +source "drivers/ram/octeon/Kconfig"
>  source "drivers/ram/rockchip/Kconfig"
>  source "drivers/ram/sifive/Kconfig"
>  source "drivers/ram/stm32mp1/Kconfig"
> -source "drivers/ram/octeon/Kconfig"
>  source "drivers/ram/starfive/Kconfig"
> +source "drivers/ram/sunxi/Kconfig"
> diff --git a/drivers/ram/sunxi/Kconfig b/drivers/ram/sunxi/Kconfig
> new file mode 100644
> index 00000000000..261d7f57409
> --- /dev/null
> +++ b/drivers/ram/sunxi/Kconfig
> @@ -0,0 +1,14 @@
> +config DRAM_SUN20I_D1
> +	bool "DM DRAM driver support for Allwinner D1"
> +	depends on RAM && ARCH_SUNXI
> +	default y
> +	help
> +	  This enables support for DRAM drivers using the driver model
> +	  for Allwinner SoCs.
> +
> +config DRAM_SUN8I_R528
> +	bool "DRAM driver support for Allwinner R528/T113s"
> +	depends on ARCH_SUNXI
> +	default y if MACH_SUN8I_R528
> +	help
> +	  Select this DRAM controller driver for the R528/T113s SoCs.

Please use a single Kconfig symbol for enabling the driver, whichever
name you choose. It doesn't need to depend on RAM -- you've already
#ifdef'd out the RAM parts. See my comments on the next patch.

Regards,
Samuel


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 16/22] sunxi: add R528/T113-s3/D1(s) DRAM initialisation code
  2023-09-28 21:54 ` [PATCH v2 16/22] sunxi: add R528/T113-s3/D1(s) DRAM initialisation code Andre Przywara
@ 2023-10-22  3:52   ` Samuel Holland
  2023-10-22 22:40     ` Andre Przywara
  0 siblings, 1 reply; 43+ messages in thread
From: Samuel Holland @ 2023-10-22  3:52 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Jernej Skrabec, Icenowy Zheng, Maxim Kiselev, Sam Edwards,
	Okhunjon Sobirjonov, linux-sunxi, andre.przywara, Jagan Teki,
	u-boot

Hi Andre,

On 9/28/23 16:54, Andre Przywara wrote:
> The Allwinner R528/T113-s/D1/D1s SoCs all share the same die, so use the
> same DRAM initialisation code.
> Make use of prior art here and lift some code from awboot[1], which
> carried init code based on earlier decompilation efforts, but with a
> GPL2 license tag.
> This code has been heavily reworked and cleaned up, to match previous
> DRAM routines for other SoCs, and also to be closer to U-Boot's coding
> style and support routines.
> The actual DRAM chip timing parameters are included in the main file,
> since they cover all DRAM types, and are protected by a new Kconfig
> CONFIG_SUNXI_DRAM_TYPE symbol, which allows the compiler to pick only
> the relevant settings, at build time.
> 
> The relevant DRAM chips/board specific configuration parameters are
> delivered via Kconfig, so this code here should work for all supported
> SoCs and DRAM chips combinations.
> 
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> Tested-by: Sam Edwards <CFSworks@gmail.com>
> ---
>  drivers/Makefile                   |    1 +
>  drivers/ram/Makefile               |    3 +
>  drivers/ram/sunxi/Kconfig          |   59 ++
>  drivers/ram/sunxi/Makefile         |    4 +
>  drivers/ram/sunxi/dram_sun20i_d1.c | 1432 ++++++++++++++++++++++++++++
>  drivers/ram/sunxi/dram_sun20i_d1.h |   73 ++
>  6 files changed, 1572 insertions(+)
>  create mode 100644 drivers/ram/sunxi/Makefile
>  create mode 100644 drivers/ram/sunxi/dram_sun20i_d1.c
>  create mode 100644 drivers/ram/sunxi/dram_sun20i_d1.h
> 
> diff --git a/drivers/Makefile b/drivers/Makefile
> index efc2a4afb24..5a4bedf7305 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -56,6 +56,7 @@ obj-$(CONFIG_$(SPL_)ALTERA_SDRAM) += ddr/altera/
>  obj-$(CONFIG_ARCH_IMX8M) += ddr/imx/imx8m/
>  obj-$(CONFIG_IMX8ULP_DRAM) += ddr/imx/imx8ulp/
>  obj-$(CONFIG_ARCH_IMX9) += ddr/imx/imx9/
> +obj-$(CONFIG_DRAM_SUN8I_R528) += ram/

This would need to be duplicated for DRAM_SUN20I_D1.

>  obj-$(CONFIG_SPL_DM_RESET) += reset/
>  obj-$(CONFIG_SPL_MUSB_NEW) += usb/musb-new/
>  obj-$(CONFIG_SPL_USB_GADGET) += usb/gadget/
> diff --git a/drivers/ram/Makefile b/drivers/ram/Makefile
> index 6eb1a241359..b4750ea11c4 100644
> --- a/drivers/ram/Makefile
> +++ b/drivers/ram/Makefile
> @@ -23,6 +23,9 @@ obj-$(CONFIG_RAM_SIFIVE) += sifive/
>  ifdef CONFIG_SPL_BUILD
>  obj-$(CONFIG_SPL_STARFIVE_DDR) += starfive/
>  endif
> +
> +obj-$(CONFIG_DRAM_SUN8I_R528) += sunxi/

This would need to be duplicated for DRAM_SUN20I_D1.

> +
>  obj-$(CONFIG_ARCH_OCTEON) += octeon/
>  
>  obj-$(CONFIG_ARCH_RMOBILE) += renesas/
> diff --git a/drivers/ram/sunxi/Kconfig b/drivers/ram/sunxi/Kconfig
> index 261d7f57409..35eeda58efa 100644
> --- a/drivers/ram/sunxi/Kconfig
> +++ b/drivers/ram/sunxi/Kconfig
> @@ -12,3 +12,62 @@ config DRAM_SUN8I_R528
>  	default y if MACH_SUN8I_R528
>  	help
>  	  Select this DRAM controller driver for the R528/T113s SoCs.
> +
> +if DRAM_SUN20I_D1 || DRAM_SUN8I_R528
> +
> +config DRAM_SUNXI_ODT_EN

You have a mixture of "DRAM_SUNXI" and "SUNXI_DRAM" for the tunables
here. I would recommend being consistent.

> +	hex "DRAM ODT EN parameter"
> +	default 0x1
> +	help
> +	  ODT EN value from vendor DRAM settings.
> +
> +config DRAM_SUNXI_TPR0
> +	hex "DRAM TPR0 parameter"
> +	default 0x0
> +	help
> +	  TPR0 value from vendor DRAM settings.
> +
> +config DRAM_SUNXI_TPR11
> +	hex "DRAM TPR11 parameter"
> +	default 0x0
> +	help
> +	  TPR11 value from vendor DRAM settings.
> +
> +config DRAM_SUNXI_TPR12
> +	hex "DRAM TPR12 parameter"
> +	default 0x0
> +	help
> +	  TPR12 value from vendor DRAM settings.
> +
> +config DRAM_SUNXI_TPR13
> +	hex "DRAM TPR13 parameter"
> +	default 0x0

I would suggest dropping the defaults for these tunables. It was
non-obvious that I was missing some configuration when I switched to
your driver. I think it's reasonable to require the defconfig/user to
provide these.

> +	help
> +	  TPR13 value from vendor DRAM settings. It tells which features
> +	  should be configured.
> +
> +choice
> +	prompt "DRAM chip type"
> +	default SUNXI_DRAM_TYPE_DDR3 if DRAM_SUN8I_R528 || DRAM_SUN20I_D1
> +
> +config SUNXI_DRAM_TYPE_DDR2
> +        bool "DDR2 chips"
> +
> +config SUNXI_DRAM_TYPE_DDR3
> +        bool "DDR3 chips"
> +
> +config SUNXI_DRAM_TYPE_LPDDR2
> +        bool "LPDDR2 chips"
> +
> +config SUNXI_DRAM_TYPE_LPDDR3
> +        bool "LPDDR3 chips"
> +endchoice
> +
> +config SUNXI_DRAM_TYPE
> +	int
> +	default 2 if SUNXI_DRAM_TYPE_DDR2
> +	default 3 if SUNXI_DRAM_TYPE_DDR3
> +	default 6 if SUNXI_DRAM_TYPE_LPDDR2
> +	default 7 if SUNXI_DRAM_TYPE_LPDDR3
> +
> +endif
> diff --git a/drivers/ram/sunxi/Makefile b/drivers/ram/sunxi/Makefile
> new file mode 100644
> index 00000000000..d6fb2cf0b65
> --- /dev/null
> +++ b/drivers/ram/sunxi/Makefile
> @@ -0,0 +1,4 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +
> +obj-$(CONFIG_DRAM_SUN20I_D1) += dram_sun20i_d1.o
> +obj-$(CONFIG_DRAM_SUN8I_R528) += dram_sun20i_d1.o
> diff --git a/drivers/ram/sunxi/dram_sun20i_d1.c b/drivers/ram/sunxi/dram_sun20i_d1.c
> new file mode 100644
> index 00000000000..c766fc24065
> --- /dev/null
> +++ b/drivers/ram/sunxi/dram_sun20i_d1.c
> @@ -0,0 +1,1432 @@
> [...]
> +/*
> + * This routine sizes a DRAM device by cycling through address lines and
> + * figuring out if they are connected to a real address line, or if the
> + * address is a mirror.
> + * First the column and bank bit allocations are set to low values (2 and 9
> + * address lines). Then a maximum allocation (16 lines) is set for rows and
> + * this is tested.
> + * Next the BA2 line is checked. This seems to be placed above the column,
> + * BA0-1 and row addresses. Finally, the column address is allocated 13 lines
> + * and these are tested. The results are placed in dram_para1 and dram_para2.
> + */
> +static int auto_scan_dram_size(const dram_para_t *para, dram_config_t *config)
> +{
> +	unsigned int rval, i, j, rank, maxrank, offs;
> +	unsigned int shft;
> +	unsigned long ptr, mc_work_mode, chk;

This breaks on 64-bit architectures, because readl(chk) can never equal
~ptr. Please change ptr and chk to unsigned int.

> +
> +	if (mctl_core_init(para, config) == 0) {
> +		printf("DRAM initialisation error : 0\n");
> +		return 0;
> +	}
> +
> +	maxrank	= (config->dram_para2 & 0xf000) ? 2 : 1;
> +	mc_work_mode = 0x3102000;
> +	offs = 0;
> +
> +	/* write test pattern */
> +	for (i = 0, ptr = CFG_SYS_SDRAM_BASE; i < 64; i++, ptr += 4)
> +		writel((i & 0x1) ? ptr : ~ptr, ptr);
> +
> +	for (rank = 0; rank < maxrank;) {
> +		/* set row mode */
> +		clrsetbits_le32(mc_work_mode, 0xf0c, 0x6f0);
> +		udelay(1);
> +
> +		// Scan per address line, until address wraps (i.e. see shadow)
> +		for (i = 11; i < 17; i++) {
> +			chk = CFG_SYS_SDRAM_BASE + (1U << (i + 11));
> +			ptr = CFG_SYS_SDRAM_BASE;
> +			for (j = 0; j < 64; j++) {
> +				if (readl(chk) != ((j & 1) ? ptr : ~ptr))
> +					break;
> +				ptr += 4;
> +				chk += 4;
> +			}
> +			if (j == 64)
> +				break;
> +		}
> +		if (i > 16)
> +			i = 16;
> +		debug("rank %d row = %d\n", rank, i);
> +
> +		/* Store rows in para 1 */
> +		shft = offs + 4;
> +		rval = config->dram_para1;
> +		rval &= ~(0xff << shft);
> +		rval |= i << shft;
> +		config->dram_para1 = rval;
> +
> +		if (rank == 1)		/* Set bank mode for rank0 */
> +			clrsetbits_le32(0x3102000, 0xffc, 0x6a4);
> +
> +		/* Set bank mode for current rank */
> +		clrsetbits_le32(mc_work_mode, 0xffc, 0x6a4);
> +		udelay(1);
> +
> +		// Test if bit A23 is BA2 or mirror XXX A22?
> +		chk = CFG_SYS_SDRAM_BASE + (1U << 22);
> +		ptr = CFG_SYS_SDRAM_BASE;
> +		for (i = 0, j = 0; i < 64; i++) {
> +			if (readl(chk) != ((i & 1) ? ptr : ~ptr)) {
> +				j = 1;
> +				break;
> +			}
> +			ptr += 4;
> +			chk += 4;
> +		}
> +
> +		debug("rank %d bank = %d\n", rank, (j + 1) << 2); /* 4 or 8 */
> +
> +		/* Store banks in para 1 */
> +		shft = 12 + offs;
> +		rval = config->dram_para1;
> +		rval &= ~(0xf << shft);
> +		rval |= j << shft;
> +		config->dram_para1 = rval;
> +
> +		if (rank == 1)		/* Set page mode for rank0 */
> +			clrsetbits_le32(0x3102000, 0xffc, 0xaa0);
> +
> +		/* Set page mode for current rank */
> +		clrsetbits_le32(mc_work_mode, 0xffc, 0xaa0);
> +		udelay(1);
> +
> +		// Scan per address line, until address wraps (i.e. see shadow)
> +		for (i = 9; i < 14; i++) {
> +			chk = CFG_SYS_SDRAM_BASE + (1U << i);
> +			ptr = CFG_SYS_SDRAM_BASE;
> +			for (j = 0; j < 64; j++) {
> +				if (readl(chk) != ((j & 1) ? ptr : ~ptr))
> +					break;
> +				ptr += 4;
> +				chk += 4;
> +			}
> +			if (j == 64)
> +				break;
> +		}
> +		if (i > 13)
> +			i = 13;
> +
> +		unsigned int pgsize = (i == 9) ? 0 : (1 << (i - 10));
> +		debug("rank %d page size = %d KB\n", rank, pgsize);
> +
> +		/* Store page size */
> +		shft = offs;
> +		rval = config->dram_para1;
> +		rval &= ~(0xf << shft);
> +		rval |= pgsize << shft;
> +		config->dram_para1 = rval;
> +
> +		// Move to next rank
> +		rank++;
> +		if (rank != maxrank) {
> +			if (rank == 1) {
> +				/* MC_WORK_MODE */
> +				clrsetbits_le32(0x3202000, 0xffc, 0x6f0);
> +
> +				/* MC_WORK_MODE2 */
> +				clrsetbits_le32(0x3202004, 0xffc, 0x6f0);
> +			}
> +			/* store rank1 config in upper half of para1 */
> +			offs += 16;
> +			mc_work_mode += 4;	/* move to MC_WORK_MODE2 */
> +		}
> +	}
> +	if (maxrank == 2) {
> +		config->dram_para2 &= 0xfffff0ff;
> +		/* note: rval is equal to para->dram_para1 here */
> +		if ((rval & 0xffff) == (rval >> 16)) {
> +			debug("rank1 config same as rank0\n");
> +		} else {
> +			config->dram_para2 |= BIT(8);
> +			debug("rank1 config different from rank0\n");
> +		}
> +	}
> +
> +	return 1;
> +}
> [...]
> +static int sunxi_ram_probe(struct udevice *dev)
> +{
> +	struct sunxi_ram_priv *priv = dev_get_priv(dev);
> +	unsigned long dram_size;
> +
> +	debug("%s: %s: probing\n", __func__, dev->name);
> +
> +	dram_size = sunxi_dram_init();
> +	if (!dram_size) {
> +		printf("DRAM init failed: %d\n", ret);

There is no ret variable anymore, so this fails to compile. With this
line and the variable size issue fixed, this driver works on my Nezha
board, so with those fixes:

Tested-by: Samuel Holland <samuel@sholland.org>

> +		return -ENODEV;
> +	}
> +
> +	priv->size = dram_size;
> +
> +	return 0;
> +}


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 16/22] sunxi: add R528/T113-s3/D1(s) DRAM initialisation code
  2023-10-22  3:52   ` Samuel Holland
@ 2023-10-22 22:40     ` Andre Przywara
  2023-10-23  2:58       ` Samuel Holland
  0 siblings, 1 reply; 43+ messages in thread
From: Andre Przywara @ 2023-10-22 22:40 UTC (permalink / raw)
  To: Samuel Holland
  Cc: Jernej Skrabec, Icenowy Zheng, Maxim Kiselev, Sam Edwards,
	Okhunjon Sobirjonov, linux-sunxi, andre.przywara, Jagan Teki,
	u-boot

On Sat, 21 Oct 2023 22:52:06 -0500
Samuel Holland <samuel@sholland.org> wrote:

Hi Samuel,

> On 9/28/23 16:54, Andre Przywara wrote:
> > The Allwinner R528/T113-s/D1/D1s SoCs all share the same die, so use the
> > same DRAM initialisation code.
> > Make use of prior art here and lift some code from awboot[1], which
> > carried init code based on earlier decompilation efforts, but with a
> > GPL2 license tag.
> > This code has been heavily reworked and cleaned up, to match previous
> > DRAM routines for other SoCs, and also to be closer to U-Boot's coding
> > style and support routines.
> > The actual DRAM chip timing parameters are included in the main file,
> > since they cover all DRAM types, and are protected by a new Kconfig
> > CONFIG_SUNXI_DRAM_TYPE symbol, which allows the compiler to pick only
> > the relevant settings, at build time.
> > 
> > The relevant DRAM chips/board specific configuration parameters are
> > delivered via Kconfig, so this code here should work for all supported
> > SoCs and DRAM chips combinations.
> > 
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > Tested-by: Sam Edwards <CFSworks@gmail.com>
> > ---
> >  drivers/Makefile                   |    1 +
> >  drivers/ram/Makefile               |    3 +
> >  drivers/ram/sunxi/Kconfig          |   59 ++
> >  drivers/ram/sunxi/Makefile         |    4 +
> >  drivers/ram/sunxi/dram_sun20i_d1.c | 1432 ++++++++++++++++++++++++++++
> >  drivers/ram/sunxi/dram_sun20i_d1.h |   73 ++
> >  6 files changed, 1572 insertions(+)
> >  create mode 100644 drivers/ram/sunxi/Makefile
> >  create mode 100644 drivers/ram/sunxi/dram_sun20i_d1.c
> >  create mode 100644 drivers/ram/sunxi/dram_sun20i_d1.h
> > 
> > diff --git a/drivers/Makefile b/drivers/Makefile
> > index efc2a4afb24..5a4bedf7305 100644
> > --- a/drivers/Makefile
> > +++ b/drivers/Makefile
> > @@ -56,6 +56,7 @@ obj-$(CONFIG_$(SPL_)ALTERA_SDRAM) += ddr/altera/
> >  obj-$(CONFIG_ARCH_IMX8M) += ddr/imx/imx8m/
> >  obj-$(CONFIG_IMX8ULP_DRAM) += ddr/imx/imx8ulp/
> >  obj-$(CONFIG_ARCH_IMX9) += ddr/imx/imx9/
> > +obj-$(CONFIG_DRAM_SUN8I_R528) += ram/  
> 
> This would need to be duplicated for DRAM_SUN20I_D1.
> 
> >  obj-$(CONFIG_SPL_DM_RESET) += reset/
> >  obj-$(CONFIG_SPL_MUSB_NEW) += usb/musb-new/
> >  obj-$(CONFIG_SPL_USB_GADGET) += usb/gadget/
> > diff --git a/drivers/ram/Makefile b/drivers/ram/Makefile
> > index 6eb1a241359..b4750ea11c4 100644
> > --- a/drivers/ram/Makefile
> > +++ b/drivers/ram/Makefile
> > @@ -23,6 +23,9 @@ obj-$(CONFIG_RAM_SIFIVE) += sifive/
> >  ifdef CONFIG_SPL_BUILD
> >  obj-$(CONFIG_SPL_STARFIVE_DDR) += starfive/
> >  endif
> > +
> > +obj-$(CONFIG_DRAM_SUN8I_R528) += sunxi/  
> 
> This would need to be duplicated for DRAM_SUN20I_D1.

Right, so I joined both symbols into one now. I think I wanted to keep
the DM_RAM and non-DM parts logically apart, but it works nevertheless.

My gut feeling is this needs more adjustments anyway once we need the
DM_RAM or want to extend it to more SoCs, so we can fix things when
they need fixing, later.

> 
> > +
> >  obj-$(CONFIG_ARCH_OCTEON) += octeon/
> >  
> >  obj-$(CONFIG_ARCH_RMOBILE) += renesas/
> > diff --git a/drivers/ram/sunxi/Kconfig b/drivers/ram/sunxi/Kconfig
> > index 261d7f57409..35eeda58efa 100644
> > --- a/drivers/ram/sunxi/Kconfig
> > +++ b/drivers/ram/sunxi/Kconfig
> > @@ -12,3 +12,62 @@ config DRAM_SUN8I_R528
> >  	default y if MACH_SUN8I_R528
> >  	help
> >  	  Select this DRAM controller driver for the R528/T113s SoCs.
> > +
> > +if DRAM_SUN20I_D1 || DRAM_SUN8I_R528
> > +
> > +config DRAM_SUNXI_ODT_EN  
> 
> You have a mixture of "DRAM_SUNXI" and "SUNXI_DRAM" for the tunables
> here. I would recommend being consistent.

This was chosen to stay consistent with the existing DRAM drivers,
which use DRAM_SUNxx_ for parameters, but SUNXI_DRAM_TYPE_ for the type
selection. I was looking into moving the other Allwinner DRAM drivers
into here as well (at least for every future SoC), and tested this with
the H616: keeping the symbols compatible was a requirement.

> 
> > +	hex "DRAM ODT EN parameter"
> > +	default 0x1
> > +	help
> > +	  ODT EN value from vendor DRAM settings.
> > +
> > +config DRAM_SUNXI_TPR0
> > +	hex "DRAM TPR0 parameter"
> > +	default 0x0
> > +	help
> > +	  TPR0 value from vendor DRAM settings.
> > +
> > +config DRAM_SUNXI_TPR11
> > +	hex "DRAM TPR11 parameter"
> > +	default 0x0
> > +	help
> > +	  TPR11 value from vendor DRAM settings.
> > +
> > +config DRAM_SUNXI_TPR12
> > +	hex "DRAM TPR12 parameter"
> > +	default 0x0
> > +	help
> > +	  TPR12 value from vendor DRAM settings.
> > +
> > +config DRAM_SUNXI_TPR13
> > +	hex "DRAM TPR13 parameter"
> > +	default 0x0  
> 
> I would suggest dropping the defaults for these tunables. It was
> non-obvious that I was missing some configuration when I switched to
> your driver. I think it's reasonable to require the defconfig/user to
> provide these.

Yeah, that's a good point. No actual value is 0, so this doesn't even
simplify defconfigs.

> > +	help
> > +	  TPR13 value from vendor DRAM settings. It tells which features
> > +	  should be configured.
> > +
> > +choice
> > +	prompt "DRAM chip type"
> > +	default SUNXI_DRAM_TYPE_DDR3 if DRAM_SUN8I_R528 || DRAM_SUN20I_D1
> > +
> > +config SUNXI_DRAM_TYPE_DDR2
> > +        bool "DDR2 chips"
> > +
> > +config SUNXI_DRAM_TYPE_DDR3
> > +        bool "DDR3 chips"
> > +
> > +config SUNXI_DRAM_TYPE_LPDDR2
> > +        bool "LPDDR2 chips"
> > +
> > +config SUNXI_DRAM_TYPE_LPDDR3
> > +        bool "LPDDR3 chips"
> > +endchoice
> > +
> > +config SUNXI_DRAM_TYPE
> > +	int
> > +	default 2 if SUNXI_DRAM_TYPE_DDR2
> > +	default 3 if SUNXI_DRAM_TYPE_DDR3
> > +	default 6 if SUNXI_DRAM_TYPE_LPDDR2
> > +	default 7 if SUNXI_DRAM_TYPE_LPDDR3
> > +
> > +endif
> > diff --git a/drivers/ram/sunxi/Makefile b/drivers/ram/sunxi/Makefile
> > new file mode 100644
> > index 00000000000..d6fb2cf0b65
> > --- /dev/null
> > +++ b/drivers/ram/sunxi/Makefile
> > @@ -0,0 +1,4 @@
> > +# SPDX-License-Identifier: GPL-2.0+
> > +
> > +obj-$(CONFIG_DRAM_SUN20I_D1) += dram_sun20i_d1.o
> > +obj-$(CONFIG_DRAM_SUN8I_R528) += dram_sun20i_d1.o
> > diff --git a/drivers/ram/sunxi/dram_sun20i_d1.c b/drivers/ram/sunxi/dram_sun20i_d1.c
> > new file mode 100644
> > index 00000000000..c766fc24065
> > --- /dev/null
> > +++ b/drivers/ram/sunxi/dram_sun20i_d1.c
> > @@ -0,0 +1,1432 @@
> > [...]
> > +/*
> > + * This routine sizes a DRAM device by cycling through address lines and
> > + * figuring out if they are connected to a real address line, or if the
> > + * address is a mirror.
> > + * First the column and bank bit allocations are set to low values (2 and 9
> > + * address lines). Then a maximum allocation (16 lines) is set for rows and
> > + * this is tested.
> > + * Next the BA2 line is checked. This seems to be placed above the column,
> > + * BA0-1 and row addresses. Finally, the column address is allocated 13 lines
> > + * and these are tested. The results are placed in dram_para1 and dram_para2.
> > + */
> > +static int auto_scan_dram_size(const dram_para_t *para, dram_config_t *config)
> > +{
> > +	unsigned int rval, i, j, rank, maxrank, offs;
> > +	unsigned int shft;
> > +	unsigned long ptr, mc_work_mode, chk;  
> 
> This breaks on 64-bit architectures, because readl(chk) can never equal
> ~ptr. Please change ptr and chk to unsigned int.

I think they were originally ints (at least I see it like this is an
earlier version), but I changed it to make "ptr" a pointer compatible
type.
Definitely "chk" is only used as a pointer, so should be long (or
uintptr_t).
The actual problem is that "ptr" is used both as a pointer *and* a
payload, which is odd. I will keep ptr long, but make sure to
write only a true 32 bit payload into the address it points to.

> 
> > +
> > +	if (mctl_core_init(para, config) == 0) {
> > +		printf("DRAM initialisation error : 0\n");
> > +		return 0;
> > +	}
> > +
> > +	maxrank	= (config->dram_para2 & 0xf000) ? 2 : 1;
> > +	mc_work_mode = 0x3102000;
> > +	offs = 0;
> > +
> > +	/* write test pattern */
> > +	for (i = 0, ptr = CFG_SYS_SDRAM_BASE; i < 64; i++, ptr += 4)
> > +		writel((i & 0x1) ? ptr : ~ptr, ptr);
> > +
> > +	for (rank = 0; rank < maxrank;) {
> > +		/* set row mode */
> > +		clrsetbits_le32(mc_work_mode, 0xf0c, 0x6f0);
> > +		udelay(1);
> > +
> > +		// Scan per address line, until address wraps (i.e. see shadow)
> > +		for (i = 11; i < 17; i++) {
> > +			chk = CFG_SYS_SDRAM_BASE + (1U << (i + 11));
> > +			ptr = CFG_SYS_SDRAM_BASE;
> > +			for (j = 0; j < 64; j++) {
> > +				if (readl(chk) != ((j & 1) ? ptr : ~ptr))
> > +					break;
> > +				ptr += 4;
> > +				chk += 4;
> > +			}
> > +			if (j == 64)
> > +				break;
> > +		}
> > +		if (i > 16)
> > +			i = 16;
> > +		debug("rank %d row = %d\n", rank, i);
> > +
> > +		/* Store rows in para 1 */
> > +		shft = offs + 4;
> > +		rval = config->dram_para1;
> > +		rval &= ~(0xff << shft);
> > +		rval |= i << shft;
> > +		config->dram_para1 = rval;
> > +
> > +		if (rank == 1)		/* Set bank mode for rank0 */
> > +			clrsetbits_le32(0x3102000, 0xffc, 0x6a4);
> > +
> > +		/* Set bank mode for current rank */
> > +		clrsetbits_le32(mc_work_mode, 0xffc, 0x6a4);
> > +		udelay(1);
> > +
> > +		// Test if bit A23 is BA2 or mirror XXX A22?
> > +		chk = CFG_SYS_SDRAM_BASE + (1U << 22);
> > +		ptr = CFG_SYS_SDRAM_BASE;
> > +		for (i = 0, j = 0; i < 64; i++) {
> > +			if (readl(chk) != ((i & 1) ? ptr : ~ptr)) {
> > +				j = 1;
> > +				break;
> > +			}
> > +			ptr += 4;
> > +			chk += 4;
> > +		}
> > +
> > +		debug("rank %d bank = %d\n", rank, (j + 1) << 2); /* 4 or 8 */
> > +
> > +		/* Store banks in para 1 */
> > +		shft = 12 + offs;
> > +		rval = config->dram_para1;
> > +		rval &= ~(0xf << shft);
> > +		rval |= j << shft;
> > +		config->dram_para1 = rval;
> > +
> > +		if (rank == 1)		/* Set page mode for rank0 */
> > +			clrsetbits_le32(0x3102000, 0xffc, 0xaa0);
> > +
> > +		/* Set page mode for current rank */
> > +		clrsetbits_le32(mc_work_mode, 0xffc, 0xaa0);
> > +		udelay(1);
> > +
> > +		// Scan per address line, until address wraps (i.e. see shadow)
> > +		for (i = 9; i < 14; i++) {
> > +			chk = CFG_SYS_SDRAM_BASE + (1U << i);
> > +			ptr = CFG_SYS_SDRAM_BASE;
> > +			for (j = 0; j < 64; j++) {
> > +				if (readl(chk) != ((j & 1) ? ptr : ~ptr))
> > +					break;
> > +				ptr += 4;
> > +				chk += 4;
> > +			}
> > +			if (j == 64)
> > +				break;
> > +		}
> > +		if (i > 13)
> > +			i = 13;
> > +
> > +		unsigned int pgsize = (i == 9) ? 0 : (1 << (i - 10));
> > +		debug("rank %d page size = %d KB\n", rank, pgsize);
> > +
> > +		/* Store page size */
> > +		shft = offs;
> > +		rval = config->dram_para1;
> > +		rval &= ~(0xf << shft);
> > +		rval |= pgsize << shft;
> > +		config->dram_para1 = rval;
> > +
> > +		// Move to next rank
> > +		rank++;
> > +		if (rank != maxrank) {
> > +			if (rank == 1) {
> > +				/* MC_WORK_MODE */
> > +				clrsetbits_le32(0x3202000, 0xffc, 0x6f0);
> > +
> > +				/* MC_WORK_MODE2 */
> > +				clrsetbits_le32(0x3202004, 0xffc, 0x6f0);
> > +			}
> > +			/* store rank1 config in upper half of para1 */
> > +			offs += 16;
> > +			mc_work_mode += 4;	/* move to MC_WORK_MODE2 */
> > +		}
> > +	}
> > +	if (maxrank == 2) {
> > +		config->dram_para2 &= 0xfffff0ff;
> > +		/* note: rval is equal to para->dram_para1 here */
> > +		if ((rval & 0xffff) == (rval >> 16)) {
> > +			debug("rank1 config same as rank0\n");
> > +		} else {
> > +			config->dram_para2 |= BIT(8);
> > +			debug("rank1 config different from rank0\n");
> > +		}
> > +	}
> > +
> > +	return 1;
> > +}
> > [...]
> > +static int sunxi_ram_probe(struct udevice *dev)
> > +{
> > +	struct sunxi_ram_priv *priv = dev_get_priv(dev);
> > +	unsigned long dram_size;
> > +
> > +	debug("%s: %s: probing\n", __func__, dev->name);
> > +
> > +	dram_size = sunxi_dram_init();
> > +	if (!dram_size) {
> > +		printf("DRAM init failed: %d\n", ret);  
> 
> There is no ret variable anymore, so this fails to compile. With this
> line and the variable size issue fixed, this driver works on my Nezha
> board, so with those fixes:

Ah, right, thanks for the heads up. I think I had some trick to compile
test this code once, but didn't use it since last year.

> Tested-by: Samuel Holland <samuel@sholland.org>

Thanks!
Andre

P.S. This driver has a lot of rough edges anyway (the whole
clock/"system" setup side, for a start), but we should get things
moving now, before the RFC version celebrates its first birthday. So I
will merge it, but am happy to take fixes: either cleanups, or fixes
for the D1.

> > +		return -ENODEV;
> > +	}
> > +
> > +	priv->size = dram_size;
> > +
> > +	return 0;
> > +}  
> 


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 16/22] sunxi: add R528/T113-s3/D1(s) DRAM initialisation code
  2023-10-22 22:40     ` Andre Przywara
@ 2023-10-23  2:58       ` Samuel Holland
  0 siblings, 0 replies; 43+ messages in thread
From: Samuel Holland @ 2023-10-23  2:58 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Jernej Skrabec, Icenowy Zheng, Maxim Kiselev, Sam Edwards,
	Okhunjon Sobirjonov, linux-sunxi, andre.przywara, Jagan Teki,
	u-boot

Hi Andre,

On 10/22/23 17:40, Andre Przywara wrote:
> On Sat, 21 Oct 2023 22:52:06 -0500
> Samuel Holland <samuel@sholland.org> wrote:
>> On 9/28/23 16:54, Andre Przywara wrote:
>>> The Allwinner R528/T113-s/D1/D1s SoCs all share the same die, so use the
>>> same DRAM initialisation code.
>>> Make use of prior art here and lift some code from awboot[1], which
>>> carried init code based on earlier decompilation efforts, but with a
>>> GPL2 license tag.
>>> This code has been heavily reworked and cleaned up, to match previous
>>> DRAM routines for other SoCs, and also to be closer to U-Boot's coding
>>> style and support routines.
>>> The actual DRAM chip timing parameters are included in the main file,
>>> since they cover all DRAM types, and are protected by a new Kconfig
>>> CONFIG_SUNXI_DRAM_TYPE symbol, which allows the compiler to pick only
>>> the relevant settings, at build time.
>>>
>>> The relevant DRAM chips/board specific configuration parameters are
>>> delivered via Kconfig, so this code here should work for all supported
>>> SoCs and DRAM chips combinations.
>>>
>>> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
>>> Tested-by: Sam Edwards <CFSworks@gmail.com>
>>> ---
>>>  drivers/Makefile                   |    1 +
>>>  drivers/ram/Makefile               |    3 +
>>>  drivers/ram/sunxi/Kconfig          |   59 ++
>>>  drivers/ram/sunxi/Makefile         |    4 +
>>>  drivers/ram/sunxi/dram_sun20i_d1.c | 1432 ++++++++++++++++++++++++++++
>>>  drivers/ram/sunxi/dram_sun20i_d1.h |   73 ++
>>>  6 files changed, 1572 insertions(+)
>>>  create mode 100644 drivers/ram/sunxi/Makefile
>>>  create mode 100644 drivers/ram/sunxi/dram_sun20i_d1.c
>>>  create mode 100644 drivers/ram/sunxi/dram_sun20i_d1.h
>>>
>>> diff --git a/drivers/Makefile b/drivers/Makefile
>>> index efc2a4afb24..5a4bedf7305 100644
>>> --- a/drivers/Makefile
>>> +++ b/drivers/Makefile
>>> @@ -56,6 +56,7 @@ obj-$(CONFIG_$(SPL_)ALTERA_SDRAM) += ddr/altera/
>>>  obj-$(CONFIG_ARCH_IMX8M) += ddr/imx/imx8m/
>>>  obj-$(CONFIG_IMX8ULP_DRAM) += ddr/imx/imx8ulp/
>>>  obj-$(CONFIG_ARCH_IMX9) += ddr/imx/imx9/
>>> +obj-$(CONFIG_DRAM_SUN8I_R528) += ram/  
>>
>> This would need to be duplicated for DRAM_SUN20I_D1.
>>
>>>  obj-$(CONFIG_SPL_DM_RESET) += reset/
>>>  obj-$(CONFIG_SPL_MUSB_NEW) += usb/musb-new/
>>>  obj-$(CONFIG_SPL_USB_GADGET) += usb/gadget/
>>> diff --git a/drivers/ram/Makefile b/drivers/ram/Makefile
>>> index 6eb1a241359..b4750ea11c4 100644
>>> --- a/drivers/ram/Makefile
>>> +++ b/drivers/ram/Makefile
>>> @@ -23,6 +23,9 @@ obj-$(CONFIG_RAM_SIFIVE) += sifive/
>>>  ifdef CONFIG_SPL_BUILD
>>>  obj-$(CONFIG_SPL_STARFIVE_DDR) += starfive/
>>>  endif
>>> +
>>> +obj-$(CONFIG_DRAM_SUN8I_R528) += sunxi/  
>>
>> This would need to be duplicated for DRAM_SUN20I_D1.
> 
> Right, so I joined both symbols into one now. I think I wanted to keep
> the DM_RAM and non-DM parts logically apart, but it works nevertheless.
> 
> My gut feeling is this needs more adjustments anyway once we need the
> DM_RAM or want to extend it to more SoCs, so we can fix things when
> they need fixing, later.
> 
>>
>>> +
>>>  obj-$(CONFIG_ARCH_OCTEON) += octeon/
>>>  
>>>  obj-$(CONFIG_ARCH_RMOBILE) += renesas/
>>> diff --git a/drivers/ram/sunxi/Kconfig b/drivers/ram/sunxi/Kconfig
>>> index 261d7f57409..35eeda58efa 100644
>>> --- a/drivers/ram/sunxi/Kconfig
>>> +++ b/drivers/ram/sunxi/Kconfig
>>> @@ -12,3 +12,62 @@ config DRAM_SUN8I_R528
>>>  	default y if MACH_SUN8I_R528
>>>  	help
>>>  	  Select this DRAM controller driver for the R528/T113s SoCs.
>>> +
>>> +if DRAM_SUN20I_D1 || DRAM_SUN8I_R528
>>> +
>>> +config DRAM_SUNXI_ODT_EN  
>>
>> You have a mixture of "DRAM_SUNXI" and "SUNXI_DRAM" for the tunables
>> here. I would recommend being consistent.
> 
> This was chosen to stay consistent with the existing DRAM drivers,
> which use DRAM_SUNxx_ for parameters, but SUNXI_DRAM_TYPE_ for the type
> selection. I was looking into moving the other Allwinner DRAM drivers
> into here as well (at least for every future SoC), and tested this with
> the H616: keeping the symbols compatible was a requirement.

Okay, that's fair. We can always revisit this later.

>>> +	hex "DRAM ODT EN parameter"
>>> +	default 0x1
>>> +	help
>>> +	  ODT EN value from vendor DRAM settings.
>>> +
>>> +config DRAM_SUNXI_TPR0
>>> +	hex "DRAM TPR0 parameter"
>>> +	default 0x0
>>> +	help
>>> +	  TPR0 value from vendor DRAM settings.
>>> +
>>> +config DRAM_SUNXI_TPR11
>>> +	hex "DRAM TPR11 parameter"
>>> +	default 0x0
>>> +	help
>>> +	  TPR11 value from vendor DRAM settings.
>>> +
>>> +config DRAM_SUNXI_TPR12
>>> +	hex "DRAM TPR12 parameter"
>>> +	default 0x0
>>> +	help
>>> +	  TPR12 value from vendor DRAM settings.
>>> +
>>> +config DRAM_SUNXI_TPR13
>>> +	hex "DRAM TPR13 parameter"
>>> +	default 0x0  
>>
>> I would suggest dropping the defaults for these tunables. It was
>> non-obvious that I was missing some configuration when I switched to
>> your driver. I think it's reasonable to require the defconfig/user to
>> provide these.
> 
> Yeah, that's a good point. No actual value is 0, so this doesn't even
> simplify defconfigs.
> 
>>> +	help
>>> +	  TPR13 value from vendor DRAM settings. It tells which features
>>> +	  should be configured.
>>> +
>>> +choice
>>> +	prompt "DRAM chip type"
>>> +	default SUNXI_DRAM_TYPE_DDR3 if DRAM_SUN8I_R528 || DRAM_SUN20I_D1
>>> +
>>> +config SUNXI_DRAM_TYPE_DDR2
>>> +        bool "DDR2 chips"
>>> +
>>> +config SUNXI_DRAM_TYPE_DDR3
>>> +        bool "DDR3 chips"
>>> +
>>> +config SUNXI_DRAM_TYPE_LPDDR2
>>> +        bool "LPDDR2 chips"
>>> +
>>> +config SUNXI_DRAM_TYPE_LPDDR3
>>> +        bool "LPDDR3 chips"
>>> +endchoice
>>> +
>>> +config SUNXI_DRAM_TYPE
>>> +	int
>>> +	default 2 if SUNXI_DRAM_TYPE_DDR2
>>> +	default 3 if SUNXI_DRAM_TYPE_DDR3
>>> +	default 6 if SUNXI_DRAM_TYPE_LPDDR2
>>> +	default 7 if SUNXI_DRAM_TYPE_LPDDR3
>>> +
>>> +endif
>>> diff --git a/drivers/ram/sunxi/Makefile b/drivers/ram/sunxi/Makefile
>>> new file mode 100644
>>> index 00000000000..d6fb2cf0b65
>>> --- /dev/null
>>> +++ b/drivers/ram/sunxi/Makefile
>>> @@ -0,0 +1,4 @@
>>> +# SPDX-License-Identifier: GPL-2.0+
>>> +
>>> +obj-$(CONFIG_DRAM_SUN20I_D1) += dram_sun20i_d1.o
>>> +obj-$(CONFIG_DRAM_SUN8I_R528) += dram_sun20i_d1.o
>>> diff --git a/drivers/ram/sunxi/dram_sun20i_d1.c b/drivers/ram/sunxi/dram_sun20i_d1.c
>>> new file mode 100644
>>> index 00000000000..c766fc24065
>>> --- /dev/null
>>> +++ b/drivers/ram/sunxi/dram_sun20i_d1.c
>>> @@ -0,0 +1,1432 @@
>>> [...]
>>> +/*
>>> + * This routine sizes a DRAM device by cycling through address lines and
>>> + * figuring out if they are connected to a real address line, or if the
>>> + * address is a mirror.
>>> + * First the column and bank bit allocations are set to low values (2 and 9
>>> + * address lines). Then a maximum allocation (16 lines) is set for rows and
>>> + * this is tested.
>>> + * Next the BA2 line is checked. This seems to be placed above the column,
>>> + * BA0-1 and row addresses. Finally, the column address is allocated 13 lines
>>> + * and these are tested. The results are placed in dram_para1 and dram_para2.
>>> + */
>>> +static int auto_scan_dram_size(const dram_para_t *para, dram_config_t *config)
>>> +{
>>> +	unsigned int rval, i, j, rank, maxrank, offs;
>>> +	unsigned int shft;
>>> +	unsigned long ptr, mc_work_mode, chk;  
>>
>> This breaks on 64-bit architectures, because readl(chk) can never equal
>> ~ptr. Please change ptr and chk to unsigned int.
> 
> I think they were originally ints (at least I see it like this is an
> earlier version), but I changed it to make "ptr" a pointer compatible
> type.
> Definitely "chk" is only used as a pointer, so should be long (or
> uintptr_t).
> The actual problem is that "ptr" is used both as a pointer *and* a
> payload, which is odd. I will keep ptr long, but make sure to
> write only a true 32 bit payload into the address it points to.

The problem isn't in the writing, it's in the "~ptr" expression in the
if statement -- readl(chk) will always have zero in its high 32 bits,
while ~ptr will set the high 32 bits. So a cast after the inversion
would also fix the problem.

>>> +
>>> +	if (mctl_core_init(para, config) == 0) {
>>> +		printf("DRAM initialisation error : 0\n");
>>> +		return 0;
>>> +	}
>>> +
>>> +	maxrank	= (config->dram_para2 & 0xf000) ? 2 : 1;
>>> +	mc_work_mode = 0x3102000;
>>> +	offs = 0;
>>> +
>>> +	/* write test pattern */
>>> +	for (i = 0, ptr = CFG_SYS_SDRAM_BASE; i < 64; i++, ptr += 4)
>>> +		writel((i & 0x1) ? ptr : ~ptr, ptr);
>>> +
>>> +	for (rank = 0; rank < maxrank;) {
>>> +		/* set row mode */
>>> +		clrsetbits_le32(mc_work_mode, 0xf0c, 0x6f0);
>>> +		udelay(1);
>>> +
>>> +		// Scan per address line, until address wraps (i.e. see shadow)
>>> +		for (i = 11; i < 17; i++) {
>>> +			chk = CFG_SYS_SDRAM_BASE + (1U << (i + 11));
>>> +			ptr = CFG_SYS_SDRAM_BASE;
>>> +			for (j = 0; j < 64; j++) {
>>> +				if (readl(chk) != ((j & 1) ? ptr : ~ptr))
>>> +					break;
>>> +				ptr += 4;
>>> +				chk += 4;
>>> +			}
>>> +			if (j == 64)
>>> +				break;
>>> +		}
>>> +		if (i > 16)
>>> +			i = 16;
>>> +		debug("rank %d row = %d\n", rank, i);
>>> +
>>> +		/* Store rows in para 1 */
>>> +		shft = offs + 4;
>>> +		rval = config->dram_para1;
>>> +		rval &= ~(0xff << shft);
>>> +		rval |= i << shft;
>>> +		config->dram_para1 = rval;
>>> +
>>> +		if (rank == 1)		/* Set bank mode for rank0 */
>>> +			clrsetbits_le32(0x3102000, 0xffc, 0x6a4);
>>> +
>>> +		/* Set bank mode for current rank */
>>> +		clrsetbits_le32(mc_work_mode, 0xffc, 0x6a4);
>>> +		udelay(1);
>>> +
>>> +		// Test if bit A23 is BA2 or mirror XXX A22?
>>> +		chk = CFG_SYS_SDRAM_BASE + (1U << 22);
>>> +		ptr = CFG_SYS_SDRAM_BASE;
>>> +		for (i = 0, j = 0; i < 64; i++) {
>>> +			if (readl(chk) != ((i & 1) ? ptr : ~ptr)) {
>>> +				j = 1;
>>> +				break;
>>> +			}
>>> +			ptr += 4;
>>> +			chk += 4;
>>> +		}
>>> +
>>> +		debug("rank %d bank = %d\n", rank, (j + 1) << 2); /* 4 or 8 */
>>> +
>>> +		/* Store banks in para 1 */
>>> +		shft = 12 + offs;
>>> +		rval = config->dram_para1;
>>> +		rval &= ~(0xf << shft);
>>> +		rval |= j << shft;
>>> +		config->dram_para1 = rval;
>>> +
>>> +		if (rank == 1)		/* Set page mode for rank0 */
>>> +			clrsetbits_le32(0x3102000, 0xffc, 0xaa0);
>>> +
>>> +		/* Set page mode for current rank */
>>> +		clrsetbits_le32(mc_work_mode, 0xffc, 0xaa0);
>>> +		udelay(1);
>>> +
>>> +		// Scan per address line, until address wraps (i.e. see shadow)
>>> +		for (i = 9; i < 14; i++) {
>>> +			chk = CFG_SYS_SDRAM_BASE + (1U << i);
>>> +			ptr = CFG_SYS_SDRAM_BASE;
>>> +			for (j = 0; j < 64; j++) {
>>> +				if (readl(chk) != ((j & 1) ? ptr : ~ptr))
>>> +					break;
>>> +				ptr += 4;
>>> +				chk += 4;
>>> +			}
>>> +			if (j == 64)
>>> +				break;
>>> +		}
>>> +		if (i > 13)
>>> +			i = 13;
>>> +
>>> +		unsigned int pgsize = (i == 9) ? 0 : (1 << (i - 10));
>>> +		debug("rank %d page size = %d KB\n", rank, pgsize);
>>> +
>>> +		/* Store page size */
>>> +		shft = offs;
>>> +		rval = config->dram_para1;
>>> +		rval &= ~(0xf << shft);
>>> +		rval |= pgsize << shft;
>>> +		config->dram_para1 = rval;
>>> +
>>> +		// Move to next rank
>>> +		rank++;
>>> +		if (rank != maxrank) {
>>> +			if (rank == 1) {
>>> +				/* MC_WORK_MODE */
>>> +				clrsetbits_le32(0x3202000, 0xffc, 0x6f0);
>>> +
>>> +				/* MC_WORK_MODE2 */
>>> +				clrsetbits_le32(0x3202004, 0xffc, 0x6f0);
>>> +			}
>>> +			/* store rank1 config in upper half of para1 */
>>> +			offs += 16;
>>> +			mc_work_mode += 4;	/* move to MC_WORK_MODE2 */
>>> +		}
>>> +	}
>>> +	if (maxrank == 2) {
>>> +		config->dram_para2 &= 0xfffff0ff;
>>> +		/* note: rval is equal to para->dram_para1 here */
>>> +		if ((rval & 0xffff) == (rval >> 16)) {
>>> +			debug("rank1 config same as rank0\n");
>>> +		} else {
>>> +			config->dram_para2 |= BIT(8);
>>> +			debug("rank1 config different from rank0\n");
>>> +		}
>>> +	}
>>> +
>>> +	return 1;
>>> +}
>>> [...]
>>> +static int sunxi_ram_probe(struct udevice *dev)
>>> +{
>>> +	struct sunxi_ram_priv *priv = dev_get_priv(dev);
>>> +	unsigned long dram_size;
>>> +
>>> +	debug("%s: %s: probing\n", __func__, dev->name);
>>> +
>>> +	dram_size = sunxi_dram_init();
>>> +	if (!dram_size) {
>>> +		printf("DRAM init failed: %d\n", ret);  
>>
>> There is no ret variable anymore, so this fails to compile. With this
>> line and the variable size issue fixed, this driver works on my Nezha
>> board, so with those fixes:
> 
> Ah, right, thanks for the heads up. I think I had some trick to compile
> test this code once, but didn't use it since last year.
> 
>> Tested-by: Samuel Holland <samuel@sholland.org>
> 
> Thanks!
> Andre
> 
> P.S. This driver has a lot of rough edges anyway (the whole
> clock/"system" setup side, for a start), but we should get things
> moving now, before the RFC version celebrates its first birthday. So I
> will merge it, but am happy to take fixes: either cleanups, or fixes
> for the D1.

Right, I'm fine with sending any fixes needed for D1 as follow-up. I'm
quite glad that we now have one version of the code that works on all
chip variants.

Regards,
Samuel


^ permalink raw reply	[flat|nested] 43+ messages in thread

end of thread, other threads:[~2023-10-23  2:58 UTC | newest]

Thread overview: 43+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
2023-09-28 21:54 ` [PATCH v2 01/22] sunxi: remove CONFIG_SATAPWR Andre Przywara
2023-10-19 23:51   ` Samuel Holland
2023-10-21 23:27     ` Andre Przywara
2023-10-22  3:34       ` Samuel Holland
2023-09-28 21:54 ` [PATCH v2 02/22] net: sunxi_emac: chase DT nodes to find PHY regulator Andre Przywara
2023-10-20  0:01   ` Samuel Holland
2023-10-21 23:33     ` Andre Przywara
2023-09-28 21:54 ` [PATCH v2 03/22] sunxi: remove CONFIG_MACPWR Andre Przywara
2023-10-21  4:35   ` Samuel Holland
2023-09-28 21:54 ` [PATCH v2 04/22] pinctrl: sunxi: move pinctrl code Andre Przywara
2023-10-19  0:18   ` Andre Przywara
2023-10-21  8:21   ` Samuel Holland
2023-09-28 21:54 ` [PATCH v2 05/22] pinctrl: sunxi: add GPIO in/out wrappers Andre Przywara
2023-10-21  8:30   ` Samuel Holland
2023-10-21 23:46     ` Andre Przywara
2023-09-28 21:54 ` [PATCH v2 06/22] pinctrl: sunxi: remove struct sunxi_gpio Andre Przywara
2023-10-21  8:37   ` Samuel Holland
2023-09-28 21:54 ` [PATCH v2 07/22] pinctrl: sunxi: remove GPIO_EXTRA_HEADER Andre Przywara
2023-10-21  8:57   ` Samuel Holland
2023-09-28 21:54 ` [PATCH v2 08/22] pinctrl: sunxi: move PIO_BASE into sunxi_gpio.h Andre Przywara
2023-09-28 21:54 ` [PATCH v2 09/22] pinctrl: sunxi: add new D1 pinctrl support Andre Przywara
2023-10-22  3:31   ` Samuel Holland
2023-09-28 21:54 ` [PATCH v2 10/22] sunxi: introduce NCAT2 generation model Andre Przywara
2023-10-22  3:40   ` Samuel Holland
2023-09-28 21:54 ` [PATCH v2 11/22] pinctrl: sunxi: add Allwinner D1 pinctrl description Andre Przywara
2023-10-21  4:34   ` Samuel Holland
2023-09-28 21:54 ` [PATCH v2 12/22] clk: sunxi: Add support for the D1 CCU Andre Przywara
2023-10-19 23:53   ` Samuel Holland
2023-09-28 21:54 ` [PATCH v2 13/22] sunxi: clock: D1/R528: Enable PLL LDO during PLL1 setup Andre Przywara
2023-09-28 21:54 ` [PATCH v2 14/22] sunxi: clock: support D1/R528 PLL6 clock Andre Przywara
2023-09-28 21:54 ` [PATCH v2 15/22] Kconfig: sunxi: prepare for using drivers/ram/sunxi Andre Przywara
2023-10-22  3:44   ` Samuel Holland
2023-09-28 21:54 ` [PATCH v2 16/22] sunxi: add R528/T113-s3/D1(s) DRAM initialisation code Andre Przywara
2023-10-22  3:52   ` Samuel Holland
2023-10-22 22:40     ` Andre Przywara
2023-10-23  2:58       ` Samuel Holland
2023-09-28 21:54 ` [PATCH v2 17/22] sunxi: add Allwinner R528/T113 SoC support Andre Przywara
2023-09-28 21:54 ` [PATCH v2 18/22] sunxi: R528: add SMHC2 pin pull ups support Andre Przywara
2023-09-28 21:54 ` [PATCH v2 19/22] sunxi: refactor serial base addresses to avoid asm/arch/cpu.h Andre Przywara
2023-09-28 21:54 ` [PATCH v2 20/22] riscv: dts: allwinner: Add the D1/D1s SoC devicetree Andre Przywara
2023-09-28 21:54 ` [PATCH v2 21/22] ARM: dts: sunxi: add Allwinner T113-s SoC .dtsi Andre Przywara
2023-09-28 21:54 ` [PATCH v2 22/22] sunxi: add MangoPi MQ-R board support Andre Przywara

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.