summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2018-12-28 22:00:24 -0500
committerTom Rini <[email protected]>2018-12-28 22:00:24 -0500
commit9735326fff8488663e27350917ccf01f2e71730a (patch)
treeb9ddf50bc81aec6f8223e244f9ccb22d4639cf6e /drivers
parentbea3d826203f90507ff32ed24bd0a3c53479e55c (diff)
parent2001a81cba9554ee8b7f6d2ecd53510640ce4f35 (diff)
Merge branch 'master' of git://git.denx.de/u-boot-uniphier
Please pull UniPhier updates v2019.01 - import DIV_ROUND_CLOSEST_ULL macro from Linux - import improvement and fix of Denali NAND driver from Linux - add NAND 200MHz clock to clk driver - allow CONFIG_BOOTCOMMAND to run custom boot command/script - sync DT with Linux 4.20
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/uniphier/clk-uniphier-sys.c8
-rw-r--r--drivers/mtd/nand/raw/denali.c53
-rw-r--r--drivers/mtd/nand/raw/denali.h1
-rw-r--r--drivers/mtd/nand/raw/denali_dt.c40
4 files changed, 72 insertions, 30 deletions
diff --git a/drivers/clk/uniphier/clk-uniphier-sys.c b/drivers/clk/uniphier/clk-uniphier-sys.c
index 9e087b6bd28..487b43ebdab 100644
--- a/drivers/clk/uniphier/clk-uniphier-sys.c
+++ b/drivers/clk/uniphier/clk-uniphier-sys.c
@@ -6,13 +6,12 @@
#include "clk-uniphier.h"
-/* Denali driver requires clk_x rate (clk: 50MHz, clk_x & ecc_clk: 200MHz) */
#define UNIPHIER_LD4_SYS_CLK_NAND(_id) \
- UNIPHIER_CLK_RATE(128, 200000000), \
+ UNIPHIER_CLK_RATE(128, 50000000), \
UNIPHIER_CLK_GATE((_id), 128, 0x2104, 2)
#define UNIPHIER_LD11_SYS_CLK_NAND(_id) \
- UNIPHIER_CLK_RATE(128, 200000000), \
+ UNIPHIER_CLK_RATE(128, 50000000), \
UNIPHIER_CLK_GATE((_id), 128, 0x210c, 0)
const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[] = {
@@ -20,6 +19,7 @@ const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[] = {
defined(CONFIG_ARCH_UNIPHIER_PRO4) || defined(CONFIG_ARCH_UNIPHIER_PRO5) ||\
defined(CONFIG_ARCH_UNIPHIER_PXS2) || defined(CONFIG_ARCH_UNIPHIER_LD6B)
UNIPHIER_LD4_SYS_CLK_NAND(2),
+ UNIPHIER_CLK_RATE(3, 200000000),
UNIPHIER_CLK_GATE_SIMPLE(6, 0x2104, 12), /* ether (Pro4, PXs2) */
UNIPHIER_CLK_GATE_SIMPLE(7, 0x2104, 5), /* ether-gb (Pro4) */
UNIPHIER_CLK_GATE_SIMPLE(8, 0x2104, 10), /* stdmac */
@@ -36,6 +36,7 @@ const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[] = {
const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = {
#if defined(CONFIG_ARCH_UNIPHIER_LD11) || defined(CONFIG_ARCH_UNIPHIER_LD20)
UNIPHIER_LD11_SYS_CLK_NAND(2),
+ UNIPHIER_CLK_RATE(3, 200000000),
UNIPHIER_CLK_GATE_SIMPLE(6, 0x210c, 6), /* ether */
UNIPHIER_CLK_GATE_SIMPLE(8, 0x210c, 8), /* stdmac */
UNIPHIER_CLK_GATE_SIMPLE(14, 0x210c, 14), /* usb30 (LD20) */
@@ -48,6 +49,7 @@ const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = {
const struct uniphier_clk_data uniphier_pxs3_sys_clk_data[] = {
#if defined(CONFIG_ARCH_UNIPHIER_PXS3)
UNIPHIER_LD11_SYS_CLK_NAND(2),
+ UNIPHIER_CLK_RATE(3, 200000000),
UNIPHIER_CLK_GATE_SIMPLE(6, 0x210c, 9), /* ether0 */
UNIPHIER_CLK_GATE_SIMPLE(7, 0x210c, 10), /* ether1 */
UNIPHIER_CLK_GATE_SIMPLE(12, 0x210c, 4), /* usb30 (gio0) */
diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c
index d1cac063f46..e0eb1339ecd 100644
--- a/drivers/mtd/nand/raw/denali.c
+++ b/drivers/mtd/nand/raw/denali.c
@@ -69,14 +69,6 @@ static int dma_mapping_error(void *dev, dma_addr_t addr)
#define DENALI_INVALID_BANK -1
#define DENALI_NR_BANKS 4
-/*
- * The bus interface clock, clk_x, is phase aligned with the core clock. The
- * clk_x is an integral multiple N of the core clk. The value N is configured
- * at IP delivery time, and its available value is 4, 5, or 6. We need to align
- * to the largest value to make it work with any possible configuration.
- */
-#define DENALI_CLK_X_MULT 6
-
static inline struct denali_nand_info *mtd_to_denali(struct mtd_info *mtd)
{
return container_of(mtd_to_nand(mtd), struct denali_nand_info, nand);
@@ -595,6 +587,12 @@ static int denali_dma_xfer(struct denali_nand_info *denali, void *buf,
}
iowrite32(DMA_ENABLE__FLAG, denali->reg + DMA_ENABLE);
+ /*
+ * The ->setup_dma() hook kicks DMA by using the data/command
+ * interface, which belongs to a different AXI port from the
+ * register interface. Read back the register to avoid a race.
+ */
+ ioread32(denali->reg + DMA_ENABLE);
denali_reset_irq(denali);
denali->setup_dma(denali, dma_addr, page, write);
@@ -946,7 +944,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr,
{
struct denali_nand_info *denali = mtd_to_denali(mtd);
const struct nand_sdr_timings *timings;
- unsigned long t_clk;
+ unsigned long t_x, mult_x;
int acc_clks, re_2_we, re_2_re, we_2_re, addr_2_data;
int rdwr_en_lo, rdwr_en_hi, rdwr_en_lo_hi, cs_setup;
int addr_2_data_mask;
@@ -957,15 +955,24 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr,
return PTR_ERR(timings);
/* clk_x period in picoseconds */
- t_clk = DIV_ROUND_DOWN_ULL(1000000000000ULL, denali->clk_x_rate);
- if (!t_clk)
+ t_x = DIV_ROUND_DOWN_ULL(1000000000000ULL, denali->clk_x_rate);
+ if (!t_x)
+ return -EINVAL;
+
+ /*
+ * The bus interface clock, clk_x, is phase aligned with the core clock.
+ * The clk_x is an integral multiple N of the core clk. The value N is
+ * configured at IP delivery time, and its available value is 4, 5, 6.
+ */
+ mult_x = DIV_ROUND_CLOSEST_ULL(denali->clk_x_rate, denali->clk_rate);
+ if (mult_x < 4 || mult_x > 6)
return -EINVAL;
if (chipnr == NAND_DATA_IFACE_CHECK_ONLY)
return 0;
/* tREA -> ACC_CLKS */
- acc_clks = DIV_ROUND_UP(timings->tREA_max, t_clk);
+ acc_clks = DIV_ROUND_UP(timings->tREA_max, t_x);
acc_clks = min_t(int, acc_clks, ACC_CLKS__VALUE);
tmp = ioread32(denali->reg + ACC_CLKS);
@@ -974,7 +981,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr,
iowrite32(tmp, denali->reg + ACC_CLKS);
/* tRWH -> RE_2_WE */
- re_2_we = DIV_ROUND_UP(timings->tRHW_min, t_clk);
+ re_2_we = DIV_ROUND_UP(timings->tRHW_min, t_x);
re_2_we = min_t(int, re_2_we, RE_2_WE__VALUE);
tmp = ioread32(denali->reg + RE_2_WE);
@@ -983,7 +990,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr,
iowrite32(tmp, denali->reg + RE_2_WE);
/* tRHZ -> RE_2_RE */
- re_2_re = DIV_ROUND_UP(timings->tRHZ_max, t_clk);
+ re_2_re = DIV_ROUND_UP(timings->tRHZ_max, t_x);
re_2_re = min_t(int, re_2_re, RE_2_RE__VALUE);
tmp = ioread32(denali->reg + RE_2_RE);
@@ -997,8 +1004,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr,
* With WE_2_RE properly set, the Denali controller automatically takes
* care of the delay; the driver need not set NAND_WAIT_TCCS.
*/
- we_2_re = DIV_ROUND_UP(max(timings->tCCS_min, timings->tWHR_min),
- t_clk);
+ we_2_re = DIV_ROUND_UP(max(timings->tCCS_min, timings->tWHR_min), t_x);
we_2_re = min_t(int, we_2_re, TWHR2_AND_WE_2_RE__WE_2_RE);
tmp = ioread32(denali->reg + TWHR2_AND_WE_2_RE);
@@ -1013,7 +1019,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr,
if (denali->revision < 0x0501)
addr_2_data_mask >>= 1;
- addr_2_data = DIV_ROUND_UP(timings->tADL_min, t_clk);
+ addr_2_data = DIV_ROUND_UP(timings->tADL_min, t_x);
addr_2_data = min_t(int, addr_2_data, addr_2_data_mask);
tmp = ioread32(denali->reg + TCWAW_AND_ADDR_2_DATA);
@@ -1023,7 +1029,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr,
/* tREH, tWH -> RDWR_EN_HI_CNT */
rdwr_en_hi = DIV_ROUND_UP(max(timings->tREH_min, timings->tWH_min),
- t_clk);
+ t_x);
rdwr_en_hi = min_t(int, rdwr_en_hi, RDWR_EN_HI_CNT__VALUE);
tmp = ioread32(denali->reg + RDWR_EN_HI_CNT);
@@ -1032,11 +1038,10 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr,
iowrite32(tmp, denali->reg + RDWR_EN_HI_CNT);
/* tRP, tWP -> RDWR_EN_LO_CNT */
- rdwr_en_lo = DIV_ROUND_UP(max(timings->tRP_min, timings->tWP_min),
- t_clk);
+ rdwr_en_lo = DIV_ROUND_UP(max(timings->tRP_min, timings->tWP_min), t_x);
rdwr_en_lo_hi = DIV_ROUND_UP(max(timings->tRC_min, timings->tWC_min),
- t_clk);
- rdwr_en_lo_hi = max(rdwr_en_lo_hi, DENALI_CLK_X_MULT);
+ t_x);
+ rdwr_en_lo_hi = max_t(int, rdwr_en_lo_hi, mult_x);
rdwr_en_lo = max(rdwr_en_lo, rdwr_en_lo_hi - rdwr_en_hi);
rdwr_en_lo = min_t(int, rdwr_en_lo, RDWR_EN_LO_CNT__VALUE);
@@ -1046,8 +1051,8 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr,
iowrite32(tmp, denali->reg + RDWR_EN_LO_CNT);
/* tCS, tCEA -> CS_SETUP_CNT */
- cs_setup = max3((int)DIV_ROUND_UP(timings->tCS_min, t_clk) - rdwr_en_lo,
- (int)DIV_ROUND_UP(timings->tCEA_max, t_clk) - acc_clks,
+ cs_setup = max3((int)DIV_ROUND_UP(timings->tCS_min, t_x) - rdwr_en_lo,
+ (int)DIV_ROUND_UP(timings->tCEA_max, t_x) - acc_clks,
0);
cs_setup = min_t(int, cs_setup, CS_SETUP_CNT__VALUE);
diff --git a/drivers/mtd/nand/raw/denali.h b/drivers/mtd/nand/raw/denali.h
index 9b797beffa7..019deda094e 100644
--- a/drivers/mtd/nand/raw/denali.h
+++ b/drivers/mtd/nand/raw/denali.h
@@ -292,6 +292,7 @@ struct udevice;
struct denali_nand_info {
struct nand_chip nand;
+ unsigned long clk_rate; /* core clock rate */
unsigned long clk_x_rate; /* bus interface clock rate */
int active_bank; /* currently selected bank */
struct udevice *dev;
diff --git a/drivers/mtd/nand/raw/denali_dt.c b/drivers/mtd/nand/raw/denali_dt.c
index 65a7797f0f3..d384b974df1 100644
--- a/drivers/mtd/nand/raw/denali_dt.c
+++ b/drivers/mtd/nand/raw/denali_dt.c
@@ -62,7 +62,7 @@ static int denali_dt_probe(struct udevice *dev)
{
struct denali_nand_info *denali = dev_get_priv(dev);
const struct denali_dt_data *data;
- struct clk clk;
+ struct clk clk, clk_x, clk_ecc;
struct resource res;
int ret;
@@ -87,15 +87,49 @@ static int denali_dt_probe(struct udevice *dev)
denali->host = devm_ioremap(dev, res.start, resource_size(&res));
- ret = clk_get_by_index(dev, 0, &clk);
+ ret = clk_get_by_name(dev, "nand", &clk);
+ if (ret)
+ ret = clk_get_by_index(dev, 0, &clk);
if (ret)
return ret;
+ ret = clk_get_by_name(dev, "nand_x", &clk_x);
+ if (ret)
+ clk_x.dev = NULL;
+
+ ret = clk_get_by_name(dev, "ecc", &clk_ecc);
+ if (ret)
+ clk_ecc.dev = NULL;
+
ret = clk_enable(&clk);
if (ret)
return ret;
- denali->clk_x_rate = clk_get_rate(&clk);
+ if (clk_x.dev) {
+ ret = clk_enable(&clk_x);
+ if (ret)
+ return ret;
+ }
+
+ if (clk_ecc.dev) {
+ ret = clk_enable(&clk_ecc);
+ if (ret)
+ return ret;
+ }
+
+ if (clk_x.dev) {
+ denali->clk_rate = clk_get_rate(&clk);
+ denali->clk_x_rate = clk_get_rate(&clk_x);
+ } else {
+ /*
+ * Hardcode the clock rates for the backward compatibility.
+ * This works for both SOCFPGA and UniPhier.
+ */
+ dev_notice(dev,
+ "necessary clock is missing. default clock rates are used.\n");
+ denali->clk_rate = 50000000;
+ denali->clk_x_rate = 200000000;
+ }
return denali_init(denali);
}