diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig index 8bdc0944896..e6b05dc3f7e 100644 --- a/drivers/clk/sunxi/Kconfig +++ b/drivers/clk/sunxi/Kconfig @@ -39,11 +39,20 @@ config CLK_SUN6I_A31 on Allwinner A31/A31s SoC. config CLK_SUN6I_A31_R - bool "Clock driver for Allwinner A31 generation PRCM" + bool "Clock driver for Allwinner A31 generation PRCM (CCU)" default SUNXI_GEN_SUN6I help This enables common clock driver support for the PRCM - in Allwinner A31/A31s/A23/A33/A83T/H3/A64/H5 SoCs. + in Allwinner A31/A31s/A23/A33/A83T/H3/A64/H5 SoCs using + the CCU binding. + +config CLK_SUN6I_PRCM + bool "Clock driver for Allwinner A31 generation PRCM (legacy)" + default MACH_SUN6I || MACH_SUN8I_A23 || MACH_SUN8I_A33 + help + This enables common clock driver support for the PRCM + in Allwinner A31/A31s/A23/A33 SoCs using the legacy PRCM + MFD binding. config CLK_SUN8I_A23 bool "Clock driver for Allwinner A23/A33" diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile index 90a277489dc..a086f09ffa7 100644 --- a/drivers/clk/sunxi/Makefile +++ b/drivers/clk/sunxi/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_CLK_SUN4I_A10) += clk_a10.o obj-$(CONFIG_CLK_SUN5I_A10S) += clk_a10s.o obj-$(CONFIG_CLK_SUN6I_A31) += clk_a31.o obj-$(CONFIG_CLK_SUN6I_A31_R) += clk_a31_r.o +obj-$(CONFIG_CLK_SUN6I_PRCM) += clk_sun6i_prcm.o obj-$(CONFIG_CLK_SUN8I_A23) += clk_a23.o obj-$(CONFIG_CLK_SUN8I_A83T) += clk_a83t.o obj-$(CONFIG_CLK_SUN8I_R40) += clk_r40.o diff --git a/drivers/clk/sunxi/clk_sun6i_prcm.c b/drivers/clk/sunxi/clk_sun6i_prcm.c new file mode 100644 index 00000000000..488b47e77a7 --- /dev/null +++ b/drivers/clk/sunxi/clk_sun6i_prcm.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022 Samuel Holland + */ + +#include +#include +#include +#include +#include + +struct sun6i_prcm_plat { + void *base; +}; + +static int sun6i_prcm_set_field(struct udevice *dev, uint reg, + u32 mask, bool set) +{ + struct sun6i_prcm_plat *plat = dev_get_plat(dev->parent); + + clrsetbits_le32(plat->base + reg, mask, set ? mask : 0); + + return 0; +} + +static int sun6i_prcm_clk_enable(struct clk *clk) +{ + return sun6i_prcm_set_field(clk->dev, 0x28, BIT(clk->id), true); +} + +static int sun6i_prcm_clk_disable(struct clk *clk) +{ + return sun6i_prcm_set_field(clk->dev, 0x28, BIT(clk->id), false); +} + +static const struct clk_ops sun6i_prcm_clk_ops = { + .enable = sun6i_prcm_clk_enable, + .disable = sun6i_prcm_clk_disable, +}; + +static const struct udevice_id sun6i_prcm_clk_ids[] = { + { .compatible = "allwinner,sun6i-a31-apb0-gates-clk" }, + { .compatible = "allwinner,sun8i-a23-apb0-gates-clk" }, + { } +}; + +U_BOOT_DRIVER(sun6i_prcm_clk) = { + .name = "sun6i_prcm_clk", + .id = UCLASS_CLK, + .of_match = sun6i_prcm_clk_ids, + .ops = &sun6i_prcm_clk_ops, +}; + +static int sun6i_prcm_reset_assert(struct reset_ctl *reset) +{ + return sun6i_prcm_set_field(reset->dev, 0xb0, BIT(reset->id), false); +} + +static int sun6i_prcm_reset_deassert(struct reset_ctl *reset) +{ + return sun6i_prcm_set_field(reset->dev, 0xb0, BIT(reset->id), true); +} + +static const struct reset_ops sun6i_prcm_reset_ops = { + .rst_assert = sun6i_prcm_reset_assert, + .rst_deassert = sun6i_prcm_reset_deassert, +}; + +static const struct udevice_id sun6i_prcm_reset_ids[] = { + { .compatible = "allwinner,sun6i-a31-clock-reset" }, + { } +}; + +U_BOOT_DRIVER(sun6i_prcm_reset) = { + .name = "sun6i_prcm_reset", + .id = UCLASS_RESET, + .of_match = sun6i_prcm_reset_ids, + .ops = &sun6i_prcm_reset_ops, +}; + +static int sun6i_prcm_of_to_plat(struct udevice *dev) +{ + struct sun6i_prcm_plat *plat = dev_get_plat(dev); + + plat->base = dev_read_addr_ptr(dev); + if (!plat->base) + return -ENOMEM; + + return 0; +} + +static const struct udevice_id sun6i_prcm_mfd_ids[] = { + { .compatible = "allwinner,sun6i-a31-prcm" }, + { .compatible = "allwinner,sun8i-a23-prcm" }, + { } +}; + +U_BOOT_DRIVER(sun6i_prcm_mfd) = { + .name = "sun6i_prcm_mfd", + .id = UCLASS_SIMPLE_BUS, + .of_match = sun6i_prcm_mfd_ids, + .of_to_plat = sun6i_prcm_of_to_plat, + .plat_auto = sizeof(struct sun6i_prcm_plat), +};