1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com> 4 * 5 * Derived from linux/drivers/power/reset/syscon-reboot.c: 6 * Copyright (C) 2013, Applied Micro Circuits Corporation 7 * Author: Feng Kan <fkan@apm.com> 8 */ 9 10 #include <common.h> 11 #include <dm.h> 12 #include <errno.h> 13 #include <regmap.h> 14 #include <sysreset.h> 15 #include <syscon.h> 16 17 struct syscon_reboot_priv { 18 struct regmap *regmap; 19 unsigned int offset; 20 unsigned int mask; 21 }; 22 23 static int syscon_reboot_request(struct udevice *dev, enum sysreset_t type) 24 { 25 struct syscon_reboot_priv *priv = dev_get_priv(dev); 26 27 regmap_write(priv->regmap, priv->offset, priv->mask); 28 29 return -EINPROGRESS; 30 } 31 32 static struct sysreset_ops syscon_reboot_ops = { 33 .request = syscon_reboot_request, 34 }; 35 36 int syscon_reboot_probe(struct udevice *dev) 37 { 38 struct syscon_reboot_priv *priv = dev_get_priv(dev); 39 int err; 40 u32 phandle; 41 ofnode node; 42 43 err = ofnode_read_u32(dev_ofnode(dev), "regmap", &phandle); 44 if (err) 45 return err; 46 47 node = ofnode_get_by_phandle(phandle); 48 if (!ofnode_valid(node)) 49 return -EINVAL; 50 51 priv->regmap = syscon_node_to_regmap(node); 52 if (!priv->regmap) { 53 pr_err("unable to find regmap\n"); 54 return -ENODEV; 55 } 56 57 priv->offset = dev_read_u32_default(dev, "offset", 0); 58 priv->mask = dev_read_u32_default(dev, "mask", 0); 59 60 return 0; 61 } 62 63 static const struct udevice_id syscon_reboot_ids[] = { 64 { .compatible = "syscon-reboot" }, 65 { /* sentinel */ } 66 }; 67 68 U_BOOT_DRIVER(syscon_reboot) = { 69 .name = "syscon_reboot", 70 .id = UCLASS_SYSRESET, 71 .of_match = syscon_reboot_ids, 72 .probe = syscon_reboot_probe, 73 .priv_auto_alloc_size = sizeof(struct syscon_reboot_priv), 74 .ops = &syscon_reboot_ops, 75 }; 76