u-boot/include/syscon.h

93 lines
2.7 KiB
C
Raw Normal View History

/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (c) 2015 Google, Inc
* Written by Simon Glass <sjg@chromium.org>
*/
#ifndef __SYSCON_H
#define __SYSCON_H
syscon: add Linux-compatible syscon API The syscon implementation in U-Boot is different from that in Linux. Thus, DT files imported from Linux do not work for U-Boot. In U-Boot driver model, each node is bound to a dedicated driver that is the most compatible to it. This design gets along with the concept of DT, and the syscon in Linux originally worked like that. However, Linux commit bdb0066df96e ("mfd: syscon: Decouple syscon interface from platform devices") changed the behavior because it is useful to let a device bind to another driver, but still work as a syscon provider. That change had happened before U-Boot initially supported the syscon driver by commit 6f98b7504f70 ("dm: Add support for generic system controllers (syscon)"). So, the U-Boot's syscon works differently from the beginning. I'd say this is mis-implementation given that DT is not oriented to a particular project, but Linux is the canon of DT in practice. The problem typically arises in the combination of "syscon" and "simple-mfd" compatibles. In Linux, they are orthogonal, i.e., the order between "syscon" and "simple-mfd" does not matter at all. Assume the following compatible. compatible = "foo,bar-syscon", "syscon", "simple-mfd"; In U-Boot, this device node is bound to the syscon driver (driver/core/syscon-uclass.c) since the "syscon" is found to be the most compatible. Then, syscon_get_regmap() succeeds. However, compatible = "foo,bar-syscon", "simple-mfd", "syscon"; does not work because this node is bound to the simple-bus driver (drivers/core/simple-bus.c) in favor of "simple-mfd" compatible. The compatible string "syscon" is just dismissed. Moreover, compatible = "foo,bar-syscon", "syscon"; works like the first case because the syscon driver populates the child devices. This is wrong because populating children is the job of "simple-mfd" (or "simple-bus"). This commit ports syscon_node_to_regmap() from Linux. This API does not require the given node to be bound to a driver in any way. Reported-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2018-04-19 03:14:04 +00:00
#include <dm/ofnode.h>
#include <fdtdec.h>
/**
* struct syscon_uc_info - Information stored by the syscon UCLASS_UCLASS
*
* @regmap: Register map for this controller
*/
struct syscon_uc_info {
struct regmap *regmap;
};
/* So far there are no ops so this is a placeholder */
struct syscon_ops {
};
#define syscon_get_ops(dev) ((struct syscon_ops *)(dev)->driver->ops)
/**
* syscon_get_regmap() - Get access to a register map
*
* @dev: Device to check (UCLASS_SCON)
* @info: Returns regmap for the device
* Return: 0 if OK, -ve on error
*/
struct regmap *syscon_get_regmap(struct udevice *dev);
/**
* syscon_get_regmap_by_driver_data() - Look up a controller by its ID
*
* Each system controller can be accessed by its driver data, which is
* assumed to be unique through the scope of all system controllers that
* are in use. This function looks up the controller given this driver data.
*
* @driver_data: Driver data value to look up
* @devp: Returns the controller correponding to @driver_data
* Return: 0 on success, -ENODEV if the ID was not found, or other -ve error
* code
*/
int syscon_get_by_driver_data(ulong driver_data, struct udevice **devp);
/**
* syscon_get_regmap_by_driver_data() - Look up a controller by its ID
*
* Each system controller can be accessed by its driver data, which is
* assumed to be unique through the scope of all system controllers that
* are in use. This function looks up the regmap given this driver data.
*
* @driver_data: Driver data value to look up
* Return: register map correponding to @driver_data, or -ve error code
*/
struct regmap *syscon_get_regmap_by_driver_data(ulong driver_data);
/**
* syscon_regmap_lookup_by_phandle() - Look up a controller by a phandle
*
* This operates by looking up the given name in the device (device
* tree property) of the device using the system controller.
*
* @dev: Device using the system controller
* @name: Name of property referring to the system controller
* Return: A pointer to the regmap if found, ERR_PTR(-ve) on error
*/
struct regmap *syscon_regmap_lookup_by_phandle(struct udevice *dev,
const char *name);
/**
* syscon_get_first_range() - get the first memory range from a syscon regmap
*
* @driver_data: Driver data value to look up
* Return: first region of register map correponding to @driver_data, or
* -ve error code
*/
void *syscon_get_first_range(ulong driver_data);
syscon: add Linux-compatible syscon API The syscon implementation in U-Boot is different from that in Linux. Thus, DT files imported from Linux do not work for U-Boot. In U-Boot driver model, each node is bound to a dedicated driver that is the most compatible to it. This design gets along with the concept of DT, and the syscon in Linux originally worked like that. However, Linux commit bdb0066df96e ("mfd: syscon: Decouple syscon interface from platform devices") changed the behavior because it is useful to let a device bind to another driver, but still work as a syscon provider. That change had happened before U-Boot initially supported the syscon driver by commit 6f98b7504f70 ("dm: Add support for generic system controllers (syscon)"). So, the U-Boot's syscon works differently from the beginning. I'd say this is mis-implementation given that DT is not oriented to a particular project, but Linux is the canon of DT in practice. The problem typically arises in the combination of "syscon" and "simple-mfd" compatibles. In Linux, they are orthogonal, i.e., the order between "syscon" and "simple-mfd" does not matter at all. Assume the following compatible. compatible = "foo,bar-syscon", "syscon", "simple-mfd"; In U-Boot, this device node is bound to the syscon driver (driver/core/syscon-uclass.c) since the "syscon" is found to be the most compatible. Then, syscon_get_regmap() succeeds. However, compatible = "foo,bar-syscon", "simple-mfd", "syscon"; does not work because this node is bound to the simple-bus driver (drivers/core/simple-bus.c) in favor of "simple-mfd" compatible. The compatible string "syscon" is just dismissed. Moreover, compatible = "foo,bar-syscon", "syscon"; works like the first case because the syscon driver populates the child devices. This is wrong because populating children is the job of "simple-mfd" (or "simple-bus"). This commit ports syscon_node_to_regmap() from Linux. This API does not require the given node to be bound to a driver in any way. Reported-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2018-04-19 03:14:04 +00:00
/**
* syscon_node_to_regmap - get regmap from syscon
*
* @node: Device node of syscon
*/
struct regmap *syscon_node_to_regmap(ofnode node);
#endif