Re: [U-Boot] [PATCH V2 07/32] misc: add i.MX8 misc driver

2018-07-18 Thread Peng Fan


> -Original Message-
> From: Lokesh Vutla [mailto:lokeshvu...@ti.com]
> Sent: 2018年7月18日 17:05
> To: Peng Fan ; sba...@denx.de; Fabio Estevam
> 
> Cc: u-boot@lists.denx.de; dl-linux-imx 
> Subject: Re: [U-Boot] [PATCH V2 07/32] misc: add i.MX8 misc driver
> 
> 
> 
> On Wednesday 18 July 2018 02:22 PM, Peng Fan wrote:
> >
> >
> >> -Original Message-
> >> From: Lokesh Vutla [mailto:lokeshvu...@ti.com]
> >> Sent: 2018年7月18日 16:38
> >> To: Peng Fan ; sba...@denx.de; Fabio Estevam
> >> 
> >> Cc: u-boot@lists.denx.de; dl-linux-imx 
> >> Subject: Re: [U-Boot] [PATCH V2 07/32] misc: add i.MX8 misc driver
> >>
> >>
> >>
> >> On Wednesday 18 July 2018 07:05 AM, Peng Fan wrote:
> >>> Add i.MX8 MISC driver to handle the communication between
> >>> A35 Core and SCU.
> >>
> >>
> >> Ideally this is a good fit under drivers/remoteproc.  Any reason why
> >> UCLASS_REMOTEPROC is not considered?
> >
> > The SCU is booted by ROM, it provide services for other Cores.
> 
> Nice. I agree that it provide services for other cores. I am trying to 
> understand
> how the communication happens. So you must be writing into a mailbox IP?
> Then drivers/mailbox should be used to send and receive messages.

Actually the communication is very simple, one message unit with 4 send register
and 4 receive register. Use poll and no share memory involved.
So only a few lines code in the low level communication part.

Currently our device tree has not been merged into Linux upstream,
NXP vendor tree use a simple mu node, no firmware node.

In U-Boot, for simple, I not invent new firmware node, so I only
has a mu node. With one node supporting mailbox/firmware dirver,
this is not good.

