[PATCH] armv7: ls102xa: Enable I-Cache to speed up the boot time

2021-02-04 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Enable the I-Cache to speed up the boot time, especailly for the NOR
boot, currently it takes about 15 seconds from power up to the U-Boot
prompt, and with the I-Cache enabled it only takes around 2.5 seconds.

Signed-off-by: Hou Zhiqiang 
---
 arch/arm/cpu/armv7/ls102xa/cpu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/cpu/armv7/ls102xa/cpu.c b/arch/arm/cpu/armv7/ls102xa/cpu.c
index ce472aa9bd..c6a39aa341 100644
--- a/arch/arm/cpu/armv7/ls102xa/cpu.c
+++ b/arch/arm/cpu/armv7/ls102xa/cpu.c
@@ -316,6 +316,8 @@ int arch_cpu_init(void)
struct ccsr_scfg *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
u32 state;
 
+   icache_enable();
+
/*
 * The RCPM FSM state may not be reset after power-on.
 * So, reset them.
-- 
2.17.1



Re: [PATCH] mmc: fsl_esdhc_imx: use VENDORSPEC_FRC_SDCLK_ON to control card clock output

2021-02-04 Thread Jaehoon Chung
Hi all,


On 2/5/21 4:23 PM, Bough Chen wrote:
>> -Original Message-
>> From: ZHIZHIKIN Andrey [mailto:andrey.zhizhi...@leica-geosystems.com]
>> Sent: 2021年2月1日 19:41
>> To: Bough Chen ; Peng Fan ;
>> u-boot@lists.denx.de
>> Cc: dl-uboot-imx ; thar...@gateworks.com
>> Subject: RE: [PATCH] mmc: fsl_esdhc_imx: use VENDORSPEC_FRC_SDCLK_ON
>> to control card clock output
>>
>> Hello Haibo,
>>
>>> -Original Message-
>>> From: Bough Chen 
>>> Sent: Monday, February 1, 2021 11:10 AM
>>> To: ZHIZHIKIN Andrey ; Peng Fan
>>> ; u-boot@lists.denx.de
>>> Cc: dl-uboot-imx ; thar...@gateworks.com
>>> Subject: RE: [PATCH] mmc: fsl_esdhc_imx: use
>> VENDORSPEC_FRC_SDCLK_ON
>>> to control card clock output
>>>
 -Original Message-
 From: ZHIZHIKIN Andrey
 [mailto:andrey.zhizhi...@leica-geosystems.com]
 Sent: 2021年2月1日 17:52
 To: Bough Chen ; Peng Fan ;
 u-boot@lists.denx.de
 Cc: dl-uboot-imx ; thar...@gateworks.com
 Subject: RE: [PATCH] mmc: fsl_esdhc_imx: use
>> VENDORSPEC_FRC_SDCLK_ON
 to control card clock output

 Hello Haibo,

> -Original Message-
> From: haibo.c...@nxp.com 
> Sent: Wednesday, January 27, 2021 11:47 AM
> To: peng@nxp.com; u-boot@lists.denx.de
> Cc: haibo.c...@nxp.com; uboot-...@nxp.com;
>> thar...@gateworks.com;
> ZHIZHIKIN Andrey 
> Subject: [PATCH] mmc: fsl_esdhc_imx: use VENDORSPEC_FRC_SDCLK_ON
> to control card clock output
>
> From: Haibo Chen 
>
> For FSL_USDHC, it do not implement
 VENDORSPEC_CKEN/PEREN/HCKEN/IPGEN,
> these are reserved bits. Instead, use VENDORSPEC_FRC_SDCLK_ON to
> gate on/off the card clock output.
>
> After commit b5874b552ffa ("mmc: fsl_esdhc_imx: add wait_dat0()
> support"), we meet SD3.0 card can't work at UHS mode,
> mmc_switch_voltage() fail because the second mmc_wait_dat0 return
> -ETIMEDOUT. According to SD spec, during voltage switch, need to
> gate off/on the card clock. If not set the FRC_SDCLK_ON, after
> CMD11, hardware will gate off the card clock automatically, so
> card do not detect the clock off/on behavior, so will draw the
> data0 line low until next
 command.
>
> Fixes: b5874b552ffa ("mmc: fsl_esdhc_imx: add wait_dat0()
> support")

 This patch does not fix the switch of uSDHC to 1v8...

 I've applied it locally on the imx8mmevk, and had following log
 during the boot when tried to query SD Card info:
 ---
 U-Boot SPL 2021.01-01004-gb852007333 (Feb 01 2021 - 09:45:42 +0100)
 Normal Boot
 WDT:   Started with servicing (60s timeout)
 Trying to boot from MMC1
 NOTICE:  BL31: v2.2(release):rel_imx_5.4.70_2.3.0-0-gf1d7187f2
 NOTICE:  BL31: Built : 22:29:05, Jan 17 2021


 U-Boot 2021.01-01004-gb852007333 (Feb 01 2021 - 09:45:42 +0100)

 CPU:   Freescale i.MX8MMQ rev1.0 at 1200 MHz
 Reset cause: POR
 Model: FSL i.MX8MM EVK board
 DRAM:  2 GiB
 WDT:   Started with servicing (60s timeout)
 MMC:   FSL_SDHC: 1, FSL_SDHC: 2
 Loading Environment from MMC... Run CMD11 1.8V switch Card did not
 respond to voltage select! : -110
>>>
>>> This do not align with my test result. Can you help identify which
>>> function first return the timeout on your side?
>>
>> I would have a look at the exact function, but it seems to me that it would 
>> be
>> wait_dat0() since if I revert the patch introducing it - high speed mode 
>> switch is
>> not timing out.
>>
>>> Or can you try a different SD card?
>>
>> It is rather strange, it seems like it is dependent on the SD Card used.
>>
>> So far, I've tried 3 SD Cards I had on hands, one of which being operable:
>> == Working:
>> "Transcend 32GB"
>> Manufacturer ID: 74
>> OEM: 4a60
>> Name: USDU1
>>
>> == Failed:
>> 1. (Kingston 32GB)
>> Manufacturer ID: 41
>> OEM: 3432
>> Name: SD32G
>>
>> 2. (Intenso 32 GB)
>> Manufacturer ID: 9f
>> OEM: 5449
>> Name: 0
>>
> 
> Hi Andrey,
> 
> With this patch, can you also add the following change to test again, I 
> double check the code logic, only the following code do not follow the SD 
> spec for voltage switch.
> Seems the two failed SD cards follow the sd voltage spec strictly.
> 
> diff --git a/drivers/mmc/fsl_esdhc_imx.c b/drivers/mmc/fsl_esdhc_imx.c
> index da33ee8253..20337b0ed4 100644
> --- a/drivers/mmc/fsl_esdhc_imx.c
> +++ b/drivers/mmc/fsl_esdhc_imx.c
> @@ -513,7 +513,7 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv 
> *priv, struct mmc *mmc,
> err = -ETIMEDOUT;
> goto out;
> }
> -
> +#if 0
> /* Switch voltage to 1.8V if CMD11 succeeded */
> if (cmd->cmdidx == SD_CMD_SWITCH_UHS18V) {
> esdhc_setbits32(>vendorspec, ESDHC_VENDORSPEC_VSELECT);
> @@ -522,6 +522,7 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv 
> *priv, struct mmc *mmc,
> /* Sleep 

Re: [RFC PATCH 05/13] mux: Inline mux functions when CONFIG_MUX is disabled

2021-02-04 Thread Pratyush Yadav
On 04/02/21 11:39PM, Sean Anderson wrote:
> This prevents multiple-definition errors.
> 
> Fixes: 0ad40b2463 ("drivers: Add a new framework for multiplexer devices")
> 
> Signed-off-by: Sean Anderson 

Reviewed-by: Pratyush Yadav 

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.


RE: [PATCH] mmc: fsl_esdhc_imx: use VENDORSPEC_FRC_SDCLK_ON to control card clock output

2021-02-04 Thread Bough Chen
> -Original Message-
> From: ZHIZHIKIN Andrey [mailto:andrey.zhizhi...@leica-geosystems.com]
> Sent: 2021年2月1日 19:41
> To: Bough Chen ; Peng Fan ;
> u-boot@lists.denx.de
> Cc: dl-uboot-imx ; thar...@gateworks.com
> Subject: RE: [PATCH] mmc: fsl_esdhc_imx: use VENDORSPEC_FRC_SDCLK_ON
> to control card clock output
> 
> Hello Haibo,
> 
> > -Original Message-
> > From: Bough Chen 
> > Sent: Monday, February 1, 2021 11:10 AM
> > To: ZHIZHIKIN Andrey ; Peng Fan
> > ; u-boot@lists.denx.de
> > Cc: dl-uboot-imx ; thar...@gateworks.com
> > Subject: RE: [PATCH] mmc: fsl_esdhc_imx: use
> VENDORSPEC_FRC_SDCLK_ON
> > to control card clock output
> >
> > > -Original Message-
> > > From: ZHIZHIKIN Andrey
> > > [mailto:andrey.zhizhi...@leica-geosystems.com]
> > > Sent: 2021年2月1日 17:52
> > > To: Bough Chen ; Peng Fan ;
> > > u-boot@lists.denx.de
> > > Cc: dl-uboot-imx ; thar...@gateworks.com
> > > Subject: RE: [PATCH] mmc: fsl_esdhc_imx: use
> VENDORSPEC_FRC_SDCLK_ON
> > > to control card clock output
> > >
> > > Hello Haibo,
> > >
> > > > -Original Message-
> > > > From: haibo.c...@nxp.com 
> > > > Sent: Wednesday, January 27, 2021 11:47 AM
> > > > To: peng@nxp.com; u-boot@lists.denx.de
> > > > Cc: haibo.c...@nxp.com; uboot-...@nxp.com;
> thar...@gateworks.com;
> > > > ZHIZHIKIN Andrey 
> > > > Subject: [PATCH] mmc: fsl_esdhc_imx: use VENDORSPEC_FRC_SDCLK_ON
> > > > to control card clock output
> > > >
> > > > From: Haibo Chen 
> > > >
> > > > For FSL_USDHC, it do not implement
> > > VENDORSPEC_CKEN/PEREN/HCKEN/IPGEN,
> > > > these are reserved bits. Instead, use VENDORSPEC_FRC_SDCLK_ON to
> > > > gate on/off the card clock output.
> > > >
> > > > After commit b5874b552ffa ("mmc: fsl_esdhc_imx: add wait_dat0()
> > > > support"), we meet SD3.0 card can't work at UHS mode,
> > > > mmc_switch_voltage() fail because the second mmc_wait_dat0 return
> > > > -ETIMEDOUT. According to SD spec, during voltage switch, need to
> > > > gate off/on the card clock. If not set the FRC_SDCLK_ON, after
> > > > CMD11, hardware will gate off the card clock automatically, so
> > > > card do not detect the clock off/on behavior, so will draw the
> > > > data0 line low until next
> > > command.
> > > >
> > > > Fixes: b5874b552ffa ("mmc: fsl_esdhc_imx: add wait_dat0()
> > > > support")
> > >
> > > This patch does not fix the switch of uSDHC to 1v8...
> > >
> > > I've applied it locally on the imx8mmevk, and had following log
> > > during the boot when tried to query SD Card info:
> > > ---
> > > U-Boot SPL 2021.01-01004-gb852007333 (Feb 01 2021 - 09:45:42 +0100)
> > > Normal Boot
> > > WDT:   Started with servicing (60s timeout)
> > > Trying to boot from MMC1
> > > NOTICE:  BL31: v2.2(release):rel_imx_5.4.70_2.3.0-0-gf1d7187f2
> > > NOTICE:  BL31: Built : 22:29:05, Jan 17 2021
> > >
> > >
> > > U-Boot 2021.01-01004-gb852007333 (Feb 01 2021 - 09:45:42 +0100)
> > >
> > > CPU:   Freescale i.MX8MMQ rev1.0 at 1200 MHz
> > > Reset cause: POR
> > > Model: FSL i.MX8MM EVK board
> > > DRAM:  2 GiB
> > > WDT:   Started with servicing (60s timeout)
> > > MMC:   FSL_SDHC: 1, FSL_SDHC: 2
> > > Loading Environment from MMC... Run CMD11 1.8V switch Card did not
> > > respond to voltage select! : -110
> >
> > This do not align with my test result. Can you help identify which
> > function first return the timeout on your side?
> 
> I would have a look at the exact function, but it seems to me that it would be
> wait_dat0() since if I revert the patch introducing it - high speed mode 
> switch is
> not timing out.
> 
> > Or can you try a different SD card?
> 
> It is rather strange, it seems like it is dependent on the SD Card used.
> 
> So far, I've tried 3 SD Cards I had on hands, one of which being operable:
> == Working:
> "Transcend 32GB"
> Manufacturer ID: 74
> OEM: 4a60
> Name: USDU1
> 
> == Failed:
> 1. (Kingston 32GB)
> Manufacturer ID: 41
> OEM: 3432
> Name: SD32G
> 
> 2. (Intenso 32 GB)
> Manufacturer ID: 9f
> OEM: 5449
> Name: 0
> 

Hi Andrey,

With this patch, can you also add the following change to test again, I double 
check the code logic, only the following code do not follow the SD spec for 
voltage switch.
Seems the two failed SD cards follow the sd voltage spec strictly.

diff --git a/drivers/mmc/fsl_esdhc_imx.c b/drivers/mmc/fsl_esdhc_imx.c
index da33ee8253..20337b0ed4 100644
--- a/drivers/mmc/fsl_esdhc_imx.c
+++ b/drivers/mmc/fsl_esdhc_imx.c
@@ -513,7 +513,7 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv 
*priv, struct mmc *mmc,
err = -ETIMEDOUT;
goto out;
}
-
+#if 0
/* Switch voltage to 1.8V if CMD11 succeeded */
if (cmd->cmdidx == SD_CMD_SWITCH_UHS18V) {
esdhc_setbits32(>vendorspec, ESDHC_VENDORSPEC_VSELECT);
@@ -522,6 +522,7 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv 
*priv, struct mmc *mmc,
/* Sleep for 5 ms - max time for card to switch to 

RE: [PATCH 2/2] ARM: imx6: mx6sabre-common: Search for boot components in /boot too

2021-02-04 Thread Peng Fan (OSS)
> Subject: [PATCH 2/2] ARM: imx6: mx6sabre-common: Search for boot
> components in /boot too
> 
> Some root filesystem configurations do not have separate /boot partition, but
> rather place kernel, DT, scripts into /boot directory. Search the /boot 
> directory
> for these boot components in case they are not found in /, which is the old
> behavior.
> 
> Signed-off-by: Marek Vasut 
> Cc: Fabio Estevam 
> Cc: Peng Fan 
> Cc: Stefano Babic 
> Cc: Ye Li 
> Cc: uboot-imx 

Reviewed-by: Peng Fan 

> ---
>  include/configs/mx6sabre_common.h | 9 ++---
>  1 file changed, 6 insertions(+), 3 deletions(-)
> 
> diff --git a/include/configs/mx6sabre_common.h
> b/include/configs/mx6sabre_common.h
> index 735532955fd..ac579f3338a 100644
> --- a/include/configs/mx6sabre_common.h
> +++ b/include/configs/mx6sabre_common.h
> @@ -73,11 +73,14 @@
>   "mmcargs=setenv bootargs console=${console},${baudrate} " \
>   "root=PARTUUID=${uuid} rootwait rw\0" \
>   "loadbootscript=" \
> - "load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};\0" \
> + "load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script} || " \
> + "load mmc ${mmcdev}:${mmcpart} ${loadaddr} boot/${script};\0" \
>   "bootscript=echo Running bootscript from mmc ...; " \
>   "source\0" \
> - "loadimage=load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}\0"
> \
> - "loadfdt=load mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdtfile}\0" \
> + "loadimage=load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image} ||
> " \
> + "load mmc ${mmcdev}:${mmcpart} ${loadaddr} boot/${image}\0" \
> + "loadfdt=load mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdtfile} || " \
> + "load mmc ${mmcdev}:${mmcpart} ${fdt_addr} boot/${fdtfile}\0" \
>   "mmcboot=echo Booting from mmc ...; " \
>   "run finduuid; " \
>   "run mmcargs; " \
> --
> 2.29.2



RE: [PATCH 1/2] ARM: imx6: mx6sabre-common: Replace fatload with FS_GENERIC load

2021-02-04 Thread Peng Fan (OSS)
> Subject: [PATCH 1/2] ARM: imx6: mx6sabre-common: Replace fatload with
> FS_GENERIC load
> 
> Replace filesystem specific fatload command with a filesystem agnostic load
> command, so the board can boot from e.g. ext4 too.
> 
> Signed-off-by: Marek Vasut 
> Cc: Fabio Estevam 
> Cc: Peng Fan 
> Cc: Stefano Babic 
> Cc: Ye Li 
> Cc: uboot-imx 

Reviewed-by: Peng Fan 

> ---
>  include/configs/mx6sabre_common.h | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/include/configs/mx6sabre_common.h
> b/include/configs/mx6sabre_common.h
> index 93d00a4dc3c..735532955fd 100644
> --- a/include/configs/mx6sabre_common.h
> +++ b/include/configs/mx6sabre_common.h
> @@ -73,11 +73,11 @@
>   "mmcargs=setenv bootargs console=${console},${baudrate} " \
>   "root=PARTUUID=${uuid} rootwait rw\0" \
>   "loadbootscript=" \
> - "fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};\0" \
> + "load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};\0" \
>   "bootscript=echo Running bootscript from mmc ...; " \
>   "source\0" \
> - "loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr}
> ${image}\0" \
> - "loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdtfile}\0" \
> + "loadimage=load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}\0"
> \
> + "loadfdt=load mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdtfile}\0" \
>   "mmcboot=echo Booting from mmc ...; " \
>   "run finduuid; " \
>   "run mmcargs; " \
> --
> 2.29.2



Re: [BUG]u-boot no boots from SD-card on NXP T2080RDB development board

2021-02-04 Thread Jaehoon Chung
On 2/5/21 7:59 AM, Jeff Hering wrote:
> The 2020.10 tagged build works on the T2080RDB card, however, all tags 
> starting with 2021.01-rc1 no long boot from SD-card on the development 
> system. This might also apply to other QorIQ development boards.
> 
> Here is a dump of the crash which occurs very early in the process (the left 
> column is a timestamp):
> 
> 00.000: .
> 00.409:
> 00.410: SD boot...
> 00.415: No max bus width provided. Assume 8-bit supported.

I'm not sure but it seems that bus-width is not correct.


> 03.972: MMC init failed
> 03.975: Initializingusing SPD
> 04.323: 2 GiB left unmapped
> 04.327: Bad trap at PC: 20, SR: 21200, vector=800
> 04.332: NIP:  XER:  LR:  REGS: 20 TRAP: 2000
> 04.334:  DAR: 
> 04.338: MSR: 00021200 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 00
> 04.338:
> 04.344: GPR00:       
>  
> 04.351: GPR08:       
>  
> 04.358: GPR16:       
>  
> 04.365: GPR24:       
>  
> 04.368: Call backtrace:
> 04.371: Exception in kernel pc 20 signal 0
> 04.375: ### ERROR ### Please RESET the board ###
> 
> 



RE: [PATCH v4 5/5] board/km: add support for seli8 design based on nxp ls102x

2021-02-04 Thread Aleksandar Gerasimovski
The SELI8 design is a new tdm service unit card for Hitachi-Powergrids
XMC and FOX product lines.

It is based on NXP LS1021 SoC and it provides following interfaces:
 - IFC interface for NOR, NAND and external FPGA's
 - 1 x RGMII ETH for debug purposes
 - 2 x SGMII ETH for management communication via back-plane
 - 1 x uQE HDLC for management communication via back-plane
 - 1 x I2C for peripheral devices
 - 1 x SPI for peripheral devices
 - 1 x UART for debug logging

It is foreseen that the design will be later re-used for another XMC and
FOX service cards with similar SoC requirements.

Signed-off-by: Rainer Boschung 
Signed-off-by: Matteo Ghidoni 
Signed-off-by: Aleksandar Gerasimovski 

---
Changes for v2:
 - fix patch subject to 60 characters
Changes for v3:
 - remove obsolete CMDLINE_TAG
Changes for v4:
 - rebase, include i2c deblocking from keymile/common.h
 - move Kconfig's from board.h to board defconfig
 - fix ENV_SIZE, it was typo or copy-paste error
---
---
 arch/arm/Kconfig|  19 ++
 arch/arm/dts/Makefile   |   2 +
 arch/arm/dts/ls1021a-pg-wcom-seli8.dts  | 111 +
 board/keymile/Kconfig   |  23 +-
 board/keymile/common/ivm.c  |  19 +-
 board/keymile/pg-wcom-ls102xa/Kconfig   |  19 ++
 board/keymile/pg-wcom-ls102xa/MAINTAINERS   |  10 +
 board/keymile/pg-wcom-ls102xa/Makefile  |  11 +
 board/keymile/pg-wcom-ls102xa/ddr.c |  90 +++
 board/keymile/pg-wcom-ls102xa/pg-wcom-ls102xa.c | 160 +
 configs/pg_wcom_seli8_defconfig |  65 ++
 include/configs/km/pg-wcom-ls102xa.h| 297 
 include/configs/pg-wcom-seli8.h |  45 
 13 files changed, 860 insertions(+), 11 deletions(-)
 create mode 100644 arch/arm/dts/ls1021a-pg-wcom-seli8.dts
 create mode 100644 board/keymile/pg-wcom-ls102xa/Kconfig
 create mode 100644 board/keymile/pg-wcom-ls102xa/MAINTAINERS
 create mode 100644 board/keymile/pg-wcom-ls102xa/Makefile
 create mode 100644 board/keymile/pg-wcom-ls102xa/ddr.c
 create mode 100644 board/keymile/pg-wcom-ls102xa/pg-wcom-ls102xa.c
 create mode 100644 configs/pg_wcom_seli8_defconfig
 create mode 100644 include/configs/km/pg-wcom-ls102xa.h
 create mode 100644 include/configs/pg-wcom-seli8.h

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 95557d6..729f1a3 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1517,6 +1517,24 @@ config TARGET_LS1021ATWR
select DM_SPI_FLASH if FSL_DSPI || FSL_QSPI
imply SCSI
 
+config TARGET_PG_WCOM_SELI8
+   bool "Support Hitachi-Powergrids SELI8 service unit card"
+   select ARCH_LS1021A
+   select ARCH_SUPPORT_PSCI
+   select BOARD_EARLY_INIT_F
+   select BOARD_LATE_INIT
+   select CPU_V7A
+   select CPU_V7_HAS_NONSEC
+   select CPU_V7_HAS_VIRT
+   select SYS_FSL_DDR
+   select FSL_DDR_INTERACTIVE
+   select VENDOR_KM
+   imply SCSI
+   help
+Support for Hitachi-Powergrids SELI8 service unit card.
+SELI8 is a QorIQ LS1021a based service unit card used
+in XMC20 and FOX615 product families.
+
 config TARGET_LS1021ATSN
bool "Support ls1021atsn"
select ARCH_LS1021A
@@ -2036,6 +2054,7 @@ source "board/variscite/dart_6ul/Kconfig"
 source "board/vscom/baltos/Kconfig"
 source "board/phytium/durian/Kconfig"
 source "board/xen/xenguest_arm64/Kconfig"
+source "board/keymile/Kconfig"
 
 source "arch/arm/Kconfig.debug"
 
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 858b79a..dbc71c0 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -399,6 +399,8 @@ dtb-$(CONFIG_ARCH_LS1021A) += ls1021a-qds-duart.dtb \
ls1021a-qds-lpuart.dtb \
ls1021a-twr-duart.dtb ls1021a-twr-lpuart.dtb \
ls1021a-iot-duart.dtb ls1021a-tsn.dtb
+dtb-$(CONFIG_TARGET_PG_WCOM_SELI8) += ls1021a-pg-wcom-seli8.dtb
+
 dtb-$(CONFIG_FSL_LSCH3) += fsl-ls2080a-qds.dtb \
fsl-ls2080a-qds-42-x.dtb \
fsl-ls2080a-rdb.dtb \
diff --git a/arch/arm/dts/ls1021a-pg-wcom-seli8.dts 
b/arch/arm/dts/ls1021a-pg-wcom-seli8.dts
new file mode 100644
index 000..e335188
--- /dev/null
+++ b/arch/arm/dts/ls1021a-pg-wcom-seli8.dts
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2013-2015 Freescale Semiconductor, Inc.
+ * Copyright 2020 Hitachi Power Grids. All rights reserved.
+ */
+
+/dts-v1/;
+#include "ls1021a.dtsi"
+
+/ {
+   model = "Hitachi-Powergrids SELI8 Service Unit for XMC and FOX";
+
+   chosen {
+   stdout-path = 
+   };
+};
+
+ {
+   status = "okay";
+   tbi-handle = <>;
+   phy-connection-type = "sgmii";
+   fixed-link {
+   speed = <1000>;
+   full-duplex;
+   };
+};
+
+ {
+   status = "okay";
+   tbi-handle = <>;
+   phy-connection-type = "sgmii";
+   fixed-link {
+   speed = <1000>;
+

[PATCH 4/5] board/km: move km i2c deblock declarations to a km/common.h

2021-02-04 Thread Aleksandar Gerasimovski
Cleanup, move the declarations to keymile/common.h instead declaring them
per-board config.h

Signed-off-by: Aleksandar Gerasimovski 

---
 board/keymile/common/common.h | 5 +
 include/configs/km/km_arm.h   | 4 
 include/configs/kmp204x.h | 6 --
 3 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/board/keymile/common/common.h b/board/keymile/common/common.h
index 8251de4..15a3c37 100644
--- a/board/keymile/common/common.h
+++ b/board/keymile/common/common.h
@@ -136,6 +136,11 @@ int set_km_env(void);
 #define DELAY_ABORT_SEQ62  /* @200kHz 9 clocks = 44us, 62us is 
ok */
 #define DELAY_HALF_PERIOD  (500 / (CONFIG_SYS_I2C_SPEED / 1000))
 
+void set_sda(int state);
+void set_scl(int state);
+int get_sda(void);
+int get_scl(void);
+
 int i2c_soft_read_pin(void);
 int i2c_make_abort(void);
 #endif /* __KEYMILE_COMMON_H */
diff --git a/include/configs/km/km_arm.h b/include/configs/km/km_arm.h
index 29060fa..4115906 100644
--- a/include/configs/km/km_arm.h
+++ b/include/configs/km/km_arm.h
@@ -110,10 +110,6 @@
 #include 
 #include 
 extern void __set_direction(unsigned pin, int high);
-void set_sda(int state);
-void set_scl(int state);
-int get_sda(void);
-int get_scl(void);
 #define KM_KIRKWOOD_SDA_PIN8
 #define KM_KIRKWOOD_SCL_PIN9
 #define KM_KIRKWOOD_SOFT_I2C_GPIOS 0x0300
diff --git a/include/configs/kmp204x.h b/include/configs/kmp204x.h
index d1eb7b5..90e3702 100644
--- a/include/configs/kmp204x.h
+++ b/include/configs/kmp204x.h
@@ -237,12 +237,6 @@ unsigned long get_board_sys_clk(unsigned long dummy);
{0, {{I2C_MUX_PCA9547, 0x70, 1 } } }, \
{0, {{I2C_MUX_PCA9547, 0x70, 2 } } }, \
}
-#ifndef __ASSEMBLY__
-void set_sda(int state);
-void set_scl(int state);
-int get_sda(void);
-int get_scl(void);
-#endif
 
 #define CONFIG_KM_IVM_BUS  1   /* I2C1 (Mux-Port 1)*/
 
-- 
1.8.3.1


[GIT PULL] TI changes for v2021.04 rc2

2021-02-04 Thread Lokesh Vutla
Hi Tom,
Please find the PR for master branch targeted for v2021.04-rc2 release.
Details about the PR are updated in the tag message.

Gitlab build report: 
https://gitlab.denx.de/u-boot/custodians/u-boot-ti/-/pipelines/6214

The following changes since commit fdcb93e1709ab1a2ebb562455621617c29e2099c:

  Merge branch '2021-02-01-assorted-fixes' (2021-02-02 09:24:10 -0500)

are available in the Git repository at:

  https://gitlab.denx.de/u-boot/custodians/u-boot-ti.git tags/ti-v2021.04-rc2

for you to fetch changes up to 6239cc8c4e8484d908afc555eb59441a16a58b53:

  arm: dts: k3-j7200: Sync Linux v5.11-rc6 dts into U-Boot (2021-02-04 20:37:57 
+0530)


- Sync DTS from Linux kernel for all K3 platforms
- Add MMC higher speed nodes for AM65x, J721e, J7200
- Convert Nokia RX-51 to use CONFIG_DM_MMC
- Minor fixes for LEGO MINDSTORMS


Aswath Govindraju (1):
  configs: am65x_evm_a53: Enable config for phandle check while getting
sequence number

Dario Binacchi (1):
  configs: am335x_evm: enable CONFIG_SPL_ALLOC_BD

David Lechner (4):
  ARM: legoev3: set serial# env var
  ARM: legoev3: drop bi_arch_number
  configs: legoev3: disable CONFIG_NET
  configs: legoev3: disable non-Linux boot options

Faiz Abbas (20):
  mmc: sdhci: Add helper functions for UHS modes
  mmc: am654_sdhci: Unconditionally switch off DLL in the beginning of
ios_post()
  mmc: am654_sdhci: Convert flag fields to BIT macro
  mmc: am654_sdhci: Add flag for PHY calibration
  mmc: am654_sdhci: Add support for AM65x SR2.0
  mmc: am654_sdhci: Add support for input tap delay
  mmc: am654_sdhci: Add support for writing to clkbuf_sel
  mmc: am654_sdhci: Add support for software tuning
  mmc: am654_sdhci: Fix HISPD bit configuration in some lower speed
modes
  mmc: am654_sdhci: Use sdhci_set_control_reg()
  arm: dts: k3-am65: Fix mmc nodes
  arm: dts: k3-j721e-main: Update otap-delay values
  arm: dts: k3-j721e-common-proc-board: Add support for UHS modes for SD
card
  arm: dts: k3-j7200-main: Add support for gpio0
  arm: dts: k3-j7200-common-proc-board: Enable support for UHS modes
  configs: j721e_evm: Add support for UHS modes
  configs: j7200_evm: Add support for UHS modes
  arm: dts: k3-am65-main: Add itapdly and clkbuf-sel values
  arm: dts: k3-am654-base-board: Limit Sd card to High speed modes
  configs: am65x_evm: Add configs for UHS modes

Lokesh Vutla (3):
  arm: dts: k3-am65: Sync Linux v5.11-rc6 dts into U-Boot
  arm: dts: k3-j721e: Sync Linux v5.11-rc6 dts into U-Boot
  arm: dts: k3-j7200: Sync Linux v5.11-rc6 dts into U-Boot

Pali Rohár (1):
  Nokia RX-51: Convert to CONFIG_DM_MMC

Suman Anna (1):
  remoteproc: k3_r5: Sync to upstreamed kernel DT property names

 arch/arm/dts/k3-am65-main.dtsi|  823 +++--
 arch/arm/dts/k3-am65-mcu.dtsi |  221 ++-
 arch/arm/dts/k3-am65-wakeup.dtsi  |   48 +-
 arch/arm/dts/k3-am65.dtsi |   10 +-
 arch/arm/dts/k3-am654-base-board-u-boot.dtsi  |  132 +-
 arch/arm/dts/k3-am654-base-board.dts  |  449 -
 arch/arm/dts/k3-am654-industrial-thermal.dtsi |   45 +
 arch/arm/dts/k3-am654-r5-base-board.dts   |   58 +-
 arch/arm/dts/k3-am654.dtsi|   10 +-
 .../k3-j7200-common-proc-board-u-boot.dtsi|   16 +-
 arch/arm/dts/k3-j7200-common-proc-board.dts   |  161 +-
 arch/arm/dts/k3-j7200-main.dtsi   |  289 +++-
 arch/arm/dts/k3-j7200-mcu-wakeup.dtsi |  244 +--
 .../arm/dts/k3-j7200-r5-common-proc-board.dts |   15 +
 arch/arm/dts/k3-j7200-som-p0.dtsi |  107 +-
 arch/arm/dts/k3-j7200.dtsi|   27 +-
 .../k3-j721e-common-proc-board-u-boot.dtsi|   70 +-
 arch/arm/dts/k3-j721e-common-proc-board.dts   |  673 +++-
 arch/arm/dts/k3-j721e-main.dtsi   | 1484 +++--
 arch/arm/dts/k3-j721e-mcu-wakeup.dtsi |  234 ++-
 .../k3-j721e-r5-common-proc-board-u-boot.dtsi |9 +
 .../arm/dts/k3-j721e-r5-common-proc-board.dts |2 -
 arch/arm/dts/k3-j721e-som-p0.dtsi |  272 ++-
 arch/arm/dts/k3-j721e.dtsi|   29 +-
 board/lego/ev3/legoev3.c  |   89 +-
 board/nokia/rx51/rx51.c   |   33 +-
 configs/am335x_evm_defconfig  |1 +
 configs/am65x_evm_a53_defconfig   |9 +
 configs/am65x_evm_r5_defconfig|2 +
 configs/j7200_evm_a72_defconfig   |8 +
 configs/j7200_evm_r5_defconfig|1 +
 configs/j721e_evm_a72_defconfig   |8 +
 configs/j721e_evm_r5_defconfig|1 +
 configs/legoev3_defconfig |8 +-
 configs/nokia_rx51_defconfig  |6 +
 .../remoteproc/ti,k3-r5f-rproc.txt|   26 +-
 drivers/mmc/Kconfig   |1 +
 drivers/mmc/am654_sdhci.c   

Re: [PATCH v2] fastboot: add UUU command UCmd and ACmd support

2021-02-04 Thread Heiko Schocher
Hi Lukasz,

Am 05.02.21 um 00:17 schrieb Lukasz Majewski:
> Hi Heiko,
> 
>> add support for the UUU commands ACmd and UCmd.
>>
>> Enable them through the Kconfig option
>> CONFIG_FASTBOOT_UUU_SUPPORT
>>
>> base was commit in NXP kernel
>> 9b149c2a2882: ("MLK-18591-3 android: Add FSL android fastboot
>> support")
>>
>> and ported it to current mainline. Tested this patch
>> on imx6ul based board.
>>
>> Signed-off-by: Heiko Schocher 
>> ---
>>
>> Changes in v2:
>> - remove unused FSL_FASTBOOT option
>> - add comment from Roman:
>>   do not enable this option per default
>>   add Kconfig comment that enabling this option may
>>   introduce a security issue.
> 
> Could you fix this patch to be applicable on top of:
> 
> https://github.com/lmajewski/u-boot-dfu/commits/testing

sent v3, which is based on above branch

bye,
Heiko
-- 
DENX Software Engineering GmbH,  Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: h...@denx.de


[PATCH v3] fastboot: add UUU command UCmd and ACmd support

2021-02-04 Thread Heiko Schocher
add support for the UUU commands ACmd and UCmd.

Enable them through the Kconfig option
CONFIG_FASTBOOT_UUU_SUPPORT

base was commit in NXP kernel
9b149c2a2882: ("MLK-18591-3 android: Add FSL android fastboot support")

and ported it to current mainline. Tested this patch
on imx6ul based board.

Signed-off-by: Heiko Schocher 
---

Changes in v3:
- rebased to https://github.com/lmajewski/u-boot-dfu/commits/testing
  as Lukasz mentioned.

Changes in v2:
- remove unused FSL_FASTBOOT option
- add comment from Roman:
  do not enable this option per default
  add Kconfig comment that enabling this option may
  introduce a security issue.

 doc/android/fastboot-protocol.rst |  5 +++
 doc/android/fastboot.rst  |  2 ++
 drivers/fastboot/Kconfig  |  9 +
 drivers/fastboot/fb_command.c | 60 +++
 drivers/usb/gadget/f_fastboot.c   | 17 +
 include/fastboot.h|  6 
 6 files changed, 99 insertions(+)

diff --git a/doc/android/fastboot-protocol.rst 
b/doc/android/fastboot-protocol.rst
index e723659e49c..e8cbd7f24ea 100644
--- a/doc/android/fastboot-protocol.rst
+++ b/doc/android/fastboot-protocol.rst
@@ -144,6 +144,11 @@ Command Reference
 
   "powerdown"  Power off the device.
 
+  "ucmd"   execute any bootloader command and wait until it
+   finishs.
+
+  "acmd"   execute any bootloader command, do not wait.
+
 Client Variables
 
 
diff --git a/doc/android/fastboot.rst b/doc/android/fastboot.rst
index ce513a2a0f2..7611f07038e 100644
--- a/doc/android/fastboot.rst
+++ b/doc/android/fastboot.rst
@@ -19,6 +19,8 @@ The current implementation supports the following standard 
commands:
 - ``reboot``
 - ``reboot-bootloader``
 - ``set_active`` (only a stub implementation which always succeeds)
+- ``ucmd`` (if enabled)
+- ``acmd`` (if enabled)
 
 The following OEM commands are supported (if enabled):
 
diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig
index a17e488714d..2d1836a80e0 100644
--- a/drivers/fastboot/Kconfig
+++ b/drivers/fastboot/Kconfig
@@ -72,6 +72,15 @@ config FASTBOOT_FLASH
  the downloaded image to a non-volatile storage device. Define
  this to enable the "fastboot flash" command.
 
+config FASTBOOT_UUU_SUPPORT
+   bool "Enable FASTBOOT i.MX UUU special command"
+   default n
+   help
+ The fastboot protocol includes "UCmd" and "ACmd" command.
+ Be aware that you provide full access to any U-Boot command,
+ including working with memory and may open a huge backdoor,
+ when enabling this option.
+
 choice
prompt "Flash provider for FASTBOOT"
depends on FASTBOOT_FLASH
diff --git a/drivers/fastboot/fb_command.c b/drivers/fastboot/fb_command.c
index 41fc8d7904d..e22006057ef 100644
--- a/drivers/fastboot/fb_command.c
+++ b/drivers/fastboot/fb_command.c
@@ -49,6 +49,11 @@ static void oem_partconf(char *, char *);
 static void oem_bootbus(char *, char *);
 #endif
 
+#if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT)
+static void run_ucmd(char *, char *);
+static void run_acmd(char *, char *);
+#endif
+
 static const struct {
const char *command;
void (*dispatch)(char *cmd_parameter, char *response);
@@ -115,6 +120,14 @@ static const struct {
[FASTBOOT_COMMAND_OEM_BOOTBUS] = {
.command = "oem bootbus",
.dispatch = oem_bootbus,
+#if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT)
+   [FASTBOOT_COMMAND_UCMD] = {
+   .command = "UCmd",
+   .dispatch = run_ucmd,
+   },
+   [FASTBOOT_COMMAND_ACMD] = {
+   .command = "ACmd",
+   .dispatch = run_acmd,
},
 #endif
 };
@@ -327,6 +340,53 @@ static void erase(char *cmd_parameter, char *response)
 }
 #endif
 
+#if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT)
+/**
+ * run_ucmd() - Execute the UCmd command
+ *
+ * @cmd_parameter: Pointer to command parameter
+ * @response: Pointer to fastboot response buffer
+ */
+static void run_ucmd(char *cmd_parameter, char *response)
+{
+   if (!cmd_parameter) {
+   pr_err("missing slot suffix\n");
+   fastboot_fail("missing command", response);
+   return;
+   }
+
+   if (run_command(cmd_parameter, 0))
+   fastboot_fail("", response);
+   else
+   fastboot_okay(NULL, response);
+}
+
+static char g_a_cmd_buff[64];
+
+void fastboot_acmd_complete(void)
+{
+   run_command(g_a_cmd_buff, 0);
+}
+
+/**
+ * run_acmd() - Execute the ACmd command
+ *
+ * @cmd_parameter: Pointer to command parameter
+ * @response: Pointer to fastboot response buffer
+ */
+static void run_acmd(char *cmd_parameter, char *response)
+{
+   if (!cmd_parameter) {
+   pr_err("missing slot suffix\n");
+   fastboot_fail("missing command", response);
+   return;
+   }
+
+   strcpy(g_a_cmd_buff, cmd_parameter);
+   

Re: [RFC PATCH 00/13] spi: dw: Add support for XIP mode

2021-02-04 Thread Sean Anderson

On 2/4/21 11:39 PM, Sean Anderson wrote:

This adds support for memory-mapped ("DIRMAP") reads (called XIP by the
datasheet). In theory, these have better performance than regular reads. In
practice, the CPU is already fast enough to max out the performance of this
peripheral.

The real end-goal is to be able to boot a XIP kernel. This SoC has just barely
enough SRAM to boot Linux, and using a XIP kernel would decrease the memory
pressure to something tolerable. It would also probably absolutely *tank* the
performance, since not only is SPI flash ~8x slower than regular memory, there
is no cache to mitigate that latency. So it remains to be seen whether this is
worth it at all.

This series is RFC because it currently reads all 1s on one board I have. On the
other board I have, it reads and writes fine. I will try and investigate this,
but I expect any changes to occur in "spi: dw: Add support for DIRMAP".


Forgot to mention, but this series depends on [1]. A git branch with
this complete series is available at [2].

[1] https://patchwork.ozlabs.org/project/uboot/list/?series=228123
[2] https://github.com/Forty-Bot/u-boot/tree/maix_xip



Sean Anderson (13):
   linux err: Synchronize with Linux 5.10
   spi-mem: Add dirmap API from Linux
   mtd: spi-nor: use spi-mem dirmap API
   core: ofnode: Fix inconsistent returns of *_read_u32_array
   mux: Inline mux functions when CONFIG_MUX is disabled
   mux: Define a stub for mux_get_by_index if CONFIG_MUX is disabled
   mux: mmio: Only complain about idle-states if it is malformed
   spi: dw: Define XIP registers
   spi: dw: Add XIP and XIP_CONCURRENT caps
   spi: dw: Use a mux to access registers
   spi: dw: Add support for DIRMAP
   riscv: k210: Increase SPI3 bus clock to CPU speed
   riscv: k210: Add bindings for SPI XIP

  arch/riscv/dts/k210.dtsi   |  25 ++-
  drivers/core/ofnode.c  |  15 +-
  drivers/mtd/spi/sf_probe.c |  79 
  drivers/mtd/spi/spi-nor-core.c |  45 +++--
  drivers/mux/mmio.c |   5 +-
  drivers/spi/Kconfig|  10 +
  drivers/spi/designware_spi.c   | 337 +++--
  drivers/spi/spi-mem.c  | 270 ++
  include/linux/err.h|  21 +-
  include/linux/mtd/spi-nor.h|   6 +
  include/mux.h  |  25 ++-
  include/spi-mem.h  |  99 ++
  12 files changed, 889 insertions(+), 48 deletions(-)





[RFC PATCH 11/13] spi: dw: Add support for DIRMAP

2021-02-04 Thread Sean Anderson
This adds support for XIP mode. It is not actually any faster than QPI
(yet), but it serves as a good starting point for using XIP mode for other
purposes (such as actual eXecuting In Place).

Signed-off-by: Sean Anderson 
---

 drivers/spi/designware_spi.c | 131 +++
 1 file changed, 131 insertions(+)

diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index 6f74a471e3..cb7a28c3bf 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -1056,10 +1056,141 @@ static int dw_spi_adjust_op_size(struct spi_slave 
*slave, struct spi_mem_op *op)
return 0;
 }
 
+#if CONFIG_IS_ENABLED(SPI_DIRMAP)
+static int dw_spi_dirmap_create(struct spi_mem_dirmap_desc *desc)
+{
+   struct dw_spi_priv *priv = dev_get_priv(desc->slave->dev->parent);
+
+   /*
+* Currently only DWC XIP is supported. DW APB SSI XIP exists, but
+* cannot send an instruction before the address, so it is left for when
+* U-Boot supports 0-X-X instructions. In addition, we only support
+* concurrent XIP (since I have no non-condcurrent XIP hardware to test
+* with)
+*/
+   if (!(priv->caps & (DW_SPI_CAP_XIP)) ||
+   !(priv->caps & (DW_SPI_CAP_DWC_SSI)) ||
+   !(priv->caps & (DW_SPI_CAP_XIP_CONCURRENT)))
+   return -ENOTSUPP;
+
+   if (!spi_mem_supports_op(desc->slave, >info.op_tmpl))
+   return -ENOTSUPP;
+
+   /*
+* Make sure the requested region doesn't go out of the physically
+* mapped flash memory bounds and the operation is read-only.
+*/
+   if (desc->info.offset + desc->info.length > priv->regs_size ||
+   desc->info.op_tmpl.data.dir != SPI_MEM_DATA_IN)
+   return -ENOTSUPP;
+
+   /* XIP only supports enhanced SPI modes */
+   if (desc->info.op_tmpl.data.buswidth == 1)
+   return -ENOTSUPP;
+
+   return 0;
+}
+
+static u32 dw_spi_update_xip_cr(const struct spi_mem_op *op, uint frf)
+{
+   uint trans_type, wait_cycles;
+
+   /* This assumes support_op has filtered invalid types */
+   if (op->addr.buswidth == 1)
+   trans_type = TRANS_TYPE_1_1_X;
+   else if (op->cmd.buswidth == 1)
+   trans_type = TRANS_TYPE_1_X_X;
+   else
+   trans_type = TRANS_TYPE_X_X_X;
+
+   if (op->dummy.buswidth)
+   wait_cycles = op->dummy.nbytes * 8 / op->dummy.buswidth;
+   else
+   wait_cycles = 0;
+
+   return FIELD_PREP(XIP_CTRL_FRF, frf)
+  | FIELD_PREP(XIP_CTRL_TRANS_TYPE_MASK, trans_type)
+  | FIELD_PREP(XIP_CTRL_ADDR_L_MASK, op->addr.nbytes * 2)
+  | FIELD_PREP(XIP_CTRL_INST_L_MASK, INST_L_8)
+  | FIELD_PREP(XIP_CTRL_WAIT_CYCLES_MASK, wait_cycles)
+  //| XIP_CTRL_DFS_HC
+  | XIP_CTRL_INST_EN
+  | XIP_CTRL_CONT_XFER_EN
+  | XIP_CTRL_PREFETCH_EN;
+}
+
+static ssize_t dw_spi_dirmap_read(struct spi_mem_dirmap_desc *desc, u64 offs,
+ size_t len, void *buf)
+{
+   int ret;
+   size_t count = len;
+   struct spi_slave *slave = desc->slave;
+   struct udevice *bus = slave->dev->parent;
+   struct dw_spi_priv *priv = dev_get_priv(bus);
+   struct spi_mem_op *op = >info.op_tmpl;
+   u8 *from, *to;
+
+   switch (op->data.buswidth) {
+   case 2:
+   priv->spi_frf = CTRLR0_SPI_FRF_DUAL;
+   break;
+   case 4:
+   priv->spi_frf = CTRLR0_SPI_FRF_QUAD;
+   break;
+   case 8:
+   priv->spi_frf = CTRLR0_SPI_FRF_OCTAL;
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   ret = dw_spi_mux_ctrl(bus);
+   if (ret)
+   return ret;
+
+   dw_write(priv, DW_SPI_SSIENR, 0);
+   //dw_write(priv, DW_SPI_CTRLR0, dw_spi_update_cr0(priv));
+   dw_write(priv, DW_SPI_XIP_CTRL, dw_spi_update_xip_cr(op, 
priv->spi_frf));
+   dw_write(priv, DW_SPI_XIP_INCR_INST, op->cmd.opcode);
+   /*
+* FIXME: U-Boot doesn't currently support wrap instructions, but we
+* can't control what the AHB master does. Just write 0 to get something
+* obviously bogus.
+*/
+   dw_write(priv, DW_SPI_XIP_WRAP_INST, 0);
+   dw_write(priv, DW_SPI_XIP_SER, 1 << spi_chip_select(slave->dev));
+   dw_write(priv, DW_SPI_SSIENR, 1);
+
+   dw_spi_mux_deselect(bus);
+
+   external_cs_manage(slave->dev, true);
+
+   ret = dw_spi_mux_xip(bus);
+   if (ret)
+   return ret;
+
+   //memcpy(buf, priv->regs + offs, len);
+   from = priv->regs + offs;
+   to = buf;
+   while (count--)
+   *to++ = *from++;
+
+   dw_spi_mux_deselect(bus);
+
+   external_cs_manage(slave->dev, false);
+
+   return len;
+}
+#endif /* CONFIG_SPI_DIRMAP */
+
 static const struct spi_controller_mem_ops 

[RFC PATCH 13/13] riscv: k210: Add bindings for SPI XIP

2021-02-04 Thread Sean Anderson
On the K210, a register in sysctl controls whether accessing an SPI device
has the xip_en signal set. Add the appropriate bindings.

Signed-off-by: Sean Anderson 
---

 arch/riscv/dts/k210.dtsi | 23 ---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/arch/riscv/dts/k210.dtsi b/arch/riscv/dts/k210.dtsi
index dac7c62289..aa1c53f09f 100644
--- a/arch/riscv/dts/k210.dtsi
+++ b/arch/riscv/dts/k210.dtsi
@@ -292,6 +292,8 @@
interrupts = <2>;
clocks = < K210_CLK_SPI2>;
resets = < K210_RST_SPI2>;
+   mux-controls = <_mux 2>;
+   mux-xip-state = <1>;
spi-max-frequency = <2500>;
status = "disabled";
};
@@ -530,6 +532,15 @@
mask = <1>;
value = <1>;
};
+
+   xip_mux: mux-controller {
+   compatible = "mmio-mux";
+   #mux-control-cells = <1>;
+   mux-reg-masks = ,
+   ,
+   ,
+   ;
+   };
};
 
aes0: aes@5045 {
@@ -563,11 +574,13 @@
compatible = "canaan,kendryte-k210-spi",
 "snps,dw-apb-ssi-4.01",
 "snps,dw-apb-ssi";
-   reg = <0x5200 0x100>;
+   reg = <0x5200 0x100>;
interrupts = <1>;
clocks = < K210_CLK_SPI0>;
clock-names = "ssi_clk";
resets = < K210_RST_SPI0>;
+   mux-controls = <_mux 0>;
+   mux-xip-state = <1>;
spi-max-frequency = <2500>;
num-cs = <4>;
reg-io-width = <4>;
@@ -580,11 +593,13 @@
compatible = "canaan,kendryte-k210-spi",
 "snps,dw-apb-ssi-4.01",
 "snps,dw-apb-ssi";
-   reg = <0x5300 0x100>;
+   reg = <0x5300 0x100>;
interrupts = <2>;
clocks = < K210_CLK_SPI1>;
clock-names = "ssi_clk";
resets = < K210_RST_SPI1>;
+   mux-controls = <_mux 1>;
+   mux-xip-state = <1>;
spi-max-frequency = <2500>;
num-cs = <4>;
reg-io-width = <4>;
@@ -596,13 +611,15 @@
#size-cells = <0>;
compatible = "canaan,kendryte-k210-ssi",
 "snps,dwc-ssi-1.01a";
-   reg = <0x5400 0x200>;
+   reg = <0x5400 0x100>;
interrupts = <4>;
clocks = < K210_CLK_SPI3>;
clock-names = "ssi_clk";
assigned-clocks = < K210_CLK_SPI3>;
assigned-clock-rates = <39000>;
resets = < K210_RST_SPI3>;
+   mux-controls = <_mux 3>;
+   mux-xip-state = <1>;
/* Could possibly go up to 200 MHz */
spi-max-frequency = <1>;
num-cs = <4>;
-- 
2.29.2



[RFC PATCH 10/13] spi: dw: Use a mux to access registers

2021-02-04 Thread Sean Anderson
To enter XIP mode, the xip_en signal must be asserted. The exact method of
setting xip_en is integration-specific, but on the K210 (and Baikal-T1) it
is set by a bit in a system configuration register. To handle this, use a
mux to select the state of xip_en before every access to control registers.

Signed-off-by: Sean Anderson 
---

 drivers/spi/designware_spi.c | 133 ++-
 1 file changed, 130 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index c41c5b4982..6f74a471e3 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -209,6 +210,7 @@ struct dw_spi_priv {
struct clk clk;
struct reset_ctl_bulk resets;
struct gpio_desc cs_gpio;   /* External chip-select gpio */
+   struct mux_control *mux;/* XIP mode mux */
 
void __iomem *regs;
fdt_size_t regs_size;
@@ -225,6 +227,7 @@ struct dw_spi_priv {
unsigned int freq;  /* Default frequency */
unsigned int mode;
 
+   u32 mux_xip_state;  /* Mux state to enable XIP mode */
u32 fifo_len;   /* depth of the FIFO buffer */
 
int bits_per_word;
@@ -346,11 +349,79 @@ static int dw_spi_of_to_plat(struct udevice *bus)
return request_gpio_cs(bus);
 }
 
-/* Restart the controller, disable all interrupts, clean rx fifo */
-static void spi_hw_init(struct udevice *bus, struct dw_spi_priv *priv)
+static int dw_spi_mux(struct udevice *dev, bool xip)
 {
+   struct dw_spi_priv *priv = dev_get_priv(dev);
+
+   if (!priv->mux)
+   return 0;
+
+   if (xip && priv->mux_xip_state)
+   return mux_control_select(priv->mux, priv->mux_xip_state);
+   else
+   return mux_control_select(priv->mux, 0);
+}
+
+/*
+ * dw_spi_mux_regs() - Select the control registers using the XIP mux
+ * @dev: The device to mux
+ *
+ * This selects the control registers using the XIP mux, driving the xip_en
+ * signal low. This function must be called before any accesses to control
+ * registers.
+ *
+ * Return: 0 on success or negative error value
+ */
+static inline int dw_spi_mux_regs(struct udevice *dev)
+{
+   return dw_spi_mux(dev, false);
+}
+
+/*
+ * dw_spi_mux_xip() - Select the control registers using the XIP mux
+ * @dev: The device to mux
+ *
+ * This selects XIP mode using the XIP mux, driving the xip_en signal high. 
This
+ * function must be called before any XIP accesses.
+ *
+ * Return: 0 on success or negative error value
+ */
+static inline int dw_spi_mux_xip(struct udevice *dev)
+{
+   return dw_spi_mux(dev, true);
+}
+
+/*
+ * dw_spi_mux_deselect()
+ * @dev: The device to mux
+ *
+ * This deselects the XIP mux, returning it to its default state. This must be
+ * called after control register or XIP accesses are finished, before other
+ * calls to @dw_spi_mux_regs or @dw_spi_mux_xip.
+ */
+static void dw_spi_mux_deselect(struct udevice *dev)
+{
+   int err;
+   struct dw_spi_priv *priv = dev_get_priv(dev);
+
+   if (!priv->mux)
+   return;
+
+   err = mux_control_deselect(priv->mux);
+   if (err)
+   dev_warn(dev, "could not deselect mux (err %d)\n", err);
+}
+
+/* Restart the controller, disable all interrupts, clean rx fifo */
+static int spi_hw_init(struct udevice *bus, struct dw_spi_priv *priv)
+{
+   int ret;
u32 cr0;
 
+   ret = dw_spi_mux_regs(bus);
+   if (ret)
+   return ret;
+
dw_write(priv, DW_SPI_SSIENR, 0);
dw_write(priv, DW_SPI_IMR, 0);
 
@@ -415,6 +486,9 @@ static void spi_hw_init(struct udevice *bus, struct 
dw_spi_priv *priv)
 
/* Set receive fifo interrupt level register for clock stretching */
dw_write(priv, DW_SPI_RXFTLR, priv->fifo_len - 1);
+
+   dw_spi_mux_deselect(bus);
+   return 0;
 }
 
 /*
@@ -480,6 +554,33 @@ static int dw_spi_reset(struct udevice *bus)
return 0;
 }
 
+int dw_spi_get_mux(struct udevice *bus)
+{
+   int ret;
+   struct dw_spi_priv *priv = dev_get_priv(bus);
+
+   ret = mux_get_by_index(bus, 0, >mux);
+   if (ret) {
+   /*
+* Return 0 if error due to !CONFIG_MUX or mux
+* DT property is not present.
+*/
+   if (ret == -ENOENT || ret == -ENOTSUPP)
+   return 0;
+
+   dev_warn(bus, "Couldn't get xip mux (error %d)\n", ret);
+   return ret;
+   }
+
+   ret = dev_read_u32(bus, "mux-xip-state", >mux_xip_state);
+   if (ret || priv->mux_xip_state > 1) {
+   dev_warn(bus, "Invalid/missing mux-xip-state property\n");
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
 static int dw_spi_probe(struct udevice *bus)
 {
struct dw_spi_plat *plat = 

[RFC PATCH 12/13] riscv: k210: Increase SPI3 bus clock to CPU speed

2021-02-04 Thread Sean Anderson
By default the SPI3 bus clock is ~100MHz, 1/4th of the CPU clock. This
causes decreased performance when accessing this peripheral.

Signed-off-by: Sean Anderson 
---

 arch/riscv/dts/k210.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/riscv/dts/k210.dtsi b/arch/riscv/dts/k210.dtsi
index 81b04018c6..dac7c62289 100644
--- a/arch/riscv/dts/k210.dtsi
+++ b/arch/riscv/dts/k210.dtsi
@@ -600,6 +600,8 @@
interrupts = <4>;
clocks = < K210_CLK_SPI3>;
clock-names = "ssi_clk";
+   assigned-clocks = < K210_CLK_SPI3>;
+   assigned-clock-rates = <39000>;
resets = < K210_RST_SPI3>;
/* Could possibly go up to 200 MHz */
spi-max-frequency = <1>;
-- 
2.29.2



[RFC PATCH 06/13] mux: Define a stub for mux_get_by_index if CONFIG_MUX is disabled

2021-02-04 Thread Sean Anderson
This allows code using mux_get_by_index to be agnostic about CONFIG_MUX.

Signed-off-by: Sean Anderson 
---

 include/mux.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/include/mux.h b/include/mux.h
index 91a89bbb9a..882a00068b 100644
--- a/include/mux.h
+++ b/include/mux.h
@@ -135,6 +135,12 @@ static inline int mux_control_deselect(struct mux_control 
*mux)
return -ENOSYS;
 }
 
+static inline int mux_get_by_index(struct udevice *dev, int index,
+  struct mux_control **mux)
+{
+   return -ENOSYS;
+}
+
 static inline struct mux_control *mux_control_get(struct udevice *dev,
  const char *mux_name)
 {
-- 
2.29.2



[RFC PATCH 07/13] mux: mmio: Only complain about idle-states if it is malformed

2021-02-04 Thread Sean Anderson
idle-states is optional, so don't complain if it doesn't exist.

Signed-off-by: Sean Anderson 
---

 drivers/mux/mmio.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/mux/mmio.c b/drivers/mux/mmio.c
index 00e0282dcc..82b1cc6aab 100644
--- a/drivers/mux/mmio.c
+++ b/drivers/mux/mmio.c
@@ -87,8 +87,11 @@ static int mmio_mux_probe(struct udevice *dev)
 
ret = dev_read_u32_array(dev, "idle-states", idle_states, num_fields);
if (ret < 0) {
-   log_err("idle-states");
devm_kfree(dev, idle_states);
+   /* dev_read_u32_array returns -EINVAL on missing property */
+   if (ret != -EINVAL)
+   return log_msg_ret("idle-states", -EINVAL);
+
idle_states = NULL;
}
 
-- 
2.29.2



[RFC PATCH 09/13] spi: dw: Add XIP and XIP_CONCURRENT caps

2021-02-04 Thread Sean Anderson
Both DW SSI APB and DWC SSI devices have an optional XIP mode. When the
xip_en signal is asserted, reads (and writes if SSIC_XIP_WRITE_REG_EN is
set) are mapped to SPI transfers.

If SSIC_CONCURRENT_XIP_EN is disabled, then XIP transfers are controlled
using SPI_CTRLR0. However, if SSIC_CONCURRENT_XIP_EN is enabled, then XIP
transfers can occur concurrently (first-come-first-serve) with non-XIP
transfers. To facilitate this, a separate XIP_CTRL register is used for
configuration which would otherwise by done using CTRLR0 and SPI_CTRLR0.

Signed-off-by: Sean Anderson 
---

 drivers/spi/designware_spi.c | 29 ++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index d7510646e7..c41c5b4982 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -202,6 +202,7 @@
 struct dw_spi_plat {
s32 frequency;  /* Default clock frequency, -1 for none */
void __iomem *regs;
+   fdt_size_t regs_size;
 };
 
 struct dw_spi_priv {
@@ -210,12 +211,15 @@ struct dw_spi_priv {
struct gpio_desc cs_gpio;   /* External chip-select gpio */
 
void __iomem *regs;
+   fdt_size_t regs_size;
 /* DW SPI capabilities */
 #define DW_SPI_CAP_CS_OVERRIDE BIT(0) /* Unimplemented */
 #define DW_SPI_CAP_KEEMBAY_MST BIT(1) /* Unimplemented */
 #define DW_SPI_CAP_DWC_SSI BIT(2)
 #define DW_SPI_CAP_DFS32   BIT(3)
 #define DW_SPI_CAP_ENHANCEDBIT(4)
+#define DW_SPI_CAP_XIP BIT(5)
+#define DW_SPI_CAP_XIP_CONCURRENT  BIT(6)
unsigned long caps;
unsigned long bus_clk_rate;
unsigned int freq;  /* Default frequency */
@@ -322,11 +326,13 @@ static int request_gpio_cs(struct udevice *bus)
 
 static int dw_spi_of_to_plat(struct udevice *bus)
 {
+   fdt_addr_t regs;
struct dw_spi_plat *plat = dev_get_plat(bus);
 
-   plat->regs = dev_read_addr_ptr(bus);
-   if (!plat->regs)
+   regs = dev_read_addr_size_index(bus, 0, >regs_size);
+   if (regs == FDT_ADDR_T_NONE)
return -EINVAL;
+   plat->regs = (void *)regs;
 
/* Use 500KHz as a suitable default */
plat->frequency = dev_read_u32_default(bus, "spi-max-frequency",
@@ -375,6 +381,19 @@ static void spi_hw_init(struct udevice *bus, struct 
dw_spi_priv *priv)
priv->caps |= DW_SPI_CAP_ENHANCED;
}
 
+   /*
+* DWC_SPI always has this register with SSIC_XIP_EN. There is no way
+* to detect XIP for DW APB SSI
+*/
+   dw_write(priv, DW_SPI_XIP_INCR_INST, 0x);
+   if (dw_read(priv, DW_SPI_XIP_INCR_INST))
+   priv->caps |= DW_SPI_CAP_XIP;
+
+   /* Exists with SSIC_CONCURRENT_XIP_EN */
+   dw_write(priv, DW_SPI_XIP_CTRL, 0x);
+   if (dw_read(priv, DW_SPI_XIP_CTRL))
+   priv->caps |= DW_SPI_CAP_XIP_CONCURRENT;
+
dw_write(priv, DW_SPI_SSIENR, 1);
 
/*
@@ -469,6 +488,7 @@ static int dw_spi_probe(struct udevice *bus)
u32 version;
 
priv->regs = plat->regs;
+   priv->regs_size = plat->regs_size;
priv->freq = plat->frequency;
 
ret = dw_spi_get_clk(bus, >bus_clk_rate);
@@ -1022,7 +1042,10 @@ static const struct udevice_id dw_spi_ids[] = {
 */
{ .compatible = "altr,socfpga-spi" },
{ .compatible = "altr,socfpga-arria10-spi" },
-   { .compatible = "canaan,kendryte-k210-spi" },
+   {
+   .compatible = "canaan,kendryte-k210-spi",
+   .data = DW_SPI_CAP_XIP,
+   },
{
.compatible = "canaan,kendryte-k210-ssi",
.data = DW_SPI_CAP_DWC_SSI,
-- 
2.29.2



[RFC PATCH 08/13] spi: dw: Define XIP registers

2021-02-04 Thread Sean Anderson
These registers and fields are necessary for XIP with
SSIC_CONCURRENT_XIP_EN.

Signed-off-by: Sean Anderson 
---

 drivers/spi/designware_spi.c | 44 +++-
 1 file changed, 38 insertions(+), 6 deletions(-)

diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index 44fb679fdb..d7510646e7 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -58,6 +58,13 @@
 #define DW_SPI_DR  0x60
 #define DW_SPI_RX_SAMPLE_DLY   0xf0
 #define DW_SPI_SPI_CTRL0   0xf4
+#define DW_SPI_XIP_MODE_BITS   0xfc
+#define DW_SPI_XIP_INCR_INST   0x100
+#define DW_SPI_XIP_WRAP_INST   0x104
+#define DW_SPI_XIP_CTRL0x108
+#define DW_SPI_XIP_SER 0x10c
+#define DW_SPI_XRXOICR 0x110
+#define DW_SPI_XIP_XNT_TIME_OUT0x114
 
 /* Bit fields in CTRLR0 */
 /*
@@ -147,9 +154,9 @@
  * FRF_BYTE
  */
 #define SPI_CTRLR0_TRANS_TYPE_MASK GENMASK(1, 0)
-#define SPI_CTRLR0_TRANS_TYPE_1_1_X0x0
-#define SPI_CTRLR0_TRANS_TYPE_1_X_X0x1
-#define SPI_CTRLR0_TRANS_TYPE_X_X_X0x2
+#define TRANS_TYPE_1_1_X   0x0
+#define TRANS_TYPE_1_X_X   0x1
+#define TRANS_TYPE_X_X_X   0x2
 /* Address length in 4-bit units */
 #define SPI_CTRLR0_ADDR_L_MASK GENMASK(5, 2)
 /* Enable mode bits after address in XIP mode */
@@ -165,6 +172,31 @@
 /* Stretch the clock if the FIFO over/underflows */
 #define SPI_CTRLR0_CLK_STRETCH_EN  BIT(30)
 
+/* Bit fields in XIP_CTRL */
+
+/* XIP SPI frame format */
+#define XIP_CTRL_FRF   GENMASK(1, 0)
+/* Same as SPI_CTRLR0_TRANS_TYPE */
+#define XIP_CTRL_TRANS_TYPE_MASK   GENMASK(3, 2)
+/* Address length in 4-bit increments */
+#define XIP_CTRL_ADDR_L_MASK   GENMASK(7, 4)
+/* Same as SPI_CTRLR0_INST_L */
+#define XIP_CTRL_INST_L_MASK   GENMASK(10, 9)
+/* Enable mode bits */
+#define XIP_CTRL_MD_BITS_ENBIT(12)
+/* Wait cycles */
+#define XIP_CTRL_WAIT_CYCLES_MASK  GENMASK(17, 13)
+/* Use fixed-size DFS in XIP mode, ignoring AHB request width */
+#define XIP_CTRL_DFS_HCBIT(18)
+/* Enable instruction phase */
+#define XIP_CTRL_INST_EN   BIT(22)
+/* Continuous transfer: don't deselect slave after one transfer */
+#define XIP_CTRL_CONT_XFER_EN  BIT(23)
+/* Mode bits length; length = 1 << (MBL + 1) */
+#define XIP_CTRL_XIP_MBL_MASK  GENMASK(27, 26)
+/* Prefetch contiguous data frames */
+#define XIP_CTRL_PREFETCH_EN   BIT(29)
+
 #define RX_TIMEOUT 1000/* timeout in ms */
 
 struct dw_spi_plat {
@@ -243,11 +275,11 @@ static u32 dw_spi_update_spi_cr0(const struct spi_mem_op 
*op)
 
/* This assumes support_op has filtered invalid types */
if (op->addr.buswidth == 1)
-   trans_type = SPI_CTRLR0_TRANS_TYPE_1_1_X;
+   trans_type = TRANS_TYPE_1_1_X;
else if (op->cmd.buswidth == 1)
-   trans_type = SPI_CTRLR0_TRANS_TYPE_1_X_X;
+   trans_type = TRANS_TYPE_1_X_X;
else
-   trans_type = SPI_CTRLR0_TRANS_TYPE_X_X_X;
+   trans_type = TRANS_TYPE_X_X_X;
 
if (op->dummy.buswidth)
wait_cycles = op->dummy.nbytes * 8 / op->dummy.buswidth;
-- 
2.29.2



[RFC PATCH 03/13] mtd: spi-nor: use spi-mem dirmap API

2021-02-04 Thread Sean Anderson
This adds support for the dirmap API to the spi-nor subsystem, as
introduced in Linux commit df5c21002cf4 ("mtd: spi-nor: use spi-mem dirmap
API").

Signed-off-by: Sean Anderson 
---

 drivers/mtd/spi/sf_probe.c | 79 ++
 drivers/mtd/spi/spi-nor-core.c | 45 +--
 include/linux/mtd/spi-nor.h|  6 +++
 3 files changed, 116 insertions(+), 14 deletions(-)

diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index 6c87434867..796a2fa6bc 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -14,9 +14,72 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "sf_internal.h"
 
+#if CONFIG_IS_ENABLED(SPI_DIRMAP)
+static int spi_nor_create_read_dirmap(struct spi_nor *nor)
+{
+   struct spi_mem_dirmap_info info = {
+   .op_tmpl = SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 1),
+ SPI_MEM_OP_ADDR(nor->addr_width, 0, 1),
+ SPI_MEM_OP_DUMMY(nor->read_dummy, 1),
+ SPI_MEM_OP_DATA_IN(0, NULL, 1)),
+   .offset = 0,
+   .length = nor->mtd.size,
+   };
+   struct spi_mem_op *op = _tmpl;
+
+   /* get transfer protocols. */
+   op->cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->read_proto);
+   op->addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->read_proto);
+   op->dummy.buswidth = op->addr.buswidth;
+   op->data.buswidth = spi_nor_get_protocol_data_nbits(nor->read_proto);
+
+   /* convert the dummy cycles to the number of bytes */
+   op->dummy.nbytes = (nor->read_dummy * op->dummy.buswidth) / 8;
+
+   nor->dirmap.rdesc = spi_mem_dirmap_create(nor->spi, );
+   return PTR_ERR_OR_ZERO(nor->dirmap.rdesc);
+}
+
+static int spi_nor_create_write_dirmap(struct spi_nor *nor)
+{
+   struct spi_mem_dirmap_info info = {
+   .op_tmpl = SPI_MEM_OP(SPI_MEM_OP_CMD(nor->program_opcode, 1),
+ SPI_MEM_OP_ADDR(nor->addr_width, 0, 1),
+ SPI_MEM_OP_NO_DUMMY,
+ SPI_MEM_OP_DATA_OUT(0, NULL, 1)),
+   .offset = 0,
+   .length = nor->mtd.size,
+   };
+   struct spi_mem_op *op = _tmpl;
+
+   /* get transfer protocols. */
+   op->cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->write_proto);
+   op->addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->write_proto);
+   op->dummy.buswidth = op->addr.buswidth;
+   op->data.buswidth = spi_nor_get_protocol_data_nbits(nor->write_proto);
+
+   if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second)
+   op->addr.nbytes = 0;
+
+   nor->dirmap.wdesc = spi_mem_dirmap_create(nor->spi, );
+   return PTR_ERR_OR_ZERO(nor->dirmap.wdesc);
+}
+#else
+static int spi_nor_create_read_dirmap(struct spi_nor *nor)
+{
+   return 0;
+}
+
+static int spi_nor_create_write_dirmap(struct spi_nor *nor)
+{
+   return 0;
+}
+#endif /* CONFIG_SPI_DIRMAP */
+
 /**
  * spi_flash_probe_slave() - Probe for a SPI flash device on a bus
  *
@@ -45,6 +108,14 @@ static int spi_flash_probe_slave(struct spi_flash *flash)
if (ret)
goto err_read_id;
 
+   ret = spi_nor_create_read_dirmap(flash);
+   if (ret)
+   return ret;
+
+   ret = spi_nor_create_write_dirmap(flash);
+   if (ret)
+   return ret;
+
if (CONFIG_IS_ENABLED(SPI_FLASH_MTD))
ret = spi_flash_mtd_register(flash);
 
@@ -83,6 +154,9 @@ struct spi_flash *spi_flash_probe(unsigned int busnum, 
unsigned int cs,
 
 void spi_flash_free(struct spi_flash *flash)
 {
+   spi_mem_dirmap_destroy(flash->dirmap.wdesc);
+   spi_mem_dirmap_destroy(flash->dirmap.rdesc);
+
if (CONFIG_IS_ENABLED(SPI_FLASH_MTD))
spi_flash_mtd_unregister();
 
@@ -143,6 +217,11 @@ int spi_flash_std_probe(struct udevice *dev)
 
 static int spi_flash_std_remove(struct udevice *dev)
 {
+   struct spi_flash *flash = dev_get_uclass_priv(dev);
+
+   spi_mem_dirmap_destroy(flash->dirmap.wdesc);
+   spi_mem_dirmap_destroy(flash->dirmap.rdesc);
+
if (CONFIG_IS_ENABLED(SPI_FLASH_MTD))
spi_flash_mtd_unregister();
 
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index e16b0e1462..32c712a9f1 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -96,13 +96,23 @@ static ssize_t spi_nor_read_data(struct spi_nor *nor, 
loff_t from, size_t len,
 
while (remaining) {
op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX;
-   ret = spi_mem_adjust_op_size(nor->spi, );
-   if (ret)
-   return ret;
 
-   ret = spi_mem_exec_op(nor->spi, );
-   if (ret)
-   return ret;
+   if 

[RFC PATCH 04/13] core: ofnode: Fix inconsistent returns of *_read_u32_array

2021-02-04 Thread Sean Anderson
The documentation for dev_read_u32_array says the return value is an errno,
but fdtdec_get_int_array returns FDT_ERRs. Convert the return values so
callers can handle errors properly.

Signed-off-by: Sean Anderson 
---

 drivers/core/ofnode.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index 7a5f4c0a73..c071b968d5 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -220,9 +220,18 @@ int ofnode_read_u32_array(ofnode node, const char 
*propname,
return of_read_u32_array(ofnode_to_np(node), propname,
 out_values, sz);
} else {
-   return fdtdec_get_int_array(gd->fdt_blob,
-   ofnode_to_offset(node), propname,
-   out_values, sz);
+   int err = fdtdec_get_int_array(gd->fdt_blob,
+  ofnode_to_offset(node), propname,
+  out_values, sz);
+
+   switch (err) {
+   case FDT_ERR_NOTFOUND:
+   return -EINVAL;
+   case FDT_ERR_BADLAYOUT:
+   return -EOVERFLOW;
+   default:
+   return 0;
+   }
}
 }
 
-- 
2.29.2



[RFC PATCH 05/13] mux: Inline mux functions when CONFIG_MUX is disabled

2021-02-04 Thread Sean Anderson
This prevents multiple-definition errors.

Fixes: 0ad40b2463 ("drivers: Add a new framework for multiplexer devices")

Signed-off-by: Sean Anderson 
---

 include/mux.h | 19 ++-
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/include/mux.h b/include/mux.h
index 23844f480a..91a89bbb9a 100644
--- a/include/mux.h
+++ b/include/mux.h
@@ -117,40 +117,41 @@ struct mux_control *devm_mux_control_get(struct udevice 
*dev,
 int dm_mux_init(void);
 
 #else
-unsigned int mux_control_states(struct mux_control *mux)
+static inline unsigned int mux_control_states(struct mux_control *mux)
 {
return -ENOSYS;
 }
 
-int __must_check mux_control_select(struct mux_control *mux,
-   unsigned int state)
+static inline int __must_check mux_control_select(struct mux_control *mux,
+ unsigned int state)
 {
return -ENOSYS;
 }
 
 #define mux_control_try_select(mux) mux_control_select(mux)
 
-int mux_control_deselect(struct mux_control *mux)
+static inline int mux_control_deselect(struct mux_control *mux)
 {
return -ENOSYS;
 }
 
-struct mux_control *mux_control_get(struct udevice *dev, const char *mux_name)
+static inline struct mux_control *mux_control_get(struct udevice *dev,
+ const char *mux_name)
 {
return NULL;
 }
 
-void mux_control_put(struct mux_control *mux)
+static inline void mux_control_put(struct mux_control *mux)
 {
 }
 
-struct mux_control *devm_mux_control_get(struct udevice *dev,
-const char *mux_name)
+static inline struct mux_control *devm_mux_control_get(struct udevice *dev,
+  const char *mux_name)
 {
return NULL;
 }
 
-int dm_mux_init(void)
+static inline int dm_mux_init(void)
 {
return -ENOSYS;
 }
-- 
2.29.2



[RFC PATCH 02/13] spi-mem: Add dirmap API from Linux

2021-02-04 Thread Sean Anderson
This adds the dirmap API originally introduced in Linux commit aa167f3fed0c
("spi: spi-mem: Add a new API to support direct mapping"). This also
includes several follow-up patches and fixes.

Changes from Linux include:
* Added Kconfig option
* Changed struct device to struct udevice
* Changed struct spi_mem to struct spi_slave

Signed-off-by: Sean Anderson 
---

 drivers/spi/Kconfig   |  10 ++
 drivers/spi/spi-mem.c | 270 ++
 include/spi-mem.h |  99 
 3 files changed, 379 insertions(+)

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 1494c91763..9663b20c74 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -40,6 +40,16 @@ config SPI_MEM
  This extension is meant to simplify interaction with SPI memories
  by providing an high-level interface to send memory-like commands.
 
+config SPI_DIRMAP
+   bool "SPI direct mapping"
+   depends on SPI_MEM
+   help
+ Enable the SPI direct mapping API. Most modern SPI controllers can
+ directly map a SPI memory (or a portion of the SPI memory) in the CPU
+ address space. Most of the time this brings significant performance
+ improvements as it automates the whole process of sending SPI memory
+ operations every time a new region is accessed.
+
 if DM_SPI
 
 config ALTERA_SPI
diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
index 6772367ef7..597cd63c00 100644
--- a/drivers/spi/spi-mem.c
+++ b/drivers/spi/spi-mem.c
@@ -21,6 +21,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #endif
 
 #ifndef __UBOOT__
@@ -468,6 +470,274 @@ int spi_mem_adjust_op_size(struct spi_slave *slave, 
struct spi_mem_op *op)
 }
 EXPORT_SYMBOL_GPL(spi_mem_adjust_op_size);
 
+#if CONFIG_IS_ENABLED(SPI_DIRMAP)
+static ssize_t spi_mem_no_dirmap_read(struct spi_mem_dirmap_desc *desc,
+ u64 offs, size_t len, void *buf)
+{
+   struct spi_mem_op op = desc->info.op_tmpl;
+   int ret;
+
+   op.addr.val = desc->info.offset + offs;
+   op.data.buf.in = buf;
+   op.data.nbytes = len;
+   ret = spi_mem_adjust_op_size(desc->slave, );
+   if (ret)
+   return ret;
+
+   ret = spi_mem_exec_op(desc->slave, );
+   if (ret)
+   return ret;
+
+   return op.data.nbytes;
+}
+
+static ssize_t spi_mem_no_dirmap_write(struct spi_mem_dirmap_desc *desc,
+  u64 offs, size_t len, const void *buf)
+{
+   struct spi_mem_op op = desc->info.op_tmpl;
+   int ret;
+
+   op.addr.val = desc->info.offset + offs;
+   op.data.buf.out = buf;
+   op.data.nbytes = len;
+   ret = spi_mem_adjust_op_size(desc->slave, );
+   if (ret)
+   return ret;
+
+   ret = spi_mem_exec_op(desc->slave, );
+   if (ret)
+   return ret;
+
+   return op.data.nbytes;
+}
+
+/**
+ * spi_mem_dirmap_create() - Create a direct mapping descriptor
+ * @mem: SPI mem device this direct mapping should be created for
+ * @info: direct mapping information
+ *
+ * This function is creating a direct mapping descriptor which can then be used
+ * to access the memory using spi_mem_dirmap_read() or spi_mem_dirmap_write().
+ * If the SPI controller driver does not support direct mapping, this function
+ * falls back to an implementation using spi_mem_exec_op(), so that the caller
+ * doesn't have to bother implementing a fallback on his own.
+ *
+ * Return: a valid pointer in case of success, and ERR_PTR() otherwise.
+ */
+struct spi_mem_dirmap_desc *
+spi_mem_dirmap_create(struct spi_slave *slave,
+ const struct spi_mem_dirmap_info *info)
+{
+   struct udevice *bus = slave->dev->parent;
+   struct dm_spi_ops *ops = spi_get_ops(bus);
+   struct spi_mem_dirmap_desc *desc;
+   int ret = -ENOTSUPP;
+
+   /* Make sure the number of address cycles is between 1 and 8 bytes. */
+   if (!info->op_tmpl.addr.nbytes || info->op_tmpl.addr.nbytes > 8)
+   return ERR_PTR(-EINVAL);
+
+   /* data.dir should either be SPI_MEM_DATA_IN or SPI_MEM_DATA_OUT. */
+   if (info->op_tmpl.data.dir == SPI_MEM_NO_DATA)
+   return ERR_PTR(-EINVAL);
+
+   desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+   if (!desc)
+   return ERR_PTR(-ENOMEM);
+
+   desc->slave = slave;
+   desc->info = *info;
+   if (ops->mem_ops && ops->mem_ops->dirmap_create)
+   ret = ops->mem_ops->dirmap_create(desc);
+
+   if (ret) {
+   desc->nodirmap = true;
+   if (!spi_mem_supports_op(desc->slave, >info.op_tmpl))
+   ret = -ENOTSUPP;
+   else
+   ret = 0;
+   }
+
+   if (ret) {
+   kfree(desc);
+   return ERR_PTR(ret);
+   }
+
+   return desc;
+}
+EXPORT_SYMBOL_GPL(spi_mem_dirmap_create);
+
+/**
+ * spi_mem_dirmap_destroy() - Destroy 

[RFC PATCH 01/13] linux err: Synchronize with Linux 5.10

2021-02-04 Thread Sean Anderson
This synchronizes linux/err.h with Linux 5.10. Notably, this adds
PTR_ERR_OR_ZERO.

Signed-off-by: Sean Anderson 
---

 include/linux/err.h | 21 +++--
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/include/linux/err.h b/include/linux/err.h
index 5ede82432d..06a80f9f29 100644
--- a/include/linux/err.h
+++ b/include/linux/err.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef _LINUX_ERR_H
 #define _LINUX_ERR_H
 
@@ -9,7 +10,7 @@
 
 /*
  * Kernel pointers have redundant information, so we can use a
- * scheme where we can return either an error code or a dentry
+ * scheme where we can return either an error code or a normal
  * pointer with the same return value.
  *
  * This should be a per-architecture thing, to allow different
@@ -21,24 +22,24 @@
 
 #define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)
 
-static inline void *ERR_PTR(long error)
+static inline void * __must_check ERR_PTR(long error)
 {
return (void *)(CONFIG_ERR_PTR_OFFSET + error);
 }
 
-static inline long PTR_ERR(const void *ptr)
+static inline long __must_check PTR_ERR(__force const void *ptr)
 {
return ((long)ptr - CONFIG_ERR_PTR_OFFSET);
 }
 
-static inline long IS_ERR(const void *ptr)
+static inline bool __must_check IS_ERR(__force const void *ptr)
 {
return IS_ERR_VALUE((unsigned long)PTR_ERR(ptr));
 }
 
-static inline bool IS_ERR_OR_NULL(const void *ptr)
+static inline bool __must_check IS_ERR_OR_NULL(__force const void *ptr)
 {
-   return !ptr || IS_ERR_VALUE((unsigned long)PTR_ERR(ptr));
+   return unlikely(!ptr) || IS_ERR_VALUE((unsigned long)ptr);
 }
 
 /**
@@ -54,6 +55,14 @@ static inline void * __must_check ERR_CAST(__force const 
void *ptr)
return (void *) ptr;
 }
 
+static inline int __must_check PTR_ERR_OR_ZERO(__force const void *ptr)
+{
+   if (IS_ERR(ptr))
+   return PTR_ERR(ptr);
+   else
+   return 0;
+}
+
 #endif
 
 #endif /* _LINUX_ERR_H */
-- 
2.29.2



[RFC PATCH 00/13] spi: dw: Add support for XIP mode

2021-02-04 Thread Sean Anderson
This adds support for memory-mapped ("DIRMAP") reads (called XIP by the
datasheet). In theory, these have better performance than regular reads. In
practice, the CPU is already fast enough to max out the performance of this
peripheral.

The real end-goal is to be able to boot a XIP kernel. This SoC has just barely
enough SRAM to boot Linux, and using a XIP kernel would decrease the memory
pressure to something tolerable. It would also probably absolutely *tank* the
performance, since not only is SPI flash ~8x slower than regular memory, there
is no cache to mitigate that latency. So it remains to be seen whether this is
worth it at all.

This series is RFC because it currently reads all 1s on one board I have. On the
other board I have, it reads and writes fine. I will try and investigate this,
but I expect any changes to occur in "spi: dw: Add support for DIRMAP".


Sean Anderson (13):
  linux err: Synchronize with Linux 5.10
  spi-mem: Add dirmap API from Linux
  mtd: spi-nor: use spi-mem dirmap API
  core: ofnode: Fix inconsistent returns of *_read_u32_array
  mux: Inline mux functions when CONFIG_MUX is disabled
  mux: Define a stub for mux_get_by_index if CONFIG_MUX is disabled
  mux: mmio: Only complain about idle-states if it is malformed
  spi: dw: Define XIP registers
  spi: dw: Add XIP and XIP_CONCURRENT caps
  spi: dw: Use a mux to access registers
  spi: dw: Add support for DIRMAP
  riscv: k210: Increase SPI3 bus clock to CPU speed
  riscv: k210: Add bindings for SPI XIP

 arch/riscv/dts/k210.dtsi   |  25 ++-
 drivers/core/ofnode.c  |  15 +-
 drivers/mtd/spi/sf_probe.c |  79 
 drivers/mtd/spi/spi-nor-core.c |  45 +++--
 drivers/mux/mmio.c |   5 +-
 drivers/spi/Kconfig|  10 +
 drivers/spi/designware_spi.c   | 337 +++--
 drivers/spi/spi-mem.c  | 270 ++
 include/linux/err.h|  21 +-
 include/linux/mtd/spi-nor.h|   6 +
 include/mux.h  |  25 ++-
 include/spi-mem.h  |  99 ++
 12 files changed, 889 insertions(+), 48 deletions(-)

-- 
2.29.2



[BUG]u-boot no boots from SD-card on NXP T2080RDB development board

2021-02-04 Thread Jeff Hering
The 2020.10 tagged build works on the T2080RDB card, however, all tags starting 
with 2021.01-rc1 no long boot from SD-card on the development system. This 
might also apply to other QorIQ development boards.

Here is a dump of the crash which occurs very early in the process (the left 
column is a timestamp):

00.000: .
00.409:
00.410: SD boot...
00.415: No max bus width provided. Assume 8-bit supported.
03.972: MMC init failed
03.975: Initializingusing SPD
04.323: 2 GiB left unmapped
04.327: Bad trap at PC: 20, SR: 21200, vector=800
04.332: NIP:  XER:  LR:  REGS: 20 TRAP: 2000
04.334:  DAR: 
04.338: MSR: 00021200 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 00
04.338:
04.344: GPR00:       
 
04.351: GPR08:       
 
04.358: GPR16:       
 
04.365: GPR24:       
 
04.368: Call backtrace:
04.371: Exception in kernel pc 20 signal 0
04.375: ### ERROR ### Please RESET the board ###



[PATCH v4 16/16] gpio: Add a way to read 3-way strapping pins

2021-02-04 Thread Simon Glass
Using the internal vs. external pull resistors it is possible to get
27 different combinations from 3 strapping pins. Add an implementation
of this.

This involves updating the sandbox GPIO driver to model external and
(weaker) internal pull resistors. The get_value() method now takes account
of what is driving a pin:

   sandbox: GPIOD_EXT_DRIVEN - in which case GPIO_EXT_HIGH provides the
  value
   outside source - in which case GPIO_EXT_PULL_UP/DOWN indicates the
  external state and we work the final state using those flags and
  the internal GPIOD_PULL_UP/DOWN flags

Of course the outside source does not really exist in sandbox. We are just
modelling it for test purpose.

Signed-off-by: Simon Glass 
---

(no changes since v3)

Changes in v3:
- Use bits 28, 29 for the new flags
- Assert that count parameter is within range
- Redo digit logic to be easier to understand
- Update function comment to explain the meaning of the digits
- Fix 'compare' typo

 arch/sandbox/include/asm/gpio.h |  5 +-
 drivers/gpio/gpio-uclass.c  | 81 +++
 drivers/gpio/sandbox.c  | 13 +++--
 include/asm-generic/gpio.h  | 40 ++
 test/dm/gpio.c  | 98 +
 5 files changed, 232 insertions(+), 5 deletions(-)

diff --git a/arch/sandbox/include/asm/gpio.h b/arch/sandbox/include/asm/gpio.h
index 33b83ea4cc3..9e10052667d 100644
--- a/arch/sandbox/include/asm/gpio.h
+++ b/arch/sandbox/include/asm/gpio.h
@@ -26,8 +26,11 @@
 /* Our own private GPIO flags, which musn't conflict with GPIOD_... */
 #define GPIOD_EXT_HIGH BIT(31) /* external source is high (else low) */
 #define GPIOD_EXT_DRIVEN   BIT(30) /* external source is driven */
+#define GPIOD_EXT_PULL_UP  BIT(29) /* GPIO has external pull-up */
+#define GPIOD_EXT_PULL_DOWNBIT(28) /* GPIO has external pull-down */
 
-#define GPIOD_SANDBOX_MASK GENMASK(31, 30)
+#define GPIOD_EXT_PULL (BIT(28) | BIT(29))
+#define GPIOD_SANDBOX_MASK GENMASK(31, 28)
 
 /**
  * Return the simulated value of a GPIO (used only in sandbox test code)
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 308e75a1476..8dc647dc9f8 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -711,6 +712,21 @@ int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong 
flags)
return dm_gpio_clrset_flags(desc, GPIOD_MASK_DIR, flags);
 }
 
+int dm_gpios_clrset_flags(struct gpio_desc *desc, int count, ulong clr,
+ ulong set)
+{
+   int ret;
+   int i;
+
+   for (i = 0; i < count; i++) {
+   ret = dm_gpio_clrset_flags([i], clr, set);
+   if (ret)
+   return log_ret(ret);
+   }
+
+   return 0;
+}
+
 int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flagsp)
 {
struct udevice *dev = desc->dev;
@@ -977,6 +993,71 @@ int dm_gpio_get_values_as_int(const struct gpio_desc 
*desc_list, int count)
return vector;
 }
 
+int dm_gpio_get_values_as_int_base3(struct gpio_desc *desc_list,
+   int count)
+{
+   static const char tristate[] = "01z";
+   enum {
+   PULLUP,
+   PULLDOWN,
+
+   NUM_OPTIONS,
+   };
+   int vals[NUM_OPTIONS];
+   uint mask;
+   uint vector = 0;
+   int ret, i;
+
+   /*
+* Limit to 19 digits which should be plenty. This avoids overflow of a
+* 32-bit int
+*/
+   assert(count < 20);
+
+   for (i = 0; i < NUM_OPTIONS; i++) {
+   uint flags = GPIOD_IS_IN;
+
+   flags |= (i == PULLDOWN) ? GPIOD_PULL_DOWN : GPIOD_PULL_UP;
+   ret = dm_gpios_clrset_flags(desc_list, count, GPIOD_MASK_PULL,
+   flags);
+   if (ret)
+   return log_msg_ret("pu", ret);
+
+   /* Give the lines time to settle */
+   udelay(10);
+
+   ret = dm_gpio_get_values_as_int(desc_list, count);
+   if (ret < 0)
+   return log_msg_ret("get1", ret);
+   vals[i] = ret;
+   }
+
+   log_debug("values: %x %x, count = %d\n", vals[0], vals[1], count);
+   for (i = count - 1, mask = 1 << i; i >= 0; i--, mask >>= 1) {
+   uint pd = vals[PULLDOWN] & mask ? 1 : 0;
+   uint pu = vals[PULLUP] & mask ? 1 : 0;
+   uint digit;
+
+   /*
+* Get value with internal pulldown active. If this is 1 then
+* there is a stronger external pullup, which we call 1. If not
+* then call it 0.
+*
+* If the values differ then the pin is floating so we call
+* this a 2.
+*/
+   if (pu == pd)
+  

[PATCH v4 15/16] gpio: Define the log category in the uclass

2021-02-04 Thread Simon Glass
This uses log_debug(), etc. but does not define the category. Fix this.

Signed-off-by: Simon Glass 
---

(no changes since v3)

Changes in v3:
- Split out the log-category change to a separate patch

 drivers/gpio/gpio-uclass.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 11fa17c14b2..308e75a1476 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -3,6 +3,8 @@
  * Copyright (c) 2013 Google, Inc
  */
 
+#define LOG_CATEGORY   UCLASS_GPIO
+
 #include 
 #include 
 #include 
-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v4 14/16] gpio: sandbox: Track whether a GPIO is driven

2021-02-04 Thread Simon Glass
Add a new flag to keep track of whether sandbox is driving the pin, or
whether it is expecting an input signal. If it is driving, then the value
of the pin is the value being driven (0 or 1). If not driving, then we
consider the value 0, since we don't currently handle things like pull-ups
yet.

Signed-off-by: Simon Glass 
Reviewed-by: Patrick Delaunay 
---

(no changes since v3)

Changes in v3:
- Use bit 30 for GPIOD_EXT_DRIVEN

 arch/sandbox/include/asm/gpio.h |  3 ++-
 drivers/gpio/sandbox.c  | 21 +++--
 2 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/arch/sandbox/include/asm/gpio.h b/arch/sandbox/include/asm/gpio.h
index 74d7a4cd959..33b83ea4cc3 100644
--- a/arch/sandbox/include/asm/gpio.h
+++ b/arch/sandbox/include/asm/gpio.h
@@ -25,8 +25,9 @@
 
 /* Our own private GPIO flags, which musn't conflict with GPIOD_... */
 #define GPIOD_EXT_HIGH BIT(31) /* external source is high (else low) */
+#define GPIOD_EXT_DRIVEN   BIT(30) /* external source is driven */
 
-#define GPIOD_SANDBOX_MASK BIT(31)
+#define GPIOD_SANDBOX_MASK GENMASK(31, 30)
 
 /**
  * Return the simulated value of a GPIO (used only in sandbox test code)
diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index d1e561ab5e6..700098446b5 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -76,16 +76,22 @@ static int set_gpio_flag(struct udevice *dev, unsigned int 
offset, ulong flag,
 int sandbox_gpio_get_value(struct udevice *dev, unsigned offset)
 {
struct gpio_state *state = get_gpio_state(dev, offset);
+   bool val;
 
if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
debug("sandbox_gpio: get_value on output gpio %u\n", offset);
 
-   return state->flags & GPIOD_EXT_HIGH ? true : false;
+   if (state->flags & GPIOD_EXT_DRIVEN)
+   val = state->flags & GPIOD_EXT_HIGH;
+   else
+   val = false;
+
+   return val;
 }
 
 int sandbox_gpio_set_value(struct udevice *dev, unsigned offset, int value)
 {
-   set_gpio_flag(dev, offset, GPIOD_EXT_HIGH, value);
+   set_gpio_flag(dev, offset, GPIOD_EXT_DRIVEN | GPIOD_EXT_HIGH, value);
 
return 0;
 }
@@ -142,8 +148,8 @@ static int sb_gpio_direction_output(struct udevice *dev, 
unsigned offset,
ret = sandbox_gpio_set_direction(dev, offset, 1);
if (ret)
return ret;
-   ret = set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE | GPIOD_EXT_HIGH,
-   value);
+   ret = set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE |
+   GPIOD_EXT_DRIVEN | GPIOD_EXT_HIGH, value);
if (ret)
return ret;
 
@@ -171,8 +177,8 @@ static int sb_gpio_set_value(struct udevice *dev, unsigned 
offset, int value)
return -1;
}
 
-   ret = set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE | GPIOD_EXT_HIGH,
-   value);
+   ret = set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE |
+   GPIOD_EXT_DRIVEN | GPIOD_EXT_HIGH, value);
if (ret)
return ret;
 
@@ -218,10 +224,13 @@ static int sb_gpio_set_flags(struct udevice *dev, 
unsigned int offset,
struct gpio_state *state = get_gpio_state(dev, offset);
 
if (flags & GPIOD_IS_OUT) {
+   flags |= GPIOD_EXT_DRIVEN;
if (flags & GPIOD_IS_OUT_ACTIVE)
flags |= GPIOD_EXT_HIGH;
else
flags &= ~GPIOD_EXT_HIGH;
+   } else {
+   flags |= state->flags & GPIOD_SANDBOX_MASK;
}
state->flags = flags;
 
-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v4 13/16] gpio: x86: Drop the deprecated methods in intel_gpio

2021-02-04 Thread Simon Glass
We don't need to implement direction_input() and direction_output()
anymore. Drop them and use update_flags() instead.

Signed-off-by: Simon Glass 
---

(no changes since v1)

 arch/x86/include/asm/intel_pinctrl_defs.h |  5 ++
 drivers/gpio/intel_gpio.c | 72 ---
 2 files changed, 43 insertions(+), 34 deletions(-)

diff --git a/arch/x86/include/asm/intel_pinctrl_defs.h 
b/arch/x86/include/asm/intel_pinctrl_defs.h
index 1ea141f082f..5d83d24bae2 100644
--- a/arch/x86/include/asm/intel_pinctrl_defs.h
+++ b/arch/x86/include/asm/intel_pinctrl_defs.h
@@ -11,6 +11,11 @@
 
 /* This file is included by device trees, so avoid BIT() macros */
 
+#define GPIO_DW_SIZE(x)(sizeof(u32) * (x))
+#define PAD_CFG_OFFSET(x, dw_num)  ((x) + GPIO_DW_SIZE(dw_num))
+#define PAD_CFG0_OFFSET(x) PAD_CFG_OFFSET(x, 0)
+#define PAD_CFG1_OFFSET(x) PAD_CFG_OFFSET(x, 1)
+
 #define PAD_CFG0_TX_STATE_BIT  0
 #define PAD_CFG0_TX_STATE  (1 << PAD_CFG0_TX_STATE_BIT)
 #define PAD_CFG0_RX_STATE_BIT  1
diff --git a/drivers/gpio/intel_gpio.c b/drivers/gpio/intel_gpio.c
index eda95485c93..ab46a94dbc1 100644
--- a/drivers/gpio/intel_gpio.c
+++ b/drivers/gpio/intel_gpio.c
@@ -3,6 +3,8 @@
  * Copyright 2019 Google LLC
  */
 
+#define LOG_CATEGORY   UCLASS_GPIO
+
 #include 
 #include 
 #include 
@@ -23,38 +25,6 @@
 #include 
 #include 
 
-static int intel_gpio_direction_input(struct udevice *dev, uint offset)
-{
-   struct udevice *pinctrl = dev_get_parent(dev);
-   uint config_offset;
-
-   config_offset = intel_pinctrl_get_config_reg_offset(pinctrl, offset);
-
-   pcr_clrsetbits32(pinctrl, config_offset,
-PAD_CFG0_MODE_MASK | PAD_CFG0_TX_STATE |
- PAD_CFG0_RX_DISABLE,
-PAD_CFG0_MODE_GPIO | PAD_CFG0_TX_DISABLE);
-
-   return 0;
-}
-
-static int intel_gpio_direction_output(struct udevice *dev, uint offset,
-  int value)
-{
-   struct udevice *pinctrl = dev_get_parent(dev);
-   uint config_offset;
-
-   config_offset = intel_pinctrl_get_config_reg_offset(pinctrl, offset);
-
-   pcr_clrsetbits32(pinctrl, config_offset,
-PAD_CFG0_MODE_MASK | PAD_CFG0_RX_STATE |
- PAD_CFG0_TX_DISABLE | PAD_CFG0_TX_STATE,
-PAD_CFG0_MODE_GPIO | PAD_CFG0_RX_DISABLE |
- (value ? PAD_CFG0_TX_STATE : 0));
-
-   return 0;
-}
-
 static int intel_gpio_get_value(struct udevice *dev, uint offset)
 {
struct udevice *pinctrl = dev_get_parent(dev);
@@ -130,6 +100,41 @@ static int intel_gpio_xlate(struct udevice *orig_dev, 
struct gpio_desc *desc,
return 0;
 }
 
+static int intel_gpio_set_flags(struct udevice *dev, unsigned int offset,
+   ulong flags)
+{
+   struct udevice *pinctrl = dev_get_parent(dev);
+   u32 bic0 = 0, bic1 = 0;
+   u32 or0, or1;
+   uint config_offset;
+
+   config_offset = intel_pinctrl_get_config_reg_offset(pinctrl, offset);
+
+   if (flags & GPIOD_IS_OUT) {
+   bic0 |= PAD_CFG0_MODE_MASK | PAD_CFG0_RX_STATE |
+   PAD_CFG0_TX_DISABLE;
+   or0 |= PAD_CFG0_MODE_GPIO | PAD_CFG0_RX_DISABLE;
+   } else if (flags & GPIOD_IS_IN) {
+   bic0 |= PAD_CFG0_MODE_MASK | PAD_CFG0_TX_STATE |
+   PAD_CFG0_RX_DISABLE;
+   or0 |= PAD_CFG0_MODE_GPIO | PAD_CFG0_TX_DISABLE;
+   }
+   if (flags & GPIOD_PULL_UP) {
+   bic1 |= PAD_CFG1_PULL_MASK;
+   or1 |= PAD_CFG1_PULL_UP_20K;
+   } else if (flags & GPIOD_PULL_DOWN) {
+   bic1 |= PAD_CFG1_PULL_MASK;
+   or1 |= PAD_CFG1_PULL_DN_20K;
+   }
+
+   pcr_clrsetbits32(pinctrl, PAD_CFG0_OFFSET(config_offset), bic0, or0);
+   pcr_clrsetbits32(pinctrl, PAD_CFG1_OFFSET(config_offset), bic1, or1);
+   log_debug("%s: flags=%lx, offset=%x, config_offset=%x, %x/%x %x/%x\n",
+ dev->name, flags, offset, config_offset, bic0, or0, bic1, 
or1);
+
+   return 0;
+}
+
 #if CONFIG_IS_ENABLED(ACPIGEN)
 static int intel_gpio_get_acpi(const struct gpio_desc *desc,
   struct acpi_gpio *gpio)
@@ -177,12 +182,11 @@ static int intel_gpio_of_to_plat(struct udevice *dev)
 }
 
 static const struct dm_gpio_ops gpio_intel_ops = {
-   .direction_input= intel_gpio_direction_input,
-   .direction_output   = intel_gpio_direction_output,
.get_value  = intel_gpio_get_value,
.set_value  = intel_gpio_set_value,
.get_function   = intel_gpio_get_function,
.xlate  = intel_gpio_xlate,
+   .set_flags  = intel_gpio_set_flags,
 #if CONFIG_IS_ENABLED(ACPIGEN)
.get_acpi   = intel_gpio_get_acpi,
 #endif

[PATCH v4 12/16] gpio: Use an 'ops' variable everywhere

2021-02-04 Thread Simon Glass
Update this driver to use the common method of putting the driver
operations in an 'ops' variable install of calling gpio_get_ops()
repeatedly. Make it const since operations do not change.

Signed-off-by: Simon Glass 

Reviewed-by: Patrick Delaunay 
---

(no changes since v1)

 drivers/gpio/gpio-uclass.c | 25 ++---
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 123794994fa..11fa17c14b2 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -219,7 +219,7 @@ int gpio_xlate_offs_flags(struct udevice *dev, struct 
gpio_desc *desc,
 static int gpio_find_and_xlate(struct gpio_desc *desc,
   struct ofnode_phandle_args *args)
 {
-   struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
+   const struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
 
if (ops->xlate)
return ops->xlate(desc->dev, desc, args);
@@ -352,6 +352,7 @@ int gpio_hog_lookup_name(const char *name, struct gpio_desc 
**desc)
 
 int dm_gpio_request(struct gpio_desc *desc, const char *label)
 {
+   const struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
struct udevice *dev = desc->dev;
struct gpio_dev_priv *uc_priv;
char *str;
@@ -363,8 +364,8 @@ int dm_gpio_request(struct gpio_desc *desc, const char 
*label)
str = strdup(label);
if (!str)
return -ENOMEM;
-   if (gpio_get_ops(dev)->request) {
-   ret = gpio_get_ops(dev)->request(dev, desc->offset, label);
+   if (ops->request) {
+   ret = ops->request(dev, desc->offset, label);
if (ret) {
free(str);
return ret;
@@ -441,14 +442,15 @@ int gpio_requestf(unsigned gpio, const char *fmt, ...)
 
 int _dm_gpio_free(struct udevice *dev, uint offset)
 {
+   const struct dm_gpio_ops *ops = gpio_get_ops(dev);
struct gpio_dev_priv *uc_priv;
int ret;
 
uc_priv = dev_get_uclass_priv(dev);
if (!uc_priv->name[offset])
return -ENXIO;
-   if (gpio_get_ops(dev)->rfree) {
-   ret = gpio_get_ops(dev)->rfree(dev, offset);
+   if (ops->rfree) {
+   ret = ops->rfree(dev, offset);
if (ret)
return ret;
}
@@ -545,9 +547,10 @@ int gpio_direction_output(unsigned gpio, int value)
 
 static int _gpio_get_value(const struct gpio_desc *desc)
 {
+   const struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
int value;
 
-   value = gpio_get_ops(desc->dev)->get_value(desc->dev, desc->offset);
+   value = ops->get_value(desc->dev, desc->offset);
 
return desc->flags & GPIOD_ACTIVE_LOW ? !value : value;
 }
@@ -643,7 +646,7 @@ static int check_dir_flags(ulong flags)
 static int _dm_gpio_set_flags(struct gpio_desc *desc, ulong flags)
 {
struct udevice *dev = desc->dev;
-   struct dm_gpio_ops *ops = gpio_get_ops(dev);
+   const struct dm_gpio_ops *ops = gpio_get_ops(dev);
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
int ret = 0;
 
@@ -710,7 +713,7 @@ int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flagsp)
 {
struct udevice *dev = desc->dev;
int ret, value;
-   struct dm_gpio_ops *ops = gpio_get_ops(dev);
+   const struct dm_gpio_ops *ops = gpio_get_ops(dev);
ulong flags;
 
ret = check_reserved(desc, "get_flags");
@@ -808,7 +811,7 @@ static int get_function(struct udevice *dev, int offset, 
bool skip_unused,
const char **namep)
 {
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
-   struct dm_gpio_ops *ops = gpio_get_ops(dev);
+   const struct dm_gpio_ops *ops = gpio_get_ops(dev);
 
BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
if (!device_active(dev))
@@ -845,7 +848,7 @@ int gpio_get_raw_function(struct udevice *dev, int offset, 
const char **namep)
 
 int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize)
 {
-   struct dm_gpio_ops *ops = gpio_get_ops(dev);
+   const struct dm_gpio_ops *ops = gpio_get_ops(dev);
struct gpio_dev_priv *priv;
char *str = buf;
int func;
@@ -885,7 +888,7 @@ int gpio_get_status(struct udevice *dev, int offset, char 
*buf, int buffsize)
 #if CONFIG_IS_ENABLED(ACPIGEN)
 int gpio_get_acpi(const struct gpio_desc *desc, struct acpi_gpio *gpio)
 {
-   struct dm_gpio_ops *ops;
+   const struct dm_gpio_ops *ops;
 
memset(gpio, '\0', sizeof(*gpio));
if (!dm_gpio_is_valid(desc)) {
-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v4 10/16] dm: gpio: Add a way to update flags

2021-02-04 Thread Simon Glass
It is convenient to be able to adjust some of the flags for a GPIO while
leaving others alone. Add a function for this.

Update dm_gpio_set_dir_flags() to make use of this.

Also update dm_gpio_set_value() to use this also, since this allows the
open-drain / open-source features to be implemented directly in the
driver, rather than using the uclass workaround.

Update the sandbox tests accordingly. This involves a lot of changes to
dm_test_gpio_opendrain_opensource() since we no-longer have the direciion
being reported differently depending on the open drain/open source flags.

Also update the STM32 drivers to let the uclass handle the active low/high
logic.

Drop the GPIOD_FLAGS_OUTPUT() macro which is no-longer used.

Signed-off-by: Simon Glass 
---

Changes in v4:
- Update dm_gpio_set_dir_flags() to clear direction flags first

Changes in v3:
- Incorporate GPIOD_FLAGS_OUTPUT() changes from Patrick Delaunay

 drivers/gpio/gpio-uclass.c  |  75 ++
 drivers/gpio/stm32_gpio.c   |   3 +-
 drivers/pinctrl/pinctrl-stmfx.c |   5 +-
 include/asm-generic/gpio.h  |  31 ++--
 test/dm/gpio.c  | 132 
 5 files changed, 203 insertions(+), 43 deletions(-)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 8931c420845..daaa1401087 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -568,6 +568,7 @@ int dm_gpio_get_value(const struct gpio_desc *desc)
 
 int dm_gpio_set_value(const struct gpio_desc *desc, int value)
 {
+   const struct dm_gpio_ops *ops;
int ret;
 
ret = check_reserved(desc, "set_value");
@@ -577,21 +578,33 @@ int dm_gpio_set_value(const struct gpio_desc *desc, int 
value)
if (desc->flags & GPIOD_ACTIVE_LOW)
value = !value;
 
+   /* GPIOD_ are directly managed by driver in set_flags */
+   ops = gpio_get_ops(desc->dev);
+   if (ops->set_flags) {
+   ulong flags = desc->flags;
+
+   if (value)
+   flags |= GPIOD_IS_OUT_ACTIVE;
+   else
+   flags &= ~GPIOD_IS_OUT_ACTIVE;
+   return ops->set_flags(desc->dev, desc->offset, flags);
+   }
+
/*
 * Emulate open drain by not actively driving the line high or
 * Emulate open source by not actively driving the line low
 */
if ((desc->flags & GPIOD_OPEN_DRAIN && value) ||
(desc->flags & GPIOD_OPEN_SOURCE && !value))
-   return gpio_get_ops(desc->dev)->direction_input(desc->dev,
-   desc->offset);
+   return ops->direction_input(desc->dev, desc->offset);
else if (desc->flags & GPIOD_OPEN_DRAIN ||
 desc->flags & GPIOD_OPEN_SOURCE)
-   return gpio_get_ops(desc->dev)->direction_output(desc->dev,
-   desc->offset,
-   value);
+   return ops->direction_output(desc->dev, desc->offset, value);
+
+   ret = ops->set_value(desc->dev, desc->offset, value);
+   if (ret)
+   return ret;
 
-   gpio_get_ops(desc->dev)->set_value(desc->dev, desc->offset, value);
return 0;
 }
 
@@ -619,6 +632,17 @@ static int check_dir_flags(ulong flags)
return 0;
 }
 
+/**
+ * _dm_gpio_set_flags() - Send flags to the driver
+ *
+ * This uses the best available method to send the given flags to the driver.
+ * Note that if flags & GPIOD_ACTIVE_LOW, the driver sees the opposite value
+ * of GPIOD_IS_OUT_ACTIVE.
+ *
+ * @desc:  GPIO description
+ * @flags: flags value to set
+ * @return 0 if OK, -ve on error
+ */
 static int _dm_gpio_set_flags(struct gpio_desc *desc, ulong flags)
 {
struct udevice *dev = desc->dev;
@@ -637,38 +661,52 @@ static int _dm_gpio_set_flags(struct gpio_desc *desc, 
ulong flags)
return ret;
}
 
+   /* If active low, invert the output state */
+   if ((flags & (GPIOD_IS_OUT | GPIOD_ACTIVE_LOW)) ==
+   (GPIOD_IS_OUT | GPIOD_ACTIVE_LOW))
+   flags ^= GPIOD_IS_OUT_ACTIVE;
+
/* GPIOD_ are directly managed by driver in set_flags */
if (ops->set_flags) {
ret = ops->set_flags(dev, desc->offset, flags);
} else {
if (flags & GPIOD_IS_OUT) {
-   ret = ops->direction_output(dev, desc->offset,
-   GPIOD_FLAGS_OUTPUT(flags));
+   bool value = flags & GPIOD_IS_OUT_ACTIVE;
+
+   ret = ops->direction_output(dev, desc->offset, value);
} else if (flags & GPIOD_IS_IN) {
ret = ops->direction_input(dev, desc->offset);
}
}
 
-   /* save the flags also in descriptor */
-   if (!ret)
-  

[PATCH v4 11/16] gpio: Replace direction_input() and direction_output()

2021-02-04 Thread Simon Glass
The new update_flags() method is more flexible since it allows the
driver to see the full flags all at once. Use that in preference to these
two functions. Add comments to that effect.

Signed-off-by: Simon Glass 

Reviewed-by: Patrick Delaunay 
---

(no changes since v1)

 drivers/gpio/gpio-uclass.c | 15 ++-
 include/asm-generic/gpio.h | 26 +-
 2 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index daaa1401087..123794994fa 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -512,13 +512,10 @@ int gpio_direction_input(unsigned gpio)
int ret;
 
ret = gpio_to_device(gpio, );
-   if (ret)
-   return ret;
-   ret = check_reserved(, "dir_input");
if (ret)
return ret;
 
-   return gpio_get_ops(desc.dev)->direction_input(desc.dev, desc.offset);
+   return dm_gpio_clrset_flags(, GPIOD_MASK_DIR, GPIOD_IS_IN);
 }
 
 /**
@@ -533,17 +530,17 @@ int gpio_direction_input(unsigned gpio)
 int gpio_direction_output(unsigned gpio, int value)
 {
struct gpio_desc desc;
+   ulong flags;
int ret;
 
ret = gpio_to_device(gpio, );
-   if (ret)
-   return ret;
-   ret = check_reserved(, "dir_output");
if (ret)
return ret;
 
-   return gpio_get_ops(desc.dev)->direction_output(desc.dev,
-   desc.offset, value);
+   flags = GPIOD_IS_OUT;
+   if (value)
+   flags |= GPIOD_IS_OUT_ACTIVE;
+   return dm_gpio_clrset_flags(, GPIOD_MASK_DIR, flags);
 }
 
 static int _gpio_get_value(const struct gpio_desc *desc)
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index af3ce21a7cf..457ecb19cd3 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -260,10 +260,32 @@ int gpio_xlate_offs_flags(struct udevice *dev, struct 
gpio_desc *desc,
 struct dm_gpio_ops {
int (*request)(struct udevice *dev, unsigned offset, const char *label);
int (*rfree)(struct udevice *dev, unsigned int offset);
+
+   /**
+* direction_input() - deprecated
+*
+* Equivalent to set_flags(...GPIOD_IS_IN)
+*/
int (*direction_input)(struct udevice *dev, unsigned offset);
+
+   /**
+* direction_output() - deprecated
+*
+* Equivalent to set_flags(...GPIOD_IS_OUT) with GPIOD_IS_OUT_ACTIVE
+* also set if @value
+*/
int (*direction_output)(struct udevice *dev, unsigned offset,
int value);
+
int (*get_value)(struct udevice *dev, unsigned offset);
+
+   /**
+* set_value() - Sets the GPIO value of an output
+*
+* If the driver provides an @set_flags() method then that is used
+* in preference to this, with GPIOD_IS_OUT_ACTIVE set according to
+* @value.
+*/
int (*set_value)(struct udevice *dev, unsigned offset, int value);
/**
 * get_function() Get the GPIO function
@@ -320,7 +342,9 @@ struct dm_gpio_ops {
 * uclass, so the driver always sees the value that should be set at the
 * pin (1=high, 0=low).
 *
-* This method is optional.
+* This method is required and should be implemented by new drivers. At
+* some point, it will supersede direction_input() and
+* direction_output(), which wil be removed.
 *
 * @dev:GPIO device
 * @offset: GPIO offset within that device
-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v4 09/16] gpio: sandbox: Make sandbox_gpio_set_flags() set all flags

2021-02-04 Thread Simon Glass
Allow this function to see all flags, including the internal sandbox ones.
This allows the tests to fully control the behaviour of the driver.

To make this work, move the setting of GPIOD_EXT_HIGH -to where the flags
are updated via driver model, rather than the sandbox 'back door'.

Signed-off-by: Simon Glass 

Reviewed-by: Patrick Delaunay 
---

(no changes since v1)

 drivers/gpio/sandbox.c | 21 -
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index 912c333e560..d1e561ab5e6 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -114,13 +114,7 @@ int sandbox_gpio_set_flags(struct udevice *dev, uint 
offset, ulong flags)
 {
struct gpio_state *state = get_gpio_state(dev, offset);
 
-   /*
-* We don't need to clear GPIOD_EXT_HIGH here to make the tests pass,
-* but this is handled in a future patch.
-*/
-   if (flags & GPIOD_IS_OUT_ACTIVE)
-   flags |= GPIOD_EXT_HIGH;
-   state->flags = (state->flags & GPIOD_SANDBOX_MASK) | flags;
+   state->flags = flags;
 
return 0;
 }
@@ -221,14 +215,23 @@ static int sb_gpio_set_flags(struct udevice *dev, 
unsigned int offset,
 ulong flags)
 {
debug("%s: offset:%u, flags = %lx\n", __func__, offset, flags);
+   struct gpio_state *state = get_gpio_state(dev, offset);
 
-   return sandbox_gpio_set_flags(dev, offset, flags);
+   if (flags & GPIOD_IS_OUT) {
+   if (flags & GPIOD_IS_OUT_ACTIVE)
+   flags |= GPIOD_EXT_HIGH;
+   else
+   flags &= ~GPIOD_EXT_HIGH;
+   }
+   state->flags = flags;
+
+   return 0;
 }
 
 static int sb_gpio_get_flags(struct udevice *dev, uint offset, ulong *flagsp)
 {
debug("%s: offset:%u\n", __func__, offset);
-   *flagsp = *get_gpio_flags(dev, offset);
+   *flagsp = *get_gpio_flags(dev, offset) & ~GPIOD_SANDBOX_MASK;
 
return 0;
 }
-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v4 06/16] gpio: sandbox: Rename GPIO dir_flags to flags

2021-02-04 Thread Simon Glass
Adjust the terminology in this driver to reflect that fact that all flags
are handled, not just direction flags.

Create a new access function to get the full GPIO state, not just the
direction flags. Drop the static invalid_dir_flags since we can rely on a
segfault if something is wrong.

Signed-off-by: Simon Glass 
Reviewed-by: Patrick Delaunay 
---

(no changes since v3)

Changes in v3:
- Drop 'dir' in 'GPIO dir flags' comment

Changes in v2:
- Swap newf and flags in sb_gpio_set_flags()

 arch/sandbox/include/asm/gpio.h |  8 ++---
 drivers/gpio/sandbox.c  | 60 +++--
 test/dm/gpio.c  | 18 +-
 3 files changed, 47 insertions(+), 39 deletions(-)

diff --git a/arch/sandbox/include/asm/gpio.h b/arch/sandbox/include/asm/gpio.h
index df4ba4fb5f3..20d78296551 100644
--- a/arch/sandbox/include/asm/gpio.h
+++ b/arch/sandbox/include/asm/gpio.h
@@ -69,17 +69,17 @@ int sandbox_gpio_set_direction(struct udevice *dev, 
unsigned int offset,
  * @param offset   GPIO offset within bank
  * @return dir_flags: bitfield accesses by GPIOD_ defines
  */
-ulong sandbox_gpio_get_dir_flags(struct udevice *dev, unsigned int offset);
+ulong sandbox_gpio_get_flags(struct udevice *dev, unsigned int offset);
 
 /**
  * Set the simulated flags of a GPIO (used only in sandbox test code)
  *
  * @param dev  device to use
  * @param offset   GPIO offset within bank
- * @param flagsdir_flags: bitfield accesses by GPIOD_ defines
+ * @param flagsbitfield accesses by GPIOD_ defines
  * @return -1 on error, 0 if ok
  */
-int sandbox_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
-  ulong flags);
+int sandbox_gpio_set_flags(struct udevice *dev, unsigned int offset,
+  ulong flags);
 
 #endif
diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index 38dc34ee910..6f2eed50bf1 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -22,34 +22,44 @@
 
 struct gpio_state {
const char *label;  /* label given by requester */
-   ulong dir_flags;/* dir_flags (GPIOD_...) */
+   ulong flags;/* flags (GPIOD_...) */
 };
 
-/* Access routines for GPIO dir flags */
-static ulong *get_gpio_dir_flags(struct udevice *dev, unsigned int offset)
+/* Access routines for GPIO info */
+static struct gpio_state *get_gpio_state(struct udevice *dev, uint offset)
 {
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
struct gpio_state *state = dev_get_priv(dev);
 
if (offset >= uc_priv->gpio_count) {
-   static ulong invalid_dir_flags;
printf("sandbox_gpio: error: invalid gpio %u\n", offset);
-   return _dir_flags;
+   return NULL;
}
 
-   return [offset].dir_flags;
+   return [offset];
+}
+
+/* Access routines for GPIO flags */
+static ulong *get_gpio_flags(struct udevice *dev, unsigned int offset)
+{
+   struct gpio_state *state = get_gpio_state(dev, offset);
+
+   if (!state)
+   return NULL;
+
+   return >flags;
 
 }
 
 static int get_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag)
 {
-   return (*get_gpio_dir_flags(dev, offset) & flag) != 0;
+   return (*get_gpio_flags(dev, offset) & flag) != 0;
 }
 
 static int set_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag,
 int value)
 {
-   ulong *gpio = get_gpio_dir_flags(dev, offset);
+   ulong *gpio = get_gpio_flags(dev, offset);
 
if (value)
*gpio |= flag;
@@ -88,15 +98,14 @@ int sandbox_gpio_set_direction(struct udevice *dev, 
unsigned offset, int output)
return 0;
 }
 
-ulong sandbox_gpio_get_dir_flags(struct udevice *dev, unsigned int offset)
+ulong sandbox_gpio_get_flags(struct udevice *dev, uint offset)
 {
-   return *get_gpio_dir_flags(dev, offset);
+   return *get_gpio_flags(dev, offset);
 }
 
-int sandbox_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
-  ulong flags)
+int sandbox_gpio_set_flags(struct udevice *dev, uint offset, ulong flags)
 {
-   *get_gpio_dir_flags(dev, offset) = flags;
+   *get_gpio_flags(dev, offset) = flags;
 
return 0;
 }
@@ -180,30 +189,29 @@ static int sb_gpio_xlate(struct udevice *dev, struct 
gpio_desc *desc,
 static int sb_gpio_set_flags(struct udevice *dev, unsigned int offset,
 ulong flags)
 {
-   ulong *dir_flags;
+   ulong *newf;
 
-   debug("%s: offset:%u, dir_flags = %lx\n", __func__, offset, flags);
+   debug("%s: offset:%u, flags = %lx\n", __func__, offset, flags);
 
-   dir_flags = get_gpio_dir_flags(dev, offset);
+   newf = get_gpio_flags(dev, offset);
 
/*
 * For testing purposes keep the output value when switching to input.
 * This allows us to manipulate the input value via the 

[PATCH v4 08/16] gpio: sandbox: Fully separate pin value from output value

2021-02-04 Thread Simon Glass
At present we have the concept of a pin's external value. This is what
is used when getting the value of a pin. But we still set the
GPIOD_IS_OUT_ACTIVE flag when changing the value. This is not actually
correct, since if the pin changes from output to input, the external
value need not change. Adjust the logic for this difference.

Signed-off-by: Simon Glass 

Reviewed-by: Patrick Delaunay 
---

(no changes since v1)

 drivers/gpio/sandbox.c | 24 
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index 4d73b954b26..912c333e560 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -85,7 +85,7 @@ int sandbox_gpio_get_value(struct udevice *dev, unsigned 
offset)
 
 int sandbox_gpio_set_value(struct udevice *dev, unsigned offset, int value)
 {
-   set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE | GPIOD_EXT_HIGH, value);
+   set_gpio_flag(dev, offset, GPIOD_EXT_HIGH, value);
 
return 0;
 }
@@ -141,10 +141,19 @@ static int sb_gpio_direction_input(struct udevice *dev, 
unsigned offset)
 static int sb_gpio_direction_output(struct udevice *dev, unsigned offset,
int value)
 {
+   int ret;
+
debug("%s: offset:%u, value = %d\n", __func__, offset, value);
 
-   return sandbox_gpio_set_direction(dev, offset, 1) |
-   sandbox_gpio_set_value(dev, offset, value);
+   ret = sandbox_gpio_set_direction(dev, offset, 1);
+   if (ret)
+   return ret;
+   ret = set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE | GPIOD_EXT_HIGH,
+   value);
+   if (ret)
+   return ret;
+
+   return 0;
 }
 
 /* read GPIO IN value of port 'offset' */
@@ -158,6 +167,8 @@ static int sb_gpio_get_value(struct udevice *dev, unsigned 
offset)
 /* write GPIO OUT value to port 'offset' */
 static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
 {
+   int ret;
+
debug("%s: offset:%u, value = %d\n", __func__, offset, value);
 
if (!sandbox_gpio_get_direction(dev, offset)) {
@@ -166,7 +177,12 @@ static int sb_gpio_set_value(struct udevice *dev, unsigned 
offset, int value)
return -1;
}
 
-   return sandbox_gpio_set_value(dev, offset, value);
+   ret = set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE | GPIOD_EXT_HIGH,
+   value);
+   if (ret)
+   return ret;
+
+   return 0;
 }
 
 static int sb_gpio_get_function(struct udevice *dev, unsigned offset)
-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v4 07/16] gpio: sandbox: Use a separate flag for the value

2021-02-04 Thread Simon Glass
At present with the sandbox GPIO driver it is not possible to change the
value of GPIOD_IS_OUT_ACTIVE unless the GPIO is an output. This makes it
hard to test changing the flags since we need to be aware of the internal
workings of the driver.

The feature is designed to aid testing.

Split this feature out into a separate sandbox-specific flag, so that the
flags can change unimpeded. This will make it easier to allow updating the
flags in a future patch.

Signed-off-by: Simon Glass 
---

(no changes since v3)

Changes in v3:
- Start at BIT(31) for sandbox-specific flags
- Add a comment to sandbox_gpio_set_flags() about clearing GPIOD_EXT_HIGH

 arch/sandbox/include/asm/gpio.h |  5 
 drivers/gpio/sandbox.c  | 47 +
 2 files changed, 29 insertions(+), 23 deletions(-)

diff --git a/arch/sandbox/include/asm/gpio.h b/arch/sandbox/include/asm/gpio.h
index 20d78296551..74d7a4cd959 100644
--- a/arch/sandbox/include/asm/gpio.h
+++ b/arch/sandbox/include/asm/gpio.h
@@ -23,6 +23,11 @@
  */
 #include 
 
+/* Our own private GPIO flags, which musn't conflict with GPIOD_... */
+#define GPIOD_EXT_HIGH BIT(31) /* external source is high (else low) */
+
+#define GPIOD_SANDBOX_MASK BIT(31)
+
 /**
  * Return the simulated value of a GPIO (used only in sandbox test code)
  *
diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index 6f2eed50bf1..4d73b954b26 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -59,12 +59,12 @@ static int get_gpio_flag(struct udevice *dev, unsigned int 
offset, ulong flag)
 static int set_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag,
 int value)
 {
-   ulong *gpio = get_gpio_flags(dev, offset);
+   struct gpio_state *state = get_gpio_state(dev, offset);
 
if (value)
-   *gpio |= flag;
+   state->flags |= flag;
else
-   *gpio &= ~flag;
+   state->flags &= ~flag;
 
return 0;
 }
@@ -75,14 +75,19 @@ static int set_gpio_flag(struct udevice *dev, unsigned int 
offset, ulong flag,
 
 int sandbox_gpio_get_value(struct udevice *dev, unsigned offset)
 {
+   struct gpio_state *state = get_gpio_state(dev, offset);
+
if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
debug("sandbox_gpio: get_value on output gpio %u\n", offset);
-   return get_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE);
+
+   return state->flags & GPIOD_EXT_HIGH ? true : false;
 }
 
 int sandbox_gpio_set_value(struct udevice *dev, unsigned offset, int value)
 {
-   return set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE, value);
+   set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE | GPIOD_EXT_HIGH, value);
+
+   return 0;
 }
 
 int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset)
@@ -93,19 +98,29 @@ int sandbox_gpio_get_direction(struct udevice *dev, 
unsigned offset)
 int sandbox_gpio_set_direction(struct udevice *dev, unsigned offset, int 
output)
 {
set_gpio_flag(dev, offset, GPIOD_IS_OUT, output);
-   set_gpio_flag(dev, offset, GPIOD_IS_IN, !(output));
+   set_gpio_flag(dev, offset, GPIOD_IS_IN, !output);
 
return 0;
 }
 
 ulong sandbox_gpio_get_flags(struct udevice *dev, uint offset)
 {
-   return *get_gpio_flags(dev, offset);
+   ulong flags = *get_gpio_flags(dev, offset);
+
+   return flags & ~GPIOD_SANDBOX_MASK;
 }
 
 int sandbox_gpio_set_flags(struct udevice *dev, uint offset, ulong flags)
 {
-   *get_gpio_flags(dev, offset) = flags;
+   struct gpio_state *state = get_gpio_state(dev, offset);
+
+   /*
+* We don't need to clear GPIOD_EXT_HIGH here to make the tests pass,
+* but this is handled in a future patch.
+*/
+   if (flags & GPIOD_IS_OUT_ACTIVE)
+   flags |= GPIOD_EXT_HIGH;
+   state->flags = (state->flags & GPIOD_SANDBOX_MASK) | flags;
 
return 0;
 }
@@ -189,23 +204,9 @@ static int sb_gpio_xlate(struct udevice *dev, struct 
gpio_desc *desc,
 static int sb_gpio_set_flags(struct udevice *dev, unsigned int offset,
 ulong flags)
 {
-   ulong *newf;
-
debug("%s: offset:%u, flags = %lx\n", __func__, offset, flags);
 
-   newf = get_gpio_flags(dev, offset);
-
-   /*
-* For testing purposes keep the output value when switching to input.
-* This allows us to manipulate the input value via the gpio command.
-*/
-   if (flags & GPIOD_IS_IN)
-   *newf = (flags & ~GPIOD_IS_OUT_ACTIVE) |
-   (*newf & GPIOD_IS_OUT_ACTIVE);
-   else
-   *newf = flags;
-
-   return 0;
+   return sandbox_gpio_set_flags(dev, offset, flags);
 }
 
 static int sb_gpio_get_flags(struct udevice *dev, uint offset, ulong *flagsp)
-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v4 05/16] gpio: Drop dm_gpio_set_dir()

2021-02-04 Thread Simon Glass
This function is not used. Drop it.

Signed-off-by: Simon Glass 

Reviewed-by: Patrick Delaunay 
---

(no changes since v1)

 drivers/gpio/gpio-uclass.c | 11 ---
 include/asm-generic/gpio.h | 11 ---
 2 files changed, 22 deletions(-)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 87254b0781b..8931c420845 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -671,17 +671,6 @@ int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong 
flags)
return ret;
 }
 
-int dm_gpio_set_dir(struct gpio_desc *desc)
-{
-   int ret;
-
-   ret = check_reserved(desc, "set_dir");
-   if (ret)
-   return ret;
-
-   return _dm_gpio_set_flags(desc, desc->flags);
-}
-
 int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flagsp)
 {
struct udevice *dev = desc->dev;
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 4f8d1938da9..f7f10c469c0 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -657,17 +657,6 @@ int dm_gpio_get_value(const struct gpio_desc *desc);
 
 int dm_gpio_set_value(const struct gpio_desc *desc, int value);
 
-/**
- * dm_gpio_set_dir() - Set the direction for a GPIO
- *
- * This sets up the direction according to the GPIO flags: desc->flags.
- *
- * @desc:  GPIO description containing device, offset and flags,
- * previously returned by gpio_request_by_name()
- * @return 0 if OK, -ve on error
- */
-int dm_gpio_set_dir(struct gpio_desc *desc);
-
 /**
  * dm_gpio_set_dir_flags() - Set direction using description and added flags
  *
-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v4 04/16] gpio: Rename dm_gpio_get_dir_flags() to dm_gpio_get_flags()

2021-02-04 Thread Simon Glass
This function can be used to get any flags, not just direction flags.
Rename it to avoid confusion.

Signed-off-by: Simon Glass 
Reviewed-by: Patrick Delaunay 
Reviewed-by: Pratyush Yadav 
---

(no changes since v3)

Changes in v3:
- Drop the word 'direction' in comments also

 drivers/gpio/gpio-uclass.c |  2 +-
 include/asm-generic/gpio.h |  6 +++---
 test/dm/gpio.c | 12 ++--
 3 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index c5cb9b92b36..87254b0781b 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -682,7 +682,7 @@ int dm_gpio_set_dir(struct gpio_desc *desc)
return _dm_gpio_set_flags(desc, desc->flags);
 }
 
-int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flagsp)
+int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flagsp)
 {
struct udevice *dev = desc->dev;
int ret, value;
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 153312d8af4..4f8d1938da9 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -683,16 +683,16 @@ int dm_gpio_set_dir(struct gpio_desc *desc);
 int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags);
 
 /**
- * dm_gpio_get_dir_flags() - Get direction flags
+ * dm_gpio_get_flags() - Get flags
  *
- * read the current direction flags
+ * Read the current flags
  *
  * @desc:  GPIO description containing device, offset and flags,
  * previously returned by gpio_request_by_name()
  * @flags: place to put the used flags
  * @return 0 if OK, -ve on error, in which case desc->flags is not updated
  */
-int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flags);
+int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flags);
 
 /**
  * gpio_get_number() - Get the global GPIO number of a GPIO
diff --git a/test/dm/gpio.c b/test/dm/gpio.c
index 36bbaedb01c..c583d2b3447 100644
--- a/test/dm/gpio.c
+++ b/test/dm/gpio.c
@@ -397,22 +397,22 @@ static int dm_test_gpio_get_dir_flags(struct 
unit_test_state *uts)
ut_asserteq(6, gpio_request_list_by_name(dev, "test3-gpios", desc_list,
 ARRAY_SIZE(desc_list), 0));
 
-   ut_assertok(dm_gpio_get_dir_flags(_list[0], ));
+   ut_assertok(dm_gpio_get_flags(_list[0], ));
ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN, flags);
 
-   ut_assertok(dm_gpio_get_dir_flags(_list[1], ));
+   ut_assertok(dm_gpio_get_flags(_list[1], ));
ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_SOURCE, flags);
 
-   ut_assertok(dm_gpio_get_dir_flags(_list[2], ));
+   ut_assertok(dm_gpio_get_flags(_list[2], ));
ut_asserteq(GPIOD_IS_OUT, flags);
 
-   ut_assertok(dm_gpio_get_dir_flags(_list[3], ));
+   ut_assertok(dm_gpio_get_flags(_list[3], ));
ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_UP, flags);
 
-   ut_assertok(dm_gpio_get_dir_flags(_list[4], ));
+   ut_assertok(dm_gpio_get_flags(_list[4], ));
ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_DOWN, flags);
 
-   ut_assertok(dm_gpio_get_dir_flags(_list[5], ));
+   ut_assertok(dm_gpio_get_flags(_list[5], ));
ut_asserteq(GPIOD_IS_IN, flags);
 
ut_assertok(gpio_free_list(dev, desc_list, 6));
-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v4 02/16] dm: gpio: Rename set_dir_flags() method to update_flags()

2021-02-04 Thread Simon Glass
The current method is a misnomer since it is also used (e.g. by stm32) to
update pull settings and open source/open drain.

Rename it and expand the documentation to cover a few more details.

Signed-off-by: Simon Glass 
Reviewed-by: Pratyush Yadav 

Reviewed-by: Patrick Delaunay 
---

(no changes since v2)

Changes in v2:
- Use set_flags() instead of update_flags()
- Fix 'provide' typo while we are here
- Make operation of set_flags() deterministic

 drivers/gpio/gpio-uclass.c  | 16 
 drivers/gpio/sandbox.c  |  6 +++---
 drivers/gpio/stm32_gpio.c   |  6 +++---
 drivers/pinctrl/pinctrl-stmfx.c |  6 +++---
 include/asm-generic/gpio.h  | 28 ++--
 test/dm/gpio.c  |  8 
 6 files changed, 43 insertions(+), 27 deletions(-)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index e84b68db772..d59e5df4b4a 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -619,7 +619,7 @@ static int check_dir_flags(ulong flags)
return 0;
 }
 
-static int _dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
+static int _dm_gpio_set_flags(struct gpio_desc *desc, ulong flags)
 {
struct udevice *dev = desc->dev;
struct dm_gpio_ops *ops = gpio_get_ops(dev);
@@ -637,9 +637,9 @@ static int _dm_gpio_set_dir_flags(struct gpio_desc *desc, 
ulong flags)
return ret;
}
 
-   /* GPIOD_ are directly managed by driver in set_dir_flags*/
-   if (ops->set_dir_flags) {
-   ret = ops->set_dir_flags(dev, desc->offset, flags);
+   /* GPIOD_ are directly managed by driver in set_flags */
+   if (ops->set_flags) {
+   ret = ops->set_flags(dev, desc->offset, flags);
} else {
if (flags & GPIOD_IS_OUT) {
ret = ops->direction_output(dev, desc->offset,
@@ -666,7 +666,7 @@ int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong 
flags)
 
/* combine the requested flags (for IN/OUT) and the descriptor flags */
flags |= desc->flags;
-   ret = _dm_gpio_set_dir_flags(desc, flags);
+   ret = _dm_gpio_set_flags(desc, flags);
 
return ret;
 }
@@ -679,7 +679,7 @@ int dm_gpio_set_dir(struct gpio_desc *desc)
if (ret)
return ret;
 
-   return _dm_gpio_set_dir_flags(desc, desc->flags);
+   return _dm_gpio_set_flags(desc, desc->flags);
 }
 
 int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flags)
@@ -1307,8 +1307,8 @@ static int gpio_post_bind(struct udevice *dev)
ops->get_function += gd->reloc_off;
if (ops->xlate)
ops->xlate += gd->reloc_off;
-   if (ops->set_dir_flags)
-   ops->set_dir_flags += gd->reloc_off;
+   if (ops->set_flags)
+   ops->set_flags += gd->reloc_off;
if (ops->get_dir_flags)
ops->get_dir_flags += gd->reloc_off;
 
diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index dc8d506e8d4..05f17928f0a 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -177,8 +177,8 @@ static int sb_gpio_xlate(struct udevice *dev, struct 
gpio_desc *desc,
return 0;
 }
 
-static int sb_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
-ulong flags)
+static int sb_gpio_set_flags(struct udevice *dev, unsigned int offset,
+ulong flags)
 {
ulong *dir_flags;
 
@@ -272,7 +272,7 @@ static const struct dm_gpio_ops gpio_sandbox_ops = {
.set_value  = sb_gpio_set_value,
.get_function   = sb_gpio_get_function,
.xlate  = sb_gpio_xlate,
-   .set_dir_flags  = sb_gpio_set_dir_flags,
+   .set_flags  = sb_gpio_set_flags,
.get_dir_flags  = sb_gpio_get_dir_flags,
 #if CONFIG_IS_ENABLED(ACPIGEN)
.get_acpi   = sb_gpio_get_acpi,
diff --git a/drivers/gpio/stm32_gpio.c b/drivers/gpio/stm32_gpio.c
index 7184db3c527..6d1bef63c36 100644
--- a/drivers/gpio/stm32_gpio.c
+++ b/drivers/gpio/stm32_gpio.c
@@ -191,8 +191,8 @@ static int stm32_gpio_get_function(struct udevice *dev, 
unsigned int offset)
return GPIOF_FUNC;
 }
 
-static int stm32_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
-   ulong flags)
+static int stm32_gpio_set_flags(struct udevice *dev, unsigned int offset,
+   ulong flags)
 {
struct stm32_gpio_priv *priv = dev_get_priv(dev);
struct stm32_gpio_regs *regs = priv->regs;
@@ -270,7 +270,7 @@ static const struct dm_gpio_ops gpio_stm32_ops = {
.get_value  = stm32_gpio_get_value,
.set_value  = stm32_gpio_set_value,
.get_function   = stm32_gpio_get_function,
-   .set_dir_flags  = 

[PATCH v4 03/16] dm: gpio: Rename get_dir_flags() method to get_flags()

2021-02-04 Thread Simon Glass
It is more useful to be able to read all the flags, not just the direction
ones. In fact this is what the STM32 driver does. Update the method name
to reflect this.

Tweak the docs a little and use 'flagsp' as the return argument, as is
common in driver model, to indicate it returns a value.

Signed-off-by: Simon Glass 
Reviewed-by: Patrick Delaunay 

Reviewed-by: Pratyush Yadav 
---

(no changes since v1)

 drivers/gpio/gpio-uclass.c  | 30 +++---
 drivers/gpio/sandbox.c  |  8 
 drivers/gpio/stm32_gpio.c   |  8 
 drivers/pinctrl/pinctrl-stmfx.c |  8 
 include/asm-generic/gpio.h  | 11 ++-
 5 files changed, 33 insertions(+), 32 deletions(-)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index d59e5df4b4a..c5cb9b92b36 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -682,39 +682,39 @@ int dm_gpio_set_dir(struct gpio_desc *desc)
return _dm_gpio_set_flags(desc, desc->flags);
 }
 
-int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flags)
+int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flagsp)
 {
struct udevice *dev = desc->dev;
int ret, value;
struct dm_gpio_ops *ops = gpio_get_ops(dev);
-   ulong dir_flags;
+   ulong flags;
 
-   ret = check_reserved(desc, "get_dir_flags");
+   ret = check_reserved(desc, "get_flags");
if (ret)
return ret;
 
/* GPIOD_ are directly provided by driver except GPIOD_ACTIVE_LOW */
-   if (ops->get_dir_flags) {
-   ret = ops->get_dir_flags(dev, desc->offset, _flags);
+   if (ops->get_flags) {
+   ret = ops->get_flags(dev, desc->offset, );
if (ret)
return ret;
 
/* GPIOD_ACTIVE_LOW is saved in desc->flags */
-   value = dir_flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0;
+   value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0;
if (desc->flags & GPIOD_ACTIVE_LOW)
value = !value;
-   dir_flags &= ~(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE);
-   dir_flags |= (desc->flags & GPIOD_ACTIVE_LOW);
+   flags &= ~(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE);
+   flags |= (desc->flags & GPIOD_ACTIVE_LOW);
if (value)
-   dir_flags |= GPIOD_IS_OUT_ACTIVE;
+   flags |= GPIOD_IS_OUT_ACTIVE;
} else {
-   dir_flags = desc->flags;
+   flags = desc->flags;
/* only GPIOD_IS_OUT_ACTIVE is provided by uclass */
-   dir_flags &= ~GPIOD_IS_OUT_ACTIVE;
+   flags &= ~GPIOD_IS_OUT_ACTIVE;
if ((desc->flags & GPIOD_IS_OUT) && _gpio_get_value(desc))
-   dir_flags |= GPIOD_IS_OUT_ACTIVE;
+   flags |= GPIOD_IS_OUT_ACTIVE;
}
-   *flags = dir_flags;
+   *flagsp = flags;
 
return 0;
 }
@@ -1309,8 +1309,8 @@ static int gpio_post_bind(struct udevice *dev)
ops->xlate += gd->reloc_off;
if (ops->set_flags)
ops->set_flags += gd->reloc_off;
-   if (ops->get_dir_flags)
-   ops->get_dir_flags += gd->reloc_off;
+   if (ops->get_flags)
+   ops->get_flags += gd->reloc_off;
 
reloc_done++;
}
diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index 05f17928f0a..38dc34ee910 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -199,11 +199,11 @@ static int sb_gpio_set_flags(struct udevice *dev, 
unsigned int offset,
return 0;
 }
 
-static int sb_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
-ulong *flags)
+static int sb_gpio_get_flags(struct udevice *dev, unsigned int offset,
+ulong *flagsp)
 {
debug("%s: offset:%u\n", __func__, offset);
-   *flags = *get_gpio_dir_flags(dev, offset);
+   *flagsp = *get_gpio_dir_flags(dev, offset);
 
return 0;
 }
@@ -273,7 +273,7 @@ static const struct dm_gpio_ops gpio_sandbox_ops = {
.get_function   = sb_gpio_get_function,
.xlate  = sb_gpio_xlate,
.set_flags  = sb_gpio_set_flags,
-   .get_dir_flags  = sb_gpio_get_dir_flags,
+   .get_flags  = sb_gpio_get_flags,
 #if CONFIG_IS_ENABLED(ACPIGEN)
.get_acpi   = sb_gpio_get_acpi,
 #endif
diff --git a/drivers/gpio/stm32_gpio.c b/drivers/gpio/stm32_gpio.c
index 6d1bef63c36..c2d7046c0dd 100644
--- a/drivers/gpio/stm32_gpio.c
+++ b/drivers/gpio/stm32_gpio.c
@@ -223,8 +223,8 @@ static int stm32_gpio_set_flags(struct udevice *dev, 
unsigned int offset,
return 0;
 }
 
-static int stm32_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
-  

[PATCH v4 00/16] gpio: Update and simplify the uclass API

2021-02-04 Thread Simon Glass
At present the GPIO uclass mirrors what was in U-Boot before driver model.
It works well in most cases but is becoming cumbersome with things like
pull-up/down and drive strength. In those cases it is easier for the
driver to deal with all the flags at one, rather than piece by piece.

In fact the current API does not officially have a method for adjusting
anything other than the direction flags. While set_dir_flags() and
get_dir_flags() do in fact support changing other flags, this is not
documented.

Secondly, set_dir_flags actually ORs the current flags with the new ones
so it is not possible to clear flags. It seems better to use a clr/set
interface (bit clear followed by OR) to provide more flexibility.

Finally, direction_input() and direction_output() are really just the same
thing as set_dir_flags(), with a different name. We currently use the
latter if available, failing back to the former. But it makes sense to
deprecate the old methods.

This series makes the above changes. Existing drivers are mostly left
alone, since they should continue to operate as is. The sandbox driver is
updated to add the required new tests and the x86 driver is switched over
to the new API.

The STM32 driver should be checked to make sure the open source/open drain
features still work as intended.

Changes in v4:
- Update dm_gpio_set_dir_flags() to clear direction flags first

Changes in v3:
- Drop the word 'direction' in comments also
- Drop 'dir' in 'GPIO dir flags' comment
- Start at BIT(31) for sandbox-specific flags
- Add a comment to sandbox_gpio_set_flags() about clearing GPIOD_EXT_HIGH
- Incorporate GPIOD_FLAGS_OUTPUT() changes from Patrick Delaunay
- Use bit 30 for GPIOD_EXT_DRIVEN
- Split out the log-category change to a separate patch
- Use bits 28, 29 for the new flags
- Assert that count parameter is within range
- Redo digit logic to be easier to understand
- Update function comment to explain the meaning of the digits
- Fix 'compare' typo

Changes in v2:
- Use set_flags() instead of update_flags()
- Fix 'provide' typo while we are here
- Make operation of set_flags() deterministic
- Swap newf and flags in sb_gpio_set_flags()

Simon Glass (16):
  gpio: Disable functions not used with of-platdata
  dm: gpio: Rename set_dir_flags() method to update_flags()
  dm: gpio: Rename get_dir_flags() method to get_flags()
  gpio: Rename dm_gpio_get_dir_flags() to dm_gpio_get_flags()
  gpio: Drop dm_gpio_set_dir()
  gpio: sandbox: Rename GPIO dir_flags to flags
  gpio: sandbox: Use a separate flag for the value
  gpio: sandbox: Fully separate pin value from output value
  gpio: sandbox: Make sandbox_gpio_set_flags() set all flags
  dm: gpio: Add a way to update flags
  gpio: Replace direction_input() and direction_output()
  gpio: Use an 'ops' variable everywhere
  gpio: x86: Drop the deprecated methods in intel_gpio
  gpio: sandbox: Track whether a GPIO is driven
  gpio: Define the log category in the uclass
  gpio: Add a way to read 3-way strapping pins

 arch/sandbox/include/asm/gpio.h   |  17 +-
 arch/x86/include/asm/intel_pinctrl_defs.h |   5 +
 drivers/gpio/gpio-uclass.c| 243 ++--
 drivers/gpio/intel_gpio.c |  72 +++---
 drivers/gpio/sandbox.c| 138 +++
 drivers/gpio/stm32_gpio.c |  17 +-
 drivers/pinctrl/pinctrl-stmfx.c   |  19 +-
 include/asm-generic/gpio.h| 139 +--
 test/dm/gpio.c| 268 +++---
 9 files changed, 690 insertions(+), 228 deletions(-)

-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v4 01/16] gpio: Disable functions not used with of-platdata

2021-02-04 Thread Simon Glass
These functions use devicetree and cannot work with of-platdata, which has
no runtime devicetree.

If they are used, the current linker error is confusing, since it talks
about missing functions in the bowels of driver model.

Avoid compiling these functions at all with of-platdata, so that a
straightforward link error points to the problem.

Series-changes; 3
- Fix 'wprl' typo

Signed-off-by: Simon Glass 

Reviewed-by: Patrick Delaunay 
---

(no changes since v1)

 drivers/gpio/gpio-uclass.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index bad6b71e0c3..e84b68db772 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -1023,6 +1023,7 @@ err:
return ret;
 }
 
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
 static int _gpio_request_by_name_nodev(ofnode node, const char *list_name,
   int index, struct gpio_desc *desc,
   int flags, bool add_index)
@@ -1109,6 +1110,7 @@ int gpio_get_list_count(struct udevice *dev, const char 
*list_name)
 
return ret;
 }
