summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/adc/meson-saradc.c2
-rw-r--r--drivers/block/Kconfig7
-rw-r--r--drivers/block/Makefile2
-rw-r--r--drivers/clk/Makefile1
-rw-r--r--drivers/clk/clk_meson.c393
-rw-r--r--drivers/clk/clk_meson.h47
-rw-r--r--drivers/gpio/da8xx_gpio.c193
-rw-r--r--drivers/gpio/omap_gpio.c10
-rw-r--r--drivers/i2c/meson_i2c.c20
-rw-r--r--drivers/misc/swap_case.c2
-rw-r--r--drivers/mtd/spi/sandbox.c7
11 files changed, 649 insertions, 35 deletions
diff --git a/drivers/adc/meson-saradc.c b/drivers/adc/meson-saradc.c
index bcab76d050..f7c919d3b0 100644
--- a/drivers/adc/meson-saradc.c
+++ b/drivers/adc/meson-saradc.c
@@ -654,7 +654,7 @@ static int meson_saradc_probe(struct udevice *dev)
struct meson_saradc_priv *priv = dev_get_priv(dev);
int ret;
- ret = regmap_init_mem(dev, &priv->regmap);
+ ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
if (ret)
return ret;
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 0792373cfc..f9502b36ba 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -37,6 +37,13 @@ config BLOCK_CACHE
it will prevent repeated reads from directory structures and other
filesystem data structures.
+config SPL_BLOCK_CACHE
+ bool "Use block device cache in SPL"
+ depends on SPL_BLK
+ default n
+ help
+ This option enables the disk-block cache in SPL
+
config IDE
bool "Support IDE controllers"
select HAVE_BLOCK_DEVICE
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 5fcafb193e..0e80ce9405 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -11,4 +11,4 @@ endif
obj-$(CONFIG_IDE) += ide.o
obj-$(CONFIG_SANDBOX) += sandbox.o
-obj-$(CONFIG_BLOCK_CACHE) += blkcache.o
+obj-$(CONFIG_$(SPL_)BLOCK_CACHE) += blkcache.o
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 58139b13a8..426c67db9b 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_$(SPL_TPL_)CLK) += clk-uclass.o clk_fixed_rate.o
obj-y += tegra/
obj-$(CONFIG_ARCH_ASPEED) += aspeed/
+obj-$(CONFIG_ARCH_MESON) += clk_meson.o
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
obj-$(CONFIG_CLK_AT91) += at91/
obj-$(CONFIG_CLK_MVEBU) += mvebu/
diff --git a/drivers/clk/clk_meson.c b/drivers/clk/clk_meson.c
new file mode 100644
index 0000000000..3850128e5c
--- /dev/null
+++ b/drivers/clk/clk_meson.c
@@ -0,0 +1,393 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018 - Beniamino Galvani <b.galvani@gmail.com>
+ * (C) Copyright 2018 - BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include <common.h>
+#include <asm/arch/clock.h>
+#include <asm/io.h>
+#include <clk-uclass.h>
+#include <div64.h>
+#include <dm.h>
+#include <dt-bindings/clock/gxbb-clkc.h>
+#include "clk_meson.h"
+
+#define XTAL_RATE 24000000
+
+struct meson_clk {
+ void __iomem *addr;
+};
+
+static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id);
+
+struct meson_gate gates[] = {
+ /* Everything Else (EE) domain gates */
+ MESON_GATE(CLKID_DDR, HHI_GCLK_MPEG0, 0),
+ MESON_GATE(CLKID_DOS, HHI_GCLK_MPEG0, 1),
+ MESON_GATE(CLKID_ISA, HHI_GCLK_MPEG0, 5),
+ MESON_GATE(CLKID_PL301, HHI_GCLK_MPEG0, 6),
+ MESON_GATE(CLKID_PERIPHS, HHI_GCLK_MPEG0, 7),
+ MESON_GATE(CLKID_SPICC, HHI_GCLK_MPEG0, 8),
+ MESON_GATE(CLKID_I2C, HHI_GCLK_MPEG0, 9),
+ MESON_GATE(CLKID_SAR_ADC, HHI_GCLK_MPEG0, 10),
+ MESON_GATE(CLKID_SMART_CARD, HHI_GCLK_MPEG0, 11),
+ MESON_GATE(CLKID_RNG0, HHI_GCLK_MPEG0, 12),
+ MESON_GATE(CLKID_UART0, HHI_GCLK_MPEG0, 13),
+ MESON_GATE(CLKID_SDHC, HHI_GCLK_MPEG0, 14),
+ MESON_GATE(CLKID_STREAM, HHI_GCLK_MPEG0, 15),
+ MESON_GATE(CLKID_ASYNC_FIFO, HHI_GCLK_MPEG0, 16),
+ MESON_GATE(CLKID_SDIO, HHI_GCLK_MPEG0, 17),
+ MESON_GATE(CLKID_ABUF, HHI_GCLK_MPEG0, 18),
+ MESON_GATE(CLKID_HIU_IFACE, HHI_GCLK_MPEG0, 19),
+ MESON_GATE(CLKID_ASSIST_MISC, HHI_GCLK_MPEG0, 23),
+ MESON_GATE(CLKID_SD_EMMC_A, HHI_GCLK_MPEG0, 24),
+ MESON_GATE(CLKID_SD_EMMC_B, HHI_GCLK_MPEG0, 25),
+ MESON_GATE(CLKID_SD_EMMC_C, HHI_GCLK_MPEG0, 26),
+ MESON_GATE(CLKID_SPI, HHI_GCLK_MPEG0, 30),
+
+ MESON_GATE(CLKID_I2S_SPDIF, HHI_GCLK_MPEG1, 2),
+ MESON_GATE(CLKID_ETH, HHI_GCLK_MPEG1, 3),
+ MESON_GATE(CLKID_DEMUX, HHI_GCLK_MPEG1, 4),
+ MESON_GATE(CLKID_AIU_GLUE, HHI_GCLK_MPEG1, 6),
+ MESON_GATE(CLKID_IEC958, HHI_GCLK_MPEG1, 7),
+ MESON_GATE(CLKID_I2S_OUT, HHI_GCLK_MPEG1, 8),
+ MESON_GATE(CLKID_AMCLK, HHI_GCLK_MPEG1, 9),
+ MESON_GATE(CLKID_AIFIFO2, HHI_GCLK_MPEG1, 10),
+ MESON_GATE(CLKID_MIXER, HHI_GCLK_MPEG1, 11),
+ MESON_GATE(CLKID_MIXER_IFACE, HHI_GCLK_MPEG1, 12),
+ MESON_GATE(CLKID_ADC, HHI_GCLK_MPEG1, 13),
+ MESON_GATE(CLKID_BLKMV, HHI_GCLK_MPEG1, 14),
+ MESON_GATE(CLKID_AIU, HHI_GCLK_MPEG1, 15),
+ MESON_GATE(CLKID_UART1, HHI_GCLK_MPEG1, 16),
+ MESON_GATE(CLKID_G2D, HHI_GCLK_MPEG1, 20),
+ MESON_GATE(CLKID_USB0, HHI_GCLK_MPEG1, 21),
+ MESON_GATE(CLKID_USB1, HHI_GCLK_MPEG1, 22),
+ MESON_GATE(CLKID_RESET, HHI_GCLK_MPEG1, 23),
+ MESON_GATE(CLKID_NAND, HHI_GCLK_MPEG1, 24),
+ MESON_GATE(CLKID_DOS_PARSER, HHI_GCLK_MPEG1, 25),
+ MESON_GATE(CLKID_USB, HHI_GCLK_MPEG1, 26),
+ MESON_GATE(CLKID_VDIN1, HHI_GCLK_MPEG1, 28),
+ MESON_GATE(CLKID_AHB_ARB0, HHI_GCLK_MPEG1, 29),
+ MESON_GATE(CLKID_EFUSE, HHI_GCLK_MPEG1, 30),
+ MESON_GATE(CLKID_BOOT_ROM, HHI_GCLK_MPEG1, 31),
+
+ MESON_GATE(CLKID_AHB_DATA_BUS, HHI_GCLK_MPEG2, 1),
+ MESON_GATE(CLKID_AHB_CTRL_BUS, HHI_GCLK_MPEG2, 2),
+ MESON_GATE(CLKID_HDMI_INTR_SYNC, HHI_GCLK_MPEG2, 3),
+ MESON_GATE(CLKID_HDMI_PCLK, HHI_GCLK_MPEG2, 4),
+ MESON_GATE(CLKID_USB1_DDR_BRIDGE, HHI_GCLK_MPEG2, 8),
+ MESON_GATE(CLKID_USB0_DDR_BRIDGE, HHI_GCLK_MPEG2, 9),
+ MESON_GATE(CLKID_MMC_PCLK, HHI_GCLK_MPEG2, 11),
+ MESON_GATE(CLKID_DVIN, HHI_GCLK_MPEG2, 12),
+ MESON_GATE(CLKID_UART2, HHI_GCLK_MPEG2, 15),
+ MESON_GATE(CLKID_SANA, HHI_GCLK_MPEG2, 22),
+ MESON_GATE(CLKID_VPU_INTR, HHI_GCLK_MPEG2, 25),
+ MESON_GATE(CLKID_SEC_AHB_AHB3_BRIDGE, HHI_GCLK_MPEG2, 26),
+ MESON_GATE(CLKID_CLK81_A53, HHI_GCLK_MPEG2, 29),
+
+ MESON_GATE(CLKID_VCLK2_VENCI0, HHI_GCLK_OTHER, 1),
+ MESON_GATE(CLKID_VCLK2_VENCI1, HHI_GCLK_OTHER, 2),
+ MESON_GATE(CLKID_VCLK2_VENCP0, HHI_GCLK_OTHER, 3),
+ MESON_GATE(CLKID_VCLK2_VENCP1, HHI_GCLK_OTHER, 4),
+ MESON_GATE(CLKID_GCLK_VENCI_INT0, HHI_GCLK_OTHER, 8),
+ MESON_GATE(CLKID_DAC_CLK, HHI_GCLK_OTHER, 10),
+ MESON_GATE(CLKID_AOCLK_GATE, HHI_GCLK_OTHER, 14),
+ MESON_GATE(CLKID_IEC958_GATE, HHI_GCLK_OTHER, 16),
+ MESON_GATE(CLKID_ENC480P, HHI_GCLK_OTHER, 20),
+ MESON_GATE(CLKID_RNG1, HHI_GCLK_OTHER, 21),
+ MESON_GATE(CLKID_GCLK_VENCI_INT1, HHI_GCLK_OTHER, 22),
+ MESON_GATE(CLKID_VCLK2_VENCLMCC, HHI_GCLK_OTHER, 24),
+ MESON_GATE(CLKID_VCLK2_VENCL, HHI_GCLK_OTHER, 25),
+ MESON_GATE(CLKID_VCLK_OTHER, HHI_GCLK_OTHER, 26),
+ MESON_GATE(CLKID_EDP, HHI_GCLK_OTHER, 31),
+
+ /* Always On (AO) domain gates */
+ MESON_GATE(CLKID_AO_MEDIA_CPU, HHI_GCLK_AO, 0),
+ MESON_GATE(CLKID_AO_AHB_SRAM, HHI_GCLK_AO, 1),
+ MESON_GATE(CLKID_AO_AHB_BUS, HHI_GCLK_AO, 2),
+ MESON_GATE(CLKID_AO_IFACE, HHI_GCLK_AO, 3),
+ MESON_GATE(CLKID_AO_I2C, HHI_GCLK_AO, 4),
+
+ /* PLL Gates */
+ /* CLKID_FCLK_DIV2 is critical for the SCPI Processor */
+ MESON_GATE(CLKID_FCLK_DIV3, HHI_MPLL_CNTL6, 28),
+ MESON_GATE(CLKID_FCLK_DIV4, HHI_MPLL_CNTL6, 29),
+ MESON_GATE(CLKID_FCLK_DIV5, HHI_MPLL_CNTL6, 30),
+ MESON_GATE(CLKID_FCLK_DIV7, HHI_MPLL_CNTL6, 31),
+ MESON_GATE(CLKID_MPLL0, HHI_MPLL_CNTL7, 14),
+ MESON_GATE(CLKID_MPLL1, HHI_MPLL_CNTL8, 14),
+ MESON_GATE(CLKID_MPLL2, HHI_MPLL_CNTL9, 14),
+ /* CLKID_CLK81 is critical for the system */
+
+ /* Peripheral Gates */
+ MESON_GATE(CLKID_SAR_ADC_CLK, HHI_SAR_CLK_CNTL, 8),
+ MESON_GATE(CLKID_SD_EMMC_A_CLK0, HHI_SD_EMMC_CLK_CNTL, 7),
+ MESON_GATE(CLKID_SD_EMMC_B_CLK0, HHI_SD_EMMC_CLK_CNTL, 23),
+ MESON_GATE(CLKID_SD_EMMC_C_CLK0, HHI_NAND_CLK_CNTL, 7),
+};
+
+static int meson_set_gate(struct clk *clk, bool on)
+{
+ struct meson_clk *priv = dev_get_priv(clk->dev);
+ struct meson_gate *gate;
+
+ if (clk->id >= ARRAY_SIZE(gates))
+ return -ENOENT;
+
+ gate = &gates[clk->id];
+
+ if (gate->reg == 0)
+ return 0;
+
+ clrsetbits_le32(priv->addr + gate->reg,
+ BIT(gate->bit), on ? BIT(gate->bit) : 0);
+ return 0;
+}
+
+static int meson_clk_enable(struct clk *clk)
+{
+ return meson_set_gate(clk, true);
+}
+
+static int meson_clk_disable(struct clk *clk)
+{
+ return meson_set_gate(clk, false);
+}
+
+static unsigned long meson_clk81_get_rate(struct clk *clk)
+{
+ struct meson_clk *priv = dev_get_priv(clk->dev);
+ unsigned long parent_rate;
+ u32 reg;
+ int parents[] = {
+ -1,
+ -1,
+ CLKID_FCLK_DIV7,
+ CLKID_MPLL1,
+ CLKID_MPLL2,
+ CLKID_FCLK_DIV4,
+ CLKID_FCLK_DIV3,
+ CLKID_FCLK_DIV5
+ };
+
+ /* mux */
+ reg = readl(priv->addr + HHI_MPEG_CLK_CNTL);
+ reg = (reg >> 12) & 7;
+
+ switch (reg) {
+ case 0:
+ parent_rate = XTAL_RATE;
+ break;
+ case 1:
+ return -ENOENT;
+ default:
+ parent_rate = meson_clk_get_rate_by_id(clk, parents[reg]);
+ }
+
+ /* divider */
+ reg = readl(priv->addr + HHI_MPEG_CLK_CNTL);
+ reg = reg & ((1 << 7) - 1);
+
+ return parent_rate / reg;
+}
+
+static long mpll_rate_from_params(unsigned long parent_rate,
+ unsigned long sdm,
+ unsigned long n2)
+{
+ unsigned long divisor = (SDM_DEN * n2) + sdm;
+
+ if (n2 < N2_MIN)
+ return -EINVAL;
+
+ return DIV_ROUND_UP_ULL((u64)parent_rate * SDM_DEN, divisor);
+}
+
+static struct parm meson_mpll0_parm[3] = {
+ {HHI_MPLL_CNTL7, 0, 14}, /* psdm */
+ {HHI_MPLL_CNTL7, 16, 9}, /* pn2 */
+};
+
+static struct parm meson_mpll1_parm[3] = {
+ {HHI_MPLL_CNTL8, 0, 14}, /* psdm */
+ {HHI_MPLL_CNTL8, 16, 9}, /* pn2 */
+};
+
+static struct parm meson_mpll2_parm[3] = {
+ {HHI_MPLL_CNTL9, 0, 14}, /* psdm */
+ {HHI_MPLL_CNTL9, 16, 9}, /* pn2 */
+};
+
+/*
+ * MultiPhase Locked Loops are outputs from a PLL with additional frequency
+ * scaling capabilities. MPLL rates are calculated as:
+ *
+ * f(N2_integer, SDM_IN ) = 2.0G/(N2_integer + SDM_IN/16384)
+ */
+static ulong meson_mpll_get_rate(struct clk *clk, unsigned long id)
+{
+ struct meson_clk *priv = dev_get_priv(clk->dev);
+ struct parm *psdm, *pn2;
+ unsigned long reg, sdm, n2;
+ unsigned long parent_rate;
+
+ switch (id) {
+ case CLKID_MPLL0:
+ psdm = &meson_mpll0_parm[0];
+ pn2 = &meson_mpll0_parm[1];
+ break;
+ case CLKID_MPLL1:
+ psdm = &meson_mpll1_parm[0];
+ pn2 = &meson_mpll1_parm[1];
+ break;
+ case CLKID_MPLL2:
+ psdm = &meson_mpll2_parm[0];
+ pn2 = &meson_mpll2_parm[1];
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ parent_rate = meson_clk_get_rate_by_id(clk, CLKID_FIXED_PLL);
+ if (IS_ERR_VALUE(parent_rate))
+ return parent_rate;
+
+ reg = readl(priv->addr + psdm->reg_off);
+ sdm = PARM_GET(psdm->width, psdm->shift, reg);
+
+ reg = readl(priv->addr + pn2->reg_off);
+ n2 = PARM_GET(pn2->width, pn2->shift, reg);
+
+ return mpll_rate_from_params(parent_rate, sdm, n2);
+}
+
+static struct parm meson_fixed_pll_parm[3] = {
+ {HHI_MPLL_CNTL, 0, 9}, /* pm */
+ {HHI_MPLL_CNTL, 9, 5}, /* pn */
+ {HHI_MPLL_CNTL, 16, 2}, /* pod */
+};
+
+static struct parm meson_sys_pll_parm[3] = {
+ {HHI_SYS_PLL_CNTL, 0, 9}, /* pm */
+ {HHI_SYS_PLL_CNTL, 9, 5}, /* pn */
+ {HHI_SYS_PLL_CNTL, 10, 2}, /* pod */
+};
+
+static ulong meson_pll_get_rate(struct clk *clk, unsigned long id)
+{
+ struct meson_clk *priv = dev_get_priv(clk->dev);
+ struct parm *pm, *pn, *pod;
+ unsigned long parent_rate_mhz = XTAL_RATE / 1000000;
+ u16 n, m, od;
+ u32 reg;
+
+ switch (id) {
+ case CLKID_FIXED_PLL:
+ pm = &meson_fixed_pll_parm[0];
+ pn = &meson_fixed_pll_parm[1];
+ pod = &meson_fixed_pll_parm[2];
+ break;
+ case CLKID_SYS_PLL:
+ pm = &meson_sys_pll_parm[0];
+ pn = &meson_sys_pll_parm[1];
+ pod = &meson_sys_pll_parm[2];
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ reg = readl(priv->addr + pn->reg_off);
+ n = PARM_GET(pn->width, pn->shift, reg);
+
+ reg = readl(priv->addr + pm->reg_off);
+ m = PARM_GET(pm->width, pm->shift, reg);
+
+ reg = readl(priv->addr + pod->reg_off);
+ od = PARM_GET(pod->width, pod->shift, reg);
+
+ return ((parent_rate_mhz * m / n) >> od) * 1000000;
+}
+
+static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id)
+{
+ ulong rate;
+
+ switch (id) {
+ case CLKID_FIXED_PLL:
+ case CLKID_SYS_PLL:
+ rate = meson_pll_get_rate(clk, id);
+ break;
+ case CLKID_FCLK_DIV2:
+ rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 2;
+ break;
+ case CLKID_FCLK_DIV3:
+ rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 3;
+ break;
+ case CLKID_FCLK_DIV4:
+ rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 4;
+ break;
+ case CLKID_FCLK_DIV5:
+ rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 5;
+ break;
+ case CLKID_FCLK_DIV7:
+ rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 7;
+ break;
+ case CLKID_MPLL0:
+ case CLKID_MPLL1:
+ case CLKID_MPLL2:
+ rate = meson_mpll_get_rate(clk, id);
+ break;
+ case CLKID_CLK81:
+ rate = meson_clk81_get_rate(clk);
+ break;
+ default:
+ if (gates[id].reg != 0) {
+ /* a clock gate */
+ rate = meson_clk81_get_rate(clk);
+ break;
+ }
+ return -ENOENT;
+ }
+
+ printf("clock %lu has rate %lu\n", id, rate);
+ return rate;
+}
+
+static ulong meson_clk_get_rate(struct clk *clk)
+{
+ return meson_clk_get_rate_by_id(clk, clk->id);
+}
+
+static int meson_clk_probe(struct udevice *dev)
+{
+ struct meson_clk *priv = dev_get_priv(dev);
+
+ priv->addr = dev_read_addr_ptr(dev);
+
+ debug("meson-clk: probed at addr %p\n", priv->addr);
+
+ return 0;
+}
+
+static struct clk_ops meson_clk_ops = {
+ .disable = meson_clk_disable,
+ .enable = meson_clk_enable,
+ .get_rate = meson_clk_get_rate,
+};
+
+static const struct udevice_id meson_clk_ids[] = {
+ { .compatible = "amlogic,gxbb-clkc" },
+ { .compatible = "amlogic,gxl-clkc" },
+ { }
+};
+
+U_BOOT_DRIVER(meson_clk) = {
+ .name = "meson_clk",
+ .id = UCLASS_CLK,
+ .of_match = meson_clk_ids,
+ .priv_auto_alloc_size = sizeof(struct meson_clk),
+ .ops = &meson_clk_ops,
+ .probe = meson_clk_probe,
+};
diff --git a/drivers/clk/clk_meson.h b/drivers/clk/clk_meson.h
new file mode 100644
index 0000000000..7adc55a980
--- /dev/null
+++ b/drivers/clk/clk_meson.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2018 - Beniamino Galvani <b.galvani@gmail.com>
+ * (C) Copyright 2018 - BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#ifndef CLK_MESON_H
+#define CLK_MESON_H
+
+/* Gate Structure */
+
+struct meson_gate {
+ unsigned int reg;
+ unsigned int bit;
+};
+
+#define MESON_GATE(id, _reg, _bit) \
+ [id] = { \
+ .reg = (_reg), \
+ .bit = (_bit), \
+ }
+
+/* PLL Parameters */
+
+struct parm {
+ u16 reg_off;
+ u8 shift;
+ u8 width;
+};
+
+#define PMASK(width) GENMASK(width - 1, 0)
+#define SETPMASK(width, shift) GENMASK(shift + width - 1, shift)
+#define CLRPMASK(width, shift) (~SETPMASK(width, shift))
+
+#define PARM_GET(width, shift, reg) \
+ (((reg) & SETPMASK(width, shift)) >> (shift))
+#define PARM_SET(width, shift, reg, val) \
+ (((reg) & CLRPMASK(width, shift)) | ((val) << (shift)))
+
+/* MPLL Parameters */
+
+#define SDM_DEN 16384
+#define N2_MIN 4
+#define N2_MAX 511
+
+#endif
diff --git a/drivers/gpio/da8xx_gpio.c b/drivers/gpio/da8xx_gpio.c
index e410f5f9df..1a1d37ae2a 100644
--- a/drivers/gpio/da8xx_gpio.c
+++ b/drivers/gpio/da8xx_gpio.c
@@ -7,11 +7,14 @@
*/
#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
#include <asm/io.h>
#include <asm/gpio.h>
#include <asm/arch/hardware.h>
#include <asm/arch/davinci_misc.h>
+#ifndef CONFIG_DM_GPIO
static struct gpio_registry {
int is_registered;
char name[GPIO_NAME_SIZE];
@@ -303,7 +306,7 @@ static const struct pinmux_config gpio_pinmux[] = {
#define davinci_configure_pin_mux(a, b)
#endif /* CONFIG_SOC_DA8XX */
-int gpio_request(unsigned gpio, const char *label)
+int gpio_request(unsigned int gpio, const char *label)
{
if (gpio >= MAX_NUM_GPIOS)
return -1;
@@ -320,7 +323,7 @@ int gpio_request(unsigned gpio, const char *label)
return 0;
}
-int gpio_free(unsigned gpio)
+int gpio_free(unsigned int gpio)
{
if (gpio >= MAX_NUM_GPIOS)
return -1;
@@ -333,42 +336,30 @@ int gpio_free(unsigned gpio)
/* Do not configure as input or change pin mux here */
return 0;
}
+#endif
-int gpio_direction_input(unsigned gpio)
+static int _gpio_direction_output(struct davinci_gpio *bank, unsigned int gpio, int value)
{
- struct davinci_gpio *bank;
-
- bank = GPIO_BANK(gpio);
- setbits_le32(&bank->dir, 1U << GPIO_BIT(gpio));
+ clrbits_le32(&bank->dir, 1U << GPIO_BIT(gpio));
+ gpio_set_value(gpio, value);
return 0;
}
-int gpio_direction_output(unsigned gpio, int value)
+static int _gpio_direction_input(struct davinci_gpio *bank, unsigned int gpio)
{
- struct davinci_gpio *bank;
-
- bank = GPIO_BANK(gpio);
- clrbits_le32(&bank->dir, 1U << GPIO_BIT(gpio));
- gpio_set_value(gpio, value);
+ setbits_le32(&bank->dir, 1U << GPIO_BIT(gpio));
return 0;
}
-int gpio_get_value(unsigned gpio)
+static int _gpio_get_value(struct davinci_gpio *bank, unsigned int gpio)
{
- struct davinci_gpio *bank;
unsigned int ip;
-
- bank = GPIO_BANK(gpio);
ip = in_le32(&bank->in_data) & (1U << GPIO_BIT(gpio));
return ip ? 1 : 0;
}
-int gpio_set_value(unsigned gpio, int value)
+static int _gpio_set_value(struct davinci_gpio *bank, unsigned int gpio, int value)
{
- struct davinci_gpio *bank;
-
- bank = GPIO_BANK(gpio);
-
if (value)
bank->set_data = 1U << GPIO_BIT(gpio);
else
@@ -377,14 +368,21 @@ int gpio_set_value(unsigned gpio, int value)
return 0;
}
+static int _gpio_get_dir(struct davinci_gpio *bank, unsigned int gpio)
+{
+ return in_le32(&bank->dir) & (1U << GPIO_BIT(gpio));
+}
+
+#ifndef CONFIG_DM_GPIO
+
void gpio_info(void)
{
- unsigned gpio, dir, val;
+ unsigned int gpio, dir, val;
struct davinci_gpio *bank;
for (gpio = 0; gpio < MAX_NUM_GPIOS; ++gpio) {
bank = GPIO_BANK(gpio);
- dir = in_le32(&bank->dir) & (1U << GPIO_BIT(gpio));
+ dir = _gpio_get_dir(bank, gpio);
val = gpio_get_value(gpio);
printf("% 4d: %s: %d [%c] %s\n",
@@ -393,3 +391,150 @@ void gpio_info(void)
gpio_registry[gpio].name);
}
}
+
+int gpio_direction_input(unsigned int gpio)
+{
+ struct davinci_gpio *bank;
+
+ bank = GPIO_BANK(gpio);
+ return _gpio_direction_input(bank, gpio);
+}
+
+int gpio_direction_output(unsigned int gpio, int value)
+{
+ struct davinci_gpio *bank;
+
+ bank = GPIO_BANK(gpio);
+ return _gpio_direction_output(bank, gpio, value);
+}
+
+int gpio_get_value(unsigned int gpio)
+{
+ struct davinci_gpio *bank;
+
+ bank = GPIO_BANK(gpio);
+ return _gpio_get_value(bank, gpio);
+}
+
+int gpio_set_value(unsigned int gpio, int value)
+{
+ struct davinci_gpio *bank;
+
+ bank = GPIO_BANK(gpio);
+ return _gpio_set_value(bank, gpio, value);
+}
+
+#else /* CONFIG_DM_GPIO */
+
+static struct davinci_gpio *davinci_get_gpio_bank(struct udevice *dev, unsigned int offset)
+{
+ struct davinci_gpio_bank *bank = dev_get_priv(dev);
+
+ /* The device tree is not broken into banks but the infrastructure is
+ * expecting it this way, so we'll first include the 0x10 offset, then
+ * calculate the bank manually based on the offset.
+ */
+
+ return ((struct davinci_gpio *)bank->base) + 0x10 + (offset >> 5);
+}
+
+static int davinci_gpio_direction_input(struct udevice *dev, unsigned int offset)
+{
+ struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset);
+
+ _gpio_direction_input(base, offset);
+ return 0;
+}
+
+static int davinci_gpio_direction_output(struct udevice *dev, unsigned int offset,
+ int value)
+{
+ struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset);
+
+ _gpio_direction_output(base, offset, value);
+ return 0;
+}
+
+static int davinci_gpio_get_value(struct udevice *dev, unsigned int offset)
+{
+ struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset);
+
+ return _gpio_get_value(base, offset);
+}
+
+static int davinci_gpio_set_value(struct udevice *dev, unsigned int offset,
+ int value)
+{
+ struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset);
+
+ _gpio_set_value(base, offset, value);
+
+ return 0;
+}
+
+static int davinci_gpio_get_function(struct udevice *dev, unsigned int offset)
+{
+ unsigned int dir;
+ struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset);
+
+ dir = _gpio_get_dir(base, offset);
+
+ if (dir)
+ return GPIOF_INPUT;
+
+ return GPIOF_OUTPUT;
+}
+
+static const struct dm_gpio_ops gpio_davinci_ops = {
+ .direction_input = davinci_gpio_direction_input,
+ .direction_output = davinci_gpio_direction_output,
+ .get_value = davinci_gpio_get_value,
+ .set_value = davinci_gpio_set_value,
+ .get_function = davinci_gpio_get_function,
+};
+
+static int davinci_gpio_probe(struct udevice *dev)
+{
+ struct davinci_gpio_bank *bank = dev_get_priv(dev);
+ struct davinci_gpio_platdata *plat = dev_get_platdata(dev);
+ struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+ const void *fdt = gd->fdt_blob;
+ int node = dev_of_offset(dev);
+
+ uc_priv->bank_name = plat->port_name;
+ uc_priv->gpio_count = fdtdec_get_int(fdt, node, "ti,ngpio", -1);
+ bank->base = (struct davinci_gpio *)plat->base;
+ return 0;
+}
+
+static const struct udevice_id davinci_gpio_ids[] = {
+ { .compatible = "ti,dm6441-gpio" },
+ { }
+};
+
+static int davinci_gpio_ofdata_to_platdata(struct udevice *dev)
+{
+ struct davinci_gpio_platdata *plat = dev_get_platdata(dev);
+ fdt_addr_t addr;
+
+ addr = devfdt_get_addr(dev);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ plat->base = addr;
+ return 0;
+}
+
+U_BOOT_DRIVER(gpio_davinci) = {
+ .name = "gpio_davinci",
+ .id = UCLASS_GPIO,
+ .ops = &gpio_davinci_ops,
+ .ofdata_to_platdata = of_match_ptr(davinci_gpio_ofdata_to_platdata),
+ .of_match = davinci_gpio_ids,
+ .bind = dm_scan_fdt_dev,
+ .platdata_auto_alloc_size = sizeof(struct davinci_gpio_platdata),
+ .probe = davinci_gpio_probe,
+ .priv_auto_alloc_size = sizeof(struct davinci_gpio_bank),
+};
+
+#endif
diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c
index d128f942a0..79a975ce71 100644
--- a/drivers/gpio/omap_gpio.c
+++ b/drivers/gpio/omap_gpio.c
@@ -288,11 +288,17 @@ static int omap_gpio_probe(struct udevice *dev)
struct gpio_bank *bank = dev_get_priv(dev);
struct omap_gpio_platdata *plat = dev_get_platdata(dev);
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+ int banknum;
+ char name[18], *str;
- uc_priv->bank_name = plat->port_name;
+ banknum = plat->bank_index;
+ sprintf(name, "GPIO%d_", banknum + 1);
+ str = strdup(name);
+ if (!str)
+ return -ENOMEM;
+ uc_priv->bank_name = str;
uc_priv->gpio_count = GPIO_PER_BANK;
bank->base = (void *)plat->base;
-
return 0;
}
diff --git a/drivers/i2c/meson_i2c.c b/drivers/i2c/meson_i2c.c
index 8c9318d4f1..7d06d95cf3 100644
--- a/drivers/i2c/meson_i2c.c
+++ b/drivers/i2c/meson_i2c.c
@@ -3,8 +3,8 @@
* (C) Copyright 2017 - Beniamino Galvani <b.galvani@gmail.com>
*/
#include <common.h>
-#include <asm/arch/i2c.h>
#include <asm/io.h>
+#include <clk.h>
#include <dm.h>
#include <i2c.h>
@@ -42,6 +42,7 @@ struct i2c_regs {
};
struct meson_i2c {
+ struct clk clk;
struct i2c_regs *regs;
struct i2c_msg *msg; /* Current I2C message */
bool last; /* Whether the message is the last */
@@ -221,9 +222,13 @@ static int meson_i2c_xfer(struct udevice *bus, struct i2c_msg *msg,
static int meson_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
{
struct meson_i2c *i2c = dev_get_priv(bus);
- unsigned int clk_rate = MESON_I2C_CLK_RATE;
+ ulong clk_rate;
unsigned int div;
+ clk_rate = clk_get_rate(&i2c->clk);
+ if (IS_ERR_VALUE(clk_rate))
+ return -EINVAL;
+
div = DIV_ROUND_UP(clk_rate, speed * 4);
/* clock divider has 12 bits */
@@ -238,7 +243,7 @@ static int meson_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
clrsetbits_le32(&i2c->regs->ctrl, REG_CTRL_CLKDIVEXT_MASK,
(div >> 10) << REG_CTRL_CLKDIVEXT_SHIFT);
- debug("meson i2c: set clk %u, src %u, div %u\n", speed, clk_rate, div);
+ debug("meson i2c: set clk %u, src %lu, div %u\n", speed, clk_rate, div);
return 0;
}
@@ -246,6 +251,15 @@ static int meson_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
static int meson_i2c_probe(struct udevice *bus)
{
struct meson_i2c *i2c = dev_get_priv(bus);
+ int ret;
+
+ ret = clk_get_by_index(bus, 0, &i2c->clk);
+ if (ret < 0)
+ return ret;
+
+ ret = clk_enable(&i2c->clk);
+ if (ret)
+ return ret;
i2c->regs = dev_read_addr_ptr(bus);
clrbits_le32(&i2c->regs->ctrl, REG_CTRL_START);
diff --git a/drivers/misc/swap_case.c b/drivers/misc/swap_case.c
index 56cd0700fa..b777404c09 100644
--- a/drivers/misc/swap_case.c
+++ b/drivers/misc/swap_case.c
@@ -21,7 +21,7 @@
*/
struct swap_case_platdata {
u16 command;
- u32 bar[2];
+ u32 bar[6];
};
#define offset_to_barnum(offset) \
diff --git a/drivers/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c
index 7893efee12..f23c0e13e0 100644
--- a/drivers/mtd/spi/sandbox.c
+++ b/drivers/mtd/spi/sandbox.c
@@ -567,16 +567,17 @@ int sandbox_sf_bind_emul(struct sandbox_state *state, int busnum, int cs,
strncpy(name, spec, sizeof(name) - 6);
name[sizeof(name) - 6] = '\0';
strcat(name, "-emul");
- str = strdup(name);
- if (!str)
- return -ENOMEM;
drv = lists_driver_lookup_name("sandbox_sf_emul");
if (!drv) {
puts("Cannot find sandbox_sf_emul driver\n");
return -ENOENT;
}
+ str = strdup(name);
+ if (!str)
+ return -ENOMEM;
ret = device_bind(bus, drv, str, NULL, of_offset, &emul);
if (ret) {
+ free(str);
printf("Cannot create emul device for spec '%s' (err=%d)\n",
spec, ret);
return ret;