mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-04 05:50:17 +00: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)
 | 
						|
};
 |