summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
authorGUI <[email protected]>2026-08-07 21:31:43 +0800
committerGitHub <[email protected]>2026-08-07 21:31:43 +0800
commita2c196d6439643356490f62370d34001ee66af99 (patch)
treea5c1ed72e404dd0dc5ed51e047e7396772c586ad /components
parentc19fe2c8238e3c5d329fca4fc219e3924240945b (diff)
[dm][phye] Add Mode/State and MIPI D-PHY timing helper (#11675)
* [dm][phye] Add Mode/State and MIPI D-PHY timing helper Extend the generic PHY framework with cached mode and submode state, avoiding redundant hardware mode changes. Add MIPI D-PHY default timing calculation helpers based on pixel clock or lane high-speed clock, and expose the new API through rtdevice.h. Signed-off-by: GuEe-GUI <[email protected]> * style: format code with clang-format * style: format complete changed files with clang-format --------- Signed-off-by: GuEe-GUI <[email protected]>
Diffstat (limited to 'components')
-rw-r--r--components/drivers/include/drivers/phye-mipi-dphy.h39
-rw-r--r--components/drivers/include/drivers/phye.h18
-rw-r--r--components/drivers/include/rtdevice.h4
-rw-r--r--components/drivers/phye/SConscript2
-rw-r--r--components/drivers/phye/phye-mipi-dphy.c70
-rw-r--r--components/drivers/phye/phye.c36
6 files changed, 162 insertions, 7 deletions
diff --git a/components/drivers/include/drivers/phye-mipi-dphy.h b/components/drivers/include/drivers/phye-mipi-dphy.h
new file mode 100644
index 0000000000..d14245e0b3
--- /dev/null
+++ b/components/drivers/include/drivers/phye-mipi-dphy.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-09-23 GuEe-GUI first version
+ */
+
+#ifndef __PHYE_MIPI_DPHY_H__
+#define __PHYE_MIPI_DPHY_H__
+
+#include <rtthread.h>
+
+struct rt_phye_configure_opts_mipi_dphy
+{
+ rt_uint64_t hs_clk_rate; /* lane HS bit rate, Hz */
+ rt_uint32_t lanes;
+
+ rt_uint32_t lpx;
+ rt_uint32_t hs_prepare;
+ rt_uint32_t hs_zero;
+ rt_uint32_t hs_trail;
+ rt_uint32_t hs_exit;
+ rt_uint32_t clk_prepare;
+ rt_uint32_t clk_zero;
+ rt_uint32_t clk_pre;
+ rt_uint32_t clk_post;
+ rt_uint32_t clk_trail;
+};
+
+rt_err_t rt_phye_mipi_dphy_get_default_config(rt_uint64_t pixel_clock,
+ rt_uint32_t bpp, rt_uint32_t lanes,
+ struct rt_phye_configure_opts_mipi_dphy *cfg);
+rt_err_t rt_phye_mipi_dphy_get_default_config_for_hsclk(rt_uint64_t hs_clk_rate,
+ rt_uint32_t lanes, struct rt_phye_configure_opts_mipi_dphy *cfg);
+
+#endif /* __PHYE_MIPI_DPHY_H__ */
diff --git a/components/drivers/include/drivers/phye.h b/components/drivers/include/drivers/phye.h
index 3776cdeac9..143a7d75e1 100644
--- a/components/drivers/include/drivers/phye.h
+++ b/components/drivers/include/drivers/phye.h
@@ -13,6 +13,7 @@
#include <rtthread.h>
#include <drivers/ofw.h>
+#include <drivers/phye-mipi-dphy.h>
enum rt_phye_mode
{
@@ -47,14 +48,20 @@ enum rt_phye_mode
struct rt_phye_ops;
+union rt_phye_configure_opts
+{
+ struct rt_phye_configure_opts_mipi_dphy mipi_dphy;
+};
+
struct rt_phye
{
struct rt_device *dev;
const struct rt_phye_ops *ops;
- int init_count;
- int power_count;
+ enum rt_phye_mode mode;
+ int init_count;
+ int power_count;
struct rt_spinlock lock;
};
@@ -66,6 +73,7 @@ struct rt_phye_ops
rt_err_t (*power_on)(struct rt_phye *phye);
rt_err_t (*power_off)(struct rt_phye *phye);
rt_err_t (*set_mode)(struct rt_phye *phye, enum rt_phye_mode mode, int submode);
+ rt_err_t (*configure)(struct rt_phye *phye, union rt_phye_configure_opts *opts);
rt_err_t (*ofw_parse)(struct rt_phye *phye, struct rt_ofw_cell_args *phye_args);
};
@@ -78,12 +86,18 @@ rt_err_t rt_phye_reset(struct rt_phye *phye);
rt_err_t rt_phye_power_on(struct rt_phye *phye);
rt_err_t rt_phye_power_off(struct rt_phye *phye);
rt_err_t rt_phye_set_mode(struct rt_phye *phye, enum rt_phye_mode mode, int submode);
+rt_err_t rt_phye_configure(struct rt_phye *phye, union rt_phye_configure_opts *opts);
rt_inline rt_err_t rt_phye_set_mode_simple(struct rt_phye *phye, enum rt_phye_mode mode)
{
return rt_phye_set_mode(phye, mode, RT_PHYE_MODE_INVALID);
}
+rt_inline enum rt_phye_mode rt_phye_get_mode(struct rt_phye *phye)
+{
+ return phye ? phye->mode : RT_PHYE_MODE_INVALID;
+}
+
struct rt_phye *rt_phye_get_by_index(struct rt_device *dev, int index);
struct rt_phye *rt_phye_get_by_name(struct rt_device *dev, const char *id);
void rt_phye_put(struct rt_phye *phye);
diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h
index 1185224304..ca0130739a 100644
--- a/components/drivers/include/rtdevice.h
+++ b/components/drivers/include/rtdevice.h
@@ -38,7 +38,7 @@
extern "C" {
#endif
-#define RT_DEVICE(device) ((rt_device_t)device)
+#define RT_DEVICE(device) ((rt_device_t)device)
#ifdef RT_USING_DM
#include "drivers/core/dm.h"
@@ -111,6 +111,7 @@ extern "C" {
#ifdef RT_USING_PHYE
#include "drivers/phye.h"
+#include "drivers/phye-mipi-dphy.h"
#endif /* RT_USING_PHYE */
#ifdef RT_USING_PIC
@@ -247,7 +248,6 @@ extern "C" {
#endif /* RT_USING_DM && RT_USING_SDHCI */
#endif /* RT_USING_SDIO */
-
#ifdef RT_USING_WDT
#include "drivers/dev_watchdog.h"
#endif /* RT_USING_WDT */
diff --git a/components/drivers/phye/SConscript b/components/drivers/phye/SConscript
index 5c5fbb08e6..1332e48015 100644
--- a/components/drivers/phye/SConscript
+++ b/components/drivers/phye/SConscript
@@ -8,7 +8,7 @@ if not GetDepend(['RT_USING_PHYE']):
cwd = GetCurrentDir()
CPPPATH = [cwd + '/../include']
-src = ['phye.c']
+src = ['phye.c', 'phye-mipi-dphy.c']
if GetDepend(['RT_PHYE_GENERIC_USB']):
src += ['phye-generic-usb.c']
diff --git a/components/drivers/phye/phye-mipi-dphy.c b/components/drivers/phye/phye-mipi-dphy.c
new file mode 100644
index 0000000000..63ec91f826
--- /dev/null
+++ b/components/drivers/phye/phye-mipi-dphy.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-09-23 GuEe-GUI first version
+ */
+
+#include <drivers/phye-mipi-dphy.h>
+
+#define PSEC_PER_SEC 1000000000000ULL
+
+static rt_err_t phye_mipi_dphy_calc_config(rt_uint64_t pixel_clock,
+ rt_uint32_t bpp, rt_uint32_t lanes, rt_uint64_t hs_clk_rate,
+ struct rt_phye_configure_opts_mipi_dphy *cfg)
+{
+ rt_uint64_t ui;
+
+ if (!cfg)
+ {
+ return -RT_EINVAL;
+ }
+
+ if (!hs_clk_rate)
+ {
+ if (!pixel_clock || !bpp || !lanes)
+ {
+ return -RT_EINVAL;
+ }
+
+ hs_clk_rate = pixel_clock * bpp / lanes;
+ }
+
+ ui = (PSEC_PER_SEC + hs_clk_rate - 1) / hs_clk_rate;
+
+ cfg->clk_pre = 8;
+ cfg->clk_prepare = 38000;
+ cfg->clk_zero = 262000;
+ cfg->clk_post = 60000 + 52 * (rt_uint32_t)ui;
+ cfg->clk_trail = 60000;
+ cfg->lpx = 50000;
+ cfg->hs_prepare = 40000 + 4 * (rt_uint32_t)ui;
+ cfg->hs_zero = 105000 + 6 * (rt_uint32_t)ui;
+ cfg->hs_trail = (4 * 8 * ui > 60000 + 4 * 4 * ui) ? 4 * 8 * (rt_uint32_t)ui : 60000 + 4 * 4 * (rt_uint32_t)ui;
+ cfg->hs_exit = 100000;
+ cfg->hs_clk_rate = hs_clk_rate;
+ cfg->lanes = lanes;
+
+ return RT_EOK;
+}
+
+rt_err_t rt_phye_mipi_dphy_get_default_config(rt_uint64_t pixel_clock,
+ rt_uint32_t bpp, rt_uint32_t lanes,
+ struct rt_phye_configure_opts_mipi_dphy *cfg)
+{
+ return phye_mipi_dphy_calc_config(pixel_clock, bpp, lanes, 0, cfg);
+}
+
+rt_err_t rt_phye_mipi_dphy_get_default_config_for_hsclk(rt_uint64_t hs_clk_rate,
+ rt_uint32_t lanes, struct rt_phye_configure_opts_mipi_dphy *cfg)
+{
+ if (!hs_clk_rate)
+ {
+ return -RT_EINVAL;
+ }
+
+ return phye_mipi_dphy_calc_config(0, 0, lanes, hs_clk_rate, cfg);
+}
diff --git a/components/drivers/phye/phye.c b/components/drivers/phye/phye.c
index 7dc6709682..cf7aeca8f0 100644
--- a/components/drivers/phye/phye.c
+++ b/components/drivers/phye/phye.c
@@ -224,6 +224,11 @@ rt_err_t rt_phye_set_mode(struct rt_phye *phye, enum rt_phye_mode mode, int subm
err = phye->ops->set_mode(phye, mode, submode);
}
+ if (!err)
+ {
+ phye->mode = mode;
+ }
+
rt_spin_unlock(&phye->lock);
}
else
@@ -234,12 +239,39 @@ rt_err_t rt_phye_set_mode(struct rt_phye *phye, enum rt_phye_mode mode, int subm
return err;
}
+rt_err_t rt_phye_configure(struct rt_phye *phye, union rt_phye_configure_opts *opts)
+{
+ rt_err_t err;
+
+ if (!phye || !opts)
+ {
+ return -RT_EINVAL;
+ }
+
+ err = RT_EOK;
+
+ rt_spin_lock(&phye->lock);
+
+ if (phye->ops->configure)
+ {
+ err = phye->ops->configure(phye, opts);
+ }
+ else
+ {
+ err = -RT_ENOSYS;
+ }
+
+ rt_spin_unlock(&phye->lock);
+
+ return err;
+}
+
static struct rt_phye *ofw_phye_get_by_index(struct rt_ofw_node *np, int index)
{
struct rt_phye *phye = RT_NULL;
#ifdef RT_USING_OFW
- rt_err_t err;
- struct rt_ofw_node *phye_np;
+ rt_err_t err;
+ struct rt_ofw_node *phye_np;
struct rt_ofw_cell_args phye_args;
if (!rt_ofw_parse_phandle_cells(np, "phys", "#phy-cells", index, &phye_args))