- New SoC specific drivers - NVIDIA Tegra PM Domain support for newer SoCs (Tegra186 and later) based on the "BPMP" firmware - Clocksource and system controller drivers for the newly added Action Semi platforms (both arm and arm64). - Reset subsystem, merged through arm-soc by tradition: - New drivers for Altera Stratix10, TI Keystone and Cortina Gemini SoCs - Various subsystem-wide cleanups - Updates for existing SoC-specific drivers - TI GPMC (General Purpose Memory Controller) - Mediatek "scpsys" system controller support for MT6797 - Broadcom "brcmstb_gisb" bus arbitrer - ARM SCPI firmware - Renesas "SYSC" system controller One more driver update was submitted for the Freescale/NXP DPAA data path acceleration that has previously been used on PowerPC chips. I ended up postponing the merge until some API questions for its unusual MMIO access are resolved. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIVAwUAWVpDFmCrR//JCVInAQKoihAAosgC3+3IHppOhHid+HepkOcp2teyKknw 42fSXVpTdfWa8Oe7q80Kzmz2CPNfFq2SzHz6oXb9WCcDFqSGr0b9aSE7NnksRjTf 2euHVJ4MnJpkRewvorRmcpK8dPXDcHwEw/8hU3yZtJUGI0IKtlrqXis+evgkz9cn YDynuVdAZgZiEfiNeSeadyNLcxaQCc3x9ovvsBXxBa1/x1pfeRnTbp+6hiHilCJu Szts/yAzZzZE9Jkf9dLKfNlsT6m2SgtjukqqOR+zHAhi7/BdTFSVUP6L8u7QjrR+ +ijTICg8FMJGiWLAOe6ED2qZVByN92EJ2AGwriYlSles9ouoGfRkJ2rwxyjbete7 avy0HP+PSBFXWdwbOcq8HX8CrbuBltagl5fkMokct6biWLLMshNZ33WWdQ6/DsM2 b9mAAZuhbs0g1qWUBD3+q6qBytSuGme6Px6fMoVEc4GQ2YVFUQOoEfZOGKRv1U1o aMWGt/6qeF8SG288rYAnQ/TuYWpOLtksV6yhotA00HUHhkTCy0xVCdyWGZtNyKhG o/x4YnhWFzHsXmqKcR1sM7LzfZY/WNmbrOLvK6i83Z0P7QptqrdaLAylL3iSPEyX ZDUgExf6PYXkWIewc3KwC5sJjuD05z3ZCgIR+mCezwbuD+3Z2fOdjodY/VBZ74hq URcM/BqtuWE= =5L6n -----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: "New SoC specific drivers: - NVIDIA Tegra PM Domain support for newer SoCs (Tegra186 and later) based on the "BPMP" firmware - Clocksource and system controller drivers for the newly added Action Semi platforms (both arm and arm64). Reset subsystem, merged through arm-soc by tradition: - New drivers for Altera Stratix10, TI Keystone and Cortina Gemini SoCs - Various subsystem-wide cleanups Updates for existing SoC-specific drivers - TI GPMC (General Purpose Memory Controller) - Mediatek "scpsys" system controller support for MT6797 - Broadcom "brcmstb_gisb" bus arbitrer - ARM SCPI firmware - Renesas "SYSC" system controller One more driver update was submitted for the Freescale/NXP DPAA data path acceleration that has previously been used on PowerPC chips. I ended up postponing the merge until some API questions for its unusual MMIO access are resolved" * tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (35 commits) clocksource: owl: Add S900 support clocksource: Add Owl timer soc: renesas: rcar-sysc: Use GENPD_FLAG_ALWAYS_ON firmware: tegra: Fix locking bugs in BPMP soc/tegra: flowctrl: Fix error handling soc/tegra: bpmp: Implement generic PM domains soc/tegra: bpmp: Update ABI header PM / Domains: Allow overriding the ->xlate() callback soc: brcmstb: enable drivers for ARM64 and BMIPS soc: renesas: Rework Kconfig and Makefile logic reset: Add the TI SCI reset driver dt-bindings: reset: Add TI SCI reset binding reset: use kref for reference counting soc: qcom: smsm: Improve error handling, quiesce probe deferral cpufreq: scpi: use new scpi_ops functions to remove duplicate code firmware: arm_scpi: add support to populate OPPs and get transition latency dt-bindings: reset: Add reset manager offsets for Stratix10 memory: omap-gpmc: add error message if bank-width property is absent memory: omap-gpmc: make dts snippet include semicolon reset: Add a Gemini reset controller ...tirimbino
commit
e854711291
@ -0,0 +1,62 @@ |
||||
Texas Instruments System Control Interface (TI-SCI) Reset Controller |
||||
===================================================================== |
||||
|
||||
Some TI SoCs contain a system controller (like the Power Management Micro |
||||
Controller (PMMC) on Keystone 66AK2G SoC) that are responsible for controlling |
||||
the state of the various hardware modules present on the SoC. Communication |
||||
between the host processor running an OS and the system controller happens |
||||
through a protocol called TI System Control Interface (TI-SCI protocol). |
||||
For TI SCI details, please refer to the document, |
||||
Documentation/devicetree/bindings/arm/keystone/ti,sci.txt |
||||
|
||||
TI-SCI Reset Controller Node |
||||
============================ |
||||
This reset controller node uses the TI SCI protocol to perform the reset |
||||
management of various hardware modules present on the SoC. Must be a child |
||||
node of the associated TI-SCI system controller node. |
||||
|
||||
Required properties: |
||||
-------------------- |
||||
- compatible : Should be "ti,sci-reset" |
||||
- #reset-cells : Should be 2. Please see the reset consumer node below for |
||||
usage details. |
||||
|
||||
TI-SCI Reset Consumer Nodes |
||||
=========================== |
||||
Each of the reset consumer nodes should have the following properties, |
||||
in addition to their own properties. |
||||
|
||||
Required properties: |
||||
-------------------- |
||||
- resets : A phandle and reset specifier pair, one pair for each reset |
||||
signal that affects the device, or that the device manages. |
||||
The phandle should point to the TI-SCI reset controller node, |
||||
and the reset specifier should have 2 cell-values. The first |
||||
cell should contain the device ID. The second cell should |
||||
contain the reset mask value used by system controller. |
||||
Please refer to the protocol documentation for these values |
||||
to be used for different devices, |
||||
http://processors.wiki.ti.com/index.php/TISCI#66AK2G02_Data |
||||
|
||||
Please also refer to Documentation/devicetree/bindings/reset/reset.txt for |
||||
common reset controller usage by consumers. |
||||
|
||||
Example: |
||||
-------- |
||||
The following example demonstrates both a TI-SCI reset controller node and a |
||||
consumer (a DSP device) on the 66AK2G SoC. |
||||
|
||||
pmmc: pmmc { |
||||
compatible = "ti,k2g-sci"; |
||||
|
||||
k2g_reset: reset-controller { |
||||
compatible = "ti,sci-reset"; |
||||
#reset-cells = <2>; |
||||
}; |
||||
}; |
||||
|
||||
dsp0: dsp@10800000 { |
||||
... |
||||
resets = <&k2g_reset 0x0046 0x1>; |
||||
... |
||||
}; |
@ -0,0 +1,172 @@ |
||||
/*
|
||||
* Actions Semi Owl timer |
||||
* |
||||
* Copyright 2012 Actions Semi Inc. |
||||
* Author: Actions Semi, Inc. |
||||
* |
||||
* Copyright (c) 2017 SUSE Linux GmbH |
||||
* Author: Andreas Färber |
||||
* |
||||
* 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/clk.h> |
||||
#include <linux/clockchips.h> |
||||
#include <linux/interrupt.h> |
||||
#include <linux/irq.h> |
||||
#include <linux/irqreturn.h> |
||||
#include <linux/sched_clock.h> |
||||
#include <linux/of.h> |
||||
#include <linux/of_address.h> |
||||
#include <linux/of_irq.h> |
||||
|
||||
#define OWL_Tx_CTL 0x0 |
||||
#define OWL_Tx_CMP 0x4 |
||||
#define OWL_Tx_VAL 0x8 |
||||
|
||||
#define OWL_Tx_CTL_PD BIT(0) |
||||
#define OWL_Tx_CTL_INTEN BIT(1) |
||||
#define OWL_Tx_CTL_EN BIT(2) |
||||
|
||||
static void __iomem *owl_timer_base; |
||||
static void __iomem *owl_clksrc_base; |
||||
static void __iomem *owl_clkevt_base; |
||||
|
||||
static inline void owl_timer_reset(void __iomem *base) |
||||
{ |
||||
writel(0, base + OWL_Tx_CTL); |
||||
writel(0, base + OWL_Tx_VAL); |
||||
writel(0, base + OWL_Tx_CMP); |
||||
} |
||||
|
||||
static inline void owl_timer_set_enabled(void __iomem *base, bool enabled) |
||||
{ |
||||
u32 ctl = readl(base + OWL_Tx_CTL); |
||||
|
||||
/* PD bit is cleared when set */ |
||||
ctl &= ~OWL_Tx_CTL_PD; |
||||
|
||||
if (enabled) |
||||
ctl |= OWL_Tx_CTL_EN; |
||||
else |
||||
ctl &= ~OWL_Tx_CTL_EN; |
||||
|
||||
writel(ctl, base + OWL_Tx_CTL); |
||||
} |
||||
|
||||
static u64 notrace owl_timer_sched_read(void) |
||||
{ |
||||
return (u64)readl(owl_clksrc_base + OWL_Tx_VAL); |
||||
} |
||||
|
||||
static int owl_timer_set_state_shutdown(struct clock_event_device *evt) |
||||
{ |
||||
owl_timer_set_enabled(owl_clkevt_base, false); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int owl_timer_set_state_oneshot(struct clock_event_device *evt) |
||||
{ |
||||
owl_timer_reset(owl_clkevt_base); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int owl_timer_tick_resume(struct clock_event_device *evt) |
||||
{ |
||||
return 0; |
||||
} |
||||
|
||||
static int owl_timer_set_next_event(unsigned long evt, |
||||
struct clock_event_device *ev) |
||||
{ |
||||
void __iomem *base = owl_clkevt_base; |
||||
|
||||
owl_timer_set_enabled(base, false); |
||||
writel(OWL_Tx_CTL_INTEN, base + OWL_Tx_CTL); |
||||
writel(0, base + OWL_Tx_VAL); |
||||
writel(evt, base + OWL_Tx_CMP); |
||||
owl_timer_set_enabled(base, true); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static struct clock_event_device owl_clockevent = { |
||||
.name = "owl_tick", |
||||
.rating = 200, |
||||
.features = CLOCK_EVT_FEAT_ONESHOT | |
||||
CLOCK_EVT_FEAT_DYNIRQ, |
||||
.set_state_shutdown = owl_timer_set_state_shutdown, |
||||
.set_state_oneshot = owl_timer_set_state_oneshot, |
||||
.tick_resume = owl_timer_tick_resume, |
||||
.set_next_event = owl_timer_set_next_event, |
||||
}; |
||||
|
||||
static irqreturn_t owl_timer1_interrupt(int irq, void *dev_id) |
||||
{ |
||||
struct clock_event_device *evt = (struct clock_event_device *)dev_id; |
||||
|
||||
writel(OWL_Tx_CTL_PD, owl_clkevt_base + OWL_Tx_CTL); |
||||
|
||||
evt->event_handler(evt); |
||||
|
||||
return IRQ_HANDLED; |
||||
} |
||||
|
||||
static int __init owl_timer_init(struct device_node *node) |
||||
{ |
||||
struct clk *clk; |
||||
unsigned long rate; |
||||
int timer1_irq, ret; |
||||
|
||||
owl_timer_base = of_io_request_and_map(node, 0, "owl-timer"); |
||||
if (IS_ERR(owl_timer_base)) { |
||||
pr_err("Can't map timer registers"); |
||||
return PTR_ERR(owl_timer_base); |
||||
} |
||||
|
||||
owl_clksrc_base = owl_timer_base + 0x08; |
||||
owl_clkevt_base = owl_timer_base + 0x14; |
||||
|
||||
timer1_irq = of_irq_get_byname(node, "timer1"); |
||||
if (timer1_irq <= 0) { |
||||
pr_err("Can't parse timer1 IRQ"); |
||||
return -EINVAL; |
||||
} |
||||
|
||||
clk = of_clk_get(node, 0); |
||||
if (IS_ERR(clk)) |
||||
return PTR_ERR(clk); |
||||
|
||||
rate = clk_get_rate(clk); |
||||
|
||||
owl_timer_reset(owl_clksrc_base); |
||||
owl_timer_set_enabled(owl_clksrc_base, true); |
||||
|
||||
sched_clock_register(owl_timer_sched_read, 32, rate); |
||||
clocksource_mmio_init(owl_clksrc_base + OWL_Tx_VAL, node->name, |
||||
rate, 200, 32, clocksource_mmio_readl_up); |
||||
|
||||
owl_timer_reset(owl_clkevt_base); |
||||
|
||||
ret = request_irq(timer1_irq, owl_timer1_interrupt, IRQF_TIMER, |
||||
"owl-timer", &owl_clockevent); |
||||
if (ret) { |
||||
pr_err("failed to request irq %d\n", timer1_irq); |
||||
return ret; |
||||
} |
||||
|
||||
owl_clockevent.cpumask = cpumask_of(0); |
||||
owl_clockevent.irq = timer1_irq; |
||||
|
||||
clockevents_config_and_register(&owl_clockevent, rate, |
||||
0xf, 0xffffffff); |
||||
|
||||
return 0; |
||||
} |
||||
CLOCKSOURCE_OF_DECLARE(owl_s500, "actions,s500-timer", owl_timer_init); |
||||
CLOCKSOURCE_OF_DECLARE(owl_s900, "actions,s900-timer", owl_timer_init); |
@ -0,0 +1,110 @@ |
||||
/*
|
||||
* Cortina Gemini Reset controller driver |
||||
* Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org> |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License version 2 as |
||||
* published by the Free Software Foundation. |
||||
*/ |
||||
|
||||
#include <linux/err.h> |
||||
#include <linux/init.h> |
||||
#include <linux/mfd/syscon.h> |
||||
#include <linux/regmap.h> |
||||
#include <linux/of.h> |
||||
#include <linux/platform_device.h> |
||||
#include <linux/reset-controller.h> |
||||
#include <dt-bindings/reset/cortina,gemini-reset.h> |
||||
|
||||
/**
|
||||
* struct gemini_reset - gemini reset controller |
||||
* @map: regmap to access the containing system controller |
||||
* @rcdev: reset controller device |
||||
*/ |
||||
struct gemini_reset { |
||||
struct regmap *map; |
||||
struct reset_controller_dev rcdev; |
||||
}; |
||||
|
||||
#define GEMINI_GLOBAL_SOFT_RESET 0x0c |
||||
|
||||
#define to_gemini_reset(p) \ |
||||
container_of((p), struct gemini_reset, rcdev) |
||||
|
||||
/*
|
||||
* This is a self-deasserting reset controller. |
||||
*/ |
||||
static int gemini_reset(struct reset_controller_dev *rcdev, |
||||
unsigned long id) |
||||
{ |
||||
struct gemini_reset *gr = to_gemini_reset(rcdev); |
||||
|
||||
/* Manual says to always set BIT 30 (CPU1) to 1 */ |
||||
return regmap_write(gr->map, |
||||
GEMINI_GLOBAL_SOFT_RESET, |
||||
BIT(GEMINI_RESET_CPU1) | BIT(id)); |
||||
} |
||||
|
||||
static int gemini_reset_status(struct reset_controller_dev *rcdev, |
||||
unsigned long id) |
||||
{ |
||||
struct gemini_reset *gr = to_gemini_reset(rcdev); |
||||
u32 val; |
||||
int ret; |
||||
|
||||
ret = regmap_read(gr->map, GEMINI_GLOBAL_SOFT_RESET, &val); |
||||
if (ret) |
||||
return ret; |
||||
|
||||
return !!(val & BIT(id)); |
||||
} |
||||
|
||||
static const struct reset_control_ops gemini_reset_ops = { |
||||
.reset = gemini_reset, |
||||
.status = gemini_reset_status, |
||||
}; |
||||
|
||||
static int gemini_reset_probe(struct platform_device *pdev) |
||||
{ |
||||
struct gemini_reset *gr; |
||||
struct device *dev = &pdev->dev; |
||||
struct device_node *np = dev->of_node; |
||||
int ret; |
||||
|
||||
gr = devm_kzalloc(dev, sizeof(*gr), GFP_KERNEL); |
||||
if (!gr) |
||||
return -ENOMEM; |
||||
|
||||
gr->map = syscon_node_to_regmap(np); |
||||
if (IS_ERR(gr->map)) { |
||||
ret = PTR_ERR(gr->map); |
||||
dev_err(dev, "unable to get regmap (%d)", ret); |
||||
return ret; |
||||
} |
||||
gr->rcdev.owner = THIS_MODULE; |
||||
gr->rcdev.nr_resets = 32; |
||||
gr->rcdev.ops = &gemini_reset_ops; |
||||
gr->rcdev.of_node = pdev->dev.of_node; |
||||
|
||||
ret = devm_reset_controller_register(&pdev->dev, &gr->rcdev); |
||||
if (ret) |
||||
return ret; |
||||
|
||||
dev_info(dev, "registered Gemini reset controller\n"); |
||||
return 0; |
||||
} |
||||
|
||||
static const struct of_device_id gemini_reset_dt_ids[] = { |
||||
{ .compatible = "cortina,gemini-syscon", }, |
||||
{ /* sentinel */ }, |
||||
}; |
||||
|
||||
static struct platform_driver gemini_reset_driver = { |
||||
.probe = gemini_reset_probe, |
||||
.driver = { |
||||
.name = "gemini-reset", |
||||
.of_match_table = gemini_reset_dt_ids, |
||||
.suppress_bind_attrs = true, |
||||
}, |
||||
}; |
||||
builtin_platform_driver(gemini_reset_driver); |
@ -0,0 +1,269 @@ |
||||
/*
|
||||
* Texas Instrument's System Control Interface (TI-SCI) reset driver |
||||
* |
||||
* Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Andrew F. Davis <afd@ti.com> |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License version 2 as |
||||
* published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any |
||||
* kind, whether express or implied; without even the implied warranty |
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
*/ |
||||
|
||||
#include <linux/idr.h> |
||||
#include <linux/module.h> |
||||
#include <linux/mutex.h> |
||||
#include <linux/of.h> |
||||
#include <linux/platform_device.h> |
||||
#include <linux/reset-controller.h> |
||||
#include <linux/soc/ti/ti_sci_protocol.h> |
||||
|
||||
/**
|
||||
* struct ti_sci_reset_control - reset control structure |
||||
* @dev_id: SoC-specific device identifier |
||||
* @reset_mask: reset mask to use for toggling reset |
||||
* @lock: synchronize reset_mask read-modify-writes |
||||
*/ |
||||
struct ti_sci_reset_control { |
||||
u32 dev_id; |
||||
u32 reset_mask; |
||||
struct mutex lock; |
||||
}; |
||||
|
||||
/**
|
||||
* struct ti_sci_reset_data - reset controller information structure |
||||
* @rcdev: reset controller entity |
||||
* @dev: reset controller device pointer |
||||
* @sci: TI SCI handle used for communication with system controller |
||||
* @idr: idr structure for mapping ids to reset control structures |
||||
*/ |
||||
struct ti_sci_reset_data { |
||||
struct reset_controller_dev rcdev; |
||||
struct device *dev; |
||||
const struct ti_sci_handle *sci; |
||||
struct idr idr; |
||||
}; |
||||
|
||||
#define to_ti_sci_reset_data(p) \ |
||||
container_of((p), struct ti_sci_reset_data, rcdev) |
||||
|
||||
/**
|
||||
* ti_sci_reset_set() - program a device's reset |
||||
* @rcdev: reset controller entity |
||||
* @id: ID of the reset to toggle |
||||
* @assert: boolean flag to indicate assert or deassert |
||||
* |
||||
* This is a common internal function used to assert or deassert a device's |
||||
* reset using the TI SCI protocol. The device's reset is asserted if the |
||||
* @assert argument is true, or deasserted if @assert argument is false. |
||||
* The mechanism itself is a read-modify-write procedure, the current device |
||||
* reset register is read using a TI SCI device operation, the new value is |
||||
* set or un-set using the reset's mask, and the new reset value written by |
||||
* using another TI SCI device operation. |
||||
* |
||||
* Return: 0 for successful request, else a corresponding error value |
||||
*/ |
||||
static int ti_sci_reset_set(struct reset_controller_dev *rcdev, |
||||
unsigned long id, bool assert) |
||||
{ |
||||
struct ti_sci_reset_data *data = to_ti_sci_reset_data(rcdev); |
||||
const struct ti_sci_handle *sci = data->sci; |
||||
const struct ti_sci_dev_ops *dev_ops = &sci->ops.dev_ops; |
||||
struct ti_sci_reset_control *control; |
||||
u32 reset_state; |
||||
int ret; |
||||
|
||||
control = idr_find(&data->idr, id); |
||||
if (!control) |
||||
return -EINVAL; |
||||
|
||||
mutex_lock(&control->lock); |
||||
|
||||
ret = dev_ops->get_device_resets(sci, control->dev_id, &reset_state); |
||||
if (ret) |
||||
goto out; |
||||
|
||||
if (assert) |
||||
reset_state |= control->reset_mask; |
||||
else |
||||
reset_state &= ~control->reset_mask; |
||||
|
||||
ret = dev_ops->set_device_resets(sci, control->dev_id, reset_state); |
||||
out: |
||||
mutex_unlock(&control->lock); |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
/**
|
||||
* ti_sci_reset_assert() - assert device reset |
||||
* @rcdev: reset controller entity |
||||
* @id: ID of the reset to be asserted |
||||
* |
||||
* This function implements the reset driver op to assert a device's reset |
||||
* using the TI SCI protocol. This invokes the function ti_sci_reset_set() |
||||
* with the corresponding parameters as passed in, but with the @assert |
||||
* argument set to true for asserting the reset. |
||||
* |
||||
* Return: 0 for successful request, else a corresponding error value |
||||
*/ |
||||
static int ti_sci_reset_assert(struct reset_controller_dev *rcdev, |
||||
unsigned long id) |
||||
{ |
||||
return ti_sci_reset_set(rcdev, id, true); |
||||
} |
||||
|
||||
/**
|
||||
* ti_sci_reset_deassert() - deassert device reset |
||||
* @rcdev: reset controller entity |
||||
* @id: ID of the reset to be deasserted |
||||
* |
||||
* This function implements the reset driver op to deassert a device's reset |
||||
* using the TI SCI protocol. This invokes the function ti_sci_reset_set() |
||||
* with the corresponding parameters as passed in, but with the @assert |
||||
* argument set to false for deasserting the reset. |
||||
* |
||||
* Return: 0 for successful request, else a corresponding error value |
||||
*/ |
||||
static int ti_sci_reset_deassert(struct reset_controller_dev *rcdev, |
||||
unsigned long id) |
||||
{ |
||||
return ti_sci_reset_set(rcdev, id, false); |
||||
} |
||||
|
||||
/**
|
||||
* ti_sci_reset_status() - check device reset status |
||||
* @rcdev: reset controller entity |
||||
* @id: ID of reset to be checked |
||||
* |
||||
* This function implements the reset driver op to return the status of a |
||||
* device's reset using the TI SCI protocol. The reset register value is read |
||||
* by invoking the TI SCI device operation .get_device_resets(), and the |
||||
* status of the specific reset is extracted and returned using this reset's |
||||
* reset mask. |
||||
* |
||||
* Return: 0 if reset is deasserted, or a non-zero value if reset is asserted |
||||
*/ |
||||
static int ti_sci_reset_status(struct reset_controller_dev *rcdev, |
||||
unsigned long id) |
||||
{ |
||||
struct ti_sci_reset_data *data = to_ti_sci_reset_data(rcdev); |
||||
const struct ti_sci_handle *sci = data->sci; |
||||
const struct ti_sci_dev_ops *dev_ops = &sci->ops.dev_ops; |
||||
struct ti_sci_reset_control *control; |
||||
u32 reset_state; |
||||
int ret; |
||||
|
||||
control = idr_find(&data->idr, id); |
||||
if (!control) |
||||
return -EINVAL; |
||||
|
||||
ret = dev_ops->get_device_resets(sci, control->dev_id, &reset_state); |
||||
if (ret) |
||||
return ret; |
||||
|
||||
return reset_state & control->reset_mask; |
||||
} |
||||
|
||||
static const struct reset_control_ops ti_sci_reset_ops = { |
||||
.assert = ti_sci_reset_assert, |
||||
.deassert = ti_sci_reset_deassert, |
||||
.status = ti_sci_reset_status, |
||||
}; |
||||
|
||||
/**
|
||||
* ti_sci_reset_of_xlate() - translate a set of OF arguments to a reset ID |
||||
* @rcdev: reset controller entity |
||||
* @reset_spec: OF reset argument specifier |
||||
* |
||||
* This function performs the translation of the reset argument specifier |
||||
* values defined in a reset consumer device node. The function allocates a |
||||
* reset control structure for that device reset, and will be used by the |
||||
* driver for performing any reset functions on that reset. An idr structure |
||||
* is allocated and used to map to the reset control structure. This idr |
||||
* is used by the driver to do reset lookups. |
||||
* |
||||
* Return: 0 for successful request, else a corresponding error value |
||||
*/ |
||||
static int ti_sci_reset_of_xlate(struct reset_controller_dev *rcdev, |
||||
const struct of_phandle_args *reset_spec) |
||||
{ |
||||
struct ti_sci_reset_data *data = to_ti_sci_reset_data(rcdev); |
||||
struct ti_sci_reset_control *control; |
||||
|
||||
if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells)) |
||||
return -EINVAL; |
||||
|
||||
control = devm_kzalloc(data->dev, sizeof(*control), GFP_KERNEL); |
||||
if (!control) |
||||
return -ENOMEM; |
||||
|
||||
control->dev_id = reset_spec->args[0]; |
||||
control->reset_mask = reset_spec->args[1]; |
||||
mutex_init(&control->lock); |
||||
|
||||
return idr_alloc(&data->idr, control, 0, 0, GFP_KERNEL); |
||||
} |
||||
|
||||
static const struct of_device_id ti_sci_reset_of_match[] = { |
||||
{ .compatible = "ti,sci-reset", }, |
||||
{ /* sentinel */ }, |
||||
}; |
||||
MODULE_DEVICE_TABLE(of, ti_sci_reset_of_match); |
||||
|
||||
static int ti_sci_reset_probe(struct platform_device *pdev) |
||||
{ |
||||
struct ti_sci_reset_data *data; |
||||
|
||||
if (!pdev->dev.of_node) |
||||
return -ENODEV; |
||||
|
||||
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); |
||||
if (!data) |
||||
return -ENOMEM; |
||||
|
||||
data->sci = devm_ti_sci_get_handle(&pdev->dev); |
||||
if (IS_ERR(data->sci)) |
||||
return PTR_ERR(data->sci); |
||||
|
||||
data->rcdev.ops = &ti_sci_reset_ops; |
||||
data->rcdev.owner = THIS_MODULE; |
||||
data->rcdev.of_node = pdev->dev.of_node; |
||||
data->rcdev.of_reset_n_cells = 2; |
||||
data->rcdev.of_xlate = ti_sci_reset_of_xlate; |
||||
data->dev = &pdev->dev; |
||||
idr_init(&data->idr); |
||||
|
||||
platform_set_drvdata(pdev, data); |
||||
|
||||
return reset_controller_register(&data->rcdev); |
||||
} |
||||
|
||||
static int ti_sci_reset_remove(struct platform_device *pdev) |
||||
{ |
||||
struct ti_sci_reset_data *data = platform_get_drvdata(pdev); |
||||
|
||||
reset_controller_unregister(&data->rcdev); |
||||
|
||||
idr_destroy(&data->idr); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static struct platform_driver ti_sci_reset_driver = { |
||||
.probe = ti_sci_reset_probe, |
||||
.remove = ti_sci_reset_remove, |
||||
.driver = { |
||||
.name = "ti-sci-reset", |
||||
.of_match_table = ti_sci_reset_of_match, |
||||
}, |
||||
}; |
||||
module_platform_driver(ti_sci_reset_driver); |
||||
|
||||
MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>"); |
||||
MODULE_DESCRIPTION("TI System Control Interface (TI SCI) Reset driver"); |
||||
MODULE_LICENSE("GPL v2"); |
@ -1,2 +1,2 @@ |
||||
obj-y += gpc.o
|
||||
obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
|
||||
obj-$(CONFIG_IMX7_PM_DOMAINS) += gpcv2.o
|
||||
|
@ -0,0 +1,63 @@ |
||||
config SOC_RENESAS |
||||
bool "Renesas SoC driver support" if COMPILE_TEST && !ARCH_RENESAS |
||||
default y if ARCH_RENESAS |
||||
select SOC_BUS |
||||
select RST_RCAR if ARCH_RCAR_GEN1 || ARCH_RCAR_GEN2 || \ |
||||
ARCH_R8A7795 || ARCH_R8A7796 |
||||
select SYSC_R8A7743 if ARCH_R8A7743 |
||||
select SYSC_R8A7745 if ARCH_R8A7745 |
||||
select SYSC_R8A7779 if ARCH_R8A7779 |
||||
select SYSC_R8A7790 if ARCH_R8A7790 |
||||
select SYSC_R8A7791 if ARCH_R8A7791 || ARCH_R8A7793 |
||||
select SYSC_R8A7792 if ARCH_R8A7792 |
||||
select SYSC_R8A7794 if ARCH_R8A7794 |
||||
select SYSC_R8A7795 if ARCH_R8A7795 |
||||
select SYSC_R8A7796 if ARCH_R8A7796 |
||||
|
||||
if SOC_RENESAS |
||||
|
||||
# SoC |
||||
config SYSC_R8A7743 |
||||
bool "RZ/G1M System Controller support" if COMPILE_TEST |
||||
select SYSC_RCAR |
||||
|
||||
config SYSC_R8A7745 |
||||
bool "RZ/G1E System Controller support" if COMPILE_TEST |
||||
select SYSC_RCAR |
||||
|
||||
config SYSC_R8A7779 |
||||
bool "R-Car H1 System Controller support" if COMPILE_TEST |
||||
select SYSC_RCAR |
||||
|
||||
config SYSC_R8A7790 |
||||
bool "R-Car H2 System Controller support" if COMPILE_TEST |
||||
select SYSC_RCAR |
||||
|
||||
config SYSC_R8A7791 |
||||
bool "R-Car M2-W/N System Controller support" if COMPILE_TEST |
||||
select SYSC_RCAR |
||||
|
||||
config SYSC_R8A7792 |
||||
bool "R-Car V2H System Controller support" if COMPILE_TEST |
||||
select SYSC_RCAR |
||||
|
||||
config SYSC_R8A7794 |
||||
bool "R-Car E2 System Controller support" if COMPILE_TEST |
||||
select SYSC_RCAR |
||||
|
||||
config SYSC_R8A7795 |
||||
bool "R-Car H3 System Controller support" if COMPILE_TEST |
||||
select SYSC_RCAR |
||||
|
||||
config SYSC_R8A7796 |
||||
bool "R-Car M3-W System Controller support" if COMPILE_TEST |
||||
select SYSC_RCAR |
||||
|
||||
# Family |
||||
config RST_RCAR |
||||
bool "R-Car Reset Controller support" if COMPILE_TEST |
||||
|
||||
config SYSC_RCAR |
||||
bool "R-Car System Controller support" if COMPILE_TEST |
||||
|
||||
endif # SOC_RENESAS |
@ -1,18 +1,17 @@ |
||||
obj-$(CONFIG_SOC_BUS) += renesas-soc.o
|
||||
# Generic, must be first because of soc_device_register()
|
||||
obj-$(CONFIG_SOC_RENESAS) += renesas-soc.o
|
||||
|
||||
obj-$(CONFIG_ARCH_RCAR_GEN1) += rcar-rst.o
|
||||
obj-$(CONFIG_ARCH_RCAR_GEN2) += rcar-rst.o
|
||||
obj-$(CONFIG_ARCH_R8A7795) += rcar-rst.o
|
||||
obj-$(CONFIG_ARCH_R8A7796) += rcar-rst.o
|
||||
# SoC
|
||||
obj-$(CONFIG_SYSC_R8A7743) += r8a7743-sysc.o
|
||||
obj-$(CONFIG_SYSC_R8A7745) += r8a7745-sysc.o
|
||||
obj-$(CONFIG_SYSC_R8A7779) += r8a7779-sysc.o
|
||||
obj-$(CONFIG_SYSC_R8A7790) += r8a7790-sysc.o
|
||||
obj-$(CONFIG_SYSC_R8A7791) += r8a7791-sysc.o
|
||||
obj-$(CONFIG_SYSC_R8A7792) += r8a7792-sysc.o
|
||||
obj-$(CONFIG_SYSC_R8A7794) += r8a7794-sysc.o
|
||||
obj-$(CONFIG_SYSC_R8A7795) += r8a7795-sysc.o
|
||||
obj-$(CONFIG_SYSC_R8A7796) += r8a7796-sysc.o
|
||||
|
||||
obj-$(CONFIG_ARCH_R8A7743) += rcar-sysc.o r8a7743-sysc.o
|
||||
obj-$(CONFIG_ARCH_R8A7745) += rcar-sysc.o r8a7745-sysc.o
|
||||
obj-$(CONFIG_ARCH_R8A7779) += rcar-sysc.o r8a7779-sysc.o
|
||||
obj-$(CONFIG_ARCH_R8A7790) += rcar-sysc.o r8a7790-sysc.o
|
||||
obj-$(CONFIG_ARCH_R8A7791) += rcar-sysc.o r8a7791-sysc.o
|
||||
obj-$(CONFIG_ARCH_R8A7792) += rcar-sysc.o r8a7792-sysc.o
|
||||
# R-Car M2-N is identical to R-Car M2-W w.r.t. power domains.
|
||||
obj-$(CONFIG_ARCH_R8A7793) += rcar-sysc.o r8a7791-sysc.o
|
||||
obj-$(CONFIG_ARCH_R8A7794) += rcar-sysc.o r8a7794-sysc.o
|
||||
obj-$(CONFIG_ARCH_R8A7795) += rcar-sysc.o r8a7795-sysc.o
|
||||
obj-$(CONFIG_ARCH_R8A7796) += rcar-sysc.o r8a7796-sysc.o
|
||||
# Family
|
||||
obj-$(CONFIG_RST_RCAR) += rcar-rst.o
|
||||
obj-$(CONFIG_SYSC_RCAR) += rcar-sysc.o
|
||||
|
@ -0,0 +1,359 @@ |
||||
/*
|
||||
* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify it |
||||
* under the terms and conditions of the GNU General Public License, |
||||
* version 2, as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope 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/of.h> |
||||
#include <linux/platform_device.h> |
||||
#include <linux/pm_domain.h> |
||||
#include <linux/slab.h> |
||||
#include <linux/version.h> |
||||
|
||||
#include <soc/tegra/bpmp.h> |
||||
#include <soc/tegra/bpmp-abi.h> |
||||
|
||||
struct tegra_powergate_info { |
||||
unsigned int id; |
||||
char *name; |
||||
}; |
||||
|
||||
struct tegra_powergate { |
||||
struct generic_pm_domain genpd; |
||||
struct tegra_bpmp *bpmp; |
||||
unsigned int id; |
||||
}; |
||||
|
||||
static inline struct tegra_powergate * |
||||
to_tegra_powergate(struct generic_pm_domain *genpd) |
||||
{ |
||||
return container_of(genpd, struct tegra_powergate, genpd); |
||||
} |
||||
|
||||
static int tegra_bpmp_powergate_set_state(struct tegra_bpmp *bpmp, |
||||
unsigned int id, u32 state) |
||||
{ |
||||
struct mrq_pg_request request; |
||||
struct tegra_bpmp_message msg; |
||||
|
||||
memset(&request, 0, sizeof(request)); |
||||
request.cmd = CMD_PG_SET_STATE; |
||||
request.id = id; |
||||
request.set_state.state = state; |
||||
|
||||
memset(&msg, 0, sizeof(msg)); |
||||
msg.mrq = MRQ_PG; |
||||
msg.tx.data = &request; |
||||
msg.tx.size = sizeof(request); |
||||
|
||||
return tegra_bpmp_transfer(bpmp, &msg); |
||||
} |
||||
|
||||
static int tegra_bpmp_powergate_get_state(struct tegra_bpmp *bpmp, |
||||
unsigned int id) |
||||
{ |
||||
struct mrq_pg_response response; |
||||
struct mrq_pg_request request; |
||||
struct tegra_bpmp_message msg; |
||||
int err; |
||||
|
||||
memset(&request, 0, sizeof(request)); |
||||
request.cmd = CMD_PG_GET_STATE; |
||||
request.id = id; |
||||
|
||||
memset(&response, 0, sizeof(response)); |
||||
|
||||
memset(&msg, 0, sizeof(msg)); |
||||
msg.mrq = MRQ_PG; |
||||
msg.tx.data = &request; |
||||
msg.tx.size = sizeof(request); |
||||
msg.rx.data = &response; |
||||
msg.rx.size = sizeof(response); |
||||
|
||||
err = tegra_bpmp_transfer(bpmp, &msg); |
||||
if (err < 0) |
||||
return PG_STATE_OFF; |
||||
|
||||
return response.get_state.state; |
||||
} |
||||
|
||||
static int tegra_bpmp_powergate_get_max_id(struct tegra_bpmp *bpmp) |
||||
{ |
||||
struct mrq_pg_response response; |
||||
struct mrq_pg_request request; |
||||
struct tegra_bpmp_message msg; |
||||
int err; |
||||
|
||||
memset(&request, 0, sizeof(request)); |
||||
request.cmd = CMD_PG_GET_MAX_ID; |
||||
|
||||
memset(&response, 0, sizeof(response)); |
||||
|
||||
memset(&msg, 0, sizeof(msg)); |
||||
msg.mrq = MRQ_PG; |
||||
msg.tx.data = &request; |
||||
msg.tx.size = sizeof(request); |
||||
msg.rx.data = &response; |
||||
msg.rx.size = sizeof(response); |
||||
|
||||
err = tegra_bpmp_transfer(bpmp, &msg); |
||||
if (err < 0) |
||||
return err; |
||||
|
||||
return response.get_max_id.max_id; |
||||
} |
||||
|
||||
static char *tegra_bpmp_powergate_get_name(struct tegra_bpmp *bpmp, |
||||
unsigned int id) |
||||
{ |
||||
struct mrq_pg_response response; |
||||
struct mrq_pg_request request; |
||||
struct tegra_bpmp_message msg; |
||||
int err; |
||||
|
||||
memset(&request, 0, sizeof(request)); |
||||
request.cmd = CMD_PG_GET_NAME; |
||||
request.id = id; |
||||
|
||||
memset(&response, 0, sizeof(response)); |
||||
|
||||
memset(&msg, 0, sizeof(msg)); |
||||
msg.mrq = MRQ_PG; |
||||
msg.tx.data = &request; |
||||
msg.tx.size = sizeof(request); |
||||
msg.rx.data = &response; |
||||
msg.rx.size = sizeof(response); |
||||
|
||||
err = tegra_bpmp_transfer(bpmp, &msg); |
||||
if (err < 0) |
||||
return NULL; |
||||
|
||||
return kstrdup(response.get_name.name, GFP_KERNEL); |
||||
} |
||||
|
||||
static inline bool tegra_bpmp_powergate_is_powered(struct tegra_bpmp *bpmp, |
||||
unsigned int id) |
||||
{ |
||||
return tegra_bpmp_powergate_get_state(bpmp, id) != PG_STATE_OFF; |
||||
} |
||||
|
||||
static int tegra_powergate_power_on(struct generic_pm_domain *domain) |
||||
{ |
||||
struct tegra_powergate *powergate = to_tegra_powergate(domain); |
||||
struct tegra_bpmp *bpmp = powergate->bpmp; |
||||
|
||||
return tegra_bpmp_powergate_set_state(bpmp, powergate->id, |
||||
PG_STATE_ON); |
||||
} |
||||
|
||||
static int tegra_powergate_power_off(struct generic_pm_domain *domain) |
||||
{ |
||||
struct tegra_powergate *powergate = to_tegra_powergate(domain); |
||||
struct tegra_bpmp *bpmp = powergate->bpmp; |
||||
|
||||
return tegra_bpmp_powergate_set_state(bpmp, powergate->id, |
||||
PG_STATE_OFF); |
||||
} |
||||
|
||||
static struct tegra_powergate * |
||||
tegra_powergate_add(struct tegra_bpmp *bpmp, |
||||
const struct tegra_powergate_info *info) |
||||
{ |
||||
struct tegra_powergate *powergate; |
||||
bool off; |
||||
int err; |
||||
|
||||
off = !tegra_bpmp_powergate_is_powered(bpmp, info->id); |
||||
|
||||
powergate = devm_kzalloc(bpmp->dev, sizeof(*powergate), GFP_KERNEL); |
||||
if (!powergate) |
||||
return ERR_PTR(-ENOMEM); |
||||
|
||||
powergate->id = info->id; |
||||
powergate->bpmp = bpmp; |
||||
|
||||
powergate->genpd.name = kstrdup(info->name, GFP_KERNEL); |
||||
powergate->genpd.power_on = tegra_powergate_power_on; |
||||
powergate->genpd.power_off = tegra_powergate_power_off; |
||||
|
||||
err = pm_genpd_init(&powergate->genpd, NULL, off); |
||||
if (err < 0) { |
||||
kfree(powergate->genpd.name); |
||||
return ERR_PTR(err); |
||||
} |
||||
|
||||
return powergate; |
||||
} |
||||
|
||||
static void tegra_powergate_remove(struct tegra_powergate *powergate) |
||||
{ |
||||
struct generic_pm_domain *genpd = &powergate->genpd; |
||||
struct tegra_bpmp *bpmp = powergate->bpmp; |
||||
int err; |
||||
|
||||
err = pm_genpd_remove(genpd); |
||||
if (err < 0) |
||||
dev_err(bpmp->dev, "failed to remove power domain %s: %d\n", |
||||
genpd->name, err); |
||||
|
||||
kfree(genpd->name); |
||||
} |
||||
|
||||
static int |
||||
tegra_bpmp_probe_powergates(struct tegra_bpmp *bpmp, |
||||
struct tegra_powergate_info **powergatesp) |
||||
{ |
||||
struct tegra_powergate_info *powergates; |
||||
unsigned int max_id, id, count = 0; |
||||
unsigned int num_holes = 0; |
||||
int err; |
||||
|
||||
err = tegra_bpmp_powergate_get_max_id(bpmp); |
||||
if (err < 0) |
||||
return err; |
||||
|
||||
max_id = err; |
||||
|
||||
dev_dbg(bpmp->dev, "maximum powergate ID: %u\n", max_id); |
||||
|
||||
powergates = kcalloc(max_id + 1, sizeof(*powergates), GFP_KERNEL); |
||||
if (!powergates) |
||||
return -ENOMEM; |
||||
|
||||
for (id = 0; id <= max_id; id++) { |
||||
struct tegra_powergate_info *info = &powergates[count]; |
||||
|
||||
info->name = tegra_bpmp_powergate_get_name(bpmp, id); |
||||
if (!info->name || info->name[0] == '\0') { |
||||
num_holes++; |
||||
continue; |
||||
} |
||||
|
||||
info->id = id; |
||||
count++; |
||||
} |
||||
|
||||
dev_dbg(bpmp->dev, "holes: %u\n", num_holes); |
||||
|
||||
*powergatesp = powergates; |
||||
|
||||
return count; |
||||
} |
||||
|
||||
static int tegra_bpmp_add_powergates(struct tegra_bpmp *bpmp, |
||||
struct tegra_powergate_info *powergates, |
||||
unsigned int count) |
||||
{ |
||||
struct genpd_onecell_data *genpd = &bpmp->genpd; |
||||
struct generic_pm_domain **domains; |
||||
struct tegra_powergate *powergate; |
||||
unsigned int i; |
||||
int err; |
||||
|
||||
domains = kcalloc(count, sizeof(*domains), GFP_KERNEL); |
||||
if (!domains) |
||||
return -ENOMEM; |
||||
|
||||
for (i = 0; i < count; i++) { |
||||
powergate = tegra_powergate_add(bpmp, &powergates[i]); |
||||
if (IS_ERR(powergate)) { |
||||
err = PTR_ERR(powergate); |
||||
goto remove; |
||||
} |
||||
|
||||
dev_dbg(bpmp->dev, "added power domain %s\n", |
||||
powergate->genpd.name); |
||||
domains[i] = &powergate->genpd; |
||||
} |
||||
|
||||
genpd->num_domains = count; |
||||
genpd->domains = domains; |
||||
|
||||
return 0; |
||||
|
||||
remove: |
||||
while (i--) { |
||||
powergate = to_tegra_powergate(domains[i]); |
||||
tegra_powergate_remove(powergate); |
||||
} |
||||
|
||||
kfree(genpd->domains); |
||||
return err; |
||||
} |
||||
|
||||
static void tegra_bpmp_remove_powergates(struct tegra_bpmp *bpmp) |
||||
{ |
||||
struct genpd_onecell_data *genpd = &bpmp->genpd; |
||||
unsigned int i = genpd->num_domains; |
||||
struct tegra_powergate *powergate; |
||||
|
||||
while (i--) { |
||||
dev_dbg(bpmp->dev, "removing power domain %s\n", |
||||
genpd->domains[i]->name); |
||||
powergate = to_tegra_powergate(genpd->domains[i]); |
||||
tegra_powergate_remove(powergate); |
||||
} |
||||
} |
||||
|
||||
static struct generic_pm_domain * |
||||
tegra_powergate_xlate(struct of_phandle_args *spec, void *data) |
||||
{ |
||||
struct generic_pm_domain *domain = ERR_PTR(-ENOENT); |
||||
struct genpd_onecell_data *genpd = data; |
||||
unsigned int i; |
||||
|
||||
for (i = 0; i < genpd->num_domains; i++) { |
||||
struct tegra_powergate *powergate; |
||||
|
||||
powergate = to_tegra_powergate(genpd->domains[i]); |
||||
if (powergate->id == spec->args[0]) { |
||||
domain = &powergate->genpd; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return domain; |
||||
} |
||||
|
||||
int tegra_bpmp_init_powergates(struct tegra_bpmp *bpmp) |
||||
{ |
||||
struct device_node *np = bpmp->dev->of_node; |
||||
struct tegra_powergate_info *powergates; |
||||
struct device *dev = bpmp->dev; |
||||
unsigned int count, i; |
||||
int err; |
||||
|
||||
err = tegra_bpmp_probe_powergates(bpmp, &powergates); |
||||
if (err < 0) |
||||
return err; |
||||
|
||||
count = err; |
||||
|
||||
dev_dbg(dev, "%u power domains probed\n", count); |
||||
|
||||
err = tegra_bpmp_add_powergates(bpmp, powergates, count); |
||||
if (err < 0) |
||||
goto free; |
||||
|
||||
bpmp->genpd.xlate = tegra_powergate_xlate; |
||||
|
||||
err = of_genpd_add_provider_onecell(np, &bpmp->genpd); |
||||
if (err < 0) { |
||||
dev_err(dev, "failed to add power domain provider: %d\n", err); |
||||
tegra_bpmp_remove_powergates(bpmp); |
||||
} |
||||
|
||||
free: |
||||
for (i = 0; i < count; i++) |
||||
kfree(powergates[i].name); |
||||
|
||||
kfree(powergates); |
||||
return err; |
||||
} |
@ -0,0 +1,30 @@ |
||||
/*
|
||||
* Copyright (c) 2017 MediaTek Inc. |
||||
* Author: Mars.C <mars.cheng@mediatek.com> |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License version 2 as |
||||
* published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
*/ |
||||
|
||||
#ifndef _DT_BINDINGS_POWER_MT6797_POWER_H |
||||
#define _DT_BINDINGS_POWER_MT6797_POWER_H |
||||
|
||||
#define MT6797_POWER_DOMAIN_VDEC 0 |
||||
#define MT6797_POWER_DOMAIN_VENC 1 |
||||
#define MT6797_POWER_DOMAIN_ISP 2 |
||||
#define MT6797_POWER_DOMAIN_MM 3 |
||||
#define MT6797_POWER_DOMAIN_AUDIO 4 |
||||
#define MT6797_POWER_DOMAIN_MFG_ASYNC 5 |
||||
#define MT6797_POWER_DOMAIN_MFG 6 |
||||
#define MT6797_POWER_DOMAIN_MFG_CORE0 7 |
||||
#define MT6797_POWER_DOMAIN_MFG_CORE1 8 |
||||
#define MT6797_POWER_DOMAIN_MFG_CORE2 9 |
||||
#define MT6797_POWER_DOMAIN_MFG_CORE3 10 |
||||
#define MT6797_POWER_DOMAIN_MJC 11 |
||||
|
||||
#endif /* _DT_BINDINGS_POWER_MT6797_POWER_H */ |
@ -0,0 +1,108 @@ |
||||
/*
|
||||
* Copyright (C) 2016 Intel Corporation. All rights reserved |
||||
* Copyright (C) 2016 Altera Corporation. All rights reserved |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms and conditions of the GNU General Public License, |
||||
* version 2, as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope 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. |
||||
* |
||||
* You should have received a copy of the GNU General Public License along with |
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* |
||||
* derived from Steffen Trumtrar's "altr,rst-mgr-a10.h" |
||||
*/ |
||||
|
||||
#ifndef _DT_BINDINGS_RESET_ALTR_RST_MGR_S10_H |
||||
#define _DT_BINDINGS_RESET_ALTR_RST_MGR_S10_H |
||||
|
||||
/* MPUMODRST */ |
||||
#define CPU0_RESET 0 |
||||
#define CPU1_RESET 1 |
||||
#define CPU2_RESET 2 |
||||
#define CPU3_RESET 3 |
||||
|
||||
/* PER0MODRST */ |
||||
#define EMAC0_RESET 32 |
||||
#define EMAC1_RESET 33 |
||||
#define EMAC2_RESET 34 |
||||
#define USB0_RESET 35 |
||||
#define USB1_RESET 36 |
||||
#define NAND_RESET 37 |
||||
/* 38 is empty */ |
||||
#define SDMMC_RESET 39 |
||||
#define EMAC0_OCP_RESET 40 |
||||
#define EMAC1_OCP_RESET 41 |
||||
#define EMAC2_OCP_RESET 42 |
||||
#define USB0_OCP_RESET 43 |
||||
#define USB1_OCP_RESET 44 |
||||
#define NAND_OCP_RESET 45 |
||||
/* 46 is empty */ |
||||
#define SDMMC_OCP_RESET 47 |
||||
#define DMA_RESET 48 |
||||
#define SPIM0_RESET 49 |
||||
#define SPIM1_RESET 50 |
||||
#define SPIS0_RESET 51 |
||||
#define SPIS1_RESET 52 |
||||
#define DMA_OCP_RESET 53 |
||||
#define EMAC_PTP_RESET 54 |
||||
/* 55 is empty*/ |
||||
#define DMAIF0_RESET 56 |
||||
#define DMAIF1_RESET 57 |
||||
#define DMAIF2_RESET 58 |
||||
#define DMAIF3_RESET 59 |
||||
#define DMAIF4_RESET 60 |
||||
#define DMAIF5_RESET 61 |
||||
#define DMAIF6_RESET 62 |
||||
#define DMAIF7_RESET 63 |
||||
|
||||
/* PER1MODRST */ |
||||
#define WATCHDOG0_RESET 64 |
||||
#define WATCHDOG1_RESET 65 |
||||
#define WATCHDOG2_RESET 66 |
||||
#define WATCHDOG3_RESET 67 |
||||
#define L4SYSTIMER0_RESET 68 |
||||
#define L4SYSTIMER1_RESET 69 |
||||
#define SPTIMER0_RESET 70 |
||||
#define SPTIMER1_RESET 71 |
||||
#define I2C0_RESET 72 |
||||
#define I2C1_RESET 73 |
||||
#define I2C2_RESET 74 |
||||
#define I2C3_RESET 75 |
||||
#define I2C4_RESET 76 |
||||
/* 77-79 is empty */ |
||||
#define UART0_RESET 80 |
||||
#define UART1_RESET 81 |
||||
/* 82-87 is empty */ |
||||
#define GPIO0_RESET 88 |
||||
#define GPIO1_RESET 89 |
||||
|
||||
/* BRGMODRST */ |
||||
#define SOC2FPGA_RESET 96 |
||||
#define LWHPS2FPGA_RESET 97 |
||||
#define FPGA2SOC_RESET 98 |
||||
#define F2SSDRAM0_RESET 99 |
||||
#define F2SSDRAM1_RESET 100 |
||||
#define F2SSDRAM2_RESET 101 |
||||
#define DDRSCH_RESET 102 |
||||
|
||||
/* COLDMODRST */ |
||||
#define CPUPO0_RESET 160 |
||||
#define CPUPO1_RESET 161 |
||||
#define CPUPO2_RESET 162 |
||||
#define CPUPO3_RESET 163 |
||||
/* 164-167 is empty */ |
||||
#define L2_RESET 168 |
||||
|
||||
/* DBGMODRST */ |
||||
#define DBG_RESET 224 |
||||
#define CSDAP_RESET 225 |
||||
|
||||
/* TAPMODRST */ |
||||
#define TAP_RESET 256 |
||||
|
||||
#endif |
@ -0,0 +1,36 @@ |
||||
#ifndef _DT_BINDINGS_RESET_CORTINA_GEMINI_H |
||||
#define _DT_BINDINGS_RESET_CORTINA_GEMINI_H |
||||
|
||||
#define GEMINI_RESET_DRAM 0 |
||||
#define GEMINI_RESET_FLASH 1 |
||||
#define GEMINI_RESET_IDE 2 |
||||
#define GEMINI_RESET_RAID 3 |
||||
#define GEMINI_RESET_SECURITY 4 |
||||
#define GEMINI_RESET_GMAC0 5 |
||||
#define GEMINI_RESET_GMAC1 6 |
||||
#define GEMINI_RESET_PCI 7 |
||||
#define GEMINI_RESET_USB0 8 |
||||
#define GEMINI_RESET_USB1 9 |
||||
#define GEMINI_RESET_DMAC 10 |
||||
#define GEMINI_RESET_APB 11 |
||||
#define GEMINI_RESET_LPC 12 |
||||
#define GEMINI_RESET_LCD 13 |
||||
#define GEMINI_RESET_INTCON0 14 |
||||
#define GEMINI_RESET_INTCON1 15 |
||||
#define GEMINI_RESET_RTC 16 |
||||
#define GEMINI_RESET_TIMER 17 |
||||
#define GEMINI_RESET_UART 18 |
||||
#define GEMINI_RESET_SSP 19 |
||||
#define GEMINI_RESET_GPIO0 20 |
||||
#define GEMINI_RESET_GPIO1 21 |
||||
#define GEMINI_RESET_GPIO2 22 |
||||
#define GEMINI_RESET_WDOG 23 |
||||
#define GEMINI_RESET_EXTERN 24 |
||||
#define GEMINI_RESET_CIR 25 |
||||
#define GEMINI_RESET_SATA0 26 |
||||
#define GEMINI_RESET_SATA1 27 |
||||
#define GEMINI_RESET_TVC 28 |
||||
#define GEMINI_RESET_CPU1 30 |
||||
#define GEMINI_RESET_GLOBAL 31 |
||||
|
||||
#endif |
Loading…
Reference in new issue