reset-oxnas.c (2785B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Oxford Semiconductor Reset Controller driver 4 * 5 * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com> 6 * Copyright (C) 2014 Ma Haijun <mahaijuns@gmail.com> 7 * Copyright (C) 2009 Oxford Semiconductor Ltd 8 */ 9#include <linux/err.h> 10#include <linux/init.h> 11#include <linux/of.h> 12#include <linux/platform_device.h> 13#include <linux/reset-controller.h> 14#include <linux/slab.h> 15#include <linux/delay.h> 16#include <linux/types.h> 17#include <linux/regmap.h> 18#include <linux/mfd/syscon.h> 19 20/* Regmap offsets */ 21#define RST_SET_REGOFFSET 0x34 22#define RST_CLR_REGOFFSET 0x38 23 24struct oxnas_reset { 25 struct regmap *regmap; 26 struct reset_controller_dev rcdev; 27}; 28 29static int oxnas_reset_reset(struct reset_controller_dev *rcdev, 30 unsigned long id) 31{ 32 struct oxnas_reset *data = 33 container_of(rcdev, struct oxnas_reset, rcdev); 34 35 regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id)); 36 msleep(50); 37 regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id)); 38 39 return 0; 40} 41 42static int oxnas_reset_assert(struct reset_controller_dev *rcdev, 43 unsigned long id) 44{ 45 struct oxnas_reset *data = 46 container_of(rcdev, struct oxnas_reset, rcdev); 47 48 regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id)); 49 50 return 0; 51} 52 53static int oxnas_reset_deassert(struct reset_controller_dev *rcdev, 54 unsigned long id) 55{ 56 struct oxnas_reset *data = 57 container_of(rcdev, struct oxnas_reset, rcdev); 58 59 regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id)); 60 61 return 0; 62} 63 64static const struct reset_control_ops oxnas_reset_ops = { 65 .reset = oxnas_reset_reset, 66 .assert = oxnas_reset_assert, 67 .deassert = oxnas_reset_deassert, 68}; 69 70static const struct of_device_id oxnas_reset_dt_ids[] = { 71 { .compatible = "oxsemi,ox810se-reset", }, 72 { .compatible = "oxsemi,ox820-reset", }, 73 { /* sentinel */ }, 74}; 75 76static int oxnas_reset_probe(struct platform_device *pdev) 77{ 78 struct oxnas_reset *data; 79 struct device *parent; 80 81 parent = pdev->dev.parent; 82 if (!parent) { 83 dev_err(&pdev->dev, "no parent\n"); 84 return -ENODEV; 85 } 86 87 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 88 if (!data) 89 return -ENOMEM; 90 91 data->regmap = syscon_node_to_regmap(parent->of_node); 92 if (IS_ERR(data->regmap)) { 93 dev_err(&pdev->dev, "failed to get parent regmap\n"); 94 return PTR_ERR(data->regmap); 95 } 96 97 platform_set_drvdata(pdev, data); 98 99 data->rcdev.owner = THIS_MODULE; 100 data->rcdev.nr_resets = 32; 101 data->rcdev.ops = &oxnas_reset_ops; 102 data->rcdev.of_node = pdev->dev.of_node; 103 104 return devm_reset_controller_register(&pdev->dev, &data->rcdev); 105} 106 107static struct platform_driver oxnas_reset_driver = { 108 .probe = oxnas_reset_probe, 109 .driver = { 110 .name = "oxnas-reset", 111 .of_match_table = oxnas_reset_dt_ids, 112 }, 113}; 114builtin_platform_driver(oxnas_reset_driver);