Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.10-rc2 157 lines 4.1 kB view raw
1/* 2 * Hisilicon Hi6220 reset controller driver 3 * 4 * Copyright (c) 2016 Linaro Limited. 5 * Copyright (c) 2015-2016 Hisilicon Limited. 6 * 7 * Author: Feng Chen <puck.chen@hisilicon.com> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 */ 13 14#include <linux/io.h> 15#include <linux/init.h> 16#include <linux/module.h> 17#include <linux/bitops.h> 18#include <linux/of.h> 19#include <linux/of_device.h> 20#include <linux/regmap.h> 21#include <linux/mfd/syscon.h> 22#include <linux/reset-controller.h> 23#include <linux/reset.h> 24#include <linux/platform_device.h> 25 26#define PERIPH_ASSERT_OFFSET 0x300 27#define PERIPH_DEASSERT_OFFSET 0x304 28#define PERIPH_MAX_INDEX 0x509 29 30#define SC_MEDIA_RSTEN 0x052C 31#define SC_MEDIA_RSTDIS 0x0530 32#define MEDIA_MAX_INDEX 8 33 34#define to_reset_data(x) container_of(x, struct hi6220_reset_data, rc_dev) 35 36enum hi6220_reset_ctrl_type { 37 PERIPHERAL, 38 MEDIA, 39}; 40 41struct hi6220_reset_data { 42 struct reset_controller_dev rc_dev; 43 struct regmap *regmap; 44}; 45 46static int hi6220_peripheral_assert(struct reset_controller_dev *rc_dev, 47 unsigned long idx) 48{ 49 struct hi6220_reset_data *data = to_reset_data(rc_dev); 50 struct regmap *regmap = data->regmap; 51 u32 bank = idx >> 8; 52 u32 offset = idx & 0xff; 53 u32 reg = PERIPH_ASSERT_OFFSET + bank * 0x10; 54 55 return regmap_write(regmap, reg, BIT(offset)); 56} 57 58static int hi6220_peripheral_deassert(struct reset_controller_dev *rc_dev, 59 unsigned long idx) 60{ 61 struct hi6220_reset_data *data = to_reset_data(rc_dev); 62 struct regmap *regmap = data->regmap; 63 u32 bank = idx >> 8; 64 u32 offset = idx & 0xff; 65 u32 reg = PERIPH_DEASSERT_OFFSET + bank * 0x10; 66 67 return regmap_write(regmap, reg, BIT(offset)); 68} 69 70static const struct reset_control_ops hi6220_peripheral_reset_ops = { 71 .assert = hi6220_peripheral_assert, 72 .deassert = hi6220_peripheral_deassert, 73}; 74 75static int hi6220_media_assert(struct reset_controller_dev *rc_dev, 76 unsigned long idx) 77{ 78 struct hi6220_reset_data *data = to_reset_data(rc_dev); 79 struct regmap *regmap = data->regmap; 80 81 return regmap_write(regmap, SC_MEDIA_RSTEN, BIT(idx)); 82} 83 84static int hi6220_media_deassert(struct reset_controller_dev *rc_dev, 85 unsigned long idx) 86{ 87 struct hi6220_reset_data *data = to_reset_data(rc_dev); 88 struct regmap *regmap = data->regmap; 89 90 return regmap_write(regmap, SC_MEDIA_RSTDIS, BIT(idx)); 91} 92 93static const struct reset_control_ops hi6220_media_reset_ops = { 94 .assert = hi6220_media_assert, 95 .deassert = hi6220_media_deassert, 96}; 97 98static int hi6220_reset_probe(struct platform_device *pdev) 99{ 100 struct device_node *np = pdev->dev.of_node; 101 struct device *dev = &pdev->dev; 102 enum hi6220_reset_ctrl_type type; 103 struct hi6220_reset_data *data; 104 struct regmap *regmap; 105 106 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 107 if (!data) 108 return -ENOMEM; 109 110 type = (enum hi6220_reset_ctrl_type)of_device_get_match_data(dev); 111 112 regmap = syscon_node_to_regmap(np); 113 if (IS_ERR(regmap)) { 114 dev_err(dev, "failed to get reset controller regmap\n"); 115 return PTR_ERR(regmap); 116 } 117 118 data->regmap = regmap; 119 data->rc_dev.of_node = np; 120 if (type == MEDIA) { 121 data->rc_dev.ops = &hi6220_media_reset_ops; 122 data->rc_dev.nr_resets = MEDIA_MAX_INDEX; 123 } else { 124 data->rc_dev.ops = &hi6220_peripheral_reset_ops; 125 data->rc_dev.nr_resets = PERIPH_MAX_INDEX; 126 } 127 128 return reset_controller_register(&data->rc_dev); 129} 130 131static const struct of_device_id hi6220_reset_match[] = { 132 { 133 .compatible = "hisilicon,hi6220-sysctrl", 134 .data = (void *)PERIPHERAL, 135 }, 136 { 137 .compatible = "hisilicon,hi6220-mediactrl", 138 .data = (void *)MEDIA, 139 }, 140 { /* sentinel */ }, 141}; 142MODULE_DEVICE_TABLE(of, hi6220_reset_match); 143 144static struct platform_driver hi6220_reset_driver = { 145 .probe = hi6220_reset_probe, 146 .driver = { 147 .name = "reset-hi6220", 148 .of_match_table = hi6220_reset_match, 149 }, 150}; 151 152static int __init hi6220_reset_init(void) 153{ 154 return platform_driver_register(&hi6220_reset_driver); 155} 156 157postcore_initcall(hi6220_reset_init);