1 /* 2 * Copyright (C) 2015 Google, Inc 3 * Written by Simon Glass <sjg@chromium.org> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <syscon.h> 10 #include <dm.h> 11 #include <errno.h> 12 #include <regmap.h> 13 #include <dm/device-internal.h> 14 #include <dm/lists.h> 15 #include <dm/root.h> 16 #include <linux/err.h> 17 18 struct regmap *syscon_get_regmap(struct udevice *dev) 19 { 20 struct syscon_uc_info *priv; 21 22 if (device_get_uclass_id(dev) != UCLASS_SYSCON) 23 return ERR_PTR(-ENOEXEC); 24 priv = dev_get_uclass_priv(dev); 25 return priv->regmap; 26 } 27 28 static int syscon_pre_probe(struct udevice *dev) 29 { 30 struct syscon_uc_info *priv = dev_get_uclass_priv(dev); 31 32 return regmap_init_mem(dev, &priv->regmap); 33 } 34 35 struct regmap *syscon_get_regmap_by_driver_data(ulong driver_data) 36 { 37 struct udevice *dev; 38 struct uclass *uc; 39 int ret; 40 41 ret = uclass_get(UCLASS_SYSCON, &uc); 42 if (ret) 43 return ERR_PTR(ret); 44 uclass_foreach_dev(dev, uc) { 45 if (dev->driver_data == driver_data) { 46 struct syscon_uc_info *priv; 47 int ret; 48 49 ret = device_probe(dev); 50 if (ret) 51 return ERR_PTR(ret); 52 priv = dev_get_uclass_priv(dev); 53 54 return priv->regmap; 55 } 56 } 57 58 return ERR_PTR(-ENODEV); 59 } 60 61 void *syscon_get_first_range(ulong driver_data) 62 { 63 struct regmap *map; 64 65 map = syscon_get_regmap_by_driver_data(driver_data); 66 if (IS_ERR(map)) 67 return map; 68 return regmap_get_range(map, 0); 69 } 70 71 UCLASS_DRIVER(syscon) = { 72 .id = UCLASS_SYSCON, 73 .name = "syscon", 74 .per_device_auto_alloc_size = sizeof(struct syscon_uc_info), 75 .pre_probe = syscon_pre_probe, 76 }; 77