* RE: [PATCH v7 2/2] iio: dac: ad5706r: Add support for AD5706R DAC
From: Torreno, Alexis Czezar @ 2026-04-13 7:15 UTC (permalink / raw)
To: David Lechner, Lars-Peter Clausen, Hennerich, Michael,
Jonathan Cameron, Sa, Nuno, Andy Shevchenko, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, Andy Shevchenko
In-Reply-To: <cdfb9deb-2439-413b-8c20-3c6ad6a81ce3@baylibre.com>
> > +static int ad5706r_regmap_write(void *context, const void *data,
> > +size_t count) {
> > + struct ad5706r_state *st = context;
> > + unsigned int num_bytes, val;
> > + u16 reg;
> > +
> > + if (count != 4)
> > + return -EINVAL;
> > +
> > + reg = get_unaligned_be16(data);
> > + num_bytes = ad5706r_reg_len(reg);
> > +
> > + struct spi_transfer xfer = {
> > + .tx_buf = st->tx_buf,
> > + .len = num_bytes + 2,
> > + };
> > +
> > + val = get_unaligned_be32(data);
> > + put_unaligned_be32(val, &st->tx_buf[0]);
>
> Can't we just do memcpy() instead of swapping the byte order twice?
This was memcpy before, was changed to this for consistency as per Andy's
suggestion. It was during v5.
Removal of this plus the other mem* commands allowed removal of string.h
in the headers.
>
> > +
> > + /* For single byte, copy the data to the correct position */
> > + if (num_bytes == AD5706R_SINGLE_BYTE_LEN)
> > + st->tx_buf[2] = st->tx_buf[3];
> > +
> > + return spi_sync_transfer(st->spi, &xfer, 1);
>
> There isn't any special paramters in the xfer struct, so spi_write() should work
> here and save a bit of code.
>
> return spi_write(st->spi, data, num_bytes);
Back in v3-v4, Joathan suggested this to be spi_write_then_read() as it was much safer,
but I requested to keep it this way since I would be adding more features to this driver
like changing spi_speeds, which cannot be done if using spi_write_then_read
>
> > +}
> > +
> > +static int ad5706r_regmap_read(void *context, const void *reg_buf,
> > + size_t reg_size, void *val_buf, size_t val_size) {
> > + struct ad5706r_state *st = context;
> > + unsigned int num_bytes;
> > + u16 reg, cmd, val;
> > + int ret;
> > +
> > + if (reg_size != 2 || val_size != 2)
> > + return -EINVAL;
> > +
> > + reg = get_unaligned_be16(reg_buf);
> > + num_bytes = ad5706r_reg_len(reg);
> > +
> > + /* Full duplex, device responds immediately after command */
> > + struct spi_transfer xfer = {
> > + .tx_buf = st->tx_buf,
> > + .rx_buf = st->rx_buf,
> > + .len = 2 + num_bytes,
> > + };
> > +
> > + cmd = AD5706R_RD_MASK | (reg & AD5706R_ADDR_MASK);
> > + put_unaligned_be16(cmd, &st->tx_buf[0]);
> > + put_unaligned_be16(0, &st->tx_buf[2]);
>
> Do we actually need to write 0s while reading?
>
> Usually, we would just do a spi_write_then_read for something like this.
Technically it's a don't care data, zero just makes it cleaner signals during debug
Discussed spi_write_then_read in a comment above
>
> > +
> > + ret = spi_sync_transfer(st->spi, &xfer, 1);
> > + if (ret)
> > + return ret;
> > +
>
>
> > + /* Extract value from response (skip 2-byte command echo) */
> > + if (num_bytes == AD5706R_SINGLE_BYTE_LEN)
> > + val = st->rx_buf[2];
> > + else if (num_bytes == AD5706R_DOUBLE_BYTE_LEN)
> > + val = get_unaligned_be16(&st->rx_buf[2]);
> > + else
> > + return -EINVAL;
> > +
> > + put_unaligned_be16(val, val_buf);
>
> Can't this all be simplified to memcpy(val_buf, &st->rx_buf[2], num_bytes); ?
>
> Or the whole thing simplified to:
>
> return spi_write_then_read(st->spi, reg_buf, 2, val_buf, num_bytes);
>
as discussed above about mem* and spi_write_then_read
^ permalink raw reply
* Re: [PATCH 2/2] media: i2c: add os02g10 image sensor driver
From: Tarang Raval @ 2026-04-13 7:20 UTC (permalink / raw)
To: Elgin Perumbilly, sakari.ailus@linux.intel.com
Cc: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Hans Verkuil, Hans de Goede, Vladimir Zapolskiy,
Laurent Pinchart, Xiaolei Wang, Walter Werner Schneider,
Kate Hsuan, Sylvain Petinot, Mehdi Djait, Heimir Thor Sverrisson,
linux-media@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <20260411094723.129738-3-elgin.perumbilly@siliconsignals.io>
Hi Elgin,
Thanks for sending these drivers.
A few minor points are listed below, please take a look.
> Add a v4l2 subdevice driver for the Omnivision os02g10 sensor.
>
> The Omnivision os02g10 is a CMOS image sensor with an active array size of
> 1920 x 1080.
>
> The following features are supported:
> - Manual exposure an gain control support
> - vblank/hblank control support
> - vflip/hflip control support
> - Test pattern control support
> - Supported resolution: 1920 x 1080 @ 30fps (SBGGR10)
>
> Signed-off-by: Elgin Perumbilly <elgin.perumbilly@siliconsignals.io>
> ---
> MAINTAINERS | 1 +
> drivers/media/i2c/Kconfig | 10 +
> drivers/media/i2c/Makefile | 1 +
> drivers/media/i2c/os02g10.c | 1010 +++++++++++++++++++++++++++++++++++
> 4 files changed, 1022 insertions(+)
> create mode 100644 drivers/media/i2c/os02g10.c
...
> +#define OS02G10_REG_SIF_CTRL OS02G10_PAGE_REG8(0x02, 0x5e)
> +#define OS02G10_ORIENTATION_BAYER_FIX 0x32
The above two definitions belong to Page 2, Please move them to the Page 2
block below.
> +/* Page 2 */
> +#define OS02G10_REG_V_START OS02G10_PAGE_REG16(0x02, 0xa0)
> +#define OS02G10_REG_V_SIZE OS02G10_PAGE_REG16(0x02, 0xa2)
> +#define OS02G10_REG_H_START OS02G10_PAGE_REG16(0x02, 0xa4)
> +#define OS02G10_REG_H_SIZE OS02G10_PAGE_REG16(0x02, 0xa6)
> +
> +#define OS02G10_LINK_FREQ_720MHZ (720 * HZ_PER_MHZ)
...
> +static int os02g10_set_ctrl(struct v4l2_ctrl *ctrl)
> +{
> + struct os02g10 *os02g10 = container_of_const(ctrl->handler,
> + struct os02g10, handler);
> + struct v4l2_subdev_state *state;
> + struct v4l2_mbus_framefmt *fmt;
> + int ret = 0;
> +
> + state = v4l2_subdev_get_locked_active_state(&os02g10->sd);
> + fmt = v4l2_subdev_state_get_format(state, 0);
> +
> + if (ctrl->id == V4L2_CID_VBLANK) {
> + /* Honour the VBLANK limits when setting exposure */
> + s64 max = fmt->height + ctrl->val - OS02G10_EXPOSURE_MARGIN;
> +
> + ret = __v4l2_ctrl_modify_range(os02g10->exposure,
> + os02g10->exposure->minimum, max,
> + os02g10->exposure->step,
> + os02g10->exposure->default_value);
> + if (ret)
> + return ret;
> + }
> +
> + if (pm_runtime_get_if_in_use(os02g10->dev) == 0)
Please use pm_runtime_get_if_active.
> + return 0;
> +
> + switch (ctrl->id) {
> + case V4L2_CID_EXPOSURE:
> + os02g10_write(os02g10, OS02G10_REG_LONG_EXPOSURE, ctrl->val, &ret);
> + break;
> + case V4L2_CID_ANALOGUE_GAIN:
> + os02g10_write(os02g10, OS02G10_REG_ANALOG_GAIN, ctrl->val, &ret);
> + break;
> + case V4L2_CID_DIGITAL_GAIN:
> + os02g10_write(os02g10, OS02G10_REG_DIGITAL_GAIN_L,
> + (ctrl->val & 0xff), &ret);
> + os02g10_write(os02g10, OS02G10_REG_DIGITAL_GAIN_H,
> + ((ctrl->val >> 8) & 0x7), &ret);
> + break;
> + case V4L2_CID_VBLANK:
> + u64 vts = ctrl->val + fmt->height;
> +
> + os02g10_update_bits(os02g10, OS02G10_REG_FRAME_EXP_SEPERATE_EN,
> + OS02G10_FRAME_EXP_SEPERATE_EN,
> + OS02G10_FRAME_EXP_SEPERATE_EN, &ret);
> + os02g10_write(os02g10, OS02G10_REG_FRAME_LENGTH, vts, &ret);
> + break;
> + case V4L2_CID_HFLIP:
> + case V4L2_CID_VFLIP:
> + os02g10_write(os02g10, OS02G10_REG_FLIP_MIRROR,
> + os02g10->hflip->val | os02g10->vflip->val << 1,
> + &ret);
> + os02g10_write(os02g10, OS02G10_REG_SIF_CTRL,
> + OS02G10_ORIENTATION_BAYER_FIX, &ret);
> + break;
> + case V4L2_CID_TEST_PATTERN:
> + os02g10_update_bits(os02g10,
> + OS02G10_REG_TEST_PATTERN,
> + OS02G10_TEST_PATTERN_ENABLE,
> + ctrl->val ? OS02G10_TEST_PATTERN_ENABLE : 0,
> + &ret);
> + break;
> + default:
> + ret = -EINVAL;
> + break;
> + }
> + os02g10_write(os02g10, OS02G10_REG_FRAME_SYNC, 0x01, &ret);
> +
> + pm_runtime_put(os02g10->dev);
> +
> + return ret;
> +}
...
> +static int os02g10_init_controls(struct os02g10 *os02g10)
> +{
> + const struct os02g10_mode *mode = &supported_modes[0];
> + u64 vblank_def, hblank_def, exp_max, pixel_rate;
> + struct v4l2_fwnode_device_properties props;
> + struct v4l2_ctrl_handler *ctrl_hdlr;
> + int ret;
> +
> + ctrl_hdlr = &os02g10->handler;
> + v4l2_ctrl_handler_init(ctrl_hdlr, 12);
> +
> + /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */
> + pixel_rate = div_u64(OS02G10_LINK_FREQ_720MHZ * 2 * 2, 10);
> + v4l2_ctrl_new_std(ctrl_hdlr, &os02g10_ctrl_ops, V4L2_CID_PIXEL_RATE, 0,
> + pixel_rate, 1, pixel_rate);
> +
> + os02g10->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &os02g10_ctrl_ops,
> + V4L2_CID_LINK_FREQ,
> + os02g10->link_freq_index,
> + 0, link_freq_menu_items);
> + if (os02g10->link_freq)
> + os02g10->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> +
> + hblank_def = mode->hts_def - mode->width;
Please use (mode->hts_def * 2) here, otherwise hblank_def can end up with
negative value.
Also, add a comment mentioning that the datasheet does not provide any
information about the unit of hts.
> + os02g10->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &os02g10_ctrl_ops,
> + V4L2_CID_HBLANK, hblank_def, hblank_def,
> + 1, hblank_def);
> + if (os02g10->hblank)
> + os02g10->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> +
> + vblank_def = mode->vts_def - mode->height;
> + os02g10->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &os02g10_ctrl_ops,
> + V4L2_CID_VBLANK, vblank_def,
> + OS02G10_FRAME_LENGTH_MAX - mode->height,
> + 1, vblank_def);
> +
...
> +static int os02g10_disable_streams(struct v4l2_subdev *sd,
> + struct v4l2_subdev_state *state, u32 pad,
> + u64 streams_mask)
> +{
> + struct os02g10 *os02g10 = to_os02g10(sd);
> + int ret;
> +
> + ret = os02g10_write(os02g10, OS02G10_REG_STREAM_CTRL,
> + OS02G10_STREAM_CTRL_OFF, NULL);
> + if (ret)
> + dev_err(os02g10->dev, "%s failed to set stream\n", __func__);
Remove __func__ from the error message; it is unnecessary.
Also, please use a more meaningful error message
> +
> + __v4l2_ctrl_grab(os02g10->vflip, false);
> + __v4l2_ctrl_grab(os02g10->hflip, false);
> +
> + pm_runtime_put(os02g10->dev);
> +
> + return ret;
> +}
> +
> +static int os02g10_get_selection(struct v4l2_subdev *sd,
> + struct v4l2_subdev_state *sd_state,
> + struct v4l2_subdev_selection *sel)
> +{
> + switch (sel->target)
> + case V4L2_SEL_TGT_CROP:
> + case V4L2_SEL_TGT_NATIVE_SIZE:
> + sel->r = os02g10_native_area;
V4L2_SEL_TGT_CROP should use the active area, and V4L2_SEL_TGT_CROP_BOUNDS
should use the native area. Please update this accordingly.
> + return 0;
> + case V4L2_SEL_TGT_CROP_DEFAULT:
> + case V4L2_SEL_TGT_CROP_BOUNDS:
> + sel->r = os02g10_active_area;
> + return 0;
> + default:
> + return -EINVAL;
> + }
> +}
...
> +static struct i2c_driver os02g10_driver = {
> + .driver = {
> + .name = "os02g10",
> + .pm = pm_ptr(&os02g10_pm_ops),
> + .of_match_table = os02g10_id,
> + },
> + .probe = os02g10_probe,
> + .remove = os02g10_remove,
> +};
> +module_i2c_driver(os02g10_driver);
> +
> +MODULE_DESCRIPTION("OS02G10 Camera Sensor Driver");
> +MODULE_AUTHOR("Tarang Raval <tarang.raval@siliconsignals.io>");
You can add your name here as well.
> +MODULE_LICENSE("GPL");
> --
> 2.34.1
Apart from the above comments, the driver looks good to me.
Reviewed-by: Tarang Raval <tarang.raval@siliconsignals.io>
Best Regards,
Tarang
^ permalink raw reply
* [PATCH v7 1/9] dt-bindings: mmc: spacemit,sdhci: add pinctrl support for voltage switching
From: Iker Pedrosa @ 2026-04-13 7:24 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Adrian Hunter, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Yixun Lan
Cc: Iker Pedrosa, Troy Mitchell, Michael Opdenacker,
Javier Martinez Canillas, linux-mmc, devicetree, linux-riscv,
spacemit, linux-kernel
In-Reply-To: <20260413-orangepi-sd-card-uhs-v7-0-16650f49c022@gmail.com>
Document pinctrl properties to support voltage-dependent pin
configuration switching for UHS-I SD card modes.
Add optional pinctrl-names property with two states:
- "default": For 3.3V operation with standard drive strength
- "state_uhs": For 1.8V operation with optimized drive strength
These pinctrl states allow the SDHCI driver to coordinate voltage
switching with pin configuration changes, ensuring proper signal
integrity during UHS-I mode transitions.
Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
---
Documentation/devicetree/bindings/mmc/spacemit,sdhci.yaml | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/Documentation/devicetree/bindings/mmc/spacemit,sdhci.yaml b/Documentation/devicetree/bindings/mmc/spacemit,sdhci.yaml
index 9a055d963a7f..34d202af909f 100644
--- a/Documentation/devicetree/bindings/mmc/spacemit,sdhci.yaml
+++ b/Documentation/devicetree/bindings/mmc/spacemit,sdhci.yaml
@@ -44,6 +44,18 @@ properties:
- const: axi
- const: sdh
+ pinctrl-names:
+ minItems: 1
+ items:
+ - const: default
+ - const: uhs
+
+ pinctrl-0:
+ description: Default pinctrl state for 3.3V operation
+
+ pinctrl-1:
+ description: Optional pinctrl state for 1.8V UHS operation with "uhs" name
+
required:
- compatible
- reg
@@ -62,4 +74,7 @@ examples:
interrupt-parent = <&plic>;
clocks = <&clk_apmu 10>, <&clk_apmu 13>;
clock-names = "core", "io";
+ pinctrl-names = "default", "uhs";
+ pinctrl-0 = <&sdhci_default_cfg>;
+ pinctrl-1 = <&sdhci_uhs_cfg>;
};
--
2.53.0
^ permalink raw reply related
* [PATCH v7 2/9] mmc: sdhci-of-k1: enable essential clock infrastructure for SD operation
From: Iker Pedrosa @ 2026-04-13 7:24 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Adrian Hunter, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Yixun Lan
Cc: Iker Pedrosa, Troy Mitchell, Michael Opdenacker,
Javier Martinez Canillas, linux-mmc, devicetree, linux-riscv,
spacemit, linux-kernel, Anand Moon, Trevor Gamblin,
Vincent Legoll
In-Reply-To: <20260413-orangepi-sd-card-uhs-v7-0-16650f49c022@gmail.com>
Ensure SD card pins receive clock signals by enabling pad clock
generation and overriding automatic clock gating. Required for all SD
operation modes.
The SDHC_GEN_PAD_CLK_ON setting in LEGACY_CTRL_REG is safe for both SD
and eMMC operation as both protocols use the same physical MMC interface
pins and require proper clock signal generation at the hardware level
for signal integrity and timing.
Additional SD-specific clock overrides (SDHC_OVRRD_CLK_OEN and
SDHC_FORCE_CLK_ON) are conditionally applied only for SD-only
controllers to handle removable card scenarios.
Tested-by: Anand Moon <linux.amoon@gmail.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Tested-by: Trevor Gamblin <tgamblin@baylibre.com>
Reviewed-by: Troy Mitchell <troy.mitchell@linux.dev>
Tested-by: Vincent Legoll <legoll@online.fr>
Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
---
drivers/mmc/host/sdhci-of-k1.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/mmc/host/sdhci-of-k1.c b/drivers/mmc/host/sdhci-of-k1.c
index 455656f9842d..0dd06fc19b85 100644
--- a/drivers/mmc/host/sdhci-of-k1.c
+++ b/drivers/mmc/host/sdhci-of-k1.c
@@ -21,6 +21,13 @@
#include "sdhci.h"
#include "sdhci-pltfm.h"
+#define SPACEMIT_SDHC_OP_EXT_REG 0x108
+#define SDHC_OVRRD_CLK_OEN BIT(11)
+#define SDHC_FORCE_CLK_ON BIT(12)
+
+#define SPACEMIT_SDHC_LEGACY_CTRL_REG 0x10C
+#define SDHC_GEN_PAD_CLK_ON BIT(6)
+
#define SPACEMIT_SDHC_MMC_CTRL_REG 0x114
#define SDHC_MISC_INT_EN BIT(1)
#define SDHC_MISC_INT BIT(2)
@@ -101,6 +108,12 @@ static void spacemit_sdhci_reset(struct sdhci_host *host, u8 mask)
if (!(host->mmc->caps2 & MMC_CAP2_NO_MMC))
spacemit_sdhci_setbits(host, SDHC_MMC_CARD_MODE, SPACEMIT_SDHC_MMC_CTRL_REG);
+
+ spacemit_sdhci_setbits(host, SDHC_GEN_PAD_CLK_ON, SPACEMIT_SDHC_LEGACY_CTRL_REG);
+
+ if (host->mmc->caps2 & MMC_CAP2_NO_MMC)
+ spacemit_sdhci_setbits(host, SDHC_OVRRD_CLK_OEN | SDHC_FORCE_CLK_ON,
+ SPACEMIT_SDHC_OP_EXT_REG);
}
static void spacemit_sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned int timing)
--
2.53.0
^ permalink raw reply related
* [PATCH v7 3/9] mmc: sdhci-of-k1: add regulator and pinctrl voltage switching support
From: Iker Pedrosa @ 2026-04-13 7:24 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Adrian Hunter, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Yixun Lan
Cc: Iker Pedrosa, Troy Mitchell, Michael Opdenacker,
Javier Martinez Canillas, linux-mmc, devicetree, linux-riscv,
spacemit, linux-kernel, Anand Moon, Trevor Gamblin,
Vincent Legoll
In-Reply-To: <20260413-orangepi-sd-card-uhs-v7-0-16650f49c022@gmail.com>
Add voltage switching infrastructure for UHS-I modes by integrating both
regulator framework (for supply voltage control) and pinctrl state
switching (for pin drive strength optimization).
- Add regulator supply parsing and voltage switching callback
- Add optional pinctrl state switching between "default" (3.3V) and
"state_uhs" (1.8V) configurations
- Enable coordinated voltage and pin configuration changes for UHS modes
This provides complete voltage switching support while maintaining
backward compatibility when pinctrl states are not defined.
Tested-by: Anand Moon <linux.amoon@gmail.com>
Tested-by: Trevor Gamblin <tgamblin@baylibre.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Reviewed-by: Troy Mitchell <troy.mitchell@linux.dev>
Tested-by: Vincent Legoll <legoll@online.fr>
Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
---
drivers/mmc/host/sdhci-of-k1.c | 72 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 72 insertions(+)
diff --git a/drivers/mmc/host/sdhci-of-k1.c b/drivers/mmc/host/sdhci-of-k1.c
index 0dd06fc19b85..d9144537032a 100644
--- a/drivers/mmc/host/sdhci-of-k1.c
+++ b/drivers/mmc/host/sdhci-of-k1.c
@@ -16,6 +16,7 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/reset.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include "sdhci.h"
@@ -71,6 +72,9 @@
struct spacemit_sdhci_host {
struct clk *clk_core;
struct clk *clk_io;
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *pinctrl_default;
+ struct pinctrl_state *pinctrl_uhs;
};
/* All helper functions will update clr/set while preserve rest bits */
@@ -219,6 +223,46 @@ static void spacemit_sdhci_pre_hs400_to_hs200(struct mmc_host *mmc)
SPACEMIT_SDHC_PHY_CTRL_REG);
}
+static int spacemit_sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
+ struct mmc_ios *ios)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct spacemit_sdhci_host *sdhst = sdhci_pltfm_priv(pltfm_host);
+ struct pinctrl_state *state;
+ int ret;
+
+ ret = sdhci_start_signal_voltage_switch(mmc, ios);
+ if (ret)
+ return ret;
+
+ if (!sdhst->pinctrl)
+ return 0;
+
+ /* Select appropriate pinctrl state based on signal voltage */
+ switch (ios->signal_voltage) {
+ case MMC_SIGNAL_VOLTAGE_330:
+ state = sdhst->pinctrl_default;
+ break;
+ case MMC_SIGNAL_VOLTAGE_180:
+ state = sdhst->pinctrl_uhs;
+ break;
+ default:
+ dev_warn(mmc_dev(mmc), "unsupported voltage %d\n", ios->signal_voltage);
+ return 0;
+ }
+
+ ret = pinctrl_select_state(sdhst->pinctrl, state);
+ if (ret) {
+ dev_warn(mmc_dev(mmc), "failed to select pinctrl state: %d\n", ret);
+ return 0;
+ }
+ dev_dbg(mmc_dev(mmc), "switched to %s pinctrl state\n",
+ ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180 ? "UHS" : "default");
+
+ return 0;
+}
+
static inline int spacemit_sdhci_get_clocks(struct device *dev,
struct sdhci_pltfm_host *pltfm_host)
{
@@ -252,6 +296,30 @@ static inline int spacemit_sdhci_get_resets(struct device *dev)
return 0;
}
+static inline void spacemit_sdhci_get_pins(struct device *dev,
+ struct sdhci_pltfm_host *pltfm_host)
+{
+ struct spacemit_sdhci_host *sdhst = sdhci_pltfm_priv(pltfm_host);
+
+ sdhst->pinctrl = devm_pinctrl_get(dev);
+ if (IS_ERR(sdhst->pinctrl)) {
+ sdhst->pinctrl = NULL;
+ dev_dbg(dev, "pinctrl not available, voltage switching will work without it\n");
+ return;
+ }
+
+ sdhst->pinctrl_default = pinctrl_lookup_state(sdhst->pinctrl, "default");
+ if (IS_ERR(sdhst->pinctrl_default))
+ sdhst->pinctrl_default = NULL;
+
+ sdhst->pinctrl_uhs = pinctrl_lookup_state(sdhst->pinctrl, "uhs");
+ if (IS_ERR(sdhst->pinctrl_uhs))
+ sdhst->pinctrl_uhs = NULL;
+
+ dev_dbg(dev, "pinctrl setup: default=%p, uhs=%p\n",
+ sdhst->pinctrl_default, sdhst->pinctrl_uhs);
+}
+
static const struct sdhci_ops spacemit_sdhci_ops = {
.get_max_clock = spacemit_sdhci_clk_get_max_clock,
.reset = spacemit_sdhci_reset,
@@ -324,6 +392,10 @@ static int spacemit_sdhci_probe(struct platform_device *pdev)
host->mmc->caps |= MMC_CAP_NEED_RSP_BUSY;
+ spacemit_sdhci_get_pins(dev, pltfm_host);
+
+ host->mmc_host_ops.start_signal_voltage_switch = spacemit_sdhci_start_signal_voltage_switch;
+
ret = spacemit_sdhci_get_clocks(dev, pltfm_host);
if (ret)
goto err_pltfm;
--
2.53.0
^ permalink raw reply related
* [PATCH v7 4/9] mmc: sdhci-of-k1: add comprehensive SDR tuning support
From: Iker Pedrosa @ 2026-04-13 7:24 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Adrian Hunter, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Yixun Lan
Cc: Iker Pedrosa, Troy Mitchell, Michael Opdenacker,
Javier Martinez Canillas, linux-mmc, devicetree, linux-riscv,
spacemit, linux-kernel, Anand Moon, Trevor Gamblin,
Vincent Legoll
In-Reply-To: <20260413-orangepi-sd-card-uhs-v7-0-16650f49c022@gmail.com>
Implement software tuning algorithm to enable UHS-I SDR modes for SD
card operation and HS200 mode for eMMC. This adds both TX and RX delay
line tuning based on the SpacemiT K1 controller capabilities.
Algorithm features:
- Add tuning register definitions (RX_CFG, DLINE_CTRL, DLINE_CFG)
- Conditional tuning: only for high-speed modes (≥100MHz)
- TX tuning: configure transmit delay line with optimal values
(dline_reg=0, delaycode=127) to ensure optimal signal output timing
- RX tuning: single-pass window detection algorithm testing full
delay range (0-255) to find optimal receive timing window
- Retry mechanism: multiple fallback delays within optimal window
for improved reliability
Tested-by: Anand Moon <linux.amoon@gmail.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Tested-by: Trevor Gamblin <tgamblin@baylibre.com>
Tested-by: Vincent Legoll <legoll@online.fr>
Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
---
drivers/mmc/host/sdhci-of-k1.c | 172 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 172 insertions(+)
diff --git a/drivers/mmc/host/sdhci-of-k1.c b/drivers/mmc/host/sdhci-of-k1.c
index d9144537032a..37b0911e7cf2 100644
--- a/drivers/mmc/host/sdhci-of-k1.c
+++ b/drivers/mmc/host/sdhci-of-k1.c
@@ -69,6 +69,28 @@
#define SDHC_PHY_DRIVE_SEL GENMASK(2, 0)
#define SDHC_RX_BIAS_CTRL BIT(5)
+#define SPACEMIT_SDHC_RX_CFG_REG 0x118
+#define SDHC_RX_SDCLK_SEL0_MASK GENMASK(1, 0)
+#define SDHC_RX_SDCLK_SEL1_MASK GENMASK(3, 2)
+#define SDHC_RX_SDCLK_SEL1 FIELD_PREP(SDHC_RX_SDCLK_SEL1_MASK, 1)
+
+#define SPACEMIT_SDHC_DLINE_CTRL_REG 0x130
+#define SDHC_DLINE_PU BIT(0)
+#define SDHC_RX_DLINE_CODE_MASK GENMASK(23, 16)
+#define SDHC_TX_DLINE_CODE_MASK GENMASK(31, 24)
+
+#define SPACEMIT_SDHC_DLINE_CFG_REG 0x134
+#define SDHC_RX_DLINE_REG_MASK GENMASK(7, 0)
+#define SDHC_RX_DLINE_GAIN BIT(8)
+#define SDHC_TX_DLINE_REG_MASK GENMASK(23, 16)
+
+#define SPACEMIT_RX_DLINE_REG 9
+#define SPACEMIT_RX_TUNE_DELAY_MIN 0x0
+#define SPACEMIT_RX_TUNE_DELAY_MAX 0xFF
+
+#define SPACEMIT_TX_TUNING_DLINE_REG 0x00
+#define SPACEMIT_TX_TUNING_DELAYCODE 127
+
struct spacemit_sdhci_host {
struct clk *clk_core;
struct clk *clk_io;
@@ -96,6 +118,50 @@ static inline void spacemit_sdhci_clrsetbits(struct sdhci_host *host, u32 clr, u
sdhci_writel(host, val, reg);
}
+static void spacemit_sdhci_set_rx_delay(struct sdhci_host *host, u8 delay)
+{
+ spacemit_sdhci_clrsetbits(host, SDHC_RX_DLINE_CODE_MASK,
+ FIELD_PREP(SDHC_RX_DLINE_CODE_MASK, delay),
+ SPACEMIT_SDHC_DLINE_CTRL_REG);
+}
+
+static void spacemit_sdhci_set_tx_delay(struct sdhci_host *host, u8 delay)
+{
+ spacemit_sdhci_clrsetbits(host, SDHC_TX_DLINE_CODE_MASK,
+ FIELD_PREP(SDHC_TX_DLINE_CODE_MASK, delay),
+ SPACEMIT_SDHC_DLINE_CTRL_REG);
+}
+
+static void spacemit_sdhci_set_tx_dline_reg(struct sdhci_host *host, u8 dline_reg)
+{
+ spacemit_sdhci_clrsetbits(host, SDHC_TX_DLINE_REG_MASK,
+ FIELD_PREP(SDHC_TX_DLINE_REG_MASK, dline_reg),
+ SPACEMIT_SDHC_DLINE_CFG_REG);
+}
+
+static void spacemit_sdhci_tx_tuning_prepare(struct sdhci_host *host)
+{
+ spacemit_sdhci_setbits(host, SDHC_TX_MUX_SEL, SPACEMIT_SDHC_TX_CFG_REG);
+ spacemit_sdhci_setbits(host, SDHC_DLINE_PU, SPACEMIT_SDHC_DLINE_CTRL_REG);
+ udelay(5);
+}
+
+static void spacemit_sdhci_prepare_tuning(struct sdhci_host *host)
+{
+ spacemit_sdhci_clrsetbits(host, SDHC_RX_DLINE_REG_MASK,
+ FIELD_PREP(SDHC_RX_DLINE_REG_MASK, SPACEMIT_RX_DLINE_REG),
+ SPACEMIT_SDHC_DLINE_CFG_REG);
+
+ spacemit_sdhci_setbits(host, SDHC_DLINE_PU, SPACEMIT_SDHC_DLINE_CTRL_REG);
+ udelay(5);
+
+ spacemit_sdhci_clrsetbits(host, SDHC_RX_SDCLK_SEL1_MASK, SDHC_RX_SDCLK_SEL1,
+ SPACEMIT_SDHC_RX_CFG_REG);
+
+ if (host->mmc->ios.timing == MMC_TIMING_MMC_HS200)
+ spacemit_sdhci_setbits(host, SDHC_HS200_USE_RFIFO, SPACEMIT_SDHC_PHY_FUNC_REG);
+}
+
static void spacemit_sdhci_reset(struct sdhci_host *host, u8 mask)
{
sdhci_reset(host, mask);
@@ -191,6 +257,111 @@ static unsigned int spacemit_sdhci_clk_get_max_clock(struct sdhci_host *host)
return clk_get_rate(pltfm_host->clk);
}
+static int spacemit_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
+{
+ int current_len = 0, current_start = 0;
+ int max_pass_len = 0, max_pass_start = 0;
+ struct mmc_host *mmc = host->mmc;
+ struct mmc_ios ios = mmc->ios;
+ u8 final_delay;
+ int ret = 0;
+ int i;
+
+ /*
+ * Tuning is required for SDR50/SDR104, HS200/HS400 cards and
+ * if clock frequency is greater than 100MHz in these modes.
+ */
+ if (host->clock < 100 * 1000 * 1000 ||
+ !(ios.timing == MMC_TIMING_MMC_HS200 ||
+ ios.timing == MMC_TIMING_UHS_SDR50 ||
+ ios.timing == MMC_TIMING_UHS_SDR104))
+ return 0;
+
+ if (mmc->caps2 & MMC_CAP2_NO_MMC) {
+ spacemit_sdhci_set_tx_dline_reg(host, SPACEMIT_TX_TUNING_DLINE_REG);
+ spacemit_sdhci_set_tx_delay(host, SPACEMIT_TX_TUNING_DELAYCODE);
+ spacemit_sdhci_tx_tuning_prepare(host);
+
+ dev_dbg(mmc_dev(host->mmc), "TX tuning: dline_reg=%d, delaycode=%d\n",
+ SPACEMIT_TX_TUNING_DLINE_REG, SPACEMIT_TX_TUNING_DELAYCODE);
+ }
+
+ spacemit_sdhci_prepare_tuning(host);
+
+ for (i = SPACEMIT_RX_TUNE_DELAY_MIN; i <= SPACEMIT_RX_TUNE_DELAY_MAX; i++) {
+ spacemit_sdhci_set_rx_delay(host, i);
+ ret = mmc_send_tuning(host->mmc, opcode, NULL);
+
+ dev_dbg(mmc_dev(host->mmc), "RX delay %d: %s\n",
+ i, ret == 0 ? "pass" : "fail");
+
+ if (ret == 0) {
+ /* Test passed - extend current window */
+ if (current_len == 0)
+ current_start = i;
+ current_len++;
+ } else {
+ /* Test failed - check if current window is best so far */
+ if (current_len > max_pass_len) {
+ max_pass_len = current_len;
+ max_pass_start = current_start;
+ }
+ current_len = 0;
+ }
+ }
+
+ if (current_len > max_pass_len) {
+ max_pass_len = current_len;
+ max_pass_start = current_start;
+ }
+
+ if (max_pass_len < 3) {
+ dev_err(mmc_dev(host->mmc), "Tuning failed: no stable window found\n");
+ return -EIO;
+ }
+
+ final_delay = max_pass_start + max_pass_len / 2;
+ spacemit_sdhci_set_rx_delay(host, final_delay);
+ ret = mmc_send_tuning(host->mmc, opcode, NULL);
+ if (ret) {
+ u8 retry_delays[] = {
+ max_pass_start + max_pass_len / 4,
+ max_pass_start + (3 * max_pass_len) / 4,
+ max_pass_start,
+ max_pass_start + max_pass_len - 1
+ };
+ int retry_count = ARRAY_SIZE(retry_delays);
+
+ dev_warn(mmc_dev(mmc), "Primary delay %d failed, trying alternatives\n",
+ final_delay);
+
+ for (i = 0; i < retry_count; i++) {
+ if (retry_delays[i] >= SPACEMIT_RX_TUNE_DELAY_MIN &&
+ retry_delays[i] <= SPACEMIT_RX_TUNE_DELAY_MAX) {
+ spacemit_sdhci_set_rx_delay(host, retry_delays[i]);
+ ret = mmc_send_tuning(host->mmc, opcode, NULL);
+ if (!ret) {
+ final_delay = retry_delays[i];
+ dev_info(mmc_dev(mmc), "Retry successful with delay %d\n",
+ final_delay);
+ break;
+ }
+ }
+ }
+
+ if (ret) {
+ dev_err(mmc_dev(mmc), "All retry attempts failed\n");
+ return -EIO;
+ }
+ }
+
+ dev_dbg(mmc_dev(host->mmc),
+ "Tuning successful: window %d-%d, using delay %d\n",
+ max_pass_start, max_pass_start + max_pass_len - 1, final_delay);
+
+ return 0;
+}
+
static int spacemit_sdhci_pre_select_hs400(struct mmc_host *mmc)
{
struct sdhci_host *host = mmc_priv(mmc);
@@ -326,6 +497,7 @@ static const struct sdhci_ops spacemit_sdhci_ops = {
.set_bus_width = sdhci_set_bus_width,
.set_clock = spacemit_sdhci_set_clock,
.set_uhs_signaling = spacemit_sdhci_set_uhs_signaling,
+ .platform_execute_tuning = spacemit_sdhci_execute_tuning,
};
static const struct sdhci_pltfm_data spacemit_sdhci_k1_pdata = {
--
2.53.0
^ permalink raw reply related
* [PATCH v7 5/9] riscv: dts: spacemit: k1: add SD card controller and pinctrl support
From: Iker Pedrosa @ 2026-04-13 7:24 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Adrian Hunter, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Yixun Lan
Cc: Iker Pedrosa, Troy Mitchell, Michael Opdenacker,
Javier Martinez Canillas, linux-mmc, devicetree, linux-riscv,
spacemit, linux-kernel, Anand Moon, Trevor Gamblin,
Vincent Legoll
In-Reply-To: <20260413-orangepi-sd-card-uhs-v7-0-16650f49c022@gmail.com>
Add SD card controller infrastructure for SpacemiT K1 SoC with complete
pinctrl support for both standard and UHS modes.
- Add sdhci0 controller definition with clocks, resets and interrupts
- Add mmc1_cfg pinctrl for 3.3V standard SD operation
- Add mmc1_uhs_cfg pinctrl for 1.8V UHS high-speed operation
- Configure appropriate drive strength and power-source properties
This provides complete SD card infrastructure that K1-based boards can
enable.
Tested-by: Anand Moon <linux.amoon@gmail.com>
Tested-by: Trevor Gamblin <tgamblin@baylibre.com>
Tested-by: Vincent Legoll <legoll@online.fr>
Reviewed-by: Troy Mitchell <troy.mitchell@linux.dev>
Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
---
arch/riscv/boot/dts/spacemit/k1-pinctrl.dtsi | 40 ++++++++++++++++++++++++++++
arch/riscv/boot/dts/spacemit/k1.dtsi | 13 +++++++++
2 files changed, 53 insertions(+)
diff --git a/arch/riscv/boot/dts/spacemit/k1-pinctrl.dtsi b/arch/riscv/boot/dts/spacemit/k1-pinctrl.dtsi
index b13dcb10f4d6..b3c472a0783b 100644
--- a/arch/riscv/boot/dts/spacemit/k1-pinctrl.dtsi
+++ b/arch/riscv/boot/dts/spacemit/k1-pinctrl.dtsi
@@ -570,4 +570,44 @@ pwm14-1-pins {
drive-strength = <32>;
};
};
+
+ mmc1_cfg: mmc1-cfg {
+ mmc1-data-cmd-pins {
+ pinmux = <K1_PADCONF(104, 0)>, /* mmc1_d3 */
+ <K1_PADCONF(105, 0)>, /* mmc1_d2 */
+ <K1_PADCONF(106, 0)>, /* mmc1_d1 */
+ <K1_PADCONF(107, 0)>, /* mmc1_d0 */
+ <K1_PADCONF(108, 0)>; /* mmc1_cmd */
+ bias-pull-up = <1>;
+ drive-strength = <19>;
+ power-source = <3300>;
+ };
+
+ mmc1-clk-pins {
+ pinmux = <K1_PADCONF(109, 0)>; /* mmc1_clk */
+ bias-pull-down = <1>;
+ drive-strength = <19>;
+ power-source = <3300>;
+ };
+ };
+
+ mmc1_uhs_cfg: mmc1-uhs-cfg {
+ mmc1-data-cmd-pins {
+ pinmux = <K1_PADCONF(104, 0)>, /* mmc1_d3 */
+ <K1_PADCONF(105, 0)>, /* mmc1_d2 */
+ <K1_PADCONF(106, 0)>, /* mmc1_d1 */
+ <K1_PADCONF(107, 0)>, /* mmc1_d0 */
+ <K1_PADCONF(108, 0)>; /* mmc1_cmd */
+ bias-pull-up = <1>;
+ drive-strength = <42>;
+ power-source = <1800>;
+ };
+
+ mmc1-clk-pins {
+ pinmux = <K1_PADCONF(109, 0)>; /* mmc1_clk */
+ bias-pull-down = <1>;
+ drive-strength = <42>;
+ power-source = <1800>;
+ };
+ };
};
diff --git a/arch/riscv/boot/dts/spacemit/k1.dtsi b/arch/riscv/boot/dts/spacemit/k1.dtsi
index f0bad6855c97..28949f804610 100644
--- a/arch/riscv/boot/dts/spacemit/k1.dtsi
+++ b/arch/riscv/boot/dts/spacemit/k1.dtsi
@@ -1211,6 +1211,19 @@ emmc: mmc@d4281000 {
interrupts = <101>;
status = "disabled";
};
+
+ sdhci0: mmc@d4280000 {
+ compatible = "spacemit,k1-sdhci";
+ reg = <0x0 0xd4280000 0x0 0x200>;
+ clocks = <&syscon_apmu CLK_SDH_AXI>,
+ <&syscon_apmu CLK_SDH0>;
+ clock-names = "core", "io";
+ resets = <&syscon_apmu RESET_SDH_AXI>,
+ <&syscon_apmu RESET_SDH0>;
+ reset-names = "axi", "sdh";
+ interrupts = <99>;
+ status = "disabled";
+ };
};
};
};
--
2.53.0
^ permalink raw reply related
* [PATCH v7 6/9] riscv: dts: spacemit: k1-orangepi-rv2: add PMIC and power infrastructure
From: Iker Pedrosa @ 2026-04-13 7:24 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Adrian Hunter, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Yixun Lan
Cc: Iker Pedrosa, Troy Mitchell, Michael Opdenacker,
Javier Martinez Canillas, linux-mmc, devicetree, linux-riscv,
spacemit, linux-kernel, Anand Moon, Trevor Gamblin,
Vincent Legoll
In-Reply-To: <20260413-orangepi-sd-card-uhs-v7-0-16650f49c022@gmail.com>
Add Spacemit P1 PMIC configuration and board power infrastructure for
voltage regulation support.
- Add board power regulators (5V input, 4V rail)
- Enable I2C8 for PMIC communication
- Configure PMIC with buck4 (vmmc) and aldo1 (vqmmc) regulators
- Set up regulator constraints for SD card operation
Tested-by: Anand Moon <linux.amoon@gmail.com>
Tested-by: Trevor Gamblin <tgamblin@baylibre.com>
Tested-by: Vincent Legoll <legoll@online.fr>
Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
---
arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts | 48 ++++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
index 7b7331cb3c72..9c417a483f6b 100644
--- a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
+++ b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
@@ -19,6 +19,25 @@ aliases {
ethernet1 = ð1;
};
+ reg_dc_in: dc-in-5v {
+ compatible = "regulator-fixed";
+ regulator-name = "dc_in_5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ reg_vcc_4v: vcc-4v {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_4v";
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <4000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ vin-supply = <®_dc_in>;
+ };
+
chosen {
stdout-path = "serial0";
};
@@ -92,3 +111,32 @@ &uart0 {
pinctrl-0 = <&uart0_2_cfg>;
status = "okay";
};
+
+&i2c8 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c8_cfg>;
+ status = "okay";
+
+ pmic@41 {
+ compatible = "spacemit,p1";
+ reg = <0x41>;
+ interrupts = <64>;
+ vin-supply = <®_vcc_4v>;
+
+ regulators {
+ buck4: buck4 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <5000>;
+ regulator-always-on;
+ };
+
+ aldo1: aldo1 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+ };
+};
--
2.53.0
^ permalink raw reply related
* [PATCH v7 7/9] riscv: dts: spacemit: k1-orangepi-rv2: add SD card support with UHS modes
From: Iker Pedrosa @ 2026-04-13 7:24 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Adrian Hunter, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Yixun Lan
Cc: Iker Pedrosa, Troy Mitchell, Michael Opdenacker,
Javier Martinez Canillas, linux-mmc, devicetree, linux-riscv,
spacemit, linux-kernel, Anand Moon, Trevor Gamblin,
Vincent Legoll
In-Reply-To: <20260413-orangepi-sd-card-uhs-v7-0-16650f49c022@gmail.com>
Add complete SD card controller support with UHS high-speed modes.
- Enable sdhci0 controller with 4-bit bus width
- Configure card detect GPIO with inversion
- Connect vmmc-supply to buck4 for 3.3V card power
- Connect vqmmc-supply to aldo1 for 1.8V/3.3V I/O switching
- Add dual pinctrl states for voltage-dependent pin configuration
- Support UHS-I SDR25, SDR50, and SDR104 modes
This enables full SD card functionality including high-speed UHS modes
for improved performance.
Tested-by: Anand Moon <linux.amoon@gmail.com>
Tested-by: Trevor Gamblin <tgamblin@baylibre.com>
Tested-by: Michael Opdenacker <michael.opdenacker@rootcommit.com>
Tested-by: Vincent Legoll <legoll@online.fr>
Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
---
arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
index 9c417a483f6b..95cfb4681ced 100644
--- a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
+++ b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
@@ -140,3 +140,22 @@ aldo1: aldo1 {
};
};
};
+
+&sdhci0 {
+ pinctrl-names = "default", "uhs";
+ pinctrl-0 = <&mmc1_cfg>;
+ pinctrl-1 = <&mmc1_uhs_cfg>;
+ bus-width = <4>;
+ cd-gpios = <&gpio K1_GPIO(80) GPIO_ACTIVE_HIGH>;
+ cd-inverted;
+ no-mmc;
+ no-sdio;
+ disable-wp;
+ cap-sd-highspeed;
+ vmmc-supply = <&buck4>;
+ vqmmc-supply = <&aldo1>;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ status = "okay";
+};
--
2.53.0
^ permalink raw reply related
* [PATCH v7 8/9] riscv: dts: spacemit: k1-bananapi-f3: add SD card support with UHS modes
From: Iker Pedrosa @ 2026-04-13 7:24 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Adrian Hunter, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Yixun Lan
Cc: Iker Pedrosa, Troy Mitchell, Michael Opdenacker,
Javier Martinez Canillas, linux-mmc, devicetree, linux-riscv,
spacemit, linux-kernel, Anand Moon
In-Reply-To: <20260413-orangepi-sd-card-uhs-v7-0-16650f49c022@gmail.com>
Add complete SD card controller support with UHS high-speed modes.
- Enable sdhci0 controller with 4-bit bus width
- Configure card detect GPIO with inversion
- Connect vmmc-supply to buck4 for 3.3V card power
- Connect vqmmc-supply to aldo1 for 1.8V/3.3V I/O switching
- Add dual pinctrl states for voltage-dependent pin configuration
- Support UHS-I SDR25, SDR50, and SDR104 modes
This enables full SD card functionality including high-speed UHS modes
for improved performance.
Suggested-by: Anand Moon <linux.amoon@gmail.com>
Tested-by: Anand Moon <linux.amoon@gmail.com>
Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
---
arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts | 24 ++++++++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts b/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts
index 5790d927b93d..a7d88564630f 100644
--- a/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts
+++ b/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts
@@ -220,7 +220,7 @@ buck3_1v8: buck3 {
regulator-always-on;
};
- buck4 {
+ buck4: buck4 {
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <3300000>;
regulator-ramp-delay = <5000>;
@@ -241,7 +241,7 @@ buck6 {
regulator-always-on;
};
- aldo1 {
+ aldo1: aldo1 {
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <3400000>;
regulator-boot-on;
@@ -367,3 +367,23 @@ hub_3_0: hub@2 {
reset-gpios = <&gpio K1_GPIO(124) GPIO_ACTIVE_LOW>;
};
};
+
+&sdhci0 {
+ pinctrl-names = "default", "uhs";
+ pinctrl-0 = <&mmc1_cfg>;
+ pinctrl-1 = <&mmc1_uhs_cfg>;
+ bus-width = <4>;
+ cd-gpios = <&gpio K1_GPIO(80) GPIO_ACTIVE_HIGH>;
+ cd-inverted;
+ broken-cd;
+ no-mmc;
+ no-sdio;
+ disable-wp;
+ cap-sd-highspeed;
+ vmmc-supply = <&buck4>;
+ vqmmc-supply = <&aldo1>;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ status = "okay";
+};
--
2.53.0
^ permalink raw reply related
* [PATCH v7 9/9] riscv: dts: spacemit: k1-musepi-pro: add SD card support with UHS modes
From: Iker Pedrosa @ 2026-04-13 7:24 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Adrian Hunter, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Yixun Lan
Cc: Iker Pedrosa, Troy Mitchell, Michael Opdenacker,
Javier Martinez Canillas, linux-mmc, devicetree, linux-riscv,
spacemit, linux-kernel, Trevor Gamblin
In-Reply-To: <20260413-orangepi-sd-card-uhs-v7-0-16650f49c022@gmail.com>
From: Trevor Gamblin <tgamblin@baylibre.com>
Update the Muse Pi Pro devicetree with SD card support to match what
was done for the OrangePi RV2 in [1]. More precisely:
- Enable sdhci0 controller with 4-bit bus width
- Configure card detect GPIO with inversion
- Connect vmmc-supply to buck4 for 3.3V card power
- Connect vqmmc-supply to aldo1 for 1.8V/3.3V I/O switching
- Add dual pinctrl states for voltage-dependent pin configuration
- Support UHS-I SDR25, SDR50, and SDR104 modes
[1] https://lore.kernel.org/linux-riscv/20260316-orangepi-sd-card-uhs-v3-0-aefd3b7832df@gmail.com/T/#
Signed-off-by: Trevor Gamblin <tgamblin@baylibre.com>
Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
---
arch/riscv/boot/dts/spacemit/k1-musepi-pro.dts | 66 ++++++++++++++++++++++++++
1 file changed, 66 insertions(+)
diff --git a/arch/riscv/boot/dts/spacemit/k1-musepi-pro.dts b/arch/riscv/boot/dts/spacemit/k1-musepi-pro.dts
index 29e333b670cf..774a4640f065 100644
--- a/arch/riscv/boot/dts/spacemit/k1-musepi-pro.dts
+++ b/arch/riscv/boot/dts/spacemit/k1-musepi-pro.dts
@@ -18,6 +18,24 @@ aliases {
ethernet0 = ð0;
serial0 = &uart0;
};
+ reg_dc_in: dc-in-5v {
+ compatible = "regulator-fixed";
+ regulator-name = "dc_in_5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ reg_vcc_4v: vcc-4v {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_4v";
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <4000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
chosen {
stdout-path = "serial0";
@@ -77,3 +95,51 @@ &uart0 {
pinctrl-names = "default";
status = "okay";
};
+
+&i2c8 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c8_cfg>;
+ status = "okay";
+
+ pmic@41 {
+ compatible = "spacemit,p1";
+ reg = <0x41>;
+ interrupts = <64>;
+ vin-supply = <®_vcc_4v>;
+
+ regulators {
+ buck4: buck4 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <5000>;
+ regulator-always-on;
+ };
+
+ aldo1: aldo1 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&sdhci0 {
+ pinctrl-names = "default", "uhs";
+ pinctrl-0 = <&mmc1_cfg>;
+ pinctrl-1 = <&mmc1_uhs_cfg>;
+ bus-width = <4>;
+ cd-gpios = <&gpio K1_GPIO(80) GPIO_ACTIVE_HIGH>;
+ cd-inverted;
+ no-mmc;
+ no-sdio;
+ disable-wp;
+ cap-sd-highspeed;
+ vmmc-supply = <&buck4>;
+ vqmmc-supply = <&aldo1>;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ status = "okay";
+};
--
2.53.0
^ permalink raw reply related
* Re: [PATCH v7 2/2] iio: dac: ad5706r: Add support for AD5706R DAC
From: Andy Shevchenko @ 2026-04-13 7:44 UTC (permalink / raw)
To: Torreno, Alexis Czezar
Cc: David Lechner, Lars-Peter Clausen, Hennerich, Michael,
Jonathan Cameron, Sa, Nuno, Andy Shevchenko, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-iio@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
Andy Shevchenko
In-Reply-To: <PH0PR03MB63515AAF92A4F2B6F7C26E70F1242@PH0PR03MB6351.namprd03.prod.outlook.com>
On Mon, Apr 13, 2026 at 10:16 AM Torreno, Alexis Czezar
<AlexisCzezar.Torreno@analog.com> wrote:
...
> > > + /* Extract value from response (skip 2-byte command echo) */
> > > + if (num_bytes == AD5706R_SINGLE_BYTE_LEN)
> > > + val = st->rx_buf[2];
> > > + else if (num_bytes == AD5706R_DOUBLE_BYTE_LEN)
> > > + val = get_unaligned_be16(&st->rx_buf[2]);
> > > + else
> > > + return -EINVAL;
> > > +
> > > + put_unaligned_be16(val, val_buf);
> >
> > Can't this all be simplified to memcpy(val_buf, &st->rx_buf[2], num_bytes); ?
Also note, num_bytes still needs validation.
> > Or the whole thing simplified to:
> >
> > return spi_write_then_read(st->spi, reg_buf, 2, val_buf, num_bytes);
>
> as discussed above about mem* and spi_write_then_read
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH 3/3] arm64: dts: qcom: eliza-mtp: Enable USB and ADSP support
From: Alexander Koskovich @ 2026-04-13 7:52 UTC (permalink / raw)
To: Abel Vesa
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, linux-arm-msm, devicetree, linux-kernel
On Tue, Mar 31, 2026 at 01:37:24PM +0300, Abel Vesa wrote:
> The Eliza MTP features a single USB Type-C port. Its USB 2.0 lines are
> routed through an eUSB2 repeater provided by the PM7750BA PMIC.
>
> Describe the port and repeater, and enable the USB controller and PHYs.
>
> Also specify the ADSP firmware and enable the remoteproc.
>
> Signed-off-by: Abel Vesa <abel.vesa@oss.qualcomm.com>
> ---
> arch/arm64/boot/dts/qcom/eliza-mtp.dts | 83 ++++++++++++++++++++++++++++++++++
> 1 file changed, 83 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/qcom/eliza-mtp.dts b/arch/arm64/boot/dts/qcom/eliza-mtp.dts
> index 90f629800cb0..c31f00e36eee 100644
> --- a/arch/arm64/boot/dts/qcom/eliza-mtp.dts
> +++ b/arch/arm64/boot/dts/qcom/eliza-mtp.dts
> @@ -6,9 +6,12 @@
> /dts-v1/;
...
>
> +&usb_hsphy {
> + vdd-supply = <&vreg_l2b>;
Shouldn't this be l7k? Looking at kera-usb.dtsi I see the vdd-supply for
eusb2_phy0 as l7k. I don't see this being overriden by anything else
downstream either.
Just bringing it up since I copied this part for another Eliza platform
(USB 2 only) and USB failed until I fixed this supply.
> + vdda12-supply = <&vreg_l4b>;
> +
> + phys = <&pm7550ba_eusb2_repeater>;
> +
> + status = "okay";
> +};
>
> --
> 2.48.1
>
^ permalink raw reply
* Re: [PATCH v7 0/2] i2c: Add Loongson-2K0300 I2C controller support
From: Andy Shevchenko @ 2026-04-13 7:52 UTC (permalink / raw)
To: Binbin Zhou
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Wolfram Sang, Andy Shevchenko,
linux-i2c, Huacai Chen, Xuerui Wang, loongarch, devicetree
In-Reply-To: <cover.1775900045.git.zhoubinbin@loongson.cn>
On Sat, Apr 11, 2026 at 12:58 PM Binbin Zhou <zhoubinbin@loongson.cn> wrote:
> This patch set describes the I2C controller integrated the
> Loongson-2K0300 chip.
>
> It has a significantly different design from the previous I2C
> controller(i2c-ls2x), such as support for master-slave transfer mode,
> and DMA transfers (implementation in progress), etc. Therefore, we try
> to name it i2c-ls2x-v2.
...
> - parent_rate_MHz -> parent_rate_mhz to avoid CamelCase.
Was it a special requirement from maintainers?
Note, the physical units are special. The m and M have quite a
different multiplier value. So, even if asked by somebody I think it's
still arguably should be kept as MHz.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v7 0/8] Add support for handling PCIe M.2 Key E connectors in devicetree
From: Chen-Yu Tsai @ 2026-04-13 7:54 UTC (permalink / raw)
To: Manivannan Sadhasivam
Cc: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Nathan Chancellor,
Nicolas Schier, Hans de Goede, Ilpo Järvinen, Mark Pearson,
Derek J. Clark, Manivannan Sadhasivam, Krzysztof Kozlowski,
Conor Dooley, Marcel Holtmann, Luiz Augusto von Dentz,
Bartosz Golaszewski, Andy Shevchenko, Bartosz Golaszewski,
linux-serial, linux-kernel, linux-kbuild, platform-driver-x86,
linux-pci, devicetree, linux-arm-msm, linux-bluetooth, linux-pm,
Stephan Gerhold, Dmitry Baryshkov, linux-acpi, Hans de Goede,
Bartosz Golaszewski
In-Reply-To: <20260326-pci-m2-e-v7-0-43324a7866e6@oss.qualcomm.com>
Hi,
On Thu, Mar 26, 2026 at 01:36:28PM +0530, Manivannan Sadhasivam wrote:
> Hi,
>
> This series is the continuation of the series [1] that added the initial support
> for the PCIe M.2 connectors. This series extends it by adding support for Key E
> connectors. These connectors are used to connect the Wireless Connectivity
> devices such as WiFi, BT, NFC and GNSS devices to the host machine over
> interfaces such as PCIe/SDIO, USB/UART and NFC. This series adds support for
> connectors that expose PCIe interface for WiFi and UART interface for BT. Other
> interfaces are left for future improvements.
Thanks for working on this. I started playing with it now that it is in
-next. The PCIe part works fine. I'm looking into how to fit the pwrseq
A couple questions:
- Given that this connector actually represents two devices, how do I
say I want the BT part to be a wakeup source, but not the WiFi part?
Does wakeup-source even work at this point?
- Are there plans to do the SDIO part?
- The matching done in the M.2 connector driver for pwrseq_get() seems a
bit naive. It simply checks if the remote device in the OF graph is
the same as the requesting device.
I think this would run into issues with USB hubs. If I have a USB hub
and two M.2 connectors, with both connectors connected to the same
hub, pwrseq_get() is going to always return only one of the instances.
This is because the USB hub has one device node with multiple OF graph
ports.
Thanks
ChenYu
> Serdev device support for BT
> ============================
>
> Adding support for the PCIe interface was mostly straightforward and a lot
> similar to the previous Key M connector. But adding UART interface has proved to
> be tricky. This is mostly because of the fact UART is a non-discoverable bus,
> unlike PCIe which is discoverable. So this series relied on the PCI notifier to
> create the serdev device for UART/BT. This means the PCIe interface will be
> brought up first and after the PCIe device enumeration, the serdev device will
> be created by the pwrseq driver. This logic is necessary since the connector
> driver and DT node don't describe the device, but just the connector. So to make
> the connector interface Plug and Play, the connector driver uses the PCIe device
> ID to identify the card and creates the serdev device. This logic could be
> extended in the future to support more M.2 cards. Even if the M.2 card uses SDIO
> interface for connecting WLAN, a SDIO notifier could be added to create the
> serdev device.
>
> Testing
> =======
>
> This series, together with the devicetree changes [2] was tested on the
> Qualcomm X1e based Lenovo Thinkpad T14s Laptop which has the WCN7850 WLAN/BT
> 1620 LGA card connected over PCIe and UART.
>
> Merge Strategy
> ==============
>
> Due to the API dependency, both the serdev and pwrseq patches need to go through
> a single tree, maybe through pwrseq tree. So the serdev patches need Ack from
> Greg. But Bluetooth patch can be merged separately.
>
> NOTE
> ====
>
> This series is based on bluetooth-next/master to resolve the conflict with the
> Bluetooth patch. Other pathces should apply cleanly on top of v7.0-rc1.
>
> [1] https://lore.kernel.org/linux-pci/20260107-pci-m2-v5-0-8173d8a72641@oss.qualcomm.com
> [2] https://github.com/Mani-Sadhasivam/linux/commit/b50f8386900990eed3dce8d91c3b643fb0e8739d
>
> Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
> ---
> Changes in v7:
> - Dropped the LGA binding change due to vendor prefix concern. This will be
> submitted later once I get clarity.
> - Fixed several issues in the cleanup path of the pwrseq-pci-m2 driver which
> includes adding the .remove() callback.
> - Rebased on top of bluetooth-next/master to resolve conflict with bluetooth
> patch.
> - Link to v6: https://lore.kernel.org/r/20260317-pci-m2-e-v6-0-9c898f108d3d@oss.qualcomm.com
>
> Changes in v6:
> - Added a check to bail out if the serdev device was already added during notifier.
> - Collected tags
> - Link to v5: https://lore.kernel.org/r/20260224-pci-m2-e-v5-0-dd9b9501d33c@oss.qualcomm.com
>
> Changes in v5:
> - Incorporated comments in the binding patch by using single endpoint per port,
> reordering port nodes, adding missing properties and using a complete example.
> - Incorporated comments in the pwrseq patch (nothing major)
> - Fixed the build issue in patch 2
> - Collected tags
> - Rebased on top of 7.0-rc1
> - Link to v4: https://lore.kernel.org/r/20260112-pci-m2-e-v4-0-eff84d2c6d26@oss.qualcomm.com
>
> Changes in v4:
> - Switched to dynamic OF node for serdev instead of swnode and dropped all
> swnode related patches
> - Link to v3: https://lore.kernel.org/r/20260110-pci-m2-e-v3-0-4faee7d0d5ae@oss.qualcomm.com
>
> Changes in v3:
> - Switched to swnode for the serdev device and dropped the custom
> serdev_device_id related patches
> - Added new swnode APIs to match the swnode with existing of_device_id
> - Incorporated comments in the bindings patch
> - Dropped the UIM interface from binding since it is not clear how it should get
> wired
> - Incorporated comments in the pwrseq driver patch
> - Splitted the pwrseq patch into two
> - Added the 1620 LGA compatible with Key E fallback based on Stephan's finding
> - Link to v2: https://lore.kernel.org/r/20251125-pci-m2-e-v2-0-32826de07cc5@oss.qualcomm.com
>
> Changes in v2:
> - Used '-' for GPIO names in the binding and removed led*-gpios properties
> - Described the endpoint nodes for port@0 and port@1 nodes
> - Added the OF graph port to the serial binding
> - Fixed the hci_qca driver to return err if devm_pwrseq_get() fails
> - Incorporated various review comments in pwrseq driver
> - Collected Ack
> - Link to v1: https://lore.kernel.org/r/20251112-pci-m2-e-v1-0-97413d6bf824@oss.qualcomm.com
>
> ---
> Manivannan Sadhasivam (8):
> serdev: Convert to_serdev_*() helpers to macros and use container_of_const()
> serdev: Add an API to find the serdev controller associated with the devicetree node
> serdev: Do not return -ENODEV from of_serdev_register_devices() if external connector is used
> dt-bindings: serial: Document the graph port
> dt-bindings: connector: Add PCIe M.2 Mechanical Key E connector
> Bluetooth: hci_qca: Add M.2 Bluetooth device support using pwrseq
> power: sequencing: pcie-m2: Add support for PCIe M.2 Key E connectors
> power: sequencing: pcie-m2: Create serdev device for WCN7850 bluetooth
>
> .../bindings/connector/pcie-m2-e-connector.yaml | 184 +++++++++++
> .../devicetree/bindings/serial/serial.yaml | 3 +
> MAINTAINERS | 1 +
> drivers/bluetooth/hci_qca.c | 9 +
> drivers/power/sequencing/Kconfig | 3 +-
> drivers/power/sequencing/pwrseq-pcie-m2.c | 346 ++++++++++++++++++++-
> drivers/tty/serdev/core.c | 28 +-
> include/linux/serdev.h | 24 +-
> 8 files changed, 570 insertions(+), 28 deletions(-)
> ---
> base-commit: 559f264e403e4d58d56a17595c60a1de011c5e20
> change-id: 20251112-pci-m2-e-94695ac9d657
>
> Best regards,
> --
> Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
>
^ permalink raw reply
* Re: Phandles
From: Krzysztof Kozlowski @ 2026-04-13 7:55 UTC (permalink / raw)
To: Kyle Bonnici
Cc: Herve Codina, devicetree-compiler@vger.kernel.org, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, devicetree@vger.kernel.org
In-Reply-To: <7F2DF84C-A010-4BCB-B973-D17BF58EDCF2@hotmail.com>
On 13/04/2026 09:10, Kyle Bonnici wrote:
>
>
>> On 13 Apr 2026, at 08:37, Krzysztof Kozlowski <krzk@kernel.org> wrote:
>>
>> On 12/04/2026 18:37, Kyle Bonnici wrote:
>>>>>> Case 1:
>>>>>> / {
>>>>>> node1 {
>>>>>> pwms = <1 &pwm0 1 20 PWM_POLARITY_NORMAL>;
>>>>>>
>>>>>> Here the first cell '1' is not a phandle.
>>>>>
>>>>> Here the compiler is making an assumption here that all `pwms` properties must be specifier properties and all use `pwm` specifier.
>>>>
>>>> I think the purpose of 'select: true' is to have the binding always applied:
>>>> https://github.com/devicetree-org/dt-schema/blob/main/dtschema/schemas/pwm/pwm-consumer.yaml#L15
>>>>
>>>
>>>
>>> I’m having trouble finding where the Devicetree Specification (v0.4) mandates that all binding systems must extend dt-schema.
>>> Since this requirement isn't explicitly in the spec, it follows that the WARNING_PROPERTY_PHANDLE_CELLS validation belongs in dt-validate rather than within dtc itself.
>>
>>
>> So you want to have a property with values not being phandle? The spec
>> defines that properties like "pwm" must contain "value of properties
>> with a phandle value type". Therefore what does '1' represents in your
>> example?
>
> I am just building and maintaining an LSP to assists Zephyr and Linux developers alike and what is technically
> allowed in Zephyr is not allowed in Linux. The issue here is that DTC is warning zephyr users about it.
Please wrap your email responses to mailing list style.
> I also find my self in the wrong to enforce these types for Zephyr dts usage given all documentation I have seen
> so far.
To repeat my question:
What does '1' stand for?
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH v8 0/9] riscv: spacemit: enable SD card support with UHS modes for OrangePi RV2
From: Iker Pedrosa @ 2026-04-13 8:02 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Adrian Hunter, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Yixun Lan, Yixun Lan
Cc: Troy Mitchell, Michael Opdenacker, Javier Martinez Canillas,
linux-mmc, devicetree, linux-riscv, spacemit, linux-kernel,
Iker Pedrosa, Anand Moon, Trevor Gamblin, Vincent Legoll
This series enables complete SD card support for the Spacemit K1-based
OrangePi RV2 board, including UHS (Ultra High Speed) modes for
high-performance SD card operation.
Background
The Spacemit K1 SoC includes an SDHCI controller capable of supporting
SD cards up to UHS-I speeds (SDR104 at 208MHz). However, mainline
currently lacks basic SD controller configuration, SDHCI driver
enhancements for voltage switching and tuning, and power management
infrastructure.
Implementation
The series enables SD card support through coordinated layers:
- Hardware infrastructure (patches 1-2): Device tree bindings for voltage
switching hardware and essential clock infrastructure.
- SDHCI driver enhancements (patches 3-7): Regulator framework
integration, pinctrl state switching for voltage domains, AIB register
programming, and comprehensive SDR tuning support for reliable UHS
operation.
- SoC and board integration (patches 8-10): Complete K1 SoC controller
definitions, PMIC power infrastructure, and OrangePi RV2 board enablement
with full UHS support.
This transforms the OrangePi RV2 from having no SD card support to full
UHS-I capability, enabling high-performance storage up to 208MHz.
Tested-by: Michael Opdenacker <michael.opdenacker@rootcommit.com>
Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
---
Changes in v8:
- Resending the series as v8. The v7 submission failed due to an SMTP
error during transit, which resulted in a broken thread on the mailing
list.
- No functional changes from v7.
- Link to v7: https://lore.kernel.org/r/20260413-orangepi-sd-card-uhs-v7-1-16650f49c022@gmail.com
Changes in v7:
- Remove sdhci-common.yaml reference from DT binding.
- Link to v6: https://lore.kernel.org/r/20260407-orangepi-sd-card-uhs-v6-0-b5b8a1b2bfc8@gmail.com
Changes in v6:
- Add pinctrl support for voltage switching. Document optional
pinctrl-names property supporting "default" and "uhs" pinctrl states
for coordinating pin configuration changes during UHS-I voltage
switching.
- Update pinctrl state naming from "state_uhs" to "uhs" to match DT
binding naming convention.
- Fix MMC drive strength values based on vendor kernel investigation.
Correct 3.3V operation from 7mA to 19mA and 1.8V UHS operation from
13mA to 42mA to match proven vendor implementation.
- Link to v5: https://lore.kernel.org/r/20260330-orangepi-sd-card-uhs-v5-0-bd853604322d@gmail.com
Changes in v5:
- Document optional pinctrl-names property supporting "default" and
"state_uhs" pinctrl states for coordinating pin configuration changes
during UHS-I voltage switching.
- Link to v4: https://lore.kernel.org/r/20260323-orangepi-sd-card-uhs-v4-0-567c9775fd0e@gmail.com
Changes in v4:
- Revert to start_signal_voltage_switch() approach for bidirectional
voltage switching: replace voltage_switch() callback with
start_signal_voltage_switch() to properly handle both 3.3V and 1.8V
signal voltage directions.
- Fix DC input voltage specification: corrected the main power supply
from 12V to 5V to match the OrangePi RV2 board specifications. The
board uses a 5V USB-C input connector, not a 12V rail as previously
specified in the device tree.
- k1-bananapi-f3.dts: add `broken-cd` property to work around card
detection. Using `broken-cd` disables hotplug detection but keeps SD
card functionality working without additional dependencies.
- Add SD card support for Muse Pi Pro board (contributed by Trevor
Gamblin): enable SD card support with UHS-I capabilities following the
same pattern as OrangePi RV2, including dual pinctrl states, PMIC
power supplies, and card detection.
- Link to v3: https://lore.kernel.org/r/20260316-orangepi-sd-card-uhs-v3-0-aefd3b7832df@gmail.com
Changes in v3:
- Rebase on mmc.git/next to resolve conflicts with "mmc: sdhci-of-k1:
add reset support" patch.
- Squash tuning infrastructure and implementation patches (3 and 4)
together to form complete functionality and avoid unused function
warnings.
- Reduce code nesting: implemented an early return sanity check in
spacemit_sdhci_voltage_switch() to reduce indentation and improve
logic flow.
- Refactor pinctrl initialization: moved pinctrl resource acquisition
and state lookup into a dedicated helper function,
spacemit_sdhci_get_pins().
- Use generic regulator node names (buck4, aldo1) instead of
device-specific aliases (sd_vmmc, sd_vqmmc) to better reflect that
these PMIC outputs serve multiple devices.
- Remove dead code handling 3.3V voltage switching from
spacemit_sdhci_voltage_switch().
- Optimize tuning algorithm to use single-pass window detection instead
of storing results in array, reducing memory usage and complexity.
- Remove unnecessary card detect check in execute_tuning() - rely on MMC
core.
- Clarify commit message to mention both SD (UHS-I) and eMMC (HS200)
tuning support.
- Add SD card support for Banana Pi BPI-F3 board with UHS-I capabilities
following the same pattern as OrangePi RV2.
- Link to v2: https://lore.kernel.org/r/20260309-orangepi-sd-card-uhs-v2-0-5bb2b574df5d@gmail.com
Changes in v2:
- Removed custom AIB voltage switching code per maintainer feedback. The
existing pinctrl driver already handles AIB voltage switching
automatically via power-source property changes during UHS mode
transitions. This eliminates code duplication.
- Squashed regulator and pinctrl commits into single voltage switching
implementation.
- Moved voltage switching callback from dynamic probe assignment to
static sdhci_ops declaration. Removed redundant SDHCI core call since
the framework handles standard voltage switching automatically.
- Made clock override (SDHC_OVRRD_CLK_OEN | SDHC_FORCE_CLK_ON)
conditional for SD/SDIO cards only. This follows vendor driver pattern
of differentiating SD and eMMC card handling.
- Include no-mmc property for SD card.
- Link to v1: https://lore.kernel.org/r/20260302-orangepi-sd-card-uhs-v1-0-89c219973c0c@gmail.com
---
Iker Pedrosa (8):
dt-bindings: mmc: spacemit,sdhci: add pinctrl support for voltage switching
mmc: sdhci-of-k1: enable essential clock infrastructure for SD operation
mmc: sdhci-of-k1: add regulator and pinctrl voltage switching support
mmc: sdhci-of-k1: add comprehensive SDR tuning support
riscv: dts: spacemit: k1: add SD card controller and pinctrl support
riscv: dts: spacemit: k1-orangepi-rv2: add PMIC and power infrastructure
riscv: dts: spacemit: k1-orangepi-rv2: add SD card support with UHS modes
riscv: dts: spacemit: k1-bananapi-f3: add SD card support with UHS modes
Trevor Gamblin (1):
riscv: dts: spacemit: k1-musepi-pro: add SD card support with UHS modes
.../devicetree/bindings/mmc/spacemit,sdhci.yaml | 15 ++
arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts | 24 +-
arch/riscv/boot/dts/spacemit/k1-musepi-pro.dts | 66 ++++++
arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts | 67 ++++++
arch/riscv/boot/dts/spacemit/k1-pinctrl.dtsi | 40 ++++
arch/riscv/boot/dts/spacemit/k1.dtsi | 13 ++
drivers/mmc/host/sdhci-of-k1.c | 257 +++++++++++++++++++++
7 files changed, 480 insertions(+), 2 deletions(-)
---
base-commit: 4c3b07bf68391122266dfb01126484daf352cf70
change-id: 20260226-orangepi-sd-card-uhs-0ecb05839b0c
Best regards,
--
Iker Pedrosa <ikerpedrosam@gmail.com>
^ permalink raw reply
* [PATCH v8 1/9] dt-bindings: mmc: spacemit,sdhci: add pinctrl support for voltage switching
From: Iker Pedrosa @ 2026-04-13 8:02 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Adrian Hunter, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Yixun Lan, Yixun Lan
Cc: Troy Mitchell, Michael Opdenacker, Javier Martinez Canillas,
linux-mmc, devicetree, linux-riscv, spacemit, linux-kernel,
Iker Pedrosa
In-Reply-To: <20260413-orangepi-sd-card-uhs-v8-0-c21c40ec16d0@gmail.com>
Document pinctrl properties to support voltage-dependent pin
configuration switching for UHS-I SD card modes.
Add optional pinctrl-names property with two states:
- "default": For 3.3V operation with standard drive strength
- "state_uhs": For 1.8V operation with optimized drive strength
These pinctrl states allow the SDHCI driver to coordinate voltage
switching with pin configuration changes, ensuring proper signal
integrity during UHS-I mode transitions.
Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
---
Documentation/devicetree/bindings/mmc/spacemit,sdhci.yaml | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/Documentation/devicetree/bindings/mmc/spacemit,sdhci.yaml b/Documentation/devicetree/bindings/mmc/spacemit,sdhci.yaml
index 9a055d963a7f..34d202af909f 100644
--- a/Documentation/devicetree/bindings/mmc/spacemit,sdhci.yaml
+++ b/Documentation/devicetree/bindings/mmc/spacemit,sdhci.yaml
@@ -44,6 +44,18 @@ properties:
- const: axi
- const: sdh
+ pinctrl-names:
+ minItems: 1
+ items:
+ - const: default
+ - const: uhs
+
+ pinctrl-0:
+ description: Default pinctrl state for 3.3V operation
+
+ pinctrl-1:
+ description: Optional pinctrl state for 1.8V UHS operation with "uhs" name
+
required:
- compatible
- reg
@@ -62,4 +74,7 @@ examples:
interrupt-parent = <&plic>;
clocks = <&clk_apmu 10>, <&clk_apmu 13>;
clock-names = "core", "io";
+ pinctrl-names = "default", "uhs";
+ pinctrl-0 = <&sdhci_default_cfg>;
+ pinctrl-1 = <&sdhci_uhs_cfg>;
};
--
2.53.0
^ permalink raw reply related
* [PATCH v8 2/9] mmc: sdhci-of-k1: enable essential clock infrastructure for SD operation
From: Iker Pedrosa @ 2026-04-13 8:02 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Adrian Hunter, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Yixun Lan, Yixun Lan
Cc: Troy Mitchell, Michael Opdenacker, Javier Martinez Canillas,
linux-mmc, devicetree, linux-riscv, spacemit, linux-kernel,
Iker Pedrosa, Anand Moon, Trevor Gamblin, Vincent Legoll
In-Reply-To: <20260413-orangepi-sd-card-uhs-v8-0-c21c40ec16d0@gmail.com>
Ensure SD card pins receive clock signals by enabling pad clock
generation and overriding automatic clock gating. Required for all SD
operation modes.
The SDHC_GEN_PAD_CLK_ON setting in LEGACY_CTRL_REG is safe for both SD
and eMMC operation as both protocols use the same physical MMC interface
pins and require proper clock signal generation at the hardware level
for signal integrity and timing.
Additional SD-specific clock overrides (SDHC_OVRRD_CLK_OEN and
SDHC_FORCE_CLK_ON) are conditionally applied only for SD-only
controllers to handle removable card scenarios.
Tested-by: Anand Moon <linux.amoon@gmail.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Tested-by: Trevor Gamblin <tgamblin@baylibre.com>
Reviewed-by: Troy Mitchell <troy.mitchell@linux.dev>
Tested-by: Vincent Legoll <legoll@online.fr>
Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
---
drivers/mmc/host/sdhci-of-k1.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/mmc/host/sdhci-of-k1.c b/drivers/mmc/host/sdhci-of-k1.c
index 455656f9842d..0dd06fc19b85 100644
--- a/drivers/mmc/host/sdhci-of-k1.c
+++ b/drivers/mmc/host/sdhci-of-k1.c
@@ -21,6 +21,13 @@
#include "sdhci.h"
#include "sdhci-pltfm.h"
+#define SPACEMIT_SDHC_OP_EXT_REG 0x108
+#define SDHC_OVRRD_CLK_OEN BIT(11)
+#define SDHC_FORCE_CLK_ON BIT(12)
+
+#define SPACEMIT_SDHC_LEGACY_CTRL_REG 0x10C
+#define SDHC_GEN_PAD_CLK_ON BIT(6)
+
#define SPACEMIT_SDHC_MMC_CTRL_REG 0x114
#define SDHC_MISC_INT_EN BIT(1)
#define SDHC_MISC_INT BIT(2)
@@ -101,6 +108,12 @@ static void spacemit_sdhci_reset(struct sdhci_host *host, u8 mask)
if (!(host->mmc->caps2 & MMC_CAP2_NO_MMC))
spacemit_sdhci_setbits(host, SDHC_MMC_CARD_MODE, SPACEMIT_SDHC_MMC_CTRL_REG);
+
+ spacemit_sdhci_setbits(host, SDHC_GEN_PAD_CLK_ON, SPACEMIT_SDHC_LEGACY_CTRL_REG);
+
+ if (host->mmc->caps2 & MMC_CAP2_NO_MMC)
+ spacemit_sdhci_setbits(host, SDHC_OVRRD_CLK_OEN | SDHC_FORCE_CLK_ON,
+ SPACEMIT_SDHC_OP_EXT_REG);
}
static void spacemit_sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned int timing)
--
2.53.0
^ permalink raw reply related
* [PATCH v8 4/9] mmc: sdhci-of-k1: add comprehensive SDR tuning support
From: Iker Pedrosa @ 2026-04-13 8:02 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Adrian Hunter, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Yixun Lan, Yixun Lan
Cc: Troy Mitchell, Michael Opdenacker, Javier Martinez Canillas,
linux-mmc, devicetree, linux-riscv, spacemit, linux-kernel,
Iker Pedrosa, Anand Moon, Trevor Gamblin, Vincent Legoll
In-Reply-To: <20260413-orangepi-sd-card-uhs-v8-0-c21c40ec16d0@gmail.com>
Implement software tuning algorithm to enable UHS-I SDR modes for SD
card operation and HS200 mode for eMMC. This adds both TX and RX delay
line tuning based on the SpacemiT K1 controller capabilities.
Algorithm features:
- Add tuning register definitions (RX_CFG, DLINE_CTRL, DLINE_CFG)
- Conditional tuning: only for high-speed modes (≥100MHz)
- TX tuning: configure transmit delay line with optimal values
(dline_reg=0, delaycode=127) to ensure optimal signal output timing
- RX tuning: single-pass window detection algorithm testing full
delay range (0-255) to find optimal receive timing window
- Retry mechanism: multiple fallback delays within optimal window
for improved reliability
Tested-by: Anand Moon <linux.amoon@gmail.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Tested-by: Trevor Gamblin <tgamblin@baylibre.com>
Tested-by: Vincent Legoll <legoll@online.fr>
Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
---
drivers/mmc/host/sdhci-of-k1.c | 172 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 172 insertions(+)
diff --git a/drivers/mmc/host/sdhci-of-k1.c b/drivers/mmc/host/sdhci-of-k1.c
index d9144537032a..37b0911e7cf2 100644
--- a/drivers/mmc/host/sdhci-of-k1.c
+++ b/drivers/mmc/host/sdhci-of-k1.c
@@ -69,6 +69,28 @@
#define SDHC_PHY_DRIVE_SEL GENMASK(2, 0)
#define SDHC_RX_BIAS_CTRL BIT(5)
+#define SPACEMIT_SDHC_RX_CFG_REG 0x118
+#define SDHC_RX_SDCLK_SEL0_MASK GENMASK(1, 0)
+#define SDHC_RX_SDCLK_SEL1_MASK GENMASK(3, 2)
+#define SDHC_RX_SDCLK_SEL1 FIELD_PREP(SDHC_RX_SDCLK_SEL1_MASK, 1)
+
+#define SPACEMIT_SDHC_DLINE_CTRL_REG 0x130
+#define SDHC_DLINE_PU BIT(0)
+#define SDHC_RX_DLINE_CODE_MASK GENMASK(23, 16)
+#define SDHC_TX_DLINE_CODE_MASK GENMASK(31, 24)
+
+#define SPACEMIT_SDHC_DLINE_CFG_REG 0x134
+#define SDHC_RX_DLINE_REG_MASK GENMASK(7, 0)
+#define SDHC_RX_DLINE_GAIN BIT(8)
+#define SDHC_TX_DLINE_REG_MASK GENMASK(23, 16)
+
+#define SPACEMIT_RX_DLINE_REG 9
+#define SPACEMIT_RX_TUNE_DELAY_MIN 0x0
+#define SPACEMIT_RX_TUNE_DELAY_MAX 0xFF
+
+#define SPACEMIT_TX_TUNING_DLINE_REG 0x00
+#define SPACEMIT_TX_TUNING_DELAYCODE 127
+
struct spacemit_sdhci_host {
struct clk *clk_core;
struct clk *clk_io;
@@ -96,6 +118,50 @@ static inline void spacemit_sdhci_clrsetbits(struct sdhci_host *host, u32 clr, u
sdhci_writel(host, val, reg);
}
+static void spacemit_sdhci_set_rx_delay(struct sdhci_host *host, u8 delay)
+{
+ spacemit_sdhci_clrsetbits(host, SDHC_RX_DLINE_CODE_MASK,
+ FIELD_PREP(SDHC_RX_DLINE_CODE_MASK, delay),
+ SPACEMIT_SDHC_DLINE_CTRL_REG);
+}
+
+static void spacemit_sdhci_set_tx_delay(struct sdhci_host *host, u8 delay)
+{
+ spacemit_sdhci_clrsetbits(host, SDHC_TX_DLINE_CODE_MASK,
+ FIELD_PREP(SDHC_TX_DLINE_CODE_MASK, delay),
+ SPACEMIT_SDHC_DLINE_CTRL_REG);
+}
+
+static void spacemit_sdhci_set_tx_dline_reg(struct sdhci_host *host, u8 dline_reg)
+{
+ spacemit_sdhci_clrsetbits(host, SDHC_TX_DLINE_REG_MASK,
+ FIELD_PREP(SDHC_TX_DLINE_REG_MASK, dline_reg),
+ SPACEMIT_SDHC_DLINE_CFG_REG);
+}
+
+static void spacemit_sdhci_tx_tuning_prepare(struct sdhci_host *host)
+{
+ spacemit_sdhci_setbits(host, SDHC_TX_MUX_SEL, SPACEMIT_SDHC_TX_CFG_REG);
+ spacemit_sdhci_setbits(host, SDHC_DLINE_PU, SPACEMIT_SDHC_DLINE_CTRL_REG);
+ udelay(5);
+}
+
+static void spacemit_sdhci_prepare_tuning(struct sdhci_host *host)
+{
+ spacemit_sdhci_clrsetbits(host, SDHC_RX_DLINE_REG_MASK,
+ FIELD_PREP(SDHC_RX_DLINE_REG_MASK, SPACEMIT_RX_DLINE_REG),
+ SPACEMIT_SDHC_DLINE_CFG_REG);
+
+ spacemit_sdhci_setbits(host, SDHC_DLINE_PU, SPACEMIT_SDHC_DLINE_CTRL_REG);
+ udelay(5);
+
+ spacemit_sdhci_clrsetbits(host, SDHC_RX_SDCLK_SEL1_MASK, SDHC_RX_SDCLK_SEL1,
+ SPACEMIT_SDHC_RX_CFG_REG);
+
+ if (host->mmc->ios.timing == MMC_TIMING_MMC_HS200)
+ spacemit_sdhci_setbits(host, SDHC_HS200_USE_RFIFO, SPACEMIT_SDHC_PHY_FUNC_REG);
+}
+
static void spacemit_sdhci_reset(struct sdhci_host *host, u8 mask)
{
sdhci_reset(host, mask);
@@ -191,6 +257,111 @@ static unsigned int spacemit_sdhci_clk_get_max_clock(struct sdhci_host *host)
return clk_get_rate(pltfm_host->clk);
}
+static int spacemit_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
+{
+ int current_len = 0, current_start = 0;
+ int max_pass_len = 0, max_pass_start = 0;
+ struct mmc_host *mmc = host->mmc;
+ struct mmc_ios ios = mmc->ios;
+ u8 final_delay;
+ int ret = 0;
+ int i;
+
+ /*
+ * Tuning is required for SDR50/SDR104, HS200/HS400 cards and
+ * if clock frequency is greater than 100MHz in these modes.
+ */
+ if (host->clock < 100 * 1000 * 1000 ||
+ !(ios.timing == MMC_TIMING_MMC_HS200 ||
+ ios.timing == MMC_TIMING_UHS_SDR50 ||
+ ios.timing == MMC_TIMING_UHS_SDR104))
+ return 0;
+
+ if (mmc->caps2 & MMC_CAP2_NO_MMC) {
+ spacemit_sdhci_set_tx_dline_reg(host, SPACEMIT_TX_TUNING_DLINE_REG);
+ spacemit_sdhci_set_tx_delay(host, SPACEMIT_TX_TUNING_DELAYCODE);
+ spacemit_sdhci_tx_tuning_prepare(host);
+
+ dev_dbg(mmc_dev(host->mmc), "TX tuning: dline_reg=%d, delaycode=%d\n",
+ SPACEMIT_TX_TUNING_DLINE_REG, SPACEMIT_TX_TUNING_DELAYCODE);
+ }
+
+ spacemit_sdhci_prepare_tuning(host);
+
+ for (i = SPACEMIT_RX_TUNE_DELAY_MIN; i <= SPACEMIT_RX_TUNE_DELAY_MAX; i++) {
+ spacemit_sdhci_set_rx_delay(host, i);
+ ret = mmc_send_tuning(host->mmc, opcode, NULL);
+
+ dev_dbg(mmc_dev(host->mmc), "RX delay %d: %s\n",
+ i, ret == 0 ? "pass" : "fail");
+
+ if (ret == 0) {
+ /* Test passed - extend current window */
+ if (current_len == 0)
+ current_start = i;
+ current_len++;
+ } else {
+ /* Test failed - check if current window is best so far */
+ if (current_len > max_pass_len) {
+ max_pass_len = current_len;
+ max_pass_start = current_start;
+ }
+ current_len = 0;
+ }
+ }
+
+ if (current_len > max_pass_len) {
+ max_pass_len = current_len;
+ max_pass_start = current_start;
+ }
+
+ if (max_pass_len < 3) {
+ dev_err(mmc_dev(host->mmc), "Tuning failed: no stable window found\n");
+ return -EIO;
+ }
+
+ final_delay = max_pass_start + max_pass_len / 2;
+ spacemit_sdhci_set_rx_delay(host, final_delay);
+ ret = mmc_send_tuning(host->mmc, opcode, NULL);
+ if (ret) {
+ u8 retry_delays[] = {
+ max_pass_start + max_pass_len / 4,
+ max_pass_start + (3 * max_pass_len) / 4,
+ max_pass_start,
+ max_pass_start + max_pass_len - 1
+ };
+ int retry_count = ARRAY_SIZE(retry_delays);
+
+ dev_warn(mmc_dev(mmc), "Primary delay %d failed, trying alternatives\n",
+ final_delay);
+
+ for (i = 0; i < retry_count; i++) {
+ if (retry_delays[i] >= SPACEMIT_RX_TUNE_DELAY_MIN &&
+ retry_delays[i] <= SPACEMIT_RX_TUNE_DELAY_MAX) {
+ spacemit_sdhci_set_rx_delay(host, retry_delays[i]);
+ ret = mmc_send_tuning(host->mmc, opcode, NULL);
+ if (!ret) {
+ final_delay = retry_delays[i];
+ dev_info(mmc_dev(mmc), "Retry successful with delay %d\n",
+ final_delay);
+ break;
+ }
+ }
+ }
+
+ if (ret) {
+ dev_err(mmc_dev(mmc), "All retry attempts failed\n");
+ return -EIO;
+ }
+ }
+
+ dev_dbg(mmc_dev(host->mmc),
+ "Tuning successful: window %d-%d, using delay %d\n",
+ max_pass_start, max_pass_start + max_pass_len - 1, final_delay);
+
+ return 0;
+}
+
static int spacemit_sdhci_pre_select_hs400(struct mmc_host *mmc)
{
struct sdhci_host *host = mmc_priv(mmc);
@@ -326,6 +497,7 @@ static const struct sdhci_ops spacemit_sdhci_ops = {
.set_bus_width = sdhci_set_bus_width,
.set_clock = spacemit_sdhci_set_clock,
.set_uhs_signaling = spacemit_sdhci_set_uhs_signaling,
+ .platform_execute_tuning = spacemit_sdhci_execute_tuning,
};
static const struct sdhci_pltfm_data spacemit_sdhci_k1_pdata = {
--
2.53.0
^ permalink raw reply related
* [PATCH v8 3/9] mmc: sdhci-of-k1: add regulator and pinctrl voltage switching support
From: Iker Pedrosa @ 2026-04-13 8:02 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Adrian Hunter, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Yixun Lan, Yixun Lan
Cc: Troy Mitchell, Michael Opdenacker, Javier Martinez Canillas,
linux-mmc, devicetree, linux-riscv, spacemit, linux-kernel,
Iker Pedrosa, Anand Moon, Trevor Gamblin, Vincent Legoll
In-Reply-To: <20260413-orangepi-sd-card-uhs-v8-0-c21c40ec16d0@gmail.com>
Add voltage switching infrastructure for UHS-I modes by integrating both
regulator framework (for supply voltage control) and pinctrl state
switching (for pin drive strength optimization).
- Add regulator supply parsing and voltage switching callback
- Add optional pinctrl state switching between "default" (3.3V) and
"state_uhs" (1.8V) configurations
- Enable coordinated voltage and pin configuration changes for UHS modes
This provides complete voltage switching support while maintaining
backward compatibility when pinctrl states are not defined.
Tested-by: Anand Moon <linux.amoon@gmail.com>
Tested-by: Trevor Gamblin <tgamblin@baylibre.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Reviewed-by: Troy Mitchell <troy.mitchell@linux.dev>
Tested-by: Vincent Legoll <legoll@online.fr>
Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
---
drivers/mmc/host/sdhci-of-k1.c | 72 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 72 insertions(+)
diff --git a/drivers/mmc/host/sdhci-of-k1.c b/drivers/mmc/host/sdhci-of-k1.c
index 0dd06fc19b85..d9144537032a 100644
--- a/drivers/mmc/host/sdhci-of-k1.c
+++ b/drivers/mmc/host/sdhci-of-k1.c
@@ -16,6 +16,7 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/reset.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include "sdhci.h"
@@ -71,6 +72,9 @@
struct spacemit_sdhci_host {
struct clk *clk_core;
struct clk *clk_io;
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *pinctrl_default;
+ struct pinctrl_state *pinctrl_uhs;
};
/* All helper functions will update clr/set while preserve rest bits */
@@ -219,6 +223,46 @@ static void spacemit_sdhci_pre_hs400_to_hs200(struct mmc_host *mmc)
SPACEMIT_SDHC_PHY_CTRL_REG);
}
+static int spacemit_sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
+ struct mmc_ios *ios)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct spacemit_sdhci_host *sdhst = sdhci_pltfm_priv(pltfm_host);
+ struct pinctrl_state *state;
+ int ret;
+
+ ret = sdhci_start_signal_voltage_switch(mmc, ios);
+ if (ret)
+ return ret;
+
+ if (!sdhst->pinctrl)
+ return 0;
+
+ /* Select appropriate pinctrl state based on signal voltage */
+ switch (ios->signal_voltage) {
+ case MMC_SIGNAL_VOLTAGE_330:
+ state = sdhst->pinctrl_default;
+ break;
+ case MMC_SIGNAL_VOLTAGE_180:
+ state = sdhst->pinctrl_uhs;
+ break;
+ default:
+ dev_warn(mmc_dev(mmc), "unsupported voltage %d\n", ios->signal_voltage);
+ return 0;
+ }
+
+ ret = pinctrl_select_state(sdhst->pinctrl, state);
+ if (ret) {
+ dev_warn(mmc_dev(mmc), "failed to select pinctrl state: %d\n", ret);
+ return 0;
+ }
+ dev_dbg(mmc_dev(mmc), "switched to %s pinctrl state\n",
+ ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180 ? "UHS" : "default");
+
+ return 0;
+}
+
static inline int spacemit_sdhci_get_clocks(struct device *dev,
struct sdhci_pltfm_host *pltfm_host)
{
@@ -252,6 +296,30 @@ static inline int spacemit_sdhci_get_resets(struct device *dev)
return 0;
}
+static inline void spacemit_sdhci_get_pins(struct device *dev,
+ struct sdhci_pltfm_host *pltfm_host)
+{
+ struct spacemit_sdhci_host *sdhst = sdhci_pltfm_priv(pltfm_host);
+
+ sdhst->pinctrl = devm_pinctrl_get(dev);
+ if (IS_ERR(sdhst->pinctrl)) {
+ sdhst->pinctrl = NULL;
+ dev_dbg(dev, "pinctrl not available, voltage switching will work without it\n");
+ return;
+ }
+
+ sdhst->pinctrl_default = pinctrl_lookup_state(sdhst->pinctrl, "default");
+ if (IS_ERR(sdhst->pinctrl_default))
+ sdhst->pinctrl_default = NULL;
+
+ sdhst->pinctrl_uhs = pinctrl_lookup_state(sdhst->pinctrl, "uhs");
+ if (IS_ERR(sdhst->pinctrl_uhs))
+ sdhst->pinctrl_uhs = NULL;
+
+ dev_dbg(dev, "pinctrl setup: default=%p, uhs=%p\n",
+ sdhst->pinctrl_default, sdhst->pinctrl_uhs);
+}
+
static const struct sdhci_ops spacemit_sdhci_ops = {
.get_max_clock = spacemit_sdhci_clk_get_max_clock,
.reset = spacemit_sdhci_reset,
@@ -324,6 +392,10 @@ static int spacemit_sdhci_probe(struct platform_device *pdev)
host->mmc->caps |= MMC_CAP_NEED_RSP_BUSY;
+ spacemit_sdhci_get_pins(dev, pltfm_host);
+
+ host->mmc_host_ops.start_signal_voltage_switch = spacemit_sdhci_start_signal_voltage_switch;
+
ret = spacemit_sdhci_get_clocks(dev, pltfm_host);
if (ret)
goto err_pltfm;
--
2.53.0
^ permalink raw reply related
* [PATCH v8 5/9] riscv: dts: spacemit: k1: add SD card controller and pinctrl support
From: Iker Pedrosa @ 2026-04-13 8:02 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Adrian Hunter, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Yixun Lan, Yixun Lan
Cc: Troy Mitchell, Michael Opdenacker, Javier Martinez Canillas,
linux-mmc, devicetree, linux-riscv, spacemit, linux-kernel,
Iker Pedrosa, Anand Moon, Trevor Gamblin, Vincent Legoll
In-Reply-To: <20260413-orangepi-sd-card-uhs-v8-0-c21c40ec16d0@gmail.com>
Add SD card controller infrastructure for SpacemiT K1 SoC with complete
pinctrl support for both standard and UHS modes.
- Add sdhci0 controller definition with clocks, resets and interrupts
- Add mmc1_cfg pinctrl for 3.3V standard SD operation
- Add mmc1_uhs_cfg pinctrl for 1.8V UHS high-speed operation
- Configure appropriate drive strength and power-source properties
This provides complete SD card infrastructure that K1-based boards can
enable.
Tested-by: Anand Moon <linux.amoon@gmail.com>
Tested-by: Trevor Gamblin <tgamblin@baylibre.com>
Tested-by: Vincent Legoll <legoll@online.fr>
Reviewed-by: Troy Mitchell <troy.mitchell@linux.dev>
Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
---
arch/riscv/boot/dts/spacemit/k1-pinctrl.dtsi | 40 ++++++++++++++++++++++++++++
arch/riscv/boot/dts/spacemit/k1.dtsi | 13 +++++++++
2 files changed, 53 insertions(+)
diff --git a/arch/riscv/boot/dts/spacemit/k1-pinctrl.dtsi b/arch/riscv/boot/dts/spacemit/k1-pinctrl.dtsi
index b13dcb10f4d6..b3c472a0783b 100644
--- a/arch/riscv/boot/dts/spacemit/k1-pinctrl.dtsi
+++ b/arch/riscv/boot/dts/spacemit/k1-pinctrl.dtsi
@@ -570,4 +570,44 @@ pwm14-1-pins {
drive-strength = <32>;
};
};
+
+ mmc1_cfg: mmc1-cfg {
+ mmc1-data-cmd-pins {
+ pinmux = <K1_PADCONF(104, 0)>, /* mmc1_d3 */
+ <K1_PADCONF(105, 0)>, /* mmc1_d2 */
+ <K1_PADCONF(106, 0)>, /* mmc1_d1 */
+ <K1_PADCONF(107, 0)>, /* mmc1_d0 */
+ <K1_PADCONF(108, 0)>; /* mmc1_cmd */
+ bias-pull-up = <1>;
+ drive-strength = <19>;
+ power-source = <3300>;
+ };
+
+ mmc1-clk-pins {
+ pinmux = <K1_PADCONF(109, 0)>; /* mmc1_clk */
+ bias-pull-down = <1>;
+ drive-strength = <19>;
+ power-source = <3300>;
+ };
+ };
+
+ mmc1_uhs_cfg: mmc1-uhs-cfg {
+ mmc1-data-cmd-pins {
+ pinmux = <K1_PADCONF(104, 0)>, /* mmc1_d3 */
+ <K1_PADCONF(105, 0)>, /* mmc1_d2 */
+ <K1_PADCONF(106, 0)>, /* mmc1_d1 */
+ <K1_PADCONF(107, 0)>, /* mmc1_d0 */
+ <K1_PADCONF(108, 0)>; /* mmc1_cmd */
+ bias-pull-up = <1>;
+ drive-strength = <42>;
+ power-source = <1800>;
+ };
+
+ mmc1-clk-pins {
+ pinmux = <K1_PADCONF(109, 0)>; /* mmc1_clk */
+ bias-pull-down = <1>;
+ drive-strength = <42>;
+ power-source = <1800>;
+ };
+ };
};
diff --git a/arch/riscv/boot/dts/spacemit/k1.dtsi b/arch/riscv/boot/dts/spacemit/k1.dtsi
index f0bad6855c97..28949f804610 100644
--- a/arch/riscv/boot/dts/spacemit/k1.dtsi
+++ b/arch/riscv/boot/dts/spacemit/k1.dtsi
@@ -1211,6 +1211,19 @@ emmc: mmc@d4281000 {
interrupts = <101>;
status = "disabled";
};
+
+ sdhci0: mmc@d4280000 {
+ compatible = "spacemit,k1-sdhci";
+ reg = <0x0 0xd4280000 0x0 0x200>;
+ clocks = <&syscon_apmu CLK_SDH_AXI>,
+ <&syscon_apmu CLK_SDH0>;
+ clock-names = "core", "io";
+ resets = <&syscon_apmu RESET_SDH_AXI>,
+ <&syscon_apmu RESET_SDH0>;
+ reset-names = "axi", "sdh";
+ interrupts = <99>;
+ status = "disabled";
+ };
};
};
};
--
2.53.0
^ permalink raw reply related
* [PATCH v8 6/9] riscv: dts: spacemit: k1-orangepi-rv2: add PMIC and power infrastructure
From: Iker Pedrosa @ 2026-04-13 8:02 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Adrian Hunter, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Yixun Lan, Yixun Lan
Cc: Troy Mitchell, Michael Opdenacker, Javier Martinez Canillas,
linux-mmc, devicetree, linux-riscv, spacemit, linux-kernel,
Iker Pedrosa, Anand Moon, Trevor Gamblin, Vincent Legoll
In-Reply-To: <20260413-orangepi-sd-card-uhs-v8-0-c21c40ec16d0@gmail.com>
Add Spacemit P1 PMIC configuration and board power infrastructure for
voltage regulation support.
- Add board power regulators (5V input, 4V rail)
- Enable I2C8 for PMIC communication
- Configure PMIC with buck4 (vmmc) and aldo1 (vqmmc) regulators
- Set up regulator constraints for SD card operation
Tested-by: Anand Moon <linux.amoon@gmail.com>
Tested-by: Trevor Gamblin <tgamblin@baylibre.com>
Tested-by: Vincent Legoll <legoll@online.fr>
Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
---
arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts | 48 ++++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
index 7b7331cb3c72..9c417a483f6b 100644
--- a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
+++ b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
@@ -19,6 +19,25 @@ aliases {
ethernet1 = ð1;
};
+ reg_dc_in: dc-in-5v {
+ compatible = "regulator-fixed";
+ regulator-name = "dc_in_5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ reg_vcc_4v: vcc-4v {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_4v";
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <4000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ vin-supply = <®_dc_in>;
+ };
+
chosen {
stdout-path = "serial0";
};
@@ -92,3 +111,32 @@ &uart0 {
pinctrl-0 = <&uart0_2_cfg>;
status = "okay";
};
+
+&i2c8 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c8_cfg>;
+ status = "okay";
+
+ pmic@41 {
+ compatible = "spacemit,p1";
+ reg = <0x41>;
+ interrupts = <64>;
+ vin-supply = <®_vcc_4v>;
+
+ regulators {
+ buck4: buck4 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <5000>;
+ regulator-always-on;
+ };
+
+ aldo1: aldo1 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+ };
+};
--
2.53.0
^ permalink raw reply related
* [PATCH v8 7/9] riscv: dts: spacemit: k1-orangepi-rv2: add SD card support with UHS modes
From: Iker Pedrosa @ 2026-04-13 8:02 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Adrian Hunter, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Yixun Lan, Yixun Lan
Cc: Troy Mitchell, Michael Opdenacker, Javier Martinez Canillas,
linux-mmc, devicetree, linux-riscv, spacemit, linux-kernel,
Iker Pedrosa, Anand Moon, Trevor Gamblin, Vincent Legoll
In-Reply-To: <20260413-orangepi-sd-card-uhs-v8-0-c21c40ec16d0@gmail.com>
Add complete SD card controller support with UHS high-speed modes.
- Enable sdhci0 controller with 4-bit bus width
- Configure card detect GPIO with inversion
- Connect vmmc-supply to buck4 for 3.3V card power
- Connect vqmmc-supply to aldo1 for 1.8V/3.3V I/O switching
- Add dual pinctrl states for voltage-dependent pin configuration
- Support UHS-I SDR25, SDR50, and SDR104 modes
This enables full SD card functionality including high-speed UHS modes
for improved performance.
Tested-by: Anand Moon <linux.amoon@gmail.com>
Tested-by: Trevor Gamblin <tgamblin@baylibre.com>
Tested-by: Michael Opdenacker <michael.opdenacker@rootcommit.com>
Tested-by: Vincent Legoll <legoll@online.fr>
Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
---
arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
index 9c417a483f6b..95cfb4681ced 100644
--- a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
+++ b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
@@ -140,3 +140,22 @@ aldo1: aldo1 {
};
};
};
+
+&sdhci0 {
+ pinctrl-names = "default", "uhs";
+ pinctrl-0 = <&mmc1_cfg>;
+ pinctrl-1 = <&mmc1_uhs_cfg>;
+ bus-width = <4>;
+ cd-gpios = <&gpio K1_GPIO(80) GPIO_ACTIVE_HIGH>;
+ cd-inverted;
+ no-mmc;
+ no-sdio;
+ disable-wp;
+ cap-sd-highspeed;
+ vmmc-supply = <&buck4>;
+ vqmmc-supply = <&aldo1>;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ status = "okay";
+};
--
2.53.0
^ permalink raw reply related
* [PATCH v8 8/9] riscv: dts: spacemit: k1-bananapi-f3: add SD card support with UHS modes
From: Iker Pedrosa @ 2026-04-13 8:02 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Adrian Hunter, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Yixun Lan, Yixun Lan
Cc: Troy Mitchell, Michael Opdenacker, Javier Martinez Canillas,
linux-mmc, devicetree, linux-riscv, spacemit, linux-kernel,
Iker Pedrosa, Anand Moon
In-Reply-To: <20260413-orangepi-sd-card-uhs-v8-0-c21c40ec16d0@gmail.com>
Add complete SD card controller support with UHS high-speed modes.
- Enable sdhci0 controller with 4-bit bus width
- Configure card detect GPIO with inversion
- Connect vmmc-supply to buck4 for 3.3V card power
- Connect vqmmc-supply to aldo1 for 1.8V/3.3V I/O switching
- Add dual pinctrl states for voltage-dependent pin configuration
- Support UHS-I SDR25, SDR50, and SDR104 modes
This enables full SD card functionality including high-speed UHS modes
for improved performance.
Suggested-by: Anand Moon <linux.amoon@gmail.com>
Tested-by: Anand Moon <linux.amoon@gmail.com>
Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
---
arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts | 24 ++++++++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts b/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts
index 5790d927b93d..a7d88564630f 100644
--- a/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts
+++ b/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts
@@ -220,7 +220,7 @@ buck3_1v8: buck3 {
regulator-always-on;
};
- buck4 {
+ buck4: buck4 {
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <3300000>;
regulator-ramp-delay = <5000>;
@@ -241,7 +241,7 @@ buck6 {
regulator-always-on;
};
- aldo1 {
+ aldo1: aldo1 {
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <3400000>;
regulator-boot-on;
@@ -367,3 +367,23 @@ hub_3_0: hub@2 {
reset-gpios = <&gpio K1_GPIO(124) GPIO_ACTIVE_LOW>;
};
};
+
+&sdhci0 {
+ pinctrl-names = "default", "uhs";
+ pinctrl-0 = <&mmc1_cfg>;
+ pinctrl-1 = <&mmc1_uhs_cfg>;
+ bus-width = <4>;
+ cd-gpios = <&gpio K1_GPIO(80) GPIO_ACTIVE_HIGH>;
+ cd-inverted;
+ broken-cd;
+ no-mmc;
+ no-sdio;
+ disable-wp;
+ cap-sd-highspeed;
+ vmmc-supply = <&buck4>;
+ vqmmc-supply = <&aldo1>;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ status = "okay";
+};
--
2.53.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox