mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-24 14:25:56 +00:00
Merge tag 'u-boot-imx-next-20250313' of https://gitlab.denx.de/u-boot/custodians/u-boot-imx into next
CI: https://source.denx.de/u-boot/custodians/u-boot-imx/-/pipelines/25142 - Support Toradex i.MX6 Apalis/Colibri v1.2 SoM. - Guard tee.bin inclusion on imx9, - Remove unneeded regulator entry on DH i.MX6 DHCOM DRC02 devicetree. - Add i.MX mailbox driver - Convert ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE to Kconfig. - Cope with existing optee node on imx8m.
This commit is contained in:
commit
bbfabe2901
17 changed files with 527 additions and 24 deletions
|
@ -315,6 +315,7 @@ F: board/freescale/*mx*/
|
|||
F: board/freescale/common/
|
||||
F: common/spl/spl_imx_container.c
|
||||
F: doc/imx/
|
||||
F: drivers/mailbox/imx-mailbox.c
|
||||
F: drivers/serial/serial_mxc.c
|
||||
F: include/imx_container.h
|
||||
|
||||
|
|
|
@ -27,11 +27,6 @@
|
|||
};
|
||||
};
|
||||
|
||||
®_usb_otg_vbus {
|
||||
gpio = <&gpio3 31 GPIO_ACTIVE_HIGH>;
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
&wdog1 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
|
|
@ -1270,8 +1270,9 @@ static int ft_add_optee_node(void *fdt, struct bd_info *bd)
|
|||
}
|
||||
}
|
||||
|
||||
/* Locate the optee node if it exists or create it. */
|
||||
subpath = "optee";
|
||||
offs = fdt_add_subnode(fdt, offs, subpath);
|
||||
offs = fdt_find_or_add_subnode(fdt, offs, subpath);
|
||||
if (offs < 0) {
|
||||
printf("Could not create %s node.\n", subpath);
|
||||
return offs;
|
||||
|
|
|
@ -12,4 +12,6 @@ IMAGE A55 bl31.bin 0x204C0000
|
|||
IMAGE A55 bl31.bin 0x204E0000
|
||||
#endif
|
||||
IMAGE A55 u-boot.bin CONFIG_TEXT_BASE
|
||||
#ifdef CONFIG_OPTEE
|
||||
IMAGE A55 tee.bin 0x96000000
|
||||
#endif
|
||||
|
|
|
@ -133,7 +133,6 @@
|
|||
#define CFG_FM_PLAT_CLK_DIV 1
|
||||
#define CFG_SYS_FM1_CLK CFG_FM_PLAT_CLK_DIV
|
||||
#define CFG_SYS_FM_MURAM_SIZE 0x30000
|
||||
#define ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE
|
||||
#define QE_MURAM_SIZE 0x6000UL
|
||||
#define MAX_QE_RISC 1
|
||||
#define QE_NUM_OF_SNUM 28
|
||||
|
@ -146,7 +145,6 @@
|
|||
#define CFG_SYS_FM1_CLK 0
|
||||
#define CFG_QBMAN_CLK_DIV 1
|
||||
#define CFG_SYS_FM_MURAM_SIZE 0x30000
|
||||
#define ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE
|
||||
#define QE_MURAM_SIZE 0x6000UL
|
||||
#define MAX_QE_RISC 1
|
||||
#define QE_NUM_OF_SNUM 28
|
||||
|
@ -165,7 +163,6 @@
|
|||
#define CFG_SYS_PME_CLK CFG_PME_PLAT_CLK_DIV
|
||||
#define CFG_SYS_FM1_CLK 0
|
||||
#define CFG_SYS_FM_MURAM_SIZE 0x28000
|
||||
#define ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE
|
||||
|
||||
#elif defined(CONFIG_ARCH_C29X)
|
||||
#define CFG_SYS_FSL_SEC_IDX_OFFSET 0x20000
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <dwc_ahsata.h>
|
||||
#include <env.h>
|
||||
#include <fsl_esdhc_imx.h>
|
||||
#include <i2c.h>
|
||||
#include <imx_thermal.h>
|
||||
#include <micrel.h>
|
||||
#include <miiphy.h>
|
||||
|
@ -77,6 +78,8 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||
|
||||
#define APALIS_IMX6_SATA_INIT_RETRIES 10
|
||||
|
||||
#define I2C_PWR 1
|
||||
|
||||
int dram_init(void)
|
||||
{
|
||||
/* use the DDR controllers configured size */
|
||||
|
@ -689,6 +692,32 @@ int board_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool is_som_variant_1_2(void)
|
||||
{
|
||||
struct udevice *bus;
|
||||
struct udevice *i2c_dev;
|
||||
int ret;
|
||||
|
||||
ret = uclass_get_device_by_seq(UCLASS_I2C, I2C_PWR, &bus);
|
||||
if (ret) {
|
||||
printf("Failed to get I2C_PWR\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* V1.2 uses the TLA2024 at 0x49 instead of the STMPE811 at 0x41 */
|
||||
ret = dm_i2c_probe(bus, 0x49, 0, &i2c_dev);
|
||||
|
||||
return (bool)!ret;
|
||||
}
|
||||
|
||||
static void select_dt_from_module_version(void)
|
||||
{
|
||||
if (is_som_variant_1_2())
|
||||
env_set("variant", "-v1.2");
|
||||
else
|
||||
env_set("variant", "");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BOARD_LATE_INIT
|
||||
int board_late_init(void)
|
||||
{
|
||||
|
@ -696,6 +725,8 @@ int board_late_init(void)
|
|||
char env_str[256];
|
||||
u32 rev;
|
||||
|
||||
select_dt_from_module_version();
|
||||
|
||||
rev = get_board_revision();
|
||||
snprintf(env_str, ARRAY_SIZE(env_str), "%.4x", rev);
|
||||
env_set("board_rev", env_str);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <cpu.h>
|
||||
#include <dm/platform_data/serial_mxc.h>
|
||||
#include <fsl_esdhc_imx.h>
|
||||
#include <i2c.h>
|
||||
#include <imx_thermal.h>
|
||||
#include <miiphy.h>
|
||||
#include <netdev.h>
|
||||
|
@ -71,6 +72,8 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||
|
||||
#define OUTPUT_RGB (PAD_CTL_SPEED_MED|PAD_CTL_DSE_60ohm|PAD_CTL_SRE_FAST)
|
||||
|
||||
#define I2C_PWR 1
|
||||
|
||||
int dram_init(void)
|
||||
{
|
||||
/* use the DDR controllers configured size */
|
||||
|
@ -609,6 +612,32 @@ int board_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool is_som_variant_1_2(void)
|
||||
{
|
||||
struct udevice *bus;
|
||||
struct udevice *i2c_dev;
|
||||
int ret;
|
||||
|
||||
ret = uclass_get_device_by_seq(UCLASS_I2C, I2C_PWR, &bus);
|
||||
if (ret) {
|
||||
printf("Failed to get I2C_PWR\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* V1.2 uses the TLA2024 at 0x49 instead of the STMPE811 at 0x41 */
|
||||
ret = dm_i2c_probe(bus, 0x49, 0, &i2c_dev);
|
||||
|
||||
return (bool)!ret;
|
||||
}
|
||||
|
||||
static void select_dt_from_module_version(void)
|
||||
{
|
||||
if (is_som_variant_1_2())
|
||||
env_set("variant", "-v1.2");
|
||||
else
|
||||
env_set("variant", "");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BOARD_LATE_INIT
|
||||
int board_late_init(void)
|
||||
{
|
||||
|
@ -616,6 +645,8 @@ int board_late_init(void)
|
|||
char env_str[256];
|
||||
u32 rev;
|
||||
|
||||
select_dt_from_module_version();
|
||||
|
||||
rev = get_board_revision();
|
||||
snprintf(env_str, ARRAY_SIZE(env_str), "%.4x", rev);
|
||||
env_set("board_rev", env_str);
|
||||
|
|
|
@ -31,7 +31,7 @@ CONFIG_DISTRO_DEFAULTS=y
|
|||
CONFIG_BOOTDELAY=1
|
||||
CONFIG_BOOTCOMMAND="run distro_bootcmd; usb start; setenv stdout serial,vidconsole; setenv stdin serial,usbkbd"
|
||||
CONFIG_USE_PREBOOT=y
|
||||
CONFIG_PREBOOT="test -n ${fdtfile} || setenv fdtfile imx6q-apalis-${fdt_board}.dtb"
|
||||
CONFIG_PREBOOT="test -n ${fdtfile} || setenv fdtfile imx6q-apalis${variant}-${fdt_board}.dtb"
|
||||
CONFIG_SYS_CBSIZE=1024
|
||||
CONFIG_SYS_PBSIZE=1055
|
||||
CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE=y
|
||||
|
|
|
@ -30,7 +30,7 @@ CONFIG_DISTRO_DEFAULTS=y
|
|||
CONFIG_BOOTDELAY=1
|
||||
CONFIG_BOOTCOMMAND="run distro_bootcmd; usb start; setenv stdout serial,vidconsole; setenv stdin serial,usbkbd"
|
||||
CONFIG_USE_PREBOOT=y
|
||||
CONFIG_PREBOOT="test -n ${fdtfile} || setenv fdtfile imx6dl-colibri-${fdt_board}.dtb"
|
||||
CONFIG_PREBOOT="test -n ${fdtfile} || setenv fdtfile imx6dl-colibri${variant}-${fdt_board}.dtb"
|
||||
CONFIG_SYS_CBSIZE=1024
|
||||
CONFIG_SYS_PBSIZE=1056
|
||||
CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE=y
|
||||
|
|
|
@ -21,6 +21,13 @@ config APPLE_MBOX
|
|||
such as the System Management Controller (SMC) and NVMe and this
|
||||
driver is required to get that functionality up and running.
|
||||
|
||||
config IMX_MU_MBOX
|
||||
bool "Enable i.MX MU MBOX support"
|
||||
depends on DM_MAILBOX
|
||||
help
|
||||
Enable support for i.MX Messaging Unit for communication with other
|
||||
processors on the SoC using mailbox interface
|
||||
|
||||
config SANDBOX_MBOX
|
||||
bool "Enable the sandbox mailbox test driver"
|
||||
depends on DM_MAILBOX && SANDBOX
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
obj-$(CONFIG_$(XPL_)DM_MAILBOX) += mailbox-uclass.o
|
||||
obj-$(CONFIG_APPLE_MBOX) += apple-mbox.o
|
||||
obj-$(CONFIG_IMX_MU_MBOX) += imx-mailbox.o
|
||||
obj-$(CONFIG_SANDBOX_MBOX) += sandbox-mbox.o
|
||||
obj-$(CONFIG_SANDBOX_MBOX) += sandbox-mbox-test.o
|
||||
obj-$(CONFIG_STM32_IPCC) += stm32-ipcc.o
|
||||
|
|
443
drivers/mailbox/imx-mailbox.c
Normal file
443
drivers/mailbox/imx-mailbox.c
Normal file
|
@ -0,0 +1,443 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2025 NXP
|
||||
*/
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <dm.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <mailbox-uclass.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/compat.h>
|
||||
|
||||
/* This driver only exposes the status bits to keep with the
|
||||
* polling methodology of u-boot.
|
||||
*/
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#define IMX_MU_CHANS 24
|
||||
|
||||
#define IMX_MU_V2_PAR_OFF 0x4
|
||||
#define IMX_MU_V2_TR_MASK GENMASK(7, 0)
|
||||
#define IMX_MU_V2_RR_MASK GENMASK(15, 8)
|
||||
|
||||
enum imx_mu_chan_type {
|
||||
IMX_MU_TYPE_TX = 0, /* Tx */
|
||||
IMX_MU_TYPE_RX = 1, /* Rx */
|
||||
IMX_MU_TYPE_TXDB = 2, /* Tx doorbell */
|
||||
IMX_MU_TYPE_RXDB = 3, /* Rx doorbell */
|
||||
IMX_MU_TYPE_RST = 4, /* Reset */
|
||||
IMX_MU_TYPE_TXDB_V2 = 5, /* Tx doorbell with S/W ACK */
|
||||
};
|
||||
|
||||
enum imx_mu_xcr {
|
||||
IMX_MU_CR,
|
||||
IMX_MU_GIER,
|
||||
IMX_MU_GCR,
|
||||
IMX_MU_TCR,
|
||||
IMX_MU_RCR,
|
||||
IMX_MU_xCR_MAX,
|
||||
};
|
||||
|
||||
enum imx_mu_xsr {
|
||||
IMX_MU_SR,
|
||||
IMX_MU_GSR,
|
||||
IMX_MU_TSR,
|
||||
IMX_MU_RSR,
|
||||
IMX_MU_xSR_MAX,
|
||||
};
|
||||
|
||||
struct imx_mu_con_priv {
|
||||
unsigned int idx;
|
||||
enum imx_mu_chan_type type;
|
||||
struct mbox_chan *chan;
|
||||
};
|
||||
|
||||
enum imx_mu_type {
|
||||
IMX_MU_V1,
|
||||
IMX_MU_V2 = BIT(1),
|
||||
IMX_MU_V2_S4 = BIT(15),
|
||||
IMX_MU_V2_IRQ = BIT(16),
|
||||
};
|
||||
|
||||
struct imx_mu {
|
||||
void __iomem *base;
|
||||
const struct imx_mu_dcfg *dcfg;
|
||||
u32 num_tr;
|
||||
u32 num_rr;
|
||||
/* use pointers to channel as a way to reserve channels */
|
||||
struct mbox_chan *channels[IMX_MU_CHANS];
|
||||
struct imx_mu_con_priv con_priv[IMX_MU_CHANS];
|
||||
};
|
||||
|
||||
struct imx_mu_dcfg {
|
||||
int (*tx)(struct imx_mu *plat, struct imx_mu_con_priv *cp, const void *data);
|
||||
int (*rx)(struct imx_mu *plat, struct imx_mu_con_priv *cp);
|
||||
int (*rxdb)(struct imx_mu *plat, struct imx_mu_con_priv *cp);
|
||||
int (*init)(struct imx_mu *plat);
|
||||
int (*of_xlate)(struct mbox_chan *chan, struct ofnode_phandle_args *args);
|
||||
enum imx_mu_type type;
|
||||
u32 xTR; /* Transmit Register0 */
|
||||
u32 xRR; /* Receive Register0 */
|
||||
u32 xSR[IMX_MU_xSR_MAX]; /* Status Registers */
|
||||
u32 xCR[IMX_MU_xCR_MAX]; /* Control Registers */
|
||||
};
|
||||
|
||||
#define IMX_MU_xSR_GIPn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(28 + (3 - (x))))
|
||||
#define IMX_MU_xSR_RFn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(24 + (3 - (x))))
|
||||
#define IMX_MU_xSR_TEn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(20 + (3 - (x))))
|
||||
|
||||
/* General Purpose Interrupt Enable */
|
||||
#define IMX_MU_xCR_GIEn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(28 + (3 - (x))))
|
||||
/* Receive Interrupt Enable */
|
||||
#define IMX_MU_xCR_RIEn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(24 + (3 - (x))))
|
||||
/* Transmit Interrupt Enable */
|
||||
#define IMX_MU_xCR_TIEn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(20 + (3 - (x))))
|
||||
/* General Purpose Interrupt Request */
|
||||
#define IMX_MU_xCR_GIRn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(16 + (3 - (x))))
|
||||
/* MU reset */
|
||||
#define IMX_MU_xCR_RST(type) (type & IMX_MU_V2 ? BIT(0) : BIT(5))
|
||||
#define IMX_MU_xSR_RST(type) (type & IMX_MU_V2 ? BIT(0) : BIT(7))
|
||||
|
||||
static void imx_mu_write(struct imx_mu *plat, u32 val, u32 offs)
|
||||
{
|
||||
iowrite32(val, plat->base + offs);
|
||||
}
|
||||
|
||||
static u32 imx_mu_read(struct imx_mu *plat, u32 offs)
|
||||
{
|
||||
return ioread32(plat->base + offs);
|
||||
}
|
||||
|
||||
static u32 imx_mu_xcr_rmw(struct imx_mu *plat, enum imx_mu_xcr type, u32 set, u32 clr)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = imx_mu_read(plat, plat->dcfg->xCR[type]);
|
||||
val &= ~clr;
|
||||
val |= set;
|
||||
imx_mu_write(plat, val, plat->dcfg->xCR[type]);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/* check that the channel is open or owned by caller */
|
||||
static int imx_mu_check_channel(struct mbox_chan *chan)
|
||||
{
|
||||
struct imx_mu *plat = dev_get_plat(chan->dev);
|
||||
|
||||
if (plat->channels[chan->id]) {
|
||||
/* if reserved check that caller owns */
|
||||
if (plat->channels[chan->id] == chan)
|
||||
return 1; /* caller owns the channel */
|
||||
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
return 0; /* channel empty */
|
||||
}
|
||||
|
||||
static int imx_mu_chan_request(struct mbox_chan *chan)
|
||||
{
|
||||
struct imx_mu *plat = dev_get_plat(chan->dev);
|
||||
struct imx_mu_con_priv *cp;
|
||||
enum imx_mu_chan_type type;
|
||||
int idx;
|
||||
|
||||
type = chan->id / 4;
|
||||
idx = chan->id % 4;
|
||||
|
||||
if (imx_mu_check_channel(chan) < 0) /* check if channel already in use */
|
||||
return -EPERM;
|
||||
|
||||
plat->channels[chan->id] = chan;
|
||||
chan->con_priv = kcalloc(1, sizeof(struct imx_mu_con_priv), 0);
|
||||
if (!chan->con_priv)
|
||||
return -ENOMEM;
|
||||
cp = chan->con_priv;
|
||||
cp->idx = idx;
|
||||
cp->type = type;
|
||||
cp->chan = chan;
|
||||
|
||||
switch (type) {
|
||||
case IMX_MU_TYPE_RX:
|
||||
imx_mu_xcr_rmw(plat, IMX_MU_RCR, IMX_MU_xCR_RIEn(plat->dcfg->type, idx), 0);
|
||||
break;
|
||||
case IMX_MU_TYPE_TXDB_V2:
|
||||
case IMX_MU_TYPE_TXDB:
|
||||
case IMX_MU_TYPE_RXDB:
|
||||
imx_mu_xcr_rmw(plat, IMX_MU_GIER, IMX_MU_xCR_GIEn(plat->dcfg->type, idx), 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx_mu_chan_free(struct mbox_chan *chan)
|
||||
{
|
||||
struct imx_mu *plat = dev_get_plat(chan->dev);
|
||||
struct imx_mu_con_priv *cp = chan->con_priv;
|
||||
|
||||
if (imx_mu_check_channel(chan) <= 0) /* check that the channel is also not empty */
|
||||
return -EINVAL;
|
||||
|
||||
/* if you own channel and channel is NOT empty */
|
||||
plat->channels[chan->id] = NULL;
|
||||
switch (cp->type) {
|
||||
case IMX_MU_TYPE_TX:
|
||||
imx_mu_xcr_rmw(plat, IMX_MU_TCR, 0, IMX_MU_xCR_TIEn(plat->dcfg->type, cp->idx));
|
||||
break;
|
||||
case IMX_MU_TYPE_RX:
|
||||
imx_mu_xcr_rmw(plat, IMX_MU_RCR, 0, IMX_MU_xCR_RIEn(plat->dcfg->type, cp->idx));
|
||||
break;
|
||||
case IMX_MU_TYPE_TXDB_V2:
|
||||
case IMX_MU_TYPE_TXDB:
|
||||
case IMX_MU_TYPE_RXDB:
|
||||
imx_mu_xcr_rmw(plat, IMX_MU_GIER, 0, IMX_MU_xCR_GIEn(plat->dcfg->type, cp->idx));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
kfree(cp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx_mu_send(struct mbox_chan *chan, const void *data)
|
||||
{
|
||||
struct imx_mu *plat = dev_get_plat(chan->dev);
|
||||
struct imx_mu_con_priv *cp = chan->con_priv;
|
||||
|
||||
if (imx_mu_check_channel(chan) < 1) /* return if channel isn't owned */
|
||||
return -EPERM;
|
||||
|
||||
return plat->dcfg->tx(plat, cp, data);
|
||||
}
|
||||
|
||||
static int imx_mu_recv(struct mbox_chan *chan, void *data)
|
||||
{
|
||||
struct imx_mu *plat = dev_get_plat(chan->dev);
|
||||
struct imx_mu_con_priv *cp = chan->con_priv;
|
||||
u32 ctrl, val;
|
||||
|
||||
if (imx_mu_check_channel(chan) < 1) /* return if channel isn't owned */
|
||||
return -EPERM;
|
||||
|
||||
switch (cp->type) {
|
||||
case IMX_MU_TYPE_TXDB_V2:
|
||||
case IMX_MU_TYPE_RXDB:
|
||||
/* check if GSR[GIRn] bit is set */
|
||||
if (readx_poll_timeout(ioread32, plat->base + plat->dcfg->xSR[IMX_MU_GSR],
|
||||
val, val & BIT(cp->idx), 1000000) < 0)
|
||||
return -EBUSY;
|
||||
|
||||
ctrl = imx_mu_read(plat, plat->dcfg->xCR[IMX_MU_GIER]);
|
||||
val = imx_mu_read(plat, plat->dcfg->xSR[IMX_MU_GSR]);
|
||||
val &= IMX_MU_xSR_GIPn(plat->dcfg->type, cp->idx) &
|
||||
(ctrl & IMX_MU_xCR_GIEn(plat->dcfg->type, cp->idx));
|
||||
break;
|
||||
default:
|
||||
dev_warn(chan->dev, "Unhandled channel type %d\n", cp->type);
|
||||
return -EOPNOTSUPP;
|
||||
};
|
||||
|
||||
if (val == IMX_MU_xSR_GIPn(plat->dcfg->type, cp->idx))
|
||||
plat->dcfg->rxdb(plat, cp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx_mu_of_to_plat(struct udevice *dev)
|
||||
{
|
||||
struct imx_mu *plat = dev_get_plat(dev);
|
||||
fdt_addr_t addr;
|
||||
|
||||
addr = dev_read_addr(dev);
|
||||
if (addr == FDT_ADDR_T_NONE)
|
||||
return -ENODEV;
|
||||
|
||||
plat->base = (struct mu_type *)addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx_mu_init_generic(struct imx_mu *plat)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int val;
|
||||
|
||||
if (plat->num_rr > 4 || plat->num_tr > 4) {
|
||||
WARN_ONCE(true, "%s not support TR/RR larger than 4\n", __func__);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* Set default MU configuration */
|
||||
for (i = 0; i < IMX_MU_xCR_MAX; i++)
|
||||
imx_mu_write(plat, 0, plat->dcfg->xCR[i]);
|
||||
|
||||
/* Clear any pending GIP */
|
||||
val = imx_mu_read(plat, plat->dcfg->xSR[IMX_MU_GSR]);
|
||||
imx_mu_write(plat, val, plat->dcfg->xSR[IMX_MU_GSR]);
|
||||
|
||||
/* Clear any pending RSR */
|
||||
for (i = 0; i < plat->num_rr; i++)
|
||||
imx_mu_read(plat, plat->dcfg->xRR + i * 4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx_mu_generic_of_xlate(struct mbox_chan *chan, struct ofnode_phandle_args *args)
|
||||
{
|
||||
enum imx_mu_chan_type type;
|
||||
int idx, cid;
|
||||
|
||||
if (args->args_count != 2) {
|
||||
dev_err(chan->dev, "Invalid argument count %d\n", args->args_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
type = args->args[0]; /* channel type */
|
||||
idx = args->args[1]; /* index */
|
||||
|
||||
cid = type * 4 + idx;
|
||||
if (cid >= IMX_MU_CHANS) {
|
||||
dev_err(chan->dev, "Not supported channel number: %d. (type: %d, idx: %d)\n",
|
||||
cid, type, idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
chan->id = cid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx_mu_generic_tx(struct imx_mu *plat, struct imx_mu_con_priv *cp,
|
||||
const void *data)
|
||||
{
|
||||
switch (cp->type) {
|
||||
case IMX_MU_TYPE_TXDB_V2:
|
||||
imx_mu_xcr_rmw(plat, IMX_MU_GCR, IMX_MU_xCR_GIRn(plat->dcfg->type, cp->idx), 0);
|
||||
break;
|
||||
default:
|
||||
dev_warn(cp->chan->dev, "Send data on wrong channel type: %d\n", cp->type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx_mu_generic_rxdb(struct imx_mu *plat, struct imx_mu_con_priv *cp)
|
||||
{
|
||||
imx_mu_write(plat, IMX_MU_xSR_GIPn(plat->dcfg->type, cp->idx),
|
||||
plat->dcfg->xSR[IMX_MU_GSR]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct imx_mu_dcfg imx_mu_cfg_imx6sx = {
|
||||
.tx = imx_mu_generic_tx,
|
||||
.rxdb = imx_mu_generic_rxdb,
|
||||
.init = imx_mu_init_generic,
|
||||
.of_xlate = imx_mu_generic_of_xlate,
|
||||
.type = IMX_MU_V1,
|
||||
.xTR = 0x0,
|
||||
.xRR = 0x10,
|
||||
.xSR = {0x20, 0x20, 0x20, 0x20},
|
||||
.xCR = {0x24, 0x24, 0x24, 0x24, 0x24},
|
||||
};
|
||||
|
||||
static const struct imx_mu_dcfg imx_mu_cfg_imx7ulp = {
|
||||
.tx = imx_mu_generic_tx,
|
||||
.rxdb = imx_mu_generic_rxdb,
|
||||
.init = imx_mu_init_generic,
|
||||
.of_xlate = imx_mu_generic_of_xlate,
|
||||
.type = IMX_MU_V1,
|
||||
.xTR = 0x20,
|
||||
.xRR = 0x40,
|
||||
.xSR = {0x60, 0x60, 0x60, 0x60},
|
||||
.xCR = {0x64, 0x64, 0x64, 0x64, 0x64},
|
||||
};
|
||||
|
||||
static const struct imx_mu_dcfg imx_mu_cfg_imx95 = {
|
||||
.tx = imx_mu_generic_tx,
|
||||
.rxdb = imx_mu_generic_rxdb,
|
||||
.init = imx_mu_init_generic,
|
||||
.of_xlate = imx_mu_generic_of_xlate,
|
||||
.type = IMX_MU_V2,
|
||||
.xTR = 0x200,
|
||||
.xRR = 0x280,
|
||||
.xSR = {0xC, 0x118, 0x124, 0x12C},
|
||||
.xCR = {0x8, 0x110, 0x114, 0x120, 0x128},
|
||||
};
|
||||
|
||||
static const struct udevice_id ids[] = {
|
||||
{ .compatible = "fsl,imx6sx-mu", .data = (ulong)&imx_mu_cfg_imx6sx },
|
||||
{ .compatible = "fsl,imx7ulp-mu", .data = (ulong)&imx_mu_cfg_imx7ulp },
|
||||
{ .compatible = "fsl,imx95-mu", .data = (ulong)&imx_mu_cfg_imx95 },
|
||||
{ }
|
||||
};
|
||||
|
||||
int imx_mu_of_xlate(struct mbox_chan *chan, struct ofnode_phandle_args *args)
|
||||
{
|
||||
struct imx_mu *plat = dev_get_plat(chan->dev);
|
||||
|
||||
return plat->dcfg->of_xlate(chan, args);
|
||||
}
|
||||
|
||||
struct mbox_ops imx_mu_ops = {
|
||||
.of_xlate = imx_mu_of_xlate,
|
||||
.request = imx_mu_chan_request,
|
||||
.rfree = imx_mu_chan_free,
|
||||
.send = imx_mu_send,
|
||||
.recv = imx_mu_recv,
|
||||
};
|
||||
|
||||
static void imx_mu_get_tr_rr(struct imx_mu *plat)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (plat->dcfg->type & IMX_MU_V2) {
|
||||
val = imx_mu_read(plat, IMX_MU_V2_PAR_OFF);
|
||||
plat->num_tr = FIELD_GET(IMX_MU_V2_TR_MASK, val);
|
||||
plat->num_rr = FIELD_GET(IMX_MU_V2_RR_MASK, val);
|
||||
} else {
|
||||
plat->num_tr = 4;
|
||||
plat->num_rr = 4;
|
||||
}
|
||||
}
|
||||
|
||||
static int imx_mu_probe(struct udevice *dev)
|
||||
{
|
||||
struct imx_mu *plat = dev_get_plat(dev);
|
||||
int ret;
|
||||
|
||||
debug("%s(dev=%p)\n", __func__, dev);
|
||||
|
||||
plat->dcfg = (void *)dev_get_driver_data(dev);
|
||||
|
||||
imx_mu_get_tr_rr(plat);
|
||||
|
||||
ret = plat->dcfg->init(plat);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to init MU\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_DRIVER(imx_mu) = {
|
||||
.name = "imx-mu",
|
||||
.id = UCLASS_MAILBOX,
|
||||
.of_match = ids,
|
||||
.of_to_plat = imx_mu_of_to_plat,
|
||||
.plat_auto = sizeof(struct imx_mu),
|
||||
.probe = imx_mu_probe,
|
||||
.ops = &imx_mu_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
|
@ -928,6 +928,12 @@ config ESDHC_DETECT_QUIRK
|
|||
bool "QIXIS-based eSDHC quirk detection"
|
||||
depends on FSL_ESDHC && FSL_QIXIS
|
||||
|
||||
config ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE
|
||||
bool
|
||||
depends on FSL_ESDHC || FSL_ESDHC_IMX
|
||||
def_bool y if ARCH_T1024 || ARCH_T1040 || ARCH_T1042 || ARCH_T2080 \
|
||||
|| FSL_ESDHC_IMX
|
||||
|
||||
config FSL_ESDHC_IMX
|
||||
bool "Freescale/NXP i.MX eSDHC controller support"
|
||||
help
|
||||
|
|
|
@ -40,12 +40,6 @@
|
|||
#include <linux/iopoll.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#ifndef ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE
|
||||
#ifdef CONFIG_FSL_USDHC
|
||||
#define ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#define SDHCI_IRQ_EN_BITS (IRQSTATEN_CC | IRQSTATEN_TC | \
|
||||
|
@ -376,7 +370,7 @@ static int esdhc_setup_data(struct fsl_esdhc_priv *priv, struct mmc *mmc,
|
|||
(timeout == 4 || timeout == 8 || timeout == 12))
|
||||
timeout++;
|
||||
|
||||
if (IS_ENABLED(ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE))
|
||||
if (IS_ENABLED(CONFIG_ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE))
|
||||
timeout = 0xE;
|
||||
|
||||
esdhc_clrsetbits32(®s->sysctl, SYSCTL_TIMEOUT_MASK, timeout << 16);
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
|
||||
#include <asm/arch/imx-regs.h>
|
||||
|
||||
#define ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE 1
|
||||
|
||||
#define PHYS_SDRAM 0x80000000
|
||||
#define PHYS_SDRAM_SIZE (32 * 1024 * 1024)
|
||||
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
|
||||
#include <asm/arch/imx-regs.h>
|
||||
|
||||
#define ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE 1
|
||||
|
||||
#define PHYS_SDRAM 0x80000000
|
||||
#define PHYS_SDRAM_SIZE (32 * 1024 * 1024)
|
||||
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
|
||||
#include <asm/arch/imx-regs.h>
|
||||
|
||||
#define ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE 1
|
||||
|
||||
/*
|
||||
* Configuration of the external SDRAM memory
|
||||
*/
|
||||
|
|
Loading…
Add table
Reference in a new issue