ARM: SoC driver updates for v4.15

This branch contains platform-related driver updates for ARM and ARM64,
 these are the areas that bring the changes:
 
 New drivers:
  - Driver support for Renesas R-Car V3M (R8A77970)
  - Power management support for Amlogic GX
  - A new driver for the Tegra BPMP thermal sensor
  - A new bus driver for Technologic Systems NBUS
 
 Changes for subsystems that prefer to merge through arm-soc:
  - The usual updates for reset controller drivers from Philipp Zabel,
    with five added drivers for SoCs in the arc, meson, socfpa, uniphier
    and mediatek families.
  - Updates to the ARM SCPI and PSCI frameworks, from Sudeep Holla,
    Heiner Kallweit and Lorenzo Pieralisi.
 
 Changes specific to some ARM-based SoC
  - The Freescale/NXP DPAA QBMan drivers from PowerPC can now work
    on ARM as well.
  - Several changes for power management on Broadcom SoCs
  - Various improvements on Qualcomm, Broadcom, Amlogic, Atmel, Mediatek
  - Minor Cleanups for Samsung, TI OMAP SoCs
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJaDggbAAoJEGCrR//JCVInIeQQAN1MDyO1UaWiFYnbkVOgzFcj
 dqbFOc41DBE/90JoBWE8kR/rjyF83OqztiaYpx9viu2qMMBZVcOwxhCUthWK59c/
 IujYdw4zGevLscF+jdrLbXgk97nfaWebsHyTAF307WAdZVJxiVGGzQEcgm71d6Zp
 CXjLiUii4winHUMK9FLRY2st0HKAevXhuvZJVV432+sTg3p7fGVilYeGOL5G62WO
 zQfCisqzC5q677kGGyUlPRGlHWMPkllsTTnfXcmV/FUiGyVa3lUWY5sEu+wCl96O
 U1ffPENeNj/A/4fa1dbErtbiNnC2z/+jf+Dg7Cn8w/dPk4Suf0ppjP8RqIGyxmDl
 Wm/UxbwDClxaeF4GSaYh2yKgGRJMH5N87bJnZRINE5ccGiol8Ww/34bFG0xNnfyh
 jSAFAc318AFG62WD4lvqWc7LSpzOYxp/MNqIFXKN692St/MJLkx8/q0nTwY1qPY0
 3SELz9II3hz+3MfDRqtRi7hZpkgHgQ+UG7S5+Xhmqrl309GOEldCjPVJhhXxWoxK
 ZPtZOuyYvGhIC+YAnHaN6lUjADIdNJZHwbuXFImx85oKHVofoxHbcni5vk8Uu7z1
 sQNYOtdDGaPG/2u9RJdJlPg/jIgLKxxt/Xm9TYVawpZ5hFANhBTtIq5ExCRAil68
 j9sMOrpZ1DzCQyR7zN2v
 =qDhq
 -----END PGP SIGNATURE-----

Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc

Pull ARM SoC driver updates from Arnd Bergmann:
 "This branch contains platform-related driver updates for ARM and
  ARM64, these are the areas that bring the changes:

  New drivers:

   - driver support for Renesas R-Car V3M (R8A77970)

   - power management support for Amlogic GX

   - a new driver for the Tegra BPMP thermal sensor

   - a new bus driver for Technologic Systems NBUS

  Changes for subsystems that prefer to merge through arm-soc:

   - the usual updates for reset controller drivers from Philipp Zabel,
     with five added drivers for SoCs in the arc, meson, socfpa,
     uniphier and mediatek families

   - updates to the ARM SCPI and PSCI frameworks, from Sudeep Holla,
     Heiner Kallweit and Lorenzo Pieralisi

  Changes specific to some ARM-based SoC

   - the Freescale/NXP DPAA QBMan drivers from PowerPC can now work on
     ARM as well

   - several changes for power management on Broadcom SoCs

   - various improvements on Qualcomm, Broadcom, Amlogic, Atmel,
     Mediatek

   - minor Cleanups for Samsung, TI OMAP SoCs"

[ NOTE! This doesn't work without the previous ARM SoC device-tree pull,
  because the R8A77970 driver is missing a header file that came from
  that pull.

  The fact that this got merged afterwards only fixes it at this point,
  and bisection of that driver will fail if/when you walk into the
  history of that driver.           - Linus ]

* tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (96 commits)
  soc: amlogic: meson-gx-pwrc-vpu: fix power-off when powered by bootloader
  bus: add driver for the Technologic Systems NBUS
  memory: omap-gpmc: Remove deprecated gpmc_update_nand_reg()
  soc: qcom: remove unused label
  soc: amlogic: gx pm domain: add PM and OF dependencies
  drivers/firmware: psci_checker: Add missing destroy_timer_on_stack()
  dt-bindings: power: add amlogic meson power domain bindings
  soc: amlogic: add Meson GX VPU Domains driver
  soc: qcom: Remote filesystem memory driver
  dt-binding: soc: qcom: Add binding for rmtfs memory
  of: reserved_mem: Accessor for acquiring reserved_mem
  of/platform: Generalize /reserved-memory handling
  soc: mediatek: pwrap: fix fatal compiler error
  soc: mediatek: pwrap: fix compiler errors
  arm64: mediatek: cleanup message for platform selection
  soc: Allow test-building of MediaTek drivers
  soc: mediatek: place Kconfig for all SoC drivers under menu
  soc: mediatek: pwrap: add support for MT7622 SoC
  soc: mediatek: pwrap: add common way for setup CS timing extenstion
  soc: mediatek: pwrap: add MediaTek MT6380 as one slave of pwrap
  ..
This commit is contained in:
Linus Torvalds 2017-11-16 16:05:01 -08:00
commit cf9b0772f2
110 changed files with 6933 additions and 996 deletions

View file

@ -28,6 +28,12 @@ config RESET_ATH79
This enables the ATH79 reset controller driver that supports the
AR71xx SoC reset controller.
config RESET_AXS10X
bool "AXS10x Reset Driver" if COMPILE_TEST
default ARC_PLAT_AXS10X
help
This enables the reset controller driver for AXS10x.
config RESET_BERLIN
bool "Berlin Reset Driver" if COMPILE_TEST
default ARCH_BERLIN
@ -75,21 +81,21 @@ config RESET_PISTACHIO
help
This enables the reset driver for ImgTec Pistachio SoCs.
config RESET_SOCFPGA
bool "SoCFPGA Reset Driver" if COMPILE_TEST
default ARCH_SOCFPGA
config RESET_SIMPLE
bool "Simple Reset Controller Driver" if COMPILE_TEST
default ARCH_SOCFPGA || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX
help
This enables the reset controller driver for Altera SoCFPGAs.
This enables a simple reset controller driver for reset lines that
that can be asserted and deasserted by toggling bits in a contiguous,
exclusive register space.
config RESET_STM32
bool "STM32 Reset Driver" if COMPILE_TEST
default ARCH_STM32
help
This enables the RCC reset controller driver for STM32 MCUs.
Currently this driver supports Altera SoCFPGAs, the RCC reset
controller in STM32 MCUs, Allwinner SoCs, and ZTE's zx2967 family.
config RESET_SUNXI
bool "Allwinner SoCs Reset Driver" if COMPILE_TEST && !ARCH_SUNXI
default ARCH_SUNXI
select RESET_SIMPLE
help
This enables the reset driver for Allwinner SoCs.
@ -121,12 +127,6 @@ config RESET_UNIPHIER
Say Y if you want to control reset signals provided by System Control
block, Media I/O block, Peripheral Block.
config RESET_ZX2967
bool "ZTE ZX2967 Reset Driver"
depends on ARCH_ZX || COMPILE_TEST
help
This enables the reset controller driver for ZTE's zx2967 family.
config RESET_ZYNQ
bool "ZYNQ Reset Driver" if COMPILE_TEST
default ARCH_ZYNQ

View file

@ -5,6 +5,7 @@ obj-$(CONFIG_ARCH_STI) += sti/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o
obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
obj-$(CONFIG_RESET_AXS10X) += reset-axs10x.o
obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o
obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
@ -13,12 +14,10 @@ obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
obj-$(CONFIG_RESET_MESON) += reset-meson.o
obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o
obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
obj-$(CONFIG_RESET_STM32) += reset-stm32.o
obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o
obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
obj-$(CONFIG_RESET_ZX2967) += reset-zx2967.o
obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o

View file

