[RFC 08/21] drm: rcar-du: Add DPLL support

2016-05-30 Thread Dirk Behme
On 30.05.2016 18:00, Ulrich Hecht wrote:
> From: Koji Matsuoka 
>
> Signed-off-by: Koji Matsuoka 
> Signed-off-by: Geert Uytterhoeven 
> ---
>   drivers/gpu/drm/rcar-du/rcar_du_crtc.c  | 97 
> -
>   drivers/gpu/drm/rcar-du/rcar_du_crtc.h  |  8 +++
>   drivers/gpu/drm/rcar-du/rcar_du_drv.c   |  1 +
>   drivers/gpu/drm/rcar-du/rcar_du_drv.h   |  1 +
>   drivers/gpu/drm/rcar-du/rcar_du_plane.h |  7 ++-
>   drivers/gpu/drm/rcar-du/rcar_du_regs.h  | 19 +++
>   6 files changed, 131 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c 
> b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> index 0d8bdda..e10943b 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> @@ -30,6 +30,12 @@
>   #include "rcar_du_regs.h"
>   #include "rcar_du_vsp.h"
>
> +#define PRODUCT_REG  0xfff00044
> +#define PRODUCT_H3_BIT   (0x4f << 8)
> +#define PRODUCT_MASK (0x7f << 8)
> +#define CUT_ES1  (0x00)
> +#define CUT_ES1_MASK (0x00ff)


NACK for the hard coded register.

We've already discussed this in the thread

https://www.mail-archive.com/linux-renesas-soc at vger.kernel.org/msg04008.html

and found that this isn't ready this way:

https://www.mail-archive.com/linux-renesas-soc at vger.kernel.org/msg04079.html

Best regards

Dirk



