summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2022-08-11 13:43:00 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2022-08-11 13:43:00 +0200
commit3fcf4400a7b051bdbe9fc175b88336519099ff22 (patch)
tree59e47312f23697970b3defc010a15f367b8e5082 /drivers
parentb33c2913d747d3c55019a1d310427ca2697de6fc (diff)
parent22a073e3a9cdbc8034d5c58a6840e2567e5b3ddd (diff)
downloadbarebox-3fcf4400a7b051bdbe9fc175b88336519099ff22.tar.gz
barebox-3fcf4400a7b051bdbe9fc175b88336519099ff22.tar.xz
Merge branch 'for-next/imx'
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ddr/imx8m/ddr_init.c33
-rw-r--r--drivers/ddr/imx8m/ddrphy_train.c74
-rw-r--r--drivers/i2c/busses/i2c-imx-early.c21
-rw-r--r--drivers/mci/imx-esdhc-pbl.c2
-rw-r--r--drivers/net/fec_imx.c11
-rw-r--r--drivers/phy/phy-core.c11
-rw-r--r--drivers/usb/imx/chipidea-imx.c10
-rw-r--r--drivers/watchdog/imxwd.c18
8 files changed, 114 insertions, 66 deletions
diff --git a/drivers/ddr/imx8m/ddr_init.c b/drivers/ddr/imx8m/ddr_init.c
index 9a4b4e2ca8..18969ddb53 100644
--- a/drivers/ddr/imx8m/ddr_init.c
+++ b/drivers/ddr/imx8m/ddr_init.c
@@ -49,17 +49,18 @@ static void ddr_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num)
*/
#define IMX8M_SAVED_DRAM_TIMING_BASE 0x180000
-static int imx8m_ddr_init(struct dram_timing_info *dram_timing,
- enum ddrc_type type)
+int imx8m_ddr_init(struct dram_timing_info *dram_timing,
+ unsigned type)
{
unsigned long src_ddrc_rcr = MX8M_SRC_DDRC_RCR_ADDR;
unsigned int tmp, initial_drate, target_freq;
+ enum ddrc_type ddrc_type = get_ddrc_type(type);
int ret;
pr_debug("start DRAM init\n");
/* Step1: Follow the power up procedure */
- switch (type) {
+ switch (ddrc_type) {
case DDRC_TYPE_MQ:
reg32_write(src_ddrc_rcr + 0x04, 0x8f00000f);
reg32_write(src_ddrc_rcr, 0x8f00000f);
@@ -81,7 +82,7 @@ static int imx8m_ddr_init(struct dram_timing_info *dram_timing,
initial_drate = dram_timing->fsp_msg[0].drate;
/* default to the frequency point 0 clock */
- ddrphy_init_set_dfi_clk(initial_drate, type);
+ ddrphy_init_set_dfi_clk(initial_drate, ddrc_type);
/* D-aasert the presetn */
reg32_write(src_ddrc_rcr, 0x8F000006);
@@ -107,7 +108,7 @@ static int imx8m_ddr_init(struct dram_timing_info *dram_timing,
/* if ddr type is LPDDR4, do it */
tmp = reg32_read(DDRC_MSTR(0));
- if (tmp & (0x1 << 5) && type != DDRC_TYPE_MN)
+ if (tmp & (0x1 << 5) && ddrc_type != DDRC_TYPE_MN)
reg32_write(DDRC_DDR_SS_GPR0, 0x01); /* LPDDR4 mode */
/* determine the initial boot frequency */
@@ -154,7 +155,7 @@ static int imx8m_ddr_init(struct dram_timing_info *dram_timing,
reg32_write(DDRC_SWCTL(0), 0x00000000);
/* Apply rank-to-rank workaround */
- update_umctl2_rank_space_setting(dram_timing->fsp_msg_num - 1, type);
+ update_umctl2_rank_space_setting(dram_timing->fsp_msg_num - 1, ddrc_type);
/* Step16: Set DFIMISC.dfi_init_start to 1 */
setbits_le32(DDRC_DFIMISC(0), (0x1 << 5));
@@ -210,23 +211,3 @@ static int imx8m_ddr_init(struct dram_timing_info *dram_timing,
return 0;
}
-
-int imx8mm_ddr_init(struct dram_timing_info *dram_timing)
-{
- return imx8m_ddr_init(dram_timing, DDRC_TYPE_MM);
-}
-
-int imx8mn_ddr_init(struct dram_timing_info *dram_timing)
-{
- return imx8m_ddr_init(dram_timing, DDRC_TYPE_MN);
-}
-
-int imx8mq_ddr_init(struct dram_timing_info *dram_timing)
-{
- return imx8m_ddr_init(dram_timing, DDRC_TYPE_MQ);
-}
-
-int imx8mp_ddr_init(struct dram_timing_info *dram_timing)
-{
- return imx8m_ddr_init(dram_timing, DDRC_TYPE_MP);
-}
diff --git a/drivers/ddr/imx8m/ddrphy_train.c b/drivers/ddr/imx8m/ddrphy_train.c
index 9dc20a4762..e9d35afdfb 100644
--- a/drivers/ddr/imx8m/ddrphy_train.c
+++ b/drivers/ddr/imx8m/ddrphy_train.c
@@ -11,6 +11,48 @@
#include <firmware.h>
#include <mach/imx8m-regs.h>
+static const u16 *lpddr4_imem_1d;
+static size_t lpddr4_imem_1d_size;
+static const u16 *lpddr4_dmem_1d;
+static size_t lpddr4_dmem_1d_size;
+static const u16 *lpddr4_imem_2d;
+static size_t lpddr4_imem_2d_size;
+static const u16 *lpddr4_dmem_2d;
+static size_t lpddr4_dmem_2d_size;
+
+void ddr_get_firmware_lpddr4(void)
+{
+ get_builtin_firmware(lpddr4_pmu_train_1d_imem_bin, &lpddr4_imem_1d,
+ &lpddr4_imem_1d_size);
+ get_builtin_firmware(lpddr4_pmu_train_1d_dmem_bin, &lpddr4_dmem_1d,
+ &lpddr4_dmem_1d_size);
+ get_builtin_firmware(lpddr4_pmu_train_2d_imem_bin, &lpddr4_imem_2d,
+ &lpddr4_imem_2d_size);
+ get_builtin_firmware(lpddr4_pmu_train_2d_dmem_bin, &lpddr4_dmem_2d,
+ &lpddr4_dmem_2d_size);
+}
+
+static const u16 *ddr4_imem_1d;
+static size_t ddr4_imem_1d_size;
+static const u16 *ddr4_dmem_1d;
+static size_t ddr4_dmem_1d_size;
+static const u16 *ddr4_imem_2d;
+static size_t ddr4_imem_2d_size;
+static const u16 *ddr4_dmem_2d;
+static size_t ddr4_dmem_2d_size;
+
+void ddr_get_firmware_ddr(void)
+{
+ get_builtin_firmware(ddr4_imem_1d_bin, &ddr4_imem_1d,
+ &ddr4_imem_1d_size);
+ get_builtin_firmware(ddr4_dmem_1d_bin, &ddr4_dmem_1d,
+ &ddr4_dmem_1d_size);
+ get_builtin_firmware(ddr4_imem_2d_bin, &ddr4_imem_2d,
+ &ddr4_imem_2d_size);
+ get_builtin_firmware(ddr4_dmem_2d_bin, &ddr4_dmem_2d,
+ &ddr4_dmem_2d_size);
+}
+
void ddr_load_train_code(enum dram_type dram_type, enum fw_type fw_type)
{
const u16 *imem, *dmem;
@@ -18,19 +60,27 @@ void ddr_load_train_code(enum dram_type dram_type, enum fw_type fw_type)
if (dram_is_lpddr4(dram_type)) {
if (fw_type == FW_1D_IMAGE) {
- get_builtin_firmware(lpddr4_pmu_train_1d_imem_bin, &imem, &isize);
- get_builtin_firmware(lpddr4_pmu_train_1d_dmem_bin, &dmem, &dsize);
+ imem = lpddr4_imem_1d;
+ isize = lpddr4_imem_1d_size;
+ dmem = lpddr4_dmem_1d;
+ dsize = lpddr4_dmem_1d_size;
} else {
- get_builtin_firmware(lpddr4_pmu_train_2d_imem_bin, &imem, &isize);
- get_builtin_firmware(lpddr4_pmu_train_2d_dmem_bin, &dmem, &dsize);
+ imem = lpddr4_imem_2d;
+ isize = lpddr4_imem_2d_size;
+ dmem = lpddr4_dmem_2d;
+ dsize = lpddr4_dmem_2d_size;
}
} else if (dram_is_ddr4(dram_type)) {
if (fw_type == FW_1D_IMAGE) {
- get_builtin_firmware(ddr4_imem_1d_bin, &imem, &isize);
- get_builtin_firmware(ddr4_dmem_1d_bin, &dmem, &dsize);
+ imem = ddr4_imem_1d;
+ isize = ddr4_imem_1d_size;
+ dmem = ddr4_dmem_1d;
+ dsize = ddr4_dmem_1d_size;
} else {
- get_builtin_firmware(ddr4_imem_2d_bin, &imem, &isize);
- get_builtin_firmware(ddr4_dmem_2d_bin, &dmem, &dsize);
+ imem = ddr4_imem_2d;
+ isize = ddr4_imem_2d_size;
+ dmem = ddr4_dmem_2d;
+ dsize = ddr4_dmem_2d_size;
}
} else {
panic("No matching DDR PHY firmware found");
@@ -43,8 +93,10 @@ void ddr_load_train_code(enum dram_type dram_type, enum fw_type fw_type)
DDRC_PHY_DMEM, dmem, dsize);
}
-int ddr_cfg_phy(struct dram_timing_info *dram_timing, enum ddrc_type type)
+int ddr_cfg_phy(struct dram_timing_info *dram_timing, unsigned type)
{
+ enum ddrc_type ddrc_type = get_ddrc_type(type);
+ enum dram_type dram_type = get_dram_type(type);
struct dram_cfg_param *dram_cfg;
struct dram_fsp_msg *fsp_msg;
unsigned int num;
@@ -66,11 +118,11 @@ int ddr_cfg_phy(struct dram_timing_info *dram_timing, enum ddrc_type type)
for (i = 0; i < dram_timing->fsp_msg_num; i++) {
pr_debug("DRAM PHY training for %dMTS\n", fsp_msg->drate);
/* set dram PHY input clocks to desired frequency */
- ddrphy_init_set_dfi_clk(fsp_msg->drate, type);
+ ddrphy_init_set_dfi_clk(fsp_msg->drate, ddrc_type);
/* load the dram training firmware image */
dwc_ddrphy_apb_wr(0xd0000, 0x0);
- ddr_load_train_code(dram_timing->dram_type, fsp_msg->fw_type);
+ ddr_load_train_code(dram_type, fsp_msg->fw_type);
/* load the frequency set point message block parameter */
dram_cfg = fsp_msg->fsp_cfg;
diff --git a/drivers/i2c/busses/i2c-imx-early.c b/drivers/i2c/busses/i2c-imx-early.c
index a79d7bd88c..4e0f7e517d 100644
--- a/drivers/i2c/busses/i2c-imx-early.c
+++ b/drivers/i2c/busses/i2c-imx-early.c
@@ -9,11 +9,12 @@
*/
#include <common.h>
#include <i2c/i2c.h>
-#include <i2c/i2c-early.h>
+#include <pbl/i2c.h>
#include "i2c-imx.h"
struct fsl_i2c {
+ struct pbl_i2c i2c;
void __iomem *regs;
unsigned int i2cr_ien_opcode;
unsigned int i2sr_clr_opcode;
@@ -170,7 +171,7 @@ static int i2c_fsl_write(struct fsl_i2c *fsl_i2c, struct i2c_msg *msg)
/* write data */
for (i = 0; i < msg->len; i++) {
ret = i2c_fsl_send(fsl_i2c, msg->buf[i]);
- if (ret)
+ if (ret)
return ret;
}
@@ -229,9 +230,9 @@ static int i2c_fsl_read(struct fsl_i2c *fsl_i2c, struct i2c_msg *msg)
* If successful returns the number of messages transferred, otherwise a negative
* error code is returned.
*/
-int i2c_fsl_xfer(void *ctx, struct i2c_msg *msgs, int num)
+static int i2c_fsl_xfer(struct pbl_i2c *i2c, struct i2c_msg *msgs, int num)
{
- struct fsl_i2c *fsl_i2c = ctx;
+ struct fsl_i2c *fsl_i2c = container_of(i2c, struct fsl_i2c, i2c);
unsigned int i, temp;
int ret;
@@ -288,7 +289,7 @@ static struct fsl_i2c fsl_i2c;
* This function returns a context pointer suitable to transfer I2C messages
* using i2c_fsl_xfer.
*/
-void *ls1046_i2c_init(void __iomem *regs)
+struct pbl_i2c *ls1046_i2c_init(void __iomem *regs)
{
fsl_i2c.regs = regs;
fsl_i2c.regshift = 0;
@@ -297,10 +298,12 @@ void *ls1046_i2c_init(void __iomem *regs)
/* Divider for ~100kHz when coming from the ROM */
fsl_i2c.ifdr = 0x3e;
- return &fsl_i2c;
+ fsl_i2c.i2c.xfer = i2c_fsl_xfer;
+
+ return &fsl_i2c.i2c;
}
-void *imx8m_i2c_early_init(void __iomem *regs)
+struct pbl_i2c *imx8m_i2c_early_init(void __iomem *regs)
{
fsl_i2c.regs = regs;
fsl_i2c.regshift = 2;
@@ -309,5 +312,7 @@ void *imx8m_i2c_early_init(void __iomem *regs)
/* Divider for ~100kHz when coming from the ROM */
fsl_i2c.ifdr = 0x0f;
- return &fsl_i2c;
+ fsl_i2c.i2c.xfer = i2c_fsl_xfer;
+
+ return &fsl_i2c.i2c;
}
diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c
index 5a76e7a663..c81eba5b9d 100644
--- a/drivers/mci/imx-esdhc-pbl.c
+++ b/drivers/mci/imx-esdhc-pbl.c
@@ -44,7 +44,7 @@ static int esdhc_send_ext_csd(struct fsl_esdhc_host *host)
return esdhc_send_cmd(host, &cmd, &data);
}
-static bool esdhc_bootpart_active(struct fsl_esdhc_host *host)
+static bool __maybe_unused esdhc_bootpart_active(struct fsl_esdhc_host *host)
{
unsigned bootpart;
diff --git a/drivers/net/fec_imx.c b/drivers/net/fec_imx.c
index 0c2d600d12..673555a48a 100644
--- a/drivers/net/fec_imx.c
+++ b/drivers/net/fec_imx.c
@@ -320,6 +320,10 @@ static int fec_init(struct eth_device *dev)
/* size of each buffer */
writel(FEC_MAX_PKT_SIZE, fec->regs + FEC_EMRBR);
+ /* set rx and tx buffer descriptor base address */
+ writel(virt_to_phys(fec->tbd_base), fec->regs + FEC_ETDSR);
+ writel(virt_to_phys(fec->rbd_base), fec->regs + FEC_ERDSR);
+
return 0;
}
@@ -359,6 +363,8 @@ static int fec_open(struct eth_device *edev)
if (fec->phy_init)
fec->phy_init(edev->phydev);
+ fec_init(edev);
+
/*
* Initialize RxBD/TxBD rings
*/
@@ -839,9 +845,6 @@ static int fec_probe(struct device_d *dev)
base += FEC_RBD_NUM * sizeof(struct buffer_descriptor);
fec->tbd_base = base;
- writel(virt_to_phys(fec->tbd_base), fec->regs + FEC_ETDSR);
- writel(virt_to_phys(fec->rbd_base), fec->regs + FEC_ERDSR);
-
ret = fec_alloc_receive_packets(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE);
if (ret < 0)
goto free_xbd;
@@ -861,8 +864,6 @@ static int fec_probe(struct device_d *dev)
if (ret)
goto free_receive_packets;
- fec_init(edev);
-
fec->miibus.read = fec_miibus_read;
fec->miibus.write = fec_miibus_write;
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index b298da0000..8a57bd1aa9 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -220,6 +220,11 @@ static struct phy_provider *of_phy_provider_lookup(struct device_node *node)
{
struct phy_provider *phy_provider;
struct device_node *child;
+ int ret;
+
+ ret = of_device_ensure_probed(node);
+ if (ret)
+ return ERR_PTR(ret);
list_for_each_entry(phy_provider, &phy_provider_list, list) {
if (phy_provider->dev->device_node == node)
@@ -255,10 +260,6 @@ static struct phy *_of_phy_get(struct device_node *np, int index)
if (ret)
return ERR_PTR(-ENODEV);
- ret = of_device_ensure_probed(args.np);
- if (ret)
- return ERR_PTR(ret);
-
phy_provider = of_phy_provider_lookup(args.np);
if (IS_ERR(phy_provider)) {
return ERR_CAST(phy_provider);
@@ -316,7 +317,7 @@ struct phy *of_phy_get_by_phandle(struct device_d *dev, const char *phandle,
phy_provider = of_phy_provider_lookup(np);
if (IS_ERR(phy_provider)) {
- return ERR_PTR(-ENODEV);
+ return ERR_CAST(phy_provider);
}
return phy_provider->of_xlate(phy_provider->dev, NULL);
diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c
index bf8b6f1eb8..f71cf80b7d 100644
--- a/drivers/usb/imx/chipidea-imx.c
+++ b/drivers/usb/imx/chipidea-imx.c
@@ -260,8 +260,6 @@ static int imx_chipidea_probe(struct device_d *dev)
* devices which have only one.
*/
ci->clk = clk_get(dev, NULL);
- if (!IS_ERR(ci->clk))
- clk_enable(ci->clk);
/* Device trees are using both "phys" and "fsl,usbphy". Prefer the
* more modern former one but fall back to the old one.
@@ -302,6 +300,14 @@ static int imx_chipidea_probe(struct device_d *dev)
ci->data.drvdata = ci;
ci->data.usbphy = ci->usbphy;
+ /*
+ * Enable the clock after we ensured that all resources are available.
+ * This is crucial since the phy can be missing which and so the
+ * usb-controller <-> usb-phy communication is only partly initialized.
+ * This can trigger strange system hangs at least on i.MX8M SoCs.
+ */
+ clk_enable(ci->clk);
+
if ((ci->flags & MXC_EHCI_PORTSC_MASK) == MXC_EHCI_MODE_HSIC)
imx_chipidea_port_init(ci);
diff --git a/drivers/watchdog/imxwd.c b/drivers/watchdog/imxwd.c
index 31ea388c2c..dba92cb46a 100644
--- a/drivers/watchdog/imxwd.c
+++ b/drivers/watchdog/imxwd.c
@@ -239,18 +239,17 @@ static int imx_wd_probe(struct device_d *dev)
priv = xzalloc(sizeof(struct imx_wd));
iores = dev_request_mem_resource(dev, 0);
- if (IS_ERR(iores)) {
- dev_err(dev, "could not get memory region\n");
- return PTR_ERR(iores);
- }
+ if (IS_ERR(iores))
+ return dev_err_probe(dev, PTR_ERR(iores),
+ "could not get memory region\n");
clk = clk_get(dev, NULL);
if (IS_ERR(clk))
- return PTR_ERR(clk);
+ return dev_err_probe(dev, PTR_ERR(clk), "Failed to get clk\n");
ret = clk_enable(clk);
if (ret)
- return ret;
+ return dev_err_probe(dev, ret, "Failed to enable clk\n");
priv->base = IOMEM(iores->start);
priv->ops = ops;
@@ -272,14 +271,17 @@ static int imx_wd_probe(struct device_d *dev)
}
ret = watchdog_register(&priv->wd);
- if (ret)
+ if (ret) {
+ dev_err_probe(dev, ret, "Failed to register watchdog device\n");
goto on_error;
+ }
}
if (priv->ops->init) {
ret = priv->ops->init(priv);
if (ret) {
- dev_err(dev, "Failed to init watchdog device %d\n", ret);
+ dev_err_probe(dev, ret,
+ "Failed to init watchdog device\n");
goto error_unregister;
}
}