diff options
Diffstat (limited to 'drivers')
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"); |