>   static u32 rcar_du_crtc_read(struct rcar_du_crtc *rcrtc, u32 reg)
>   {
>   struct rcar_du_device *rcdu = rcrtc->group->dev;
> @@ -106,14 +112,74 @@ static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)
>* Hardware Setup
>*/
>
> +static void rcar_du_dpll_divider(struct dpll_info *dpll, unsigned int extclk,
> +  unsigned int mode_clock)
> +{
> + unsigned long dpllclk;
> + unsigned long diff;
> + unsigned long n, m, fdpll;
> + bool match_flag = false;
> + bool clk_diff_set = true;
> +
> + for (n = 39; n < 120; n++) {
> + for (m = 0; m < 4; m++) {
> + for (fdpll = 1; fdpll < 32; fdpll++) {
> + /* 1/2 (FRQSEL=1) for duty rate 50% */
> + dpllclk = extclk * (n + 1) / (m + 1)
> +  / (fdpll + 1) / 2;
> + if (dpllclk >= 4)
> + continue;
> +
> + diff = abs((long)dpllclk - (long)mode_clock);
> + if (clk_diff_set ||
> + ((diff == 0) || (dpll->diff > diff))) {
> + dpll->diff = diff;
> + dpll->n = n;
> + dpll->m = m;
> + dpll->fdpll = fdpll;
> + dpll->dpllclk = dpllclk;
> +
> + if (clk_diff_set)
> + clk_diff_set = false;
> +
> + if (diff == 0) {
> + match_flag = true;
> + break;
> + }
> + }
> + }
> + if (match_flag)
> + break;
> + }
> + if (match_flag)
> + break;
> + }
> +}
> +
>   static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
>   {
>   const struct drm_display_mode *mode = &rcrtc->crtc.state->adjusted_mode;
> + struct rcar_du_device *rcdu = rcrtc->group->dev;
>   unsigned long mode_clock = mode->clock * 1000;
>   unsigned long clk;
>   u32 value;
>   u32 escr;
>   u32 div;
> + u32 dpll_reg = 0;
> + struct dpll_info *dpll;
> + void __iomem *product_reg;
> + bool h3_es1_workaround = false;
> +
> + dpll = kzalloc(sizeof(*dpll), GFP_KERNEL);
> + if (dpll == NULL)
> + return;
> +
> + /* DU2 DPLL Clock Select bit workaround in R-Car H3(ES1.0) */
> + product_reg = ioremap(PRODUCT_REG, 0x04);
> + if (((readl(product_reg) & PRODUCT_MASK) == PRODUCT_H3_BIT)
> + && ((readl(product_reg) & CUT_ES1_MASK) == CUT_ES1))
> + h3_es1_workaround = true;
> + iounmap(product_reg);
>
>   /* Compute the clock divisor and select the internal or external dot
>* clock based on the requested frequency.
> @@ -130,6 +196,15 @@ static void rcar_du_crtc_set_display_timing(struct 
> rcar_du_crtc *rcrtc)
>   u32 extdiv;
>
>   extclk = clk_get_rate(rcrtc->extclock);
> +
> + if (rcdu->info->dpll_ch & (0x01 << rcrtc->index)) {
> + rcar_du_dpll_divider(dpll, extclk, mode_clock);
> + extclk = dpll->dpllclk;
> + dev_dbg(rcrtc->group->dev->dev,
> + "dpllclk:%

Re: [PATCH 3/6] staging: drm/imx: add i.MX IPUv3 base driver

2012-09-15 Thread Dirk Behme

On 12.09.2012 12:31, Sascha Hauer wrote:

The IPU is the Image Processing Unit found on i.MX51/53/6 SoCs. It
features several units for image processing, this patch adds support
for the units needed for Framebuffer support, namely:

- Display Controller (dc)
- Display Interface (di)
- Display Multi Fifo Controller (dmfc)
- Display Processor (dp)
- Image DMA Controller (idmac)

This patch is based on the Freescale driver, but follows a different
approach. The Freescale code implements logical idmac channels and
the handling of the subunits is hidden in common idmac code pathes
in big switch/case statements. This patch instead just provides code
and resource management for the different subunits. The user, in this
case the framebuffer driver, decides how the different units play
together.

The IPU has other units missing in this patch:

- CMOS Sensor Interface (csi)
- Video Deinterlacer (vdi)
- Sensor Multi FIFO Controler (smfc)
- Image Converter (ic)
- Image Rotator (irt)

Signed-off-by: Sascha Hauer 



+static int ipu_reset(struct ipu_soc *ipu)
+{
+   unsigned long timeout;
+
+   ipu_cm_write(ipu, 0x807F, IPU_MEM_RST);
+
+   timeout = jiffies + msecs_to_jiffies(1000);
+   while (ipu_cm_read(ipu, IPU_MEM_RST) & 0x8000) {
+   if (time_after(jiffies, timeout))
+   return -ETIME;
+   cpu_relax();
+   }
+
+   mdelay(300);

  


+   return 0;
+}


While doing some boot time measurement with i.MX6, we found that the 
above mdelay(300) is hurting regarding boot time. On i.MX6 you have two 
IPU instances, so in the end you get 600ms additional delay.


Looking at the Freescale code, this function looks like

static int ipu_reset(struct ipu_soc *ipu)
{
int timeout = 1000;

ipu_cm_write(ipu, 0x807F, IPU_MEM_RST);

while (ipu_cm_read(ipu, IPU_MEM_RST) & 0x8000) {
 if (!timeout--)
   return -ETIME;
 msleep(1);
}
return 0;
}

So there is a msleep() in the loop but no mdelay() outside. Any idea why 
the mdelay() is needed here? Or what could be done regarding boot time 
with this?


Note: This is just a question, this shouldn't block the staging process.

Best regards

Dirk


___
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH, RFC] i.MX DRM support

2012-07-02 Thread Dirk Behme

On 02.07.2012 12:05, Sascha Hauer wrote:

On Thu, Jun 14, 2012 at 03:43:22PM +0200, Sascha Hauer wrote:

Hi All,

The following is the state-of-the-art i.MX IPU (Image Processing Unit)
DRM support.

This code is around for quite some time now and has been posted several
times with different APIs, first with plain old framebuffer support, now
DRM, first platform device binding, now devicetree. Unfortunately there's
quite much code needed to get something useful out of the IPU, so these
patches haven't received a lot of attention from people not involved in
i.MX. I think we have now come to a point where this code needs more public
exposure and where it's easier to talk in incremental changes instead of
blobs. Therefore I request this to go to staging for some cycles.


Dave, Greg,

Comments to this one? I addressed the comments I received so far and am
about to respin this series. Is it ok to put this to staging? If yes,
should I move the whole stuff into drivers/staging/ or should it stay
in drivers/gpu/drm with just a Kconfig dependency on STAGING?


We are very interested in this, so +1 from my side for this.

Many thanks and best regards

Dirk

Btw.: Based on

http://git.pengutronix.de/?p=imx/linux-2.6.git;a=shortlog;h=refs/heads/work/gpu/imx-drm-ipu-complete

with [1] below I fixed some compiler warnings.

I have some additional warnings

drivers/gpu/drm/drm_edid.c: In function 'drm_find_cea_extension':
drivers/gpu/drm/drm_edid.c:1466: warning: array subscript is above array 
bounds

drivers/gpu/drm/drm_edid.c: In function 'drm_detect_hdmi_monitor':
drivers/gpu/drm/drm_edid.c:1466: warning: array subscript is above array 
bounds

drivers/gpu/drm/drm_edid.c: In function 'drm_detect_monitor_audio':
drivers/gpu/drm/drm_edid.c:1466: warning: array subscript is above array 
bounds

drivers/gpu/drm/drm_edid.c: In function 'drm_edid_to_eld':
drivers/gpu/drm/drm_edid.c:1466: warning: array subscript is above array 
bounds

drivers/gpu/drm/drm_edid.c: In function 'drm_add_edid_modes':
drivers/gpu/drm/drm_edid.c:1466: warning: array subscript is above array 
bounds
drivers/gpu/drm/drm_edid.c:1466: warning: array subscript is above array 
bounds


but these seems to be compiler specific and not related to Sacha's patches.

[1]

From: Dirk Behme 
Subject: [PATCH 1/2] DRM i.MX: ldb: Fix compiler warnings

Fix the compiler warnings

drivers/gpu/drm/imx/imx-ldb.c: In function 'imx_ldb_encoder_mode_fixup':
drivers/gpu/drm/imx/imx-ldb.c:118: warning: unused variable 'imx_ldb_ch'
drivers/gpu/drm/imx/imx-ldb.c: In function 'imx_ldb_encoder_prepare':
drivers/gpu/drm/imx/imx-ldb.c:134: warning: format '%ld' expects type 
'long int', but argument 6 has type 'int'


Signed-off-by: Dirk Behme 

---
 drivers/gpu/drm/imx/imx-ldb.c |4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Index: freescale-linux-2.6-imx.git/drivers/gpu/drm/imx/imx-ldb.c
===
--- freescale-linux-2.6-imx.git.orig/drivers/gpu/drm/imx/imx-ldb.c
+++ freescale-linux-2.6-imx.git/drivers/gpu/drm/imx/imx-ldb.c
@@ -115,9 +115,9 @@ static bool imx_ldb_encoder_mode_fixup(s
   struct drm_display_mode *mode,
   struct drm_display_mode *adjusted_mode)
 {
+/*
struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);

-/*
adjusted_mode->clock = clk_round_rate(imx_ldb_ch->clk_pll,
adjusted_mode->clock * 1000) / 1000;
 */
@@ -131,7 +131,7 @@ static void imx_ldb_encoder_prepare(stru
int ret;
struct drm_display_mode *mode = &encoder->crtc->mode;

-   dev_dbg(ldb->dev, "%s: now: %ld want: %ld\n", __func__,
+   dev_dbg(ldb->dev, "%s: now: %ld want: %d\n", __func__,
clk_get_rate(imx_ldb_ch->clk_pll),
mode->clock * 1000 * 7);
clk_set_rate(imx_ldb_ch->clk_pll, mode->clock * 1000 * 7);


___
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH, RFC] i.MX DRM support

2012-07-02 Thread Dirk Behme
On 02.07.2012 12:05, Sascha Hauer wrote:
> On Thu, Jun 14, 2012 at 03:43:22PM +0200, Sascha Hauer wrote:
>> Hi All,
>>
>> The following is the state-of-the-art i.MX IPU (Image Processing Unit)
>> DRM support.
>>
>> This code is around for quite some time now and has been posted several
>> times with different APIs, first with plain old framebuffer support, now
>> DRM, first platform device binding, now devicetree. Unfortunately there's
>> quite much code needed to get something useful out of the IPU, so these
>> patches haven't received a lot of attention from people not involved in
>> i.MX. I think we have now come to a point where this code needs more public
>> exposure and where it's easier to talk in incremental changes instead of
>> blobs. Therefore I request this to go to staging for some cycles.
> 
> Dave, Greg,
> 
> Comments to this one? I addressed the comments I received so far and am
> about to respin this series. Is it ok to put this to staging? If yes,
> should I move the whole stuff into drivers/staging/ or should it stay
> in drivers/gpu/drm with just a Kconfig dependency on STAGING?

We are very interested in this, so +1 from my side for this.

Many thanks and best regards

Dirk

Btw.: Based on

http://git.pengutronix.de/?p=imx/linux-2.6.git;a=shortlog;h=refs/heads/work/gpu/imx-drm-ipu-complete

with [1] below I fixed some compiler warnings.

I have some additional warnings

drivers/gpu/drm/drm_edid.c: In function 'drm_find_cea_extension':
drivers/gpu/drm/drm_edid.c:1466: warning: array subscript is above array 
bounds
drivers/gpu/drm/drm_edid.c: In function 'drm_detect_hdmi_monitor':
drivers/gpu/drm/drm_edid.c:1466: warning: array subscript is above array 
bounds
drivers/gpu/drm/drm_edid.c: In function 'drm_detect_monitor_audio':
drivers/gpu/drm/drm_edid.c:1466: warning: array subscript is above array 
bounds
drivers/gpu/drm/drm_edid.c: In function 'drm_edid_to_eld':
drivers/gpu/drm/drm_edid.c:1466: warning: array subscript is above array 
bounds
drivers/gpu/drm/drm_edid.c: In function 'drm_add_edid_modes':
drivers/gpu/drm/drm_edid.c:1466: warning: array subscript is above array 
bounds
drivers/gpu/drm/drm_edid.c:1466: warning: array subscript is above array 
bounds

but these seems to be compiler specific and not related to Sacha's patches.

[1]

From: Dirk Behme 
Subject: [PATCH 1/2] DRM i.MX: ldb: Fix compiler warnings

Fix the compiler warnings

drivers/gpu/drm/imx/imx-ldb.c: In function 'imx_ldb_encoder_mode_fixup':
drivers/gpu/drm/imx/imx-ldb.c:118: warning: unused variable 'imx_ldb_ch'
drivers/gpu/drm/imx/imx-ldb.c: In function 'imx_ldb_encoder_prepare':
drivers/gpu/drm/imx/imx-ldb.c:134: warning: format '%ld' expects type 
'long int', but argument 6 has type 'int'

Signed-off-by: Dirk Behme 

---
  drivers/gpu/drm/imx/imx-ldb.c |4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

Index: freescale-linux-2.6-imx.git/drivers/gpu/drm/imx/imx-ldb.c
===
--- freescale-linux-2.6-imx.git.orig/drivers/gpu/drm/imx/imx-ldb.c
+++ freescale-linux-2.6-imx.git/drivers/gpu/drm/imx/imx-ldb.c
@@ -115,9 +115,9 @@ static bool imx_ldb_encoder_mode_fixup(s
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
  {
+/*
 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);

-/*
 adjusted_mode->clock = clk_round_rate(imx_ldb_ch->clk_pll,
 adjusted_mode->clock * 1000) / 1000;
  */
@@ -131,7 +131,7 @@ static void imx_ldb_encoder_prepare(stru
 int ret;
 struct drm_display_mode *mode = &encoder->crtc->mode;

-   dev_dbg(ldb->dev, "%s: now: %ld want: %ld\n", __func__,
+   dev_dbg(ldb->dev, "%s: now: %ld want: %d\n", __func__,
 clk_get_rate(imx_ldb_ch->clk_pll),
 mode->clock * 1000 * 7);
 clk_set_rate(imx_ldb_ch->clk_pll, mode->clock * 1000 * 7);




[PATCH 3/6] staging: drm/imx: add i.MX IPUv3 base driver

2012-09-14 Thread Dirk Behme
On 12.09.2012 12:31, Sascha Hauer wrote:
> The IPU is the Image Processing Unit found on i.MX51/53/6 SoCs. It
> features several units for image processing, this patch adds support
> for the units needed for Framebuffer support, namely:
> 
> - Display Controller (dc)
> - Display Interface (di)
> - Display Multi Fifo Controller (dmfc)
> - Display Processor (dp)
> - Image DMA Controller (idmac)
> 
> This patch is based on the Freescale driver, but follows a different
> approach. The Freescale code implements logical idmac channels and
> the handling of the subunits is hidden in common idmac code pathes
> in big switch/case statements. This patch instead just provides code
> and resource management for the different subunits. The user, in this
> case the framebuffer driver, decides how the different units play
> together.
> 
> The IPU has other units missing in this patch:
> 
> - CMOS Sensor Interface (csi)
> - Video Deinterlacer (vdi)
> - Sensor Multi FIFO Controler (smfc)
> - Image Converter (ic)
> - Image Rotator (irt)
> 
> Signed-off-by: Sascha Hauer 

> +static int ipu_reset(struct ipu_soc *ipu)
> +{
> +   unsigned long timeout;
> +
> +   ipu_cm_write(ipu, 0x807F, IPU_MEM_RST);
> +
> +   timeout = jiffies + msecs_to_jiffies(1000);
> +   while (ipu_cm_read(ipu, IPU_MEM_RST) & 0x8000) {
> +   if (time_after(jiffies, timeout))
> +   return -ETIME;
> +   cpu_relax();
> +   }
> +
> +   mdelay(300);
   

> +   return 0;
> +}

While doing some boot time measurement with i.MX6, we found that the 
above mdelay(300) is hurting regarding boot time. On i.MX6 you have two 
IPU instances, so in the end you get 600ms additional delay.

Looking at the Freescale code, this function looks like

static int ipu_reset(struct ipu_soc *ipu)
{
int timeout = 1000;

ipu_cm_write(ipu, 0x807F, IPU_MEM_RST);

while (ipu_cm_read(ipu, IPU_MEM_RST) & 0x8000) {
  if (!timeout--)
return -ETIME;
  msleep(1);
}
return 0;
}

So there is a msleep() in the loop but no mdelay() outside. Any idea why 
the mdelay() is needed here? Or what could be done regarding boot time 
with this?

Note: This is just a question, this shouldn't block the staging process.

Best regards

Dirk




Re: [PATCH RFC 1/3] rust: add useful ops for u64

2025-02-19 Thread Dirk Behme
On 17/02/2025 15:04, Alexandre Courbot wrote:
> It is common to build a u64 from its high and low parts obtained from
> two 32-bit registers. Conversely, it is also common to split a u64 into
> two u32s to write them into registers. Add an extension trait for u64
> that implement these methods in a new `num` module.
> 
> It is expected that this trait will be extended with other useful
> operations, and similar extension traits implemented for other types.
> 
> Signed-off-by: Alexandre Courbot 
> ---
>  rust/kernel/lib.rs |  1 +
>  rust/kernel/num.rs | 32 
>  2 files changed, 33 insertions(+)
> 
> diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
> index 
> 496ed32b0911a9fdbce5d26738b9cf7ef910b269..8c0c7c20a16aa96e3d3e444be3e03878650ddf77
>  100644
> --- a/rust/kernel/lib.rs
> +++ b/rust/kernel/lib.rs
> @@ -59,6 +59,7 @@
>  pub mod miscdevice;
>  #[cfg(CONFIG_NET)]
>  pub mod net;
> +pub mod num;
>  pub mod of;
>  pub mod page;
>  #[cfg(CONFIG_PCI)]
> diff --git a/rust/kernel/num.rs b/rust/kernel/num.rs
> new file mode 100644
> index 
> ..5e714cbda4575b8d74f50660580dc4c5683f8c2b
> --- /dev/null
> +++ b/rust/kernel/num.rs
> @@ -0,0 +1,32 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +//! Numerical and binary utilities for primitive types.
> +
> +/// Useful operations for `u64`.
> +pub trait U64Ext {
> +/// Build a `u64` by combining its `high` and `low` parts.
> +///
> +/// ```
> +/// use kernel::num::U64Ext;
> +/// assert_eq!(u64::from_u32s(0x01234567, 0x89abcdef), 
> 0x01234567_89abcdef);
> +/// ```
> +fn from_u32s(high: u32, low: u32) -> Self;
> +
> +/// Returns the `(high, low)` u32s that constitute `self`.
> +///
> +/// ```
> +/// use kernel::num::U64Ext;
> +/// assert_eq!(u64::into_u32s(0x01234567_89abcdef), (0x1234567, 
> 0x89abcdef));
> +/// ```
> +fn into_u32s(self) -> (u32, u32);
> +}
> +
> +impl U64Ext for u64 {
> +fn from_u32s(high: u32, low: u32) -> Self {
> +((high as u64) << u32::BITS) | low as u64
> +}
> +
> +fn into_u32s(self) -> (u32, u32) {
> +((self >> u32::BITS) as u32, self as u32)
> +}
> +}
Just as a question: Would it make sense to make this more generic?

For example

u64 -> u32, u32 / u32, u32 -> u64 (as done here)
u32 -> u16, u16 / u16, u16 -> u32
u16 -> u8, u8 / u8, u8 -> u16

Additionally, I wonder if this might be combined with the Integer trait
[1]? But the usize and signed ones might not make sense here...

Dirk

[1] E.g.

https://github.com/senekor/linux/commit/7291dcc98e8ab74e34c1600784ec9ff3e2fa32d0



Re: [PATCH RFC 1/3] rust: add useful ops for u64

2025-02-20 Thread Dirk Behme
On 18/02/2025 14:07, Alexandre Courbot wrote:
> On Tue Feb 18, 2025 at 7:07 PM JST, Dirk Behme wrote:
>> On 17/02/2025 15:04, Alexandre Courbot wrote:
>>> It is common to build a u64 from its high and low parts obtained from
>>> two 32-bit registers. Conversely, it is also common to split a u64 into
>>> two u32s to write them into registers. Add an extension trait for u64
>>> that implement these methods in a new `num` module.
>>>
>>> It is expected that this trait will be extended with other useful
>>> operations, and similar extension traits implemented for other types.
>>>
>>> Signed-off-by: Alexandre Courbot 
>>> ---
>>>  rust/kernel/lib.rs |  1 +
>>>  rust/kernel/num.rs | 32 
>>>  2 files changed, 33 insertions(+)
>>>
>>> diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
>>> index 
>>> 496ed32b0911a9fdbce5d26738b9cf7ef910b269..8c0c7c20a16aa96e3d3e444be3e03878650ddf77
>>>  100644
>>> --- a/rust/kernel/lib.rs
>>> +++ b/rust/kernel/lib.rs
>>> @@ -59,6 +59,7 @@
>>>  pub mod miscdevice;
>>>  #[cfg(CONFIG_NET)]
>>>  pub mod net;
>>> +pub mod num;
>>>  pub mod of;
>>>  pub mod page;
>>>  #[cfg(CONFIG_PCI)]
>>> diff --git a/rust/kernel/num.rs b/rust/kernel/num.rs
>>> new file mode 100644
>>> index 
>>> ..5e714cbda4575b8d74f50660580dc4c5683f8c2b
>>> --- /dev/null
>>> +++ b/rust/kernel/num.rs
>>> @@ -0,0 +1,32 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +
>>> +//! Numerical and binary utilities for primitive types.
>>> +
>>> +/// Useful operations for `u64`.
>>> +pub trait U64Ext {
>>> +/// Build a `u64` by combining its `high` and `low` parts.
>>> +///
>>> +/// ```
>>> +/// use kernel::num::U64Ext;
>>> +/// assert_eq!(u64::from_u32s(0x01234567, 0x89abcdef), 
>>> 0x01234567_89abcdef);
>>> +/// ```
>>> +fn from_u32s(high: u32, low: u32) -> Self;
>>> +
>>> +/// Returns the `(high, low)` u32s that constitute `self`.
>>> +///
>>> +/// ```
>>> +/// use kernel::num::U64Ext;
>>> +/// assert_eq!(u64::into_u32s(0x01234567_89abcdef), (0x1234567, 
>>> 0x89abcdef));
>>> +/// ```
>>> +fn into_u32s(self) -> (u32, u32);
>>> +}
>>> +
>>> +impl U64Ext for u64 {
>>> +fn from_u32s(high: u32, low: u32) -> Self {
>>> +((high as u64) << u32::BITS) | low as u64
>>> +}
>>> +
>>> +fn into_u32s(self) -> (u32, u32) {
>>> +((self >> u32::BITS) as u32, self as u32)
>>> +}
>>> +}
>> Just as a question: Would it make sense to make this more generic?
>>
>> For example
>>
>> u64 -> u32, u32 / u32, u32 -> u64 (as done here)
>> u32 -> u16, u16 / u16, u16 -> u32
>> u16 -> u8, u8 / u8, u8 -> u16
>>
>> Additionally, I wonder if this might be combined with the Integer trait
>> [1]? But the usize and signed ones might not make sense here...
>>
>> Dirk
>>
>> [1] E.g.
>>
>> https://github.com/senekor/linux/commit/7291dcc98e8ab74e34c1600784ec9ff3e2fa32d0
> 
> I agree something more generic would be nice. One drawback I see though
> is that it would have to use more generic (and lengthy) method names -
> i.e. `from_components(u32, u32)` instead of `from_u32s`.
> 
> I quickly tried to write a completely generic trait where the methods
> are auto-implemented from constants and associated types, but got stuck
> by the impossibility to use `as` in that context without a macro.


Being inspired by the Integer trait example [1] above, just as an idea,
I wonder if anything like

impl_split_merge! {
(u64, u32),
(u32, u16),
(u16, u8),
}

would be implementable?


> Regardless, I was looking for an already existing trait/module to
> leverage instead of introducing a whole new one, maybe the one you
> linked is what I was looking for?
Cheers,

Dirk