Commit ff591a91 authored by Alban Bedel's avatar Alban Bedel Committed by Philipp Zabel

reset: Add a driver for the reset controller on the AR71XX/AR9XXX

The AR71XX/AR9XXX SoC have a simple reset controller with one bit per
reset line.
Signed-off-by: default avatarAlban Bedel <albeu@free.fr>
Acked-by: default avatarRalf Baechle <ralf@linux-mips.org>
Signed-off-by: default avatarPhilipp Zabel <p.zabel@pengutronix.de>
parent f25b5eda
...@@ -118,6 +118,7 @@ config ATH25 ...@@ -118,6 +118,7 @@ config ATH25
config ATH79 config ATH79
bool "Atheros AR71XX/AR724X/AR913X based boards" bool "Atheros AR71XX/AR724X/AR913X based boards"
select ARCH_HAS_RESET_CONTROLLER
select ARCH_REQUIRE_GPIOLIB select ARCH_REQUIRE_GPIOLIB
select BOOT_RAW select BOOT_RAW
select CEVT_R4K select CEVT_R4K
......
...@@ -3,3 +3,4 @@ obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o ...@@ -3,3 +3,4 @@ obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
obj-$(CONFIG_ARCH_STI) += sti/ obj-$(CONFIG_ARCH_STI) += sti/
obj-$(CONFIG_ATH79) += reset-ath79.o
/*
* Copyright (C) 2015 Alban Bedel <albeu@free.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
struct ath79_reset {
struct reset_controller_dev rcdev;
void __iomem *base;
spinlock_t lock;
};
static int ath79_reset_update(struct reset_controller_dev *rcdev,
unsigned long id, bool assert)
{
struct ath79_reset *ath79_reset =
container_of(rcdev, struct ath79_reset, rcdev);
unsigned long flags;
u32 val;
spin_lock_irqsave(&ath79_reset->lock, flags);
val = readl(ath79_reset->base);
if (assert)
val |= BIT(id);
else
val &= ~BIT(id);
writel(val, ath79_reset->base);
spin_unlock_irqrestore(&ath79_reset->lock, flags);
return 0;
}
static int ath79_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return ath79_reset_update(rcdev, id, true);
}
static int ath79_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return ath79_reset_update(rcdev, id, false);
}
static int ath79_reset_status(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct ath79_reset *ath79_reset =
container_of(rcdev, struct ath79_reset, rcdev);
u32 val;
val = readl(ath79_reset->base);
return !!(val & BIT(id));
}
static struct reset_control_ops ath79_reset_ops = {
.assert = ath79_reset_assert,
.deassert = ath79_reset_deassert,
.status = ath79_reset_status,
};
static int ath79_reset_probe(struct platform_device *pdev)
{
struct ath79_reset *ath79_reset;
struct resource *res;
ath79_reset = devm_kzalloc(&pdev->dev,
sizeof(*ath79_reset), GFP_KERNEL);
if (!ath79_reset)
return -ENOMEM;
platform_set_drvdata(pdev, ath79_reset);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ath79_reset->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(ath79_reset->base))
return PTR_ERR(ath79_reset->base);
ath79_reset->rcdev.ops = &ath79_reset_ops;
ath79_reset->rcdev.owner = THIS_MODULE;
ath79_reset->rcdev.of_node = pdev->dev.of_node;
ath79_reset->rcdev.of_reset_n_cells = 1;
ath79_reset->rcdev.nr_resets = 32;
return reset_controller_register(&ath79_reset->rcdev);
}
static int ath79_reset_remove(struct platform_device *pdev)
{
struct ath79_reset *ath79_reset = platform_get_drvdata(pdev);
reset_controller_unregister(&ath79_reset->rcdev);
return 0;
}
static const struct of_device_id ath79_reset_dt_ids[] = {
{ .compatible = "qca,ar7100-reset", },
{ },
};
MODULE_DEVICE_TABLE(of, ath79_reset_dt_ids);
static struct platform_driver ath79_reset_driver = {
.probe = ath79_reset_probe,
.remove = ath79_reset_remove,
.driver = {
.name = "ath79-reset",
.of_match_table = ath79_reset_dt_ids,
},
};
module_platform_driver(ath79_reset_driver);
MODULE_AUTHOR("Alban Bedel <albeu@free.fr>");
MODULE_DESCRIPTION("AR71xx Reset Controller Driver");
MODULE_LICENSE("GPL");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment