diff options
| author | GUI <[email protected]> | 2026-08-07 21:31:43 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-08-07 21:31:43 +0800 |
| commit | a2c196d6439643356490f62370d34001ee66af99 (patch) | |
| tree | a5c1ed72e404dd0dc5ed51e047e7396772c586ad /components | |
| parent | c19fe2c8238e3c5d329fca4fc219e3924240945b (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.h | 39 | ||||
| -rw-r--r-- | components/drivers/include/drivers/phye.h | 18 | ||||
| -rw-r--r-- | components/drivers/include/rtdevice.h | 4 | ||||
| -rw-r--r-- | components/drivers/phye/SConscript | 2 | ||||
| -rw-r--r-- | components/drivers/phye/phye-mipi-dphy.c | 70 | ||||
| -rw-r--r-- | components/drivers/phye/phye.c | 36 |
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)) |