@ -0,0 +1,83 @@
/*
* Copyright (C) 2017 Synopsys.
*
* Synopsys AXS10x reset driver.
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
#define to_axs10x_rst(p) container_of((p), struct axs10x_rst, rcdev)
#define AXS10X_MAX_RESETS 32
struct axs10x_rst {
void __iomem *regs_rst;
spinlock_t lock;
struct reset_controller_dev rcdev;
};
static int axs10x_reset_reset(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct axs10x_rst *rst = to_axs10x_rst(rcdev);
unsigned long flags;
spin_lock_irqsave(&rst->lock, flags);
writel(BIT(id), rst->regs_rst);
spin_unlock_irqrestore(&rst->lock, flags);
return 0;
}
static const struct reset_control_ops axs10x_reset_ops = {
.reset = axs10x_reset_reset,
};
static int axs10x_reset_probe(struct platform_device *pdev)
{
struct axs10x_rst *rst;
struct resource *mem;
rst = devm_kzalloc(&pdev->dev, sizeof(*rst), GFP_KERNEL);
if (!rst)
return -ENOMEM;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rst->regs_rst = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(rst->regs_rst))
return PTR_ERR(rst->regs_rst);
spin_lock_init(&rst->lock);
rst->rcdev.owner = THIS_MODULE;
rst->rcdev.ops = &axs10x_reset_ops;
rst->rcdev.of_node = pdev->dev.of_node;
rst->rcdev.nr_resets = AXS10X_MAX_RESETS;
return devm_reset_controller_register(&pdev->dev, &rst->rcdev);
}
static const struct of_device_id axs10x_reset_dt_match[] = {
{ .compatible = "snps,axs10x-reset" },
{ },
};
static struct platform_driver axs10x_reset_driver = {
.probe = axs10x_reset_probe,
.driver = {
.name = "axs10x-reset",
.of_match_table = axs10x_reset_dt_match,
},
};
builtin_platform_driver(axs10x_reset_driver);
MODULE_AUTHOR("Eugeniy Paltsev <[email protected]>");
MODULE_DESCRIPTION("Synopsys AXS10x reset driver");
MODULE_LICENSE("GPL v2");

View file

@ -62,13 +62,16 @@
#include <linux/reset-controller.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/of_device.h>
#define REG_COUNT 8
#define BITS_PER_REG 32
#define LEVEL_OFFSET 0x7c
struct meson_reset {
void __iomem *reg_base;
struct reset_controller_dev rcdev;
spinlock_t lock;
};
static int meson_reset_reset(struct reset_controller_dev *rcdev,
@ -80,26 +83,68 @@ static int meson_reset_reset(struct reset_controller_dev *rcdev,
unsigned int offset = id % BITS_PER_REG;
void __iomem *reg_addr = data->reg_base + (bank << 2);
if (bank >= REG_COUNT)
return -EINVAL;
writel(BIT(offset), reg_addr);
return 0;
}
static const struct reset_control_ops meson_reset_ops = {
static int meson_reset_level(struct reset_controller_dev *rcdev,
unsigned long id, bool assert)
{
struct meson_reset *data =
container_of(rcdev, struct meson_reset, rcdev);
unsigned int bank = id / BITS_PER_REG;
unsigned int offset = id % BITS_PER_REG;
void __iomem *reg_addr = data->reg_base + LEVEL_OFFSET + (bank << 2);
unsigned long flags;
u32 reg;
spin_lock_irqsave(&data->lock, flags);
reg = readl(reg_addr);
if (assert)
writel(reg & ~BIT(offset), reg_addr);
else
writel(reg | BIT(offset), reg_addr);
spin_unlock_irqrestore(&data->lock, flags);
return 0;
}
static int meson_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return meson_reset_level(rcdev, id, true);
}
static int meson_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return meson_reset_level(rcdev, id, false);
}
static const struct reset_control_ops meson_reset_meson8_ops = {
.reset = meson_reset_reset,
};
static const struct reset_control_ops meson_reset_gx_ops = {
.reset = meson_reset_reset,
.assert = meson_reset_assert,
.deassert = meson_reset_deassert,
};
static const struct of_device_id meson_reset_dt_ids[] = {
{ .compatible = "amlogic,meson8b-reset", },
{ .compatible = "amlogic,meson-gxbb-reset", },
{ .compatible = "amlogic,meson8b-reset",
.data = &meson_reset_meson8_ops, },
{ .compatible = "amlogic,meson-gxbb-reset",
.data = &meson_reset_gx_ops, },
{ /* sentinel */ },
};
static int meson_reset_probe(struct platform_device *pdev)
{
const struct reset_control_ops *ops;
struct meson_reset *data;
struct resource *res;
@ -107,6 +152,10 @@ static int meson_reset_probe(struct platform_device *pdev)
if (!data)
return -ENOMEM;
ops = of_device_get_match_data(&pdev->dev);
if (!ops)
return -EINVAL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
data->reg_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(data->reg_base))
@ -114,9 +163,11 @@ static int meson_reset_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, data);
spin_lock_init(&data->lock);
data->rcdev.owner = THIS_MODULE;
data->rcdev.nr_resets = REG_COUNT * BITS_PER_REG;
data->rcdev.ops = &meson_reset_ops;
data->rcdev.ops = ops;
data->rcdev.of_node = pdev->dev.of_node;
return devm_reset_controller_register(&pdev->dev, &data->rcdev);

View file

