xref: /rk3399_rockchip-uboot/drivers/core/syscon-uclass.c (revision 10427e2df5a90fdf95a3ef373e36c5dd49ba07ad)
157251285SSimon Glass /*
257251285SSimon Glass  * Copyright (C) 2015 Google, Inc
357251285SSimon Glass  * Written by Simon Glass <sjg@chromium.org>
457251285SSimon Glass  *
557251285SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
657251285SSimon Glass  */
757251285SSimon Glass 
857251285SSimon Glass #include <common.h>
957251285SSimon Glass #include <syscon.h>
1057251285SSimon Glass #include <dm.h>
1157251285SSimon Glass #include <errno.h>
1257251285SSimon Glass #include <regmap.h>
1357251285SSimon Glass #include <dm/device-internal.h>
1457251285SSimon Glass #include <dm/lists.h>
1557251285SSimon Glass #include <dm/root.h>
1657251285SSimon Glass #include <linux/err.h>
1757251285SSimon Glass 
syscon_get_regmap(struct udevice * dev)1857251285SSimon Glass struct regmap *syscon_get_regmap(struct udevice *dev)
1957251285SSimon Glass {
209f4629beSSimon Glass 	struct syscon_uc_info *priv;
2157251285SSimon Glass 
229f4629beSSimon Glass 	if (device_get_uclass_id(dev) != UCLASS_SYSCON)
239f4629beSSimon Glass 		return ERR_PTR(-ENOEXEC);
249f4629beSSimon Glass 	priv = dev_get_uclass_priv(dev);
2557251285SSimon Glass 	return priv->regmap;
2657251285SSimon Glass }
2757251285SSimon Glass 
syscon_pre_probe(struct udevice * dev)2857251285SSimon Glass static int syscon_pre_probe(struct udevice *dev)
2957251285SSimon Glass {
3057251285SSimon Glass 	struct syscon_uc_info *priv = dev_get_uclass_priv(dev);
3157251285SSimon Glass 
3204ecf36bSSimon Glass 	/*
3304ecf36bSSimon Glass 	 * With OF_PLATDATA we really have no way of knowing the format of
3404ecf36bSSimon Glass 	 * the device-specific platform data. So we assume that it starts with
3504ecf36bSSimon Glass 	 * a 'reg' member, and this holds a single address and size. Drivers
3604ecf36bSSimon Glass 	 * using OF_PLATDATA will need to ensure that this is true.
3704ecf36bSSimon Glass 	 */
3804ecf36bSSimon Glass #if CONFIG_IS_ENABLED(OF_PLATDATA)
3904ecf36bSSimon Glass 	struct syscon_base_platdata *plat = dev_get_platdata(dev);
4004ecf36bSSimon Glass 
4104ecf36bSSimon Glass 	return regmap_init_mem_platdata(dev, plat->reg, ARRAY_SIZE(plat->reg),
4204ecf36bSSimon Glass 					&priv->regmap);
4304ecf36bSSimon Glass #else
4457251285SSimon Glass 	return regmap_init_mem(dev, &priv->regmap);
4504ecf36bSSimon Glass #endif
4657251285SSimon Glass }
4757251285SSimon Glass 
syscon_regmap_lookup_by_phandle(struct udevice * dev,const char * name)48*10427e2dSJean-Jacques Hiblot struct regmap *syscon_regmap_lookup_by_phandle(struct udevice *dev,
49*10427e2dSJean-Jacques Hiblot 					       const char *name)
50*10427e2dSJean-Jacques Hiblot {
51*10427e2dSJean-Jacques Hiblot 	struct udevice *syscon;
52*10427e2dSJean-Jacques Hiblot 	struct regmap *r;
53*10427e2dSJean-Jacques Hiblot 	int err;
54*10427e2dSJean-Jacques Hiblot 
55*10427e2dSJean-Jacques Hiblot 	err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
56*10427e2dSJean-Jacques Hiblot 					   name, &syscon);
57*10427e2dSJean-Jacques Hiblot 	if (err)
58*10427e2dSJean-Jacques Hiblot 		return ERR_PTR(err);
59*10427e2dSJean-Jacques Hiblot 
60*10427e2dSJean-Jacques Hiblot 	r = syscon_get_regmap(syscon);
61*10427e2dSJean-Jacques Hiblot 	if (!r)
62*10427e2dSJean-Jacques Hiblot 		return ERR_PTR(-ENODEV);
63*10427e2dSJean-Jacques Hiblot 
64*10427e2dSJean-Jacques Hiblot 	return r;
65*10427e2dSJean-Jacques Hiblot }
66*10427e2dSJean-Jacques Hiblot 
syscon_get_by_driver_data(ulong driver_data,struct udevice ** devp)67ac94b7bcSSimon Glass int syscon_get_by_driver_data(ulong driver_data, struct udevice **devp)
6857251285SSimon Glass {
6957251285SSimon Glass 	struct udevice *dev;
7057251285SSimon Glass 	struct uclass *uc;
7157251285SSimon Glass 	int ret;
7257251285SSimon Glass 
73532f2435SSimon Glass 	*devp = NULL;
7457251285SSimon Glass 	ret = uclass_get(UCLASS_SYSCON, &uc);
7557251285SSimon Glass 	if (ret)
76ac94b7bcSSimon Glass 		return ret;
7757251285SSimon Glass 	uclass_foreach_dev(dev, uc) {
7857251285SSimon Glass 		if (dev->driver_data == driver_data) {
79ac94b7bcSSimon Glass 			*devp = dev;
80ac94b7bcSSimon Glass 			return device_probe(dev);
81ac94b7bcSSimon Glass 		}
82ac94b7bcSSimon Glass 	}
83ac94b7bcSSimon Glass 
84ac94b7bcSSimon Glass 	return -ENODEV;
85ac94b7bcSSimon Glass }
86ac94b7bcSSimon Glass 
syscon_get_regmap_by_driver_data(ulong driver_data)87ac94b7bcSSimon Glass struct regmap *syscon_get_regmap_by_driver_data(ulong driver_data)
88ac94b7bcSSimon Glass {
8957251285SSimon Glass 	struct syscon_uc_info *priv;
90ac94b7bcSSimon Glass 	struct udevice *dev;
9157251285SSimon Glass 	int ret;
9257251285SSimon Glass 
93ac94b7bcSSimon Glass 	ret = syscon_get_by_driver_data(driver_data, &dev);
9457251285SSimon Glass 	if (ret)
9557251285SSimon Glass 		return ERR_PTR(ret);
9657251285SSimon Glass 	priv = dev_get_uclass_priv(dev);
9757251285SSimon Glass 
9857251285SSimon Glass 	return priv->regmap;
9957251285SSimon Glass }
10057251285SSimon Glass 
syscon_get_first_range(ulong driver_data)10157251285SSimon Glass void *syscon_get_first_range(ulong driver_data)
10257251285SSimon Glass {
10357251285SSimon Glass 	struct regmap *map;
10457251285SSimon Glass 
10557251285SSimon Glass 	map = syscon_get_regmap_by_driver_data(driver_data);
10657251285SSimon Glass 	if (IS_ERR(map))
10757251285SSimon Glass 		return map;
10857251285SSimon Glass 	return regmap_get_range(map, 0);
10957251285SSimon Glass }
11057251285SSimon Glass 
11157251285SSimon Glass UCLASS_DRIVER(syscon) = {
11257251285SSimon Glass 	.id		= UCLASS_SYSCON,
11357251285SSimon Glass 	.name		= "syscon",
11457251285SSimon Glass 	.per_device_auto_alloc_size = sizeof(struct syscon_uc_info),
11557251285SSimon Glass 	.pre_probe = syscon_pre_probe,
11657251285SSimon Glass };
1178291bc87SPaul Burton 
1188291bc87SPaul Burton static const struct udevice_id generic_syscon_ids[] = {
1198291bc87SPaul Burton 	{ .compatible = "syscon" },
1208291bc87SPaul Burton 	{ }
1218291bc87SPaul Burton };
1228291bc87SPaul Burton 
1238291bc87SPaul Burton U_BOOT_DRIVER(generic_syscon) = {
1248291bc87SPaul Burton 	.name	= "syscon",
1258291bc87SPaul Burton 	.id	= UCLASS_SYSCON,
126745fb9c2SSimon Glass #if !CONFIG_IS_ENABLED(OF_PLATDATA)
127745fb9c2SSimon Glass 	.bind           = dm_scan_fdt_dev,
128745fb9c2SSimon Glass #endif
1298291bc87SPaul Burton 	.of_match = generic_syscon_ids,
1308291bc87SPaul Burton };
131