On 22/11/20 9:41 pm, Dario Binacchi wrote: > We can handle the sysc interconnect target module in a generic way for > many TI SoCs. Initially let's just enable domain clocks before the > children are probed. > > The code is loosely based on the drivers/bus/ti-sysc.c of the Linux > kernel version 5.9-rc7. > For DT binding details see: > - Documentation/devicetree/bindings/bus/ti-sysc.txt > > Signed-off-by: Dario Binacchi <[email protected]> > > --- > > (no changes since v4) > > Changes in v4: > - Include device_compat.h header for dev_xxx macros. > > arch/arm/Kconfig | 1 + > drivers/bus/Kconfig | 7 ++ > drivers/bus/Makefile | 1 + > drivers/bus/ti-sysc.c | 166 ++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 175 insertions(+) > create mode 100644 drivers/bus/ti-sysc.c > > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig > index 5903c09370..4cc2c242d1 100644 > --- a/arch/arm/Kconfig > +++ b/arch/arm/Kconfig > @@ -799,6 +799,7 @@ config ARCH_OMAP2PLUS > select SPL_BOARD_INIT if SPL > select SPL_STACK_R if SPL > select SUPPORT_SPL > + select TI_SYSC Not all OMAP2 platform need TI_SYSC. With this change nokia builds are failing. I will make this as imply and disable it in Nokia config. Thanks and regards, Lokesh > imply FIT > > config ARCH_MESON > diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig > index 07a33c6287..733bec5a56 100644 > --- a/drivers/bus/Kconfig > +++ b/drivers/bus/Kconfig > @@ -5,6 +5,13 @@ > > menu "Bus devices" > > +config TI_SYSC > + bool "TI sysc interconnect target module driver" > + depends on ARCH_OMAP2PLUS > + help > + Generic driver for Texas Instruments interconnect target module > + found on many TI SoCs. > + > config UNIPHIER_SYSTEM_BUS > bool "UniPhier System Bus driver" > depends on ARCH_UNIPHIER > diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile > index 0b97fc1f8b..875bb4ed42 100644 > --- a/drivers/bus/Makefile > +++ b/drivers/bus/Makefile > @@ -3,4 +3,5 @@ > # Makefile for the bus drivers. > # > > +obj-$(CONFIG_TI_SYSC) += ti-sysc.o > obj-$(CONFIG_UNIPHIER_SYSTEM_BUS) += uniphier-system-bus.o > diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c > new file mode 100644 > index 0000000000..65974a70a6 > --- /dev/null > +++ b/drivers/bus/ti-sysc.c > @@ -0,0 +1,166 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Texas Instruments sysc interconnect target driver > + * > + * Copyright (C) 2020 Dario Binacchi <[email protected]> > + */ > + > +#include <common.h> > +#include <clk.h> > +#include <dm.h> > +#include <dm/device_compat.h> > + > +enum ti_sysc_clocks { > + TI_SYSC_FCK, > + TI_SYSC_ICK, > + TI_SYSC_MAX_CLOCKS, > +}; > + > +static const char *const clock_names[] = {"fck", "ick"}; > + > +struct ti_sysc_priv { > + int clocks_count; > + struct clk clocks[TI_SYSC_MAX_CLOCKS]; > +}; > + > +static const struct udevice_id ti_sysc_ids[] = { > + {.compatible = "ti,sysc-omap2"}, > + {.compatible = "ti,sysc-omap4"}, > + {.compatible = "ti,sysc-omap4-simple"}, > + {.compatible = "ti,sysc-omap3430-sr"}, > + {.compatible = "ti,sysc-omap3630-sr"}, > + {.compatible = "ti,sysc-omap4-sr"}, > + {.compatible = "ti,sysc-omap3-sham"}, > + {.compatible = "ti,sysc-omap-aes"}, > + {.compatible = "ti,sysc-mcasp"}, > + {.compatible = "ti,sysc-usb-host-fs"}, > + {} > +}; > + > +static int ti_sysc_get_one_clock(struct udevice *dev, enum ti_sysc_clocks > index) > +{ > + struct ti_sysc_priv *priv = dev_get_priv(dev); > + const char *name; > + int err; > + > + switch (index) { > + case TI_SYSC_FCK: > + break; > + case TI_SYSC_ICK: > + break; > + default: > + return -EINVAL; > + } > + > + name = clock_names[index]; > + > + err = clk_get_by_name(dev, name, &priv->clocks[index]); > + if (err) { > + if (err == -ENODATA) > + return 0; > + > + dev_err(dev, "failed to get %s clock\n", name); > + return err; > + } > + > + return 0; > +} > + > +static int ti_sysc_put_clocks(struct udevice *dev) > +{ > + struct ti_sysc_priv *priv = dev_get_priv(dev); > + int err; > + > + err = clk_release_all(priv->clocks, priv->clocks_count); > + if (err) > + dev_err(dev, "failed to release all clocks\n"); > + > + return err; > +} > + > +static int ti_sysc_get_clocks(struct udevice *dev) > +{ > + struct ti_sysc_priv *priv = dev_get_priv(dev); > + int i, err; > + > + for (i = 0; i < TI_SYSC_MAX_CLOCKS; i++) { > + err = ti_sysc_get_one_clock(dev, i); > + if (!err) > + priv->clocks_count++; > + else if (err != -ENOENT) > + return err; > + } > + > + return 0; > +} > + > +static int ti_sysc_child_post_remove(struct udevice *dev) > +{ > + struct ti_sysc_priv *priv = dev_get_priv(dev->parent); > + int i, err; > + > + for (i = 0; i < priv->clocks_count; i++) { > + err = clk_disable(&priv->clocks[i]); > + if (err) { > + dev_err(dev->parent, "failed to disable %s clock\n", > + clock_names[i]); > + return err; > + } > + } > + > + return 0; > +} > + > +static int ti_sysc_child_pre_probe(struct udevice *dev) > +{ > + struct ti_sysc_priv *priv = dev_get_priv(dev->parent); > + int i, err; > + > + for (i = 0; i < priv->clocks_count; i++) { > + err = clk_enable(&priv->clocks[i]); > + if (err) { > + dev_err(dev->parent, "failed to enable %s clock\n", > + clock_names[i]); > + return err; > + } > + } > + > + return 0; > +} > + > +static int ti_sysc_remove(struct udevice *dev) > +{ > + return ti_sysc_put_clocks(dev); > +} > + > +static int ti_sysc_probe(struct udevice *dev) > +{ > + int err; > + > + err = ti_sysc_get_clocks(dev); > + if (err) > + goto clocks_err; > + > + return 0; > + > +clocks_err: > + ti_sysc_put_clocks(dev); > + return err; > +} > + > +UCLASS_DRIVER(ti_sysc) = { > + .id = UCLASS_SIMPLE_BUS, > + .name = "ti_sysc", > + .post_bind = dm_scan_fdt_dev > +}; > + > +U_BOOT_DRIVER(ti_sysc) = { > + .name = "ti_sysc", > + .id = UCLASS_SIMPLE_BUS, > + .of_match = ti_sysc_ids, > + .probe = ti_sysc_probe, > + .remove = ti_sysc_remove, > + .child_pre_probe = ti_sysc_child_pre_probe, > + .child_post_remove = ti_sysc_child_post_remove, > + .priv_auto_alloc_size = sizeof(struct ti_sysc_priv) > +}; >