@ -0,0 +1,186 @@
/*
* Simple Reset Controller Driver
*
* Copyright (C) 2017 Pengutronix, Philipp Zabel <kernel@pengutronix.de>
*
* Based on Allwinner SoCs Reset Controller driver
*
* Copyright 2013 Maxime Ripard
*
* Maxime Ripard <maxime.ripard@free-electrons.com>
*
* 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.
*/
#include <linux/device.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
#include <linux/spinlock.h>
#include "reset-simple.h"
static inline struct reset_simple_data *
to_reset_simple_data(struct reset_controller_dev *rcdev)
{
return container_of(rcdev, struct reset_simple_data, rcdev);
}
static int reset_simple_update(struct reset_controller_dev *rcdev,
unsigned long id, bool assert)
{
struct reset_simple_data *data = to_reset_simple_data(rcdev);
int reg_width = sizeof(u32);
int bank = id / (reg_width * BITS_PER_BYTE);
int offset = id % (reg_width * BITS_PER_BYTE);
unsigned long flags;
u32 reg;
spin_lock_irqsave(&data->lock, flags);
reg = readl(data->membase + (bank * reg_width));
if (assert ^ data->active_low)
reg |= BIT(offset);
else
reg &= ~BIT(offset);
writel(reg, data->membase + (bank * reg_width));
spin_unlock_irqrestore(&data->lock, flags);
return 0;
}
static int reset_simple_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return reset_simple_update(rcdev, id, true);
}
static int reset_simple_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return reset_simple_update(rcdev, id, false);
}
static int reset_simple_status(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct reset_simple_data *data = to_reset_simple_data(rcdev);
int reg_width = sizeof(u32);
int bank = id / (reg_width * BITS_PER_BYTE);
int offset = id % (reg_width * BITS_PER_BYTE);
u32 reg;
reg = readl(data->membase + (bank * reg_width));
return !(reg & BIT(offset)) ^ !data->status_active_low;
}
const struct reset_control_ops reset_simple_ops = {
.assert = reset_simple_assert,
.deassert = reset_simple_deassert,
.status = reset_simple_status,
};
/**
* struct reset_simple_devdata - simple reset controller properties
* @reg_offset: offset between base address and first reset register.
* @nr_resets: number of resets. If not set, default to resource size in bits.
* @active_low: if true, bits are cleared to assert the reset. Otherwise, bits
* are set to assert the reset.
* @status_active_low: if true, bits read back as cleared while the reset is
* asserted. Otherwise, bits read back as set while the
* reset is asserted.
*/
struct reset_simple_devdata {
u32 reg_offset;
u32 nr_resets;
bool active_low;
bool status_active_low;
};
#define SOCFPGA_NR_BANKS 8
static const struct reset_simple_devdata reset_simple_socfpga = {
.reg_offset = 0x10,
.nr_resets = SOCFPGA_NR_BANKS * 32,
.status_active_low = true,
};
static const struct reset_simple_devdata reset_simple_active_low = {
.active_low = true,
.status_active_low = true,
};
static const struct of_device_id reset_simple_dt_ids[] = {
{ .compatible = "altr,rst-mgr", .data = &reset_simple_socfpga },
{ .compatible = "st,stm32-rcc", },
{ .compatible = "allwinner,sun6i-a31-clock-reset",
.data = &reset_simple_active_low },
{ .compatible = "zte,zx296718-reset",
.data = &reset_simple_active_low },
{ /* sentinel */ },
};
static int reset_simple_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct reset_simple_devdata *devdata;
struct reset_simple_data *data;
void __iomem *membase;
struct resource *res;
u32 reg_offset = 0;
devdata = of_device_get_match_data(dev);
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
membase = devm_ioremap_resource(dev, res);
if (IS_ERR(membase))
return PTR_ERR(membase);
spin_lock_init(&data->lock);
data->membase = membase;
data->rcdev.owner = THIS_MODULE;
data->rcdev.nr_resets = resource_size(res) * BITS_PER_BYTE;
data->rcdev.ops = &reset_simple_ops;
data->rcdev.of_node = dev->of_node;
if (devdata) {
reg_offset = devdata->reg_offset;
if (devdata->nr_resets)
data->rcdev.nr_resets = devdata->nr_resets;
data->active_low = devdata->active_low;
data->status_active_low = devdata->status_active_low;
}
if (of_device_is_compatible(dev->of_node, "altr,rst-mgr") &&
of_property_read_u32(dev->of_node, "altr,modrst-offset",
&reg_offset)) {
dev_warn(dev,
"missing altr,modrst-offset property, assuming 0x%x!\n",
reg_offset);
}
data->membase += reg_offset;
return devm_reset_controller_register(dev, &data->rcdev);
}
static struct platform_driver reset_simple_driver = {
.probe = reset_simple_probe,
.driver = {
.name = "simple-reset",
.of_match_table = reset_simple_dt_ids,
},
};
builtin_platform_driver(reset_simple_driver);

View file

@ -0,0 +1,45 @@
/*
* Simple Reset Controller ops
*
* Based on Allwinner SoCs Reset Controller driver
*
* Copyright 2013 Maxime Ripard
*
* Maxime Ripard <maxime.ripard@free-electrons.com>
*
* 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.
*/
#ifndef __RESET_SIMPLE_H__
#define __RESET_SIMPLE_H__
#include <linux/io.h>
#include <linux/reset-controller.h>
#include <linux/spinlock.h>
/**
* struct reset_simple_data - driver data for simple reset controllers
* @lock: spinlock to protect registers during read-modify-write cycles
* @membase: memory mapped I/O register range
* @rcdev: reset controller device base structure
* @active_low: if true, bits are cleared to assert the reset. Otherwise, bits
* are set to assert the reset. Note that this says nothing about
* the voltage level of the actual reset line.
* @status_active_low: if true, bits read back as cleared while the reset is
* asserted. Otherwise, bits read back as set while the
* reset is asserted.
*/
struct reset_simple_data {
spinlock_t lock;
void __iomem *membase;
struct reset_controller_dev rcdev;
bool active_low;
bool status_active_low;
};
extern const struct reset_control_ops reset_simple_ops;
#endif /* __RESET_SIMPLE_H__ */

View file

@ -1,157 +0,0 @@
/*
* Socfpga Reset Controller Driver
*
* Copyright 2014 Steffen Trumtrar <s.trumtrar@pengutronix.de>
*
* based on
* Allwinner SoCs Reset Controller driver
*
* Copyright 2013 Maxime Ripard
*
* Maxime Ripard <maxime.ripard@free-electrons.com>
*
* 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.
*/
#include <linux/err.h>
#include <linux/io.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#define BANK_INCREMENT 4
#define NR_BANKS 8
struct socfpga_reset_data {
spinlock_t lock;
void __iomem *membase;
struct reset_controller_dev rcdev;
};
static int socfpga_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct socfpga_reset_data *data = container_of(rcdev,
struct socfpga_reset_data,
rcdev);
int reg_width = sizeof(u32);
int bank = id / (reg_width * BITS_PER_BYTE);
int offset = id % (reg_width * BITS_PER_BYTE);
unsigned long flags;
u32 reg;
spin_lock_irqsave(&data->lock, flags);
reg = readl(data->membase + (bank * BANK_INCREMENT));
writel(reg | BIT(offset), data->membase + (bank * BANK_INCREMENT));
spin_unlock_irqrestore(&data->lock, flags);
return 0;
}
static int socfpga_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct socfpga_reset_data *data = container_of(rcdev,
struct socfpga_reset_data,
rcdev);
int reg_width = sizeof(u32);
int bank = id / (reg_width * BITS_PER_BYTE);
int offset = id % (reg_width * BITS_PER_BYTE);
unsigned long flags;
u32 reg;
spin_lock_irqsave(&data->lock, flags);
reg = readl(data->membase + (bank * BANK_INCREMENT));
writel(reg & ~BIT(offset), data->membase + (bank * BANK_INCREMENT));
spin_unlock_irqrestore(&data->lock, flags);
return 0;
}
static int socfpga_reset_status(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct socfpga_reset_data *data = container_of(rcdev,
struct socfpga_reset_data, rcdev);
int reg_width = sizeof(u32);
int bank = id / (reg_width * BITS_PER_BYTE);
int offset = id % (reg_width * BITS_PER_BYTE);
u32 reg;
reg = readl(data->membase + (bank * BANK_INCREMENT));
return !(reg & BIT(offset));
}
static const struct reset_control_ops socfpga_reset_ops = {
.assert = socfpga_reset_assert,
.deassert = socfpga_reset_deassert,
.status = socfpga_reset_status,
};
static int socfpga_reset_probe(struct platform_device *pdev)
{
struct socfpga_reset_data *data;
struct resource *res;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
u32 modrst_offset;
/*
* The binding was mainlined without the required property.
* Do not continue, when we encounter an old DT.
*/
if (!of_find_property(pdev->dev.of_node, "#reset-cells", NULL)) {
dev_err(&pdev->dev, "%pOF missing #reset-cells property\n",
pdev->dev.of_node);
return -EINVAL;
}
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
data->membase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(data->membase))
return PTR_ERR(data->membase);
if (of_property_read_u32(np, "altr,modrst-offset", &modrst_offset)) {
dev_warn(dev, "missing altr,modrst-offset property, assuming 0x10!\n");
modrst_offset = 0x10;
}
data->membase += modrst_offset;
spin_lock_init(&data->lock);
data->rcdev.owner = THIS_MODULE;
data->rcdev.nr_resets = NR_BANKS * (sizeof(u32) * BITS_PER_BYTE);
data->rcdev.ops = &socfpga_reset_ops;
data->rcdev.of_node = pdev->dev.of_node;
return devm_reset_controller_register(dev, &data->rcdev);
}
static const struct of_device_id socfpga_reset_dt_ids[] = {
{ .compatible = "altr,rst-mgr", },
{ /* sentinel */ },
};
static struct platform_driver socfpga_reset_driver = {
.probe = socfpga_reset_probe,
.driver = {
.name = "socfpga-reset",
.of_match_table = socfpga_reset_dt_ids,
},
};
builtin_platform_driver(socfpga_reset_driver);

View file

@ -1,108 +0,0 @@
/*
* Copyright (C) Maxime Coquelin 2015
* Author: Maxime Coquelin <mcoquelin.stm32@gmail.com>
* License terms: GNU General Public License (GPL), version 2
*
* Heavily based on sunxi driver from Maxime Ripard.
*/
#include <linux/err.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/types.h>
struct stm32_reset_data {
spinlock_t lock;
void __iomem *membase;
struct reset_controller_dev rcdev;
};
static int stm32_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct stm32_reset_data *data = container_of(rcdev,
struct stm32_reset_data,
rcdev);
int bank = id / BITS_PER_LONG;
int offset = id % BITS_PER_LONG;
unsigned long flags;
u32 reg;
spin_lock_irqsave(&data->lock, flags);
reg = readl(data->membase + (bank * 4));
writel(reg | BIT(offset), data->membase + (bank * 4));
spin_unlock_irqrestore(&data->lock, flags);
return 0;
}
static int stm32_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct stm32_reset_data *data = container_of(rcdev,
struct stm32_reset_data,
rcdev);
int bank = id / BITS_PER_LONG;
int offset = id % BITS_PER_LONG;
unsigned long flags;
u32 reg;
spin_lock_irqsave(&data->lock, flags);
reg = readl(data->membase + (bank * 4));
writel(reg & ~BIT(offset), data->membase + (bank * 4));
spin_unlock_irqrestore(&data->lock, flags);
return 0;
}
static const struct reset_control_ops stm32_reset_ops = {
.assert = stm32_reset_assert,
.deassert = stm32_reset_deassert,
};
static const struct of_device_id stm32_reset_dt_ids[] = {
{ .compatible = "st,stm32-rcc", },
{ /* sentinel */ },
};
static int stm32_reset_probe(struct platform_device *pdev)
{
struct stm32_reset_data *data;
struct resource *res;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
data->membase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(data->membase))
return PTR_ERR(data->membase);
spin_lock_init(&data->lock);
data->rcdev.owner = THIS_MODULE;
data->rcdev.nr_resets = resource_size(res) * 8;
data->rcdev.ops = &stm32_reset_ops;
data->rcdev.of_node = pdev->dev.of_node;
return devm_reset_controller_register(&pdev->dev, &data->rcdev);
}
static struct platform_driver stm32_reset_driver = {
.probe = stm32_reset_probe,
.driver = {
.name = "stm32-rcc-reset",
.of_match_table = stm32_reset_dt_ids,
},
};
builtin_platform_driver(stm32_reset_driver);

View file

