summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/at91/pmc.c57
-rw-r--r--drivers/clk/clk-uclass.c37
-rw-r--r--drivers/clk/clk.c65
-rw-r--r--drivers/clk/clk_sandbox.c6
-rw-r--r--drivers/clk/clk_sandbox_test.c9
-rw-r--r--drivers/clk/imx/clk-imx6q.c73
-rw-r--r--drivers/clk/imx/clk-imx8mm.c88
-rw-r--r--drivers/clk/imx/clk-imx8mn.c88
-rw-r--r--drivers/clk/imx/clk-imx8mp.c90
-rw-r--r--drivers/clk/imx/clk-imxrt1020.c65
-rw-r--r--drivers/clk/imx/clk-imxrt1050.c85
-rw-r--r--drivers/clk/microchip/mpfs_clk.c67
-rw-r--r--drivers/ddr/marvell/axp/ddr3_axp.h2
-rw-r--r--drivers/ddr/marvell/axp/ddr3_axp_config.h2
-rw-r--r--drivers/dma/bcm6348-iudma.c6
-rw-r--r--drivers/gpio/Kconfig4
-rw-r--r--drivers/gpio/sunxi_gpio.c130
-rw-r--r--drivers/i2c/sun6i_p2wi.c27
-rw-r--r--drivers/i2c/sun8i_rsb.c61
-rw-r--r--drivers/net/bcm6348-eth.c6
-rw-r--r--drivers/net/bcm6368-eth.c6
-rw-r--r--drivers/net/phy/Kconfig4
-rw-r--r--drivers/net/sun8i_emac.c90
-rw-r--r--drivers/net/sunxi_emac.c7
-rw-r--r--drivers/phy/bcm6318-usbh-phy.c4
-rw-r--r--drivers/phy/bcm6348-usbh-phy.c4
-rw-r--r--drivers/phy/bcm6368-usbh-phy.c8
-rw-r--r--drivers/pinctrl/Kconfig1
-rw-r--r--drivers/pinctrl/Makefile2
-rw-r--r--drivers/pinctrl/sunxi/Kconfig127
-rw-r--r--drivers/pinctrl/sunxi/Makefile3
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sunxi.c897
-rw-r--r--drivers/pwm/sunxi_pwm.c11
-rw-r--r--drivers/rtc/Kconfig8
-rw-r--r--drivers/rtc/mcfrtc.c4
-rw-r--r--drivers/serial/Kconfig39
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/serial-uclass.c26
-rw-r--r--drivers/serial/serial.c2
-rw-r--r--drivers/serial/serial_semihosting.c156
-rw-r--r--drivers/spi/bcm63xx_hsspi.c8
-rw-r--r--drivers/spi/bcm63xx_spi.c4
-rw-r--r--drivers/spi/designware_spi.c2
-rw-r--r--drivers/spi/spi-sunxi.c84
-rw-r--r--drivers/timer/Kconfig8
-rw-r--r--drivers/timer/Makefile1
-rw-r--r--drivers/timer/atmel_tcb_timer.c161
-rw-r--r--drivers/video/video-uclass.c3
48 files changed, 1609 insertions, 1030 deletions
diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
index 1fa42d728b5..270892517a9 100644
--- a/drivers/clk/at91/pmc.c
+++ b/drivers/clk/at91/pmc.c
@@ -7,6 +7,7 @@
#include <common.h>
#include <asm/io.h>
#include <clk-uclass.h>
+#include <linux/clk-provider.h>
#include "pmc.h"
static int at91_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args)
@@ -21,60 +22,12 @@ static int at91_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args)
return 0;
}
-static ulong at91_clk_get_rate(struct clk *clk)
-{
- struct clk *c;
- int ret;
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_get_rate(c);
-}
-
-static ulong at91_clk_set_rate(struct clk *clk, ulong rate)
-{
- struct clk *c;
- int ret;
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_set_rate(c, rate);
-}
-
-static int at91_clk_enable(struct clk *clk)
-{
- struct clk *c;
- int ret;
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_enable(c);
-}
-
-static int at91_clk_disable(struct clk *clk)
-{
- struct clk *c;
- int ret;
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_disable(c);
-}
-
const struct clk_ops at91_clk_ops = {
.of_xlate = at91_clk_of_xlate,
- .set_rate = at91_clk_set_rate,
- .get_rate = at91_clk_get_rate,
- .enable = at91_clk_enable,
- .disable = at91_clk_disable,
+ .set_rate = ccf_clk_set_rate,
+ .get_rate = ccf_clk_get_rate,
+ .enable = ccf_clk_enable,
+ .disable = ccf_clk_disable,
};
/**
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index c20c928bf1d..b89c77bf794 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -138,14 +138,7 @@ static int clk_get_by_indexed_prop(struct udevice *dev, const char *prop_name,
int clk_get_by_index(struct udevice *dev, int index, struct clk *clk)
{
- struct ofnode_phandle_args args;
- int ret;
-
- ret = dev_read_phandle_with_args(dev, "clocks", "#clock-cells", 0,
- index, &args);
-
- return clk_get_by_index_tail(ret, dev_ofnode(dev), &args, "clocks",
- index, clk);
+ return clk_get_by_index_nodev(dev_ofnode(dev), index, clk);
}
int clk_get_by_index_nodev(ofnode node, int index, struct clk *clk)
@@ -400,18 +393,7 @@ int clk_set_defaults(struct udevice *dev, enum clk_defaults_stage stage)
int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk)
{
- int index;
-
- debug("%s(dev=%p, name=%s, clk=%p)\n", __func__, dev, name, clk);
- clk->dev = NULL;
-
- index = dev_read_stringlist_search(dev, "clock-names", name);
- if (index < 0) {
- debug("fdt_stringlist_search() failed: %d\n", index);
- return index;
- }
-
- return clk_get_by_index(dev, index, clk);
+ return clk_get_by_name_nodev(dev_ofnode(dev), name, clk);
}
#endif /* OF_REAL */
@@ -447,9 +429,7 @@ int clk_release_all(struct clk *clk, int count)
if (ret && ret != -ENOSYS)
return ret;
- ret = clk_free(&clk[i]);
- if (ret && ret != -ENOSYS)
- return ret;
+ clk_free(&clk[i]);
}
return 0;
@@ -472,19 +452,18 @@ int clk_request(struct udevice *dev, struct clk *clk)
return ops->request(clk);
}
-int clk_free(struct clk *clk)
+void clk_free(struct clk *clk)
{
const struct clk_ops *ops;
debug("%s(clk=%p)\n", __func__, clk);
if (!clk_valid(clk))
- return 0;
+ return;
ops = clk_dev_ops(clk->dev);
- if (!ops->rfree)
- return 0;
-
- return ops->rfree(clk);
+ if (ops->rfree)
+ ops->rfree(clk);
+ return;
}
ulong clk_get_rate(struct clk *clk)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index eff0fa134f7..a5a3461b66c 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -74,3 +74,68 @@ bool clk_dev_binded(struct clk *clk)
return false;
}
+
+/* Helper functions for clock ops */
+
+ulong ccf_clk_get_rate(struct clk *clk)
+{
+ struct clk *c;
+ int err = clk_get_by_id(clk->id, &c);
+
+ if (err)
+ return err;
+ return clk_get_rate(c);
+}
+
+ulong ccf_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ struct clk *c;
+ int err = clk_get_by_id(clk->id, &c);
+
+ if (err)
+ return err;
+ return clk_set_rate(c, rate);
+}
+
+int ccf_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ struct clk *c, *p;
+ int err = clk_get_by_id(clk->id, &c);
+
+ if (err)
+ return err;
+
+ err = clk_get_by_id(parent->id, &p);
+ if (err)
+ return err;
+
+ return clk_set_parent(c, p);
+}
+
+static int ccf_clk_endisable(struct clk *clk, bool enable)
+{
+ struct clk *c;
+ int err = clk_get_by_id(clk->id, &c);
+
+ if (err)
+ return err;
+ return enable ? clk_enable(c) : clk_disable(c);
+}
+
+int ccf_clk_enable(struct clk *clk)
+{
+ return ccf_clk_endisable(clk, true);
+}
+
+int ccf_clk_disable(struct clk *clk)
+{
+ return ccf_clk_endisable(clk, false);
+}
+
+const struct clk_ops ccf_clk_ops = {
+ .set_rate = ccf_clk_set_rate,
+ .get_rate = ccf_clk_get_rate,
+ .set_parent = ccf_clk_set_parent,
+ .enable = ccf_clk_enable,
+ .disable = ccf_clk_disable,
+};
diff --git a/drivers/clk/clk_sandbox.c b/drivers/clk/clk_sandbox.c
index 57acf7d8553..636914db8ca 100644
--- a/drivers/clk/clk_sandbox.c
+++ b/drivers/clk/clk_sandbox.c
@@ -101,15 +101,15 @@ static int sandbox_clk_request(struct clk *clk)
return 0;
}
-static int sandbox_clk_free(struct clk *clk)
+static void sandbox_clk_free(struct clk *clk)
{
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
if (clk->id >= SANDBOX_CLK_ID_COUNT)
- return -EINVAL;
+ return;
priv->requested[clk->id] = false;
- return 0;
+ return;
}
static struct clk_ops sandbox_clk_ops = {
diff --git a/drivers/clk/clk_sandbox_test.c b/drivers/clk/clk_sandbox_test.c
index f665fd3cc45..5807a454f3b 100644
--- a/drivers/clk/clk_sandbox_test.c
+++ b/drivers/clk/clk_sandbox_test.c
@@ -137,14 +137,11 @@ int sandbox_clk_test_disable_bulk(struct udevice *dev)
int sandbox_clk_test_free(struct udevice *dev)
{
struct sandbox_clk_test *sbct = dev_get_priv(dev);
- int i, ret;
+ int i;
devm_clk_put(dev, sbct->clkps[SANDBOX_CLK_TEST_ID_DEVM1]);
- for (i = 0; i < SANDBOX_CLK_TEST_NON_DEVM_COUNT; i++) {
- ret = clk_free(&sbct->clks[i]);
- if (ret)
- return ret;
- }
+ for (i = 0; i < SANDBOX_CLK_TEST_NON_DEVM_COUNT; i++)
+ clk_free(&sbct->clks[i]);
return 0;
}
diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c
index 5343036babd..67825af89b8 100644
--- a/drivers/clk/imx/clk-imx6q.c
+++ b/drivers/clk/imx/clk-imx6q.c
@@ -14,79 +14,22 @@
#include "clk.h"
-static int imx6q_check_id(ulong id)
+static int imx6q_clk_request(struct clk *clk)
{
- if (id < IMX6QDL_CLK_DUMMY || id >= IMX6QDL_CLK_END) {
- printf("%s: Invalid clk ID #%lu\n", __func__, id);
+ if (clk->id < IMX6QDL_CLK_DUMMY || clk->id >= IMX6QDL_CLK_END) {
+ printf("%s: Invalid clk ID #%lu\n", __func__, clk->id);
return -EINVAL;
}
return 0;
}
-static ulong imx6q_clk_get_rate(struct clk *clk)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu)\n", __func__, clk->id);
-
- ret = imx6q_check_id(clk->id);
- if (ret)
- return ret;
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_get_rate(c);
-}
-
-static ulong imx6q_clk_set_rate(struct clk *clk, unsigned long rate)
-{
- debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
-
- return rate;
-}
-
-static int __imx6q_clk_enable(struct clk *clk, bool enable)
-{
- struct clk *c;
- int ret = 0;
-
- debug("%s(#%lu) en: %d\n", __func__, clk->id, enable);
-
- ret = imx6q_check_id(clk->id);
- if (ret)
- return ret;
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- if (enable)
- ret = clk_enable(c);
- else
- ret = clk_disable(c);
-
- return ret;
-}
-
-static int imx6q_clk_disable(struct clk *clk)
-{
- return __imx6q_clk_enable(clk, 0);
-}
-
-static int imx6q_clk_enable(struct clk *clk)
-{
- return __imx6q_clk_enable(clk, 1);
-}
-
static struct clk_ops imx6q_clk_ops = {
- .set_rate = imx6q_clk_set_rate,
- .get_rate = imx6q_clk_get_rate,
- .enable = imx6q_clk_enable,
- .disable = imx6q_clk_disable,
+ .request = imx6q_clk_request,
+ .set_rate = ccf_clk_set_rate,
+ .get_rate = ccf_clk_get_rate,
+ .enable = ccf_clk_enable,
+ .disable = ccf_clk_disable,
};
static const char *const usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c
index 3aa8c641f9a..443bbdae332 100644
--- a/drivers/clk/imx/clk-imx8mm.c
+++ b/drivers/clk/imx/clk-imx8mm.c
@@ -140,92 +140,6 @@ static const char *imx8mm_ecspi2_sels[] = {"clock-osc-24m", "sys_pll2_200m", "sy
static const char *imx8mm_ecspi3_sels[] = {"clock-osc-24m", "sys_pll2_200m", "sys_pll1_40m", "sys_pll1_160m",
"sys_pll1_800m", "sys_pll3_out", "sys_pll2_250m", "audio_pll2_out", };
-static ulong imx8mm_clk_get_rate(struct clk *clk)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu)\n", __func__, clk->id);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_get_rate(c);
-}
-
-static ulong imx8mm_clk_set_rate(struct clk *clk, unsigned long rate)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_set_rate(c, rate);
-}
-
-static int __imx8mm_clk_enable(struct clk *clk, bool enable)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu) en: %d\n", __func__, clk->id, enable);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- if (enable)
- ret = clk_enable(c);
- else
- ret = clk_disable(c);
-
- return ret;
-}
-
-static int imx8mm_clk_disable(struct clk *clk)
-{
- return __imx8mm_clk_enable(clk, 0);
-}
-
-static int imx8mm_clk_enable(struct clk *clk)
-{
- return __imx8mm_clk_enable(clk, 1);
-}
-
-static int imx8mm_clk_set_parent(struct clk *clk, struct clk *parent)
-{
- struct clk *c, *cp;
- int ret;
-
- debug("%s(#%lu), parent: %lu\n", __func__, clk->id, parent->id);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- ret = clk_get_by_id(parent->id, &cp);
- if (ret)
- return ret;
-
- ret = clk_set_parent(c, cp);
- c->dev->parent = cp->dev;
-
- return ret;
-}
-
-static struct clk_ops imx8mm_clk_ops = {
- .set_rate = imx8mm_clk_set_rate,
- .get_rate = imx8mm_clk_get_rate,
- .enable = imx8mm_clk_enable,
- .disable = imx8mm_clk_disable,
- .set_parent = imx8mm_clk_set_parent,
-};
-
static int imx8mm_clk_probe(struct udevice *dev)
{
void __iomem *base;
@@ -470,7 +384,7 @@ U_BOOT_DRIVER(imx8mm_clk) = {
.name = "clk_imx8mm",
.id = UCLASS_CLK,
.of_match = imx8mm_clk_ids,
- .ops = &imx8mm_clk_ops,
+ .ops = &ccf_clk_ops,
.probe = imx8mm_clk_probe,
.flags = DM_FLAG_PRE_RELOC,
};
diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c
index e398d7de02a..bb62138f8ca 100644
--- a/drivers/clk/imx/clk-imx8mn.c
+++ b/drivers/clk/imx/clk-imx8mn.c
@@ -148,92 +148,6 @@ static const char * const imx8mn_usb_phy_sels[] = {"clock-osc-24m", "sys_pll1_10
"sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
"clk_ext3", "audio_pll2_out", };
-static ulong imx8mn_clk_get_rate(struct clk *clk)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu)\n", __func__, clk->id);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_get_rate(c);
-}
-
-static ulong imx8mn_clk_set_rate(struct clk *clk, unsigned long rate)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_set_rate(c, rate);
-}
-
-static int __imx8mn_clk_enable(struct clk *clk, bool enable)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu) en: %d\n", __func__, clk->id, enable);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- if (enable)
- ret = clk_enable(c);
- else
- ret = clk_disable(c);
-
- return ret;
-}
-
-static int imx8mn_clk_disable(struct clk *clk)
-{
- return __imx8mn_clk_enable(clk, 0);
-}
-
-static int imx8mn_clk_enable(struct clk *clk)
-{
- return __imx8mn_clk_enable(clk, 1);
-}
-
-static int imx8mn_clk_set_parent(struct clk *clk, struct clk *parent)
-{
- struct clk *c, *cp;
- int ret;
-
- debug("%s(#%lu), parent: %lu\n", __func__, clk->id, parent->id);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- ret = clk_get_by_id(parent->id, &cp);
- if (ret)
- return ret;
-
- ret = clk_set_parent(c, cp);
- c->dev->parent = cp->dev;
-
- return ret;
-}
-
-static struct clk_ops imx8mn_clk_ops = {
- .set_rate = imx8mn_clk_set_rate,
- .get_rate = imx8mn_clk_get_rate,
- .enable = imx8mn_clk_enable,
- .disable = imx8mn_clk_disable,
- .set_parent = imx8mn_clk_set_parent,
-};
-
static int imx8mn_clk_probe(struct udevice *dev)
{
void __iomem *base;
@@ -481,7 +395,7 @@ U_BOOT_DRIVER(imx8mn_clk) = {
.name = "clk_imx8mn",
.id = UCLASS_CLK,
.of_match = imx8mn_clk_ids,
- .ops = &imx8mn_clk_ops,
+ .ops = &ccf_clk_ops,
.probe = imx8mn_clk_probe,
.flags = DM_FLAG_PRE_RELOC,
};
diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c
index c77500bcce0..ad84ce38ede 100644
--- a/drivers/clk/imx/clk-imx8mp.c
+++ b/drivers/clk/imx/clk-imx8mp.c
@@ -186,94 +186,6 @@ static const char *imx8mp_enet_phy_ref_sels[] = {"clock-osc-24m", "sys_pll2_50m"
static const char *imx8mp_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", };
-
-static ulong imx8mp_clk_get_rate(struct clk *clk)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu)\n", __func__, clk->id);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_get_rate(c);
-}
-
-static ulong imx8mp_clk_set_rate(struct clk *clk, unsigned long rate)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_set_rate(c, rate);
-}
-
-static int __imx8mp_clk_enable(struct clk *clk, bool enable)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu) en: %d\n", __func__, clk->id, enable);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- if (enable)
- ret = clk_enable(c);
- else
- ret = clk_disable(c);
-
- return ret;
-}
-
-static int imx8mp_clk_disable(struct clk *clk)
-{
- return __imx8mp_clk_enable(clk, 0);
-}
-
-static int imx8mp_clk_enable(struct clk *clk)
-{
- return __imx8mp_clk_enable(clk, 1);
-}
-
-static int imx8mp_clk_set_parent(struct clk *clk, struct clk *parent)
-{
- struct clk *c, *cp;
- int ret;
-
- debug("%s(#%lu), parent: %lu\n", __func__, clk->id, parent->id);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- ret = clk_get_by_id(parent->id, &cp);
- if (ret)
- return ret;
-
- ret = clk_set_parent(c, cp);
-
- c->dev->parent = cp->dev;
-
- return ret;
-}
-
-static struct clk_ops imx8mp_clk_ops = {
- .set_rate = imx8mp_clk_set_rate,
- .get_rate = imx8mp_clk_get_rate,
- .enable = imx8mp_clk_enable,
- .disable = imx8mp_clk_disable,
- .set_parent = imx8mp_clk_set_parent,
-};
-
static int imx8mp_clk_probe(struct udevice *dev)
{
void __iomem *base;
@@ -409,7 +321,7 @@ U_BOOT_DRIVER(imx8mp_clk) = {
.name = "clk_imx8mp",
.id = UCLASS_CLK,
.of_match = imx8mp_clk_ids,
- .ops = &imx8mp_clk_ops,
+ .ops = &ccf_clk_ops,
.probe = imx8mp_clk_probe,
.flags = DM_FLAG_PRE_RELOC,
};
diff --git a/drivers/clk/imx/clk-imxrt1020.c b/drivers/clk/imx/clk-imxrt1020.c
index 840f783940f..3f8b4df3c5a 100644
--- a/drivers/clk/imx/clk-imxrt1020.c
+++ b/drivers/clk/imx/clk-imxrt1020.c
@@ -14,68 +14,11 @@
#include "clk.h"
-static ulong imxrt1020_clk_get_rate(struct clk *clk)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu)\n", __func__, clk->id);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_get_rate(c);
-}
-
-static ulong imxrt1020_clk_set_rate(struct clk *clk, unsigned long rate)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_set_rate(c, rate);
-}
-
-static int __imxrt1020_clk_enable(struct clk *clk, bool enable)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu) en: %d\n", __func__, clk->id, enable);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- if (enable)
- ret = clk_enable(c);
- else
- ret = clk_disable(c);
-
- return ret;
-}
-
-static int imxrt1020_clk_disable(struct clk *clk)
-{
- return __imxrt1020_clk_enable(clk, 0);
-}
-
-static int imxrt1020_clk_enable(struct clk *clk)
-{
- return __imxrt1020_clk_enable(clk, 1);
-}
-
static struct clk_ops imxrt1020_clk_ops = {
- .set_rate = imxrt1020_clk_set_rate,
- .get_rate = imxrt1020_clk_get_rate,
- .enable = imxrt1020_clk_enable,
- .disable = imxrt1020_clk_disable,
+ .set_rate = ccf_clk_set_rate,
+ .get_rate = ccf_clk_get_rate,
+ .enable = ccf_clk_enable,
+ .disable = ccf_clk_disable,
};
static const char * const pll2_bypass_sels[] = {"pll2_sys", "osc", };
diff --git a/drivers/clk/imx/clk-imxrt1050.c b/drivers/clk/imx/clk-imxrt1050.c
index 3e171610024..5cb5e3bc15a 100644
--- a/drivers/clk/imx/clk-imxrt1050.c
+++ b/drivers/clk/imx/clk-imxrt1050.c
@@ -15,89 +15,6 @@
#include "clk.h"
-static ulong imxrt1050_clk_get_rate(struct clk *clk)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu)\n", __func__, clk->id);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_get_rate(c);
-}
-
-static ulong imxrt1050_clk_set_rate(struct clk *clk, ulong rate)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_set_rate(c, rate);
-}
-
-static int __imxrt1050_clk_enable(struct clk *clk, bool enable)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu) en: %d\n", __func__, clk->id, enable);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- if (enable)
- ret = clk_enable(c);
- else
- ret = clk_disable(c);
-
- return ret;
-}
-
-static int imxrt1050_clk_disable(struct clk *clk)
-{
- return __imxrt1050_clk_enable(clk, 0);
-}
-
-static int imxrt1050_clk_enable(struct clk *clk)
-{
- return __imxrt1050_clk_enable(clk, 1);
-}
-
-static int imxrt1050_clk_set_parent(struct clk *clk, struct clk *parent)
-{
- struct clk *c, *cp;
- int ret;
-
- debug("%s(#%lu), parent: %lu\n", __func__, clk->id, parent->id);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- ret = clk_get_by_id(parent->id, &cp);
- if (ret)
- return ret;
-
- return clk_set_parent(c, cp);
-}
-
-static struct clk_ops imxrt1050_clk_ops = {
- .set_rate = imxrt1050_clk_set_rate,
- .get_rate = imxrt1050_clk_get_rate,
- .enable = imxrt1050_clk_enable,
- .disable = imxrt1050_clk_disable,
- .set_parent = imxrt1050_clk_set_parent,
-};
-
static const char * const pll_ref_sels[] = {"osc", "dummy", };
static const char * const pll1_bypass_sels[] = {"pll1_arm", "pll1_arm_ref_sel", };
static const char * const pll2_bypass_sels[] = {"pll2_sys", "pll2_sys_ref_sel", };
@@ -317,7 +234,7 @@ U_BOOT_DRIVER(imxrt1050_clk) = {
.name = "clk_imxrt1050",
.id = UCLASS_CLK,
.of_match = imxrt1050_clk_ids,
- .ops = &imxrt1050_clk_ops,
+ .ops = &ccf_clk_ops,
.probe = imxrt1050_clk_probe,
.flags = DM_FLAG_PRE_RELOC,
};
diff --git a/drivers/clk/microchip/mpfs_clk.c b/drivers/clk/microchip/mpfs_clk.c
index 05d7647206c..67828c9bf40 100644
--- a/drivers/clk/microchip/mpfs_clk.c
+++ b/drivers/clk/microchip/mpfs_clk.c
@@ -15,63 +15,6 @@
#include "mpfs_clk.h"
-/* All methods are delegated to CCF clocks */
-
-static ulong mpfs_clk_get_rate(struct clk *clk)
-{
- struct clk *c;
- int err = clk_get_by_id(clk->id, &c);
-
- if (err)
- return err;
- return clk_get_rate(c);
-}
-
-static ulong mpfs_clk_set_rate(struct clk *clk, unsigned long rate)
-{
- struct clk *c;
- int err = clk_get_by_id(clk->id, &c);
-
- if (err)
- return err;
- return clk_set_rate(c, rate);
-}
-
-static int mpfs_clk_set_parent(struct clk *clk, struct clk *parent)
-{
- struct clk *c, *p;
- int err = clk_get_by_id(clk->id, &c);
-
- if (err)
- return err;
-
- err = clk_get_by_id(parent->id, &p);
- if (err)
- return err;
-
- return clk_set_parent(c, p);
-}
-
-static int mpfs_clk_endisable(struct clk *clk, bool enable)
-{
- struct clk *c;
- int err = clk_get_by_id(clk->id, &c);
-
- if (err)
- return err;
- return enable ? clk_enable(c) : clk_disable(c);
-}
-
-static int mpfs_clk_enable(struct clk *clk)
-{
- return mpfs_clk_endisable(clk, true);
-}
-
-static int mpfs_clk_disable(struct clk *clk)
-{
- return mpfs_clk_endisable(clk, false);
-}
-
static int mpfs_clk_probe(struct udevice *dev)
{
int ret;
@@ -100,14 +43,6 @@ static int mpfs_clk_probe(struct udevice *dev)
return ret;
}
-static const struct clk_ops mpfs_clk_ops = {
- .set_rate = mpfs_clk_set_rate,
- .get_rate = mpfs_clk_get_rate,
- .set_parent = mpfs_clk_set_parent,
- .enable = mpfs_clk_enable,
- .disable = mpfs_clk_disable,
-};
-
static const struct udevice_id mpfs_of_match[] = {
{ .compatible = "microchip,mpfs-clkcfg" },
{ }
@@ -117,7 +52,7 @@ U_BOOT_DRIVER(mpfs_clk) = {
.name = "mpfs_clk",
.id = UCLASS_CLK,
.of_match = mpfs_of_match,
- .ops = &mpfs_clk_ops,
+ .ops = &ccf_clk_ops,
.probe = mpfs_clk_probe,
.priv_auto = sizeof(struct clk),
.flags = DM_FLAG_PRE_RELOC,
diff --git a/drivers/ddr/marvell/axp/ddr3_axp.h b/drivers/ddr/marvell/axp/ddr3_axp.h
index 970651f8702..a14c766dda7 100644
--- a/drivers/ddr/marvell/axp/ddr3_axp.h
+++ b/drivers/ddr/marvell/axp/ddr3_axp.h
@@ -37,7 +37,7 @@
#define ECC_SUPPORT
#endif
#define NEW_FABRIC_TWSI_ADDR 0x4E
-#ifdef CONFIG_DB_784MP_GP
+#ifdef CONFIG_TARGET_DB_MV784MP_GP
#define BUS_WIDTH_ECC_TWSI_ADDR 0x4E
#else
#define BUS_WIDTH_ECC_TWSI_ADDR 0x4F
diff --git a/drivers/ddr/marvell/axp/ddr3_axp_config.h b/drivers/ddr/marvell/axp/ddr3_axp_config.h
index 437a02efbac..ab09e72623a 100644
--- a/drivers/ddr/marvell/axp/ddr3_axp_config.h
+++ b/drivers/ddr/marvell/axp/ddr3_axp_config.h
@@ -138,7 +138,7 @@
* Enables I2C auto detection different options
*/
#if defined(CONFIG_DB_88F78X60) || defined(CONFIG_DB_88F78X60_REV2) || \
- defined(CONFIG_DB_784MP_GP)
+ defined(CONFIG_TARGET_DB_MV784MP_GP)
#define AUTO_DETECTION_SUPPORT
#endif
#endif
diff --git a/drivers/dma/bcm6348-iudma.c b/drivers/dma/bcm6348-iudma.c
index c04aa55cb42..4fc650272d9 100644
--- a/drivers/dma/bcm6348-iudma.c
+++ b/drivers/dma/bcm6348-iudma.c
@@ -596,11 +596,7 @@ static int bcm6348_iudma_probe(struct udevice *dev)
return ret;
}
- ret = clk_free(&clk);
- if (ret < 0) {
- pr_err("error freeing clock %d\n", i);
- return ret;
- }
+ clk_free(&clk);
}
/* try to perform resets */
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index c3f110933a0..a55e3686934 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -84,6 +84,10 @@ config ALTERA_PIO
Select this to enable PIO for Altera devices. Please find
details on the "Embedded Peripherals IP User Guide" of Altera.
+config BCM2835_GPIO
+ bool "BCM2835 GPIO driver"
+ depends on DM_GPIO
+
config BCM6345_GPIO
bool "BCM6345 GPIO driver"
depends on DM_GPIO && (ARCH_BMIPS || ARCH_BCM68360 || \
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
index 6c3c10862c4..1e85db179a6 100644
--- a/drivers/gpio/sunxi_gpio.c
+++ b/drivers/gpio/sunxi_gpio.c
@@ -16,15 +16,8 @@
#include <malloc.h>
#include <asm/io.h>
#include <asm/gpio.h>
-#include <dm/device-internal.h>
#include <dt-bindings/gpio/gpio.h>
-struct sunxi_gpio_plat {
- struct sunxi_gpio *regs;
- const char *bank_name; /* Name of bank, e.g. "B" */
- int gpio_count;
-};
-
#if !CONFIG_IS_ENABLED(DM_GPIO)
static int sunxi_gpio_output(u32 pin, u32 val)
{
@@ -211,28 +204,6 @@ static const struct dm_gpio_ops gpio_sunxi_ops = {
.set_flags = sunxi_gpio_set_flags,
};
-/**
- * Returns the name of a GPIO bank
- *
- * GPIO banks are named A, B, C, ...
- *
- * @bank: Bank number (0, 1..n-1)
- * Return: allocated string containing the name
- */
-static char *gpio_bank_name(int bank)
-{
- char *name;
-
- name = malloc(3);
- if (name) {
- name[0] = 'P';
- name[1] = 'A' + bank;
- name[2] = '\0';
- }
-
- return name;
-}
-
static int gpio_sunxi_probe(struct udevice *dev)
{
struct sunxi_gpio_plat *plat = dev_get_plat(dev);
@@ -240,114 +211,17 @@ static int gpio_sunxi_probe(struct udevice *dev)
/* Tell the uclass how many GPIOs we have */
if (plat) {
- uc_priv->gpio_count = plat->gpio_count;
+ uc_priv->gpio_count = SUNXI_GPIOS_PER_BANK;
uc_priv->bank_name = plat->bank_name;
}
return 0;
}
-struct sunxi_gpio_soc_data {
- int start;
- int no_banks;
-};
-
-/**
- * We have a top-level GPIO device with no actual GPIOs. It has a child
- * device for each Sunxi bank.
- */
-static int gpio_sunxi_bind(struct udevice *parent)
-{
- struct sunxi_gpio_soc_data *soc_data =
- (struct sunxi_gpio_soc_data *)dev_get_driver_data(parent);
- struct sunxi_gpio_plat *plat = dev_get_plat(parent);
- struct sunxi_gpio_reg *ctlr;
- int bank, ret;
-
- /* If this is a child device, there is nothing to do here */
- if (plat)
- return 0;
-
- ctlr = dev_read_addr_ptr(parent);
- for (bank = 0; bank < soc_data->no_banks; bank++) {
- struct sunxi_gpio_plat *plat;
- struct udevice *dev;
-
- plat = calloc(1, sizeof(*plat));
- if (!plat)
- return -ENOMEM;
- plat->regs = &ctlr->gpio_bank[bank];
- plat->bank_name = gpio_bank_name(soc_data->start + bank);
- plat->gpio_count = SUNXI_GPIOS_PER_BANK;
-
- ret = device_bind(parent, parent->driver, plat->bank_name, plat,
- dev_ofnode(parent), &dev);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-static const struct sunxi_gpio_soc_data soc_data_a_all = {
- .start = 0,
- .no_banks = SUNXI_GPIO_BANKS,
-};
-
-static const struct sunxi_gpio_soc_data soc_data_l_1 = {
- .start = 'L' - 'A',
- .no_banks = 1,
-};
-
-static const struct sunxi_gpio_soc_data soc_data_l_2 = {
- .start = 'L' - 'A',
- .no_banks = 2,
-};
-
-static const struct sunxi_gpio_soc_data soc_data_l_3 = {
- .start = 'L' - 'A',
- .no_banks = 3,
-};
-
-#define ID(_compat_, _soc_data_) \
- { .compatible = _compat_, .data = (ulong)&soc_data_##_soc_data_ }
-
-static const struct udevice_id sunxi_gpio_ids[] = {
- ID("allwinner,sun4i-a10-pinctrl", a_all),
- ID("allwinner,sun5i-a10s-pinctrl", a_all),
- ID("allwinner,sun5i-a13-pinctrl", a_all),
- ID("allwinner,sun50i-h5-pinctrl", a_all),
- ID("allwinner,sun6i-a31-pinctrl", a_all),
- ID("allwinner,sun6i-a31s-pinctrl", a_all),
- ID("allwinner,sun7i-a20-pinctrl", a_all),
- ID("allwinner,sun8i-a23-pinctrl", a_all),
- ID("allwinner,sun8i-a33-pinctrl", a_all),
- ID("allwinner,sun8i-a83t-pinctrl", a_all),
- ID("allwinner,sun8i-h3-pinctrl", a_all),
- ID("allwinner,sun8i-r40-pinctrl", a_all),
- ID("allwinner,sun8i-v3-pinctrl", a_all),
- ID("allwinner,sun8i-v3s-pinctrl", a_all),
- ID("allwinner,sun9i-a80-pinctrl", a_all),
- ID("allwinner,sun50i-a64-pinctrl", a_all),
- ID("allwinner,sun50i-h6-pinctrl", a_all),
- ID("allwinner,sun50i-h616-pinctrl", a_all),
- ID("allwinner,sun6i-a31-r-pinctrl", l_2),
- ID("allwinner,sun8i-a23-r-pinctrl", l_1),
- ID("allwinner,sun8i-a83t-r-pinctrl", l_1),
- ID("allwinner,sun8i-h3-r-pinctrl", l_1),
- ID("allwinner,sun9i-a80-r-pinctrl", l_3),
- ID("allwinner,sun50i-a64-r-pinctrl", l_1),
- ID("allwinner,sun50i-h6-r-pinctrl", l_2),
- ID("allwinner,sun50i-h616-r-pinctrl", l_1),
- { }
-};
-
U_BOOT_DRIVER(gpio_sunxi) = {
.name = "gpio_sunxi",
.id = UCLASS_GPIO,
- .ops = &gpio_sunxi_ops,
- .of_match = sunxi_gpio_ids,
- .bind = gpio_sunxi_bind,
.probe = gpio_sunxi_probe,
+ .ops = &gpio_sunxi_ops,
};
#endif /* DM_GPIO */
diff --git a/drivers/i2c/sun6i_p2wi.c b/drivers/i2c/sun6i_p2wi.c
index c9e1b3fcd5f..d221323295d 100644
--- a/drivers/i2c/sun6i_p2wi.c
+++ b/drivers/i2c/sun6i_p2wi.c
@@ -14,10 +14,12 @@
*/
#include <axp_pmic.h>
+#include <clk.h>
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <i2c.h>
+#include <reset.h>
#include <time.h>
#include <asm/io.h>
#include <asm/arch/cpu.h>
@@ -102,12 +104,6 @@ static int sun6i_p2wi_change_to_p2wi_mode(struct sunxi_p2wi_reg *base,
static void sun6i_p2wi_init(struct sunxi_p2wi_reg *base)
{
- /* Enable p2wi and PIO clk, and de-assert their resets */
- prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_P2WI);
-
- sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN6I_GPL0_R_P2WI_SCK);
- sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN6I_GPL1_R_P2WI_SDA);
-
/* Reset p2wi controller and set clock to CLKIN(12)/8 = 1.5 MHz */
writel(P2WI_CTRL_RESET, &base->ctrl);
sdelay(0x100);
@@ -142,6 +138,12 @@ void p2wi_init(void)
{
struct sunxi_p2wi_reg *base = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE;
+ /* Enable p2wi and PIO clk, and de-assert their resets */
+ prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_P2WI);
+
+ sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN6I_GPL0_R_P2WI_SCK);
+ sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN6I_GPL1_R_P2WI_SDA);
+
sun6i_p2wi_init(base);
}
#endif
@@ -180,9 +182,19 @@ static int sun6i_p2wi_probe_chip(struct udevice *bus, uint chip_addr,
static int sun6i_p2wi_probe(struct udevice *bus)
{
struct sun6i_p2wi_priv *priv = dev_get_priv(bus);
+ struct reset_ctl *reset;
+ struct clk *clk;
priv->base = dev_read_addr_ptr(bus);
+ reset = devm_reset_control_get(bus, NULL);
+ if (!IS_ERR(reset))
+ reset_deassert(reset);
+
+ clk = devm_clk_get(bus, NULL);
+ if (!IS_ERR(clk))
+ clk_enable(clk);
+
sun6i_p2wi_init(priv->base);
return 0;
@@ -191,11 +203,12 @@ static int sun6i_p2wi_probe(struct udevice *bus)
static int sun6i_p2wi_child_pre_probe(struct udevice *child)
{
struct dm_i2c_chip *chip = dev_get_parent_plat(child);
+ struct udevice *bus = child->parent;
/* Ensure each transfer is for a single register. */
chip->flags |= DM_I2C_CHIP_RD_ADDRESS | DM_I2C_CHIP_WR_ADDRESS;
- return 0;
+ return sun6i_p2wi_probe_chip(bus, chip->chip_addr, 0);
}
static const struct dm_i2c_ops sun6i_p2wi_ops = {
diff --git a/drivers/i2c/sun8i_rsb.c b/drivers/i2c/sun8i_rsb.c
index 716b245a003..47fa05b6d1c 100644
--- a/drivers/i2c/sun8i_rsb.c
+++ b/drivers/i2c/sun8i_rsb.c
@@ -9,10 +9,12 @@
*/
#include <axp_pmic.h>
+#include <clk.h>
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <i2c.h>
+#include <reset.h>
#include <time.h>
#include <asm/arch/cpu.h>
#include <asm/arch/gpio.h>
@@ -95,27 +97,6 @@ static int sun8i_rsb_set_device_address(struct sunxi_rsb_reg *base,
return sun8i_rsb_do_trans(base);
}
-static void sun8i_rsb_cfg_io(void)
-{
-#ifdef CONFIG_MACH_SUN8I
- sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_GPL_R_RSB);
- sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN8I_GPL_R_RSB);
- sunxi_gpio_set_pull(SUNXI_GPL(0), 1);
- sunxi_gpio_set_pull(SUNXI_GPL(1), 1);
- sunxi_gpio_set_drv(SUNXI_GPL(0), 2);
- sunxi_gpio_set_drv(SUNXI_GPL(1), 2);
-#elif defined CONFIG_MACH_SUN9I
- sunxi_gpio_set_cfgpin(SUNXI_GPN(0), SUN9I_GPN_R_RSB);
- sunxi_gpio_set_cfgpin(SUNXI_GPN(1), SUN9I_GPN_R_RSB);
- sunxi_gpio_set_pull(SUNXI_GPN(0), 1);
- sunxi_gpio_set_pull(SUNXI_GPN(1), 1);
- sunxi_gpio_set_drv(SUNXI_GPN(0), 2);
- sunxi_gpio_set_drv(SUNXI_GPN(1), 2);
-#else
-#error unsupported MACH_SUNXI
-#endif
-}
-
static void sun8i_rsb_set_clk(struct sunxi_rsb_reg *base)
{
u32 div = 0;
@@ -147,12 +128,6 @@ static int sun8i_rsb_set_device_mode(struct sunxi_rsb_reg *base)
static int sun8i_rsb_init(struct sunxi_rsb_reg *base)
{
- /* Enable RSB and PIO clk, and de-assert their resets */
- prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_RSB);
-
- /* Setup external pins */
- sun8i_rsb_cfg_io();
-
writel(RSB_CTRL_SOFT_RST, &base->ctrl);
sun8i_rsb_set_clk(base);
@@ -185,6 +160,25 @@ int rsb_init(void)
{
struct sunxi_rsb_reg *base = (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
+ /* Enable RSB and PIO clk, and de-assert their resets */
+ prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_RSB);
+
+ if (IS_ENABLED(CONFIG_MACH_SUN9I)) {
+ sunxi_gpio_set_cfgpin(SUNXI_GPN(0), SUN9I_GPN_R_RSB);
+ sunxi_gpio_set_cfgpin(SUNXI_GPN(1), SUN9I_GPN_R_RSB);
+ sunxi_gpio_set_pull(SUNXI_GPN(0), 1);
+ sunxi_gpio_set_pull(SUNXI_GPN(1), 1);
+ sunxi_gpio_set_drv(SUNXI_GPN(0), 2);
+ sunxi_gpio_set_drv(SUNXI_GPN(1), 2);
+ } else {
+ sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_GPL_R_RSB);
+ sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN8I_GPL_R_RSB);
+ sunxi_gpio_set_pull(SUNXI_GPL(0), 1);
+ sunxi_gpio_set_pull(SUNXI_GPL(1), 1);
+ sunxi_gpio_set_drv(SUNXI_GPL(0), 2);
+ sunxi_gpio_set_drv(SUNXI_GPL(1), 2);
+ }
+
return sun8i_rsb_init(base);
}
#endif
@@ -243,20 +237,31 @@ static int sun8i_rsb_probe_chip(struct udevice *bus, uint chip_addr,
static int sun8i_rsb_probe(struct udevice *bus)
{
struct sun8i_rsb_priv *priv = dev_get_priv(bus);
+ struct reset_ctl *reset;
+ struct clk *clk;
priv->base = dev_read_addr_ptr(bus);
+ reset = devm_reset_control_get(bus, NULL);
+ if (!IS_ERR(reset))
+ reset_deassert(reset);
+
+ clk = devm_clk_get(bus, NULL);
+ if (!IS_ERR(clk))
+ clk_enable(clk);
+
return sun8i_rsb_init(priv->base);
}
static int sun8i_rsb_child_pre_probe(struct udevice *child)
{
struct dm_i2c_chip *chip = dev_get_parent_plat(child);
+ struct udevice *bus = child->parent;
/* Ensure each transfer is for a single register. */
chip->flags |= DM_I2C_CHIP_RD_ADDRESS | DM_I2C_CHIP_WR_ADDRESS;
- return 0;
+ return sun8i_rsb_probe_chip(bus, chip->chip_addr, 0);
}
static const struct dm_i2c_ops sun8i_rsb_ops = {
diff --git a/drivers/net/bcm6348-eth.c b/drivers/net/bcm6348-eth.c
index aad7b612134..06e0dd74a5b 100644
--- a/drivers/net/bcm6348-eth.c
+++ b/drivers/net/bcm6348-eth.c
@@ -461,11 +461,7 @@ static int bcm6348_eth_probe(struct udevice *dev)
return ret;
}
- ret = clk_free(&clk);
- if (ret < 0) {
- pr_err("%s: error freeing clock %d\n", __func__, i);
- return ret;
- }
+ clk_free(&clk);
}
/* try to perform resets */
diff --git a/drivers/net/bcm6368-eth.c b/drivers/net/bcm6368-eth.c
index 29abe7fc969..c2a8b9f0576 100644
--- a/drivers/net/bcm6368-eth.c
+++ b/drivers/net/bcm6368-eth.c
@@ -546,11 +546,7 @@ static int bcm6368_eth_probe(struct udevice *dev)
return ret;
}
- ret = clk_free(&clk);
- if (ret < 0) {
- pr_err("%s: error freeing clock %d\n", __func__, i);
- return ret;
- }
+ clk_free(&clk);
}
/* try to perform resets */
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index eed6eb18669..014a4de223e 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -2,6 +2,10 @@
config BITBANGMII
bool "Bit-banged ethernet MII management channel support"
+config BITBANGMII_MULTI
+ bool "Enable the multi bus support"
+ depends on BITBANGMII
+
config MV88E6352_SWITCH
bool "Marvell 88E6352 switch support"
diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
index 2e24d122141..b23faa228e0 100644
--- a/drivers/net/sun8i_emac.c
+++ b/drivers/net/sun8i_emac.c
@@ -29,7 +29,6 @@
#include <miiphy.h>
#include <net.h>
#include <reset.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
#include <wait_bit.h>
#define MDIO_CMD_MII_BUSY BIT(0)
@@ -81,13 +80,6 @@
#define AHB_GATE_OFFSET_EPHY 0
-/* IO mux settings */
-#define SUN8I_IOMUX_H3 2
-#define SUN8I_IOMUX_R40 5
-#define SUN8I_IOMUX_H6 5
-#define SUN8I_IOMUX_H616 2
-#define SUN8I_IOMUX 4
-
/* H3/A64 EMAC Register's offset */
#define EMAC_CTL0 0x00
#define EMAC_CTL0_FULL_DUPLEX BIT(0)
@@ -519,85 +511,6 @@ static int sun8i_emac_eth_start(struct udevice *dev)
return 0;
}
-static int parse_phy_pins(struct udevice *dev)
-{
- int offset;
- const char *pin_name;
- int drive, pull = SUN4I_PINCTRL_NO_PULL, i;
- u32 iomux;
-
- offset = fdtdec_lookup_phandle(gd->fdt_blob, dev_of_offset(dev),
- "pinctrl-0");
- if (offset < 0) {
- printf("WARNING: emac: cannot find pinctrl-0 node\n");
- return offset;
- }
-
- drive = fdt_getprop_u32_default_node(gd->fdt_blob, offset, 0,
- "drive-strength", ~0);
- if (drive != ~0) {
- if (drive <= 10)
- drive = SUN4I_PINCTRL_10_MA;
- else if (drive <= 20)
- drive = SUN4I_PINCTRL_20_MA;
- else if (drive <= 30)
- drive = SUN4I_PINCTRL_30_MA;
- else
- drive = SUN4I_PINCTRL_40_MA;
- }
-
- if (fdt_get_property(gd->fdt_blob, offset, "bias-pull-up", NULL))
- pull = SUN4I_PINCTRL_PULL_UP;
- else if (fdt_get_property(gd->fdt_blob, offset, "bias-pull-down", NULL))
- pull = SUN4I_PINCTRL_PULL_DOWN;
-
- /*
- * The GPIO pinmux value is an integration choice, so depends on the
- * SoC, not the EMAC variant.
- */
- if (IS_ENABLED(CONFIG_MACH_SUNXI_H3_H5))
- iomux = SUN8I_IOMUX_H3;
- else if (IS_ENABLED(CONFIG_MACH_SUN8I_R40))
- iomux = SUN8I_IOMUX_R40;
- else if (IS_ENABLED(CONFIG_MACH_SUN50I_H6))
- iomux = SUN8I_IOMUX_H6;
- else if (IS_ENABLED(CONFIG_MACH_SUN50I_H616))
- iomux = SUN8I_IOMUX_H616;
- else if (IS_ENABLED(CONFIG_MACH_SUN8I_A83T))
- iomux = SUN8I_IOMUX;
- else if (IS_ENABLED(CONFIG_MACH_SUN50I))
- iomux = SUN8I_IOMUX;
- else
- BUILD_BUG_ON_MSG(1, "missing pinmux value for Ethernet pins");
-
- for (i = 0; ; i++) {
- int pin;
-
- pin_name = fdt_stringlist_get(gd->fdt_blob, offset,
- "pins", i, NULL);
- if (!pin_name)
- break;
-
- pin = sunxi_name_to_gpio(pin_name);
- if (pin < 0)
- continue;
-
- sunxi_gpio_set_cfgpin(pin, iomux);
-
- if (drive != ~0)
- sunxi_gpio_set_drv(pin, drive);
- if (pull != ~0)
- sunxi_gpio_set_pull(pin, pull);
- }
-
- if (!i) {
- printf("WARNING: emac: cannot find pins property\n");
- return -2;
- }
-
- return 0;
-}
-
static int sun8i_emac_eth_recv(struct udevice *dev, int flags, uchar **packetp)
{
struct emac_eth_dev *priv = dev_get_priv(dev);
@@ -965,9 +878,6 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
priv->interface = pdata->phy_interface;
- if (!priv->use_internal_phy)
- parse_phy_pins(dev);
-
sun8i_pdata->tx_delay_ps = fdtdec_get_int(gd->fdt_blob, node,
"allwinner,tx-delay-ps", 0);
if (sun8i_pdata->tx_delay_ps < 0 || sun8i_pdata->tx_delay_ps > 700)
diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c
index 17ad88e732e..d15b0add7c9 100644
--- a/drivers/net/sunxi_emac.c
+++ b/drivers/net/sunxi_emac.c
@@ -17,7 +17,6 @@
#include <net.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
-#include <asm/arch/gpio.h>
/* EMAC register */
struct emac_regs {
@@ -511,15 +510,11 @@ static int sunxi_emac_board_setup(struct udevice *dev,
struct sunxi_sramc_regs *sram =
(struct sunxi_sramc_regs *)SUNXI_SRAMC_BASE;
struct emac_regs *regs = priv->regs;
- int pin, ret;
+ int ret;
/* Map SRAM to EMAC */
setbits_le32(&sram->ctrl1, 0x5 << 2);
- /* Configure pin mux settings for MII Ethernet */
- for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(17); pin++)
- sunxi_gpio_set_cfgpin(pin, SUNXI_GPA_EMAC);
-
/* Set up clock gating */
ret = clk_enable(&priv->clk);
if (ret) {
diff --git a/drivers/phy/bcm6318-usbh-phy.c b/drivers/phy/bcm6318-usbh-phy.c
index 60608a55bc2..1c10853940a 100644
--- a/drivers/phy/bcm6318-usbh-phy.c
+++ b/drivers/phy/bcm6318-usbh-phy.c
@@ -98,9 +98,7 @@ static int bcm6318_usbh_probe(struct udevice *dev)
if (ret < 0)
return ret;
- ret = clk_free(&clk);
- if (ret < 0)
- return ret;
+ clk_free(&clk);
/* enable power domain */
ret = power_domain_get(dev, &pwr_dom);
diff --git a/drivers/phy/bcm6348-usbh-phy.c b/drivers/phy/bcm6348-usbh-phy.c
index 1b6b5ad177e..ce6be3d7dab 100644
--- a/drivers/phy/bcm6348-usbh-phy.c
+++ b/drivers/phy/bcm6348-usbh-phy.c
@@ -62,9 +62,7 @@ static int bcm6348_usbh_probe(struct udevice *dev)
if (ret < 0)
return ret;
- ret = clk_free(&clk);
- if (ret < 0)
- return ret;
+ clk_free(&clk);
/* perform reset */
ret = reset_get_by_index(dev, 0, &rst_ctl);
diff --git a/drivers/phy/bcm6368-usbh-phy.c b/drivers/phy/bcm6368-usbh-phy.c
index 4d3a63faada..d057f1f52e8 100644
--- a/drivers/phy/bcm6368-usbh-phy.c
+++ b/drivers/phy/bcm6368-usbh-phy.c
@@ -137,9 +137,7 @@ static int bcm6368_usbh_probe(struct udevice *dev)
if (ret < 0)
return ret;
- ret = clk_free(&clk);
- if (ret < 0)
- return ret;
+ clk_free(&clk);
#if defined(CONFIG_POWER_DOMAIN)
/* enable power domain */
@@ -176,9 +174,7 @@ static int bcm6368_usbh_probe(struct udevice *dev)
if (ret < 0)
return ret;
- ret = clk_free(&clk);
- if (ret < 0)
- return ret;
+ clk_free(&clk);
}
mdelay(100);
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index d7477d7c336..13033198f96 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -342,6 +342,7 @@ source "drivers/pinctrl/nexell/Kconfig"
source "drivers/pinctrl/nxp/Kconfig"
source "drivers/pinctrl/renesas/Kconfig"
source "drivers/pinctrl/rockchip/Kconfig"
+source "drivers/pinctrl/sunxi/Kconfig"
source "drivers/pinctrl/uniphier/Kconfig"
endmenu
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 030c38f5cc1..9b4978253b9 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -14,7 +14,7 @@ obj-$(CONFIG_PINCTRL_INTEL) += intel/
obj-$(CONFIG_ARCH_MTMIPS) += mtmips/
obj-$(CONFIG_ARCH_RMOBILE) += renesas/
obj-$(CONFIG_PINCTRL_SANDBOX) += pinctrl-sandbox.o
-
+obj-$(CONFIG_PINCTRL_SUNXI) += sunxi/
obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/
obj-$(CONFIG_PINCTRL_PIC32) += pinctrl_pic32.o
obj-$(CONFIG_PINCTRL_EXYNOS) += exynos/
diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
new file mode 100644
index 00000000000..77da90836b6
--- /dev/null
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -0,0 +1,127 @@
+# SPDX-License-Identifier: GPL-2.0
+
+if ARCH_SUNXI
+
+config PINCTRL_SUNXI
+ select PINCTRL_FULL
+ select PINCTRL_GENERIC
+ select PINCONF
+ select PINMUX
+ bool
+
+config PINCTRL_SUNIV_F1C100S
+ bool "Support for the Allwinner F1C100s PIO"
+ default MACH_SUNIV
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN4I_A10
+ bool "Support for the Allwinner A10 PIO"
+ default MACH_SUN4I
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN5I_A13
+ bool "Support for the Allwinner A10s/A13 PIO"
+ default MACH_SUN5I
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN6I_A31
+ bool "Support for the Allwinner A31 PIO"
+ default MACH_SUN6I
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN6I_A31_R
+ bool "Support for the Allwinner A31 R-PIO"
+ default MACH_SUN6I
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN7I_A20
+ bool "Support for the Allwinner A20/R40 PIO"
+ default MACH_SUN7I || MACH_SUN8I_R40
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN8I_A23
+ bool "Support for the Allwinner A23 PIO"
+ default MACH_SUN8I_A23
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN8I_A23_R
+ bool "Support for the Allwinner A23/A33 R-PIO"
+ default MACH_SUN8I_A23 || MACH_SUN8I_A33
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN8I_A33
+ bool "Support for the Allwinner A33 PIO"
+ default MACH_SUN8I_A33
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN8I_A83T
+ bool "Support for the Allwinner A83T PIO"
+ default MACH_SUN8I_A83T
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN8I_A83T_R
+ bool "Support for the Allwinner A83T R-PIO"
+ default MACH_SUN8I_A83T
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN8I_H3
+ bool "Support for the Allwinner H3 PIO"
+ default MACH_SUN8I_H3
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN8I_H3_R
+ bool "Support for the Allwinner H3/H5 R-PIO"
+ default MACH_SUN8I_H3 || MACH_SUN50I_H5
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN8I_V3S
+ bool "Support for the Allwinner V3s PIO"
+ default MACH_SUN8I_V3S
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN9I_A80
+ bool "Support for the Allwinner A80 PIO"
+ default MACH_SUN9I
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN9I_A80_R
+ bool "Support for the Allwinner A80 R-PIO"
+ default MACH_SUN9I
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN50I_A64
+ bool "Support for the Allwinner A64 PIO"
+ default MACH_SUN50I
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN50I_A64_R
+ bool "Support for the Allwinner A64 R-PIO"
+ default MACH_SUN50I
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN50I_H5
+ bool "Support for the Allwinner H5 PIO"
+ default MACH_SUN50I_H5
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN50I_H6
+ bool "Support for the Allwinner H6 PIO"
+ default MACH_SUN50I_H6
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN50I_H6_R
+ bool "Support for the Allwinner H6 R-PIO"
+ default MACH_SUN50I_H6
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN50I_H616
+ bool "Support for the Allwinner H616 PIO"
+ default MACH_SUN50I_H616
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN50I_H616_R
+ bool "Support for the Allwinner H616 R-PIO"
+ default MACH_SUN50I_H616
+ select PINCTRL_SUNXI
+
+endif
diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
new file mode 100644
index 00000000000..6a8c01f3729
--- /dev/null
+++ b/drivers/pinctrl/sunxi/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-y += pinctrl-sunxi.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
new file mode 100644
index 00000000000..9ce2bc1b3af
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -0,0 +1,897 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <clk.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/pinctrl.h>
+#include <errno.h>
+#include <malloc.h>
+
+#include <asm/gpio.h>
+
+extern U_BOOT_DRIVER(gpio_sunxi);
+
+/*
+ * This structure implements a simplified view of the possible pinmux settings:
+ * Each mux value is assumed to be the same for a given function, across the
+ * pins in each group (almost universally true, with same rare exceptions not
+ * relevant to U-Boot), but also across different ports (not true in many
+ * cases). We ignore the first problem, and work around the latter by just
+ * supporting one particular port for a each function. This works fine for all
+ * board configurations so far. If this would need to be revisited, we could
+ * add a "u8 port;" below and match that, with 0 encoding the "don't care" case.
+ */
+struct sunxi_pinctrl_function {
+ const char name[sizeof("gpio_out")];
+ u8 mux;
+};
+
+struct sunxi_pinctrl_desc {
+ const struct sunxi_pinctrl_function *functions;
+ u8 num_functions;
+ u8 first_bank;
+ u8 num_banks;
+};
+
+struct sunxi_pinctrl_plat {
+ struct sunxi_gpio __iomem *base;
+};
+
+static int sunxi_pinctrl_get_pins_count(struct udevice *dev)
+{
+ const struct sunxi_pinctrl_desc *desc = dev_get_priv(dev);
+
+ return desc->num_banks * SUNXI_GPIOS_PER_BANK;
+}
+
+static const char *sunxi_pinctrl_get_pin_name(struct udevice *dev,
+ uint pin_selector)
+{
+ const struct sunxi_pinctrl_desc *desc = dev_get_priv(dev);
+ static char pin_name[sizeof("PN31")];
+
+ snprintf(pin_name, sizeof(pin_name), "P%c%d",
+ pin_selector / SUNXI_GPIOS_PER_BANK + desc->first_bank + 'A',
+ pin_selector % SUNXI_GPIOS_PER_BANK);
+
+ return pin_name;
+}
+
+static int sunxi_pinctrl_get_functions_count(struct udevice *dev)
+{
+ const struct sunxi_pinctrl_desc *desc = dev_get_priv(dev);
+
+ return desc->num_functions;
+}
+
+static const char *sunxi_pinctrl_get_function_name(struct udevice *dev,
+ uint func_selector)
+{
+ const struct sunxi_pinctrl_desc *desc = dev_get_priv(dev);
+
+ return desc->functions[func_selector].name;
+}
+
+static int sunxi_pinctrl_pinmux_set(struct udevice *dev, uint pin_selector,
+ uint func_selector)
+{
+ const struct sunxi_pinctrl_desc *desc = dev_get_priv(dev);
+ struct sunxi_pinctrl_plat *plat = dev_get_plat(dev);
+ int bank = pin_selector / SUNXI_GPIOS_PER_BANK;
+ int pin = pin_selector % SUNXI_GPIOS_PER_BANK;
+
+ debug("set mux: %-4s => %s (%d)\n",
+ sunxi_pinctrl_get_pin_name(dev, pin_selector),
+ sunxi_pinctrl_get_function_name(dev, func_selector),
+ desc->functions[func_selector].mux);
+
+ sunxi_gpio_set_cfgbank(plat->base + bank, pin,
+ desc->functions[func_selector].mux);
+
+ return 0;
+}
+
+static const struct pinconf_param sunxi_pinctrl_pinconf_params[] = {
+ { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
+ { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 2 },
+ { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
+ { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 10 },
+};
+
+static int sunxi_pinctrl_pinconf_set_pull(struct sunxi_pinctrl_plat *plat,
+ uint bank, uint pin, uint bias)
+{
+ struct sunxi_gpio *regs = &plat->base[bank];
+
+ sunxi_gpio_set_pull_bank(regs, pin, bias);
+
+ return 0;
+}
+
+static int sunxi_pinctrl_pinconf_set_drive(struct sunxi_pinctrl_plat *plat,
+ uint bank, uint pin, uint drive)
+{
+ struct sunxi_gpio *regs = &plat->base[bank];
+
+ if (drive < 10 || drive > 40)
+ return -EINVAL;
+
+ /* Convert mA to the register value, rounding down. */
+ sunxi_gpio_set_drv_bank(regs, pin, drive / 10 - 1);
+
+ return 0;
+}
+
+static int sunxi_pinctrl_pinconf_set(struct udevice *dev, uint pin_selector,
+ uint param, uint val)
+{
+ struct sunxi_pinctrl_plat *plat = dev_get_plat(dev);
+ int bank = pin_selector / SUNXI_GPIOS_PER_BANK;
+ int pin = pin_selector % SUNXI_GPIOS_PER_BANK;
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_BIAS_PULL_UP:
+ return sunxi_pinctrl_pinconf_set_pull(plat, bank, pin, val);
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ return sunxi_pinctrl_pinconf_set_drive(plat, bank, pin, val);
+ }
+
+ return -EINVAL;
+}
+
+static int sunxi_pinctrl_get_pin_muxing(struct udevice *dev, uint pin_selector,
+ char *buf, int size)
+{
+ struct sunxi_pinctrl_plat *plat = dev_get_plat(dev);
+ int bank = pin_selector / SUNXI_GPIOS_PER_BANK;
+ int pin = pin_selector % SUNXI_GPIOS_PER_BANK;
+ int mux = sunxi_gpio_get_cfgbank(plat->base + bank, pin);
+
+ switch (mux) {
+ case SUNXI_GPIO_INPUT:
+ strlcpy(buf, "gpio input", size);
+ break;
+ case SUNXI_GPIO_OUTPUT:
+ strlcpy(buf, "gpio output", size);
+ break;
+ case SUNXI_GPIO_DISABLE:
+ strlcpy(buf, "disabled", size);
+ break;
+ default:
+ snprintf(buf, size, "function %d", mux);
+ break;
+ }
+
+ return 0;
+}
+
+static const struct pinctrl_ops sunxi_pinctrl_ops = {
+ .get_pins_count = sunxi_pinctrl_get_pins_count,
+ .get_pin_name = sunxi_pinctrl_get_pin_name,
+ .get_functions_count = sunxi_pinctrl_get_functions_count,
+ .get_function_name = sunxi_pinctrl_get_function_name,
+ .pinmux_set = sunxi_pinctrl_pinmux_set,
+ .pinconf_num_params = ARRAY_SIZE(sunxi_pinctrl_pinconf_params),
+ .pinconf_params = sunxi_pinctrl_pinconf_params,
+ .pinconf_set = sunxi_pinctrl_pinconf_set,
+ .set_state = pinctrl_generic_set_state,
+ .get_pin_muxing = sunxi_pinctrl_get_pin_muxing,
+};
+
+static int sunxi_pinctrl_bind(struct udevice *dev)
+{
+ struct sunxi_pinctrl_plat *plat = dev_get_plat(dev);
+ struct sunxi_pinctrl_desc *desc;
+ struct sunxi_gpio_plat *gpio_plat;
+ struct udevice *gpio_dev;
+ int i, ret;
+
+ desc = (void *)dev_get_driver_data(dev);
+ if (!desc)
+ return -EINVAL;
+ dev_set_priv(dev, desc);
+
+ plat->base = dev_read_addr_ptr(dev);
+
+ ret = device_bind_driver_to_node(dev, "gpio_sunxi", dev->name,
+ dev_ofnode(dev), &gpio_dev);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < desc->num_banks; ++i) {
+ gpio_plat = malloc(sizeof(*gpio_plat));
+ if (!gpio_plat)
+ return -ENOMEM;
+
+ gpio_plat->regs = plat->base + i;
+ gpio_plat->bank_name[0] = 'P';
+ gpio_plat->bank_name[1] = 'A' + desc->first_bank + i;
+ gpio_plat->bank_name[2] = '\0';
+
+ ret = device_bind(gpio_dev, DM_DRIVER_REF(gpio_sunxi),
+ gpio_plat->bank_name, gpio_plat,
+ ofnode_null(), NULL);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int sunxi_pinctrl_probe(struct udevice *dev)
+{
+ struct clk *apb_clk;
+
+ apb_clk = devm_clk_get(dev, "apb");
+ if (!IS_ERR(apb_clk))
+ clk_enable(apb_clk);
+
+ return 0;
+}
+
+static const struct sunxi_pinctrl_function suniv_f1c100s_pinctrl_functions[] = {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 3 }, /* PE11-PE12 */
+ { "i2c1", 3 }, /* PD5-PD6 */
+ { "mmc0", 2 }, /* PF0-PF5 */
+ { "mmc1", 3 }, /* PC0-PC2 */
+ { "spi0", 2 }, /* PC0-PC3 */
+#if IS_ENABLED(CONFIG_UART0_PORT_F)
+ { "uart0", 3 }, /* PF2-PF4 */
+#else
+ { "uart0", 5 }, /* PE0-PE1 */
+#endif
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused suniv_f1c100s_pinctrl_desc = {
+ .functions = suniv_f1c100s_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(suniv_f1c100s_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_A,
+ .num_banks = 6,
+};
+
+static const struct sunxi_pinctrl_function sun4i_a10_pinctrl_functions[] = {
+ { "emac", 2 }, /* PA0-PA17 */
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 }, /* PB0-PB1 */
+ { "i2c1", 2 }, /* PB18-PB19 */
+ { "mmc0", 2 }, /* PF0-PF5 */
+#if IS_ENABLED(CONFIG_MMC1_PINS_PH)
+ { "mmc1", 5 }, /* PH22-PH27 */
+#else
+ { "mmc1", 4 }, /* PG0-PG5 */
+#endif
+ { "mmc2", 3 }, /* PC6-PC15 */
+ { "mmc3", 2 }, /* PI4-PI9 */
+ { "spi0", 3 }, /* PC0-PC2, PC23 */
+#if IS_ENABLED(CONFIG_UART0_PORT_F)
+ { "uart0", 4 }, /* PF2-PF4 */
+#else
+ { "uart0", 2 }, /* PB22-PB23 */
+#endif
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun4i_a10_pinctrl_desc = {
+ .functions = sun4i_a10_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun4i_a10_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_A,
+ .num_banks = 9,
+};
+
+static const struct sunxi_pinctrl_function sun5i_a13_pinctrl_functions[] = {
+ { "emac", 2 }, /* PA0-PA17 */
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 }, /* PB0-PB1 */
+ { "i2c1", 2 }, /* PB15-PB16 */
+ { "mmc0", 2 }, /* PF0-PF5 */
+ { "mmc1", 2 }, /* PG3-PG8 */
+ { "mmc2", 3 }, /* PC6-PC15 */
+ { "spi0", 3 }, /* PC0-PC3 */
+#if IS_ENABLED(CONFIG_UART0_PORT_F)
+ { "uart0", 4 }, /* PF2-PF4 */
+#else
+ { "uart0", 2 }, /* PB19-PB20 */
+#endif
+ { "uart1", 4 }, /* PG3-PG4 */
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun5i_a13_pinctrl_desc = {
+ .functions = sun5i_a13_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun5i_a13_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_A,
+ .num_banks = 7,
+};
+
+static const struct sunxi_pinctrl_function sun6i_a31_pinctrl_functions[] = {
+ { "gmac", 2 }, /* PA0-PA27 */
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 }, /* PH14-PH15 */
+ { "i2c1", 2 }, /* PH16-PH17 */
+ { "mmc0", 2 }, /* PF0-PF5 */
+ { "mmc1", 2 }, /* PG0-PG5 */
+ { "mmc2", 3 }, /* PC6-PC15, PC24 */
+ { "mmc3", 4 }, /* PC6-PC15, PC24 */
+ { "spi0", 3 }, /* PC0-PC2, PC27 */
+#if IS_ENABLED(CONFIG_UART0_PORT_F)
+ { "uart0", 3 }, /* PF2-PF4 */
+#else
+ { "uart0", 2 }, /* PH20-PH21 */
+#endif
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun6i_a31_pinctrl_desc = {
+ .functions = sun6i_a31_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun6i_a31_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_A,
+ .num_banks = 8,
+};
+
+static const struct sunxi_pinctrl_function sun6i_a31_r_pinctrl_functions[] = {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_i2c", 2 }, /* PL0-PL1 */
+ { "s_uart", 2 }, /* PL2-PL3 */
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun6i_a31_r_pinctrl_desc = {
+ .functions = sun6i_a31_r_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun6i_a31_r_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_L,
+ .num_banks = 2,
+};
+
+static const struct sunxi_pinctrl_function sun7i_a20_pinctrl_functions[] = {
+ { "emac", 2 }, /* PA0-PA17 */
+ { "gmac", 5 }, /* PA0-PA17 */
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 }, /* PB0-PB1 */
+ { "i2c1", 2 }, /* PB18-PB19 */
+ { "mmc0", 2 }, /* PF0-PF5 */
+#if IS_ENABLED(CONFIG_MMC1_PINS_PH)
+ { "mmc1", 5 }, /* PH22-PH27 */
+#else
+ { "mmc1", 4 }, /* PG0-PG5 */
+#endif
+ { "mmc2", 3 }, /* PC5-PC15, PC24 */
+ { "spi0", 3 }, /* PC0-PC2, PC23 */
+#if IS_ENABLED(CONFIG_UART0_PORT_F)
+ { "uart0", 4 }, /* PF2-PF4 */
+#else
+ { "uart0", 2 }, /* PB22-PB23 */
+#endif
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun7i_a20_pinctrl_desc = {
+ .functions = sun7i_a20_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun7i_a20_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_A,
+ .num_banks = 9,
+};
+
+static const struct sunxi_pinctrl_function sun8i_a23_pinctrl_functions[] = {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 }, /* PH2-PH3 */
+ { "i2c1", 2 }, /* PH4-PH5 */
+ { "mmc0", 2 }, /* PF0-PF5 */
+ { "mmc1", 2 }, /* PG0-PG5 */
+ { "mmc2", 3 }, /* PC5-PC16 */
+ { "spi0", 3 }, /* PC0-PC3 */
+#if IS_ENABLED(CONFIG_UART0_PORT_F)
+ { "uart0", 3 }, /* PF2-PF4 */
+#endif
+ { "uart1", 2 }, /* PG6-PG7 */
+ { "uart2", 2 }, /* PB0-PB1 */
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun8i_a23_pinctrl_desc = {
+ .functions = sun8i_a23_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun8i_a23_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_A,
+ .num_banks = 8,
+};
+
+static const struct sunxi_pinctrl_function sun8i_a23_r_pinctrl_functions[] = {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_i2c", 3 }, /* PL0-PL1 */
+ { "s_uart", 2 }, /* PL2-PL3 */
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun8i_a23_r_pinctrl_desc = {
+ .functions = sun8i_a23_r_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun8i_a23_r_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_L,
+ .num_banks = 1,
+};
+
+static const struct sunxi_pinctrl_function sun8i_a33_pinctrl_functions[] = {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 }, /* PH2-PH3 */
+ { "i2c1", 2 }, /* PH4-PH5 */
+ { "mmc0", 2 }, /* PF0-PF5 */
+ { "mmc1", 2 }, /* PG0-PG5 */
+ { "mmc2", 3 }, /* PC5-PC16 */
+ { "spi0", 3 }, /* PC0-PC3 */
+#if IS_ENABLED(CONFIG_UART0_PORT_F)
+ { "uart0", 3 }, /* PF2-PF4 */
+#else
+ { "uart0", 3 }, /* PB0-PB1 */
+#endif
+ { "uart1", 2 }, /* PG6-PG7 */
+ { "uart2", 2 }, /* PB0-PB1 */
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun8i_a33_pinctrl_desc = {
+ .functions = sun8i_a33_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun8i_a33_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_A,
+ .num_banks = 8,
+};
+
+static const struct sunxi_pinctrl_function sun8i_a83t_pinctrl_functions[] = {
+ { "gmac", 4 }, /* PD2-PD23 */
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 }, /* PH0-PH1 */
+ { "i2c1", 2 }, /* PH2-PH3 */
+ { "mmc0", 2 }, /* PF0-PF5 */
+ { "mmc1", 2 }, /* PG0-PG5 */
+ { "mmc2", 3 }, /* PC5-PC16 */
+ { "spi0", 3 }, /* PC0-PC3 */
+#if IS_ENABLED(CONFIG_UART0_PORT_F)
+ { "uart0", 3 }, /* PF2-PF4 */
+#else
+ { "uart0", 2 }, /* PB9-PB10 */
+#endif
+ { "uart1", 2 }, /* PG6-PG7 */
+ { "uart2", 2 }, /* PB0-PB1 */
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun8i_a83t_pinctrl_desc = {
+ .functions = sun8i_a83t_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun8i_a83t_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_A,
+ .num_banks = 8,
+};
+
+static const struct sunxi_pinctrl_function sun8i_a83t_r_pinctrl_functions[] = {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_i2c", 2 }, /* PL8-PL9 */
+ { "s_uart", 2 }, /* PL2-PL3 */
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun8i_a83t_r_pinctrl_desc = {
+ .functions = sun8i_a83t_r_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun8i_a83t_r_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_L,
+ .num_banks = 1,
+};
+
+static const struct sunxi_pinctrl_function sun8i_h3_pinctrl_functions[] = {
+ { "emac", 2 }, /* PD0-PD17 */
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 }, /* PA11-PA12 */
+ { "i2c1", 3 }, /* PA18-PA19 */
+ { "mmc0", 2 }, /* PF0-PF5 */
+ { "mmc1", 2 }, /* PG0-PG5 */
+ { "mmc2", 3 }, /* PC5-PC16 */
+ { "spi0", 3 }, /* PC0-PC3 */
+#if IS_ENABLED(CONFIG_UART0_PORT_F)
+ { "uart0", 3 }, /* PF2-PF4 */
+#else
+ { "uart0", 2 }, /* PA4-PA5 */
+#endif
+ { "uart1", 2 }, /* PG6-PG7 */
+ { "uart2", 2 }, /* PA0-PA1 */
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun8i_h3_pinctrl_desc = {
+ .functions = sun8i_h3_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun8i_h3_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_A,
+ .num_banks = 7,
+};
+
+static const struct sunxi_pinctrl_function sun8i_h3_r_pinctrl_functions[] = {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_i2c", 2 }, /* PL0-PL1 */
+ { "s_uart", 2 }, /* PL2-PL3 */
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun8i_h3_r_pinctrl_desc = {
+ .functions = sun8i_h3_r_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun8i_h3_r_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_L,
+ .num_banks = 1,
+};
+
+static const struct sunxi_pinctrl_function sun8i_v3s_pinctrl_functions[] = {
+ { "emac", 4 }, /* PD0-PD17 */
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 }, /* PB6-PB7 */
+ { "i2c1", 2 }, /* PB8-PB9 */
+ { "mmc0", 2 }, /* PF0-PF5 */
+ { "mmc1", 2 }, /* PG0-PG5 */
+ { "mmc2", 2 }, /* PC0-PC10 */
+ { "spi0", 3 }, /* PC0-PC3 */
+#if IS_ENABLED(CONFIG_UART0_PORT_F)
+ { "uart0", 3 }, /* PF2-PF4 */
+#else
+ { "uart0", 3 }, /* PB8-PB9 */
+#endif
+ { "uart1", 2 }, /* PG6-PG7 */
+ { "uart2", 2 }, /* PB0-PB1 */
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun8i_v3s_pinctrl_desc = {
+ .functions = sun8i_v3s_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun8i_v3s_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_A,
+ .num_banks = 7,
+};
+
+static const struct sunxi_pinctrl_function sun9i_a80_pinctrl_functions[] = {
+ { "gmac", 2 }, /* PA0-PA17 */
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 }, /* PH0-PH1 */
+ { "i2c1", 2 }, /* PH2-PH3 */
+ { "mmc0", 2 }, /* PF0-PF5 */
+ { "mmc1", 2 }, /* PG0-PG5 */
+ { "mmc2", 3 }, /* PC6-PC16 */
+ { "spi0", 3 }, /* PC0-PC2, PC19 */
+#if IS_ENABLED(CONFIG_UART0_PORT_F)
+ { "uart0", 4 }, /* PF2-PF4 */
+#else
+ { "uart0", 2 }, /* PH12-PH13 */
+#endif
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun9i_a80_pinctrl_desc = {
+ .functions = sun9i_a80_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun9i_a80_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_A,
+ .num_banks = 8,
+};
+
+static const struct sunxi_pinctrl_function sun9i_a80_r_pinctrl_functions[] = {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_i2c0", 2 }, /* PN0-PN1 */
+ { "s_i2c1", 3 }, /* PM8-PM9 */
+ { "s_uart", 3 }, /* PL0-PL1 */
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun9i_a80_r_pinctrl_desc = {
+ .functions = sun9i_a80_r_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun9i_a80_r_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_L,
+ .num_banks = 3,
+};
+
+static const struct sunxi_pinctrl_function sun50i_a64_pinctrl_functions[] = {
+ { "emac", 4 }, /* PD8-PD23 */
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 }, /* PH0-PH1 */
+ { "i2c1", 2 }, /* PH2-PH3 */
+ { "mmc0", 2 }, /* PF0-PF5 */
+ { "mmc1", 2 }, /* PG0-PG5 */
+ { "mmc2", 3 }, /* PC1-PC16 */
+ { "pwm", 2 }, /* PD22 */
+ { "spi0", 4 }, /* PC0-PC3 */
+#if IS_ENABLED(CONFIG_UART0_PORT_F)
+ { "uart0", 3 }, /* PF2-PF4 */
+#else
+ { "uart0", 4 }, /* PB8-PB9 */
+#endif
+ { "uart1", 2 }, /* PG6-PG7 */
+ { "uart2", 2 }, /* PB0-PB1 */
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun50i_a64_pinctrl_desc = {
+ .functions = sun50i_a64_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun50i_a64_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_A,
+ .num_banks = 8,
+};
+
+static const struct sunxi_pinctrl_function sun50i_a64_r_pinctrl_functions[] = {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_i2c", 2 }, /* PL8-PL9 */
+ { "s_uart", 2 }, /* PL2-PL3 */
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun50i_a64_r_pinctrl_desc = {
+ .functions = sun50i_a64_r_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun50i_a64_r_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_L,
+ .num_banks = 1,
+};
+
+static const struct sunxi_pinctrl_function sun50i_h5_pinctrl_functions[] = {
+ { "emac", 2 }, /* PD0-PD17 */
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 }, /* PA11-PA12 */
+ { "i2c1", 3 }, /* PA18-PA19 */
+ { "mmc0", 2 }, /* PF0-PF5 */
+ { "mmc1", 2 }, /* PG0-PG5 */
+ { "mmc2", 3 }, /* PC1-PC16 */
+ { "spi0", 3 }, /* PC0-PC3 */
+#if IS_ENABLED(CONFIG_UART0_PORT_F)
+ { "uart0", 3 }, /* PF2-PF4 */
+#else
+ { "uart0", 2 }, /* PA4-PA5 */
+#endif
+ { "uart1", 2 }, /* PG6-PG7 */
+ { "uart2", 2 }, /* PA0-PA1 */
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h5_pinctrl_desc = {
+ .functions = sun50i_h5_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun50i_h5_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_A,
+ .num_banks = 7,
+};
+
+static const struct sunxi_pinctrl_function sun50i_h6_pinctrl_functions[] = {
+ { "emac", 5 }, /* PD0-PD20 */
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 }, /* PD25-PD26 */
+ { "i2c1", 4 }, /* PH5-PH6 */
+ { "mmc0", 2 }, /* PF0-PF5 */
+ { "mmc1", 2 }, /* PG0-PG5 */
+ { "mmc2", 3 }, /* PC1-PC14 */
+ { "spi0", 4 }, /* PC0-PC7 */
+#if IS_ENABLED(CONFIG_UART0_PORT_F)
+ { "uart0", 3 }, /* PF2-PF4 */
+#else
+ { "uart0", 2 }, /* PH0-PH1 */
+#endif
+ { "uart1", 2 }, /* PG6-PG7 */
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h6_pinctrl_desc = {
+ .functions = sun50i_h6_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun50i_h6_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_A,
+ .num_banks = 8,
+};
+
+static const struct sunxi_pinctrl_function sun50i_h6_r_pinctrl_functions[] = {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_i2c", 3 }, /* PL0-PL1 */
+ { "s_uart", 2 }, /* PL2-PL3 */
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h6_r_pinctrl_desc = {
+ .functions = sun50i_h6_r_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun50i_h6_r_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_L,
+ .num_banks = 2,
+};
+
+static const struct sunxi_pinctrl_function sun50i_h616_pinctrl_functions[] = {
+ { "emac0", 2 }, /* PI0-PI16 */
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 }, /* PF0-PF5 */
+ { "mmc1", 2 }, /* PG0-PG5 */
+ { "mmc2", 3 }, /* PC0-PC16 */
+ { "spi0", 4 }, /* PC0-PC7, PC15-PC16 */
+#if IS_ENABLED(CONFIG_UART0_PORT_F)
+ { "uart0", 3 }, /* PF2-PF4 */
+#else
+ { "uart0", 2 }, /* PH0-PH1 */
+#endif
+ { "uart1", 2 }, /* PG6-PG7 */
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h616_pinctrl_desc = {
+ .functions = sun50i_h616_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun50i_h616_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_A,
+ .num_banks = 9,
+};
+
+static const struct sunxi_pinctrl_function sun50i_h616_r_pinctrl_functions[] = {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_i2c", 3 }, /* PL0-PL1 */
+ { "s_uart", 2 }, /* PL2-PL3 */
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h616_r_pinctrl_desc = {
+ .functions = sun50i_h616_r_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun50i_h616_r_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_L,
+ .num_banks = 1,
+};
+
+static const struct udevice_id sunxi_pinctrl_ids[] = {
+#ifdef CONFIG_PINCTRL_SUNIV_F1C100S
+ {
+ .compatible = "allwinner,suniv-f1c100s-pinctrl",
+ .data = (ulong)&suniv_f1c100s_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN4I_A10
+ {
+ .compatible = "allwinner,sun4i-a10-pinctrl",
+ .data = (ulong)&sun4i_a10_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN5I_A13
+ {
+ .compatible = "allwinner,sun5i-a10s-pinctrl",
+ .data = (ulong)&sun5i_a13_pinctrl_desc,
+ },
+ {
+ .compatible = "allwinner,sun5i-a13-pinctrl",
+ .data = (ulong)&sun5i_a13_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN6I_A31
+ {
+ .compatible = "allwinner,sun6i-a31-pinctrl",
+ .data = (ulong)&sun6i_a31_pinctrl_desc,
+ },
+ {
+ .compatible = "allwinner,sun6i-a31s-pinctrl",
+ .data = (ulong)&sun6i_a31_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN6I_A31_R
+ {
+ .compatible = "allwinner,sun6i-a31-r-pinctrl",
+ .data = (ulong)&sun6i_a31_r_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN7I_A20
+ {
+ .compatible = "allwinner,sun7i-a20-pinctrl",
+ .data = (ulong)&sun7i_a20_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN8I_A23
+ {
+ .compatible = "allwinner,sun8i-a23-pinctrl",
+ .data = (ulong)&sun8i_a23_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN8I_A23_R
+ {
+ .compatible = "allwinner,sun8i-a23-r-pinctrl",
+ .data = (ulong)&sun8i_a23_r_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN8I_A33
+ {
+ .compatible = "allwinner,sun8i-a33-pinctrl",
+ .data = (ulong)&sun8i_a33_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN8I_A83T
+ {
+ .compatible = "allwinner,sun8i-a83t-pinctrl",
+ .data = (ulong)&sun8i_a83t_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN8I_A83T_R
+ {
+ .compatible = "allwinner,sun8i-a83t-r-pinctrl",
+ .data = (ulong)&sun8i_a83t_r_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN8I_H3
+ {
+ .compatible = "allwinner,sun8i-h3-pinctrl",
+ .data = (ulong)&sun8i_h3_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN8I_H3_R
+ {
+ .compatible = "allwinner,sun8i-h3-r-pinctrl",
+ .data = (ulong)&sun8i_h3_r_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN7I_A20
+ {
+ .compatible = "allwinner,sun8i-r40-pinctrl",
+ .data = (ulong)&sun7i_a20_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN8I_V3S
+ {
+ .compatible = "allwinner,sun8i-v3-pinctrl",
+ .data = (ulong)&sun8i_v3s_pinctrl_desc,
+ },
+ {
+ .compatible = "allwinner,sun8i-v3s-pinctrl",
+ .data = (ulong)&sun8i_v3s_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN9I_A80
+ {
+ .compatible = "allwinner,sun9i-a80-pinctrl",
+ .data = (ulong)&sun9i_a80_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN9I_A80_R
+ {
+ .compatible = "allwinner,sun9i-a80-r-pinctrl",
+ .data = (ulong)&sun9i_a80_r_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN50I_A64
+ {
+ .compatible = "allwinner,sun50i-a64-pinctrl",
+ .data = (ulong)&sun50i_a64_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN50I_A64_R
+ {
+ .compatible = "allwinner,sun50i-a64-r-pinctrl",
+ .data = (ulong)&sun50i_a64_r_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN50I_H5
+ {
+ .compatible = "allwinner,sun50i-h5-pinctrl",
+ .data = (ulong)&sun50i_h5_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN50I_H6
+ {
+ .compatible = "allwinner,sun50i-h6-pinctrl",
+ .data = (ulong)&sun50i_h6_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN50I_H6_R
+ {
+ .compatible = "allwinner,sun50i-h6-r-pinctrl",
+ .data = (ulong)&sun50i_h6_r_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN50I_H616
+ {
+ .compatible = "allwinner,sun50i-h616-pinctrl",
+ .data = (ulong)&sun50i_h616_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN50I_H616_R
+ {
+ .compatible = "allwinner,sun50i-h616-r-pinctrl",
+ .data = (ulong)&sun50i_h616_r_pinctrl_desc,
+ },
+#endif
+ {}
+};
+
+U_BOOT_DRIVER(sunxi_pinctrl) = {
+ .name = "sunxi-pinctrl",
+ .id = UCLASS_PINCTRL,
+ .of_match = sunxi_pinctrl_ids,
+ .bind = sunxi_pinctrl_bind,
+ .probe = sunxi_pinctrl_probe,
+ .plat_auto = sizeof(struct sunxi_pinctrl_plat),
+ .ops = &sunxi_pinctrl_ops,
+};
diff --git a/drivers/pwm/sunxi_pwm.c b/drivers/pwm/sunxi_pwm.c
index e3d5ee456b0..bb1bec05ec3 100644
--- a/drivers/pwm/sunxi_pwm.c
+++ b/drivers/pwm/sunxi_pwm.c
@@ -13,7 +13,6 @@
#include <asm/global_data.h>
#include <asm/io.h>
#include <asm/arch/pwm.h>
-#include <asm/arch/gpio.h>
#include <power/regulator.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -45,14 +44,6 @@ static const u32 prescaler_table[] = {
1, /* 1111 */
};
-static int sunxi_pwm_config_pinmux(void)
-{
-#ifdef CONFIG_MACH_SUN50I
- sunxi_gpio_set_cfgpin(SUNXI_GPD(22), SUNXI_GPD_PWM);
-#endif
- return 0;
-}
-
static int sunxi_pwm_set_invert(struct udevice *dev, uint channel,
bool polarity)
{
@@ -137,8 +128,6 @@ static int sunxi_pwm_set_enable(struct udevice *dev, uint channel, bool enable)
return 0;
}
- sunxi_pwm_config_pinmux();
-
if (priv->invert)
v &= ~SUNXI_PWM_CTRL_CH0_ACT_STA;
else
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 71777cdd05f..7a6c6efb4b0 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -168,6 +168,14 @@ config RTC_MC146818
clock with a wide array of features and 50 bytes of general-purpose,
battery-backed RAM. The driver supports access to the clock and RAM.
+config MCFRTC
+ bool "Use common CF RTC driver"
+ depends on M68K
+
+config SYS_MCFRTC_BASE
+ hex "Base address for RTC in immap.h"
+ depends on MCFRTC
+
config RTC_M41T62
bool "Enable M41T62 driver"
help
diff --git a/drivers/rtc/mcfrtc.c b/drivers/rtc/mcfrtc.c
index e10638ec7dd..d2ac889c309 100644
--- a/drivers/rtc/mcfrtc.c
+++ b/drivers/rtc/mcfrtc.c
@@ -13,10 +13,6 @@
#undef RTC_DEBUG
-#ifndef CONFIG_SYS_MCFRTC_BASE
-#error RTC_BASE is not defined!
-#endif
-
#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
#define STARTOFTIME 1970
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 345d1881f55..76171e7146a 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -133,6 +133,19 @@ config SERIAL_RX_BUFFER_SIZE
help
The size of the RX buffer (needs to be power of 2)
+config SERIAL_PUTS
+ bool "Enable printing strings all at once"
+ depends on DM_SERIAL
+ help
+ Some serial drivers are much more efficient when printing multiple
+ characters at once rather than printing characters individually. This
+ can be because they can load a fifo, or because individual print
+ calls have a constant overhead. With this option set, the serial
+ subsystem will try to provide serial drivers with as many characters
+ at once as possible, instead of printing characters one by one. Most
+ serial drivers do not need this config to print efficiently. If
+ unsure, say N.
+
config SERIAL_SEARCH_ALL
bool "Search for serial devices after default one failed"
depends on DM_SERIAL
@@ -399,6 +412,15 @@ config DEBUG_UART_SANDBOX
start up driver model. The driver will be available until the real
driver model serial is running.
+config DEBUG_UART_SEMIHOSTING
+ bool "semihosting"
+ depends on SEMIHOSTING_SERIAL
+ help
+ Select this to enable the debug UART using the semihosting driver.
+ This provides basic serial output from the console without needing to
+ start up driver model. The driver will be available until the real
+ driver model serial is running.
+
config DEBUG_UART_SIFIVE
bool "SiFive UART"
depends on SIFIVE_SERIAL
@@ -647,6 +669,10 @@ config FSL_LPUART
Select this to enable a Low Power UART for Freescale VF610 and
QorIQ Layerscape devices.
+config LPUART
+ bool "Use the LPUART as console"
+ depends on FSL_LPUART
+
config MVEBU_A3700_UART
bool "UART support for Armada 3700"
help
@@ -778,6 +804,19 @@ config SCIF_CONSOLE
on systems with RCar or SH SoCs, say Y to this option. If unsure,
say N.
+config SEMIHOSTING_SERIAL
+ bool "Semihosting UART support"
+ depends on SEMIHOSTING && !SERIAL_RX_BUFFER
+ help
+ Select this to enable a serial UART using semihosting. Special halt
+ instructions will be issued which an external debugger (such as a
+ JTAG emulator) may interpret. The debugger will display U-Boot's
+ console output on the host system.
+
+ Enable this option only if you are using a debugger which supports
+ semihosting. If you are not using a debugger, this driver will halt
+ the boot.
+
config UNIPHIER_SERIAL
bool "Support for UniPhier on-chip UART"
depends on ARCH_UNIPHIER
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 52e70aa1917..b68b5e7b2bf 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -52,6 +52,7 @@ endif
obj-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o
obj-$(CONFIG_SANDBOX_SERIAL) += sandbox.o
obj-$(CONFIG_SCIF_CONSOLE) += serial_sh.o
+obj-$(CONFIG_SEMIHOSTING_SERIAL) += serial_semihosting.o
obj-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o
obj-$(CONFIG_FSL_LPUART) += serial_lpuart.o
obj-$(CONFIG_FSL_LINFLEXUART) += serial_linflexuart.o
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index f30f352bd7a..10d6b800e2f 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -200,8 +200,30 @@ static void _serial_putc(struct udevice *dev, char ch)
static void _serial_puts(struct udevice *dev, const char *str)
{
- while (*str)
- _serial_putc(dev, *str++);
+ struct dm_serial_ops *ops = serial_get_ops(dev);
+
+ if (!CONFIG_IS_ENABLED(SERIAL_PUTS) || !ops->puts) {
+ while (*str)
+ _serial_putc(dev, *str++);
+ return;
+ }
+
+ do {
+ const char *newline = strchrnul(str, '\n');
+ size_t len = newline - str + !!*newline;
+
+ do {
+ ssize_t written = ops->puts(dev, str, len);
+
+ if (written < 0)
+ return;
+ str += written;
+ len -= written;
+ } while (len);
+
+ if (*newline)
+ _serial_putc(dev, '\r');
+ } while (*str);
}
static int __serial_getc(struct udevice *dev)
diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c
index ebbd21916d7..6cdbb89841c 100644
--- a/drivers/serial/serial.c
+++ b/drivers/serial/serial.c
@@ -126,6 +126,7 @@ serial_initfunc(mxc_serial_initialize);
serial_initfunc(ns16550_serial_initialize);
serial_initfunc(pl01x_serial_initialize);
serial_initfunc(pxa_serial_initialize);
+serial_initfunc(smh_serial_initialize);
serial_initfunc(sh_serial_initialize);
serial_initfunc(mtk_serial_initialize);
@@ -180,6 +181,7 @@ int serial_initialize(void)
ns16550_serial_initialize();
pl01x_serial_initialize();
pxa_serial_initialize();
+ smh_serial_initialize();
sh_serial_initialize();
mtk_serial_initialize();
diff --git a/drivers/serial/serial_semihosting.c b/drivers/serial/serial_semihosting.c
new file mode 100644
index 00000000000..62b1b2241b3
--- /dev/null
+++ b/drivers/serial/serial_semihosting.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 Sean Anderson <sean.anderson@seco.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <serial.h>
+#include <semihosting.h>
+
+/**
+ * struct smh_serial_priv - Semihosting serial private data
+ * @infd: stdin file descriptor (or error)
+ */
+struct smh_serial_priv {
+ int infd;
+ int outfd;
+};
+
+#if CONFIG_IS_ENABLED(DM_SERIAL)
+static int smh_serial_getc(struct udevice *dev)
+{
+ char ch = 0;
+ struct smh_serial_priv *priv = dev_get_priv(dev);
+
+ if (priv->infd < 0)
+ return smh_getc();
+
+ smh_read(priv->infd, &ch, sizeof(ch));
+ return ch;
+}
+
+static int smh_serial_putc(struct udevice *dev, const char ch)
+{
+ smh_putc(ch);
+ return 0;
+}
+
+static const struct dm_serial_ops smh_serial_ops = {
+ .putc = smh_serial_putc,
+ .getc = smh_serial_getc,
+};
+
+static int smh_serial_bind(struct udevice *dev)
+{
+ if (semihosting_enabled())
+ return 0;
+ return -ENOENT;
+}
+
+static int smh_serial_probe(struct udevice *dev)
+{
+ struct smh_serial_priv *priv = dev_get_priv(dev);
+
+ priv->infd = smh_open(":tt", MODE_READ);
+ return 0;
+}
+
+U_BOOT_DRIVER(smh_serial) = {
+ .name = "serial_semihosting",
+ .id = UCLASS_SERIAL,
+ .bind = smh_serial_bind,
+ .probe = smh_serial_probe,
+ .priv_auto = sizeof(struct smh_serial_priv),
+ .ops = &smh_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRVINFO(smh_serial) = {
+ .name = "serial_semihosting",
+};
+#else /* DM_SERIAL */
+static int infd = -ENODEV;
+static int outfd = -ENODEV;
+
+static int smh_serial_start(void)
+{
+ infd = smh_open(":tt", MODE_READ);
+ outfd = smh_open(":tt", MODE_WRITE);
+ return 0;
+}
+
+static int smh_serial_stop(void)
+{
+ if (outfd >= 0)
+ smh_close(outfd);
+ return 0;
+}
+
+static void smh_serial_setbrg(void)
+{
+}
+
+static int smh_serial_getc(void)
+{
+ char ch = 0;
+
+ if (infd < 0)
+ return smh_getc();
+
+ smh_read(infd, &ch, sizeof(ch));
+ return ch;
+}
+
+static int smh_serial_tstc(void)
+{
+ return 1;
+}
+
+static void smh_serial_puts(const char *s)
+{
+ ulong unused;
+
+ if (outfd < 0)
+ smh_puts(s);
+ else
+ smh_write(outfd, s, strlen(s), &unused);
+}
+
+struct serial_device serial_smh_device = {
+ .name = "serial_smh",
+ .start = smh_serial_start,
+ .stop = smh_serial_stop,
+ .setbrg = smh_serial_setbrg,
+ .getc = smh_serial_getc,
+ .tstc = smh_serial_tstc,
+ .putc = smh_putc,
+ .puts = smh_serial_puts,
+};
+
+void smh_serial_initialize(void)
+{
+ if (semihosting_enabled())
+ serial_register(&serial_smh_device);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &serial_smh_device;
+}
+#endif
+
+#ifdef CONFIG_DEBUG_UART_SEMIHOSTING
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+}
+
+static inline void _debug_uart_putc(int c)
+{
+ smh_putc(c);
+}
+
+DEBUG_UART_FUNCS
+#endif
diff --git a/drivers/spi/bcm63xx_hsspi.c b/drivers/spi/bcm63xx_hsspi.c
index 85108df565c..47002f8b566 100644
--- a/drivers/spi/bcm63xx_hsspi.c
+++ b/drivers/spi/bcm63xx_hsspi.c
@@ -355,9 +355,7 @@ static int bcm63xx_hsspi_probe(struct udevice *dev)
if (ret < 0 && ret != -ENOSYS)
return ret;
- ret = clk_free(&clk);
- if (ret < 0 && ret != -ENOSYS)
- return ret;
+ clk_free(&clk);
/* get clock rate */
ret = clk_get_by_name(dev, "pll", &clk);
@@ -366,9 +364,7 @@ static int bcm63xx_hsspi_probe(struct udevice *dev)
priv->clk_rate = clk_get_rate(&clk);
- ret = clk_free(&clk);
- if (ret < 0 && ret != -ENOSYS)
- return ret;
+ clk_free(&clk);
/* perform reset */
ret = reset_get_by_index(dev, 0, &rst_ctl);
diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
index dd5e62b2fe1..0600d56c69e 100644
--- a/drivers/spi/bcm63xx_spi.c
+++ b/drivers/spi/bcm63xx_spi.c
@@ -391,9 +391,7 @@ static int bcm63xx_spi_probe(struct udevice *dev)
if (ret < 0)
return ret;
- ret = clk_free(&clk);
- if (ret < 0)
- return ret;
+ clk_free(&clk);
/* perform reset */
ret = reset_get_by_index(dev, 0, &rst_ctl);
diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index 47bea0b376a..1c7d0ca310b 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -732,7 +732,7 @@ static int dw_spi_remove(struct udevice *bus)
if (ret)
return ret;
- ret = clk_free(&priv->clk);
+ clk_free(&priv->clk);
if (ret)
return ret;
#endif
diff --git a/drivers/spi/spi-sunxi.c b/drivers/spi/spi-sunxi.c
index d62355ec6fb..b6cd7ddafad 100644
--- a/drivers/spi/spi-sunxi.c
+++ b/drivers/spi/spi-sunxi.c
@@ -32,7 +32,6 @@
#include <linux/bitops.h>
#include <asm/bitops.h>
-#include <asm/gpio.h>
#include <asm/io.h>
#include <linux/iopoll.h>
@@ -180,87 +179,6 @@ static void sun4i_spi_set_cs(struct udevice *bus, u8 cs, bool enable)
writel(reg, SPI_REG(priv, SPI_TCR));
}
-static int sun4i_spi_parse_pins(struct udevice *dev)
-{
- const void *fdt = gd->fdt_blob;
- const char *pin_name;
- const fdt32_t *list;
- u32 phandle;
- int drive, pull = 0, pin, i;
- int offset;
- int size;
-
- list = fdt_getprop(fdt, dev_of_offset(dev), "pinctrl-0", &size);
- if (!list) {
- printf("WARNING: sun4i_spi: cannot find pinctrl-0 node\n");
- return -EINVAL;
- }
-
- while (size) {
- phandle = fdt32_to_cpu(*list++);
- size -= sizeof(*list);
-
- offset = fdt_node_offset_by_phandle(fdt, phandle);
- if (offset < 0)
- return offset;
-
- drive = fdt_getprop_u32_default_node(fdt, offset, 0,
- "drive-strength", 0);
- if (drive) {
- if (drive <= 10)
- drive = 0;
- else if (drive <= 20)
- drive = 1;
- else if (drive <= 30)
- drive = 2;
- else
- drive = 3;
- } else {
- drive = fdt_getprop_u32_default_node(fdt, offset, 0,
- "allwinner,drive",
- 0);
- drive = min(drive, 3);
- }
-
- if (fdt_get_property(fdt, offset, "bias-disable", NULL))
- pull = 0;
- else if (fdt_get_property(fdt, offset, "bias-pull-up", NULL))
- pull = 1;
- else if (fdt_get_property(fdt, offset, "bias-pull-down", NULL))
- pull = 2;
- else
- pull = fdt_getprop_u32_default_node(fdt, offset, 0,
- "allwinner,pull",
- 0);
- pull = min(pull, 2);
-
- for (i = 0; ; i++) {
- pin_name = fdt_stringlist_get(fdt, offset,
- "pins", i, NULL);
- if (!pin_name) {
- pin_name = fdt_stringlist_get(fdt, offset,
- "allwinner,pins",
- i, NULL);
- if (!pin_name)
- break;
- }
-
- pin = sunxi_name_to_gpio(pin_name);
- if (pin < 0)
- break;
-
- if (IS_ENABLED(CONFIG_MACH_SUN50I) ||
- IS_ENABLED(CONFIG_SUN50I_GEN_H6))
- sunxi_gpio_set_cfgpin(pin, SUN50I_GPC_SPI0);
- else
- sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0);
- sunxi_gpio_set_drv(pin, drive);
- sunxi_gpio_set_pull(pin, pull);
- }
- }
- return 0;
-}
-
static inline int sun4i_spi_set_clock(struct udevice *dev, bool enable)
{
struct sun4i_spi_priv *priv = dev_get_priv(dev);
@@ -507,8 +425,6 @@ static int sun4i_spi_probe(struct udevice *bus)
return ret;
}
- sun4i_spi_parse_pins(bus);
-
priv->variant = plat->variant;
priv->base = plat->base;
priv->freq = plat->max_hz;
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index 89131426542..8fad59b81aa 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -96,6 +96,14 @@ config ATMEL_PIT_TIMER
it is designed to offer maximum accuracy and efficient management,
even for systems with long response time.
+config ATMEL_TCB_TIMER
+ bool "Atmel timer counter support"
+ depends on TIMER
+ depends on ARCH_AT91
+ help
+ Select this to enable the use of the timer counter as a monotonic
+ counter.
+
config CADENCE_TTC_TIMER
bool "Cadence TTC (Triple Timer Counter)"
depends on TIMER
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
index e2bd530eb04..58da6c1e846 100644
--- a/drivers/timer/Makefile
+++ b/drivers/timer/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_ARC_TIMER) += arc_timer.o
obj-$(CONFIG_AST_TIMER) += ast_timer.o
obj-$(CONFIG_ATCPIT100_TIMER) += atcpit100_timer.o
obj-$(CONFIG_ATMEL_PIT_TIMER) += atmel_pit_timer.o
+obj-$(CONFIG_ATMEL_TCB_TIMER) += atmel_tcb_timer.o
obj-$(CONFIG_CADENCE_TTC_TIMER) += cadence-ttc.o
obj-$(CONFIG_DESIGNWARE_APB_TIMER) += dw-apb-timer.o
obj-$(CONFIG_MPC83XX_TIMER) += mpc83xx_timer.o
diff --git a/drivers/timer/atmel_tcb_timer.c b/drivers/timer/atmel_tcb_timer.c
new file mode 100644
index 00000000000..8c17987c7d7
--- /dev/null
+++ b/drivers/timer/atmel_tcb_timer.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 Microchip Corporation
+ *
+ * Author: Clément Léger <clement.leger@bootlin.com>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <timer.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+
+#define TCB_CHAN(chan) ((chan) * 0x40)
+
+#define TCB_CCR(chan) (0x0 + TCB_CHAN(chan))
+#define TCB_CCR_CLKEN (1 << 0)
+
+#define TCB_CMR(chan) (0x4 + TCB_CHAN(chan))
+#define TCB_CMR_WAVE (1 << 15)
+#define TCB_CMR_TIMER_CLOCK2 1
+#define TCB_CMR_XC1 6
+#define TCB_CMR_ACPA_SET (1 << 16)
+#define TCB_CMR_ACPC_CLEAR (2 << 18)
+
+#define TCB_CV(chan) (0x10 + TCB_CHAN(chan))
+
+#define TCB_RA(chan) (0x14 + TCB_CHAN(chan))
+#define TCB_RC(chan) (0x1c + TCB_CHAN(chan))
+
+#define TCB_IDR(chan) (0x28 + TCB_CHAN(chan))
+
+#define TCB_BCR 0xc0
+#define TCB_BCR_SYNC (1 << 0)
+
+#define TCB_BMR 0xc4
+#define TCB_BMR_TC1XC1S_TIOA0 (2 << 2)
+
+#define TCB_WPMR 0xe4
+#define TCB_WPMR_WAKEY 0x54494d
+
+#define TCB_CLK_DIVISOR 8
+struct atmel_tcb_plat {
+ void __iomem *base;
+};
+
+static u64 atmel_tcb_get_count(struct udevice *dev)
+{
+ struct atmel_tcb_plat *plat = dev_get_plat(dev);
+ u64 cv0 = 0;
+ u64 cv1 = 0;
+
+ do {
+ cv1 = readl(plat->base + TCB_CV(1));
+ cv0 = readl(plat->base + TCB_CV(0));
+ } while (readl(plat->base + TCB_CV(1)) != cv1);
+
+ cv0 |= cv1 << 32;
+
+ return cv0;
+}
+
+static void atmel_tcb_configure(void __iomem *base)
+{
+ /* Disable write protection */
+ writel(TCB_WPMR_WAKEY, base + TCB_WPMR);
+
+ /* Disable all irqs for both channel 0 & 1 */
+ writel(0xff, base + TCB_IDR(0));
+ writel(0xff, base + TCB_IDR(1));
+
+ /*
+ * In order to avoid wrapping, use a 64 bit counter by chaining
+ * two channels.
+ * Channel 0 is configured to generate a clock on TIOA0 which is cleared
+ * when reaching 0x80000000 and set when reaching 0.
+ */
+ writel(TCB_CMR_TIMER_CLOCK2 | TCB_CMR_WAVE | TCB_CMR_ACPA_SET
+ | TCB_CMR_ACPC_CLEAR, base + TCB_CMR(0));
+ writel(0x80000000, base + TCB_RC(0));
+ writel(0x1, base + TCB_RA(0));
+ writel(TCB_CCR_CLKEN, base + TCB_CCR(0));
+
+ /* Channel 1 is configured to use TIOA0 as input */
+ writel(TCB_CMR_XC1 | TCB_CMR_WAVE, base + TCB_CMR(1));
+ writel(TCB_CCR_CLKEN, base + TCB_CCR(1));
+
+ /* Set XC1 input to be TIOA0 (ie output of Channel 0) */
+ writel(TCB_BMR_TC1XC1S_TIOA0, base + TCB_BMR);
+
+ /* Sync & start all timers */
+ writel(TCB_BCR_SYNC, base + TCB_BCR);
+}
+
+static int atmel_tcb_probe(struct udevice *dev)
+{
+ struct atmel_tcb_plat *plat = dev_get_plat(dev);
+ struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct clk clk;
+ ulong clk_rate;
+ int ret;
+
+ if (!device_is_compatible(dev->parent, "atmel,sama5d2-tcb"))
+ return -EINVAL;
+
+ /* Currently, we only support channel 0 and 1 to be chained */
+ if (dev_read_addr_index(dev, 0) != 0 &&
+ dev_read_addr_index(dev, 1) != 1) {
+ printf("Error: only chained timers 0 and 1 are supported\n");
+ return -EINVAL;
+ }
+
+ ret = clk_get_by_name(dev->parent, "t0_clk", &clk);
+ if (ret)
+ return -EINVAL;
+
+ ret = clk_enable(&clk);
+ if (ret)
+ return ret;
+
+ clk_rate = clk_get_rate(&clk);
+ if (!clk_rate) {
+ clk_disable(&clk);
+ return -EINVAL;
+ }
+
+ uc_priv->clock_rate = clk_rate / TCB_CLK_DIVISOR;
+
+ atmel_tcb_configure(plat->base);
+
+ return 0;
+}
+
+static int atmel_tcb_of_to_plat(struct udevice *dev)
+{
+ struct atmel_tcb_plat *plat = dev_get_plat(dev);
+
+ plat->base = dev_read_addr_ptr(dev->parent);
+
+ return 0;
+}
+
+static const struct timer_ops atmel_tcb_ops = {
+ .get_count = atmel_tcb_get_count,
+};
+
+static const struct udevice_id atmel_tcb_ids[] = {
+ { .compatible = "atmel,tcb-timer" },
+ { }
+};
+
+U_BOOT_DRIVER(atmel_tcb) = {
+ .name = "atmel_tcb",
+ .id = UCLASS_TIMER,
+ .of_match = atmel_tcb_ids,
+ .of_to_plat = atmel_tcb_of_to_plat,
+ .plat_auto = sizeof(struct atmel_tcb_plat),
+ .probe = atmel_tcb_probe,
+ .ops = &atmel_tcb_ops,
+};
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index 9ae032e9c2d..01e8af5ac67 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -407,7 +407,8 @@ static int video_post_probe(struct udevice *dev)
return ret;
}
- if (IS_ENABLED(CONFIG_VIDEO_LOGO) && !plat->hide_logo) {
+ if (IS_ENABLED(CONFIG_VIDEO_LOGO) &&
+ !IS_ENABLED(CONFIG_SPLASH_SCREEN) && !plat->hide_logo) {
ret = show_splash(dev);
if (ret) {
log_debug("Cannot show splash screen\n");