+#endif /* OF_PLATDATA */
 
 int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc)
 {
-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v3 2/2] x86: coral: Show memory config and SKU ID on startup

2021-02-04 Thread Simon Glass
Provide the model information through sysinfo so that it shows up on
boot. For memconfig 4 pins are provided, for 16 combinations. For SKU
ID there are two options:

   - two pins provided in a ternary arrangement, for 9 combinations.
   - reading from the EC

Add a binding doc and drop the unused #defines as well.

Example:

   U-Boot 2021.01-rc5

   CPU:   Intel(R) Celeron(R) CPU N3450 @ 1.10GHz
   DRAM:  3.9 GiB
   MMC:   sdmmc@1b,0: 1, emmc@1c,0: 2
   Video: 1024x768x32 @ b000
   Model: Google Coral (memconfig 5, SKU 3)

Signed-off-by: Simon Glass 

Acked-by: Bin Meng 
---

Changes in v3:
- Rebase to master
- Drop patches previously applied

Changes in v2:
- Fix two missing asterisks in comments

 arch/x86/dts/chromebook_coral.dts |  11 ++
 board/google/chromebook_coral/coral.c | 143 +-
 board/google/chromebook_coral/variant_gpio.h  |   6 -
 .../sysinfo/google,coral.txt  |  37 +
 include/sysinfo.h |   2 +-
 5 files changed, 184 insertions(+), 15 deletions(-)
 create mode 100644 doc/device-tree-bindings/sysinfo/google,coral.txt