@ -22,64 +22,11 @@
#include <linux/spinlock.h>
#include <linux/types.h>
struct sunxi_reset_data {
spinlock_t lock;
void __iomem *membase;
struct reset_controller_dev rcdev;
};
static int sunxi_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct sunxi_reset_data *data = container_of(rcdev,
struct sunxi_reset_data,
rcdev);
int reg_width = sizeof(u32);
int bank = id / (reg_width * BITS_PER_BYTE);
int offset = id % (reg_width * BITS_PER_BYTE);
unsigned long flags;
u32 reg;
spin_lock_irqsave(&data->lock, flags);
reg = readl(data->membase + (bank * reg_width));
writel(reg & ~BIT(offset), data->membase + (bank * reg_width));
spin_unlock_irqrestore(&data->lock, flags);
return 0;
}
static int sunxi_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct sunxi_reset_data *data = container_of(rcdev,
struct sunxi_reset_data,
rcdev);
int reg_width = sizeof(u32);
int bank = id / (reg_width * BITS_PER_BYTE);
int offset = id % (reg_width * BITS_PER_BYTE);
unsigned long flags;
u32 reg;
spin_lock_irqsave(&data->lock, flags);
reg = readl(data->membase + (bank * reg_width));
writel(reg | BIT(offset), data->membase + (bank * reg_width));
spin_unlock_irqrestore(&data->lock, flags);
return 0;
}
static const struct reset_control_ops sunxi_reset_ops = {
.assert = sunxi_reset_assert,
.deassert = sunxi_reset_deassert,
};
#include "reset-simple.h"
static int sunxi_reset_init(struct device_node *np)
{
struct sunxi_reset_data *data;
struct reset_simple_data *data;
struct resource res;
resource_size_t size;
int ret;
@ -108,8 +55,9 @@ static int sunxi_reset_init(struct device_node *np)
data->rcdev.owner = THIS_MODULE;
data->rcdev.nr_resets = size * 8;
data->rcdev.ops = &sunxi_reset_ops;
data->rcdev.ops = &reset_simple_ops;
data->rcdev.of_node = np;
data->active_low = true;
return reset_controller_register(&data->rcdev);
@ -122,6 +70,8 @@ err_alloc:
* These are the reset controller we need to initialize early on in
* our system, before we can even think of using a regular device
* driver for it.
* The controllers that we can register through the regular device
* model are handled by the simple reset driver directly.
*/
static const struct of_device_id sunxi_early_reset_dt_ids[] __initconst = {
{ .compatible = "allwinner,sun6i-a31-ahb1-reset", },
@ -135,45 +85,3 @@ void __init sun6i_reset_init(void)
for_each_matching_node(np, sunxi_early_reset_dt_ids)
sunxi_reset_init(np);
}
/*
* And these are the controllers we can register through the regular
* device model.
*/
static const struct of_device_id sunxi_reset_dt_ids[] = {
{ .compatible = "allwinner,sun6i-a31-clock-reset", },
{ /* sentinel */ },
};
static int sunxi_reset_probe(struct platform_device *pdev)
{
struct sunxi_reset_data *data;
struct resource *res;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
data->membase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(data->membase))
return PTR_ERR(data->membase);
spin_lock_init(&data->lock);
data->rcdev.owner = THIS_MODULE;
data->rcdev.nr_resets = resource_size(res) * 8;
data->rcdev.ops = &sunxi_reset_ops;
data->rcdev.of_node = pdev->dev.of_node;
return devm_reset_controller_register(&pdev->dev, &data->rcdev);
}
static struct platform_driver sunxi_reset_driver = {
.probe = sunxi_reset_probe,
.driver = {
.name = "sunxi-reset",
.of_match_table = sunxi_reset_dt_ids,
},
};
builtin_platform_driver(sunxi_reset_driver);

View file