Considering the lowlevel communication is very simple in U-Boot,
I directly merge the communication and protocol code in the 
driver/misc/imx8/*.c.

In future when Linux community accepted i.MX8 device tree, I could sync
and use a more clean implementation.

Thanks,
Peng.

> 
> Thanks and regards,
> Lokesh
> 
> > It is not like rpmsg things. I think the misc driver is a good fit for
> > my case.
> >
> > I also see that Tegra BPMP driver using misc driver.
> >
> > Thanks,
> > Peng.
> >
> >>
> >> Thanks and regards,
> >> Lokesh
> >>
> >>>
> >>> Signed-off-by: Peng Fan 
> >>> ---
> >>>  drivers/misc/Makefile  |   1 +
> >>>  drivers/misc/imx8/Makefile |   3 +
> >>>  drivers/misc/imx8/scu.c| 247
> >> +
> >>>  3 files changed, 251 insertions(+)
> >>>  create mode 100644 drivers/misc/imx8/Makefile  create mode 100644
> >>> drivers/misc/imx8/scu.c
> >>>
> >>> diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index
> >>> 4ce9d213f0..c0de02c30d 100644
> >>> --- a/drivers/misc/Makefile
> >>> +++ b/drivers/misc/Makefile
> >>> @@ -6,6 +6,7 @@
> >>>  obj-$(CONFIG_MISC) += misc-uclass.o
> >>>  obj-$(CONFIG_ALI152X) += ali512x.o
> >>>  obj-$(CONFIG_ALTERA_SYSID) += altera_sysid.o
> >>> +obj-$(CONFIG_ARCH_IMX8) += imx8/
> >>>  obj-$(CONFIG_ATSHA204A) += atsha204a-i2c.o
> >>>  obj-$(CONFIG_DS4510)  += ds4510.o
> >>>  obj-$(CONFIG_CBMEM_CONSOLE) += cbmem_console.o diff --git
> >>> a/drivers/misc/imx8/Makefile b/drivers/misc/imx8/Makefile new file
> >>> mode 100644 index 00..3395340d22
> >>> --- /dev/null
> >>> +++ b/drivers/misc/imx8/Makefile
> >>
> >>> @@ -0,0 +1,3 @@
> >>> +# SPDX-License-Identifier: GPL-2.0+
> >>> +
> >>> +obj-y += scu.o
> >>> diff --git a/drivers/misc/imx8/scu.c b/drivers/misc/imx8/scu.c new
> >>> file mode 100644 index 00..f12c7a96f2
> >>> --- /dev/null
> >>> +++ b/drivers/misc/imx8/scu.c
> >>> @@ -0,0 +1,247 @@
> >>> +// SPDX-License-Identifier: GPL-2.0
> >>> +/*
> >>> + * Copyright 2018 NXP
> >>> + *
> >>> + * Peng Fan 
> >>> + */
> >>> +
> >>> +#include 
> >>> +#include 
> >>> +#include 
> >>> +#include 
> >>> +#include 
> >>> +#include 
> >>> +#include 
> >>> +#include 
> >>> +#include 
> >>> +
> >>> +DECLARE_GLOBAL_DATA_PTR;
> >>> +
> >>> +struct mu_type {
> 

Re: [U-Boot] [PATCH V2 07/32] misc: add i.MX8 misc driver

2018-07-18 Thread Lokesh Vutla


On Wednesday 18 July 2018 02:22 PM, Peng Fan wrote:
> 
> 
>> -Original Message-
>> From: Lokesh Vutla [mailto:lokeshvu...@ti.com]
>> Sent: 2018年7月18日 16:38
>> To: Peng Fan ; sba...@denx.de; Fabio Estevam
>> 
>> Cc: u-boot@lists.denx.de; dl-linux-imx 
>> Subject: Re: [U-Boot] [PATCH V2 07/32] misc: add i.MX8 misc driver
>>
>>
>>
>> On Wednesday 18 July 2018 07:05 AM, Peng Fan wrote:
>>> Add i.MX8 MISC driver to handle the communication between
>>> A35 Core and SCU.
>>
>>
>> Ideally this is a good fit under drivers/remoteproc.  Any reason why
>> UCLASS_REMOTEPROC is not considered?
> 
> The SCU is booted by ROM, it provide services for other Cores.

Nice. I agree that it provide services for other cores. I am trying to
understand how the communication happens. So you must be writing into a
mailbox IP? Then drivers/mailbox should be used to send and receive
messages.

Thanks and regards,
Lokesh

> It is not like rpmsg things. I think the misc driver
> is a good fit for my case.
> 
> I also see that Tegra BPMP driver using misc driver.
> 
> Thanks,
> Peng.
> 
>>
>> Thanks and regards,
>> Lokesh
>>
>>>
>>> Signed-off-by: Peng Fan 
>>> ---
>>>  drivers/misc/Makefile  |   1 +
>>>  drivers/misc/imx8/Makefile |   3 +
>>>  drivers/misc/imx8/scu.c| 247
>> +
>>>  3 files changed, 251 insertions(+)
>>>  create mode 100644 drivers/misc/imx8/Makefile  create mode 100644
>>> drivers/misc/imx8/scu.c
>>>
>>> diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index
>>> 4ce9d213f0..c0de02c30d 100644
>>> --- a/drivers/misc/Makefile
>>> +++ b/drivers/misc/Makefile
>>> @@ -6,6 +6,7 @@
>>>  obj-$(CONFIG_MISC) += misc-uclass.o
>>>  obj-$(CONFIG_ALI152X) += ali512x.o
>>>  obj-$(CONFIG_ALTERA_SYSID) += altera_sysid.o
>>> +obj-$(CONFIG_ARCH_IMX8) += imx8/
>>>  obj-$(CONFIG_ATSHA204A) += atsha204a-i2c.o
>>>  obj-$(CONFIG_DS4510)  += ds4510.o
>>>  obj-$(CONFIG_CBMEM_CONSOLE) += cbmem_console.o diff --git
>>> a/drivers/misc/imx8/Makefile b/drivers/misc/imx8/Makefile new file
>>> mode 100644 index 00..3395340d22
>>> --- /dev/null
>>> +++ b/drivers/misc/imx8/Makefile
>>
>>> @@ -0,0 +1,3 @@
>>> +# SPDX-License-Identifier: GPL-2.0+
>>> +
>>> +obj-y += scu.o
>>> diff --git a/drivers/misc/imx8/scu.c b/drivers/misc/imx8/scu.c new
>>> file mode 100644 index 00..f12c7a96f2
>>> --- /dev/null
>>> +++ b/drivers/misc/imx8/scu.c
>>> @@ -0,0 +1,247 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +/*
>>> + * Copyright 2018 NXP
>>> + *
>>> + * Peng Fan 
>>> + */
>>> +
>>> +#include 
>>> +#include 
>>> +#include 
>>> +#include 
>>> +#include 
>>> +#include 
>>> +#include 
>>> +#include 
>>> +#include 
>>> +
>>> +DECLARE_GLOBAL_DATA_PTR;
>>> +
>>> +struct mu_type {
>>> +   u32 tr[4];
>>> +   u32 rr[4];
>>> +   u32 sr;
>>> +   u32 cr;
>>> +};
>>> +
>>> +struct imx8_scu {
>>> +   struct mu_type *base;
>>> +   struct udevice *clk;
>>> +   struct udevice *pinclk;
>>> +};
>>> +
>>> +#define MU_CR_GIE_MASK 0xF000u
>>> +#define MU_CR_RIE_MASK 0xF00u
>>> +#define MU_CR_GIR_MASK 0xFu
>>> +#define MU_CR_TIE_MASK 0xF0u
>>> +#define MU_CR_F_MASK   0x7u
>>> +#define MU_SR_TE0_MASK BIT(23)
>>> +#define MU_SR_RF0_MASK BIT(27)
>>> +#define MU_TR_COUNT4
>>> +#define MU_RR_COUNT4
>>> +static inline void mu_hal_init(struct mu_type *base) {
>>> +   /* Clear GIEn, RIEn, TIEn, GIRn and ABFn. */
>>> +   clrbits_le32(>cr, MU_CR_GIE_MASK | MU_CR_RIE_MASK |
>>> +MU_CR_TIE_MASK | MU_CR_GIR_MASK | MU_CR_F_MASK); }
>>> +
>>> +static int mu_hal_sendmsg(struct mu_type *base, u32 reg_index, u32
>>> +msg) {
>>> +   u32 mask = MU_SR_TE0_MASK >> reg_index;
>>> +   u32 val;
>>> +   int ret;
>>> +
>>> +   assert(reg_index < MU_TR_COUNT);
>>> +
>>> +   /* Wait TX register to be empty. */
>>> +   ret = readl_poll_timeout(>sr, val, val & mask, 1);
>>>

Re: [U-Boot] [PATCH V2 07/32] misc: add i.MX8 misc driver

2018-07-18 Thread Peng Fan


> -Original Message-
> From: Lokesh Vutla [mailto:lokeshvu...@ti.com]
> Sent: 2018年7月18日 16:38
> To: Peng Fan ; sba...@denx.de; Fabio Estevam
> 
> Cc: u-boot@lists.denx.de; dl-linux-imx 
> Subject: Re: [U-Boot] [PATCH V2 07/32] misc: add i.MX8 misc driver
> 
> 
> 
> On Wednesday 18 July 2018 07:05 AM, Peng Fan wrote:
> > Add i.MX8 MISC driver to handle the communication between
> > A35 Core and SCU.
> 
> 
> Ideally this is a good fit under drivers/remoteproc.  Any reason why
> UCLASS_REMOTEPROC is not considered?

The SCU is booted by ROM, it provide services for other Cores.
It is not like rpmsg things. I think the misc driver
is a good fit for my case.

I also see that Tegra BPMP driver using misc driver.

Thanks,
Peng.

> 
> Thanks and regards,
> Lokesh
> 
> >
> > Signed-off-by: Peng Fan 
> > ---
> >  drivers/misc/Makefile  |   1 +
> >  drivers/misc/imx8/Makefile |   3 +
> >  drivers/misc/imx8/scu.c| 247
> +
> >  3 files changed, 251 insertions(+)
> >  create mode 100644 drivers/misc/imx8/Makefile  create mode 100644
> > drivers/misc/imx8/scu.c
> >
> > diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index
> > 4ce9d213f0..c0de02c30d 100644
> > --- a/drivers/misc/Makefile
> > +++ b/drivers/misc/Makefile
> > @@ -6,6 +6,7 @@
> >  obj-$(CONFIG_MISC) += misc-uclass.o
> >  obj-$(CONFIG_ALI152X) += ali512x.o
> >  obj-$(CONFIG_ALTERA_SYSID) += altera_sysid.o
> > +obj-$(CONFIG_ARCH_IMX8) += imx8/
> >  obj-$(CONFIG_ATSHA204A) += atsha204a-i2c.o
> >  obj-$(CONFIG_DS4510)  += ds4510.o
> >  obj-$(CONFIG_CBMEM_CONSOLE) += cbmem_console.o diff --git
> > a/drivers/misc/imx8/Makefile b/drivers/misc/imx8/Makefile new file
> > mode 100644 index 00..3395340d22
> > --- /dev/null
> > +++ b/drivers/misc/imx8/Makefile
> 
> > @@ -0,0 +1,3 @@
> > +# SPDX-License-Identifier: GPL-2.0+
> > +
> > +obj-y += scu.o
> > diff --git a/drivers/misc/imx8/scu.c b/drivers/misc/imx8/scu.c new
> > file mode 100644 index 00..f12c7a96f2
> > --- /dev/null
> > +++ b/drivers/misc/imx8/scu.c
> > @@ -0,0 +1,247 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright 2018 NXP
> > + *
> > + * Peng Fan 
> > + */
> > +
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +struct mu_type {
> > +   u32 tr[4];
> > +   u32 rr[4];
> > +   u32 sr;
> > +   u32 cr;
> > +};
> > +
> > +struct imx8_scu {
> > +   struct mu_type *base;
> > +   struct udevice *clk;
> > +   struct udevice *pinclk;
> > +};
> > +
> > +#define MU_CR_GIE_MASK 0xF000u
> > +#define MU_CR_RIE_MASK 0xF00u
> > +#define MU_CR_GIR_MASK 0xFu
> > +#define MU_CR_TIE_MASK 0xF0u
> > +#define MU_CR_F_MASK   0x7u
> > +#define MU_SR_TE0_MASK BIT(23)
> > +#define MU_SR_RF0_MASK BIT(27)
> > +#define MU_TR_COUNT4
> > +#define MU_RR_COUNT4
> > +static inline void mu_hal_init(struct mu_type *base) {
> > +   /* Clear GIEn, RIEn, TIEn, GIRn and ABFn. */
> > +   clrbits_le32(>cr, MU_CR_GIE_MASK | MU_CR_RIE_MASK |
> > +MU_CR_TIE_MASK | MU_CR_GIR_MASK | MU_CR_F_MASK); }
> > +
> > +static int mu_hal_sendmsg(struct mu_type *base, u32 reg_index, u32
> > +msg) {
> > +   u32 mask = MU_SR_TE0_MASK >> reg_index;
> > +   u32 val;
> > +   int ret;
> > +
> > +   assert(reg_index < MU_TR_COUNT);
> > +
> > +   /* Wait TX register to be empty. */
> > +   ret = readl_poll_timeout(>sr, val, val & mask, 1);
> > +   if (ret < 0) {
> > +   printf("%s timeout\n", __func__);
> > +   return -ETIMEDOUT;
> > +   }
> > +
> > +   writel(msg, >tr[reg_index]);
> > +
> > +   return 0;
> > +}
> > +
> > +static int mu_hal_receivemsg(struct mu_type *base, u32 reg_index, u32
> > +*msg) {
> > +   u32 mask = MU_SR_RF0_MASK >> reg_index;
> > +   u32 val;
> > +   int ret;
> > +
> > +   assert(reg_index < MU_TR_COUNT);
> > +
> > +   /* Wait RX register to be full. */
> > +   ret = readl_poll_timeout(>sr, val, val & mask, 1);
> > +   if (re

Re: [U-Boot] [PATCH V2 07/32] misc: add i.MX8 misc driver

2018-07-18 Thread Lokesh Vutla


On Wednesday 18 July 2018 07:05 AM, Peng Fan wrote:
> Add i.MX8 MISC driver to handle the communication between
> A35 Core and SCU.


Ideally this is a good fit under drivers/remoteproc.  Any reason why
UCLASS_REMOTEPROC is not considered?

Thanks and regards,
Lokesh

> 
> Signed-off-by: Peng Fan 
> ---
>  drivers/misc/Makefile  |   1 +
>  drivers/misc/imx8/Makefile |   3 +
>  drivers/misc/imx8/scu.c| 247 
> +
>  3 files changed, 251 insertions(+)
>  create mode 100644 drivers/misc/imx8/Makefile
>  create mode 100644 drivers/misc/imx8/scu.c
> 
> diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
> index 4ce9d213f0..c0de02c30d 100644
> --- a/drivers/misc/Makefile
> +++ b/drivers/misc/Makefile
> @@ -6,6 +6,7 @@
>  obj-$(CONFIG_MISC) += misc-uclass.o
>  obj-$(CONFIG_ALI152X) += ali512x.o
>  obj-$(CONFIG_ALTERA_SYSID) += altera_sysid.o
> +obj-$(CONFIG_ARCH_IMX8) += imx8/
>  obj-$(CONFIG_ATSHA204A) += atsha204a-i2c.o
>  obj-$(CONFIG_DS4510)  += ds4510.o
>  obj-$(CONFIG_CBMEM_CONSOLE) += cbmem_console.o
> diff --git a/drivers/misc/imx8/Makefile b/drivers/misc/imx8/Makefile
> new file mode 100644
> index 00..3395340d22
> --- /dev/null
> +++ b/drivers/misc/imx8/Makefile

> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +
> +obj-y += scu.o
> diff --git a/drivers/misc/imx8/scu.c b/drivers/misc/imx8/scu.c
> new file mode 100644
> index 00..f12c7a96f2
> --- /dev/null
> +++ b/drivers/misc/imx8/scu.c
> @@ -0,0 +1,247 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2018 NXP
> + *
> + * Peng Fan 
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +struct mu_type {
> + u32 tr[4];
> + u32 rr[4];
> + u32 sr;
> + u32 cr;
> +};
> +
> +struct imx8_scu {
> + struct mu_type *base;
> + struct udevice *clk;
> + struct udevice *pinclk;
> +};
> +
> +#define MU_CR_GIE_MASK   0xF000u
> +#define MU_CR_RIE_MASK   0xF00u
> +#define MU_CR_GIR_MASK   0xFu
> +#define MU_CR_TIE_MASK   0xF0u
> +#define MU_CR_F_MASK 0x7u
> +#define MU_SR_TE0_MASK   BIT(23)
> +#define MU_SR_RF0_MASK   BIT(27)
> +#define MU_TR_COUNT  4
> +#define MU_RR_COUNT  4
> +static inline void mu_hal_init(struct mu_type *base)
> +{
> + /* Clear GIEn, RIEn, TIEn, GIRn and ABFn. */
> + clrbits_le32(>cr, MU_CR_GIE_MASK | MU_CR_RIE_MASK |
> +  MU_CR_TIE_MASK | MU_CR_GIR_MASK | MU_CR_F_MASK);
> +}
> +
> +static int mu_hal_sendmsg(struct mu_type *base, u32 reg_index, u32 msg)
> +{
> + u32 mask = MU_SR_TE0_MASK >> reg_index;
> + u32 val;
> + int ret;
> +
> + assert(reg_index < MU_TR_COUNT);
> +
> + /* Wait TX register to be empty. */
> + ret = readl_poll_timeout(>sr, val, val & mask, 1);
> + if (ret < 0) {
> + printf("%s timeout\n", __func__);
> + return -ETIMEDOUT;
> + }
> +
> + writel(msg, >tr[reg_index]);
> +
> + return 0;
> +}
> +
> +static int mu_hal_receivemsg(struct mu_type *base, u32 reg_index, u32 *msg)
> +{
> + u32 mask = MU_SR_RF0_MASK >> reg_index;
> + u32 val;
> + int ret;
> +
> + assert(reg_index < MU_TR_COUNT);
> +
> + /* Wait RX register to be full. */
> + ret = readl_poll_timeout(>sr, val, val & mask, 1);
> + if (ret < 0) {
> + printf("%s timeout\n", __func__);
> + return -ETIMEDOUT;
> + }
> +
> + *msg = readl(>rr[reg_index]);
> +
> + return 0;
> +}
> +
> +static void sc_ipc_read(struct mu_type *base, void *data)
> +{
> + struct sc_rpc_msg_s *msg = (struct sc_rpc_msg_s *)data;
> + u8 count = 0;
> +
> + /* Check parms */
> + if (!base || !msg)
> + return;
> +
> + /* Read first word */
> + mu_hal_receivemsg(base, 0, (u32 *)msg);
> + count++;
> +
> + /* Check size */
> + if (msg->size > SC_RPC_MAX_MSG) {
> + *((u32 *)msg) = 0;
> + return;
> + }
> +
> + /* Read remaining words */
> + while (count < msg->size) {
> + mu_hal_receivemsg(base, count % MU_RR_COUNT,
> +   >DATA.u32[count - 1]);
> + count++;
> + }
> +}
> +
> +static void sc_ipc_write(struct mu_type *base, void *data)
> +{
> + struct sc_rpc_msg_s *msg = (struct sc_rpc_msg_s *)data;
> + u8 count = 0;
> +
> + /* Check parms */
> + if (!base || !msg)
> + return;
> +
> + /* Check size */
> + if (msg->size > SC_RPC_MAX_MSG)
> + return;
> +
> + /* Write first word */
> + mu_hal_sendmsg(base, 0, *((u32 *)msg));
> + count++;
> +
> + /* Write remaining words */
> + while (count < msg->size) {
> + mu_hal_sendmsg(base, count % MU_TR_COUNT,
> +msg->DATA.u32[count - 

[U-Boot] [PATCH V2 07/32] misc: add i.MX8 misc driver

2018-07-17 Thread Peng Fan
Add i.MX8 MISC driver to handle the communication between
A35 Core and SCU.

Signed-off-by: Peng Fan 
---
 drivers/misc/Makefile  |   1 +
 drivers/misc/imx8/Makefile |   3 +
 drivers/misc/imx8/scu.c| 247 +
 3 files changed, 251 insertions(+)
 create mode 100644 drivers/misc/imx8/Makefile
 create mode 100644 drivers/misc/imx8/scu.c

diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 4ce9d213f0..c0de02c30d 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -6,6 +6,7 @@
 obj-$(CONFIG_MISC) += misc-uclass.o
 obj-$(CONFIG_ALI152X) += ali512x.o
 obj-$(CONFIG_ALTERA_SYSID) += altera_sysid.o
+obj-$(CONFIG_ARCH_IMX8) += imx8/
 obj-$(CONFIG_ATSHA204A) += atsha204a-i2c.o
 obj-$(CONFIG_DS4510)  += ds4510.o
 obj-$(CONFIG_CBMEM_CONSOLE) += cbmem_console.o
diff --git a/drivers/misc/imx8/Makefile b/drivers/misc/imx8/Makefile
new file mode 100644
index 00..3395340d22
--- /dev/null
+++ b/drivers/misc/imx8/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y += scu.o
diff --git a/drivers/misc/imx8/scu.c b/drivers/misc/imx8/scu.c
new file mode 100644
index 00..f12c7a96f2
--- /dev/null
+++ b/drivers/misc/imx8/scu.c
@@ -0,0 +1,247 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 NXP
+ *
+ * Peng Fan 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct mu_type {
+   u32 tr[4];
+   u32 rr[4];
+   u32 sr;
+   u32 cr;
+};
+
+struct imx8_scu {
+   struct mu_type *base;
+   struct udevice *clk;
+   struct udevice *pinclk;
+};
+
+#define MU_CR_GIE_MASK 0xF000u
+#define MU_CR_RIE_MASK 0xF00u
+#define MU_CR_GIR_MASK 0xFu
+#define MU_CR_TIE_MASK 0xF0u
+#define MU_CR_F_MASK   0x7u
+#define MU_SR_TE0_MASK BIT(23)
+#define MU_SR_RF0_MASK BIT(27)
+#define MU_TR_COUNT4
+#define MU_RR_COUNT4
+static inline void mu_hal_init(struct mu_type *base)
+{
+   /* Clear GIEn, RIEn, TIEn, GIRn and ABFn. */
+   clrbits_le32(>cr, MU_CR_GIE_MASK | MU_CR_RIE_MASK |
+MU_CR_TIE_MASK | MU_CR_GIR_MASK | MU_CR_F_MASK);
+}
+
+static int mu_hal_sendmsg(struct mu_type *base, u32 reg_index, u32 msg)
+{
+   u32 mask = MU_SR_TE0_MASK >> reg_index;
+   u32 val;
+   int ret;
+
+   assert(reg_index < MU_TR_COUNT);
+
+   /* Wait TX register to be empty. */
+   ret = readl_poll_timeout(>sr, val, val & mask, 1);
+   if (ret < 0) {
+   printf("%s timeout\n", __func__);
+   return -ETIMEDOUT;
+   }
+
+   writel(msg, >tr[reg_index]);
+
+   return 0;
+}
+
+static int mu_hal_receivemsg(struct mu_type *base, u32 reg_index, u32 *msg)
+{
+   u32 mask = MU_SR_RF0_MASK >> reg_index;
+   u32 val;
+   int ret;
+
+   assert(reg_index < MU_TR_COUNT);
+
+   /* Wait RX register to be full. */
+   ret = readl_poll_timeout(>sr, val, val & mask, 1);
+   if (ret < 0) {
+   printf("%s timeout\n", __func__);
+   return -ETIMEDOUT;
+   }
+
+   *msg = readl(>rr[reg_index]);
+
+   return 0;
+}
+
+static void sc_ipc_read(struct mu_type *base, void *data)
+{
+   struct sc_rpc_msg_s *msg = (struct sc_rpc_msg_s *)data;
+   u8 count = 0;
+
+   /* Check parms */
+   if (!base || !msg)
+   return;
+
+   /* Read first word */
+   mu_hal_receivemsg(base, 0, (u32 *)msg);
+   count++;
+
+   /* Check size */
+   if (msg->size > SC_RPC_MAX_MSG) {
+   *((u32 *)msg) = 0;
+   return;
+   }
+
+   /* Read remaining words */
+   while (count < msg->size) {
+   mu_hal_receivemsg(base, count % MU_RR_COUNT,
+ >DATA.u32[count - 1]);
+   count++;
+   }
+}
+
+static void sc_ipc_write(struct mu_type *base, void *data)
+{
+   struct sc_rpc_msg_s *msg = (struct sc_rpc_msg_s *)data;
+   u8 count = 0;
+
+   /* Check parms */
+   if (!base || !msg)
+   return;
+
+   /* Check size */
+   if (msg->size > SC_RPC_MAX_MSG)
+   return;
+
+   /* Write first word */
+   mu_hal_sendmsg(base, 0, *((u32 *)msg));
+   count++;
+
+   /* Write remaining words */
+   while (count < msg->size) {
+   mu_hal_sendmsg(base, count % MU_TR_COUNT,
+  msg->DATA.u32[count - 1]);
+   count++;
+   }
+}
+
+/*
+ * Note the function prototype use msgid as the 2nd parameter, here
+ * we take it as no_resp.
+ */
+static int imx8_scu_call(struct udevice *dev, int no_resp, void *tx_msg,
+int tx_size, void *rx_msg, int rx_size)
+{
+   struct imx8_scu *priv = dev_get_priv(dev);
+   sc_err_t result;
+
+   /* Expect tx_msg, rx_msg are the same value */
+   if