diff --git a/arch/x86/dts/chromebook_coral.dts 
b/arch/x86/dts/chromebook_coral.dts
index 2ffe3b423c3..18bbafe5981 100644
--- a/arch/x86/dts/chromebook_coral.dts
+++ b/arch/x86/dts/chromebook_coral.dts
@@ -55,6 +55,17 @@
recovery-gpios = <_nw (-1) GPIO_ACTIVE_LOW>;
write-protect-gpios = <_nw GPIO_75 GPIO_ACTIVE_HIGH>;
phase-enforce-gpios = <_n GPIO_10 GPIO_ACTIVE_HIGH>;
+   memconfig-gpios = <_nw GPIO_101 GPIO_ACTIVE_HIGH
+   _nw GPIO_102 GPIO_ACTIVE_HIGH
+   _n GPIO_38 GPIO_ACTIVE_HIGH
+   _n GPIO_45 GPIO_ACTIVE_HIGH>;
+
+   /*
+* This is used for reef only:
+*
+* skuconfig-gpios = <_nw GPIO_16 GPIO_ACTIVE_HIGH
+*  _nw GPIO_17 GPIO_ACTIVE_HIGH>;
+*/
smbios {
/* Type 1 table */
system {
diff --git a/board/google/chromebook_coral/coral.c 
b/board/google/chromebook_coral/coral.c
index 34b2c2ac5d5..23f2f5ab596 100644
--- a/board/google/chromebook_coral/coral.c
+++ b/board/google/chromebook_coral/coral.c
@@ -3,17 +3,22 @@
  * Copyright 2019 Google LLC
  */
 
+#define LOG_CATEGORY   UCLASS_SYSINFO
+
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include "variant_gpio.h"
 
 struct cros_gpio_info {
@@ -28,10 +33,125 @@ int arch_misc_init(void)
return 0;
 }
 
-/* This function is needed if CONFIG_CMDLINE is not enabled */
-int board_run_command(const char *cmdline)
+static int get_memconfig(struct udevice *dev)
+{
+   struct gpio_desc gpios[4];
+   int cfg;
+   int ret;
+
+   ret = gpio_request_list_by_name(dev, "memconfig-gpios", gpios,
+   ARRAY_SIZE(gpios),
+   GPIOD_IS_IN | GPIOD_PULL_UP);
+   if (ret < 0) {
+   log_debug("Cannot get GPIO list '%s' (%d)\n", dev->name, ret);
+   return ret;
+   }
+
+   /* Give the lines time to settle */
+   udelay(10);
+
+   ret = dm_gpio_get_values_as_int(gpios, ARRAY_SIZE(gpios));
+   if (ret < 0)
+   return log_msg_ret("get", ret);
+   cfg = ret;
+
+   ret = gpio_free_list(dev, gpios, ARRAY_SIZE(gpios));
+   if (ret)
+   return log_msg_ret("free", ret);
+
+   return cfg;
+}
+
+/**
+ * get_skuconfig() - Get the SKU number either from pins or the EC
+ *
+ * Two options are supported:
+ * skuconfig-gpios - two pins in the device tree (tried first)
+ * EC  - reading from the EC (backup)
+ *
+ * @dev: sysinfo device to use
+ * @return SKU ID, or -ve error if not found
+ */
+static int get_skuconfig(struct udevice *dev)
 {
-   printf("No command line\n");
+   struct gpio_desc gpios[2];
+   int cfg;
+   int ret;
+
+   ret = gpio_request_list_by_name(dev, "skuconfig-gpios", gpios,
+   ARRAY_SIZE(gpios),
+   GPIOD_IS_IN);
+   if (ret != ARRAY_SIZE(gpios)) {
+   struct udevice *cros_ec;
+
+   log_debug("Cannot get GPIO list '%s' (%d)\n", dev->name, ret);
+
+   /* Try the EC */
+   ret = uclass_first_device_err(UCLASS_CROS_EC, _ec);
+   if (ret < 0) {
+   log_err("Cannot find EC for SKU details\n");
+   return log_msg_ret("sku", ret);
+   }
+   ret = cros_ec_get_sku_id(cros_ec);
+   if (ret < 0) {
+   log_err("Cannot read SKU details\n");
+   return log_msg_ret("sku", ret);
+   }
+
+   return ret;

Re: [PATCH v4 12/12] smbios: Allow a few values to come from sysinfo

2021-02-04 Thread Simon Glass
Hi Bin,

On Thu, 4 Feb 2021 at 21:17, Simon Glass  wrote:
>
> While static configuration is useful it cannot cover every case. Sometimes
> board revisions are encoded in resistor straps and must be read at
> runtime.
>
> The easiest way to provide this information is via sysinfo, since the
> board can then provide a driver to read whatever is needed.
>
> Add some standard sysinfo options for this, and use them to obtain the
> required information.
>
> Signed-off-by: Simon Glass 
> Reviewed-by: Bin Meng 
> ---
>
> (no changes since v3)
>
> Changes in v3:
> - Use SMBIOS_STR_MAX for the max sysinfo string length
>
>  include/sysinfo.h | 11 +++
>  lib/smbios.c  | 32 +---
>  2 files changed, 40 insertions(+), 3 deletions(-)

Sorry this cannot be applied yet. It depends on the GPIO series.

Regards,
Simon


[PATCH v3 0/2] x86: Minor improvements mostly for image loading

2021-02-04 Thread Simon Glass
This series provides a few improvements for loading of images. It also
provides a way to show more detailed model information as well as an
of-platdata fix noticed recently.

Note that this series depends on the GPIO series here:

   http://patchwork.ozlabs.org/project/uboot/list/?series=226118

Changes in v3:
- Rebase to master
- Rebase to master
- Drop patches previously applied

Changes in v2:
- Fix two missing asterisks in comments

Simon Glass (2):
  sysinfo: Allow showing model info from sysinfo
  x86: coral: Show memory config and SKU ID on startup

 arch/x86/dts/chromebook_coral.dts |  11 ++
 board/google/chromebook_coral/coral.c | 143 +-
 board/google/chromebook_coral/variant_gpio.h  |   6 -
 common/board_info.c   |  37 -
 .../sysinfo/google,coral.txt  |  37 +
 include/sysinfo.h |  17 ++-
 6 files changed, 228 insertions(+), 23 deletions(-)
 create mode 100644 doc/device-tree-bindings/sysinfo/google,coral.txt

-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v3 1/2] sysinfo: Allow showing model info from sysinfo

2021-02-04 Thread Simon Glass
Some boards may want to show the SKU ID or other information obtained at
runtime. Allow this to come from sysinfo. The board can then provide a
sysinfo driver to provide it.

Signed-off-by: Simon Glass 
Reviewed-by: Bin Meng 
---

Changes in v3:
- Rebase to master

 common/board_info.c | 37 +
 include/sysinfo.h   | 15 +++
 2 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/common/board_info.c b/common/board_info.c
index a6db087f960..20a2dea1f35 100644
--- a/common/board_info.c
+++ b/common/board_info.c
@@ -1,30 +1,51 @@
 // SPDX-License-Identifier: GPL-2.0+
 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
 
+DECLARE_GLOBAL_DATA_PTR;
+
 int __weak checkboard(void)
 {
return 0;
 }
 
 /*
- * If the root node of the DTB has a "model" property, show it.
+ * Check sysinfo for board information. Failing that if the root node of the 
DTB
+ * has a "model" property, show it.
+ *
  * Then call checkboard().
  */
 int __weak show_board_info(void)
 {
-#ifdef CONFIG_OF_CONTROL
-   DECLARE_GLOBAL_DATA_PTR;
-   const char *model;
+   if (IS_ENABLED(CONFIG_OF_CONTROL)) {
+   struct udevice *dev;
+   const char *model;
+   char str[80];
+   int ret = -ENOSYS;
+
+   if (IS_ENABLED(CONFIG_SYSINFO)) {
+   /* This might provide more detail */
+   ret = uclass_first_device_err(UCLASS_SYSINFO, );
+   if (!ret)
+   ret = sysinfo_get_str(dev,
+ SYSINFO_ID_BOARD_MODEL,
+ sizeof(str), str);
+   }
 
-   model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
+   /* Fail back to the main 'model' if available */
+   if (ret)
+   model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
+   else
+   model = str;
 
-   if (model)
-   printf("Model: %s\n", model);
-#endif
+   if (model)
+   printf("Model: %s\n", model);
+   }
 
return checkboard();
 }
diff --git a/include/sysinfo.h b/include/sysinfo.h
index c045d316b07..8bd2343e7bf 100644
--- a/include/sysinfo.h
+++ b/include/sysinfo.h
@@ -32,6 +32,21 @@
  */
 
 #if CONFIG_IS_ENABLED(SYSINFO)
+/** enum sysinfo_id - Standard IDs defined by U-Boot */
+enum sysinfo_id {
+   SYSINFO_ID_NONE,
+
+   /* For SMBIOS tables */
+   SYSINFO_ID_SMBIOS_SYSTEM_VERSION,
+   SYSINFO_ID_SMBIOS_BASEBOARD_VERSION,
+
+   /* For show_board_info() */
+   SYSINFO_ID_BOARD_MODEL,
+
+   /* First value available for downstream/board used */
+   SYSINFO_ID_USER = 0x1000,
+};
+
 struct sysinfo_ops {
/**
 * detect() - Run the hardware info detection procedure for this
-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v4 12/12] smbios: Allow a few values to come from sysinfo

2021-02-04 Thread Simon Glass
While static configuration is useful it cannot cover every case. Sometimes
board revisions are encoded in resistor straps and must be read at
runtime.

The easiest way to provide this information is via sysinfo, since the
board can then provide a driver to read whatever is needed.

Add some standard sysinfo options for this, and use them to obtain the
required information.

Signed-off-by: Simon Glass 
Reviewed-by: Bin Meng 
---

(no changes since v3)

Changes in v3:
- Use SMBIOS_STR_MAX for the max sysinfo string length

 include/sysinfo.h | 11 +++
 lib/smbios.c  | 32 +---
 2 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/include/sysinfo.h b/include/sysinfo.h
index 6e021253524..743f3554659 100644
--- a/include/sysinfo.h
+++ b/include/sysinfo.h
@@ -31,6 +31,17 @@
  * to read the serial number.
  */
 
+/** enum sysinfo_id - Standard IDs defined by U-Boot */
+enum sysinfo_id {
+   SYSINFO_ID_NONE,
+
+   SYSINFO_ID_SMBIOS_SYSTEM_VERSION,
+   SYSINFO_ID_SMBIOS_BASEBOARD_VERSION,
+
+   /* First value available for downstream/board used */
+   SYSINFO_ID_USER = 0x1000,
+};
+
 struct sysinfo_ops {
/**
 * detect() - Run the hardware info detection procedure for this
diff --git a/lib/smbios.c b/lib/smbios.c
index e8bfc9ee1ce..7d463c84a93 100644
--- a/lib/smbios.c
+++ b/lib/smbios.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #ifdef CONFIG_CPU
@@ -108,14 +109,25 @@ static int smbios_add_string(struct smbios_ctx *ctx, 
const char *str)
 }
 
 /**
- * smbios_add_prop() - Add a property from the device tree
+ * smbios_add_prop_si() - Add a property from the devicetree or sysinfo
+ *
+ * Sysinfo is used if available, with a fallback to devicetree
  *
  * @ctx:   context for writing the tables
  * @prop:  property to write
  * @return 0 if not found, else SMBIOS string number (1 or more)
  */
-static int smbios_add_prop(struct smbios_ctx *ctx, const char *prop)
+static int smbios_add_prop_si(struct smbios_ctx *ctx, const char *prop,
+ int sysinfo_id)
 {
+   if (sysinfo_id && ctx->dev) {
+   char val[SMBIOS_STR_MAX];
+   int ret;
+
+   ret = sysinfo_get_str(ctx->dev, sysinfo_id, sizeof(val), val);
+   if (!ret)
+   return smbios_add_string(ctx, val);
+   }
if (IS_ENABLED(CONFIG_OF_CONTROL)) {
const char *str;
 
@@ -127,6 +139,17 @@ static int smbios_add_prop(struct smbios_ctx *ctx, const 
char *prop)
return 0;
 }
 
+/**
+ * smbios_add_prop() - Add a property from the devicetree
+ *
+ * @prop:  property to write
+ * @return 0 if not found, else SMBIOS string number (1 or more)
+ */
+static int smbios_add_prop(struct smbios_ctx *ctx, const char *prop)
+{
+   return smbios_add_prop_si(ctx, prop, SYSINFO_ID_NONE);
+}
+
 static void smbios_set_eos(struct smbios_ctx *ctx, char *eos)
 {
ctx->eos = eos;
@@ -240,7 +263,8 @@ static int smbios_write_type1(ulong *current, int handle,
smbios_set_eos(ctx, t->eos);
t->manufacturer = smbios_add_prop(ctx, "manufacturer");
t->product_name = smbios_add_prop(ctx, "product");
-   t->version = smbios_add_prop(ctx, "version");
+   t->version = smbios_add_prop_si(ctx, "version",
+   SYSINFO_ID_SMBIOS_SYSTEM_VERSION);
if (serial_str) {
t->serial_number = smbios_add_string(ctx, serial_str);
strncpy((char *)t->uuid, serial_str, sizeof(t->uuid));
@@ -269,6 +293,8 @@ static int smbios_write_type2(ulong *current, int handle,
smbios_set_eos(ctx, t->eos);
t->manufacturer = smbios_add_prop(ctx, "manufacturer");
t->product_name = smbios_add_prop(ctx, "product");
+   t->version = smbios_add_prop_si(ctx, "version",
+   SYSINFO_ID_SMBIOS_BASEBOARD_VERSION);
t->asset_tag_number = smbios_add_prop(ctx, "asset-tag");
t->feature_flags = SMBIOS_BOARD_FEATURE_HOSTING;
t->board_type = SMBIOS_BOARD_MOTHERBOARD;
-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v4 11/12] x86: coral: Add sysinfo ops

2021-02-04 Thread Simon Glass
These ops are missing at present which is not permitted. Add an empty
operation struct.

Note: If the uclass requires operations then the drivers should provide
them. Otherwise, checking for missing operations must be done in every
uclass operation, so it adds to code size.

Signed-off-by: Simon Glass 
Reviewed-by: Bin Meng 
---

(no changes since v3)

Changes in v3:
- Expand commit to explain why operations are required

Changes in v2:
- Add new patch to fix crash on coral

 board/google/chromebook_coral/coral.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/board/google/chromebook_coral/coral.c 
b/board/google/chromebook_coral/coral.c
index 34b2c2ac5d5..f9fb3f163f0 100644
--- a/board/google/chromebook_coral/coral.c
+++ b/board/google/chromebook_coral/coral.c
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -143,6 +144,9 @@ struct acpi_ops coral_acpi_ops = {
.inject_dsdt= chromeos_acpi_gpio_generate,
 };
 
+struct sysinfo_ops coral_sysinfo_ops = {
+};
+
 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
 static const struct udevice_id coral_ids[] = {
{ .compatible = "google,coral" },
@@ -154,5 +158,6 @@ U_BOOT_DRIVER(coral_drv) = {
.name   = "coral",
.id = UCLASS_SYSINFO,
.of_match   = of_match_ptr(coral_ids),
+   .ops= _sysinfo_ops,
ACPI_OPS_PTR(_acpi_ops)
 };
-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v4 09/12] smbios: Add more options for the BIOS version string

2021-02-04 Thread Simon Glass
At present the version string is obtained from PLAIN_VERSION. Some boards
may want to configure this using the device tree, since the build system
can more easily insert things there after U-Boot itself is built. Add this
option to the code.

Also in some cases the version needs to be generated programmatically,
such as when it is stored elsewhere in the ROM and must be read first.
To handle this, keep a pointer around so that it can be updated later.
This works by storing the last string in the context, since it is easier
than passing out a little-used extra parameter.

Provide a function to update the version string.

Signed-off-by: Simon Glass 
Reviewed-by: Bin Meng 
---

(no changes since v3)

Changes in v3:
- Add missing DECLARE_GLOBAL_DATA_PTR

Changes in v2:
- Correct documentation format

 include/asm-generic/global_data.h |  6 
 include/smbios.h  | 12 +++
 lib/smbios.c  | 58 +--
 3 files changed, 73 insertions(+), 3 deletions(-)

diff --git a/include/asm-generic/global_data.h 
b/include/asm-generic/global_data.h
index b6f707e97e5..6c9ca57e083 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -447,6 +447,12 @@ struct global_data {
 */
struct acpi_ctx *acpi_ctx;
 #endif
+#if CONFIG_IS_ENABLED(GENERATE_SMBIOS_TABLE)
+   /**
+* @smbios_version: Points to SMBIOS type 0 version
+*/
+   char *smbios_version;
+#endif
 };
 
 /**
diff --git a/include/smbios.h b/include/smbios.h
index 1cbeabf9522..ecc4fd1de3b 100644
--- a/include/smbios.h
+++ b/include/smbios.h
@@ -257,4 +257,16 @@ const struct smbios_header *smbios_header(const struct 
smbios_entry *entry, int
  */
 const char *smbios_string(const struct smbios_header *header, int index);
 
+/**
+ * smbios_update_version() - Update the version string
+ *
+ * This can be called after the SMBIOS tables are written (e.g. after the 
U-Boot
+ * main loop has started) to update the BIOS version string (SMBIOS table 0).
+ *
+ * @version: New version string to use
+ * @return 0 if OK, -ENOENT if no version string was previously written,
+ * -ENOSPC if the new string is too large to fit
+ */
+int smbios_update_version(const char *version);
+
 #endif /* _SMBIOS_H_ */
diff --git a/lib/smbios.c b/lib/smbios.c
index a7273529cc4..e8bfc9ee1ce 100644
--- a/lib/smbios.c
+++ b/lib/smbios.c
@@ -17,6 +17,12 @@
 #include 
 #endif
 
+DECLARE_GLOBAL_DATA_PTR;
+
+enum {
+   SMBIOS_STR_MAX  = 64,   /* Maximum length allowed for a string */
+};
+
 /**
  * struct smbios_ctx - context for writing SMBIOS tables
  *
@@ -27,12 +33,15 @@
  * @next_ptr:  pointer to the start of the next string to be added. When the
  * table is nopt empty, this points to the byte after the \0 of the
  * previous string.
+ * @last_str:  points to the last string that was written to the table, or NULL
+ * if none
  */
 struct smbios_ctx {
ofnode node;
struct udevice *dev;
char *eos;
char *next_ptr;
+   char *last_str;
 };
 
 /**
@@ -78,6 +87,7 @@ static int smbios_add_string(struct smbios_ctx *ctx, const 
char *str)
 
for (;;) {
if (!*p) {
+   ctx->last_str = p;
strcpy(p, str);
p += strlen(str);
*p++ = '\0';
@@ -87,8 +97,10 @@ static int smbios_add_string(struct smbios_ctx *ctx, const 
char *str)
return i;
}
 
-   if (!strcmp(p, str))
+   if (!strcmp(p, str)) {
+   ctx->last_str = p;
return i;
+   }
 
p += strlen(p) + 1;
i++;
@@ -119,6 +131,35 @@ static void smbios_set_eos(struct smbios_ctx *ctx, char 
*eos)
 {
ctx->eos = eos;
ctx->next_ptr = eos;
+   ctx->last_str = NULL;
+}
+
+int smbios_update_version(const char *version)
+{
+   char *ptr = gd->smbios_version;
+   uint old_len, len;
+
+   if (!ptr)
+   return log_ret(-ENOENT);
+
+   /*
+* This string is supposed to have at least enough bytes and is
+* padded with spaces. Update it, taking care not to move the
+* \0 terminator, so that other strings in the string table
+* are not disturbed. See smbios_add_string()
+*/
+   old_len = strnlen(ptr, SMBIOS_STR_MAX);
+   len = strnlen(version, SMBIOS_STR_MAX);
+   if (len > old_len)
+   return log_ret(-ENOSPC);
+
+   log_debug("Replacing SMBIOS type 0 version string '%s'\n", ptr);
+   memcpy(ptr, version, len);
+#ifdef LOG_DEBUG
+   print_buffer((ulong)ptr, ptr, 1, old_len + 1, 0);
+#endif
+
+   return 0;
 }
 
 /**
@@ -146,7 +187,18 @@ static int smbios_write_type0(ulong *current, int handle,
fill_smbios_header(t, SMBIOS_BIOS_INFORMATION, len, handle);
smbios_set_eos(ctx, 

[PATCH v4 10/12] sysinfo: Move #ifdef so that operations are always defined

2021-02-04 Thread Simon Glass
At present the struct is not available unless SYSINFO is enabled. This is
annoying since code it is not possible to use compile-time checks like
CONFIG_IS_ENABLED(SYSINFO) with this header.

Fix it by moving the #ifdef.

Signed-off-by: Simon Glass 

Reviewed-by: Bin Meng 
---

(no changes since v2)

Changes in v2:
- Add new patch to fix sysinfo with CONFIG_IS_ENABLED()

 include/sysinfo.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/sysinfo.h b/include/sysinfo.h
index c045d316b07..6e021253524 100644
--- a/include/sysinfo.h
+++ b/include/sysinfo.h
@@ -31,7 +31,6 @@
  * to read the serial number.
  */
 
-#if CONFIG_IS_ENABLED(SYSINFO)
 struct sysinfo_ops {
/**
 * detect() - Run the hardware info detection procedure for this
@@ -102,6 +101,7 @@ struct sysinfo_ops {
 
 #define sysinfo_get_ops(dev)   ((struct sysinfo_ops *)(dev)->driver->ops)
 
+#if CONFIG_IS_ENABLED(SYSINFO)
 /**
  * sysinfo_detect() - Run the hardware info detection procedure for this 
device.
  *
-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v4 08/12] smbios: Track the end of the string table

2021-02-04 Thread Simon Glass
Add a new member to the context struct which tracks the end of the string
table. This allows us to avoid recalculating this at the end.

Signed-off-by: Simon Glass 

Reviewed-by: Bin Meng 
---

(no changes since v1)

 lib/smbios.c | 32 +++-
 1 file changed, 15 insertions(+), 17 deletions(-)

diff --git a/lib/smbios.c b/lib/smbios.c
index 43628d67579..a7273529cc4 100644
--- a/lib/smbios.c
+++ b/lib/smbios.c
@@ -24,11 +24,15 @@
  * @dev:   sysinfo device to use (NULL if none)
  * @eos:   end-of-string pointer for the table being processed. This is set
  * up when we start processing a table
+ * @next_ptr:  pointer to the start of the next string to be added. When the
+ * table is nopt empty, this points to the byte after the \0 of the
+ * previous string.
  */
 struct smbios_ctx {
ofnode node;
struct udevice *dev;
char *eos;
+   char *next_ptr;
 };
 
 /**
@@ -77,6 +81,7 @@ static int smbios_add_string(struct smbios_ctx *ctx, const 
char *str)
strcpy(p, str);
p += strlen(str);
*p++ = '\0';
+   ctx->next_ptr = p;
*p++ = '\0';
 
return i;
@@ -113,6 +118,7 @@ static int smbios_add_prop(struct smbios_ctx *ctx, const 
char *prop)
 static void smbios_set_eos(struct smbios_ctx *ctx, char *eos)
 {
ctx->eos = eos;
+   ctx->next_ptr = eos;
 }
 
 /**
@@ -120,21 +126,13 @@ static void smbios_set_eos(struct smbios_ctx *ctx, char 
*eos)
  *
  * This computes the size of the string area including the string terminator.
  *
- * @start: string area start address
+ * @ctx:   SMBIOS context
  * @return:string area size
  */
-static int smbios_string_table_len(char *start)
+static int smbios_string_table_len(const struct smbios_ctx *ctx)
 {
-   char *p = start;
-   int i, len = 0;
-
-   while (*p) {
-   i = strlen(p) + 1;
-   p += i;
-   len += i;
-   }
-
-   return len + 1;
+   /* Allow for the final \0 after all strings */
+   return (ctx->next_ptr + 1) - ctx->eos;
 }
 
 static int smbios_write_type0(ulong *current, int handle,
@@ -170,7 +168,7 @@ static int smbios_write_type0(ulong *current, int handle,
t->ec_major_release = 0xff;
t->ec_minor_release = 0xff;
 
-   len = t->length + smbios_string_table_len(t->eos);
+   len = t->length + smbios_string_table_len(ctx);
*current += len;
unmap_sysmem(t);
 
@@ -200,7 +198,7 @@ static int smbios_write_type1(ulong *current, int handle,
t->sku_number = smbios_add_prop(ctx, "sku");
t->family = smbios_add_prop(ctx, "family");
 
-   len = t->length + smbios_string_table_len(t->eos);
+   len = t->length + smbios_string_table_len(ctx);
*current += len;
unmap_sysmem(t);
 
@@ -223,7 +221,7 @@ static int smbios_write_type2(ulong *current, int handle,
t->feature_flags = SMBIOS_BOARD_FEATURE_HOSTING;
t->board_type = SMBIOS_BOARD_MOTHERBOARD;
 
-   len = t->length + smbios_string_table_len(t->eos);
+   len = t->length + smbios_string_table_len(ctx);
*current += len;
unmap_sysmem(t);
 
@@ -247,7 +245,7 @@ static int smbios_write_type3(ulong *current, int handle,
t->thermal_state = SMBIOS_STATE_SAFE;
t->security_status = SMBIOS_SECURITY_NONE;
 
-   len = t->length + smbios_string_table_len(t->eos);
+   len = t->length + smbios_string_table_len(ctx);
*current += len;
unmap_sysmem(t);
 
@@ -306,7 +304,7 @@ static int smbios_write_type4(ulong *current, int handle,
t->l3_cache_handle = 0x;
t->processor_family2 = t->processor_family;
 
-   len = t->length + smbios_string_table_len(t->eos);
+   len = t->length + smbios_string_table_len(ctx);
*current += len;
unmap_sysmem(t);
 
-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v4 07/12] smbios: Drop the eos parameter

2021-02-04 Thread Simon Glass
We can store this in the context and avoid passing it to each function.
This makes it easier to follow and will also allow keeping track of the
end of the string table (in future patches).

Add an 'eos' field to the context and create a function to set it up.

Signed-off-by: Simon Glass 
Reviewed-by: Bin Meng 
---

(no changes since v3)

Changes in v3:
- Fix comment for smbios_add_prop()
- Rename set_eos() to smbios_set_eos()

 lib/smbios.c | 60 +++-
 1 file changed, 36 insertions(+), 24 deletions(-)

diff --git a/lib/smbios.c b/lib/smbios.c
index 4d2cb0f85e2..43628d67579 100644
--- a/lib/smbios.c
+++ b/lib/smbios.c
@@ -22,10 +22,13 @@
  *
  * @node:  node containing the information to write (ofnode_null() if none)
  * @dev:   sysinfo device to use (NULL if none)
+ * @eos:   end-of-string pointer for the table being processed. This is set
+ * up when we start processing a table
  */
 struct smbios_ctx {
ofnode node;
struct udevice *dev;
+   char *eos;
 };
 
 /**
@@ -57,14 +60,15 @@ struct smbios_write_method {
  * This adds a string to the string area which is appended directly after
  * the formatted portion of an SMBIOS structure.
  *
- * @start: string area start address
+ * @ctx:   SMBIOS context
  * @str:   string to add
  * @return:string number in the string area (1 or more)
  */
-static int smbios_add_string(char *start, const char *str)
+static int smbios_add_string(struct smbios_ctx *ctx, const char *str)
 {
int i = 1;
-   char *p = start;
+   char *p = ctx->eos;
+
if (!*str)
str = "Unknown";
 
@@ -89,26 +93,28 @@ static int smbios_add_string(char *start, const char *str)
 /**
  * smbios_add_prop() - Add a property from the device tree
  *
- * @start: string area start address
  * @ctx:   context for writing the tables
  * @prop:  property to write
  * @return 0 if not found, else SMBIOS string number (1 or more)
  */
-static int smbios_add_prop(char *start, struct smbios_ctx *ctx,
-  const char *prop)
+static int smbios_add_prop(struct smbios_ctx *ctx, const char *prop)
 {
-
if (IS_ENABLED(CONFIG_OF_CONTROL)) {
const char *str;
 
str = ofnode_read_string(ctx->node, prop);
if (str)
-   return smbios_add_string(start, str);
+   return smbios_add_string(ctx, str);
}
 
return 0;
 }
 
+static void smbios_set_eos(struct smbios_ctx *ctx, char *eos)
+{
+   ctx->eos = eos;
+}
+
 /**
  * smbios_string_table_len() - compute the string area size
  *
@@ -140,9 +146,10 @@ static int smbios_write_type0(ulong *current, int handle,
t = map_sysmem(*current, len);
memset(t, 0, sizeof(struct smbios_type0));
fill_smbios_header(t, SMBIOS_BIOS_INFORMATION, len, handle);
-   t->vendor = smbios_add_string(t->eos, "U-Boot");
-   t->bios_ver = smbios_add_string(t->eos, PLAIN_VERSION);
-   t->bios_release_date = smbios_add_string(t->eos, U_BOOT_DMI_DATE);
+   smbios_set_eos(ctx, t->eos);
+   t->vendor = smbios_add_string(ctx, "U-Boot");
+   t->bios_ver = smbios_add_string(ctx, PLAIN_VERSION);
+   t->bios_release_date = smbios_add_string(ctx, U_BOOT_DMI_DATE);
 #ifdef CONFIG_ROM_SIZE
t->bios_rom_size = (CONFIG_ROM_SIZE / 65536) - 1;
 #endif
@@ -180,17 +187,18 @@ static int smbios_write_type1(ulong *current, int handle,
t = map_sysmem(*current, len);
memset(t, 0, sizeof(struct smbios_type1));
fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, handle);
-   t->manufacturer = smbios_add_prop(t->eos, ctx, "manufacturer");
-   t->product_name = smbios_add_prop(t->eos, ctx, "product");
-   t->version = smbios_add_prop(t->eos, ctx, "version");
+   smbios_set_eos(ctx, t->eos);
+   t->manufacturer = smbios_add_prop(ctx, "manufacturer");
+   t->product_name = smbios_add_prop(ctx, "product");
+   t->version = smbios_add_prop(ctx, "version");
if (serial_str) {
-   t->serial_number = smbios_add_string(t->eos, serial_str);
+   t->serial_number = smbios_add_string(ctx, serial_str);
strncpy((char *)t->uuid, serial_str, sizeof(t->uuid));
} else {
-   t->serial_number = smbios_add_prop(t->eos, ctx, "serial");
+   t->serial_number = smbios_add_prop(ctx, "serial");
}
-   t->sku_number = smbios_add_prop(t->eos, ctx, "sku");
-   t->family = smbios_add_prop(t->eos, ctx, "family");
+   t->sku_number = smbios_add_prop(ctx, "sku");
+   t->family = smbios_add_prop(ctx, "family");
 
len = t->length + smbios_string_table_len(t->eos);
*current += len;
@@ -208,9 +216,10 @@ static int smbios_write_type2(ulong *current, int handle,
t = map_sysmem(*current, len);
memset(t, 0, sizeof(struct smbios_type2));

[PATCH v4 02/12] Makefile: Provide numeric versions

2021-02-04 Thread Simon Glass
For SMBIOS we want to store the numeric version numbers in the tables. It
does not make sense to parse the strings. Instead, add new #defines with
the version and patchlevel.

Signed-off-by: Simon Glass 
Reviewed-by: Bin Meng 
---

(no changes since v3)

Changes in v3:
- Use .rst file instead of README

 Makefile| 4 
 doc/develop/version.rst | 8 
 2 files changed, 12 insertions(+)

diff --git a/Makefile b/Makefile
index 23dd11f723a..ebbedb1fb1a 100644
--- a/Makefile
+++ b/Makefile
@@ -1853,9 +1853,13 @@ prepare: prepare0
 # Generate some files
 # ---
 
+# Use sed to remove leading zeros from PATCHLEVEL to avoid using octal numbers
 define filechk_version.h
(echo \#define PLAIN_VERSION \"$(UBOOTRELEASE)\"; \
echo \#define U_BOOT_VERSION \"U-Boot \" PLAIN_VERSION; \
+   echo \#define U_BOOT_VERSION_NUM $(VERSION); \
+   echo \#define U_BOOT_VERSION_NUM_PATCH $$(echo $(PATCHLEVEL) | \
+   sed -e "s/^0*//"); \
echo \#define CC_VERSION_STRING \"$$(LC_ALL=C $(CC) --version | head -n 
1)\"; \
echo \#define LD_VERSION_STRING \"$$(LC_ALL=C $(LD) --version | head -n 
1)\"; )
 endef
diff --git a/doc/develop/version.rst b/doc/develop/version.rst
index 6da31a4a1e7..a7797db41bb 100644
--- a/doc/develop/version.rst
+++ b/doc/develop/version.rst
@@ -69,6 +69,14 @@ The following are available:
  U-Boot 2020.10 (Jan 06 2021 - 08:50:36 -0700)
  U-Boot 2021.01-rc5-00248-g60dd854f3ba-dirty (Jan 06 2021 - 08:50:36 
-0700) for spring
 
+   U_BOOT_VERSION_NUM (integer #define)
+  Release year, e.g. 2021 for release 2021.01. Note
+  this is an integer, not a string.
+
+   U_BOOT_VERSION_NUM_PATCH (integer #define)
+  Patch number, e.g. 1 for release 2020.01. Note
+  this is an integer, not a string.
+
 Build date/time is also included. See the generated file
 include/generated/timestamp_autogenerated.h for the available
 fields. For example::
-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v4 06/12] smbios: Use a struct to keep track of context

2021-02-04 Thread Simon Glass
At present we pass the ofnode to each function. We also pass the 'eos'
pointer for adding new strings. We don't track the current end of the
string table, so have smbios_string_table_len() to find that.

The code can be made more efficient if it keeps information in a
context struct. This also makes it easier to add more features.

As a first step, switch the ofnode parameter to be a context pointer.
Update smbios_add_prop() at the same time to avoid changing the same
lines of code in consecutive patches.

Signed-off-by: Simon Glass 
Reviewed-by: Bin Meng 
---

(no changes since v2)

Changes in v2:
- Zero the context's dev pointer if not used

 lib/smbios.c | 87 +---
 1 file changed, 55 insertions(+), 32 deletions(-)

diff --git a/lib/smbios.c b/lib/smbios.c
index a072d9ec10b..4d2cb0f85e2 100644
--- a/lib/smbios.c
+++ b/lib/smbios.c
@@ -17,15 +17,27 @@
 #include 
 #endif
 
+/**
+ * struct smbios_ctx - context for writing SMBIOS tables
+ *
+ * @node:  node containing the information to write (ofnode_null() if none)
+ * @dev:   sysinfo device to use (NULL if none)
+ */
+struct smbios_ctx {
+   ofnode node;
+   struct udevice *dev;
+};
+
 /**
  * Function prototype to write a specific type of SMBIOS structure
  *
  * @addr:  start address to write the structure
  * @handle:the structure's handle, a unique 16-bit number
- * @node:  node containing the information to write (ofnode_null() if none)
+ * @ctx:   context for writing the tables
  * @return:size of the structure
  */
-typedef int (*smbios_write_type)(ulong *addr, int handle, ofnode node);
+typedef int (*smbios_write_type)(ulong *addr, int handle,
+struct smbios_ctx *ctx);
 
 /**
  * struct smbios_write_method - Information about a table-writing function
@@ -78,17 +90,18 @@ static int smbios_add_string(char *start, const char *str)
  * smbios_add_prop() - Add a property from the device tree
  *
  * @start: string area start address
- * @node:  node containing the information to write (ofnode_null() if none)
+ * @ctx:   context for writing the tables
  * @prop:  property to write
  * @return 0 if not found, else SMBIOS string number (1 or more)
  */
-static int smbios_add_prop(char *start, ofnode node, const char *prop)
+static int smbios_add_prop(char *start, struct smbios_ctx *ctx,
+  const char *prop)
 {
 
if (IS_ENABLED(CONFIG_OF_CONTROL)) {
const char *str;
 
-   str = ofnode_read_string(node, prop);
+   str = ofnode_read_string(ctx->node, prop);
if (str)
return smbios_add_string(start, str);
}
@@ -118,7 +131,8 @@ static int smbios_string_table_len(char *start)
return len + 1;
 }
 
-static int smbios_write_type0(ulong *current, int handle, ofnode node)
+static int smbios_write_type0(ulong *current, int handle,
+ struct smbios_ctx *ctx)
 {
struct smbios_type0 *t;
int len = sizeof(struct smbios_type0);
@@ -156,7 +170,8 @@ static int smbios_write_type0(ulong *current, int handle, 
ofnode node)
return len;
 }
 
-static int smbios_write_type1(ulong *current, int handle, ofnode node)
+static int smbios_write_type1(ulong *current, int handle,
+ struct smbios_ctx *ctx)
 {
struct smbios_type1 *t;
int len = sizeof(struct smbios_type1);
@@ -165,17 +180,17 @@ static int smbios_write_type1(ulong *current, int handle, 
ofnode node)
t = map_sysmem(*current, len);
memset(t, 0, sizeof(struct smbios_type1));
fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, handle);
-   t->manufacturer = smbios_add_prop(t->eos, node, "manufacturer");
-   t->product_name = smbios_add_prop(t->eos, node, "product");
-   t->version = smbios_add_prop(t->eos, node, "version");
+   t->manufacturer = smbios_add_prop(t->eos, ctx, "manufacturer");
+   t->product_name = smbios_add_prop(t->eos, ctx, "product");
+   t->version = smbios_add_prop(t->eos, ctx, "version");
if (serial_str) {
t->serial_number = smbios_add_string(t->eos, serial_str);
strncpy((char *)t->uuid, serial_str, sizeof(t->uuid));
} else {
-   t->serial_number = smbios_add_prop(t->eos, node, "serial");
+   t->serial_number = smbios_add_prop(t->eos, ctx, "serial");
}
-   t->sku_number = smbios_add_prop(t->eos, node, "sku");
-   t->family = smbios_add_prop(t->eos, node, "family");
+   t->sku_number = smbios_add_prop(t->eos, ctx, "sku");
+   t->family = smbios_add_prop(t->eos, ctx, "family");
 
len = t->length + smbios_string_table_len(t->eos);
*current += len;
@@ -184,7 +199,8 @@ static int smbios_write_type1(ulong *current, int handle, 
ofnode node)
return len;
 }
 
-static int smbios_write_type2(ulong 

[PATCH v4 05/12] smbios: Set BIOS release version

2021-02-04 Thread Simon Glass
We may as well include the U-Boot release information in the type-0 table
since it is designed for that purpose.

U-Boot uses release versions based on the year and month. The year cannot
fit in a byte, so drop the century.

Signed-off-by: Simon Glass 
Reviewed-by: Bin Meng 
---

(no changes since v2)

Changes in v2:
- Add a comment about dropping the century

 lib/smbios.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/lib/smbios.c b/lib/smbios.c
index b1171f544a8..a072d9ec10b 100644
--- a/lib/smbios.c
+++ b/lib/smbios.c
@@ -143,8 +143,9 @@ static int smbios_write_type0(ulong *current, int handle, 
ofnode node)
 #endif
t->bios_characteristics_ext2 = BIOS_CHARACTERISTICS_EXT2_TARGET;
 
-   t->bios_major_release = 0xff;
-   t->bios_minor_release = 0xff;
+   /* bios_major_release has only one byte, so drop century */
+   t->bios_major_release = U_BOOT_VERSION_NUM % 100;
+   t->bios_minor_release = U_BOOT_VERSION_NUM_PATCH;
t->ec_major_release = 0xff;
t->ec_minor_release = 0xff;
 
-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v4 03/12] smbios: Move smbios_write_type to the C file

2021-02-04 Thread Simon Glass
This type is not used outside the smbios.c file so there is no need for it
to be in the header file. Move it.

Signed-off-by: Simon Glass 
Reviewed-by: Christian Gmeiner 
Reviewed-by: Bin Meng 
---

(no changes since v1)

 include/smbios.h | 10 --
 lib/smbios.c | 10 ++
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/include/smbios.h b/include/smbios.h
index 1846607c3cf..fc69188a8fe 100644
--- a/include/smbios.h
+++ b/include/smbios.h
@@ -219,16 +219,6 @@ static inline void fill_smbios_header(void *table, int 
type,
header->handle = handle;
 }
 
-/**
- * Function prototype to write a specific type of SMBIOS structure
- *
- * @addr:  start address to write the structure
- * @handle:the structure's handle, a unique 16-bit number
- * @node:  node containing the information to write (ofnode_null() if none)
- * @return:size of the structure
- */
-typedef int (*smbios_write_type)(ulong *addr, int handle, ofnode node);
-
 /**
  * write_smbios_table() - Write SMBIOS table
  *
diff --git a/lib/smbios.c b/lib/smbios.c
index 1e10fa84207..b1171f544a8 100644
--- a/lib/smbios.c
+++ b/lib/smbios.c
@@ -17,6 +17,16 @@
 #include 
 #endif
 
+/**
+ * Function prototype to write a specific type of SMBIOS structure
+ *
+ * @addr:  start address to write the structure
+ * @handle:the structure's handle, a unique 16-bit number
+ * @node:  node containing the information to write (ofnode_null() if none)
+ * @return:size of the structure
+ */
+typedef int (*smbios_write_type)(ulong *addr, int handle, ofnode node);
+
 /**
  * struct smbios_write_method - Information about a table-writing function
  *
-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v4 04/12] smbios: Use char consistently for the eos member

2021-02-04 Thread Simon Glass
At present a few of the structs use u8 instead of char. This is a string,
so char is better. Update them.

Signed-off-by: Simon Glass 
Reviewed-by: Christian Gmeiner 
Reviewed-by: Bin Meng 
---

(no changes since v1)

 include/smbios.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/smbios.h b/include/smbios.h
index fc69188a8fe..1cbeabf9522 100644
--- a/include/smbios.h
+++ b/include/smbios.h
@@ -183,14 +183,14 @@ struct __packed smbios_type32 {
u16 handle;
u8 reserved[6];
u8 boot_status;
-   u8 eos[SMBIOS_STRUCT_EOS_BYTES];
+   char eos[SMBIOS_STRUCT_EOS_BYTES];
 };
 
 struct __packed smbios_type127 {
u8 type;
u8 length;
u16 handle;
-   u8 eos[SMBIOS_STRUCT_EOS_BYTES];
+   char eos[SMBIOS_STRUCT_EOS_BYTES];
 };
 
 struct __packed smbios_header {
-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v4 01/12] README: Add doumentation for version information

2021-02-04 Thread Simon Glass
There are quite a few available version options in U-Boot. Add a list of
the available Makefile variables and #defines, along with examples.

Signed-off-by: Simon Glass 
Reviewed-by: Bin Meng 
---

Changes in v4:
- Drop debugging change to doc/Makefile

Changes in v3:
- Move to doc/ and .rst format
- Add examples for converting epoch values

 doc/develop/index.rst   |  1 +
 doc/develop/version.rst | 93 +
 2 files changed, 94 insertions(+)
 create mode 100644 doc/develop/version.rst

diff --git a/doc/develop/index.rst b/doc/develop/index.rst
index beaa64d8d90..ac57fdb8f30 100644
--- a/doc/develop/index.rst
+++ b/doc/develop/index.rst
@@ -13,6 +13,7 @@ Implementation
global_data
logging
menus
+   version
 
 Debugging
 -
diff --git a/doc/develop/version.rst b/doc/develop/version.rst
new file mode 100644
index 000..6da31a4a1e7
--- /dev/null
+++ b/doc/develop/version.rst
@@ -0,0 +1,93 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright (c) 2013 The Chromium OS Authors.
+
+Version information
+===
+
+U-Boot releases are named by year and patch level, for example 2020.10 means 
the
+release that came out in October 2020. Release candidates are tagged every few
+weeks as the project heads to the next release. So 2020.10-rc1 was the first
+release candidate (RC), tagged soon after 2020.07 was released.
+
+See https://www.denx.de/wiki/view/U-Boot/ReleaseCycle for full details.
+
+Within the build system, various Makefile variables are created, making use of
+VERSION, PATCHLEVEL and EXTRAVERSION defined at the top of 'Makefile'. There is
+also SUBLEVEL available for downstream use. See also CONFIG_IDENT_STRING.
+
+Some variables end up in a generated header file at
+include/generated/version_autogenerated.h and can be accessed from C source by
+including 
+
+The following are available:
+
+   UBOOTRELEASE (Makefile)
+  Full release version as a string. If this is not a tagged release, it 
also
+  includes the number of commits since the last tag as well as the the git
+  hash.  If there are uncommitted changes a '-dirty' suffix is added too.
+
+  This is written by scripts/setlocalversion (maintained by Linux) to
+  include/config/uboot.release and ends up in the UBOOTRELEASE Makefile
+  variable.
+
+  Examples::
+
+ 2020.10-rc3
+ 2021.01-rc5-00248-g60dd854f3ba-dirty
+
+   PLAIN_VERSION (string #define)
+  This is UBOOTRELEASE but available in C source.
+
+  Examples::
+
+ 2020.10
+ 2021.01-rc5-00248-g60dd854f3ba-dirty
+
+   UBOOTVERSION (Makefile)
+  This holds just the first three components of UBOOTRELEASE (i.e. not the
+  git hash, etc.)
+
+  Examples::
+
+ 2020.10
+ 2021.01-rc5
+
+   U_BOOT_VERSION (string #define)
+  "U-Boot " followed by UBOOTRELEASE, for example::
+
+ U-Boot 2020.10
+ U-Boot 2021.01-rc5
+
+  This is used as part of the banner string when U-Boot starts.
+
+   U_BOOT_VERSION_STRING (string #define)
+  U_BOOT_VERSION followed by build-time information
+  and CONFIG_IDENT_STRING.
+
+  Examples::
+
+ U-Boot 2020.10 (Jan 06 2021 - 08:50:36 -0700)
+ U-Boot 2021.01-rc5-00248-g60dd854f3ba-dirty (Jan 06 2021 - 08:50:36 
-0700) for spring
+
+Build date/time is also included. See the generated file
+include/generated/timestamp_autogenerated.h for the available
+fields. For example::
+
+   #define U_BOOT_DATE "Jan 06 2021" (US format only)
+   #define U_BOOT_TIME "08:50:36"(24-hour clock)
+   #define U_BOOT_TZ "-0700" (Time zone in hours)
+   #define U_BOOT_DMI_DATE "01/06/2021"  (US format only)
+   #define U_BOOT_BUILD_DATE 0x20210106  (hex mmdd format)
+   #define U_BOOT_EPOCH 1609948236
+
+The Epoch is the number of seconds since midnight on 1/1/70. You can convert
+this to a time with::
+
+   $ date -u -d @1609948236
+   Wed 06 Jan 2021 03:50:36 PM UTC
+   $ date -d 'Wed 06 Jan 2021 03:50:36 PM UTC' +%s
+   1609948236
+
+Every time you build U-Boot this will update based on the time
+on your build machine. See 'Reproducible builds' if you want to
+avoid that.
-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v4 00/12] smbios: Enhancements for more flexibility

2021-02-04 Thread Simon Glass
This series includes various patches to allow more flexibility as to where
the data for SMBIOS tables comes from:

- introduces some standard sysinfo options as a source, e.g. to read
   strapping pins to determine the board revision
- allows the U-Boot version number to be included
- allows the version number to be provided programmatically, e.g. to
   support the build system adding information after U-Boot is built

Documentation is added for how to obtain version information.

The code is also refactored a little to make it easier to maintain.

Changes in v4:
- Drop debugging change to doc/Makefile

Changes in v3:
- Move to doc/ and .rst format
- Add examples for converting epoch values
- Use .rst file instead of README
- Fix comment for smbios_add_prop()
- Rename set_eos() to smbios_set_eos()
- Add missing DECLARE_GLOBAL_DATA_PTR
- Expand commit to explain why operations are required
- Use SMBIOS_STR_MAX for the max sysinfo string length

Changes in v2:
- Add a comment about dropping the century
- Zero the context's dev pointer if not used
- Correct documentation format
- Add new patch to fix sysinfo with CONFIG_IS_ENABLED()
- Add new patch to fix crash on coral

Simon Glass (12):
  README: Add doumentation for version information
  Makefile: Provide numeric versions
  smbios: Move smbios_write_type to the C file
  smbios: Use char consistently for the eos member
  smbios: Set BIOS release version
  smbios: Use a struct to keep track of context
  smbios: Drop the eos parameter
  smbios: Track the end of the string table
  smbios: Add more options for the BIOS version string
  sysinfo: Move #ifdef so that operations are always defined
  x86: coral: Add sysinfo ops
  smbios: Allow a few values to come from sysinfo

 Makefile  |   4 +
 board/google/chromebook_coral/coral.c |   5 +
 doc/develop/index.rst |   1 +
 doc/develop/version.rst   | 101 +++
 include/asm-generic/global_data.h |   6 +
 include/smbios.h  |  26 +--
 include/sysinfo.h |  13 +-
 lib/smbios.c  | 248 +++---
 8 files changed, 328 insertions(+), 76 deletions(-)
 create mode 100644 doc/develop/version.rst

-- 
2.30.0.478.g8a0d178c01-goog



[PATCH v2 14/14] riscv: k210: Enable QSPI for spi3

2021-02-04 Thread Sean Anderson
This device has four IOs connected to the SPI flash. Add the appropriate
bindings.

Signed-off-by: Sean Anderson 
Reviewed-by: Bin Meng 
Reviewed-by: Leo Liang 

---

(no changes since v1)

 arch/riscv/dts/k210-maix-bit.dts | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/riscv/dts/k210-maix-bit.dts b/arch/riscv/dts/k210-maix-bit.dts
index e4dea205b2..902dcfd08a 100644
--- a/arch/riscv/dts/k210-maix-bit.dts
+++ b/arch/riscv/dts/k210-maix-bit.dts
@@ -200,6 +200,8 @@
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <5000>;
+   spi-tx-bus-width = <4>;
+   spi-rx-bus-width = <4>;
m25p,fast-read;
broken-flash-reset;
};
-- 
2.29.2



[PATCH v2 13/14] spi: dw: Support clock stretching

2021-02-04 Thread Sean Anderson
We don't always read/write to the FIFO fast enough. Enable clock stretching
for enhanced SPI transfers. This is only possible with DWC SSI devices more
recent than 1.01a. We also need to set the RXFTLR register to tell the
device when to start reciving again. In particular, the default of 0 will
result in the device never restarting reception if there is an overflow. On
the transmit side, we need to set CTRL1 so that the device knows when to
keep stretching the clock if the FIFO is empty.

Signed-off-by: Sean Anderson 
---

(no changes since v1)

 drivers/spi/designware_spi.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index 64a3a8556b..44fb679fdb 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -258,6 +258,7 @@ static u32 dw_spi_update_spi_cr0(const struct spi_mem_op 
*op)
   | FIELD_PREP(SPI_CTRLR0_ADDR_L_MASK, op->addr.nbytes * 2)
   | FIELD_PREP(SPI_CTRLR0_INST_L_MASK, INST_L_8)
   | FIELD_PREP(SPI_CTRLR0_WAIT_CYCLES_MASK, wait_cycles)
+  | SPI_CTRLR0_CLK_STRETCH_EN;
 }
 
 static int request_gpio_cs(struct udevice *bus)
@@ -360,6 +361,9 @@ static void spi_hw_init(struct udevice *bus, struct 
dw_spi_priv *priv)
priv->fifo_len = (fifo == 1) ? 0 : fifo;
dw_write(priv, DW_SPI_TXFTLR, 0);
}
+
+   /* Set receive fifo interrupt level register for clock stretching */
+   dw_write(priv, DW_SPI_RXFTLR, priv->fifo_len - 1);
 }
 
 /*
@@ -782,8 +786,7 @@ static int dw_spi_exec_op(struct spi_slave *slave, const 
struct spi_mem_op *op)
 
dw_write(priv, DW_SPI_SSIENR, 0);
dw_write(priv, DW_SPI_CTRLR0, cr0);
-   if (read)
-   dw_write(priv, DW_SPI_CTRLR1, op->data.nbytes - 1);
+   dw_write(priv, DW_SPI_CTRLR1, op->data.nbytes - 1);
if (priv->spi_frf != CTRLR0_SPI_FRF_BYTE)
dw_write(priv, DW_SPI_SPI_CTRL0, spi_cr0);
dw_write(priv, DW_SPI_SSIENR, 1);
-- 
2.29.2



[PATCH v2 12/14] spi: dw: Support enhanced SPI

2021-02-04 Thread Sean Anderson
This adds support for DUAL/QUAD/OCTAL transfers. This adds
dw_spi_supports_op to do some sanity checks which would otherwise live in
exec_op. We only support byte transfers, but as far as I could tell only
bytes are supported by mem_ops (e.g. every part of the opcode has nbytes).

Signed-off-by: Sean Anderson 
---

(no changes since v1)

 drivers/spi/designware_spi.c | 136 ++-
 1 file changed, 119 insertions(+), 17 deletions(-)

diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index e110c5bca1..64a3a8556b 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -218,7 +218,8 @@ static u32 dw_spi_update_cr0(struct dw_spi_priv *priv)
 priv->bits_per_word - 1)
| FIELD_PREP(DWC_SSI_CTRLR0_FRF_MASK, priv->type)
| FIELD_PREP(DWC_SSI_CTRLR0_MODE_MASK, priv->mode)
-   | FIELD_PREP(DWC_SSI_CTRLR0_TMOD_MASK, priv->tmode);
+   | FIELD_PREP(DWC_SSI_CTRLR0_TMOD_MASK, priv->tmode)
+   | FIELD_PREP(DWC_SSI_CTRLR0_SPI_FRF_MASK, priv->spi_frf);
} else {
if (priv->caps & DW_SPI_CAP_DFS32)
cr0 = FIELD_PREP(CTRLR0_DFS_32_MASK,
@@ -229,12 +230,36 @@ static u32 dw_spi_update_cr0(struct dw_spi_priv *priv)
 
cr0 |= FIELD_PREP(CTRLR0_FRF_MASK, priv->type)
|  FIELD_PREP(CTRLR0_MODE_MASK, priv->mode)
-   |  FIELD_PREP(CTRLR0_TMOD_MASK, priv->tmode);
+   |  FIELD_PREP(CTRLR0_TMOD_MASK, priv->tmode)
+   |  FIELD_PREP(CTRLR0_SPI_FRF_MASK, priv->spi_frf);
}
 
return cr0;
 }
 
+static u32 dw_spi_update_spi_cr0(const struct spi_mem_op *op)
+{
+   uint trans_type, wait_cycles;
+
+   /* This assumes support_op has filtered invalid types */
+   if (op->addr.buswidth == 1)
+   trans_type = SPI_CTRLR0_TRANS_TYPE_1_1_X;
+   else if (op->cmd.buswidth == 1)
+   trans_type = SPI_CTRLR0_TRANS_TYPE_1_X_X;
+   else
+   trans_type = SPI_CTRLR0_TRANS_TYPE_X_X_X;
+
+   if (op->dummy.buswidth)
+   wait_cycles = op->dummy.nbytes * 8 / op->dummy.buswidth;
+   else
+   wait_cycles = 0;
+
+   return FIELD_PREP(SPI_CTRLR0_TRANS_TYPE_MASK, trans_type)
+  | FIELD_PREP(SPI_CTRLR0_ADDR_L_MASK, op->addr.nbytes * 2)
+  | FIELD_PREP(SPI_CTRLR0_INST_L_MASK, INST_L_8)
+  | FIELD_PREP(SPI_CTRLR0_WAIT_CYCLES_MASK, wait_cycles)
+}
+
 static int request_gpio_cs(struct udevice *bus)
 {
 #if CONFIG_IS_ENABLED(DM_GPIO) && !defined(CONFIG_SPL_BUILD)
@@ -619,6 +644,13 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int 
bitlen,
u32 val, cs;
uint frames;
 
+   /* DUAL/QUAD/OCTAL only supported by exec_op for now */
+   if (priv->mode & (SPI_TX_DUAL | SPI_TX_QUAD | SPI_TX_OCTAL |
+ SPI_RX_DUAL | SPI_RX_QUAD | SPI_RX_OCTAL))
+   return -1;
+
+   priv->spi_frf = CTRLR0_SPI_FRF_BYTE;
+
/* spi core configured to do 8 bit transfers */
if (bitlen % priv->bits_per_word) {
dev_err(dev, "Non byte aligned SPI transfer.\n");
@@ -697,6 +729,9 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int 
bitlen,
 /*
  * This function is necessary for reading SPI flash with the native CS
  * c.f. https://lkml.org/lkml/2015/12/23/132
+ *
+ * It also lets us handle DUAL/QUAD/OCTAL transfers in a much more idiomatic
+ * way.
  */
 static int dw_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
 {
@@ -707,37 +742,72 @@ static int dw_spi_exec_op(struct spi_slave *slave, const 
struct spi_mem_op *op)
struct spi_mem_op *mut_op = (struct spi_mem_op *)op;
u8 op_len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes;
u8 op_buf[op_len];
-   u32 cr0, val;
+   u32 cr0, spi_cr0, val;
+
+   /* Only bytes are supported for spi-mem transfers */
+   if (priv->bits_per_word != 8)
+   return -EINVAL;
+
+   switch (op->data.buswidth) {
+   case 0:
+   case 1:
+   priv->spi_frf = CTRLR0_SPI_FRF_BYTE;
+   break;
+   case 2:
+   priv->spi_frf = CTRLR0_SPI_FRF_DUAL;
+   break;
+   case 4:
+   priv->spi_frf = CTRLR0_SPI_FRF_QUAD;
+   break;
+   case 8:
+   priv->spi_frf = CTRLR0_SPI_FRF_OCTAL;
+   break;
+   /* BUG: should have been filtered out by supports_op */
+   default:
+   return -EINVAL;
+   }
 
if (read)
-   priv->tmode = CTRLR0_TMOD_EPROMREAD;
+   if (priv->spi_frf == CTRLR0_SPI_FRF_BYTE)
+   priv->tmode = CTRLR0_TMOD_EPROMREAD;
+   else
+   priv->tmode = CTRLR0_TMOD_RO;
else
priv->tmode = CTRLR0_TMOD_TO;
 

[PATCH v2 09/14] spi: dw: Rewrite poll_transfer logic

2021-02-04 Thread Sean Anderson
This rewrites poll_transfer, dw_writer, and dw_reader.

* We now use RO transfers (instead of always using TR). This eliminates the
  need to send out dummy words, and simplifies the transmit logic.
* All parameters (except regs and bits_per_word) are passed explicitly.
* Most parameters have been made explicit (instead of being recalculated on
  every loop).
* Transfers are measured in units of frames instead of bytes. This matches
  the measurements used by the device and eliminates several divisions by
  bits_per_word.
* We now check if we have over-/under-flowed the FIFO. This should help
  prevent hangs when the device stops the transfer and U-Boot doesn't
  realize it (and then waits for the remaining data forever). TXUI is not
  present in DW_APB_SSI, but in the worst case we just don't write data.

  Unfortunately, this doesn't seem to solve all problems, and there are
  some remaining bugs (such as some transfers containing all 1s or all 0s)
  when we have many fifo overflows. This is solved for DWC devices by
  enabling clock stretching.
* poll_transfer is now used by dw_spi_exec_op as well as xfer.
* There are separate inner loops for 8-, 16-, and 32-bit frame sizes. This
  should hopefully reduce the amount of over-/under-flows. However, I
  haven't done exhaustive testing to ensure this is really necessary. In
  particular, I was never able to prevent read overflows at 50MHz clock
  speed.

These changes should probably have been split up into several commits, but
several depend on each other, and it would be difficult to break this up
while preserving bisectability.

Signed-off-by: Sean Anderson 
---

(no changes since v1)

 drivers/spi/designware_spi.c | 284 +--
 1 file changed, 171 insertions(+), 113 deletions(-)

diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index 6375e6d778..72cca14887 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -134,14 +134,10 @@ struct dw_spi_priv {
unsigned int freq;  /* Default frequency */
unsigned int mode;
 
-   const void *tx;
-   const void *tx_end;
-   void *rx;
-   void *rx_end;
u32 fifo_len;   /* depth of the FIFO buffer */
 
int bits_per_word;
-   int len;
+   int frames; /* Number of frames in the transfer */
u8 cs;  /* chip select pin */
u8 tmode;   /* TR/TO/RO/EEPROM */
u8 type;/* SPI/SSP/MicroWire */
@@ -372,14 +368,24 @@ static int dw_spi_probe(struct udevice *bus)
return 0;
 }
 
-/* Return the max entries we can fill into tx fifo */
-static inline u32 tx_max(struct dw_spi_priv *priv)
+/**
+ * dw_writer() - Write data frames to the tx fifo
+ * @priv: Driver private info
+ * @tx: The tx buffer
+ * @idx: The number of data frames already transmitted
+ * @tx_frames: The number of data frames left to transmit
+ * @rx_frames: The number of data frames left to receive (0 if only
+ * transmitting)
+ * @frame_bytes: The number of bytes taken up by one data frame
+ *
+ * This function writes up to @tx_frames data frames using data from @tx[@idx].
+ *
+ * Return: The number of frames read
+ */
+static uint dw_writer(struct dw_spi_priv *priv, const void *tx, uint idx,
+ uint tx_frames, uint rx_frames, uint frame_bytes)
 {
-   u32 tx_left, tx_room, rxtx_gap;
-
-   tx_left = (priv->tx_end - priv->tx) / (priv->bits_per_word >> 3);
-   tx_room = priv->fifo_len - dw_read(priv, DW_SPI_TXFLR);
-
+   u32 tx_room = priv->fifo_len - dw_read(priv, DW_SPI_TXFLR);
/*
 * Another concern is about the tx/rx mismatch, we
 * thought about using (priv->fifo_len - rxflr - txflr) as
@@ -388,67 +394,131 @@ static inline u32 tx_max(struct dw_spi_priv *priv)
 * shift registers. So a control from sw point of
 * view is taken.
 */
-   rxtx_gap = ((priv->rx_end - priv->rx) - (priv->tx_end - priv->tx)) /
-   (priv->bits_per_word >> 3);
+   u32 rxtx_gap = rx_frames - tx_frames;
+   u32 count = min3(tx_frames, tx_room, (u32)(priv->fifo_len - rxtx_gap));
+   u32 *dr = priv->regs + DW_SPI_DR;
 
-   return min3(tx_left, tx_room, (u32)(priv->fifo_len - rxtx_gap));
-}
+   if (!count)
+   return 0;
 
-/* Return the max entries we should read out of rx fifo */
-static inline u32 rx_max(struct dw_spi_priv *priv)
-{
-   u32 rx_left = (priv->rx_end - priv->rx) / (priv->bits_per_word >> 3);
-
-   return min_t(u32, rx_left, dw_read(priv, DW_SPI_RXFLR));
-}
-
-static void dw_writer(struct dw_spi_priv *priv)
-{
-   u32 max = tx_max(priv);
-   u32 txw = 0x;
-
-   while (max--) {
-   /* Set the tx word if the transfer's original "tx" is not null 
*/
-   if (priv->tx_end - priv->len) {
-   if 

[PATCH v2 11/14] spi: dw: Define registers for enhanced mode

2021-02-04 Thread Sean Anderson
This adds some registers needed for DUAL/QUAD/OCTAL modes. It also adds the
fields in (R)ISR so we can check for over-/under-flow.

Signed-off-by: Sean Anderson 
---

Changes in v2:
- Fix some inconsistencies in register naming and usage

 drivers/spi/designware_spi.c | 60 ++--
 1 file changed, 57 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index c2639141c6..e110c5bca1 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -56,6 +56,8 @@
 #define DW_SPI_IDR 0x58
 #define DW_SPI_VERSION 0x5c
 #define DW_SPI_DR  0x60
+#define DW_SPI_RX_SAMPLE_DLY   0xf0
+#define DW_SPI_SPI_CTRL0   0xf4
 
 /* Bit fields in CTRLR0 */
 /*
@@ -80,8 +82,8 @@
 #define CTRLR0_TMOD_RO 0x2 /* recv only */
 #define CTRLR0_TMOD_EPROMREAD  0x3 /* eeprom read mode */
 
-#define CTRLR0_SLVOE_OFFSET10
-#define CTRLR0_SRL_OFFSET  11
+#define CTRLR0_SLVOE_OFFSETBIT(10)
+#define CTRLR0_SRL BIT(11)
 #define CTRLR0_CFS_MASKGENMASK(15, 12)
 
 /* Only present when SSI_MAX_XFER_SIZE=32 */
@@ -92,13 +94,15 @@
 #define CTRLR0_SPI_FRF_BYTE0x0
 #defineCTRLR0_SPI_FRF_DUAL 0x1
 #defineCTRLR0_SPI_FRF_QUAD 0x2
+#defineCTRLR0_SPI_FRF_OCTAL0x3
 
 /* Bit fields in CTRLR0 based on DWC_ssi_databook.pdf v1.01a */
 #define DWC_SSI_CTRLR0_DFS_MASKGENMASK(4, 0)
 #define DWC_SSI_CTRLR0_FRF_MASKGENMASK(7, 6)
 #define DWC_SSI_CTRLR0_MODE_MASK   GENMASK(9, 8)
 #define DWC_SSI_CTRLR0_TMOD_MASK   GENMASK(11, 10)
-#define DWC_SSI_CTRLR0_SRL_OFFSET  13
+#define DWC_SSI_CTRLR0_SRL BIT(13)
+#define DWC_SSI_CTRLR0_SSTEBIT(14)
 #define DWC_SSI_CTRLR0_SPI_FRF_MASKGENMASK(23, 22)
 
 /* Bit fields in SR, 7 bits */
@@ -111,6 +115,56 @@
 #define SR_TX_ERR  BIT(5)
 #define SR_DCOLBIT(6)
 
+/* Bit fields in (R)ISR */
+
+/* TX FIFO Empty */
+#define ISR_TXEI   BIT(0)
+/* TX FIFO Overflow */
+#define ISR_TXOI   BIT(1)
+/* RX FIFO Underflow */
+#define ISR_RXUI   BIT(2)
+/* RX FIFO Overflow */
+#define ISR_RXOI   BIT(3)
+/* RX FIFO Full */
+#define ISR_RXFI   BIT(4)
+/* Multi-master contention */
+#define ISR_MSTI   BIT(5)
+/* XIP Receive FIFO Overflow */
+#define ISR_XRXOI  BIT(6)
+/* TX FIFO Underflow */
+#define ISR_TXUI   BIT(7)
+/* AXI Error */
+#define ISR_AXIE   BIT(8)
+/* SPI TX Error */
+#define ISR_SPITE  BIT(10)
+/* SSI Done */
+#define ISR_DONE   BIT(11)
+
+/* Bit fields in SPI_CTRLR0 */
+
+/*
+ * Whether the instruction or address use the value of SPI_FRF or use
+ * FRF_BYTE
+ */
+#define SPI_CTRLR0_TRANS_TYPE_MASK GENMASK(1, 0)
+#define SPI_CTRLR0_TRANS_TYPE_1_1_X0x0
+#define SPI_CTRLR0_TRANS_TYPE_1_X_X0x1
+#define SPI_CTRLR0_TRANS_TYPE_X_X_X0x2
+/* Address length in 4-bit units */
+#define SPI_CTRLR0_ADDR_L_MASK GENMASK(5, 2)
+/* Enable mode bits after address in XIP mode */
+#define SPI_CTRLR0_XIP_MD_BIT_EN   BIT(7)
+/* Instruction length */
+#define SPI_CTRLR0_INST_L_MASK GENMASK(9, 8)
+#define INST_L_0   0x0
+#define INST_L_4   0x1
+#define INST_L_8   0x2
+#define INST_L_16  0x3
+/* Number of "dummy" cycles */
+#define SPI_CTRLR0_WAIT_CYCLES_MASKGENMASK(15, 11)
+/* Stretch the clock if the FIFO over/underflows */
+#define SPI_CTRLR0_CLK_STRETCH_EN  BIT(30)
+
 #define RX_TIMEOUT 1000/* timeout in ms */
 
 struct dw_spi_plat {
-- 
2.29.2



[PATCH v2 10/14] spi: dw: Add ENHANCED cap

2021-02-04 Thread Sean Anderson
This capability corresponds to an SSIC_SPI_MODE of 1, 2, or 3.  This
doesn't do much yet, but it does add support for detection and for
disallowing unsupported modes. Unfortunately, we cannot discriminate
between these modes (only that SSIC_SPI_MODE != 0), so we just pretend to
have DUAL+QUAD+OCTAL and let the slave determine what we actually use.

Signed-off-by: Sean Anderson 
---

Changes in v2:
- Merge CAP_{DUAL,QUAD,OCTAL} into CAP_ENHANCED

 drivers/spi/designware_spi.c | 22 +-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index 72cca14887..c2639141c6 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -129,6 +129,7 @@ struct dw_spi_priv {
 #define DW_SPI_CAP_KEEMBAY_MST BIT(1) /* Unimplemented */
 #define DW_SPI_CAP_DWC_SSI BIT(2)
 #define DW_SPI_CAP_DFS32   BIT(3)
+#define DW_SPI_CAP_ENHANCEDBIT(4)
unsigned long caps;
unsigned long bus_clk_rate;
unsigned int freq;  /* Default frequency */
@@ -141,6 +142,7 @@ struct dw_spi_priv {
u8 cs;  /* chip select pin */
u8 tmode;   /* TR/TO/RO/EEPROM */
u8 type;/* SPI/SSP/MicroWire */
+   u8 spi_frf; /* BYTE/DUAL/QUAD/OCTAL */
 };
 
 static inline u32 dw_read(struct dw_spi_priv *priv, u32 offset)
@@ -249,6 +251,18 @@ static void spi_hw_init(struct udevice *bus, struct 
dw_spi_priv *priv)
if (priv->caps & DW_SPI_CAP_DWC_SSI || !FIELD_GET(CTRLR0_DFS_MASK, cr0))
priv->caps |= DW_SPI_CAP_DFS32;
 
+   /*
+* If SPI_FRF exists that means we have DUAL, QUAD, or OCTAL. Since we
+* can't differentiate, just set a general ENHANCED cap and let the
+* slave decide what to use.
+*/
+   if (priv->caps & DW_SPI_CAP_DWC_SSI) {
+   if (FIELD_GET(DWC_SSI_CTRLR0_SPI_FRF_MASK, cr0))
+   priv->caps |= DW_SPI_CAP_ENHANCED;
+   } else if (FIELD_GET(CTRLR0_SPI_FRF_MASK, cr0)) {
+   priv->caps |= DW_SPI_CAP_ENHANCED;
+   }
+
dw_write(priv, DW_SPI_SSIENR, 1);
 
/*
@@ -746,13 +760,19 @@ static int dw_spi_set_mode(struct udevice *bus, uint mode)
 {
struct dw_spi_priv *priv = dev_get_priv(bus);
 
+   if (!(priv->caps & DW_SPI_CAP_ENHANCED) &&
+   (mode & (SPI_RX_DUAL | SPI_TX_DUAL |
+SPI_RX_QUAD | SPI_TX_QUAD |
+SPI_RX_OCTAL | SPI_TX_OCTAL)))
+   return -EINVAL;
+
/*
 * Can't set mode yet. Since this depends on if rx, tx, or
 * rx & tx is requested. So we have to defer this to the
 * real transfer function.
 */
priv->mode = mode;
-   dev_dbg(bus, "mode=%d\n", priv->mode);
+   dev_dbg(bus, "mode=%x\n", mode);
 
return 0;
 }
-- 
2.29.2



[PATCH v2 08/14] spi: dw: Switch to capabilities

2021-02-04 Thread Sean Anderson
Since Linux commit cc760f3143f5 ("spi: dw: Convert CS-override to DW SPI
capabilities"), the Linux driver has used capability flags instead of
using ad-hoc flags and functions. This is a great idea, and we should use
it as well.

The .data field in the compatible array has switched from being an
initialization function to being a set of default capabilities. This is
necessary since some capabilities cannot be determined at runtime.

Signed-off-by: Sean Anderson 
---

(no changes since v1)

 drivers/spi/designware_spi.c | 151 +--
 1 file changed, 73 insertions(+), 78 deletions(-)

diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index 4ef948a0b9..6375e6d778 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -123,9 +123,13 @@ struct dw_spi_priv {
struct reset_ctl_bulk resets;
struct gpio_desc cs_gpio;   /* External chip-select gpio */
 
-   u32 (*update_cr0)(struct dw_spi_priv *priv);
-
void __iomem *regs;
+/* DW SPI capabilities */
+#define DW_SPI_CAP_CS_OVERRIDE BIT(0) /* Unimplemented */
+#define DW_SPI_CAP_KEEMBAY_MST BIT(1) /* Unimplemented */
+#define DW_SPI_CAP_DWC_SSI BIT(2)
+#define DW_SPI_CAP_DFS32   BIT(3)
+   unsigned long caps;
unsigned long bus_clk_rate;
unsigned int freq;  /* Default frequency */
unsigned int mode;
@@ -135,7 +139,6 @@ struct dw_spi_priv {
void *rx;
void *rx_end;
u32 fifo_len;   /* depth of the FIFO buffer */
-   u32 max_xfer;   /* Maximum transfer size (in bits) */
 
int bits_per_word;
int len;
@@ -154,51 +157,30 @@ static inline void dw_write(struct dw_spi_priv *priv, u32 
offset, u32 val)
__raw_writel(val, priv->regs + offset);
 }
 
-static u32 dw_spi_dw16_update_cr0(struct dw_spi_priv *priv)
+static u32 dw_spi_update_cr0(struct dw_spi_priv *priv)
 {
-   return FIELD_PREP(CTRLR0_DFS_MASK, priv->bits_per_word - 1)
-| FIELD_PREP(CTRLR0_FRF_MASK, priv->type)
-| FIELD_PREP(CTRLR0_MODE_MASK, priv->mode)
-| FIELD_PREP(CTRLR0_TMOD_MASK, priv->tmode);
-}
+   u32 cr0;
 
-static u32 dw_spi_dw32_update_cr0(struct dw_spi_priv *priv)
-{
-   return FIELD_PREP(CTRLR0_DFS_32_MASK, priv->bits_per_word - 1)
-| FIELD_PREP(CTRLR0_FRF_MASK, priv->type)
-| FIELD_PREP(CTRLR0_MODE_MASK, priv->mode)
-| FIELD_PREP(CTRLR0_TMOD_MASK, priv->tmode);
-}
-
-static u32 dw_spi_dwc_update_cr0(struct dw_spi_priv *priv)
-{
-   return FIELD_PREP(DWC_SSI_CTRLR0_DFS_MASK, priv->bits_per_word - 1)
-| FIELD_PREP(DWC_SSI_CTRLR0_FRF_MASK, priv->type)
-| FIELD_PREP(DWC_SSI_CTRLR0_MODE_MASK, priv->mode)
-| FIELD_PREP(DWC_SSI_CTRLR0_TMOD_MASK, priv->tmode);
-}
-
-static int dw_spi_apb_init(struct udevice *bus, struct dw_spi_priv *priv)
-{
-   /* If we read zeros from DFS, then we need to use DFS_32 instead */
-   dw_write(priv, DW_SPI_SSIENR, 0);
-   dw_write(priv, DW_SPI_CTRLR0, 0x);
-   if (FIELD_GET(CTRLR0_DFS_MASK, dw_read(priv, DW_SPI_CTRLR0))) {
-   priv->max_xfer = 16;
-   priv->update_cr0 = dw_spi_dw16_update_cr0;
+   if (priv->caps & DW_SPI_CAP_DWC_SSI) {
+   cr0 = FIELD_PREP(DWC_SSI_CTRLR0_DFS_MASK,
+priv->bits_per_word - 1)
+   | FIELD_PREP(DWC_SSI_CTRLR0_FRF_MASK, priv->type)
+   | FIELD_PREP(DWC_SSI_CTRLR0_MODE_MASK, priv->mode)
+   | FIELD_PREP(DWC_SSI_CTRLR0_TMOD_MASK, priv->tmode);
} else {
-   priv->max_xfer = 32;
-   priv->update_cr0 = dw_spi_dw32_update_cr0;
+   if (priv->caps & DW_SPI_CAP_DFS32)
+   cr0 = FIELD_PREP(CTRLR0_DFS_32_MASK,
+priv->bits_per_word - 1);
+   else
+   cr0 = FIELD_PREP(CTRLR0_DFS_MASK,
+priv->bits_per_word - 1);
+
+   cr0 |= FIELD_PREP(CTRLR0_FRF_MASK, priv->type)
+   |  FIELD_PREP(CTRLR0_MODE_MASK, priv->mode)
+   |  FIELD_PREP(CTRLR0_TMOD_MASK, priv->tmode);
}
 
-   return 0;
-}
-
-static int dw_spi_dwc_init(struct udevice *bus, struct dw_spi_priv *priv)
-{
-   priv->max_xfer = 32;
-   priv->update_cr0 = dw_spi_dwc_update_cr0;
-   return 0;
+   return cr0;
 }
 
 static int request_gpio_cs(struct udevice *bus)
@@ -251,8 +233,26 @@ static int dw_spi_of_to_plat(struct udevice *bus)
 /* Restart the controller, disable all interrupts, clean rx fifo */
 static void spi_hw_init(struct udevice *bus, struct dw_spi_priv *priv)
 {
+   u32 cr0;
+
dw_write(priv, DW_SPI_SSIENR, 0);
dw_write(priv, DW_SPI_IMR, 0);
+
+   /*
+* Detect features by writing CTRLR0 and seeing which 

[PATCH v2 07/14] spi: dw: Actually mask interrupts

2021-02-04 Thread Sean Anderson
Writing 1s to this register *unmasks* interrupts. Mask them instead.

Signed-off-by: Sean Anderson 
---

Changes in v2:
- Actually mask interrupts

 drivers/spi/designware_spi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index 519d6e32bd..4ef948a0b9 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -252,7 +252,7 @@ static int dw_spi_of_to_plat(struct udevice *bus)
 static void spi_hw_init(struct udevice *bus, struct dw_spi_priv *priv)
 {
dw_write(priv, DW_SPI_SSIENR, 0);
-   dw_write(priv, DW_SPI_IMR, 0xff);
+   dw_write(priv, DW_SPI_IMR, 0);
dw_write(priv, DW_SPI_SSIENR, 1);
 
/*
-- 
2.29.2



[PATCH v2 06/14] spi: dw: Log status register on timeout

2021-02-04 Thread Sean Anderson
This logs the status register on timeout, so it is easier to determine the
cause of the failure.

Signed-off-by: Sean Anderson 
---

(no changes since v1)

 drivers/spi/designware_spi.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index 742121140d..519d6e32bd 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -552,6 +552,7 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int 
bitlen,
if (readl_poll_timeout(priv->regs + DW_SPI_SR, val,
   (val & SR_TF_EMPT) && !(val & SR_BUSY),
   RX_TIMEOUT * 1000)) {
+   dev_dbg(bus, "timed out; sr=%x\n", dw_read(priv, DW_SPI_SR));
ret = -ETIMEDOUT;
}
 
@@ -639,6 +640,8 @@ static int dw_spi_exec_op(struct spi_slave *slave, const 
struct spi_mem_op *op)
if (readl_poll_timeout(priv->regs + DW_SPI_SR, val,
   (val & SR_TF_EMPT) && !(val & SR_BUSY),
   RX_TIMEOUT * 1000)) {
+   dev_dbg(bus, "timed out; sr=%x\n",
+   dw_read(priv, DW_SPI_SR));
ret = -ETIMEDOUT;
}
}
-- 
2.29.2



[PATCH v2 03/14] mtd: spi-nor-core: Fix typo in documentation

2021-02-04 Thread Sean Anderson
This line should come before the docs for the next function.

Fixes: 7aeedac0153 ("mtd: spi: Port SPI NOR framework from Linux")

Signed-off-by: Sean Anderson 
Reviewed-by: Bin Meng 
Reviewed-by: Pratyush Yadav 
---

(no changes since v1)

 include/linux/mtd/spi-nor.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 4a8e19ee4f..39ef872ebf 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -302,8 +302,8 @@ struct spi_flash {
  * @flash_lock:[FLASH-SPECIFIC] lock a region of the SPI NOR
  * @flash_unlock:  [FLASH-SPECIFIC] unlock a region of the SPI NOR
  * @flash_is_locked:   [FLASH-SPECIFIC] check if a region of the SPI NOR is
- * @quad_enable:   [FLASH-SPECIFIC] enables SPI NOR quad mode
  * completely locked
+ * @quad_enable:   [FLASH-SPECIFIC] enables SPI NOR quad mode
  * @priv:  the private data
  */
 struct spi_nor {
-- 
2.29.2



[PATCH v2 05/14] spi: spi-mem: Add debug message for spi-mem ops

2021-02-04 Thread Sean Anderson
This prints some basic metadata about the SPI memory op. This information
may be used to debug SPI drivers (e.g. determining the expected SPI mode).
It is also helpful for verifying that the data on the wire matches the data
intended to be transmitted (e.g. with a logic analyzer). The opcode is
printed with a format of %02Xh to match the notation commonly used in flash
datasheets.

Signed-off-by: Sean Anderson 
Reviewed-by: Pratyush Yadav 
---

Changes in v2:
- Add more information to exec_op debug message

 drivers/spi/spi-mem.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
index c095ae9505..6772367ef7 100644
--- a/drivers/spi/spi-mem.c
+++ b/drivers/spi/spi-mem.c
@@ -220,6 +220,13 @@ int spi_mem_exec_op(struct spi_slave *slave, const struct 
spi_mem_op *op)
int ret;
int i;
 
+   dev_dbg(slave->dev,
+   "exec %02Xh %u-%u-%u addr=%llx dummy cycles=%u data bytes=%u\n",
+   op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth,
+   op->data.buswidth, op->addr.val,
+   op->dummy.buswidth ? op->dummy.nbytes * 8 / op->dummy.buswidth 
: 0,
+   op->data.nbytes);
+
if (!spi_mem_supports_op(slave, op))
return -ENOTSUPP;
 
-- 
2.29.2



[PATCH v2 04/14] mtd: spi-mem: Export spi_mem_default_supports_op

2021-02-04 Thread Sean Anderson
This is useful for extending the default functionality. This mirrors the
change in Linux commit 46109648052f ("spi: spi-mem: export
spi_mem_default_supports_op()").

Signed-off-by: Sean Anderson 
Reviewed-by: Bin Meng 
Reviewed-by: Pratyush Yadav 
---

(no changes since v1)

 include/spi-mem.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/include/spi-mem.h b/include/spi-mem.h
index ca0f55c8fd..1dd556b6cf 100644
--- a/include/spi-mem.h
+++ b/include/spi-mem.h
@@ -236,6 +236,9 @@ spi_controller_dma_unmap_mem_op_data(struct spi_controller 
*ctlr,
 
 int spi_mem_adjust_op_size(struct spi_slave *slave, struct spi_mem_op *op);
 
+bool spi_mem_default_supports_op(struct spi_slave *slave,
+const struct spi_mem_op *op);
+
 bool spi_mem_supports_op(struct spi_slave *slave, const struct spi_mem_op *op);
 
 int spi_mem_exec_op(struct spi_slave *slave, const struct spi_mem_op *op);
-- 
2.29.2



[PATCH v2 02/14] cmd: sf: Print error on test failure

2021-02-04 Thread Sean Anderson
The sf test command is used to test spi flashes (and spi masters). Printing
the exact error code is very helpful to those debugging the spi stack.

Signed-off-by: Sean Anderson 
Reviewed-by: Bin Meng 
Reviewed-by: Pratyush Yadav 
---

(no changes since v1)

 cmd/sf.c | 22 +-
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/cmd/sf.c b/cmd/sf.c
index de80fcd38b..46346fb9d4 100644
--- a/cmd/sf.c
+++ b/cmd/sf.c
@@ -445,20 +445,22 @@ static int spi_flash_test(struct spi_flash *flash, 
uint8_t *buf, ulong len,
   ulong offset, uint8_t *vbuf)
 {
struct test_info test;
-   int i;
+   int err, i;
 
printf("SPI flash test:\n");
memset(, '\0', sizeof(test));
test.base_ms = get_timer(0);
test.bytes = len;
-   if (spi_flash_erase(flash, offset, len)) {
-   printf("Erase failed\n");
+   err = spi_flash_erase(flash, offset, len);
+   if (err) {
+   printf("Erase failed (err = %d)\n", err);
return -1;
}
spi_test_next_stage();
 
-   if (spi_flash_read(flash, offset, len, vbuf)) {
-   printf("Check read failed\n");
+   err = spi_flash_read(flash, offset, len, vbuf);
+   if (err) {
+   printf("Check read failed (err = %d)\n", err);
return -1;
}
for (i = 0; i < len; i++) {
@@ -471,15 +473,17 @@ static int spi_flash_test(struct spi_flash *flash, 
uint8_t *buf, ulong len,
}
spi_test_next_stage();
 
-   if (spi_flash_write(flash, offset, len, buf)) {
-   printf("Write failed\n");
+   err = spi_flash_write(flash, offset, len, buf);
+   if (err) {
+   printf("Write failed (err = %d)\n", err);
return -1;
}
memset(vbuf, '\0', len);
spi_test_next_stage();
 
-   if (spi_flash_read(flash, offset, len, vbuf)) {
-   printf("Read failed\n");
+   err = spi_flash_read(flash, offset, len, vbuf);
+   if (err) {
+   printf("Read failed (ret = %d)\n", err);
return -1;
}
spi_test_next_stage();
-- 
2.29.2



[PATCH v2 01/14] cmd: sf: Display errno on erase failure

2021-02-04 Thread Sean Anderson
If there is an error while erasing SPI flash, no errno is displayed. This
makes it difficult to determine the cause of the error. This change mirrors
the logic for write errors above.

Signed-off-by: Sean Anderson 
Reviewed-by: Bin Meng 
Reviewed-by: Pratyush Yadav 
---

(no changes since v1)

 cmd/sf.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/cmd/sf.c b/cmd/sf.c
index c0d6a8f8a0..de80fcd38b 100644
--- a/cmd/sf.c
+++ b/cmd/sf.c
@@ -344,8 +344,11 @@ static int do_spi_flash_erase(int argc, char *const argv[])
}
 
ret = spi_flash_erase(flash, offset, size);
-   printf("SF: %zu bytes @ %#x Erased: %s\n", (size_t)size, (u32)offset,
-  ret ? "ERROR" : "OK");
+   printf("SF: %zu bytes @ %#x Erased: ", (size_t)size, (u32)offset);
+   if (ret)
+   printf("ERROR %d\n", ret);
+   else
+   printf("OK\n");
 
return ret == 0 ? 0 : 1;
 }
-- 
2.29.2



[PATCH v2 00/14] spi: dw: Add support for DUAL/QUAD/OCTAL modes

2021-02-04 Thread Sean Anderson
This series adds support for enhanced SPI modes. It was tested on a K210 (DWC
SSI with QSPI flash).

If anyone has a designware device with QSPI flash attached (especially a DW SSI
APB device), I'd greatly appreciate them testing out this patch series.

Many of the earlier patches in this series are general fixups and can be split
off/merged separately if desired.

Changes in v2:
- Add more information to exec_op debug message
- Actually mask interrupts
- Merge CAP_{DUAL,QUAD,OCTAL} into CAP_ENHANCED
- Fix some inconsistencies in register naming and usage
- Moved some hunks between commits so things make more sense

Sean Anderson (14):
  cmd: sf: Display errno on erase failure
  cmd: sf: Print error on test failure
  mtd: spi-nor-core: Fix typo in documentation
  mtd: spi-mem: Export spi_mem_default_supports_op
  spi: spi-mem: Add debug message for spi-mem ops
  spi: dw: Log status register on timeout
  spi: dw: Actually mask interrupts
  spi: dw: Switch to capabilities
  spi: dw: Rewrite poll_transfer logic
  spi: dw: Add ENHANCED cap
  spi: dw: Define registers for enhanced mode
  spi: dw: Support enhanced SPI
  spi: dw: Support clock stretching
  riscv: k210: Enable QSPI for spi3

 arch/riscv/dts/k210-maix-bit.dts |   2 +
 cmd/sf.c |  29 +-
 drivers/spi/designware_spi.c | 647 +--
 drivers/spi/spi-mem.c|   7 +
 include/linux/mtd/spi-nor.h  |   2 +-
 include/spi-mem.h|   3 +
 6 files changed, 472 insertions(+), 218 deletions(-)

-- 
2.29.2



Re: [PATCH v2 6/6] log: Convert log values to printf() if not enabled

2021-02-04 Thread Simon Glass
Hi Sean,

On Thu, 4 Feb 2021 at 18:28, Sean Anderson  wrote:
>
> On 1/20/21 10:10 PM, Simon Glass wrote:
> > At present if logging not enabled, log_info() becomes a nop. But we want
> > log output at the 'info' level to be akin to printf(). Update the macro to
> > pass the output straight to printf() in this case.
> >
> > This mimics the behaviour for the log_...() macros like log_debug() and
> > log_info(), so we can drop the special case for these.
> >
> > Add new tests to cover this case.
> > Signed-off-by: Simon Glass 
> > ---
> >
> > Changes in v2:
> > - Update commit message and cover letter to mention log_...() macros
> > - Add a test for !CONFIG_LOG
> > - Update log() to (effectively) call debug() for log_level == LOGL_DEBUG
> >
> >   doc/develop/logging.rst |  6 --
> >   include/log.h   | 33 ++---
> >   test/log/Makefile   |  1 +
> >   test/log/nolog_ndebug.c | 38 ++
> >   test/log/nolog_test.c   |  3 +++
> >   5 files changed, 60 insertions(+), 21 deletions(-)
> >   create mode 100644 test/log/nolog_ndebug.c
> >
> > diff --git a/doc/develop/logging.rst b/doc/develop/logging.rst
> > index b6c6b45049f..55cef42664d 100644
> > --- a/doc/develop/logging.rst
> > +++ b/doc/develop/logging.rst
> > @@ -54,6 +54,10 @@ If CONFIG_LOG is not set, then no logging will be 
> > available.
> >   The above have SPL and TPL versions also, e.g. CONFIG_SPL_LOG_MAX_LEVEL 
> > and
> >   CONFIG_TPL_LOG_MAX_LEVEL.
> >
> > +If logging is disabled, the default behaviour is to output any message at
> > +level LOGL_INFO and below. If logging is disabled and DEBUG is defined (at
> > +the very top of a C file) then any message at LOGL_DEBUG will be written.
> > +
> >   Temporary logging within a single file
> >   --
> >
> > @@ -293,8 +297,6 @@ More logging destinations:
> >
> >   Convert debug() statements in the code to log() statements
> >
> > -Support making printf() emit log statements at L_INFO level
> > -
> >   Convert error() statements in the code to log() statements
> >
> >   Figure out what to do with BUG(), BUG_ON() and warn_non_spl()
> > diff --git a/include/log.h b/include/log.h
> > index 6ef891d4d2d..748e34d5a26 100644
> > --- a/include/log.h
> > +++ b/include/log.h
> > @@ -156,6 +156,10 @@ static inline int _log_nop(enum log_category_t cat, 
> > enum log_level_t level,
> >*/
> >   #if CONFIG_IS_ENABLED(LOG)
> >   #define _LOG_MAX_LEVEL CONFIG_VAL(LOG_MAX_LEVEL)
> > +#else
> > +#define _LOG_MAX_LEVEL LOGL_INFO
> > +#endif
> > +
> >   #define log_emer(_fmt...)   log(LOG_CATEGORY, LOGL_EMERG, ##_fmt)
> >   #define log_alert(_fmt...)  log(LOG_CATEGORY, LOGL_ALERT, ##_fmt)
> >   #define log_crit(_fmt...)   log(LOG_CATEGORY, LOGL_CRIT, ##_fmt)
> > @@ -167,41 +171,32 @@ static inline int _log_nop(enum log_category_t cat, 
> > enum log_level_t level,
> >   #define log_content(_fmt...)log(LOG_CATEGORY, LOGL_DEBUG_CONTENT, 
> > ##_fmt)
> >   #define log_io(_fmt...) log(LOG_CATEGORY, LOGL_DEBUG_IO, 
> > ##_fmt)
> >   #define log_cont(_fmt...)   log(LOGC_CONT, LOGL_CONT, ##_fmt)
> > -#else
> > -#define _LOG_MAX_LEVEL LOGL_INFO
> > -#define log_emerg(_fmt, ...) printf(_fmt, ##__VA_ARGS__)
> > -#define log_alert(_fmt, ...) printf(_fmt, ##__VA_ARGS__)
> > -#define log_crit(_fmt, ...)  printf(_fmt, ##__VA_ARGS__)
> > -#define log_err(_fmt, ...)   printf(_fmt, ##__VA_ARGS__)
> > -#define log_warning(_fmt, ...)   printf(_fmt, ##__VA_ARGS__)
> > -#define log_notice(_fmt, ...)printf(_fmt, ##__VA_ARGS__)
> > -#define log_info(_fmt, ...)  printf(_fmt, ##__VA_ARGS__)
> > -#define log_cont(_fmt, ...)  printf(_fmt, ##__VA_ARGS__)
> > -#define log_debug(_fmt, ...) debug(_fmt, ##__VA_ARGS__)
> > -#define log_content(_fmt...) log_nop(LOG_CATEGORY, \
> > - LOGL_DEBUG_CONTENT, ##_fmt)
> > -#define log_io(_fmt...)  log_nop(LOG_CATEGORY, LOGL_DEBUG_IO, 
> > ##_fmt)
> > -#endif
> >
> > -#if CONFIG_IS_ENABLED(LOG)
> >   #ifdef LOG_DEBUG
> >   #define _LOG_DEBUG  LOGL_FORCE_DEBUG
> >   #else
> >   #define _LOG_DEBUG  0
> >   #endif
> >
> > +#if CONFIG_IS_ENABLED(LOG)
> > +
> >   /* Emit a log record if the level is less that the maximum */
> >   #define log(_cat, _level, _fmt, _args...) ({ \
> >   int _l = _level; \
> > - if (CONFIG_IS_ENABLED(LOG) && \
> > - (_LOG_DEBUG != 0 || _l <= _LOG_MAX_LEVEL)) \
> > + if (_LOG_DEBUG != 0 || _l <= _LOG_MAX_LEVEL) \
> >   _log((enum log_category_t)(_cat), \
> >(enum log_level_t)(_l | _LOG_DEBUG), __FILE__, \
> >__LINE__, __func__, \
> > pr_fmt(_fmt), ##_args); \
> >   })
> >   #else
> > -#define log(_cat, _level, _fmt, _args...)
> > +/* Note: _LOG_DEBUG != 0 avoids a warning with clang */
> > +#define log(_cat, _level, _fmt, _args...) ({ \
> > + int _l = _level; \
> > + if (_LOG_DEBUG != 0 || _l <= LOGL_INFO 

Re: [PATCH v3 12/12] smbios: Allow a few values to come from sysinfo

2021-02-04 Thread Simon Glass
Hi Bin,

On Mon, 1 Feb 2021 at 00:25, Bin Meng  wrote:
>
> Hi Simon,
>
> On Mon, Jan 25, 2021 at 1:51 AM Simon Glass  wrote:
> >
> > While static configuration is useful it cannot cover every case. Sometimes
> > board revisions are encoded in resistor straps and must be read at
> > runtime.
> >
> > The easiest way to provide this information is via sysinfo, since the
> > board can then provide a driver to read whatever is needed.
> >
> > Add some standard sysinfo options for this, and use them to obtain the
> > required information.
> >
> > Signed-off-by: Simon Glass 
> >
>
> I guess you used patman to automatically collect the Reviewed-by tag?
>
> Is this blank line inserted by patman? If yes, we should fix patman to
> avoid this.

Yes I use patman to collect review tags and also to show comments. I
find it much more convenient than using the web interface.

I believe that bug is fixed now, but let's see if it happens again.

Regards,
Simon


Re: [PATCH v1] test: Allow simple glob pattern in the test name

2021-02-04 Thread Simon Glass
Hi Andy,

On Wed, 3 Feb 2021 at 08:32, Andy Shevchenko
 wrote:
>
> When run `ut dm [test name]` allow to use simple pattern to run all tests
> started with given prefix. For example, to run all ACPI test cases:
> ut dm acpi*
>
> Signed-off-by: Andy Shevchenko 
> ---
>  test/dm/test-main.c | 12 +---
>  1 file changed, 9 insertions(+), 3 deletions(-)

This seems like a good idea to me.

Can you please send it rebased to u-boot-dm/test-working though? I
have done a bit of refactoring and this function is now in
test/test-main.c

Regards,
Simon


Re: [PATCH v1] test: Include /sbin to the PATH when creating ext4 disk image

2021-02-04 Thread Simon Glass
Hi Andy,

On Wed, 3 Feb 2021 at 08:32, Andy Shevchenko
 wrote:
>
> On some distributions the mkfs.ext4 is under /sbin and /sbin is not set
> for mere users. Include /sbin to the PATH when creating ext4 disk image,
> so that users won't get a scary traceback from Python.
>
> Signed-off-by: Andy Shevchenko 
> ---
>  test/py/tests/test_env.py | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/test/py/tests/test_env.py b/test/py/tests/test_env.py
> index 940279651da0..536467320e06 100644
> --- a/test/py/tests/test_env.py
> +++ b/test/py/tests/test_env.py
> @@ -414,6 +414,9 @@ def mk_env_ext4(state_test_env):
>  if os.path.exists(persistent):
>  c.log.action('Disk image file ' + persistent + ' already exists')
>  else:
> +root_path = os.path.abspath('.').split(os.path.sep)[0] + os.path.sep

Is it not enough to do os.path.abspath('.') ? I think it would be good
to have a comment as to what we need this gymnastics.

> +sbin_path = os.path.join(root_path, 'sbin')
> +os.environ["PATH"] += os.pathsep + sbin_path
>  try:
>  u_boot_utils.run_and_log(c, 'dd if=/dev/zero of=%s bs=1M 
> count=16' % persistent)
>  u_boot_utils.run_and_log(c, 'mkfs.ext4 %s' % persistent)
> --
> 2.30.0
>

Regards,
Simon


Re: [PATCH] gpio-uclass: fix gpio flags save condition

2021-02-04 Thread Simon Glass
Hi Köry,

On Mon, 25 Jan 2021 at 07:27, Köry Maincent  wrote:
>
> Hello Simon,
>
> On Sun, 24 Jan 2021 13:24:14 -0700
> Simon Glass  wrote:
>
> > Hi Kory,
> >
> > On Fri, 22 Jan 2021 at 08:23, Kory Maincent  
> > wrote:
> > >
> > > The commit cd2faeba1a moves the location where we save the flags to the 
> > > gpio
> > > descriptor but it adds a "!" character.
> > > This breaks the condition we expect to save the flags.
> > >
> > > Signed-off-by: Kory Maincent 
> > > ---
> > >  drivers/gpio/gpio-uclass.c | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > >
> >
> > This does indeed seem to be a bug, and the tests do not cover it. But
> > this happens to be fixed by my GPIO series. I'm about to send out v3
> > so will copy you on it.
>
> Thanks.
>
> I have tested your series of patch and it seems to have also an issue with my
> use case.
> I am working with w1-gpio.
> I got this issue:
> => w1 bus
> check_dir_flags: flags 0x16 has GPIOD_IS_OUT and GPIOD_IS_IN
> gpio_sunxi PD: PD error: set_dir_flags for gpio PD2 has invalid dir flags 0x16
> Bus 0:  onewire  (active)
> w1_eeprom@0 (0) uclass w1_eeprom : family 0x0

Thank you for that. I think that is because dm_gpio_set_dir_flags()
does not clear the flags first. But we now do actually update
desc->flags, where as before it was just supposed to happen. So I
think this function needs to update to clear the direction flags, then
add in the ones passed.

I have pushed this to u-boot-dm/gpio-working if you can test it again.

Regards,
Simon


Re: [PATCH 1/4] Respect that some compression algos can be enabled separately for SPL

2021-02-04 Thread Tim Harvey
On Thu, Feb 4, 2021 at 12:49 PM Stefano Babic  wrote:
>
> Hallo Tim,
>
> On 04.02.21 18:31, Tim Harvey wrote:
> > On Sat, Jan 30, 2021 at 1:23 PM Stefano Babic  wrote:
> >>
> >> Hi everybody,
> >>
> >> On 27.01.21 14:19, Stefano Babic wrote:
> >>> On 27.01.21 08:57, Frieder Schrempf wrote:
>  On 26.01.21 18:53, Tim Harvey wrote:
> > On Sat, Jan 23, 2021 at 4:39 AM Stefano Babic  wrote:
> >>
> >> Hi Tim,
> >>
> >> there is a weird side effect with this patch, breaking m68k
> >> architecture. For some reason, image.c is not compiled clean because gd
> >> is not declared anymore.
> >>
> >> In file included from tools/common/image.c:1:
> >> ./tools/../common/image.c: In function ‘get_table_entry_id’:
> >> ./tools/../common/image.c:982:41: error: ‘gd’ undeclared (first use in
> >> this function)
> >>  982 |   if (t->sname && strcasecmp(t->sname + gd->reloc_off, name)
> >> == 0)
> >>  | ^~
> >> ./tools/../common/image.c:982:41: note: each undeclared identifier is
> >> reported only once for each functi
> >>
> >> Can you take a look ? Thanks !
> >>
> >
> > Stefano,
> >
> > I have no idea what could cause this... must be something to do with
> > including kconfig.h?
> >
> > What board/target would I build to reproduce this?
> >
> > Frieder, do you have any ideas?
> 
>  I can't remember if I did a full test on all platforms when I wrote this
>  patch. Probably not.
> 
>  And I have no idea what is causing this, nor do I currently have the
>  time to have a closer look, sorry.
> 
>  BTW, this is a very good example for what I said earlier:
> 
>  "I failed to do upstreaming work for U-Boot for quite some time. Mainly
>  because whenever I try to, I end up fixing/cleaning some weird U-Boot
>  code/behavior and spending way more time than I actually have available."
> >>>
> >>> True, but...we cannot even break other boards, too. I have also get a
> >>> short look at the issue, but I could not find myself the reason, too. I
> >>> plan to get a deeper look in the week end.
> >>
> >> It looks like that only for m68k the following statement does not work
> >>
> >> #if CONFIG_IS_ENABLED(GZIP) && !defined(USE_HOSTCC)
> >>
> >> But if I replace this with the equivalent one:
> >>
> >> +#ifndef USE_HOSTCC
> >> +#if CONFIG_IS_ENABLED(GZIP)
> >>
> >> This works - someone else should have discovered this before, because in
> >> common/image.c USE_HOSTCC is never anded with another CONFIG.
> >>
> >> I have not found why this happens just for m68k, no issue with
> >> arm/aarch64 or PowerPC. I send a V2 with the changes like above.
> >>
> >> @Tim: why do we need include/kconfig ?
> >
> > Stefano,
> >
> > If we switch to your method above we don't need it (it was needed for
> > what I submitted).
>
> Ok
>
> >
> > Shall I resubmit with your suggested change around
> > GZIP/BZIP2/LZMA/LZO/LZ4/ZSTD in image_decomp?
>
> Yes, please.
>
> > And if so, with these
> > changes would I replace Frieder's sign-off with a Cc as the patch has
> > changed quite a bit from his original derived work?
>
> No, I do not think so. Original work is from Frieder, and his work
> should be tracked. You add of course your Signed-off-by, but without
> removing Frieder's.
>
> >
> > Have you had any time to review the reset of the patch series yet?
>
> The rest, you mean :-)
>
> It was ok for me and I was already merging the whole series until I got
> this weird error on m68k.
>

Ok, I'll submit a v2 with the changes here. The pmic driver already
got applied so the series will drop that patch.

Thanks,

Tim


Re: [PATCH v2 6/6] log: Convert log values to printf() if not enabled

2021-02-04 Thread Sean Anderson

On 1/20/21 10:10 PM, Simon Glass wrote:

At present if logging not enabled, log_info() becomes a nop. But we want
log output at the 'info' level to be akin to printf(). Update the macro to
pass the output straight to printf() in this case.

This mimics the behaviour for the log_...() macros like log_debug() and
log_info(), so we can drop the special case for these.

Add new tests to cover this case.
Signed-off-by: Simon Glass 
---

Changes in v2:
- Update commit message and cover letter to mention log_...() macros
- Add a test for !CONFIG_LOG
- Update log() to (effectively) call debug() for log_level == LOGL_DEBUG

  doc/develop/logging.rst |  6 --
  include/log.h   | 33 ++---
  test/log/Makefile   |  1 +
  test/log/nolog_ndebug.c | 38 ++
  test/log/nolog_test.c   |  3 +++
  5 files changed, 60 insertions(+), 21 deletions(-)
  create mode 100644 test/log/nolog_ndebug.c

diff --git a/doc/develop/logging.rst b/doc/develop/logging.rst
index b6c6b45049f..55cef42664d 100644
--- a/doc/develop/logging.rst
+++ b/doc/develop/logging.rst
@@ -54,6 +54,10 @@ If CONFIG_LOG is not set, then no logging will be available.
  The above have SPL and TPL versions also, e.g. CONFIG_SPL_LOG_MAX_LEVEL and
  CONFIG_TPL_LOG_MAX_LEVEL.
  
+If logging is disabled, the default behaviour is to output any message at

+level LOGL_INFO and below. If logging is disabled and DEBUG is defined (at
+the very top of a C file) then any message at LOGL_DEBUG will be written.
+
  Temporary logging within a single file
  --
  
@@ -293,8 +297,6 @@ More logging destinations:
  
  Convert debug() statements in the code to log() statements
  
-Support making printf() emit log statements at L_INFO level

-
  Convert error() statements in the code to log() statements
  
  Figure out what to do with BUG(), BUG_ON() and warn_non_spl()

diff --git a/include/log.h b/include/log.h
index 6ef891d4d2d..748e34d5a26 100644
--- a/include/log.h
+++ b/include/log.h
@@ -156,6 +156,10 @@ static inline int _log_nop(enum log_category_t cat, enum 
log_level_t level,
   */
  #if CONFIG_IS_ENABLED(LOG)
  #define _LOG_MAX_LEVEL CONFIG_VAL(LOG_MAX_LEVEL)
+#else
+#define _LOG_MAX_LEVEL LOGL_INFO
+#endif
+
  #define log_emer(_fmt...) log(LOG_CATEGORY, LOGL_EMERG, ##_fmt)
  #define log_alert(_fmt...)log(LOG_CATEGORY, LOGL_ALERT, ##_fmt)
  #define log_crit(_fmt...) log(LOG_CATEGORY, LOGL_CRIT, ##_fmt)
@@ -167,41 +171,32 @@ static inline int _log_nop(enum log_category_t cat, enum 
log_level_t level,
  #define log_content(_fmt...)  log(LOG_CATEGORY, LOGL_DEBUG_CONTENT, ##_fmt)
  #define log_io(_fmt...)   log(LOG_CATEGORY, LOGL_DEBUG_IO, ##_fmt)
  #define log_cont(_fmt...) log(LOGC_CONT, LOGL_CONT, ##_fmt)
-#else
-#define _LOG_MAX_LEVEL LOGL_INFO
-#define log_emerg(_fmt, ...)   printf(_fmt, ##__VA_ARGS__)
-#define log_alert(_fmt, ...)   printf(_fmt, ##__VA_ARGS__)
-#define log_crit(_fmt, ...)printf(_fmt, ##__VA_ARGS__)
-#define log_err(_fmt, ...) printf(_fmt, ##__VA_ARGS__)
-#define log_warning(_fmt, ...) printf(_fmt, ##__VA_ARGS__)
-#define log_notice(_fmt, ...)  printf(_fmt, ##__VA_ARGS__)
-#define log_info(_fmt, ...)printf(_fmt, ##__VA_ARGS__)
-#define log_cont(_fmt, ...)printf(_fmt, ##__VA_ARGS__)
-#define log_debug(_fmt, ...)   debug(_fmt, ##__VA_ARGS__)
-#define log_content(_fmt...)   log_nop(LOG_CATEGORY, \
-   LOGL_DEBUG_CONTENT, ##_fmt)
-#define log_io(_fmt...)log_nop(LOG_CATEGORY, LOGL_DEBUG_IO, 
##_fmt)
-#endif
  
-#if CONFIG_IS_ENABLED(LOG)

  #ifdef LOG_DEBUG
  #define _LOG_DEBUGLOGL_FORCE_DEBUG
  #else
  #define _LOG_DEBUG0
  #endif
  
+#if CONFIG_IS_ENABLED(LOG)

+
  /* Emit a log record if the level is less that the maximum */
  #define log(_cat, _level, _fmt, _args...) ({ \
int _l = _level; \
-   if (CONFIG_IS_ENABLED(LOG) && \
-   (_LOG_DEBUG != 0 || _l <= _LOG_MAX_LEVEL)) \
+   if (_LOG_DEBUG != 0 || _l <= _LOG_MAX_LEVEL) \
_log((enum log_category_t)(_cat), \
 (enum log_level_t)(_l | _LOG_DEBUG), __FILE__, \
 __LINE__, __func__, \
  pr_fmt(_fmt), ##_args); \
})
  #else
-#define log(_cat, _level, _fmt, _args...)
+/* Note: _LOG_DEBUG != 0 avoids a warning with clang */
+#define log(_cat, _level, _fmt, _args...) ({ \
+   int _l = _level; \
+   if (_LOG_DEBUG != 0 || _l <= LOGL_INFO || \


Should this be < CONFIG_LOGLEVEL?

--Sean


+   (_DEBUG && _l == LOGL_DEBUG)) \
+   printf(_fmt, ##_args); \
+   })
  #endif
  
  #define log_nop(_cat, _level, _fmt, _args...) ({ \

diff --git a/test/log/Makefile b/test/log/Makefile
index 0e900363595..b63064e8d02 100644
--- a/test/log/Makefile
+++ b/test/log/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_CONSOLE_RECORD) += cont_test.o
  obj-y += pr_cont_test.o
  else
  

Re: [PATCH v2 0/6] log: Allow multiple lines and conversion to printf()

2021-02-04 Thread Simon Glass
+Heinrich Schuchardt

Hi Heinrich,

On Wed, 20 Jan 2021 at 20:11, Simon Glass  wrote:
>
> At present when logging is not enabled, all log() calls become nops. This
> does not seem right, since if the log level is high enough then there
> should be some sort of message. So in that case, this series updates it to
> print the message if the log level is above LOGL_INFO.
>
> This mimics the behaviour for the log_...() macros like log_debug() and
> log_info(), so we can drop the special case for these.
>
> Also the current implementation does not support multiple log calls on the
> same line nicely. The tags are repeated so the line is very hard to read.
> This series adds that as a new feature.
>
> Changes in v2:
> - Move the newline check into log_dispatch()
> - Update commit message and cover letter to mention log_...() macros
> - Add a test for !CONFIG_LOG
> - Update log() to (effectively) call debug() for log_level == LOGL_DEBUG
>
> Simon Glass (6):
>   log: Set up a flag byte for log records
>   log: Handle line continuation
>   log: Add return-checking macros for 0 being success
>   sandbox: log: Avoid build error with !CONFIG_LOG
>   tpm: Don't select LOG
>   log: Convert log values to printf() if not enabled

I should have sent this series to you as well, since you had a comment
on the original version.

It is at u-boot-dm/log-working if that is easier.

Regards,
Simon


[PATCH v3] video: sunxi_display: Convert to DM_VIDEO

2021-02-04 Thread Andre Przywara
From: Jagan Teki 

DM_VIDEO migration deadline is already expired, but around
80 Allwinner boards are still using video in a legacy way.

= WARNING ==
This board does not use CONFIG_DM_VIDEO Please update
the board to use CONFIG_DM_VIDEO before the v2019.07 release.
Failure to update by the deadline may result in board removal.
See doc/driver-model/migration.rst for more info.


Convert the legacy video driver over to the DM_VIDEO framework. This is
a minimal conversion: it doesn't use the DT for finding its resources,
nor does it use DM clocks or DM devices for the outputs (LCD, HDMI, CVBS).

Tested in Bananapi M1+ Plus 1920x1200 HDMI out. (Jagan)

Signed-off-by: Jagan Teki 
[Andre: rebase and smaller fixes]
Signed-off-by: Andre Przywara 
---
Hi,

I picked this one up to get rid of the warnings. I dropped the BMP
support for now (v2 1/3 and v2 2/3), I need to have a closer look, as
I am not convinced this was the right solution.

Cheers,
Andre

Changelog v2 .. v3:
- rebase against master, fixing up renamed variables and structs
- replace enum with #define
- remove BMP from Kconfig
- fix memory node size calculation in simplefb setup

 arch/arm/mach-sunxi/Kconfig |   9 +-
 drivers/video/sunxi/sunxi_display.c | 262 
 include/configs/sunxi-common.h  |  17 --
 scripts/config_whitelist.txt|   1 -
 4 files changed, 157 insertions(+), 132 deletions(-)

diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 0135575ca1e..a29d11505aa 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -816,13 +816,14 @@ config VIDEO_SUNXI
depends on !MACH_SUN9I
depends on !MACH_SUN50I
depends on !SUN50I_GEN_H6
-   select VIDEO
+   select DM_VIDEO
+   select DISPLAY
imply VIDEO_DT_SIMPLEFB
default y
---help---
-   Say Y here to add support for using a cfb console on the HDMI, LCD
-   or VGA output found on most sunxi devices. See doc/README.video for
-   info on how to select the video output and mode.
+   Say Y here to add support for using a graphical console on the HDMI,
+   LCD or VGA output found on older sunxi devices. This will also provide
+   a simple_framebuffer device for Linux.
 
 config VIDEO_HDMI
bool "HDMI output support"
diff --git a/drivers/video/sunxi/sunxi_display.c 
b/drivers/video/sunxi/sunxi_display.c
index f52aba4d21c..61498d1642f 100644
--- a/drivers/video/sunxi/sunxi_display.c
+++ b/drivers/video/sunxi/sunxi_display.c
@@ -7,6 +7,8 @@
  */
 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -28,7 +30,9 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 #include "../videomodes.h"
 #include "../anx9804.h"
 #include "../hitachi_tx18d42vm_lcd.h"
@@ -45,6 +49,11 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/* Maximum LCD size we support */
+#define LCD_MAX_WIDTH  3840
+#define LCD_MAX_HEIGHT 2160
+#define LCD_MAX_LOG2_BPP   VIDEO_BPP32
+
 enum sunxi_monitor {
sunxi_monitor_none,
sunxi_monitor_dvi,
@@ -59,12 +68,11 @@ enum sunxi_monitor {
 #define SUNXI_MONITOR_LAST sunxi_monitor_composite_pal_nc
 
 struct sunxi_display {
-   GraphicDevice graphic_device;
enum sunxi_monitor monitor;
unsigned int depth;
unsigned int fb_addr;
unsigned int fb_size;
-} sunxi_display;
+};
 
 const struct ctfb_res_modes composite_video_modes[2] = {
/*  x y  hz  pixclk ps/kHz   le   ri  up  lo   hs vs  s  vmode */
@@ -214,7 +222,8 @@ static int sunxi_hdmi_edid_get_block(int block, u8 *buf)
return r;
 }
 
-static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode,
+static int sunxi_hdmi_edid_get_mode(struct sunxi_display *sunxi_display,
+   struct ctfb_res_modes *mode,
bool verbose_mode)
 {
struct edid1_info edid1;
@@ -291,14 +300,14 @@ static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes 
*mode,
}
 
/* Check for basic audio support, if found enable hdmi output */
-   sunxi_display.monitor = sunxi_monitor_dvi;
+   sunxi_display->monitor = sunxi_monitor_dvi;
for (i = 0; i < ext_blocks; i++) {
if (cea681[i].extension_tag != EDID_CEA861_EXTENSION_TAG ||
cea681[i].revision < 2)
continue;
 
if (EDID_CEA861_SUPPORTS_BASIC_AUDIO(cea681[i]))
-   sunxi_display.monitor = sunxi_monitor_hdmi;
+   sunxi_display->monitor = sunxi_monitor_hdmi;
}
 
return 0;
@@ -414,9 +423,9 @@ static void sunxi_frontend_mode_set(const struct 
ctfb_res_modes *mode,
 static void sunxi_frontend_enable(void) {}
 #endif
 
-static bool sunxi_is_composite(void)
+static bool sunxi_is_composite(enum sunxi_monitor monitor)
 {
-   switch 

Re: [PATCH v2 27/28] fs/squashfs: sqfs_read: fragmented files are not supported

2021-02-04 Thread João Marcos Costa
Em qua., 27 de jan. de 2021 às 12:15, Simon Glass 
escreveu:

> Hi Joao,

Hello!

>
>
> This test works the first time I run it but fails the second time,
> since the directory already exists. This makes it necessary to disable
> the test for development.
>
> It also uses the wrong quoting style - we have settled on a single
> quote by default in U-Boot.
>
> Finally, the tests and some functions need comments about what they do
> and what the arguments are.
>
> Please can you take a look?

Absolutely. Excuse me for such a late reply.

>


> Thanks,
> Simon
>


-- 
Atenciosamente,
João Marcos Costa

www.linkedin.com/in/jmarcoscosta/
https://github.com/jmarcoscosta


Re: [PATCH v2] fastboot: add UUU command UCmd and ACmd support

2021-02-04 Thread Lukasz Majewski
Hi Heiko,

> add support for the UUU commands ACmd and UCmd.
> 
> Enable them through the Kconfig option
> CONFIG_FASTBOOT_UUU_SUPPORT
> 
> base was commit in NXP kernel
> 9b149c2a2882: ("MLK-18591-3 android: Add FSL android fastboot
> support")
> 
> and ported it to current mainline. Tested this patch
> on imx6ul based board.
> 
> Signed-off-by: Heiko Schocher 
> ---
> 
> Changes in v2:
> - remove unused FSL_FASTBOOT option
> - add comment from Roman:
>   do not enable this option per default
>   add Kconfig comment that enabling this option may
>   introduce a security issue.

Could you fix this patch to be applicable on top of:

https://github.com/lmajewski/u-boot-dfu/commits/testing

Thanks in advance,

Best regards,
Lukasz

> 
>  doc/android/fastboot-protocol.rst |  5 +++
>  doc/android/fastboot.rst  |  2 +
>  drivers/fastboot/Kconfig  |  9 +
>  drivers/fastboot/fb_command.c | 62
> +++ drivers/usb/gadget/f_fastboot.c   |
> 17 + include/fastboot.h|  7 
>  6 files changed, 102 insertions(+)
> 
> diff --git a/doc/android/fastboot-protocol.rst
> b/doc/android/fastboot-protocol.rst index e723659e49c..e8cbd7f24ea
> 100644 --- a/doc/android/fastboot-protocol.rst
> +++ b/doc/android/fastboot-protocol.rst
> @@ -144,6 +144,11 @@ Command Reference
>  
>"powerdown"  Power off the device.
>  
> +  "ucmd"   execute any bootloader command and wait until
> it
> +   finishs.
> +
> +  "acmd"   execute any bootloader command, do not wait.
> +
>  Client Variables
>  
>  
> diff --git a/doc/android/fastboot.rst b/doc/android/fastboot.rst
> index 2877c3cbaaa..b58d1b5b31a 100644
> --- a/doc/android/fastboot.rst
> +++ b/doc/android/fastboot.rst
> @@ -19,6 +19,8 @@ The current implementation supports the following
> standard commands:
>  - ``reboot``
>  - ``reboot-bootloader``
>  - ``set_active`` (only a stub implementation which always succeeds)
> +- ``ucmd`` (if enabled)
> +- ``acmd`` (if enabled)
>  
>  The following OEM commands are supported (if enabled):
>  
> diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig
> index 4352ba67a71..898e222cf60 100644
> --- a/drivers/fastboot/Kconfig
> +++ b/drivers/fastboot/Kconfig
> @@ -72,6 +72,15 @@ config FASTBOOT_FLASH
> the downloaded image to a non-volatile storage device.
> Define this to enable the "fastboot flash" command.
>  
> +config FASTBOOT_UUU_SUPPORT
> + bool "Enable FASTBOOT i.MX UUU special command"
> + default n
> + help
> +   The fastboot protocol includes "UCmd" and "ACmd" command.
> +   Be aware that you provide full access to any U-Boot
> command,
> +   including working with memory and may open a huge backdoor,
> +   when enabling this option.
> +
>  choice
>   prompt "Flash provider for FASTBOOT"
>   depends on FASTBOOT_FLASH
> diff --git a/drivers/fastboot/fb_command.c
> b/drivers/fastboot/fb_command.c index d3c578672dc..31a47e46386 100644
> --- a/drivers/fastboot/fb_command.c
> +++ b/drivers/fastboot/fb_command.c
> @@ -43,6 +43,11 @@ static void reboot_recovery(char *, char *);
>  static void oem_format(char *, char *);
>  #endif
>  
> +#if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT)
> +static void run_ucmd(char *, char *);
> +static void run_acmd(char *, char *);
> +#endif
> +
>  static const struct {
>   const char *command;
>   void (*dispatch)(char *cmd_parameter, char *response);
> @@ -99,6 +104,16 @@ static const struct {
>   .dispatch = oem_format,
>   },
>  #endif
> +#if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT)
> + [FASTBOOT_COMMAND_UCMD] = {
> + .command = "UCmd",
> + .dispatch = run_ucmd,
> + },
> + [FASTBOOT_COMMAND_ACMD] = {
> + .command = "ACmd",
> + .dispatch = run_acmd,
> + },
> +#endif
>  };
>  
>  /**
> @@ -309,6 +324,53 @@ static void erase(char *cmd_parameter, char
> *response) }
>  #endif
>  
> +#if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT)
> +/**
> + * run_ucmd() - Execute the UCmd command
> + *
> + * @cmd_parameter: Pointer to command parameter
> + * @response: Pointer to fastboot response buffer
> + */
> +static void run_ucmd(char *cmd_parameter, char *response)
> +{
> + if (!cmd_parameter) {
> + pr_err("missing slot suffix\n");
> + fastboot_fail("missing command", response);
> + return;
> + }
> +
> + if (run_command(cmd_parameter, 0))
> + fastboot_fail("", response);
> + else
> + fastboot_okay(NULL, response);
> +}
> +
> +static char g_a_cmd_buff[64];
> +
> +void fastboot_acmd_complete(void)
> +{
> + run_command(g_a_cmd_buff, 0);
> +}
> +
> +/**
> + * run_acmd() - Execute the ACmd command
> + *
> + * @cmd_parameter: Pointer to command parameter
> + * @response: Pointer to fastboot response buffer
> + */
> +static void run_acmd(char *cmd_parameter, char *response)
> +{
> + 

Re: [PATCH v2] ARM: mx6: Add function to set serial#

2021-02-04 Thread Tom Rini
On Thu, Feb 04, 2021 at 11:31:22PM +0100, Heinrich Schuchardt wrote:
> On 2/4/21 11:12 PM, Sean Anderson wrote:
> > 
> > 
> > On 2/4/21 5:03 PM, Heinrich Schuchardt wrote:
> >  > On 2/4/21 10:58 PM, Tom Rini wrote:
> >  >> On Thu, Feb 04, 2021 at 04:44:22PM -0500, Sean Anderson wrote:
> >  >>
> >  >>> The serial number OTP is similar to the imx7 version, except that the
> >  >>> register names are different. This also sets serial# directly,
> >  >>> instead of
> >  >>> providing board_get_serial.
> >  >>>
> >  >>> Signed-off-by: Sean Anderson 
> >  >>
> >  >> Reviewed-by: Tom Rini 
> >  >>
> >  >
> >  > The current patch is without effect.
> >  >
> >  > We need to enable CONFIG_ARCH_MISC_INIT on i.MX6 by default, e.g.
> >  >
> >  > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> >  > index 95557d6ed6..ba189c404d 100644
> >  > --- a/arch/arm/Kconfig
> >  > +++ b/arch/arm/Kconfig
> >  > @@ -901,6 +901,7 @@ config ARCH_MX6
> >  >  select SYS_FSL_HAS_SEC
> >  >  select SYS_FSL_SEC_COMPAT_4
> >  >  select SYS_FSL_SEC_LE
> >  > +   select ARCH_MISC_INIT
> >  >  imply MXC_GPIO
> >  >  imply SYS_THUMB_BUILD
> >  >
> >  > Best regards
> >  >
> >  > Heinrich
> > 
> > Do any boards on i.MX6 currently set serial# themselves? arch_misc_init
> > is called before board_late_init, which is (AFACT) typically where
> > boards set serial#. Any boards which conditionally set serial# (e.g.
> > from an eeprom) will not set things up properly. I looked over things
> > quickly, and I didn't see anything. So it may be fine to enable this.
> > 
> > Though by this logic, shouldn't you have implied ARCH_MISC_INIT back in
> > 90865614b4 ("ARM: mx6: make CAAM usable on the i.MX6 boards")?
> 
> +1 to activate the flag.
> I was already wondering why the random number generator on my Wandboard
> was not working.
> 
> The three i.MX6 boards with misc_init_r() don's set serial#:
> 
> board/congatec/cgtqmx6eval/cgtqmx6eval.c:755:int misc_init_r(void)
> board/toradex/apalis_imx6/apalis_imx6.c:786:int misc_init_r(void)
> board/toradex/colibri_imx6/colibri_imx6.c:679:int misc_init_r(void)
> 
> git grep -n 'serial#' | grep mx6
> 
> finds nothing.

No.  We have things in Kconfig so that boards can enable what they want
without having to go and change the config.h file.  We only use
select/imply for things that it's between required (if you don't have
this, your platform does not function at all) and strongly encouraged
(it should be hard to opt out of distro defaults for example because
this is what makes almost any distribution turn-key to use on a given
platform).  Everything else should be something easily turned on/off in
the defconfig.  Is "serial#" and in turn the serial-number property in
the device tree handy?  Sure is.  Has i.MX6 been going fine without it
for it's long lifespan?  Yup.  Is there an argument that it should be
easier to opt-out of on all the other platforms?  Probably so, yes (I
think there's some cases where Linux userspace expects it for some
stuff, I want to say allwinner?  Maybe Pi?).

-- 
Tom


signature.asc
Description: PGP signature


Re: [PATCH v2 3/3] video: sunxi_display: Convert to DM_VIDEO

2021-02-04 Thread Andre Przywara
On Fri, 19 Jun 2020 09:30:22 +0200
Maxime Ripard  wrote:

Hi,

I have picked up this patch, rebased, updated and fixed some parts.

I will send a v3 ASAP, so we can continue the discussion on this.

I am replying here to some of the outstanding comments, since this has
the context:

> On Thu, Jun 18, 2020 at 09:37:07PM +0530, Jagan Teki wrote:
> > On Thu, Jun 18, 2020 at 12:54 PM Maxime Ripard  wrote:  
> > >
> > > On Thu, Jun 18, 2020 at 01:54:37AM +0530, Jagan Teki wrote:  
> > > > DM_VIDEO migration deadline is already expired, but around
> > > > 80 Allwinner boards are still using video in a legacy way.
> > > >
> > > > = WARNING ==
> > > > This board does not use CONFIG_DM_VIDEO Please update
> > > > the board to use CONFIG_DM_VIDEO before the v2019.07 release.
> > > > Failure to update by the deadline may result in board removal.
> > > > See doc/driver-model/migration.rst for more info.
> > > > 
> > > >
> > > > So let's live these boards on the tree before the video maintainer
> > > > removes it by converting in to DM_VIDEO.
> > > >
> > > > Tested in Bananapi M1+ Plus 1920x1200 HDMI out.
> > > >
> > > > Signed-off-by: Jagan Teki 
> > > > ---
> > > > Changes for v2:
> > > > - add BMP support
> > > >
> > > >  arch/arm/mach-sunxi/Kconfig |   4 +-
> > > >  drivers/video/sunxi/sunxi_display.c | 264 
> > > >  include/configs/sunxi-common.h  |  17 --
> > > >  scripts/config_whitelist.txt|   1 -
> > > >  4 files changed, 157 insertions(+), 129 deletions(-)
> > > >
> > > > diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
> > > > index be0822bfb7..7d2fb55ff0 100644
> > > > --- a/arch/arm/mach-sunxi/Kconfig
> > > > +++ b/arch/arm/mach-sunxi/Kconfig
> > > > @@ -758,8 +758,10 @@ config VIDEO_SUNXI
> > > >   depends on !MACH_SUN9I
> > > >   depends on !MACH_SUN50I
> > > >   depends on !MACH_SUN50I_H6
> > > > - select VIDEO
> > > > + select DM_VIDEO
> > > > + select DISPLAY
> > > >   imply VIDEO_DT_SIMPLEFB
> > > > + imply CMD_BMP
> > > >   default y
> > > >   ---help---
> > > >   Say Y here to add support for using a cfb console on the HDMI, LCD
> > > > diff --git a/drivers/video/sunxi/sunxi_display.c 
> > > > b/drivers/video/sunxi/sunxi_display.c
> > > > index f52aba4d21..fb51b0c5ba 100644
> > > > --- a/drivers/video/sunxi/sunxi_display.c
> > > > +++ b/drivers/video/sunxi/sunxi_display.c
> > > > @@ -7,6 +7,8 @@
> > > >   */
> > > >
> > > >  #include 
> > > > +#include 
> > > > +#include 
> > > >  #include 
> > > >  #include 
> > > >  #include 
> > > > @@ -28,7 +30,9 @@
> > > >  #include 
> > > >  #include 
> > > >  #include 
> > > > +#include 
> > > >  #include 
> > > > +#include 
> > > >  #include "../videomodes.h"
> > > >  #include "../anx9804.h"
> > > >  #include "../hitachi_tx18d42vm_lcd.h"
> > > > @@ -45,6 +49,13 @@
> > > >
> > > >  DECLARE_GLOBAL_DATA_PTR;
> > > >
> > > > +enum {
> > > > + /* Maximum LCD size we support */
> > > > + LCD_MAX_WIDTH   = 3840,
> > > > + LCD_MAX_HEIGHT  = 2160,
> > > > + LCD_MAX_LOG2_BPP= VIDEO_BPP32,
> > > > +};  
> > >
> > > Why is that an enum? Those three values don't have any relationship with
> > > each other.  
> > 
> > Not sure I understand your question. These are maximum resolution
> > followed by maximum bpp supporting. based on these the fbbuffer
> > allocation happens, please see sunxi_de_bind on this patch.  
> 
> An enum is used for variables that can hold multiple values. There's no
> relationship between those values, you cannot use the BPP in place of
> the width there for example, it doesn't make any sense. So you must not
> use an enum.

I agree that an enum does not make sense here. That seems to be
copied from sunxi_de2.c, which has the same code ;-)
My guess is this stems from some misunderstood "use enums instead of
#define!" recommendation. I replaced it with old-fashioned #defines.

> 
> > > > -ulong board_get_usable_ram_top(ulong total_size)
> > > > -{
> > > > - return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE;
> > > > -}
> > > > -  
> > >
> > > I couldn't find how you're allocating and reserving the video buffer now
> > > for simplefb to use later on.  
> > 
> > Based on maximum supporting resolutions and bpp as explained above and
> > similar like what sunxi_de2 and other platforms like rockchip. via
> > plat->size.  
> 
> It really doesn't explain how you're allocating and reserving it for
> simplefb though, merely how much memory you're allocating.
> 
> Let me rephrase this. simplefb will run in Linux based on an address
> that is passed from the bootloader to Linux through the device tree. How
> do you make sure that Linux will not reuse that buffer for something
> else once it's been booted?
> 
> The previous code was doing that by removing enough space from the total
> memory available, so Linux could 

Re: [PATCH v2] ARM: mx6: Add function to set serial#

2021-02-04 Thread Heinrich Schuchardt

On 2/4/21 11:12 PM, Sean Anderson wrote:



On 2/4/21 5:03 PM, Heinrich Schuchardt wrote:
 > On 2/4/21 10:58 PM, Tom Rini wrote:
 >> On Thu, Feb 04, 2021 at 04:44:22PM -0500, Sean Anderson wrote:
 >>
 >>> The serial number OTP is similar to the imx7 version, except that the
 >>> register names are different. This also sets serial# directly,
 >>> instead of
 >>> providing board_get_serial.
 >>>
 >>> Signed-off-by: Sean Anderson 
 >>
 >> Reviewed-by: Tom Rini 
 >>
 >
 > The current patch is without effect.
 >
 > We need to enable CONFIG_ARCH_MISC_INIT on i.MX6 by default, e.g.
 >
 > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
 > index 95557d6ed6..ba189c404d 100644
 > --- a/arch/arm/Kconfig
 > +++ b/arch/arm/Kconfig
 > @@ -901,6 +901,7 @@ config ARCH_MX6
 >  select SYS_FSL_HAS_SEC
 >  select SYS_FSL_SEC_COMPAT_4
 >  select SYS_FSL_SEC_LE
 > +   select ARCH_MISC_INIT
 >  imply MXC_GPIO
 >  imply SYS_THUMB_BUILD
 >
 > Best regards
 >
 > Heinrich

Do any boards on i.MX6 currently set serial# themselves? arch_misc_init
is called before board_late_init, which is (AFACT) typically where
boards set serial#. Any boards which conditionally set serial# (e.g.
from an eeprom) will not set things up properly. I looked over things
quickly, and I didn't see anything. So it may be fine to enable this.

Though by this logic, shouldn't you have implied ARCH_MISC_INIT back in
90865614b4 ("ARM: mx6: make CAAM usable on the i.MX6 boards")?


+1 to activate the flag.
I was already wondering why the random number generator on my Wandboard
was not working.

The three i.MX6 boards with misc_init_r() don's set serial#:

board/congatec/cgtqmx6eval/cgtqmx6eval.c:755:int misc_init_r(void)
board/toradex/apalis_imx6/apalis_imx6.c:786:int misc_init_r(void)
board/toradex/colibri_imx6/colibri_imx6.c:679:int misc_init_r(void)

git grep -n 'serial#' | grep mx6

finds nothing.

Best regards

Heinrich



--Sean




Re: [PATCH v2] ARM: mx6: Add function to set serial#

2021-02-04 Thread Tom Rini
On Thu, Feb 04, 2021 at 11:03:06PM +0100, Heinrich Schuchardt wrote:
> On 2/4/21 10:58 PM, Tom Rini wrote:
> > On Thu, Feb 04, 2021 at 04:44:22PM -0500, Sean Anderson wrote:
> > 
> > > The serial number OTP is similar to the imx7 version, except that the
> > > register names are different. This also sets serial# directly, instead of
> > > providing board_get_serial.
> > > 
> > > Signed-off-by: Sean Anderson 
> > 
> > Reviewed-by: Tom Rini 
> > 
> 
> The current patch is without effect.
> 
> We need to enable CONFIG_ARCH_MISC_INIT on i.MX6 by default, e.g.
> 
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 95557d6ed6..ba189c404d 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -901,6 +901,7 @@ config ARCH_MX6
> select SYS_FSL_HAS_SEC
> select SYS_FSL_SEC_COMPAT_4
> select SYS_FSL_SEC_LE
> +   select ARCH_MISC_INIT
> imply MXC_GPIO
> imply SYS_THUMB_BUILD

No, we don't need to enable it by default.  If boards want it, they can
enable it.

-- 
Tom


signature.asc
Description: PGP signature


Re: [PATCH u-boot-marvell] mmc: mv_sdhci: call mmc_of_parse()

2021-02-04 Thread Jaehoon Chung
Dear Marek,

On 2/5/21 1:38 AM, Marek Behún wrote:
> On Thu, 4 Feb 2021 07:18:23 +0900
> Jaehoon Chung  wrote:
> 
>>> Commit da18c62b6e6a causes the regression. The Fixes tag, as I
>>> understand, should link to commit with which the regression first
>>> occured, so that if someone wanted to backport my patch to previous
>>> version of U-Boot, they would know that they only have to do it if
>>> their repository contains that commit.  
>>
>> Well, i don't think so. This patch is not a bug fix patch about
>> commit da18c62b6e6a. Just mv_sdhci driver didn't use mmc_of_parse()
>> before. (If someone set to MMC_NON_REMOVABLE capabilities in
>> host->cap, it should be working.)
>>
>> Not need to add *Fixes*. Its commit is a generic callback function.
>> And mmc_of_parse() is also generic function to use Driver-model.
> 
> Lets apply Baruch's version. I don't really care if the Fixes tag is
> there or not...

I don't have any objection with your patch. It was just my opinion. 
But it needs to choose one of them. Yours and Baruch's patch are same. 

If you want to add Fixes tags, i think that it has to add in Baruch's patch.
Because his patch was firstly posted than yours. 

Best Regards,
Jaehoon Chung

> 
> Marek
> 



Re: [PATCH 2/3] mmc: meson_gx_mmc: use mmc_pwrseq instead of meson_mmc_pwrseq

2021-02-04 Thread Jaehoon Chung
Hi Neil,

On 2/4/21 11:05 PM, Neil Armstrong wrote:
> On 01/02/2021 10:28, Jaehoon Chung wrote:
>> Use mmc_pwrseq instead of meson_mmc_pwrseq.
>>
>> Signed-off-by: Jaehoon Chung 
>> ---
>>  drivers/mmc/meson_gx_mmc.c | 41 +++---
>>  1 file changed, 3 insertions(+), 38 deletions(-)
>>
>> diff --git a/drivers/mmc/meson_gx_mmc.c b/drivers/mmc/meson_gx_mmc.c
>> index 8b6dfa3b9603..0ef140562cd2 100644
>> --- a/drivers/mmc/meson_gx_mmc.c
>> +++ b/drivers/mmc/meson_gx_mmc.c
>> @@ -292,12 +292,11 @@ static int meson_mmc_probe(struct udevice *dev)
>>  
>>  mmc_set_clock(mmc, cfg->f_min, MMC_CLK_ENABLE);
>>  
>> -#ifdef CONFIG_PWRSEQ
>> +#ifdef CONFIG_MMC_PWRSEQ
>>  /* Enable power if needed */
>> -ret = uclass_get_device_by_phandle(UCLASS_PWRSEQ, dev, "mmc-pwrseq",
>> -   _dev);
>> +ret = mmc_pwrseq_get_power(dev, cfg);
>>  if (!ret) {
>> -ret = pwrseq_set_power(pwr_dev, true);
>> +ret = pwrseq_set_power(cfg->pwr_dev, true);
>>  if (ret)
>>  return ret;
>>  }
>> @@ -342,37 +341,3 @@ U_BOOT_DRIVER(meson_mmc) = {
>>  .of_to_plat = meson_mmc_of_to_plat,
>>  .plat_auto  = sizeof(struct meson_mmc_plat),
>>  };
>> -
>> -#ifdef CONFIG_PWRSEQ
>> -static int meson_mmc_pwrseq_set_power(struct udevice *dev, bool enable)
>> -{
>> -struct gpio_desc reset;
>> -int ret;
>> -
>> -ret = gpio_request_by_name(dev, "reset-gpios", 0, , GPIOD_IS_OUT);
>> -if (ret)
>> -return ret;
>> -dm_gpio_set_value(, 1);
>> -udelay(1);
>> -dm_gpio_set_value(, 0);
>> -udelay(200);
>> -
>> -return 0;
>> -}
>> -
>> -static const struct pwrseq_ops meson_mmc_pwrseq_ops = {
>> -.set_power  = meson_mmc_pwrseq_set_power,
>> -};
>> -
>> -static const struct udevice_id meson_mmc_pwrseq_ids[] = {
>> -{ .compatible = "mmc-pwrseq-emmc" },
>> -{ }
>> -};
>> -
>> -U_BOOT_DRIVER(meson_mmc_pwrseq_drv) = {
>> -.name   = "mmc_pwrseq_emmc",
>> -.id = UCLASS_PWRSEQ,
>> -.of_match   = meson_mmc_pwrseq_ids,
>> -.ops= _mmc_pwrseq_ops,
>> -};
>> -#endif
>>
> 
> Acked-by: Neil Armstrong 
> 
> You should probably also update the amlogic defconfigs in this patchset, no ?

Amlogic defconfigs are already enabled CONFIG_PWRSEQ.
CONFIG_MMC_PWRSEQ is depends on CONFIG_PWRSEQ and it will be enabled by default.
So it didn't need to update any defconfig..

But Now after listened your mention, my thinking is changed.
Because some boards can be used only CONFIG_PWRSEQ without CONFIG_MMC_PWRSEQ.

Thanks for pointing out. I will update amlogic defconfigs.

If i misunderstood something, let me know, plz.

Best Regards,
Jaehoon Chung

> 
> Neil
> 



Re: [PATCH v2] ARM: mx6: Add function to set serial#

2021-02-04 Thread Sean Anderson




On 2/4/21 5:03 PM, Heinrich Schuchardt wrote:
> On 2/4/21 10:58 PM, Tom Rini wrote:
>> On Thu, Feb 04, 2021 at 04:44:22PM -0500, Sean Anderson wrote:
>>
>>> The serial number OTP is similar to the imx7 version, except that the
>>> register names are different. This also sets serial# directly,
>>> instead of
>>> providing board_get_serial.
>>>
>>> Signed-off-by: Sean Anderson 
>>
>> Reviewed-by: Tom Rini 
>>
>
> The current patch is without effect.
>
> We need to enable CONFIG_ARCH_MISC_INIT on i.MX6 by default, e.g.
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 95557d6ed6..ba189c404d 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -901,6 +901,7 @@ config ARCH_MX6
>  select SYS_FSL_HAS_SEC
>  select SYS_FSL_SEC_COMPAT_4
>  select SYS_FSL_SEC_LE
> +   select ARCH_MISC_INIT
>  imply MXC_GPIO
>  imply SYS_THUMB_BUILD
>
> Best regards
>
> Heinrich

Do any boards on i.MX6 currently set serial# themselves? arch_misc_init
is called before board_late_init, which is (AFACT) typically where
boards set serial#. Any boards which conditionally set serial# (e.g.
from an eeprom) will not set things up properly. I looked over things
quickly, and I didn't see anything. So it may be fine to enable this.

Though by this logic, shouldn't you have implied ARCH_MISC_INIT back in
90865614b4 ("ARM: mx6: make CAAM usable on the i.MX6 boards")?

--Sean


Re: [PATCH] board: amlogic: odroid: add runtime detection of the N2/N2+/C4/HC4 variants

2021-02-04 Thread Jaehoon Chung
On 2/4/21 11:03 PM, Neil Armstrong wrote:
> Hi,
> 
> On 04/02/2021 10:11, Marek Szyprowski wrote:
>> Use the ADC channel 1 to check the hardware revision of the board and
>> detect the N2 vs. N2+ and the C4 vs. HC4 variants. Each of them use
>> different dtb file, so adjust fdtfile environment variable to the
>> detected variant.
>>
>> The ADC min/max values for each variant are taken from the vendor code,
>> adjusted to the 12-bit ADC driver operation mode (vendor code use 10-bit
>> mode).
>>
>> Signed-off-by: Marek Szyprowski 
>> ---
>> The relevant vendor's code is here:
>> https://protect2.fireeye.com/v1/url?k=482d7422-17b64cfb-482cff6d-0cc47a3356b2-d15937f4c8fdfe96=1=3e3b54dc-363e-452d-840c-1c29fdfd5c70=https%3A%2F%2Fgithub.com%2Fhardkernel%2Fu-boot%2Fblob%2Fodroidg12-v2015.01%2Fboard%2Fhardkernel%2Fodroid-common%2Fboard.c%23L55
>> ---
>>  arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi |  6 ++
>>  arch/arm/dts/meson-sm1-odroid-c4-u-boot.dtsi  |  6 ++
>>  board/amlogic/odroid-n2/odroid-n2.c   | 80 +++
>>  configs/odroid-c4_defconfig   |  4 +-
>>  configs/odroid-n2_defconfig   |  4 +-
>>  5 files changed, 98 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi 
>> b/arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi
>> index 236f2468dc..a92f9e9ff1 100644
>> --- a/arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi
>> +++ b/arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi
>> @@ -5,3 +5,9 @@
>>   */
>>  
>>  #include "meson-g12-common-u-boot.dtsi"
>> +
>> +/* SARADC is needed for proper board variant detection */
>> + {
>> +status = "okay";
>> +vref-supply = <_1v8>;
>> +};
>> diff --git a/arch/arm/dts/meson-sm1-odroid-c4-u-boot.dtsi 
>> b/arch/arm/dts/meson-sm1-odroid-c4-u-boot.dtsi
>> index fbcc8287c5..963bf96b25 100644
>> --- a/arch/arm/dts/meson-sm1-odroid-c4-u-boot.dtsi
>> +++ b/arch/arm/dts/meson-sm1-odroid-c4-u-boot.dtsi
>> @@ -12,6 +12,12 @@
>>  snps,reset-active-low;
>>  };
>>  
>> +/* SARADC is needed for proper board variant detection */
>> + {
>> +status = "okay";
>> +vref-supply = <_1v8>;
>> +};
>> +
>>  _vdd {
>>  gpio = <_ao GPIOAO_3 GPIO_OPEN_DRAIN>;
>>  };
>> diff --git a/board/amlogic/odroid-n2/odroid-n2.c 
>> b/board/amlogic/odroid-n2/odroid-n2.c
>> index d9955433bf..2eb7fa93be 100644
>> --- a/board/amlogic/odroid-n2/odroid-n2.c
>> +++ b/board/amlogic/odroid-n2/odroid-n2.c
>> @@ -6,6 +6,7 @@
>>  
>>  #include 
>>  #include 
>> +#include 
>>  #include 
>>  #include 
>>  #include 
>> @@ -19,6 +20,11 @@
>>  #define EFUSE_MAC_SIZE  12
>>  #define MAC_ADDR_LEN6
>>  
>> +#define ODROID_HW_VS_ADC_CHANNEL1
>> +
>> +#define MESON_SOC_ID_G12B   0x29
>> +#define MESON_SOC_ID_SM10x2b
>> +
>>  int mmc_get_env_dev(void)
>>  {
>>  if (meson_get_boot_device() == BOOT_DEVICE_EMMC)
>> @@ -26,6 +32,79 @@ int mmc_get_env_dev(void)
>>  return 0;
>>  }
>>  
>> +/* Variant detection is based on the ADC RAW values for the channel #1 */
>> +static struct meson_odroid_boards {
>> +unsigned int soc_id;
>> +unsigned int adc_min;
>> +unsigned int adc_max;
>> +char *variant;
>> +} boards[] = {
>> +/* OdroidN2 rev 2018,7,23 */
>> +{ MESON_SOC_ID_G12B, 80 * 4,  90 * 4, "n2" },
>> +/* OdroidN2 rev 2018,12,6 */
>> +{ MESON_SOC_ID_G12B, 160 * 4, 170 * 4, "n2" },
>> +/* OdroidN2 rev 2019,1,17 */
>> +{ MESON_SOC_ID_G12B, 245 * 4, 255 * 4, "n2" },
>> +/* OdroidN2 rev 2019,2,7 */
>> +{ MESON_SOC_ID_G12B, 330 * 4, 350 * 4, "n2" },
>> +/* OdroidN2plus rev 2019,11,20 */
>> +{ MESON_SOC_ID_G12B, 410 * 4, 430 * 4, "n2_plus" },
>> +/* OdroidC4 rev 2020,01,29 */
>> +{ MESON_SOC_ID_SM1,   80 * 4, 100 * 4, "c4" },
>> +/* OdroidHC4 rev 2019,12,10 */
>> +{ MESON_SOC_ID_SM1,  300 * 4, 320 * 4, "hc4" },
>> +/* OdroidC4 rev 2019,11,29 */
>> +{ MESON_SOC_ID_SM1,  335 * 4, 345 * 4, "c4" },
>> +/* OdroidHC4 rev 2020,8,7 */
>> +{ MESON_SOC_ID_SM1,  590 * 4, 610 * 4, "hc4" },
>> +};
>> +
>> +static void odroid_set_fdtfile(char *soc, char *variant)
>> +{
>> +char s[128];
>> +
>> +snprintf(s, sizeof(s), "amlogic/meson-%s-odroid-%s.dtb", soc, variant);
>> +env_set("fdtfile", s);
>> +}
>> +
>> +static int odroid_detect_variant(void)
>> +{
>> +char *variant = "", *soc = "";
>> +unsigned int adcval = 0;
>> +int ret, i, soc_id = 0;
>> +
>> +if (of_machine_is_compatible("amlogic,sm1")) {
>> +soc_id = MESON_SOC_ID_SM1;
>> +soc = "sm1";
>> +} else if (of_machine_is_compatible("amlogic,g12b")) {
>> +soc_id = MESON_SOC_ID_G12B;
>> +soc = "g12b";
>> +} else {
>> +return -1;
>> +}
>> +
>> +ret = adc_channel_single_shot("adc@9000", ODROID_HW_VS_ADC_CHANNEL,
>> +  );
>> +if (ret)
>> +return ret;
>> +
>> +for (i = 0 ; i < ARRAY_SIZE(boards) ; ++i) {
>> +if 

Re: [PATCH v2] ARM: mx6: Add function to set serial#

2021-02-04 Thread Heinrich Schuchardt

On 2/4/21 10:58 PM, Tom Rini wrote:

On Thu, Feb 04, 2021 at 04:44:22PM -0500, Sean Anderson wrote:


The serial number OTP is similar to the imx7 version, except that the
register names are different. This also sets serial# directly, instead of
providing board_get_serial.

Signed-off-by: Sean Anderson 


Reviewed-by: Tom Rini 



The current patch is without effect.

We need to enable CONFIG_ARCH_MISC_INIT on i.MX6 by default, e.g.

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 95557d6ed6..ba189c404d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -901,6 +901,7 @@ config ARCH_MX6
select SYS_FSL_HAS_SEC
select SYS_FSL_SEC_COMPAT_4
select SYS_FSL_SEC_LE
+   select ARCH_MISC_INIT
imply MXC_GPIO
imply SYS_THUMB_BUILD

Best regards

Heinrich


Re: [PATCH v2] ARM: mx6: Add function to set serial#

2021-02-04 Thread Tom Rini
On Thu, Feb 04, 2021 at 04:44:22PM -0500, Sean Anderson wrote:

> The serial number OTP is similar to the imx7 version, except that the
> register names are different. This also sets serial# directly, instead of
> providing board_get_serial.
> 
> Signed-off-by: Sean Anderson 

Reviewed-by: Tom Rini 

-- 
Tom


signature.asc
Description: PGP signature


Re: Please pull u-boot-dm

2021-02-04 Thread Tom Rini
On Wed, Feb 03, 2021 at 09:30:59PM -0700, Simon Glass wrote:

> Hi Tom,
> 
> 
> https://gitlab.denx.de/u-boot/custodians/u-boot-dm/-/pipelines/6206
> 
> The following changes since commit fdcb93e1709ab1a2ebb562455621617c29e2099c:
> 
>   Merge branch '2021-02-01-assorted-fixes' (2021-02-02 09:24:10 -0500)
> 
> are available in the Git repository at:
> 
>   git://git.denx.de/u-boot-dm.git tags/dm-pull-3feb21
> 
> for you to fetch changes up to 6f5edbaf938952e4a9860727c633dcaa36caf699:
> 
>   firmware: smci: possible NULL dereference (2021-02-03 03:38:41 -0700)
> 

Applied to u-boot/master, thanks!

-- 
Tom


signature.asc
Description: PGP signature


Re: Please pull u-boot-x86

2021-02-04 Thread Tom Rini
On Thu, Feb 04, 2021 at 08:08:51AM +0800, Bin Meng wrote:

> Hi Tom,
> 
> This PR includes the following x86 changes for v2021.04:
> 
> - Fix broken multi-core boot for QEMU x86
> - Add zboot support to boot x86 Linux kernel image in the PXE sysboot utility
> 
> Azure results: PASS
> https://dev.azure.com/bmeng/GitHub/_build/results?buildId=320=results
> 
> The following changes since commit fdcb93e1709ab1a2ebb562455621617c29e2099c:
> 
>   Merge branch '2021-02-01-assorted-fixes' (2021-02-02 09:24:10 -0500)
> 
> are available in the git repository at:
> 
>   https://gitlab.denx.de/u-boot/custodians/u-boot-x86
> 
> for you to fetch changes up to 18c25821836b4673aa67a43c792a4a82480f47fa:
> 
>   cmd: pxe_utils: sysboot: Add zboot support to boot x86 Linux kernel
> image (2021-02-03 23:16:44 +0800)
> 

Applied to u-boot/master, thanks!

-- 
Tom


signature.asc
Description: PGP signature


  1   2   3   >