summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/clk-hsdk-cgu.c177
-rw-r--r--drivers/dma/ti-edma3.c55
-rw-r--r--drivers/gpio/pca953x.c6
-rw-r--r--drivers/gpio/tca642x.c6
-rw-r--r--drivers/mmc/omap_hsmmc.c253
-rw-r--r--drivers/serial/Kconfig2
-rw-r--r--drivers/serial/Makefile2
-rw-r--r--drivers/serial/serial_stm32.c (renamed from drivers/serial/serial_stm32x7.c)4
-rw-r--r--drivers/serial/serial_stm32.h (renamed from drivers/serial/serial_stm32x7.h)4
9 files changed, 442 insertions, 67 deletions
diff --git a/drivers/clk/clk-hsdk-cgu.c b/drivers/clk/clk-hsdk-cgu.c
index c80f90ec2f..4362d583cb 100644
--- a/drivers/clk/clk-hsdk-cgu.c
+++ b/drivers/clk/clk-hsdk-cgu.c
@@ -42,7 +42,9 @@
* |-->| TUNNEL PLL |
* | --------------
* | |
- * | |-->|CGU_TUN_IDIV|----------->
+ * | |-->|CGU_TUN_IDIV_TUN|----------->
+ * | |-->|CGU_TUN_IDIV_ROM|----------->
+ * | |-->|CGU_TUN_IDIV_PWM|----------->
* |
* | ------------
* |-->| HDMI PLL |
@@ -60,7 +62,9 @@
DECLARE_GLOBAL_DATA_PTR;
#define CGU_ARC_IDIV 0x080
-#define CGU_TUN_IDIV 0x380
+#define CGU_TUN_IDIV_TUN 0x380
+#define CGU_TUN_IDIV_ROM 0x390
+#define CGU_TUN_IDIV_PWM 0x3A0
#define CGU_HDMI_IDIV_APB 0x480
#define CGU_SYS_IDIV_APB 0x180
#define CGU_SYS_IDIV_AXI 0x190
@@ -114,8 +118,68 @@ DECLARE_GLOBAL_DATA_PTR;
#define CREG_CORE_IF_CLK_DIV_1 0x0
#define CREG_CORE_IF_CLK_DIV_2 0x1
+#define MIN_PLL_RATE 100000000 /* 100 MHz */
#define PARENT_RATE 33333333 /* fixed clock - xtal */
-#define CGU_MAX_CLOCKS 24
+#define CGU_MAX_CLOCKS 26
+
+#define CGU_SYS_CLOCKS 16
+#define MAX_AXI_CLOCKS 4
+
+#define CGU_TUN_CLOCKS 3
+#define MAX_TUN_CLOCKS 6
+
+struct hsdk_tun_idiv_cfg {
+ u32 oft;
+ u8 val[MAX_TUN_CLOCKS];
+};
+
+struct hsdk_tun_clk_cfg {
+ const u32 clk_rate[MAX_TUN_CLOCKS];
+ const u32 pll_rate[MAX_TUN_CLOCKS];
+ const struct hsdk_tun_idiv_cfg idiv[CGU_TUN_CLOCKS];
+};
+
+static const struct hsdk_tun_clk_cfg tun_clk_cfg = {
+ { 25000000, 50000000, 75000000, 100000000, 125000000, 150000000 },
+ { 600000000, 600000000, 600000000, 600000000, 700000000, 600000000 }, {
+ { CGU_TUN_IDIV_TUN, { 24, 12, 8, 6, 6, 4 } },
+ { CGU_TUN_IDIV_ROM, { 4, 4, 4, 4, 5, 4 } },
+ { CGU_TUN_IDIV_PWM, { 8, 8, 8, 8, 10, 8 } }
+ }
+};
+
+struct hsdk_sys_idiv_cfg {
+ u32 oft;
+ u8 val[MAX_AXI_CLOCKS];
+};
+
+struct hsdk_axi_clk_cfg {
+ const u32 clk_rate[MAX_AXI_CLOCKS];
+ const u32 pll_rate[MAX_AXI_CLOCKS];
+ const struct hsdk_sys_idiv_cfg idiv[CGU_SYS_CLOCKS];
+};
+
+static const struct hsdk_axi_clk_cfg axi_clk_cfg = {
+ { 200000000, 400000000, 600000000, 800000000 },
+ { 800000000, 800000000, 600000000, 800000000 }, {
+ { CGU_SYS_IDIV_APB, { 4, 4, 3, 4 } }, /* APB */
+ { CGU_SYS_IDIV_AXI, { 4, 2, 1, 1 } }, /* AXI */
+ { CGU_SYS_IDIV_ETH, { 2, 2, 2, 2 } }, /* ETH */
+ { CGU_SYS_IDIV_USB, { 2, 2, 2, 2 } }, /* USB */
+ { CGU_SYS_IDIV_SDIO, { 2, 2, 2, 2 } }, /* SDIO */
+ { CGU_SYS_IDIV_HDMI, { 2, 2, 2, 2 } }, /* HDMI */
+ { CGU_SYS_IDIV_GFX_CORE, { 1, 1, 1, 1 } }, /* GPU-CORE */
+ { CGU_SYS_IDIV_GFX_DMA, { 2, 2, 2, 2 } }, /* GPU-DMA */
+ { CGU_SYS_IDIV_GFX_CFG, { 4, 4, 3, 4 } }, /* GPU-CFG */
+ { CGU_SYS_IDIV_DMAC_CORE,{ 2, 2, 2, 2 } }, /* DMAC-CORE */
+ { CGU_SYS_IDIV_DMAC_CFG, { 4, 4, 3, 4 } }, /* DMAC-CFG */
+ { CGU_SYS_IDIV_SDIO_REF, { 8, 8, 6, 8 } }, /* SDIO-REF */
+ { CGU_SYS_IDIV_SPI_REF, { 24, 24, 18, 24 } }, /* SPI-REF */
+ { CGU_SYS_IDIV_I2C_REF, { 4, 4, 3, 4 } }, /* I2C-REF */
+ { CGU_SYS_IDIV_UART_REF, { 24, 24, 18, 24 } }, /* UART-REF */
+ { CGU_SYS_IDIV_EBI_REF, { 16, 16, 12, 16 } } /* EBI-REF */
+ }
+};
struct hsdk_pll_cfg {
u32 rate;
@@ -201,6 +265,9 @@ static const struct hsdk_pll_devdata hdmi_pll_dat = {
};
static ulong idiv_set(struct clk *, ulong);
+static ulong cpu_clk_set(struct clk *, ulong);
+static ulong axi_clk_set(struct clk *, ulong);
+static ulong tun_clk_set(struct clk *, ulong);
static ulong idiv_get(struct clk *);
static int idiv_off(struct clk *);
static ulong pll_set(struct clk *, ulong);
@@ -218,11 +285,11 @@ struct hsdk_cgu_clock_map {
static const struct hsdk_cgu_clock_map clock_map[] = {
{ CGU_ARC_PLL, 0, 0, &core_pll_dat, pll_get, pll_set, NULL },
- { CGU_ARC_PLL, 0, CGU_ARC_IDIV, &core_pll_dat, idiv_get, idiv_set, idiv_off },
+ { CGU_ARC_PLL, 0, CGU_ARC_IDIV, &core_pll_dat, idiv_get, cpu_clk_set, idiv_off },
{ CGU_DDR_PLL, 0, 0, &sdt_pll_dat, pll_get, pll_set, NULL },
{ CGU_SYS_PLL, 0, 0, &sdt_pll_dat, pll_get, pll_set, NULL },
{ CGU_SYS_PLL, 0, CGU_SYS_IDIV_APB, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
- { CGU_SYS_PLL, 0, CGU_SYS_IDIV_AXI, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
+ { CGU_SYS_PLL, 0, CGU_SYS_IDIV_AXI, &sdt_pll_dat, idiv_get, axi_clk_set, idiv_off },
{ CGU_SYS_PLL, 0, CGU_SYS_IDIV_ETH, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
{ CGU_SYS_PLL, 0, CGU_SYS_IDIV_USB, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
{ CGU_SYS_PLL, 0, CGU_SYS_IDIV_SDIO, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
@@ -238,7 +305,9 @@ static const struct hsdk_cgu_clock_map clock_map[] = {
{ CGU_SYS_PLL, 0, CGU_SYS_IDIV_UART_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
{ CGU_SYS_PLL, 0, CGU_SYS_IDIV_EBI_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
{ CGU_TUN_PLL, 0, 0, &sdt_pll_dat, pll_get, pll_set, NULL },
- { CGU_TUN_PLL, 0, CGU_TUN_IDIV, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
+ { CGU_TUN_PLL, 0, CGU_TUN_IDIV_TUN, &sdt_pll_dat, idiv_get, tun_clk_set, idiv_off },
+ { CGU_TUN_PLL, 0, CGU_TUN_IDIV_ROM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
+ { CGU_TUN_PLL, 0, CGU_TUN_IDIV_PWM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
{ CGU_HDMI_PLL, 0, 0, &hdmi_pll_dat, pll_get, pll_set, NULL },
{ CGU_HDMI_PLL, 0, CGU_HDMI_IDIV_APB, &hdmi_pll_dat, idiv_get, idiv_set, idiv_off }
};
@@ -423,7 +492,7 @@ static ulong pll_set(struct clk *sclk, ulong rate)
}
}
- pr_err("invalid rate=%ld, parent_rate=%d\n", best_rate, PARENT_RATE);
+ pr_err("invalid rate=%ld Hz, parent_rate=%d Hz\n", best_rate, PARENT_RATE);
return -EINVAL;
}
@@ -453,6 +522,94 @@ static ulong idiv_get(struct clk *sclk)
return parent_rate / div_factor;
}
+/* Special behavior: wen we set this clock we set both idiv and pll */
+static ulong cpu_clk_set(struct clk *sclk, ulong rate)
+{
+ ulong ret;
+
+ ret = pll_set(sclk, rate);
+ idiv_set(sclk, rate);
+
+ return ret;
+}
+
+/* Special behavior: wen we set this clock we set both idiv and pll and all pll dividers */
+static ulong axi_clk_set(struct clk *sclk, ulong rate)
+{
+ struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
+ ulong pll_rate;
+ int i, freq_idx = -1;
+ ulong ret = 0;
+
+ pll_rate = pll_get(sclk);
+
+ for (i = 0; i < MAX_AXI_CLOCKS; i++) {
+ if (axi_clk_cfg.clk_rate[i] == rate) {
+ freq_idx = i;
+ break;
+ }
+ }
+
+ if (freq_idx < 0) {
+ pr_err("axi clk: invalid rate=%ld Hz\n", rate);
+ return -EINVAL;
+ }
+
+ /* configure PLL before dividers */
+ if (axi_clk_cfg.pll_rate[freq_idx] < pll_rate)
+ ret = pll_set(sclk, axi_clk_cfg.pll_rate[freq_idx]);
+
+ /* configure SYS dividers */
+ for (i = 0; i < CGU_SYS_CLOCKS; i++) {
+ clk->idiv_regs = clk->cgu_regs + axi_clk_cfg.idiv[i].oft;
+ hsdk_idiv_write(clk, axi_clk_cfg.idiv[i].val[freq_idx]);
+ }
+
+ /* configure PLL after dividers */
+ if (axi_clk_cfg.pll_rate[freq_idx] >= pll_rate)
+ ret = pll_set(sclk, axi_clk_cfg.pll_rate[freq_idx]);
+
+ return ret;
+}
+
+static ulong tun_clk_set(struct clk *sclk, ulong rate)
+{
+ struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
+ ulong pll_rate;
+ int i, freq_idx = -1;
+ ulong ret = 0;
+
+ pll_rate = pll_get(sclk);
+
+ for (i = 0; i < MAX_TUN_CLOCKS; i++) {
+ if (tun_clk_cfg.clk_rate[i] == rate) {
+ freq_idx = i;
+ break;
+ }
+ }
+
+ if (freq_idx < 0) {
+ pr_err("tun clk: invalid rate=%ld Hz\n", rate);
+ return -EINVAL;
+ }
+
+ /* configure PLL before dividers */
+ if (tun_clk_cfg.pll_rate[freq_idx] < pll_rate)
+ ret = pll_set(sclk, tun_clk_cfg.pll_rate[freq_idx]);
+
+ /* configure SYS dividers */
+ for (i = 0; i < CGU_TUN_CLOCKS; i++) {
+ clk->idiv_regs = clk->cgu_regs + tun_clk_cfg.idiv[i].oft;
+ hsdk_idiv_write(clk, tun_clk_cfg.idiv[i].val[freq_idx]);
+ }
+
+ /* configure PLL after dividers */
+ if (tun_clk_cfg.pll_rate[freq_idx] >= pll_rate)
+ ret = pll_set(sclk, tun_clk_cfg.pll_rate[freq_idx]);
+
+ return ret;
+}
+
static ulong idiv_set(struct clk *sclk, ulong rate)
{
struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
@@ -466,14 +623,14 @@ static ulong idiv_set(struct clk *sclk, ulong rate)
}
if (div_factor & ~CGU_IDIV_MASK) {
- pr_err("invalid rate=%ld, parent_rate=%ld, div=%d: max divider valie is%d\n",
+ pr_err("invalid rate=%ld Hz, parent_rate=%ld Hz, div=%d: max divider valie is%d\n",
rate, parent_rate, div_factor, CGU_IDIV_MASK);
div_factor = CGU_IDIV_MASK;
}
if (div_factor == 0) {
- pr_err("invalid rate=%ld, parent_rate=%ld, div=%d: min divider valie is 1\n",
+ pr_err("invalid rate=%ld Hz, parent_rate=%ld Hz, div=%d: min divider valie is 1\n",
rate, parent_rate, div_factor);
div_factor = 1;
@@ -559,6 +716,6 @@ U_BOOT_DRIVER(hsdk_cgu_clk) = {
.id = UCLASS_CLK,
.of_match = hsdk_cgu_clk_id,
.probe = hsdk_cgu_clk_probe,
- .platdata_auto_alloc_size = sizeof(struct hsdk_cgu_clk),
+ .priv_auto_alloc_size = sizeof(struct hsdk_cgu_clk),
.ops = &hsdk_cgu_ops,
};
diff --git a/drivers/dma/ti-edma3.c b/drivers/dma/ti-edma3.c
index 635eb7876d..852c9e1fd7 100644
--- a/drivers/dma/ti-edma3.c
+++ b/drivers/dma/ti-edma3.c
@@ -34,10 +34,14 @@
#define EDMA3_QEESR 0x108c
#define EDMA3_QSECR 0x1094
+#define EDMA_FILL_BUFFER_SIZE 512
+
struct ti_edma3_priv {
u32 base;
};
+static u8 edma_fill_buffer[EDMA_FILL_BUFFER_SIZE] __aligned(ARCH_DMA_MINALIGN);
+
/**
* qedma3_start - start qdma on a channel
* @base: base address of edma
@@ -391,7 +395,7 @@ void qedma3_stop(u32 base, struct edma3_channel_config *cfg)
}
void __edma3_transfer(unsigned long edma3_base_addr, unsigned int edma_slot_num,
- void *dst, void *src, size_t len)
+ void *dst, void *src, size_t len, size_t s_len)
{
struct edma3_slot_config slot;
struct edma3_channel_config edma_channel;
@@ -401,7 +405,11 @@ void __edma3_transfer(unsigned long edma3_base_addr, unsigned int edma_slot_num,
unsigned int addr = (unsigned int) (dst);
unsigned int max_acnt = 0x7FFFU;
- if (len > max_acnt) {
+ if (len > s_len) {
+ b_cnt_value = (len / s_len);
+ rem_bytes = (len % s_len);
+ a_cnt_value = s_len;
+ } else if (len > max_acnt) {
b_cnt_value = (len / max_acnt);
rem_bytes = (len % max_acnt);
a_cnt_value = max_acnt;
@@ -412,7 +420,10 @@ void __edma3_transfer(unsigned long edma3_base_addr, unsigned int edma_slot_num,
slot.acnt = a_cnt_value;
slot.bcnt = b_cnt_value;
slot.ccnt = 1;
- slot.src_bidx = a_cnt_value;
+ if (len == s_len)
+ slot.src_bidx = a_cnt_value;
+ else
+ slot.src_bidx = 0;
slot.dst_bidx = a_cnt_value;
slot.src_cidx = 0;
slot.dst_cidx = 0;
@@ -438,8 +449,11 @@ void __edma3_transfer(unsigned long edma3_base_addr, unsigned int edma_slot_num,
if (rem_bytes != 0) {
slot.opt = 0;
- slot.src =
- (b_cnt_value * max_acnt) + ((unsigned int) src);
+ if (len == s_len)
+ slot.src =
+ (b_cnt_value * max_acnt) + ((unsigned int) src);
+ else
+ slot.src = (unsigned int) src;
slot.acnt = rem_bytes;
slot.bcnt = 1;
slot.ccnt = 1;
@@ -468,12 +482,39 @@ void __edma3_transfer(unsigned long edma3_base_addr, unsigned int edma_slot_num,
}
}
+void __edma3_fill(unsigned long edma3_base_addr, unsigned int edma_slot_num,
+ void *dst, u8 val, size_t len)
+{
+ int xfer_len;
+ int max_xfer = EDMA_FILL_BUFFER_SIZE * 65535;
+
+ memset((void *)edma_fill_buffer, val, sizeof(edma_fill_buffer));
+
+ while (len) {
+ xfer_len = len;
+ if (xfer_len > max_xfer)
+ xfer_len = max_xfer;
+
+ __edma3_transfer(edma3_base_addr, edma_slot_num, dst,
+ edma_fill_buffer, xfer_len,
+ EDMA_FILL_BUFFER_SIZE);
+ len -= xfer_len;
+ dst += xfer_len;
+ }
+}
+
#ifndef CONFIG_DMA
void edma3_transfer(unsigned long edma3_base_addr, unsigned int edma_slot_num,
void *dst, void *src, size_t len)
{
- __edma3_transfer(edma3_base_addr, edma_slot_num, dst, src, len);
+ __edma3_transfer(edma3_base_addr, edma_slot_num, dst, src, len, len);
+}
+
+void edma3_fill(unsigned long edma3_base_addr, unsigned int edma_slot_num,
+ void *dst, u8 val, size_t len)
+{
+ __edma3_fill(edma3_base_addr, edma_slot_num, dst, val, len);
}
#else
@@ -488,7 +529,7 @@ static int ti_edma3_transfer(struct udevice *dev, int direction, void *dst,
switch (direction) {
case DMA_MEM_TO_MEM:
- __edma3_transfer(priv->base, 1, dst, src, len);
+ __edma3_transfer(priv->base, 1, dst, src, len, len);
break;
default:
pr_err("Transfer type not implemented in DMA driver\n");
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
index d1c1ae1411..10a105df94 100644
--- a/drivers/gpio/pca953x.c
+++ b/drivers/gpio/pca953x.c
@@ -142,7 +142,7 @@ int pca953x_get_val(uint8_t chip)
return (int)val;
}
-#ifdef CONFIG_CMD_PCA953X
+#if defined(CONFIG_CMD_PCA953X) && !defined(CONFIG_SPL_BUILD)
/*
* Display pca953x information
*/
@@ -193,7 +193,7 @@ static int pca953x_info(uint8_t chip)
return 0;
}
-cmd_tbl_t cmd_pca953x[] = {
+static cmd_tbl_t cmd_pca953x[] = {
U_BOOT_CMD_MKENT(device, 3, 0, (void *)PCA953X_CMD_DEVICE, "", ""),
U_BOOT_CMD_MKENT(output, 4, 0, (void *)PCA953X_CMD_OUTPUT, "", ""),
U_BOOT_CMD_MKENT(input, 3, 0, (void *)PCA953X_CMD_INPUT, "", ""),
@@ -201,7 +201,7 @@ cmd_tbl_t cmd_pca953x[] = {
U_BOOT_CMD_MKENT(info, 2, 0, (void *)PCA953X_CMD_INFO, "", ""),
};
-int do_pca953x(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+static int do_pca953x(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
static uint8_t chip = CONFIG_SYS_I2C_PCA953X_ADDR;
int ret = CMD_RET_USAGE, val;
diff --git a/drivers/gpio/tca642x.c b/drivers/gpio/tca642x.c
index 6386835d5d..730460a999 100644
--- a/drivers/gpio/tca642x.c
+++ b/drivers/gpio/tca642x.c
@@ -163,7 +163,7 @@ int tca642x_set_inital_state(uchar chip, struct tca642x_bank_info init_data[])
return ret;
}
-#ifdef CONFIG_CMD_TCA642X
+#if defined(CONFIG_CMD_TCA642X) && !defined(CONFIG_SPL_BUILD)
/*
* Display tca642x information
*/
@@ -212,7 +212,7 @@ static int tca642x_info(uchar chip)
return 0;
}
-cmd_tbl_t cmd_tca642x[] = {
+static cmd_tbl_t cmd_tca642x[] = {
U_BOOT_CMD_MKENT(device, 3, 0, (void *)TCA642X_CMD_DEVICE, "", ""),
U_BOOT_CMD_MKENT(output, 4, 0, (void *)TCA642X_CMD_OUTPUT, "", ""),
U_BOOT_CMD_MKENT(input, 3, 0, (void *)TCA642X_CMD_INPUT, "", ""),
@@ -220,7 +220,7 @@ cmd_tbl_t cmd_tca642x[] = {
U_BOOT_CMD_MKENT(info, 2, 0, (void *)TCA642X_CMD_INFO, "", ""),
};
-int do_tca642x(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+static int do_tca642x(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
static uchar chip = CONFIG_SYS_I2C_TCA642X_ADDR;
int ret = CMD_RET_USAGE, val;
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index 30443d13a0..b12d6d9102 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -25,6 +25,7 @@
#include <config.h>
#include <common.h>
#include <malloc.h>
+#include <memalign.h>
#include <mmc.h>
#include <part.h>
#include <i2c.h>
@@ -56,10 +57,6 @@ DECLARE_GLOBAL_DATA_PTR;
#define SYSCTL_SRC (1 << 25)
#define SYSCTL_SRD (1 << 26)
-struct omap2_mmc_platform_config {
- u32 reg_offset;
-};
-
struct omap_hsmmc_data {
struct hsmmc *base_addr;
#if !CONFIG_IS_ENABLED(DM_MMC)
@@ -75,11 +72,45 @@ struct omap_hsmmc_data {
int wp_gpio;
#endif
#endif
+ u8 controller_flags;
+#ifndef CONFIG_OMAP34XX
+ struct omap_hsmmc_adma_desc *adma_desc_table;
+ uint desc_slot;
+#endif
};
+#ifndef CONFIG_OMAP34XX
+struct omap_hsmmc_adma_desc {
+ u8 attr;
+ u8 reserved;
+ u16 len;
+ u32 addr;
+};
+
+#define ADMA_MAX_LEN 63488
+
+/* Decriptor table defines */
+#define ADMA_DESC_ATTR_VALID BIT(0)
+#define ADMA_DESC_ATTR_END BIT(1)
+#define ADMA_DESC_ATTR_INT BIT(2)
+#define ADMA_DESC_ATTR_ACT1 BIT(4)
+#define ADMA_DESC_ATTR_ACT2 BIT(5)
+
+#define ADMA_DESC_TRANSFER_DATA ADMA_DESC_ATTR_ACT2
+#define ADMA_DESC_LINK_DESC (ADMA_DESC_ATTR_ACT1 | ADMA_DESC_ATTR_ACT2)
+#endif
+
/* If we fail after 1 second wait, something is really bad */
#define MAX_RETRY_MS 1000
+/* DMA transfers can take a long time if a lot a data is transferred.
+ * The timeout must take in account the amount of data. Let's assume
+ * that the time will never exceed 333 ms per MB (in other word we assume
+ * that the bandwidth is always above 3MB/s).
+ */
+#define DMA_TIMEOUT_PER_MB 333
+#define OMAP_HSMMC_USE_ADMA BIT(2)
+
static int mmc_read_data(struct hsmmc *mmc_base, char *buf, unsigned int size);
static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,
unsigned int siz);
@@ -246,6 +277,11 @@ static int omap_hsmmc_init_setup(struct mmc *mmc)
return -ETIMEDOUT;
}
}
+#ifndef CONFIG_OMAP34XX
+ reg_val = readl(&mmc_base->hl_hwinfo);
+ if (reg_val & MADMA_EN)
+ priv->controller_flags |= OMAP_HSMMC_USE_ADMA;
+#endif
writel(DTW_1_BITMODE | SDBP_PWROFF | SDVS_3V0, &mmc_base->hctl);
writel(readl(&mmc_base->capa) | VS30_3V0SUP | VS18_1V8SUP,
&mmc_base->capa);
@@ -258,7 +294,7 @@ static int omap_hsmmc_init_setup(struct mmc *mmc)
dsor = 240;
mmc_reg_out(&mmc_base->sysctl, (ICE_MASK | DTO_MASK | CEN_MASK),
- (ICE_STOP | DTO_15THDTO | CEN_DISABLE));
+ (ICE_STOP | DTO_15THDTO));
mmc_reg_out(&mmc_base->sysctl, ICE_MASK | CLKD_MASK,
(dsor << CLKD_OFFSET) | ICE_OSCILLATE);
start = get_timer(0);
@@ -273,8 +309,8 @@ static int omap_hsmmc_init_setup(struct mmc *mmc)
writel(readl(&mmc_base->hctl) | SDBP_PWRON, &mmc_base->hctl);
writel(IE_BADA | IE_CERR | IE_DEB | IE_DCRC | IE_DTO | IE_CIE |
- IE_CEB | IE_CCRC | IE_CTO | IE_BRR | IE_BWR | IE_TC | IE_CC,
- &mmc_base->ie);
+ IE_CEB | IE_CCRC | IE_ADMAE | IE_CTO | IE_BRR | IE_BWR | IE_TC |
+ IE_CC, &mmc_base->ie);
mmc_init_stream(mmc_base);
@@ -326,6 +362,118 @@ static void mmc_reset_controller_fsm(struct hsmmc *mmc_base, u32 bit)
}
}
}
+
+#ifndef CONFIG_OMAP34XX
+static void omap_hsmmc_adma_desc(struct mmc *mmc, char *buf, u16 len, bool end)
+{
+ struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
+ struct omap_hsmmc_adma_desc *desc;
+ u8 attr;
+
+ desc = &priv->adma_desc_table[priv->desc_slot];
+
+ attr = ADMA_DESC_ATTR_VALID | ADMA_DESC_TRANSFER_DATA;
+ if (!end)
+ priv->desc_slot++;
+ else
+ attr |= ADMA_DESC_ATTR_END;
+
+ desc->len = len;
+ desc->addr = (u32)buf;
+ desc->reserved = 0;
+ desc->attr = attr;
+}
+
+static void omap_hsmmc_prepare_adma_table(struct mmc *mmc,
+ struct mmc_data *data)
+{
+ uint total_len = data->blocksize * data->blocks;
+ uint desc_count = DIV_ROUND_UP(total_len, ADMA_MAX_LEN);
+ struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
+ int i = desc_count;
+ char *buf;
+
+ priv->desc_slot = 0;
+ priv->adma_desc_table = (struct omap_hsmmc_adma_desc *)
+ memalign(ARCH_DMA_MINALIGN, desc_count *
+ sizeof(struct omap_hsmmc_adma_desc));
+
+ if (data->flags & MMC_DATA_READ)
+ buf = data->dest;
+ else
+ buf = (char *)data->src;
+
+ while (--i) {
+ omap_hsmmc_adma_desc(mmc, buf, ADMA_MAX_LEN, false);
+ buf += ADMA_MAX_LEN;
+ total_len -= ADMA_MAX_LEN;
+ }
+
+ omap_hsmmc_adma_desc(mmc, buf, total_len, true);
+
+ flush_dcache_range((long)priv->adma_desc_table,
+ (long)priv->adma_desc_table +
+ ROUND(desc_count *
+ sizeof(struct omap_hsmmc_adma_desc),
+ ARCH_DMA_MINALIGN));
+}
+
+static void omap_hsmmc_prepare_data(struct mmc *mmc, struct mmc_data *data)
+{
+ struct hsmmc *mmc_base;
+ struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
+ u32 val;
+ char *buf;
+
+ mmc_base = priv->base_addr;
+ omap_hsmmc_prepare_adma_table(mmc, data);
+
+ if (data->flags & MMC_DATA_READ)
+ buf = data->dest;
+ else
+ buf = (char *)data->src;
+
+ val = readl(&mmc_base->hctl);
+ val |= DMA_SELECT;
+ writel(val, &mmc_base->hctl);
+
+ val = readl(&mmc_base->con);
+ val |= DMA_MASTER;
+ writel(val, &mmc_base->con);
+
+ writel((u32)priv->adma_desc_table, &mmc_base->admasal);
+
+ flush_dcache_range((u32)buf,
+ (u32)buf +
+ ROUND(data->blocksize * data->blocks,
+ ARCH_DMA_MINALIGN));
+}
+
+static void omap_hsmmc_dma_cleanup(struct mmc *mmc)
+{
+ struct hsmmc *mmc_base;
+ struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
+ u32 val;
+
+ mmc_base = priv->base_addr;
+
+ val = readl(&mmc_base->con);
+ val &= ~DMA_MASTER;
+ writel(val, &mmc_base->con);
+
+ val = readl(&mmc_base->hctl);
+ val &= ~DMA_SELECT;
+ writel(val, &mmc_base->hctl);
+
+ kfree(priv->adma_desc_table);
+}
+#else
+#define omap_hsmmc_adma_desc
+#define omap_hsmmc_prepare_adma_table
+#define omap_hsmmc_prepare_data
+#define omap_hsmmc_dma_cleanup
+#endif
+
#if !CONFIG_IS_ENABLED(DM_MMC)
static int omap_hsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data)
@@ -336,12 +484,20 @@ static int omap_hsmmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
struct mmc_data *data)
{
struct omap_hsmmc_data *priv = dev_get_priv(dev);
+#ifndef CONFIG_OMAP34XX
+ struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+ struct mmc *mmc = upriv->mmc;
+#endif
#endif
struct hsmmc *mmc_base;
unsigned int flags, mmc_stat;
ulong start;
mmc_base = priv->base_addr;
+
+ if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
+ return 0;
+
start = get_timer(0);
while ((readl(&mmc_base->pstate) & (DATI_MASK | CMDI_MASK)) != 0) {
if (get_timer(0) - start > MAX_RETRY_MS) {
@@ -388,7 +544,8 @@ static int omap_hsmmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
/* enable default flags */
flags = flags | (CMD_TYPE_NORMAL | CICE_NOCHECK | CCCE_NOCHECK |
- MSBS_SGLEBLK | ACEN_DISABLE | BCE_DISABLE | DE_DISABLE);
+ MSBS_SGLEBLK);
+ flags &= ~(ACEN_ENABLE | BCE_ENABLE | DE_ENABLE);
if (cmd->resp_type & MMC_RSP_CRC)
flags |= CCCE_CHECK;
@@ -398,7 +555,7 @@ static int omap_hsmmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
if (data) {
if ((cmd->cmdidx == MMC_CMD_READ_MULTIPLE_BLOCK) ||
(cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK)) {
- flags |= (MSBS_MULTIBLK | BCE_ENABLE);
+ flags |= (MSBS_MULTIBLK | BCE_ENABLE | ACEN_ENABLE);
data->blocksize = 512;
writel(data->blocksize | (data->blocks << 16),
&mmc_base->blk);
@@ -409,6 +566,14 @@ static int omap_hsmmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
flags |= (DP_DATA | DDIR_READ);
else
flags |= (DP_DATA | DDIR_WRITE);
+
+#ifndef CONFIG_OMAP34XX
+ if ((priv->controller_flags & OMAP_HSMMC_USE_ADMA) &&
+ !mmc_is_tuning_cmd(cmd->cmdidx)) {
+ omap_hsmmc_prepare_data(mmc, data);
+ flags |= DE_ENABLE;
+ }
+#endif
}
writel(cmd->cmdarg, &mmc_base->arg);
@@ -418,7 +583,7 @@ static int omap_hsmmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
start = get_timer(0);
do {
mmc_stat = readl(&mmc_base->stat);
- if (get_timer(0) - start > MAX_RETRY_MS) {
+ if (get_timer(start) > MAX_RETRY_MS) {
printf("%s : timeout: No status update\n", __func__);
return -ETIMEDOUT;
}
@@ -445,6 +610,41 @@ static int omap_hsmmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
}
}
+#ifndef CONFIG_OMAP34XX
+ if ((priv->controller_flags & OMAP_HSMMC_USE_ADMA) && data &&
+ !mmc_is_tuning_cmd(cmd->cmdidx)) {
+ u32 sz_mb, timeout;
+
+ if (mmc_stat & IE_ADMAE) {
+ omap_hsmmc_dma_cleanup(mmc);
+ return -EIO;
+ }
+
+ sz_mb = DIV_ROUND_UP(data->blocksize * data->blocks, 1 << 20);
+ timeout = sz_mb * DMA_TIMEOUT_PER_MB;
+ if (timeout < MAX_RETRY_MS)
+ timeout = MAX_RETRY_MS;
+
+ start = get_timer(0);
+ do {
+ mmc_stat = readl(&mmc_base->stat);
+ if (mmc_stat & TC_MASK) {
+ writel(readl(&mmc_base->stat) | TC_MASK,
+ &mmc_base->stat);
+ break;
+ }
+ if (get_timer(start) > timeout) {
+ printf("%s : DMA timeout: No status update\n",
+ __func__);
+ return -ETIMEDOUT;
+ }
+ } while (1);
+
+ omap_hsmmc_dma_cleanup(mmc);
+ return 0;
+ }
+#endif
+
if (data && (data->flags & MMC_DATA_READ)) {
mmc_read_data(mmc_base, data->dest,
data->blocksize * data->blocks);
@@ -612,7 +812,7 @@ static int omap_hsmmc_set_ios(struct udevice *dev)
}
mmc_reg_out(&mmc_base->sysctl, (ICE_MASK | DTO_MASK | CEN_MASK),
- (ICE_STOP | DTO_15THDTO | CEN_DISABLE));
+ (ICE_STOP | DTO_15THDTO));
mmc_reg_out(&mmc_base->sysctl, ICE_MASK | CLKD_MASK,
(dsor << CLKD_OFFSET) | ICE_OSCILLATE);
@@ -802,15 +1002,13 @@ static int omap_hsmmc_ofdata_to_platdata(struct udevice *dev)
{
struct omap_hsmmc_plat *plat = dev_get_platdata(dev);
struct mmc_config *cfg = &plat->cfg;
- struct omap2_mmc_platform_config *data =
- (struct omap2_mmc_platform_config *)dev_get_driver_data(dev);
const void *fdt = gd->fdt_blob;
int node = dev_of_offset(dev);
int val;
plat->base_addr = map_physmem(devfdt_get_addr(dev),
sizeof(struct hsmmc *),
- MAP_NOCACHE) + data->reg_offset;
+ MAP_NOCACHE);
cfg->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
val = fdtdec_get_int(fdt, node, "bus-width", -1);
@@ -886,31 +1084,10 @@ static int omap_hsmmc_probe(struct udevice *dev)
}
#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
-static const struct omap2_mmc_platform_config omap3_mmc_pdata = {
- .reg_offset = 0,
-};
-
-static const struct omap2_mmc_platform_config am33xx_mmc_pdata = {
- .reg_offset = 0x100,
-};
-
-static const struct omap2_mmc_platform_config omap4_mmc_pdata = {
- .reg_offset = 0x100,
-};
-
static const struct udevice_id omap_hsmmc_ids[] = {
- {
- .compatible = "ti,omap3-hsmmc",
- .data = (ulong)&omap3_mmc_pdata
- },
- {
- .compatible = "ti,omap4-hsmmc",
- .data = (ulong)&omap4_mmc_pdata
- },
- {
- .compatible = "ti,am33xx-hsmmc",
- .data = (ulong)&am33xx_mmc_pdata
- },
+ { .compatible = "ti,omap3-hsmmc" },
+ { .compatible = "ti,omap4-hsmmc" },
+ { .compatible = "ti,am33xx-hsmmc" },
{ }
};
#endif
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 122b8e786a..7b20b47964 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -529,7 +529,7 @@ config STI_ASC_SERIAL
on STiH410 SoC. This is a basic implementation, it supports
following baudrate 9600, 19200, 38400, 57600 and 115200.
-config STM32X7_SERIAL
+config STM32_SERIAL
bool "STMicroelectronics STM32 SoCs on-chip UART"
depends on DM_SERIAL && (STM32F4 || STM32F7 || STM32H7)
help
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 7adcee3e10..5ef603ab15 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -44,7 +44,7 @@ obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o
obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o
obj-$(CONFIG_STI_ASC_SERIAL) += serial_sti_asc.o
obj-$(CONFIG_PIC32_SERIAL) += serial_pic32.o
-obj-$(CONFIG_STM32X7_SERIAL) += serial_stm32x7.o
+obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o
obj-$(CONFIG_BCM283X_MU_SERIAL) += serial_bcm283x_mu.o
obj-$(CONFIG_MSM_SERIAL) += serial_msm.o
obj-$(CONFIG_MVEBU_A3700_UART) += serial_mvebu_a3700.o
diff --git a/drivers/serial/serial_stm32x7.c b/drivers/serial/serial_stm32.c
index d1580e3cb5..286b954fdd 100644
--- a/drivers/serial/serial_stm32x7.c
+++ b/drivers/serial/serial_stm32.c
@@ -11,7 +11,7 @@
#include <asm/io.h>
#include <serial.h>
#include <asm/arch/stm32.h>
-#include "serial_stm32x7.h"
+#include "serial_stm32.h"
DECLARE_GLOBAL_DATA_PTR;
@@ -148,7 +148,7 @@ static const struct dm_serial_ops stm32_serial_ops = {
};
U_BOOT_DRIVER(serial_stm32) = {
- .name = "serial_stm32x7",
+ .name = "serial_stm32",
.id = UCLASS_SERIAL,
.of_match = of_match_ptr(stm32_serial_id),
.ofdata_to_platdata = of_match_ptr(stm32_serial_ofdata_to_platdata),
diff --git a/drivers/serial/serial_stm32x7.h b/drivers/serial/serial_stm32.h
index f7dca39103..d08ba1f55f 100644
--- a/drivers/serial/serial_stm32x7.h
+++ b/drivers/serial/serial_stm32.h
@@ -5,8 +5,8 @@
* SPDX-License-Identifier: GPL-2.0+
*/
-#ifndef _SERIAL_STM32_X7_
-#define _SERIAL_STM32_X7_
+#ifndef _SERIAL_STM32_
+#define _SERIAL_STM32_
#define CR1_OFFSET(x) (x ? 0x0c : 0x00)
#define CR3_OFFSET(x) (x ? 0x14 : 0x08)