"Das U-Boot" Source Tree
at master 80 lines 1.9 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2020 Sean Anderson 4 */ 5 6#include <dm.h> 7#include <regmap.h> 8#include <reset.h> 9#include <reset-uclass.h> 10#include <syscon.h> 11#include <linux/bitops.h> 12#include <linux/err.h> 13 14struct syscon_reset_priv { 15 struct regmap *regmap; 16 uint offset; 17 uint mask; 18 bool assert_high; 19}; 20 21static int syscon_reset_request(struct reset_ctl *rst) 22{ 23 struct syscon_reset_priv *priv = dev_get_priv(rst->dev); 24 25 if (BIT(rst->id) & priv->mask) 26 return 0; 27 else 28 return -EINVAL; 29} 30 31static int syscon_reset_assert(struct reset_ctl *rst) 32{ 33 struct syscon_reset_priv *priv = dev_get_priv(rst->dev); 34 35 return regmap_update_bits(priv->regmap, priv->offset, BIT(rst->id), 36 priv->assert_high ? BIT(rst->id) : 0); 37} 38 39static int syscon_reset_deassert(struct reset_ctl *rst) 40{ 41 struct syscon_reset_priv *priv = dev_get_priv(rst->dev); 42 43 return regmap_update_bits(priv->regmap, priv->offset, BIT(rst->id), 44 priv->assert_high ? 0 : BIT(rst->id)); 45} 46 47static const struct reset_ops syscon_reset_ops = { 48 .request = syscon_reset_request, 49 .rst_assert = syscon_reset_assert, 50 .rst_deassert = syscon_reset_deassert, 51}; 52 53int syscon_reset_probe(struct udevice *dev) 54{ 55 struct syscon_reset_priv *priv = dev_get_priv(dev); 56 57 priv->regmap = syscon_regmap_lookup_by_phandle(dev, "regmap"); 58 if (IS_ERR(priv->regmap)) 59 return -ENODEV; 60 61 priv->offset = dev_read_u32_default(dev, "offset", 0); 62 priv->mask = dev_read_u32_default(dev, "mask", 0); 63 priv->assert_high = dev_read_u32_default(dev, "assert-high", true); 64 65 return 0; 66} 67 68static const struct udevice_id syscon_reset_ids[] = { 69 { .compatible = "syscon-reset" }, 70 { }, 71}; 72 73U_BOOT_DRIVER(syscon_reset) = { 74 .name = "syscon_reset", 75 .id = UCLASS_RESET, 76 .of_match = syscon_reset_ids, 77 .probe = syscon_reset_probe, 78 .priv_auto = sizeof(struct syscon_reset_priv), 79 .ops = &syscon_reset_ops, 80};