* [PATCH 0/3] Add SDHCI support for Canaan K230 SoC
@ 2026-02-04 8:29 Jiayu Du
2026-02-04 8:29 ` [PATCH 1/3] dt-bindings: mmc: Add sdhci support for Canaan k230 Jiayu Du
` (2 more replies)
0 siblings, 3 replies; 13+ messages in thread
From: Jiayu Du @ 2026-02-04 8:29 UTC (permalink / raw)
To: ulf.hansson, adrian.hunter, robh, krzk+dt, conor+dt
Cc: pjw, palmer, aou, linux-mmc, devicetree, linux-riscv,
linux-kernel, gaohan, me, Jiayu Du
This series is based on the k230 usbphy series[1].
This patch series adds SDHCI support for the Canaan K230 SoC,
which uses Synopsys DWCMSHC SDHCI controllers, include MMC0 and MMC1.
The MMC0 supports eMMC, while MMC1 supports SDIO. Detailed information
can be found in the vendor's manual[2].
Link: https://lore.kernel.org/all/20260121145526.14672-1-jiayu.riscv@isrc.iscas.ac.cn/ [1]
Link: https://www.kendryte.com/k230/zh/dev/00_hardware/K230_%E7%A1%AC%E4%BB%B6%E8%AE%BE%E8%AE%A1%E6%8C%87%E5%8D%97.html#mmc [2]
Jiayu Du (3):
dt-bindings: mmc: Add sdhci support for Canaan k230
mmc: sdhci-dwcmshc: Add Canaan K230 DWCMSHC controller support
riscv: dts: canaan: Add mmc nodes for K230
.../bindings/mmc/snps,dwcmshc-sdhci.yaml | 22 ++
.../boot/dts/canaan/k230-canmv-dshanpi.dts | 17 ++
.../dts/canaan/k230-canmv-module-dshanpi.dtsi | 7 +
arch/riscv/boot/dts/canaan/k230.dtsi | 26 ++
drivers/mmc/host/sdhci-of-dwcmshc.c | 247 ++++++++++++++++++
5 files changed, 319 insertions(+)
--
2.52.0
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH 1/3] dt-bindings: mmc: Add sdhci support for Canaan k230 2026-02-04 8:29 [PATCH 0/3] Add SDHCI support for Canaan K230 SoC Jiayu Du @ 2026-02-04 8:29 ` Jiayu Du 2026-02-04 18:10 ` Conor Dooley 2026-02-04 8:29 ` [PATCH 2/3] mmc: sdhci-dwcmshc: Add Canaan K230 DWCMSHC controller support Jiayu Du 2026-02-04 8:29 ` [PATCH 3/3] riscv: dts: canaan: Add mmc nodes for K230 Jiayu Du 2 siblings, 1 reply; 13+ messages in thread From: Jiayu Du @ 2026-02-04 8:29 UTC (permalink / raw) To: ulf.hansson, adrian.hunter, robh, krzk+dt, conor+dt Cc: pjw, palmer, aou, linux-mmc, devicetree, linux-riscv, linux-kernel, gaohan, me, Jiayu Du The Canaan k230 uses the SDHCI from Synopsys. Add compatible strings to the k230. The k230 has two controllers. MMC0 supports eMMC, while MMC1 supports SDIO. Signed-off-by: Jiayu Du <jiayu.riscv@isrc.iscas.ac.cn> --- .../bindings/mmc/snps,dwcmshc-sdhci.yaml | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml index 7e7c55dc2440..cab33da3af7d 100644 --- a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml +++ b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml @@ -23,6 +23,8 @@ properties: - const: sophgo,sg2044-dwcmshc - const: sophgo,sg2042-dwcmshc - enum: + - canaan,k230-emmc + - canaan,k230-sdio - rockchip,rk3568-dwcmshc - rockchip,rk3588-dwcmshc - snps,dwcmshc-sdhci @@ -87,6 +89,26 @@ required: allOf: - $ref: mmc-controller.yaml# + - if: + properties: + compatible: + contains: + enum: + - canaan,k230-emmc + - canaan,k230-sdio + then: + properties: + clocks: + minItems: 2 + maxItems: 5 + clock-names: + items: + - const: core + - const: bus + - const: axi + - const: block + - const: timer + - if: properties: compatible: -- 2.52.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 1/3] dt-bindings: mmc: Add sdhci support for Canaan k230 2026-02-04 8:29 ` [PATCH 1/3] dt-bindings: mmc: Add sdhci support for Canaan k230 Jiayu Du @ 2026-02-04 18:10 ` Conor Dooley 2026-02-05 7:13 ` Jiayu Du 0 siblings, 1 reply; 13+ messages in thread From: Conor Dooley @ 2026-02-04 18:10 UTC (permalink / raw) To: Jiayu Du Cc: ulf.hansson, adrian.hunter, robh, krzk+dt, conor+dt, pjw, palmer, aou, linux-mmc, devicetree, linux-riscv, linux-kernel, gaohan, me [-- Attachment #1: Type: text/plain, Size: 2074 bytes --] On Wed, Feb 04, 2026 at 04:29:06PM +0800, Jiayu Du wrote: > The Canaan k230 uses the SDHCI from Synopsys. Add compatible strings > to the k230. The k230 has two controllers. MMC0 supports eMMC, while > MMC1 supports SDIO. > > Signed-off-by: Jiayu Du <jiayu.riscv@isrc.iscas.ac.cn> > --- > .../bindings/mmc/snps,dwcmshc-sdhci.yaml | 22 +++++++++++++++++++ > 1 file changed, 22 insertions(+) > > diff --git a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml > index 7e7c55dc2440..cab33da3af7d 100644 > --- a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml > +++ b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml > @@ -23,6 +23,8 @@ properties: > - const: sophgo,sg2044-dwcmshc > - const: sophgo,sg2042-dwcmshc > - enum: > + - canaan,k230-emmc > + - canaan,k230-sdio I don't understand why there are two compatibles here, when the driver is able to handle them both identically, using the common properties for mmc controllers to differentiate. Is which is emmc and which sdio actually just determined by how the k230 boards use them? Or, if there are pinout differences, would pinctrl allow each to be used for either? > - rockchip,rk3568-dwcmshc > - rockchip,rk3588-dwcmshc > - snps,dwcmshc-sdhci > @@ -87,6 +89,26 @@ required: > allOf: > - $ref: mmc-controller.yaml# > > + - if: > + properties: > + compatible: > + contains: > + enum: > + - canaan,k230-emmc > + - canaan,k230-sdio > + then: > + properties: > + clocks: > + minItems: 2 > + maxItems: 5 > + clock-names: > + items: > + - const: core > + - const: bus > + - const: axi > + - const: block > + - const: timer > + > - if: > properties: > compatible: > -- > 2.52.0 > [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/3] dt-bindings: mmc: Add sdhci support for Canaan k230 2026-02-04 18:10 ` Conor Dooley @ 2026-02-05 7:13 ` Jiayu Du 2026-02-05 19:19 ` Conor Dooley 0 siblings, 1 reply; 13+ messages in thread From: Jiayu Du @ 2026-02-05 7:13 UTC (permalink / raw) To: Conor Dooley Cc: ulf.hansson, adrian.hunter, robh, krzk+dt, conor+dt, pjw, palmer, aou, linux-mmc, devicetree, linux-riscv, linux-kernel, gaohan, me On Wed, Feb 04, 2026 at 06:10:25PM +0000, Conor Dooley wrote: > On Wed, Feb 04, 2026 at 04:29:06PM +0800, Jiayu Du wrote: > > The Canaan k230 uses the SDHCI from Synopsys. Add compatible strings > > to the k230. The k230 has two controllers. MMC0 supports eMMC, while > > MMC1 supports SDIO. > > > > Signed-off-by: Jiayu Du <jiayu.riscv@isrc.iscas.ac.cn> > > --- > > .../bindings/mmc/snps,dwcmshc-sdhci.yaml | 22 +++++++++++++++++++ > > 1 file changed, 22 insertions(+) > > > > diff --git a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml > > index 7e7c55dc2440..cab33da3af7d 100644 > > --- a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml > > +++ b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml > > @@ -23,6 +23,8 @@ properties: > > - const: sophgo,sg2044-dwcmshc > > - const: sophgo,sg2042-dwcmshc > > - enum: > > + - canaan,k230-emmc > > + - canaan,k230-sdio > > I don't understand why there are two compatibles here, when the driver > is able to handle them both identically, using the common properties for > mmc controllers to differentiate. Is which is emmc and which sdio > actually just determined by how the k230 boards use them? > > Or, if there are pinout differences, would pinctrl allow each to be used > for either? Hi, Thanks for the review! Actually, the two compatibles aren't just board choices. They come from real SoC-level differences between the two MMC controllers. From the K230 Hardware Guide [1]: - MMC0 supports eMMC5.0 and SDIO3.0, usually for eMMC chips. - MMC1 only does SDIO3.0 in 4/1-bit mode up to SDR104, and the manual clearly says it can't handle eMMC because of pin count and limits. And the driver treats them a bit differently, such as whether there is a phy and the initialization method. So I think keeping separate compatibles makes sense to show these hardware differences clearly. About pinctrl, MMC1 pins can mux to other things like GPIO, but MMC0 pins are fixed in hardware. In next version, I will add pinctrl node for MMC1 in the board dts. Link: https://github.com/kendryte/k230_docs/blob/main/en/00_hardware/K230_Hardware_Design_Guide.md#mmc-circuit [1] Regards, Jiayu Du > > > - rockchip,rk3568-dwcmshc > > - rockchip,rk3588-dwcmshc > > - snps,dwcmshc-sdhci > > @@ -87,6 +89,26 @@ required: > > allOf: > > - $ref: mmc-controller.yaml# > > > > + - if: > > + properties: > > + compatible: > > + contains: > > + enum: > > + - canaan,k230-emmc > > + - canaan,k230-sdio > > + then: > > + properties: > > + clocks: > > + minItems: 2 > > + maxItems: 5 > > + clock-names: > > + items: > > + - const: core > > + - const: bus > > + - const: axi > > + - const: block > > + - const: timer > > + > > - if: > > properties: > > compatible: > > -- > > 2.52.0 > > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/3] dt-bindings: mmc: Add sdhci support for Canaan k230 2026-02-05 7:13 ` Jiayu Du @ 2026-02-05 19:19 ` Conor Dooley 2026-02-06 2:56 ` Jiayu Du 0 siblings, 1 reply; 13+ messages in thread From: Conor Dooley @ 2026-02-05 19:19 UTC (permalink / raw) To: Jiayu Du Cc: ulf.hansson, adrian.hunter, robh, krzk+dt, conor+dt, pjw, palmer, aou, linux-mmc, devicetree, linux-riscv, linux-kernel, gaohan, me [-- Attachment #1: Type: text/plain, Size: 3717 bytes --] On Thu, Feb 05, 2026 at 03:13:00PM +0800, Jiayu Du wrote: > On Wed, Feb 04, 2026 at 06:10:25PM +0000, Conor Dooley wrote: > > On Wed, Feb 04, 2026 at 04:29:06PM +0800, Jiayu Du wrote: > > > The Canaan k230 uses the SDHCI from Synopsys. Add compatible strings > > > to the k230. The k230 has two controllers. MMC0 supports eMMC, while > > > MMC1 supports SDIO. > > > > > > Signed-off-by: Jiayu Du <jiayu.riscv@isrc.iscas.ac.cn> > > > --- > > > .../bindings/mmc/snps,dwcmshc-sdhci.yaml | 22 +++++++++++++++++++ > > > 1 file changed, 22 insertions(+) > > > > > > diff --git a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml > > > index 7e7c55dc2440..cab33da3af7d 100644 > > > --- a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml > > > +++ b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml > > > @@ -23,6 +23,8 @@ properties: > > > - const: sophgo,sg2044-dwcmshc > > > - const: sophgo,sg2042-dwcmshc > > > - enum: > > > + - canaan,k230-emmc > > > + - canaan,k230-sdio > > > > I don't understand why there are two compatibles here, when the driver > > is able to handle them both identically, using the common properties for > > mmc controllers to differentiate. Is which is emmc and which sdio > > actually just determined by how the k230 boards use them? > > > > Or, if there are pinout differences, would pinctrl allow each to be used > > for either? > > Hi, Thanks for the review! > > Actually, the two compatibles aren't just board choices. They come from > real SoC-level differences between the two MMC controllers. > > From the K230 Hardware Guide [1]: > - MMC0 supports eMMC5.0 and SDIO3.0, usually for eMMC chips. > - MMC1 only does SDIO3.0 in 4/1-bit mode up to SDR104, and the manual > clearly says it can't handle eMMC because of pin count and limits. > > And the driver treats them a bit differently, such as whether there > is a phy and the initialization method. So I think keeping separate > compatibles makes sense to show these hardware differences clearly. Ah, I didn't notice that there was some logic, I just checked the match data and I missed that. What you have is fine then I think. > > About pinctrl, MMC1 pins can mux to other things like GPIO, but MMC0 > pins are fixed in hardware. In next version, I will add pinctrl node > for MMC1 in the board dts. > > Link: https://github.com/kendryte/k230_docs/blob/main/en/00_hardware/K230_Hardware_Design_Guide.md#mmc-circuit [1] > > > > > - rockchip,rk3568-dwcmshc > > > - rockchip,rk3588-dwcmshc > > > - snps,dwcmshc-sdhci > > > @@ -87,6 +89,26 @@ required: > > > allOf: > > > - $ref: mmc-controller.yaml# > > > > > > + - if: > > > + properties: > > > + compatible: > > > + contains: > > > + enum: > > > + - canaan,k230-emmc > > > + - canaan,k230-sdio > > > + then: > > > + properties: > > > + clocks: > > > + minItems: 2 > > > + maxItems: 5 Additionally, why does this have a range? Why is it not minItems: 5? You've got only one instance per compatible, so the number of clocks for each compatible is not variable. > > > + clock-names: > > > + items: > > > + - const: core > > > + - const: bus > > > + - const: axi > > > + - const: block > > > + - const: timer > > > + > > > - if: > > > properties: > > > compatible: > > > -- > > > 2.52.0 > > > > > [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/3] dt-bindings: mmc: Add sdhci support for Canaan k230 2026-02-05 19:19 ` Conor Dooley @ 2026-02-06 2:56 ` Jiayu Du 0 siblings, 0 replies; 13+ messages in thread From: Jiayu Du @ 2026-02-06 2:56 UTC (permalink / raw) To: Conor Dooley Cc: ulf.hansson, adrian.hunter, robh, krzk+dt, conor+dt, pjw, palmer, aou, linux-mmc, devicetree, linux-riscv, linux-kernel, gaohan, me On Thu, Feb 05, 2026 at 07:19:36PM +0000, Conor Dooley wrote: > On Thu, Feb 05, 2026 at 03:13:00PM +0800, Jiayu Du wrote: > > On Wed, Feb 04, 2026 at 06:10:25PM +0000, Conor Dooley wrote: > > > On Wed, Feb 04, 2026 at 04:29:06PM +0800, Jiayu Du wrote: > > > > The Canaan k230 uses the SDHCI from Synopsys. Add compatible strings > > > > to the k230. The k230 has two controllers. MMC0 supports eMMC, while > > > > MMC1 supports SDIO. > > > > > > > > Signed-off-by: Jiayu Du <jiayu.riscv@isrc.iscas.ac.cn> > > > > --- > > > > .../bindings/mmc/snps,dwcmshc-sdhci.yaml | 22 +++++++++++++++++++ > > > > 1 file changed, 22 insertions(+) > > > > > > > > diff --git a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml > > > > index 7e7c55dc2440..cab33da3af7d 100644 > > > > --- a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml > > > > +++ b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml > > > > @@ -23,6 +23,8 @@ properties: > > > > - const: sophgo,sg2044-dwcmshc > > > > - const: sophgo,sg2042-dwcmshc > > > > - enum: > > > > + - canaan,k230-emmc > > > > + - canaan,k230-sdio > > > > > > I don't understand why there are two compatibles here, when the driver > > > is able to handle them both identically, using the common properties for > > > mmc controllers to differentiate. Is which is emmc and which sdio > > > actually just determined by how the k230 boards use them? > > > > > > Or, if there are pinout differences, would pinctrl allow each to be used > > > for either? > > > > Hi, Thanks for the review! > > > > Actually, the two compatibles aren't just board choices. They come from > > real SoC-level differences between the two MMC controllers. > > > > From the K230 Hardware Guide [1]: > > - MMC0 supports eMMC5.0 and SDIO3.0, usually for eMMC chips. > > - MMC1 only does SDIO3.0 in 4/1-bit mode up to SDR104, and the manual > > clearly says it can't handle eMMC because of pin count and limits. > > > > And the driver treats them a bit differently, such as whether there > > is a phy and the initialization method. So I think keeping separate > > compatibles makes sense to show these hardware differences clearly. > > Ah, I didn't notice that there was some logic, I just checked the match > data and I missed that. What you have is fine then I think. > > > > > About pinctrl, MMC1 pins can mux to other things like GPIO, but MMC0 > > pins are fixed in hardware. In next version, I will add pinctrl node > > for MMC1 in the board dts. > > > > Link: https://github.com/kendryte/k230_docs/blob/main/en/00_hardware/K230_Hardware_Design_Guide.md#mmc-circuit [1] > > > > > > > - rockchip,rk3568-dwcmshc > > > > - rockchip,rk3588-dwcmshc > > > > - snps,dwcmshc-sdhci > > > > @@ -87,6 +89,26 @@ required: > > > > allOf: > > > > - $ref: mmc-controller.yaml# > > > > > > > > + - if: > > > > + properties: > > > > + compatible: > > > > + contains: > > > > + enum: > > > > + - canaan,k230-emmc > > > > + - canaan,k230-sdio > > > > + then: > > > > + properties: > > > > + clocks: > > > > + minItems: 2 > > > > + maxItems: 5 > > Additionally, why does this have a range? Why is it not minItems: 5? > You've got only one instance per compatible, so the number of clocks for > each compatible is not variable. You're right. In the next version, I will change it to minItems: 5. Thank you for your review! Regards, Jiayu Du > > > > + clock-names: > > > > + items: > > > > + - const: core > > > > + - const: bus > > > > + - const: axi > > > > + - const: block > > > > + - const: timer > > > > + > > > > - if: > > > > properties: > > > > compatible: > > > > -- > > > > 2.52.0 > > > > ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 2/3] mmc: sdhci-dwcmshc: Add Canaan K230 DWCMSHC controller support 2026-02-04 8:29 [PATCH 0/3] Add SDHCI support for Canaan K230 SoC Jiayu Du 2026-02-04 8:29 ` [PATCH 1/3] dt-bindings: mmc: Add sdhci support for Canaan k230 Jiayu Du @ 2026-02-04 8:29 ` Jiayu Du 2026-02-04 9:43 ` Yao Zi 2026-02-06 13:26 ` Krzysztof Kozlowski 2026-02-04 8:29 ` [PATCH 3/3] riscv: dts: canaan: Add mmc nodes for K230 Jiayu Du 2 siblings, 2 replies; 13+ messages in thread From: Jiayu Du @ 2026-02-04 8:29 UTC (permalink / raw) To: ulf.hansson, adrian.hunter, robh, krzk+dt, conor+dt Cc: pjw, palmer, aou, linux-mmc, devicetree, linux-riscv, linux-kernel, gaohan, me, Jiayu Du Add SDHCI controller driver for Canaan k230 SoC. Implement custom sdhci_ops for set_clock, phy init, init and reset. Signed-off-by: Jiayu Du <jiayu.riscv@isrc.iscas.ac.cn> --- drivers/mmc/host/sdhci-of-dwcmshc.c | 247 ++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index 204830b40587..bc427bfbba25 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -128,9 +128,11 @@ #define PHY_CNFG_PHY_PWRGOOD_MASK BIT_MASK(1) /* bit [1] */ #define PHY_CNFG_PAD_SP_MASK GENMASK(19, 16) /* bits [19:16] */ #define PHY_CNFG_PAD_SP 0x0c /* PMOS TX drive strength */ +#define PHY_CNFG_PAD_SP_k230 0x09 /* PMOS TX drive strength for k230 */ #define PHY_CNFG_PAD_SP_SG2042 0x09 /* PMOS TX drive strength for SG2042 */ #define PHY_CNFG_PAD_SN_MASK GENMASK(23, 20) /* bits [23:20] */ #define PHY_CNFG_PAD_SN 0x0c /* NMOS TX drive strength */ +#define PHY_CNFG_PAD_SN_k230 0x08 /* NMOS TX drive strength for k230 */ #define PHY_CNFG_PAD_SN_SG2042 0x08 /* NMOS TX drive strength for SG2042 */ /* PHY command/response pad settings */ @@ -153,14 +155,22 @@ #define PHY_PAD_RXSEL_3V3 0x2 /* Receiver type select for 3.3V */ #define PHY_PAD_WEAKPULL_MASK GENMASK(4, 3) /* bits [4:3] */ +#define PHY_PAD_WEAKPULL_DISABLED 0x0 /* Weak pull up and pull down disabled */ #define PHY_PAD_WEAKPULL_PULLUP 0x1 /* Weak pull up enabled */ #define PHY_PAD_WEAKPULL_PULLDOWN 0x2 /* Weak pull down enabled */ #define PHY_PAD_TXSLEW_CTRL_P_MASK GENMASK(8, 5) /* bits [8:5] */ #define PHY_PAD_TXSLEW_CTRL_P 0x3 /* Slew control for P-Type pad TX */ +#define PHY_PAD_TXSLEW_CTRL_P_k230_VAL2 0x2 /* Slew control for P-Type pad TX for k230 */ #define PHY_PAD_TXSLEW_CTRL_N_MASK GENMASK(12, 9) /* bits [12:9] */ #define PHY_PAD_TXSLEW_CTRL_N 0x3 /* Slew control for N-Type pad TX */ #define PHY_PAD_TXSLEW_CTRL_N_SG2042 0x2 /* Slew control for N-Type pad TX for SG2042 */ +#define PHY_PAD_TXSLEW_CTRL_N_k230_VAL2 0x2 /* Slew control for N-Type pad TX for k230 */ +#define PHY_PAD_TXSLEW_CTRL_N_k230_VAL1 0x1 /* Slew control for N-Type pad TX for k230 */ + +/* PHY Common DelayLine config settings */ +#define PHY_COMMDL_CNFG (DWC_MSHC_PTR_PHY_R + 0x1c) +#define PHY_COMMDL_CNFG_DLSTEP_SEL BIT(0) /* DelayLine outputs on PAD enabled */ /* PHY CLK delay line settings */ #define PHY_SDCLKDL_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x1d) @@ -174,7 +184,10 @@ #define PHY_SDCLKDL_DC_HS400 0x18 /* delay code for HS400 mode */ #define PHY_SMPLDL_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x20) +#define PHY_SMPLDL_CNFG_EXTDLY_EN BIT(0) #define PHY_SMPLDL_CNFG_BYPASS_EN BIT(1) +#define PHY_SMPLDL_CNFG_INPSEL_MASK GENMASK(3, 2) /* bits [3:2] */ +#define PHY_SMPLDL_CNFG_INPSEL 0x3 /* delay line input source */ /* PHY drift_cclk_rx delay line configuration setting */ #define PHY_ATDL_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x21) @@ -227,6 +240,14 @@ /* SMC call for BlueField-3 eMMC RST_N */ #define BLUEFIELD_SMC_SET_EMMC_RST_N 0x82000007 +/* Canaan specific Registers */ +#define SD0_CTRL 0x00 +#define SD0_HOST_REG_VOL_STABLE BIT(4) +#define SD0_CARD_WRITE_PROT BIT(6) +#define SD1_CTRL 0x08 +#define SD1_HOST_REG_VOL_STABLE BIT(0) +#define SD1_CARD_WRITE_PROT BIT(2) + /* Eswin specific Registers */ #define EIC7700_CARD_CLK_STABLE BIT(28) #define EIC7700_INT_BCLK_STABLE BIT(16) @@ -268,6 +289,12 @@ struct eic7700_priv { unsigned int drive_impedance; }; +struct k230_priv { + /* Kendryte k230 specific */ + bool have_phy; + struct regmap *hi_sys_regmap; +}; + #define DWCMSHC_MAX_OTHER_CLKS 3 struct dwcmshc_priv { @@ -1650,6 +1677,201 @@ static int eic7700_init(struct device *dev, struct sdhci_host *host, struct dwcm return 0; } +static void dwcmshc_k230_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) +{ + u16 clk; + + sdhci_set_clock(host, clock); + + clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + clk |= SDHCI_PROG_CLOCK_MODE; + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); +} + +static void sdhci_k230_config_phy_delay(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct dwcmshc_priv *dwc_priv = sdhci_pltfm_priv(pltfm_host); + u32 val; + + sdhci_writeb(host, PHY_COMMDL_CNFG_DLSTEP_SEL, PHY_COMMDL_CNFG); + sdhci_writeb(host, 0x0, PHY_SDCLKDL_CNFG_R); + sdhci_writeb(host, PHY_SDCLKDL_DC_INITIAL, + PHY_SDCLKDL_DC_R); + + val = PHY_SMPLDL_CNFG_EXTDLY_EN; + val |= FIELD_PREP(PHY_SMPLDL_CNFG_INPSEL_MASK, + PHY_SMPLDL_CNFG_INPSEL); + sdhci_writeb(host, val, PHY_SMPLDL_CNFG_R); + + sdhci_writeb(host, FIELD_PREP(PHY_ATDL_CNFG_INPSEL_MASK, + PHY_ATDL_CNFG_INPSEL), PHY_ATDL_CNFG_R); + + val = sdhci_readl(host, dwc_priv->vendor_specific_area1 + + DWCMSHC_EMMC_ATCTRL); + val |= AT_CTRL_TUNE_CLK_STOP_EN; + val |= FIELD_PREP(AT_CTRL_PRE_CHANGE_DLY_MASK, + AT_CTRL_PRE_CHANGE_DLY); + val |= FIELD_PREP(AT_CTRL_POST_CHANGE_DLY_MASK, + AT_CTRL_POST_CHANGE_DLY); + sdhci_writel(host, val, dwc_priv->vendor_specific_area1 + + DWCMSHC_EMMC_ATCTRL); + sdhci_writel(host, 0x0, dwc_priv->vendor_specific_area1 + + DWCMSHC_AT_STAT); +} + +static int dwcmshc_k230_phy_init(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); + u32 rxsel = PHY_PAD_RXSEL_3V3; + unsigned int timeout = 15000; + u32 val; + u32 reg; + + /* reset phy */ + sdhci_writew(host, 0, PHY_CNFG_R); + + /* Disable the clock */ + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); + + if (priv->flags & FLAG_IO_FIXED_1V8) + rxsel = PHY_PAD_RXSEL_1V8; + + val = rxsel; + val |= FIELD_PREP(PHY_PAD_TXSLEW_CTRL_P_MASK, PHY_PAD_TXSLEW_CTRL_P_k230_VAL2); + val |= FIELD_PREP(PHY_PAD_TXSLEW_CTRL_N_MASK, PHY_PAD_TXSLEW_CTRL_N_k230_VAL2); + val |= FIELD_PREP(PHY_PAD_WEAKPULL_MASK, PHY_PAD_WEAKPULL_PULLUP); + + sdhci_writew(host, val, PHY_CMDPAD_CNFG_R); + sdhci_writew(host, val, PHY_DATAPAD_CNFG_R); + sdhci_writew(host, val, PHY_RSTNPAD_CNFG_R); + + val = rxsel; + val |= FIELD_PREP(PHY_PAD_TXSLEW_CTRL_P_MASK, PHY_PAD_TXSLEW_CTRL_P_k230_VAL2); + val |= FIELD_PREP(PHY_PAD_TXSLEW_CTRL_N_MASK, PHY_PAD_TXSLEW_CTRL_N_k230_VAL2); + sdhci_writew(host, val, PHY_CLKPAD_CNFG_R); + + val = rxsel; + val |= FIELD_PREP(PHY_PAD_WEAKPULL_MASK, PHY_PAD_WEAKPULL_PULLDOWN); + val |= FIELD_PREP(PHY_PAD_TXSLEW_CTRL_P_MASK, PHY_PAD_TXSLEW_CTRL_P_k230_VAL2); + val |= FIELD_PREP(PHY_PAD_TXSLEW_CTRL_N_MASK, PHY_PAD_TXSLEW_CTRL_N_k230_VAL2); + sdhci_writew(host, val, PHY_STBPAD_CNFG_R); + + sdhci_k230_config_phy_delay(host); + + /* Wait max 150 ms */ + while (1) { + reg = sdhci_readl(host, PHY_CNFG_R); + if (reg & FIELD_PREP(PHY_CNFG_PHY_PWRGOOD_MASK, 1)) + break; + if (!timeout) + return -ETIMEDOUT; + timeout--; + usleep_range(10, 15); + } + + reg = FIELD_PREP(PHY_CNFG_PAD_SN_MASK, PHY_CNFG_PAD_SN_k230) | + FIELD_PREP(PHY_CNFG_PAD_SP_MASK, PHY_CNFG_PAD_SP_k230); + sdhci_writel(host, reg, PHY_CNFG_R); + + /* de-assert the phy */ + reg |= PHY_CNFG_RSTN_DEASSERT; + sdhci_writel(host, reg, PHY_CNFG_R); + + return 0; +} + +static void dwcmshc_k230_sdhci_reset(struct sdhci_host *host, u8 mask) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct dwcmshc_priv *dwc_priv = sdhci_pltfm_priv(pltfm_host); + struct k230_priv *k230_priv = dwc_priv->priv; + u8 emmc_ctrl; + + dwcmshc_reset(host, mask); + + if (mask == SDHCI_RESET_ALL) { + emmc_ctrl = sdhci_readw(host, + dwc_priv->vendor_specific_area1 + + DWCMSHC_EMMC_CONTROL); + sdhci_writeb(host, emmc_ctrl, + dwc_priv->vendor_specific_area1 + + DWCMSHC_EMMC_CONTROL); + + if (k230_priv->have_phy) + dwcmshc_k230_phy_init(host); + else + sdhci_writel(host, 0x0, + dwc_priv->vendor_specific_area1 + + DWCMSHC_HOST_CTRL3); + } +} + +static int dwcmshc_k230_init(struct device *dev, struct sdhci_host *host, + struct dwcmshc_priv *dwc_priv) +{ + static const char * const clk_ids[] = {"base", "timer", "ahb"}; + struct device_node *usb_phy_node; + struct k230_priv *k230_priv; + u32 data; + int ret; + + k230_priv = devm_kzalloc(dev, sizeof(struct k230_priv), GFP_KERNEL); + if (!k230_priv) + return -ENOMEM; + dwc_priv->priv = k230_priv; + + usb_phy_node = of_find_compatible_node(NULL, NULL, "canaan,k230-usb-phy"); + if (!usb_phy_node) { + return dev_err_probe(dev, -ENODEV, + "Failed to find k230-usb-phy node\n"); + } + + k230_priv->hi_sys_regmap = device_node_to_regmap(usb_phy_node); + of_node_put(usb_phy_node); + if (IS_ERR(k230_priv->hi_sys_regmap)) { + return dev_err_probe(dev, PTR_ERR(k230_priv->hi_sys_regmap), + "Failed to get k230-usb-phy regmap\n"); + } + + ret = dwcmshc_get_enable_other_clks(mmc_dev(host->mmc), dwc_priv, + ARRAY_SIZE(clk_ids), clk_ids); + if (ret) { + return dev_err_probe(dev, ret, + "Failed to get/enable k230 mmc other clocks\n"); + } + + if (of_device_is_compatible(dev->of_node, "canaan,k230-sdio")) { + k230_priv->have_phy = false; + host->mmc->caps |= MMC_CAP_SD_HIGHSPEED; + host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; + ret = regmap_read(k230_priv->hi_sys_regmap, SD1_CTRL, &data); + if (ret) + return dev_err_probe(dev, ret, "Failed to read SD1_CTRL\n"); + + data |= SD1_CARD_WRITE_PROT | SD1_HOST_REG_VOL_STABLE; + ret = regmap_write(k230_priv->hi_sys_regmap, SD1_CTRL, data); + if (ret) + return dev_err_probe(dev, ret, "Failed to write SD1_CTRL\n"); + } else { + k230_priv->have_phy = true; + host->flags &= ~SDHCI_SIGNALING_330; + dwc_priv->flags |= FLAG_IO_FIXED_1V8; + ret = regmap_read(k230_priv->hi_sys_regmap, SD0_CTRL, &data); + if (ret) + return dev_err_probe(dev, ret, "Failed to read SD0_CTRL\n"); + + data |= SD0_CARD_WRITE_PROT | SD0_HOST_REG_VOL_STABLE; + ret = regmap_write(k230_priv->hi_sys_regmap, SD0_CTRL, data); + if (ret) + return dev_err_probe(dev, ret, "Failed to write SD0_CTRL\n"); + } + host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; + + return 0; +} + static const struct sdhci_ops sdhci_dwcmshc_ops = { .set_clock = sdhci_set_clock, .set_bus_width = sdhci_set_bus_width, @@ -1736,6 +1958,15 @@ static const struct sdhci_ops sdhci_dwcmshc_eic7700_ops = { .platform_execute_tuning = sdhci_eic7700_executing_tuning, }; +static const struct sdhci_ops sdhci_dwcmshc_k230_ops = { + .set_clock = dwcmshc_k230_sdhci_set_clock, + .set_bus_width = sdhci_set_bus_width, + .set_uhs_signaling = dwcmshc_set_uhs_signaling, + .get_max_clock = sdhci_pltfm_clk_get_max_clock, + .reset = dwcmshc_k230_sdhci_reset, + .adma_write_desc = dwcmshc_adma_write_desc, +}; + static const struct dwcmshc_pltfm_data sdhci_dwcmshc_pdata = { .pdata = { .ops = &sdhci_dwcmshc_ops, @@ -1827,6 +2058,14 @@ static const struct dwcmshc_pltfm_data sdhci_dwcmshc_eic7700_pdata = { .init = eic7700_init, }; +static const struct dwcmshc_pltfm_data sdhci_dwcmshc_k230_pdata = { + .pdata = { + .ops = &sdhci_dwcmshc_k230_ops, + .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, + }, + .init = dwcmshc_k230_init, +}; + static const struct cqhci_host_ops dwcmshc_cqhci_ops = { .enable = dwcmshc_sdhci_cqe_enable, .disable = sdhci_cqe_disable, @@ -1899,6 +2138,14 @@ static void dwcmshc_cqhci_init(struct sdhci_host *host, struct platform_device * } static const struct of_device_id sdhci_dwcmshc_dt_ids[] = { + { + .compatible = "canaan,k230-emmc", + .data = &sdhci_dwcmshc_k230_pdata, + }, + { + .compatible = "canaan,k230-sdio", + .data = &sdhci_dwcmshc_k230_pdata, + }, { .compatible = "rockchip,rk3588-dwcmshc", .data = &sdhci_dwcmshc_rk35xx_pdata, -- 2.52.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] mmc: sdhci-dwcmshc: Add Canaan K230 DWCMSHC controller support 2026-02-04 8:29 ` [PATCH 2/3] mmc: sdhci-dwcmshc: Add Canaan K230 DWCMSHC controller support Jiayu Du @ 2026-02-04 9:43 ` Yao Zi 2026-02-06 13:26 ` Krzysztof Kozlowski 1 sibling, 0 replies; 13+ messages in thread From: Yao Zi @ 2026-02-04 9:43 UTC (permalink / raw) To: Jiayu Du, ulf.hansson, adrian.hunter, robh, krzk+dt, conor+dt Cc: pjw, palmer, aou, linux-mmc, devicetree, linux-riscv, linux-kernel, gaohan On Wed, Feb 04, 2026 at 04:29:07PM +0800, Jiayu Du wrote: > Add SDHCI controller driver for Canaan k230 SoC. Implement custom > sdhci_ops for set_clock, phy init, init and reset. > > Signed-off-by: Jiayu Du <jiayu.riscv@isrc.iscas.ac.cn> > --- > drivers/mmc/host/sdhci-of-dwcmshc.c | 247 ++++++++++++++++++++++++++++ > 1 file changed, 247 insertions(+) > > diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c > index 204830b40587..bc427bfbba25 100644 > --- a/drivers/mmc/host/sdhci-of-dwcmshc.c > +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c ... > +static void dwcmshc_k230_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) > +{ > + u16 clk; > + > + sdhci_set_clock(host, clock); > + > + clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); > + clk |= SDHCI_PROG_CLOCK_MODE; > + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); Why it's necessary to always set SDHCI_PROG_CLOCK_MODE? If it's a vendor quirk, it deserves a comment to explain what's happening here. > +} ... > +static int dwcmshc_k230_phy_init(struct sdhci_host *host) > +{ > + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); > + struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); > + u32 rxsel = PHY_PAD_RXSEL_3V3; > + unsigned int timeout = 15000; > + u32 val; > + u32 reg; > + > + /* reset phy */ > + sdhci_writew(host, 0, PHY_CNFG_R); > + > + /* Disable the clock */ > + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); > + > + if (priv->flags & FLAG_IO_FIXED_1V8) > + rxsel = PHY_PAD_RXSEL_1V8; This may be a little nitpick, but the logic looks cleaner to me if you do rxsel = priv->flags & FLAG_IO_FIXED_1V8 ? PHY_PAD_RXSEL_1V8 : PHY_PAD_RXSEL_3V3; ... > + /* Wait max 150 ms */ > + while (1) { > + reg = sdhci_readl(host, PHY_CNFG_R); > + if (reg & FIELD_PREP(PHY_CNFG_PHY_PWRGOOD_MASK, 1)) > + break; > + if (!timeout) > + return -ETIMEDOUT; > + timeout--; > + usleep_range(10, 15); > + } You could use readx_poll_timeout() with sdhci_readl() to simplify this loop. > + reg = FIELD_PREP(PHY_CNFG_PAD_SN_MASK, PHY_CNFG_PAD_SN_k230) | > + FIELD_PREP(PHY_CNFG_PAD_SP_MASK, PHY_CNFG_PAD_SP_k230); > + sdhci_writel(host, reg, PHY_CNFG_R); > + > + /* de-assert the phy */ > + reg |= PHY_CNFG_RSTN_DEASSERT; > + sdhci_writel(host, reg, PHY_CNFG_R); > + > + return 0; > +} > +static int dwcmshc_k230_init(struct device *dev, struct sdhci_host *host, > + struct dwcmshc_priv *dwc_priv) > +{ ... > + if (!usb_phy_node) { > + return dev_err_probe(dev, -ENODEV, > + "Failed to find k230-usb-phy node\n"); > + } Please drop the curly braces, if there's only one statement in the body of an if, they're not necessary. This is also preferred in kernel coding style, > Do not unnecessarily use braces where a single statement will do.[1] Same for branches below. > + k230_priv->hi_sys_regmap = device_node_to_regmap(usb_phy_node); > + of_node_put(usb_phy_node); > + if (IS_ERR(k230_priv->hi_sys_regmap)) { > + return dev_err_probe(dev, PTR_ERR(k230_priv->hi_sys_regmap), > + "Failed to get k230-usb-phy regmap\n"); > + } ... > + host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; Why not set it in sdhci_dwcmshc_k230_data.pdata.quirks? > + return 0; > +} ... > +static const struct dwcmshc_pltfm_data sdhci_dwcmshc_k230_pdata = { > + .pdata = { > + .ops = &sdhci_dwcmshc_k230_ops, > + .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, > + }, > + .init = dwcmshc_k230_init, > +}; Best regards, Yao Zi [1]: https://elixir.bootlin.com/linux/v6.19-rc5/source/Documentation/process/coding-style.rst#L197 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] mmc: sdhci-dwcmshc: Add Canaan K230 DWCMSHC controller support 2026-02-04 8:29 ` [PATCH 2/3] mmc: sdhci-dwcmshc: Add Canaan K230 DWCMSHC controller support Jiayu Du 2026-02-04 9:43 ` Yao Zi @ 2026-02-06 13:26 ` Krzysztof Kozlowski 2026-02-07 8:45 ` Jiayu Du 1 sibling, 1 reply; 13+ messages in thread From: Krzysztof Kozlowski @ 2026-02-06 13:26 UTC (permalink / raw) To: Jiayu Du, ulf.hansson, adrian.hunter, robh, krzk+dt, conor+dt Cc: pjw, palmer, aou, linux-mmc, devicetree, linux-riscv, linux-kernel, gaohan, me On 04/02/2026 09:29, Jiayu Du wrote: > +static int dwcmshc_k230_init(struct device *dev, struct sdhci_host *host, > + struct dwcmshc_priv *dwc_priv) > +{ > + static const char * const clk_ids[] = {"base", "timer", "ahb"}; > + struct device_node *usb_phy_node; > + struct k230_priv *k230_priv; > + u32 data; > + int ret; > + > + k230_priv = devm_kzalloc(dev, sizeof(struct k230_priv), GFP_KERNEL); > + if (!k230_priv) > + return -ENOMEM; > + dwc_priv->priv = k230_priv; > + > + usb_phy_node = of_find_compatible_node(NULL, NULL, "canaan,k230-usb-phy"); Hm? You should use phandles, not look for various nodes. > + if (!usb_phy_node) { Please follow Linux coding style. > + return dev_err_probe(dev, -ENODEV, > + "Failed to find k230-usb-phy node\n"); > + } > + > + k230_priv->hi_sys_regmap = device_node_to_regmap(usb_phy_node); > + of_node_put(usb_phy_node); > + if (IS_ERR(k230_priv->hi_sys_regmap)) { > + return dev_err_probe(dev, PTR_ERR(k230_priv->hi_sys_regmap), > + "Failed to get k230-usb-phy regmap\n"); > + } > + > + ret = dwcmshc_get_enable_other_clks(mmc_dev(host->mmc), dwc_priv, > + ARRAY_SIZE(clk_ids), clk_ids); > + if (ret) { > + return dev_err_probe(dev, ret, > + "Failed to get/enable k230 mmc other clocks\n"); > + } > + > + if (of_device_is_compatible(dev->of_node, "canaan,k230-sdio")) { Driver match data is for this. Best regards, Krzysztof ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] mmc: sdhci-dwcmshc: Add Canaan K230 DWCMSHC controller support 2026-02-06 13:26 ` Krzysztof Kozlowski @ 2026-02-07 8:45 ` Jiayu Du 2026-02-07 9:32 ` Krzysztof Kozlowski 0 siblings, 1 reply; 13+ messages in thread From: Jiayu Du @ 2026-02-07 8:45 UTC (permalink / raw) To: Krzysztof Kozlowski, ulf.hansson, adrian.hunter, robh, krzk+dt, conor+dt Cc: pjw, palmer, aou, linux-mmc, devicetree, linux-riscv, linux-kernel, gaohan, me On Fri, Feb 06, 2026 at 02:26:40PM +0100, Krzysztof Kozlowski wrote: > On 04/02/2026 09:29, Jiayu Du wrote: > > +static int dwcmshc_k230_init(struct device *dev, struct sdhci_host *host, > > + struct dwcmshc_priv *dwc_priv) > > +{ > > + static const char * const clk_ids[] = {"base", "timer", "ahb"}; > > + struct device_node *usb_phy_node; > > + struct k230_priv *k230_priv; > > + u32 data; > > + int ret; > > + > > + k230_priv = devm_kzalloc(dev, sizeof(struct k230_priv), GFP_KERNEL); > > + if (!k230_priv) > > + return -ENOMEM; > > + dwc_priv->priv = k230_priv; > > + > > + usb_phy_node = of_find_compatible_node(NULL, NULL, "canaan,k230-usb-phy"); > > Hm? You should use phandles, not look for various nodes. Only one usbphy node has the canaan, k230-usb-phy compatibility. So in this situation, is it ok to continue using of_find_compatible_node? > > + if (!usb_phy_node) { > > Please follow Linux coding style. I will fix it in next version. > > + return dev_err_probe(dev, -ENODEV, > > + "Failed to find k230-usb-phy node\n"); > > + } > > + > > + k230_priv->hi_sys_regmap = device_node_to_regmap(usb_phy_node); > > + of_node_put(usb_phy_node); > > + if (IS_ERR(k230_priv->hi_sys_regmap)) { > > + return dev_err_probe(dev, PTR_ERR(k230_priv->hi_sys_regmap), > > + "Failed to get k230-usb-phy regmap\n"); > > + } > > + > > + ret = dwcmshc_get_enable_other_clks(mmc_dev(host->mmc), dwc_priv, > > + ARRAY_SIZE(clk_ids), clk_ids); > > + if (ret) { > > + return dev_err_probe(dev, ret, > > + "Failed to get/enable k230 mmc other clocks\n"); > > + } > > + > > + if (of_device_is_compatible(dev->of_node, "canaan,k230-sdio")) { > > Driver match data is for this. What you mean is that I shouldn't use of_find_compatible_node, but I can use device_get_match_data instead? Then I can continue to distinguish between SDIO and eMMC to do parameter configuration Or do you mean that I should put the parameters to be adjusted into the pdata structure? But currently, the dwcmshc structure is not suitable for containing vendor-specific properties. Regards, Jiayu Du > > Best regards, > Krzysztof ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] mmc: sdhci-dwcmshc: Add Canaan K230 DWCMSHC controller support 2026-02-07 8:45 ` Jiayu Du @ 2026-02-07 9:32 ` Krzysztof Kozlowski 2026-02-08 15:44 ` Jiayu Du 0 siblings, 1 reply; 13+ messages in thread From: Krzysztof Kozlowski @ 2026-02-07 9:32 UTC (permalink / raw) To: Jiayu Du, ulf.hansson, adrian.hunter, robh, krzk+dt, conor+dt Cc: pjw, palmer, aou, linux-mmc, devicetree, linux-riscv, linux-kernel, gaohan, me On 07/02/2026 09:45, Jiayu Du wrote: > On Fri, Feb 06, 2026 at 02:26:40PM +0100, Krzysztof Kozlowski wrote: >> On 04/02/2026 09:29, Jiayu Du wrote: >>> +static int dwcmshc_k230_init(struct device *dev, struct sdhci_host *host, >>> + struct dwcmshc_priv *dwc_priv) >>> +{ >>> + static const char * const clk_ids[] = {"base", "timer", "ahb"}; >>> + struct device_node *usb_phy_node; >>> + struct k230_priv *k230_priv; >>> + u32 data; >>> + int ret; >>> + >>> + k230_priv = devm_kzalloc(dev, sizeof(struct k230_priv), GFP_KERNEL); >>> + if (!k230_priv) >>> + return -ENOMEM; >>> + dwc_priv->priv = k230_priv; >>> + >>> + usb_phy_node = of_find_compatible_node(NULL, NULL, "canaan,k230-usb-phy"); >> >> Hm? You should use phandles, not look for various nodes. > > Only one usbphy node has the canaan, k230-usb-phy compatibility. > So in this situation, is it ok to continue using of_find_compatible_node? Amount of nodes does not matter. This is not how you express links/dependencies between devices. Phandle is for this. This is wrong on many levels, including missing device links, bypassing kernel API/layers. > >>> + if (!usb_phy_node) { >> >> Please follow Linux coding style. > > I will fix it in next version. > >>> + return dev_err_probe(dev, -ENODEV, >>> + "Failed to find k230-usb-phy node\n"); >>> + } >>> + >>> + k230_priv->hi_sys_regmap = device_node_to_regmap(usb_phy_node); >>> + of_node_put(usb_phy_node); >>> + if (IS_ERR(k230_priv->hi_sys_regmap)) { >>> + return dev_err_probe(dev, PTR_ERR(k230_priv->hi_sys_regmap), >>> + "Failed to get k230-usb-phy regmap\n"); >>> + } >>> + >>> + ret = dwcmshc_get_enable_other_clks(mmc_dev(host->mmc), dwc_priv, >>> + ARRAY_SIZE(clk_ids), clk_ids); >>> + if (ret) { >>> + return dev_err_probe(dev, ret, >>> + "Failed to get/enable k230 mmc other clocks\n"); >>> + } >>> + >>> + if (of_device_is_compatible(dev->of_node, "canaan,k230-sdio")) { >> >> Driver match data is for this. > > What you mean is that I shouldn't use of_find_compatible_node, but I can > use device_get_match_data instead? Then I can continue to distinguish > between SDIO and eMMC to do parameter configuration > > Or do you mean that I should put the parameters to be adjusted into the > pdata structure? But currently, the dwcmshc structure is not suitable for > containing vendor-specific properties. Parameters should go to driver match data. I already requested this for some other driver and this has to be fixed. Best regards, Krzysztof ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] mmc: sdhci-dwcmshc: Add Canaan K230 DWCMSHC controller support 2026-02-07 9:32 ` Krzysztof Kozlowski @ 2026-02-08 15:44 ` Jiayu Du 0 siblings, 0 replies; 13+ messages in thread From: Jiayu Du @ 2026-02-08 15:44 UTC (permalink / raw) To: Krzysztof Kozlowski, ulf.hansson, adrian.hunter, robh, krzk+dt, conor+dt Cc: pjw, palmer, aou, linux-mmc, devicetree, linux-riscv, linux-kernel, gaohan, me On Sat, Feb 07, 2026 at 10:32:55AM +0100, Krzysztof Kozlowski wrote: > On 07/02/2026 09:45, Jiayu Du wrote: > > On Fri, Feb 06, 2026 at 02:26:40PM +0100, Krzysztof Kozlowski wrote: > >> On 04/02/2026 09:29, Jiayu Du wrote: > >>> +static int dwcmshc_k230_init(struct device *dev, struct sdhci_host *host, > >>> + struct dwcmshc_priv *dwc_priv) > >>> +{ > >>> + static const char * const clk_ids[] = {"base", "timer", "ahb"}; > >>> + struct device_node *usb_phy_node; > >>> + struct k230_priv *k230_priv; > >>> + u32 data; > >>> + int ret; > >>> + > >>> + k230_priv = devm_kzalloc(dev, sizeof(struct k230_priv), GFP_KERNEL); > >>> + if (!k230_priv) > >>> + return -ENOMEM; > >>> + dwc_priv->priv = k230_priv; > >>> + > >>> + usb_phy_node = of_find_compatible_node(NULL, NULL, "canaan,k230-usb-phy"); > >> > >> Hm? You should use phandles, not look for various nodes. > > > > Only one usbphy node has the canaan, k230-usb-phy compatibility. > > So in this situation, is it ok to continue using of_find_compatible_node? > > Amount of nodes does not matter. This is not how you express > links/dependencies between devices. Phandle is for this. This is wrong > on many levels, including missing device links, bypassing kernel API/layers. Thank you for your review. I will fix it. > > > > > >>> + if (!usb_phy_node) { > >> > >> Please follow Linux coding style. > > > > I will fix it in next version. > > > >>> + return dev_err_probe(dev, -ENODEV, > >>> + "Failed to find k230-usb-phy node\n"); > >>> + } > >>> + > >>> + k230_priv->hi_sys_regmap = device_node_to_regmap(usb_phy_node); > >>> + of_node_put(usb_phy_node); > >>> + if (IS_ERR(k230_priv->hi_sys_regmap)) { > >>> + return dev_err_probe(dev, PTR_ERR(k230_priv->hi_sys_regmap), > >>> + "Failed to get k230-usb-phy regmap\n"); > >>> + } > >>> + > >>> + ret = dwcmshc_get_enable_other_clks(mmc_dev(host->mmc), dwc_priv, > >>> + ARRAY_SIZE(clk_ids), clk_ids); > >>> + if (ret) { > >>> + return dev_err_probe(dev, ret, > >>> + "Failed to get/enable k230 mmc other clocks\n"); > >>> + } > >>> + > >>> + if (of_device_is_compatible(dev->of_node, "canaan,k230-sdio")) { > >> > >> Driver match data is for this. > > > > What you mean is that I shouldn't use of_find_compatible_node, but I can > > use device_get_match_data instead? Then I can continue to distinguish > > between SDIO and eMMC to do parameter configuration > > > > Or do you mean that I should put the parameters to be adjusted into the > > pdata structure? But currently, the dwcmshc structure is not suitable for > > containing vendor-specific properties. > > Parameters should go to driver match data. I already requested this for > some other driver and this has to be fixed. I will make fix to enable dwcmshc_pltfm_data to support the addition of vendor-specific properties. And if possible, could you give me with some examples? I would be very grateful. > > Best regards, > Krzysztof ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 3/3] riscv: dts: canaan: Add mmc nodes for K230 2026-02-04 8:29 [PATCH 0/3] Add SDHCI support for Canaan K230 SoC Jiayu Du 2026-02-04 8:29 ` [PATCH 1/3] dt-bindings: mmc: Add sdhci support for Canaan k230 Jiayu Du 2026-02-04 8:29 ` [PATCH 2/3] mmc: sdhci-dwcmshc: Add Canaan K230 DWCMSHC controller support Jiayu Du @ 2026-02-04 8:29 ` Jiayu Du 2 siblings, 0 replies; 13+ messages in thread From: Jiayu Du @ 2026-02-04 8:29 UTC (permalink / raw) To: ulf.hansson, adrian.hunter, robh, krzk+dt, conor+dt Cc: pjw, palmer, aou, linux-mmc, devicetree, linux-riscv, linux-kernel, gaohan, me, Jiayu Du Add MMC nodes to K230, including eMMC and SDIO. Enable HS200 eMMC on the SoM and SDIO high-speed on the board. Signed-off-by: Jiayu Du <jiayu.riscv@isrc.iscas.ac.cn> --- .../boot/dts/canaan/k230-canmv-dshanpi.dts | 17 ++++++++++++ .../dts/canaan/k230-canmv-module-dshanpi.dtsi | 7 +++++ arch/riscv/boot/dts/canaan/k230.dtsi | 26 +++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/arch/riscv/boot/dts/canaan/k230-canmv-dshanpi.dts b/arch/riscv/boot/dts/canaan/k230-canmv-dshanpi.dts index 55197cfc25b4..fdf6524db09b 100644 --- a/arch/riscv/boot/dts/canaan/k230-canmv-dshanpi.dts +++ b/arch/riscv/boot/dts/canaan/k230-canmv-dshanpi.dts @@ -15,6 +15,8 @@ / { aliases { serial0 = &uart0; + mmc0 = &emmc; + mmc1 = &sdio; }; chosen { @@ -75,6 +77,21 @@ uart0-rxd-cfg { }; }; +&emmc { + vmmc-supply = <&vdd_3v3>; + vqmmc-supply = <&vdd_1v8>; +}; + +&sdio { + bus-width = <4>; + max-frequency = <50000000>; + vmmc-supply = <&vdd_3v3>; + vqmmc-supply = <&vdd_3v3>; + cap-sd-highspeed; + no-1-8-v; + status = "okay"; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_pins>; diff --git a/arch/riscv/boot/dts/canaan/k230-canmv-module-dshanpi.dtsi b/arch/riscv/boot/dts/canaan/k230-canmv-module-dshanpi.dtsi index 566665d39239..1db7569253fe 100644 --- a/arch/riscv/boot/dts/canaan/k230-canmv-module-dshanpi.dtsi +++ b/arch/riscv/boot/dts/canaan/k230-canmv-module-dshanpi.dtsi @@ -24,3 +24,10 @@ &sysclk { clocks = <&osc24m>, <&timerx_pulse_in>; clock-names = "osc24m", "timer-pulse-in"; }; + +&emmc { + bus-width = <8>; + max-frequency = <200000000>; + mmc-hs200-1_8v; + status = "okay"; +}; diff --git a/arch/riscv/boot/dts/canaan/k230.dtsi b/arch/riscv/boot/dts/canaan/k230.dtsi index b369b7d8dc83..296bf448403d 100644 --- a/arch/riscv/boot/dts/canaan/k230.dtsi +++ b/arch/riscv/boot/dts/canaan/k230.dtsi @@ -177,6 +177,32 @@ usb1: usb@91540000 { status = "disabled"; }; + emmc: mmc@91580000 { + compatible = "canaan,k230-emmc"; + reg = <0x0 0x91580000 0x0 0x1000>; + clocks = <&sysclk K230_HS_SD0_AXI_GATE>, + <&sysclk K230_HS_SD0_CARD_GATE>, + <&sysclk K230_HS_SD0_BASE_GATE>, + <&sysclk K230_HS_SD0_TIMER_GATE>, + <&sysclk K230_HS_SD0_AHB_GATE>; + clock-names = "bus", "core", "base", "timer", "ahb"; + interrupts = <142 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + sdio: mmc@91581000 { + compatible = "canaan,k230-sdio"; + reg = <0x0 0x91581000 0x0 0x1000>; + clocks = <&sysclk K230_HS_SD1_AXI_GATE>, + <&sysclk K230_HS_SD1_CARD_GATE>, + <&sysclk K230_HS_SD1_BASE_GATE>, + <&sysclk K230_HS_SD1_TIMER_GATE>, + <&sysclk K230_HS_SD1_AHB_GATE>; + clock-names = "bus", "core", "base", "timer", "ahb"; + interrupts = <144 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + usbphy: usb-phy@91585000 { compatible = "canaan,k230-usb-phy"; reg = <0x0 0x91585000 0x0 0x400>; -- 2.52.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-02-08 15:44 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-02-04 8:29 [PATCH 0/3] Add SDHCI support for Canaan K230 SoC Jiayu Du 2026-02-04 8:29 ` [PATCH 1/3] dt-bindings: mmc: Add sdhci support for Canaan k230 Jiayu Du 2026-02-04 18:10 ` Conor Dooley 2026-02-05 7:13 ` Jiayu Du 2026-02-05 19:19 ` Conor Dooley 2026-02-06 2:56 ` Jiayu Du 2026-02-04 8:29 ` [PATCH 2/3] mmc: sdhci-dwcmshc: Add Canaan K230 DWCMSHC controller support Jiayu Du 2026-02-04 9:43 ` Yao Zi 2026-02-06 13:26 ` Krzysztof Kozlowski 2026-02-07 8:45 ` Jiayu Du 2026-02-07 9:32 ` Krzysztof Kozlowski 2026-02-08 15:44 ` Jiayu Du 2026-02-04 8:29 ` [PATCH 3/3] riscv: dts: canaan: Add mmc nodes for K230 Jiayu Du
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox