mirror of
				https://source.denx.de/u-boot/u-boot.git
				synced 2025-10-31 00:11:51 +01:00 
			
		
		
		
	The module defines a duplicate uclass driver for UCLASS_SIMPLE_BUS, but it is not allowed. This breaks of-platdata and makes the result non-deterministic. The driver does not need to be an uclass driver, so lets remove it. I had turned it into an uclass driver because I thought wrongly it had to call the dm_scan_fdt_dev routine to work properly, but some tests on the board have shown otherwise. Signed-off-by: Dario Binacchi <dariobin@libero.it> Reviewed-by: Simon Glass <sjg@chromium.org>
		
			
				
	
	
		
			161 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			161 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0+
 | |
| /*
 | |
|  * Texas Instruments sysc interconnect target driver
 | |
|  *
 | |
|  * Copyright (C) 2020 Dario Binacchi <dariobin@libero.it>
 | |
|  */
 | |
| 
 | |
| #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;
 | |
| }
 | |
| 
 | |
| 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 = sizeof(struct ti_sysc_priv)
 | |
| };
 |