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.13-rc5 108 lines 2.7 kB view raw
1/* 2 * Copyright (C) Maxime Coquelin 2015 3 * Author: Maxime Coquelin <mcoquelin.stm32@gmail.com> 4 * License terms: GNU General Public License (GPL), version 2 5 * 6 * Heavily based on sunxi driver from Maxime Ripard. 7 */ 8 9#include <linux/err.h> 10#include <linux/io.h> 11#include <linux/of.h> 12#include <linux/of_address.h> 13#include <linux/platform_device.h> 14#include <linux/reset-controller.h> 15#include <linux/slab.h> 16#include <linux/spinlock.h> 17#include <linux/types.h> 18 19struct stm32_reset_data { 20 spinlock_t lock; 21 void __iomem *membase; 22 struct reset_controller_dev rcdev; 23}; 24 25static int stm32_reset_assert(struct reset_controller_dev *rcdev, 26 unsigned long id) 27{ 28 struct stm32_reset_data *data = container_of(rcdev, 29 struct stm32_reset_data, 30 rcdev); 31 int bank = id / BITS_PER_LONG; 32 int offset = id % BITS_PER_LONG; 33 unsigned long flags; 34 u32 reg; 35 36 spin_lock_irqsave(&data->lock, flags); 37 38 reg = readl(data->membase + (bank * 4)); 39 writel(reg | BIT(offset), data->membase + (bank * 4)); 40 41 spin_unlock_irqrestore(&data->lock, flags); 42 43 return 0; 44} 45 46static int stm32_reset_deassert(struct reset_controller_dev *rcdev, 47 unsigned long id) 48{ 49 struct stm32_reset_data *data = container_of(rcdev, 50 struct stm32_reset_data, 51 rcdev); 52 int bank = id / BITS_PER_LONG; 53 int offset = id % BITS_PER_LONG; 54 unsigned long flags; 55 u32 reg; 56 57 spin_lock_irqsave(&data->lock, flags); 58 59 reg = readl(data->membase + (bank * 4)); 60 writel(reg & ~BIT(offset), data->membase + (bank * 4)); 61 62 spin_unlock_irqrestore(&data->lock, flags); 63 64 return 0; 65} 66 67static const struct reset_control_ops stm32_reset_ops = { 68 .assert = stm32_reset_assert, 69 .deassert = stm32_reset_deassert, 70}; 71 72static const struct of_device_id stm32_reset_dt_ids[] = { 73 { .compatible = "st,stm32-rcc", }, 74 { /* sentinel */ }, 75}; 76 77static int stm32_reset_probe(struct platform_device *pdev) 78{ 79 struct stm32_reset_data *data; 80 struct resource *res; 81 82 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 83 if (!data) 84 return -ENOMEM; 85 86 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 87 data->membase = devm_ioremap_resource(&pdev->dev, res); 88 if (IS_ERR(data->membase)) 89 return PTR_ERR(data->membase); 90 91 spin_lock_init(&data->lock); 92 93 data->rcdev.owner = THIS_MODULE; 94 data->rcdev.nr_resets = resource_size(res) * 8; 95 data->rcdev.ops = &stm32_reset_ops; 96 data->rcdev.of_node = pdev->dev.of_node; 97 98 return devm_reset_controller_register(&pdev->dev, &data->rcdev); 99} 100 101static struct platform_driver stm32_reset_driver = { 102 .probe = stm32_reset_probe, 103 .driver = { 104 .name = "stm32-rcc-reset", 105 .of_match_table = stm32_reset_dt_ids, 106 }, 107}; 108builtin_platform_driver(stm32_reset_driver);