@ -58,6 +58,7 @@ static const struct uniphier_reset_data uniphier_ld4_sys_reset_data[] = {
static const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
UNIPHIER_RESETX(2, 0x2000, 2), /* NAND */
UNIPHIER_RESETX(6, 0x2000, 12), /* Ether */
UNIPHIER_RESETX(8, 0x2000, 10), /* STDMAC (HSC, MIO, RLE) */
UNIPHIER_RESETX(12, 0x2000, 6), /* GIO (Ether, SATA, USB3) */
UNIPHIER_RESETX(14, 0x2000, 17), /* USB30 */
@ -76,6 +77,7 @@ static const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = {
static const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
UNIPHIER_RESETX(2, 0x2000, 2), /* NAND */
UNIPHIER_RESETX(6, 0x2000, 12), /* Ether */
UNIPHIER_RESETX(8, 0x2000, 10), /* STDMAC (HSC, RLE) */
UNIPHIER_RESETX(14, 0x2000, 17), /* USB30 */
UNIPHIER_RESETX(15, 0x2004, 17), /* USB31 */
@ -92,6 +94,7 @@ static const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
static const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = {
UNIPHIER_RESETX(2, 0x200c, 0), /* NAND */
UNIPHIER_RESETX(4, 0x200c, 2), /* eMMC */
UNIPHIER_RESETX(6, 0x200c, 6), /* Ether */
UNIPHIER_RESETX(8, 0x200c, 8), /* STDMAC (HSC, MIO) */
UNIPHIER_RESETX(40, 0x2008, 0), /* AIO */
UNIPHIER_RESETX(41, 0x2008, 1), /* EVEA */
@ -102,6 +105,7 @@ static const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = {
static const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
UNIPHIER_RESETX(2, 0x200c, 0), /* NAND */
UNIPHIER_RESETX(4, 0x200c, 2), /* eMMC */
UNIPHIER_RESETX(6, 0x200c, 6), /* Ether */
UNIPHIER_RESETX(8, 0x200c, 8), /* STDMAC (HSC) */
UNIPHIER_RESETX(12, 0x200c, 5), /* GIO (PCIe, USB3) */
UNIPHIER_RESETX(16, 0x200c, 12), /* USB30-PHY0 */
@ -114,6 +118,20 @@ static const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
UNIPHIER_RESET_END,
};
static const struct uniphier_reset_data uniphier_pxs3_sys_reset_data[] = {
UNIPHIER_RESETX(2, 0x200c, 0), /* NAND */
UNIPHIER_RESETX(4, 0x200c, 2), /* eMMC */
UNIPHIER_RESETX(8, 0x200c, 12), /* STDMAC */
UNIPHIER_RESETX(12, 0x200c, 4), /* USB30 link (GIO0) */
UNIPHIER_RESETX(13, 0x200c, 5), /* USB31 link (GIO1) */
UNIPHIER_RESETX(16, 0x200c, 16), /* USB30-PHY0 */
UNIPHIER_RESETX(17, 0x200c, 18), /* USB30-PHY1 */
UNIPHIER_RESETX(18, 0x200c, 20), /* USB30-PHY2 */
UNIPHIER_RESETX(20, 0x200c, 17), /* USB31-PHY0 */
UNIPHIER_RESETX(21, 0x200c, 19), /* USB31-PHY1 */
UNIPHIER_RESET_END,
};
/* Media I/O reset data */
#define UNIPHIER_MIO_RESET_SD(id, ch) \
UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 0)
@ -359,6 +377,10 @@ static const struct of_device_id uniphier_reset_match[] = {
.compatible = "socionext,uniphier-ld20-reset",
.data = uniphier_ld20_sys_reset_data,
},
{
.compatible = "socionext,uniphier-pxs3-reset",
.data = uniphier_pxs3_sys_reset_data,
},
/* Media I/O reset, SD reset */
{
.compatible = "socionext,uniphier-ld4-mio-reset",
@ -392,6 +414,10 @@ static const struct of_device_id uniphier_reset_match[] = {
.compatible = "socionext,uniphier-ld20-sd-reset",
.data = uniphier_pro5_sd_reset_data,
},
{
.compatible = "socionext,uniphier-pxs3-sd-reset",
.data = uniphier_pro5_sd_reset_data,
},
/* Peripheral reset */
{
.compatible = "socionext,uniphier-ld4-peri-reset",
@ -421,6 +447,10 @@ static const struct of_device_id uniphier_reset_match[] = {
.compatible = "socionext,uniphier-ld20-peri-reset",
.data = uniphier_pro4_peri_reset_data,
},
{
.compatible = "socionext,uniphier-pxs3-peri-reset",
.data = uniphier_pro4_peri_reset_data,
},
/* Analog signal amplifiers reset */
{
.compatible = "socionext,uniphier-ld11-adamv-reset",

View file

@ -1,99 +0,0 @@
/*
* ZTE's zx2967 family reset controller driver
*
* Copyright (C) 2017 ZTE Ltd.
*
* Author: Baoyou Xie <baoyou.xie@linaro.org>
*
* License terms: GNU General Public License (GPL) version 2
*/
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
struct zx2967_reset {
void __iomem *reg_base;
spinlock_t lock;
struct reset_controller_dev rcdev;
};
static int zx2967_reset_act(struct reset_controller_dev *rcdev,
unsigned long id, bool assert)
{
struct zx2967_reset *reset = NULL;
int bank = id / 32;
int offset = id % 32;
u32 reg;
unsigned long flags;
reset = container_of(rcdev, struct zx2967_reset, rcdev);
spin_lock_irqsave(&reset->lock, flags);
reg = readl_relaxed(reset->reg_base + (bank * 4));
if (assert)
reg &= ~BIT(offset);
else
reg |= BIT(offset);
writel_relaxed(reg, reset->reg_base + (bank * 4));
spin_unlock_irqrestore(&reset->lock, flags);
return 0;
}
static int zx2967_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return zx2967_reset_act(rcdev, id, true);
}
static int zx2967_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return zx2967_reset_act(rcdev, id, false);
}
static const struct reset_control_ops zx2967_reset_ops = {
.assert = zx2967_reset_assert,
.deassert = zx2967_reset_deassert,
};
static int zx2967_reset_probe(struct platform_device *pdev)
{
struct zx2967_reset *reset;
struct resource *res;
reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
if (!reset)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
reset->reg_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(reset->reg_base))
return PTR_ERR(reset->reg_base);
spin_lock_init(&reset->lock);
reset->rcdev.owner = THIS_MODULE;
reset->rcdev.nr_resets = resource_size(res) * 8;
reset->rcdev.ops = &zx2967_reset_ops;
reset->rcdev.of_node = pdev->dev.of_node;
return devm_reset_controller_register(&pdev->dev, &reset->rcdev);
}
static const struct of_device_id zx2967_reset_dt_ids[] = {
{ .compatible = "zte,zx296718-reset", },
{},
};
static struct platform_driver zx2967_reset_driver = {
.probe = zx2967_reset_probe,
.driver = {
.name = "zx2967-reset",
.of_match_table = zx2967_reset_dt_ids,
},
};
builtin_platform_driver(zx2967_reset_driver);