ARM: SoC driver updates
Driver updates for ARM SoCs. * Reset subsystem, merged through arm-soc by tradition: - Make bool drivers explicitly non-modular - New support for i.MX7 and Arria10 reset controllers * PATA driver for Palmchip BK371 (acked by Tejun) * Power domain drivers for i.MX (GPC, GPCv2) - Moved out of mach-imx for GPC - Bunch of tweaks, fixes, etc * PMC support for Tegra186 * SoC detection support for Renesas RZ/G1H and RZ/G1N * Move Tegra flow controller driver from mach directory to drivers/soc - (Power management / CPU power driver) * Misc smaller tweaks for other platforms -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJZEAZuAAoJEIwa5zzehBx3jCEP/1dcXY746rQoOMUDPyWF5+SZ w0l8dHUQhu4WjNGryfb9DbyiE3d6xlvPVzr9AJeAg6c5I+iikgeogS0XHNpWCU96 FR1Ftb6zo8DIaGognBL9bK5HM7NXjd/EKBkMk0Ggs9/NRFUnakkbpdfivsl2BACx mCGo15+kbgQSQsMJtd5/KfsgY5h7lXJG0fZ8LV5E1E5BSa/AofZtKVgCKfhbd0zV gQqm7xfxtURHtucc7MYNEoKNk5rlrZhOlG6DdG0d6+rscCBrmL1I5giqm8y24+wW z+JJuk21+oVtltLz09JuX51xur3CGyJ+qNJdRPE1P1Udn7wj5zA+ew9qqJi1cgNf 63tBxooBpH6R8dGcOfjKECD6lBBqBr/Dd8ReWbMyn0XF1HMAxgpfPtExu9WcDzGu 9Fr/shUiEA3jqhbzSy6DCHugpnHPdHPyY64MqzisgOEVsituQ7MSefTIGSNusDlk K36I7j93mDAF5y2fTXqbjZKoRuu6KCySvGDXzBqGwhcNzUQk14iPwjtMDZ/l9Raj sQJCUxHntUovHs+VTCwS7ahqZyn0VRNx2bt1aJXNHKzuUovpA9/X5X9HCRZJDovB 0bCGQZ124+H/VsWvSjVtIh7oknU3vSQJPxS6KLKoi3rvywuqW562lGjCTqvjBJKD FMZ5NA8VoWXM2rgTDOyx =B43K -----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 Olof Johansson: "Driver updates for ARM SoCs: Reset subsystem, merged through arm-soc by tradition: - Make bool drivers explicitly non-modular - New support for i.MX7 and Arria10 reset controllers PATA driver for Palmchip BK371 (acked by Tejun) Power domain drivers for i.MX (GPC, GPCv2) - Moved out of mach-imx for GPC - Bunch of tweaks, fixes, etc PMC support for Tegra186 SoC detection support for Renesas RZ/G1H and RZ/G1N Move Tegra flow controller driver from mach directory to drivers/soc - (Power management / CPU power driver) Misc smaller tweaks for other platforms" * tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (60 commits) soc: pm-domain: Fix the mangled urls soc: renesas: rcar-sysc: Add support for R-Car H3 ES2.0 soc: renesas: rcar-sysc: Add support for fixing up power area tables soc: renesas: Register SoC device early soc: imx: gpc: add workaround for i.MX6QP to the GPC PD driver dt-bindings: imx-gpc: add i.MX6 QuadPlus compatible soc: imx: gpc: add defines for domain index soc: imx: Add GPCv2 power gating driver dt-bindings: Add GPCv2 power gating driver ARM/clk: move the ICST library to drivers/clk ARM: plat-versatile: remove stale clock header ARM: keystone: Drop PM domain support for k2g soc: ti: Add ti_sci_pm_domains driver dt-bindings: Add TI SCI PM Domains PM / Domains: Do not check if simple providers have phandle cells PM / Domains: Add generic data pointer to genpd data struct soc/tegra: Add initial flowctrl support for Tegra132/210 soc/tegra: flowctrl: Add basic platform driver soc/tegra: Move Tegra flowctrl driver ARM: tegra: Remove unnecessary inclusion of flowctrl header ...
This commit is contained in:
commit
0160e00ae8
|
@ -0,0 +1,34 @@
|
|||
NVIDIA Tegra Power Management Controller (PMC)
|
||||
|
||||
Required properties:
|
||||
- compatible: Should contain one of the following:
|
||||
- "nvidia,tegra186-pmc": for Tegra186
|
||||
- reg: Must contain an (offset, length) pair of the register set for each
|
||||
entry in reg-names.
|
||||
- reg-names: Must include the following entries:
|
||||
- "pmc"
|
||||
- "wake"
|
||||
- "aotag"
|
||||
- "scratch"
|
||||
|
||||
Optional properties:
|
||||
- nvidia,invert-interrupt: If present, inverts the PMU interrupt signal.
|
||||
|
||||
Example:
|
||||
|
||||
SoC DTSI:
|
||||
|
||||
pmc@c3600000 {
|
||||
compatible = "nvidia,tegra186-pmc";
|
||||
reg = <0 0x0c360000 0 0x10000>,
|
||||
<0 0x0c370000 0 0x10000>,
|
||||
<0 0x0c380000 0 0x10000>,
|
||||
<0 0x0c390000 0 0x10000>;
|
||||
reg-names = "pmc", "wake", "aotag", "scratch";
|
||||
};
|
||||
|
||||
Board DTS:
|
||||
|
||||
pmc@c360000 {
|
||||
nvidia,invert-interrupt;
|
||||
};
|
|
@ -1,22 +1,42 @@
|
|||
Freescale i.MX General Power Controller
|
||||
=======================================
|
||||
|
||||
The i.MX6Q General Power Control (GPC) block contains DVFS load tracking
|
||||
counters and Power Gating Control (PGC) for the CPU and PU (GPU/VPU) power
|
||||
domains.
|
||||
The i.MX6 General Power Control (GPC) block contains DVFS load tracking
|
||||
counters and Power Gating Control (PGC).
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "fsl,imx6q-gpc" or "fsl,imx6sl-gpc"
|
||||
- compatible: Should be one of the following:
|
||||
- fsl,imx6q-gpc
|
||||
- fsl,imx6qp-gpc
|
||||
- fsl,imx6sl-gpc
|
||||
- reg: should be register base and length as documented in the
|
||||
datasheet
|
||||
- interrupts: Should contain GPC interrupt request 1
|
||||
- pu-supply: Link to the LDO regulator powering the PU power domain
|
||||
- clocks: Clock phandles to devices in the PU power domain that need
|
||||
to be enabled during domain power-up for reset propagation.
|
||||
- #power-domain-cells: Should be 1, see below:
|
||||
- interrupts: Should contain one interrupt specifier for the GPC interrupt
|
||||
- clocks: Must contain an entry for each entry in clock-names.
|
||||
See Documentation/devicetree/bindings/clocks/clock-bindings.txt for details.
|
||||
- clock-names: Must include the following entries:
|
||||
- ipg
|
||||
|
||||
The gpc node is a power-controller as documented by the generic power domain
|
||||
bindings in Documentation/devicetree/bindings/power/power_domain.txt.
|
||||
The power domains are generic power domain providers as documented in
|
||||
Documentation/devicetree/bindings/power/power_domain.txt. They are described as
|
||||
subnodes of the power gating controller 'pgc' node of the GPC and should
|
||||
contain the following:
|
||||
|
||||
Required properties:
|
||||
- reg: Must contain the DOMAIN_INDEX of this power domain
|
||||
The following DOMAIN_INDEX values are valid for i.MX6Q:
|
||||
ARM_DOMAIN 0
|
||||
PU_DOMAIN 1
|
||||
The following additional DOMAIN_INDEX value is valid for i.MX6SL:
|
||||
DISPLAY_DOMAIN 2
|
||||
|
||||
- #power-domain-cells: Should be 0
|
||||
|
||||
Optional properties:
|
||||
- clocks: a number of phandles to clocks that need to be enabled during domain
|
||||
power-up sequencing to ensure reset propagation into devices located inside
|
||||
this power domain
|
||||
- power-supply: a phandle to the regulator powering this domain
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -25,14 +45,30 @@ Example:
|
|||
reg = <0x020dc000 0x4000>;
|
||||
interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<0 90 IRQ_TYPE_LEVEL_HIGH>;
|
||||
pu-supply = <®_pu>;
|
||||
clocks = <&clks IMX6QDL_CLK_GPU3D_CORE>,
|
||||
<&clks IMX6QDL_CLK_GPU3D_SHADER>,
|
||||
<&clks IMX6QDL_CLK_GPU2D_CORE>,
|
||||
<&clks IMX6QDL_CLK_GPU2D_AXI>,
|
||||
<&clks IMX6QDL_CLK_OPENVG_AXI>,
|
||||
<&clks IMX6QDL_CLK_VPU_AXI>;
|
||||
#power-domain-cells = <1>;
|
||||
clocks = <&clks IMX6QDL_CLK_IPG>;
|
||||
clock-names = "ipg";
|
||||
|
||||
pgc {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
power-domain@0 {
|
||||
reg = <0>;
|
||||
#power-domain-cells = <0>;
|
||||
};
|
||||
|
||||
pd_pu: power-domain@1 {
|
||||
reg = <1>;
|
||||
#power-domain-cells = <0>;
|
||||
power-supply = <®_pu>;
|
||||
clocks = <&clks IMX6QDL_CLK_GPU3D_CORE>,
|
||||
<&clks IMX6QDL_CLK_GPU3D_SHADER>,
|
||||
<&clks IMX6QDL_CLK_GPU2D_CORE>,
|
||||
<&clks IMX6QDL_CLK_GPU2D_AXI>,
|
||||
<&clks IMX6QDL_CLK_OPENVG_AXI>,
|
||||
<&clks IMX6QDL_CLK_VPU_AXI>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
@ -40,20 +76,13 @@ Specifying power domain for IP modules
|
|||
======================================
|
||||
|
||||
IP cores belonging to a power domain should contain a 'power-domains' property
|
||||
that is a phandle pointing to the gpc device node and a DOMAIN_INDEX specifying
|
||||
the power domain the device belongs to.
|
||||
that is a phandle pointing to the power domain the device belongs to.
|
||||
|
||||
Example of a device that is part of the PU power domain:
|
||||
|
||||
vpu: vpu@02040000 {
|
||||
reg = <0x02040000 0x3c000>;
|
||||
/* ... */
|
||||
power-domains = <&gpc 1>;
|
||||
power-domains = <&pd_pu>;
|
||||
/* ... */
|
||||
};
|
||||
|
||||
The following DOMAIN_INDEX values are valid for i.MX6Q:
|
||||
ARM_DOMAIN 0
|
||||
PU_DOMAIN 1
|
||||
The following additional DOMAIN_INDEX value is valid for i.MX6SL:
|
||||
DISPLAY_DOMAIN 2
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
Freescale i.MX General Power Controller v2
|
||||
==========================================
|
||||
|
||||
The i.MX7S/D General Power Control (GPC) block contains Power Gating
|
||||
Control (PGC) for various power domains.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: Should be "fsl,imx7d-gpc"
|
||||
|
||||
- reg: should be register base and length as documented in the
|
||||
datasheet
|
||||
|
||||
- interrupts: Should contain GPC interrupt request 1
|
||||
|
||||
Power domains contained within GPC node are generic power domain
|
||||
providers, documented in
|
||||
Documentation/devicetree/bindings/power/power_domain.txt, which are
|
||||
described as subnodes of the power gating controller 'pgc' node,
|
||||
which, in turn, is expected to contain the following:
|
||||
|
||||
Required properties:
|
||||
|
||||
- reg: Power domain index. Valid values are defined in
|
||||
include/dt-bindings/power/imx7-power.h
|
||||
|
||||
- #power-domain-cells: Should be 0
|
||||
|
||||
Optional properties:
|
||||
|
||||
- power-supply: Power supply used to power the domain
|
||||
|
||||
Example:
|
||||
|
||||
gpc: gpc@303a0000 {
|
||||
compatible = "fsl,imx7d-gpc";
|
||||
reg = <0x303a0000 0x1000>;
|
||||
interrupt-controller;
|
||||
interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#interrupt-cells = <3>;
|
||||
interrupt-parent = <&intc>;
|
||||
|
||||
pgc {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pgc_pcie_phy: power-domain@3 {
|
||||
#power-domain-cells = <0>;
|
||||
|
||||
reg = <IMX7_POWER_DOMAIN_PCIE_PHY>;
|
||||
power-supply = <®_1p0d>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Specifying power domain for IP modules
|
||||
======================================
|
||||
|
||||
IP cores belonging to a power domain should contain a 'power-domains'
|
||||
property that is a phandle for PGC node representing the domain.
|
||||
|
||||
Example of a device that is part of the PCIE_PHY power domain:
|
||||
|
||||
pcie: pcie@33800000 {
|
||||
reg = <0x33800000 0x4000>,
|
||||
<0x4ff00000 0x80000>;
|
||||
/* ... */
|
||||
power-domains = <&pgc_pcie_phy>;
|
||||
/* ... */
|
||||
};
|
|
@ -0,0 +1,47 @@
|
|||
Freescale i.MX7 System Reset Controller
|
||||
======================================
|
||||
|
||||
Please also refer to reset.txt in this directory for common reset
|
||||
controller binding usage.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "fsl,imx7-src", "syscon"
|
||||
- reg: should be register base and length as documented in the
|
||||
datasheet
|
||||
- interrupts: Should contain SRC interrupt
|
||||
- #reset-cells: 1, see below
|
||||
|
||||
example:
|
||||
|
||||
src: reset-controller@30390000 {
|
||||
compatible = "fsl,imx7d-src", "syscon";
|
||||
reg = <0x30390000 0x2000>;
|
||||
interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
||||
|
||||
Specifying reset lines connected to IP modules
|
||||
==============================================
|
||||
|
||||
The system reset controller can be used to reset various set of
|
||||
peripherals. Device nodes that need access to reset lines should
|
||||
specify them as a reset phandle in their corresponding node as
|
||||
specified in reset.txt.
|
||||
|
||||
Example:
|
||||
|
||||
pcie: pcie@33800000 {
|
||||
|
||||
...
|
||||
|
||||
resets = <&src IMX7_RESET_PCIEPHY>,
|
||||
<&src IMX7_RESET_PCIE_CTRL_APPS_EN>;
|
||||
reset-names = "pciephy", "apps";
|
||||
|
||||
...
|
||||
};
|
||||
|
||||
|
||||
For list of all valid reset indicies see
|
||||
<dt-bindings/reset/imx7-reset.h>
|
|
@ -0,0 +1,57 @@
|
|||
Texas Instruments TI-SCI Generic Power Domain
|
||||
---------------------------------------------
|
||||
|
||||
Some TI SoCs contain a system controller (like the PMMC, etc...) that is
|
||||
responsible for controlling the state of the IPs that are present.
|
||||
Communication between the host processor running an OS and the system
|
||||
controller happens through a protocol known as TI-SCI [1].
|
||||
|
||||
[1] Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
|
||||
|
||||
PM Domain Node
|
||||
==============
|
||||
The PM domain node represents the global PM domain managed by the PMMC, which
|
||||
in this case is the implementation as documented by the generic PM domain
|
||||
bindings in Documentation/devicetree/bindings/power/power_domain.txt. Because
|
||||
this relies on the TI SCI protocol to communicate with the PMMC it must be a
|
||||
child of the pmmc node.
|
||||
|
||||
Required Properties:
|
||||
--------------------
|
||||
- compatible: should be "ti,sci-pm-domain"
|
||||
- #power-domain-cells: Must be 1 so that an id can be provided in each
|
||||
device node.
|
||||
|
||||
Example (K2G):
|
||||
-------------
|
||||
pmmc: pmmc {
|
||||
compatible = "ti,k2g-sci";
|
||||
...
|
||||
|
||||
k2g_pds: power-controller {
|
||||
compatible = "ti,sci-pm-domain";
|
||||
#power-domain-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
PM Domain Consumers
|
||||
===================
|
||||
Hardware blocks belonging to a PM domain should contain a "power-domains"
|
||||
property that is a phandle pointing to the corresponding PM domain node
|
||||
along with an index representing the device id to be passed to the PMMC
|
||||
for device control.
|
||||
|
||||
Required Properties:
|
||||
--------------------
|
||||
- power-domains: phandle pointing to the corresponding PM domain node
|
||||
and an ID representing the device.
|
||||
|
||||
See dt-bindings/genpd/k2g.h for the list of valid identifiers for k2g.
|
||||
|
||||
Example (K2G):
|
||||
--------------------
|
||||
uart0: serial@02530c00 {
|
||||
compatible = "ns16550a";
|
||||
...
|
||||
power-domains = <&k2g_pds K2G_DEV_UART0>;
|
||||
};
|
|
@ -653,7 +653,9 @@ M: Thor Thayer <thor.thayer@linux.intel.com>
|
|||
S: Maintained
|
||||
F: drivers/gpio/gpio-altera-a10sr.c
|
||||
F: drivers/mfd/altera-a10sr.c
|
||||
F: drivers/reset/reset-a10sr.c
|
||||
F: include/linux/mfd/altera-a10sr.h
|
||||
F: include/dt-bindings/reset/altr,rst-mgr-a10sr.h
|
||||
|
||||
ALTERA TRIPLE SPEED ETHERNET DRIVER
|
||||
M: Vince Bridgers <vbridger@opensource.altera.com>
|
||||
|
@ -1282,6 +1284,7 @@ F: arch/arm/mach-mxs/
|
|||
F: arch/arm/boot/dts/imx*
|
||||
F: arch/arm/configs/imx*_defconfig
|
||||
F: drivers/clk/imx/
|
||||
F: drivers/soc/imx/
|
||||
F: include/soc/imx/
|
||||
|
||||
ARM/FREESCALE VYBRID ARM ARCHITECTURE
|
||||
|
@ -12604,6 +12607,9 @@ S: Maintained
|
|||
F: Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
|
||||
F: drivers/firmware/ti_sci*
|
||||
F: include/linux/soc/ti/ti_sci_protocol.h
|
||||
F: Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
|
||||
F: include/dt-bindings/genpd/k2g.h
|
||||
F: drivers/soc/ti/ti_sci_pm_domains.c
|
||||
|
||||
THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER
|
||||
M: Hans Verkuil <hverkuil@xs4all.nl>
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
config ICST
|
||||
bool
|
||||
|
||||
config SA1111
|
||||
bool
|
||||
select DMABOUNCE if !ARCH_PXA
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
obj-y += firmware.o
|
||||
|
||||
obj-$(CONFIG_ICST) += icst.o
|
||||
obj-$(CONFIG_SA1111) += sa1111.o
|
||||
obj-$(CONFIG_DMABOUNCE) += dmabounce.o
|
||||
obj-$(CONFIG_SHARP_LOCOMO) += locomo.o
|
||||
|
|
|
@ -10,26 +10,17 @@
|
|||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqchip.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/irqchip/arm-gic.h>
|
||||
#include "common.h"
|
||||
#include "hardware.h"
|
||||
|
||||
#define GPC_CNTR 0x000
|
||||
#define GPC_IMR1 0x008
|
||||
#define GPC_PGC_GPU_PDN 0x260
|
||||
#define GPC_PGC_GPU_PUPSCR 0x264
|
||||
#define GPC_PGC_GPU_PDNSCR 0x268
|
||||
#define GPC_PGC_CPU_PDN 0x2a0
|
||||
#define GPC_PGC_CPU_PUPSCR 0x2a4
|
||||
#define GPC_PGC_CPU_PDNSCR 0x2a8
|
||||
|
@ -39,18 +30,6 @@
|
|||
#define IMR_NUM 4
|
||||
#define GPC_MAX_IRQS (IMR_NUM * 32)
|
||||
|
||||
#define GPU_VPU_PUP_REQ BIT(1)
|
||||
#define GPU_VPU_PDN_REQ BIT(0)
|
||||
|
||||
#define GPC_CLK_MAX 6
|
||||
|
||||
struct pu_domain {
|
||||
struct generic_pm_domain base;
|
||||
struct regulator *reg;
|
||||
struct clk *clk[GPC_CLK_MAX];
|
||||
int num_clks;
|
||||
};
|
||||
|
||||
static void __iomem *gpc_base;
|
||||
static u32 gpc_wake_irqs[IMR_NUM];
|
||||
static u32 gpc_saved_imrs[IMR_NUM];
|
||||
|
@ -296,199 +275,3 @@ void __init imx_gpc_check_dt(void)
|
|||
gpc_base = of_iomap(np, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void _imx6q_pm_pu_power_off(struct generic_pm_domain *genpd)
|
||||
{
|
||||
int iso, iso2sw;
|
||||
u32 val;
|
||||
|
||||
/* Read ISO and ISO2SW power down delays */
|
||||
val = readl_relaxed(gpc_base + GPC_PGC_GPU_PDNSCR);
|
||||
iso = val & 0x3f;
|
||||
iso2sw = (val >> 8) & 0x3f;
|
||||
|
||||
/* Gate off PU domain when GPU/VPU when powered down */
|
||||
writel_relaxed(0x1, gpc_base + GPC_PGC_GPU_PDN);
|
||||
|
||||
/* Request GPC to power down GPU/VPU */
|
||||
val = readl_relaxed(gpc_base + GPC_CNTR);
|
||||
val |= GPU_VPU_PDN_REQ;
|
||||
writel_relaxed(val, gpc_base + GPC_CNTR);
|
||||
|
||||
/* Wait ISO + ISO2SW IPG clock cycles */
|
||||
ndelay((iso + iso2sw) * 1000 / 66);
|
||||
}
|
||||
|
||||
static int imx6q_pm_pu_power_off(struct generic_pm_domain *genpd)
|
||||
{
|
||||
struct pu_domain *pu = container_of(genpd, struct pu_domain, base);
|
||||
|
||||
_imx6q_pm_pu_power_off(genpd);
|
||||
|
||||
if (pu->reg)
|
||||
regulator_disable(pu->reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx6q_pm_pu_power_on(struct generic_pm_domain *genpd)
|
||||
{
|
||||
struct pu_domain *pu = container_of(genpd, struct pu_domain, base);
|
||||
int i, ret, sw, sw2iso;
|
||||
u32 val;
|
||||
|
||||
if (pu->reg)
|
||||
ret = regulator_enable(pu->reg);
|
||||
if (pu->reg && ret) {
|
||||
pr_err("%s: failed to enable regulator: %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Enable reset clocks for all devices in the PU domain */
|
||||
for (i = 0; i < pu->num_clks; i++)
|
||||
clk_prepare_enable(pu->clk[i]);
|
||||
|
||||
/* Gate off PU domain when GPU/VPU when powered down */
|
||||
writel_relaxed(0x1, gpc_base + GPC_PGC_GPU_PDN);
|
||||
|
||||
/* Read ISO and ISO2SW power down delays */
|
||||
val = readl_relaxed(gpc_base + GPC_PGC_GPU_PUPSCR);
|
||||
sw = val & 0x3f;
|
||||
sw2iso = (val >> 8) & 0x3f;
|
||||
|
||||
/* Request GPC to power up GPU/VPU */
|
||||
val = readl_relaxed(gpc_base + GPC_CNTR);
|
||||
val |= GPU_VPU_PUP_REQ;
|
||||
writel_relaxed(val, gpc_base + GPC_CNTR);
|
||||
|
||||
/* Wait ISO + ISO2SW IPG clock cycles */
|
||||
ndelay((sw + sw2iso) * 1000 / 66);
|
||||
|
||||
/* Disable reset clocks for all devices in the PU domain */
|
||||
for (i = 0; i < pu->num_clks; i++)
|
||||
clk_disable_unprepare(pu->clk[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct generic_pm_domain imx6q_arm_domain = {
|
||||
.name = "ARM",
|
||||
};
|
||||
|
||||
static struct pu_domain imx6q_pu_domain = {
|
||||
.base = {
|
||||
.name = "PU",
|
||||
.power_off = imx6q_pm_pu_power_off,
|
||||
.power_on = imx6q_pm_pu_power_on,
|
||||
},
|
||||
};
|
||||
|
||||
static struct generic_pm_domain imx6sl_display_domain = {
|
||||
.name = "DISPLAY",
|
||||
};
|
||||
|
||||
static struct generic_pm_domain *imx_gpc_domains[] = {
|
||||
&imx6q_arm_domain,
|
||||
&imx6q_pu_domain.base,
|
||||
&imx6sl_display_domain,
|
||||
};
|
||||
|
||||
static struct genpd_onecell_data imx_gpc_onecell_data = {
|
||||
.domains = imx_gpc_domains,
|
||||
.num_domains = ARRAY_SIZE(imx_gpc_domains),
|
||||
};
|
||||
|
||||
static int imx_gpc_genpd_init(struct device *dev, struct regulator *pu_reg)
|
||||
{
|
||||
struct clk *clk;
|
||||
int i, ret;
|
||||
|
||||
imx6q_pu_domain.reg = pu_reg;
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
clk = of_clk_get(dev->of_node, i);
|
||||
if (IS_ERR(clk))
|
||||
break;
|
||||
if (i >= GPC_CLK_MAX) {
|
||||
dev_err(dev, "more than %d clocks\n", GPC_CLK_MAX);
|
||||
goto clk_err;
|
||||
}
|
||||
imx6q_pu_domain.clk[i] = clk;
|
||||
}
|
||||
imx6q_pu_domain.num_clks = i;
|
||||
|
||||
/* Enable power always in case bootloader disabled it. */
|
||||
imx6q_pm_pu_power_on(&imx6q_pu_domain.base);
|
||||
|
||||
if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS))
|
||||
return 0;
|
||||
|
||||
imx6q_pu_domain.base.states = devm_kzalloc(dev,
|
||||
sizeof(*imx6q_pu_domain.base.states),
|
||||
GFP_KERNEL);
|
||||
if (!imx6q_pu_domain.base.states)
|
||||
return -ENOMEM;
|
||||
|
||||
imx6q_pu_domain.base.states[0].power_off_latency_ns = 25000;
|
||||
imx6q_pu_domain.base.states[0].power_on_latency_ns = 2000000;
|
||||
imx6q_pu_domain.base.state_count = 1;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(imx_gpc_domains); i++)
|
||||
pm_genpd_init(imx_gpc_domains[i], NULL, false);
|
||||
|
||||
ret = of_genpd_add_provider_onecell(dev->of_node,
|
||||
&imx_gpc_onecell_data);
|
||||
if (ret)
|
||||
goto power_off;
|
||||
|
||||
return 0;
|
||||
|
||||
power_off:
|
||||
imx6q_pm_pu_power_off(&imx6q_pu_domain.base);
|
||||
clk_err:
|
||||
while (i--)
|
||||
clk_put(imx6q_pu_domain.clk[i]);
|
||||
imx6q_pu_domain.reg = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int imx_gpc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct regulator *pu_reg;
|
||||
int ret;
|
||||
|
||||
/* bail out if DT too old and doesn't provide the necessary info */
|
||||
if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells"))
|
||||
return 0;
|
||||
|
||||
pu_reg = devm_regulator_get_optional(&pdev->dev, "pu");
|
||||
if (PTR_ERR(pu_reg) == -ENODEV)
|
||||
pu_reg = NULL;
|
||||
if (IS_ERR(pu_reg)) {
|
||||
ret = PTR_ERR(pu_reg);
|
||||
dev_err(&pdev->dev, "failed to get pu regulator: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return imx_gpc_genpd_init(&pdev->dev, pu_reg);
|
||||
}
|
||||
|
||||
static const struct of_device_id imx_gpc_dt_ids[] = {
|
||||
{ .compatible = "fsl,imx6q-gpc" },
|
||||
{ .compatible = "fsl,imx6sl-gpc" },
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct platform_driver imx_gpc_driver = {
|
||||
.driver = {
|
||||
.name = "imx-gpc",
|
||||
.of_match_table = imx_gpc_dt_ids,
|
||||
},
|
||||
.probe = imx_gpc_probe,
|
||||
};
|
||||
|
||||
static int __init imx_pgc_init(void)
|
||||
{
|
||||
return platform_driver_register(&imx_gpc_driver);
|
||||
}
|
||||
subsys_initcall(imx_pgc_init);
|
||||
|
|
|
@ -10,6 +10,7 @@ config ARCH_KEYSTONE
|
|||
select ARCH_SUPPORTS_BIG_ENDIAN
|
||||
select ZONE_DMA if ARM_LPAE
|
||||
select PINCTRL
|
||||
select PM_GENERIC_DOMAINS if PM
|
||||
help
|
||||
Support for boards based on the Texas Instruments Keystone family of
|
||||
SoCs.
|
||||
|
|
|
@ -32,7 +32,9 @@ static struct pm_clk_notifier_block platform_domain_notifier = {
|
|||
};
|
||||
|
||||
static const struct of_device_id of_keystone_table[] = {
|
||||
{.compatible = "ti,keystone"},
|
||||
{.compatible = "ti,k2hk"},
|
||||
{.compatible = "ti,k2e"},
|
||||
{.compatible = "ti,k2l"},
|
||||
{ /* end of list */ },
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ asflags-y += -march=armv7-a
|
|||
|
||||
obj-y += io.o
|
||||
obj-y += irq.o
|
||||
obj-y += flowctrl.o
|
||||
obj-y += pm.o
|
||||
obj-y += reset.o
|
||||
obj-y += reset-handler.o
|
||||
|
|
|
@ -26,12 +26,13 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <soc/tegra/flowctrl.h>
|
||||
|
||||
#include <asm/cpuidle.h>
|
||||
#include <asm/smp_plat.h>
|
||||
#include <asm/suspend.h>
|
||||
|
||||
#include "cpuidle.h"
|
||||
#include "flowctrl.h"
|
||||
#include "iomap.h"
|
||||
#include "irq.h"
|
||||
#include "pm.h"
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/jiffies.h>
|
||||
#include <linux/smp.h>
|
||||
|
||||
#include <soc/tegra/flowctrl.h>
|
||||
#include <soc/tegra/fuse.h>
|
||||
#include <soc/tegra/pmc.h>
|
||||
|
||||
|
@ -30,7 +31,6 @@
|
|||
#include <asm/smp_scu.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "flowctrl.h"
|
||||
#include "iomap.h"
|
||||
#include "reset.h"
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/spinlock.h>
|
||||
#include <linux/suspend.h>
|
||||
|
||||
#include <soc/tegra/flowctrl.h>
|
||||
#include <soc/tegra/fuse.h>
|
||||
#include <soc/tegra/pm.h>
|
||||
#include <soc/tegra/pmc.h>
|
||||
|
@ -38,7 +39,6 @@
|
|||
#include <asm/suspend.h>
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
#include "flowctrl.h"
|
||||
#include "iomap.h"
|
||||
#include "pm.h"
|
||||
#include "reset.h"
|
||||
|
|
|
@ -17,12 +17,12 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
#include <soc/tegra/flowctrl.h>
|
||||
#include <soc/tegra/fuse.h>
|
||||
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/cache.h>
|
||||
|
||||
#include "flowctrl.h"
|
||||
#include "iomap.h"
|
||||
#include "reset.h"
|
||||
#include "sleep.h"
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include <linux/linkage.h>
|
||||
|
||||
#include <soc/tegra/flowctrl.h>
|
||||
|
||||
#include <asm/assembler.h>
|
||||
#include <asm/proc-fns.h>
|
||||
#include <asm/cp15.h>
|
||||
|
@ -27,7 +29,6 @@
|
|||
|
||||
#include "irammap.h"
|
||||
#include "sleep.h"
|
||||
#include "flowctrl.h"
|
||||
|
||||
#define EMC_CFG 0xc
|
||||
#define EMC_ADR_CFG 0x10
|
||||
|
|
|
@ -16,13 +16,13 @@
|
|||
|
||||
#include <linux/linkage.h>
|
||||
|
||||
#include <soc/tegra/flowctrl.h>
|
||||
#include <soc/tegra/fuse.h>
|
||||
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/assembler.h>
|
||||
#include <asm/cache.h>
|
||||
|
||||
#include "flowctrl.h"
|
||||
#include "irammap.h"
|
||||
#include "sleep.h"
|
||||
|
||||
|
|
|
@ -30,8 +30,6 @@
|
|||
#include <asm/hardware/cache-l2x0.h>
|
||||
|
||||
#include "iomap.h"
|
||||
|
||||
#include "flowctrl.h"
|
||||
#include "sleep.h"
|
||||
|
||||
#define CLK_RESET_CCLK_BURST 0x20
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
#include "board.h"
|
||||
#include "common.h"
|
||||
#include "cpuidle.h"
|
||||
#include "flowctrl.h"
|
||||
#include "iomap.h"
|
||||
#include "irq.h"
|
||||
#include "pm.h"
|
||||
|
@ -75,7 +74,6 @@ static void __init tegra_init_early(void)
|
|||
{
|
||||
of_register_trusted_foundations();
|
||||
tegra_cpu_reset_handler_init();
|
||||
tegra_flowctrl_init();
|
||||
}
|
||||
|
||||
static void __init tegra_dt_init_irq(void)
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
#ifndef PLAT_CLOCK_H
|
||||
#define PLAT_CLOCK_H
|
||||
|
||||
#include <asm/hardware/icst.h>
|
||||
|
||||
struct clk_ops {
|
||||
long (*round)(struct clk *, unsigned long);
|
||||
int (*set)(struct clk *, unsigned long);
|
||||
void (*setvco)(struct clk *, struct icst_vco);
|
||||
};
|
||||
|
||||
int icst_clk_set(struct clk *, unsigned long);
|
||||
long icst_clk_round(struct clk *, unsigned long);
|
||||
|
||||
#endif
|
|
@ -518,6 +518,15 @@ config PATA_BF54X
|
|||
|
||||
If unsure, say N.
|
||||
|
||||
config PATA_BK3710
|
||||
tristate "Palmchip BK3710 PATA support"
|
||||
depends on ARCH_DAVINCI
|
||||
help
|
||||
This option enables support for the integrated IDE controller on
|
||||
the TI DaVinci SoC.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config PATA_CMD64X
|
||||
tristate "CMD64x PATA support"
|
||||
depends on PCI
|
||||
|
|
|
@ -51,6 +51,7 @@ obj-$(CONFIG_PATA_ARTOP) += pata_artop.o
|
|||
obj-$(CONFIG_PATA_ATIIXP) += pata_atiixp.o
|
||||
obj-$(CONFIG_PATA_ATP867X) += pata_atp867x.o
|
||||
obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o
|
||||
obj-$(CONFIG_PATA_BK3710) += pata_bk3710.o
|
||||
obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o
|
||||
obj-$(CONFIG_PATA_CS5520) += pata_cs5520.o
|
||||
obj-$(CONFIG_PATA_CS5530) += pata_cs5530.o
|
||||
|
|
|
@ -0,0 +1,382 @@
|
|||
/*
|
||||
* Palmchip BK3710 PATA controller driver
|
||||
*
|
||||
* Copyright (c) 2017 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Based on palm_bk3710.c:
|
||||
*
|
||||
* Copyright (C) 2006 Texas Instruments.
|
||||
* Copyright (C) 2007 MontaVista Software, Inc., <source@mvista.com>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <linux/ata.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/libata.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define DRV_NAME "pata_bk3710"
|
||||
|
||||
#define BK3710_TF_OFFSET 0x1F0
|
||||
#define BK3710_CTL_OFFSET 0x3F6
|
||||
|
||||
#define BK3710_BMISP 0x02
|
||||
#define BK3710_IDETIMP 0x40
|
||||
#define BK3710_UDMACTL 0x48
|
||||
#define BK3710_MISCCTL 0x50
|
||||
#define BK3710_REGSTB 0x54
|
||||
#define BK3710_REGRCVR 0x58
|
||||
#define BK3710_DATSTB 0x5C
|
||||
#define BK3710_DATRCVR 0x60
|
||||
#define BK3710_DMASTB 0x64
|
||||
#define BK3710_DMARCVR 0x68
|
||||
#define BK3710_UDMASTB 0x6C
|
||||
#define BK3710_UDMATRP 0x70
|
||||
#define BK3710_UDMAENV 0x74
|
||||
#define BK3710_IORDYTMP 0x78
|
||||
|
||||
static struct scsi_host_template pata_bk3710_sht = {
|
||||
ATA_BMDMA_SHT(DRV_NAME),
|
||||
};
|
||||
|
||||
static unsigned int ideclk_period; /* in nanoseconds */
|
||||
|
||||
struct pata_bk3710_udmatiming {
|
||||
unsigned int rptime; /* tRP -- Ready to pause time (nsec) */
|
||||
unsigned int cycletime; /* tCYCTYP2/2 -- avg Cycle Time (nsec) */
|
||||
/* tENV is always a minimum of 20 nsec */
|
||||
};
|
||||
|
||||
static const struct pata_bk3710_udmatiming pata_bk3710_udmatimings[6] = {
|
||||
{ 160, 240 / 2 }, /* UDMA Mode 0 */
|
||||
{ 125, 160 / 2 }, /* UDMA Mode 1 */
|
||||
{ 100, 120 / 2 }, /* UDMA Mode 2 */
|
||||
{ 100, 90 / 2 }, /* UDMA Mode 3 */
|
||||
{ 100, 60 / 2 }, /* UDMA Mode 4 */
|
||||
{ 85, 40 / 2 }, /* UDMA Mode 5 */
|
||||
};
|
||||
|
||||
static void pata_bk3710_setudmamode(void __iomem *base, unsigned int dev,
|
||||
unsigned int mode)
|
||||
{
|
||||
u32 val32;
|
||||
u16 val16;
|
||||
u8 tenv, trp, t0;
|
||||
|
||||
/* DMA Data Setup */
|
||||
t0 = DIV_ROUND_UP(pata_bk3710_udmatimings[mode].cycletime,
|
||||
ideclk_period) - 1;
|
||||
tenv = DIV_ROUND_UP(20, ideclk_period) - 1;
|
||||
trp = DIV_ROUND_UP(pata_bk3710_udmatimings[mode].rptime,
|
||||
ideclk_period) - 1;
|
||||
|
||||
/* udmastb Ultra DMA Access Strobe Width */
|
||||
val32 = ioread32(base + BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8));
|
||||
val32 |= t0 << (dev ? 8 : 0);
|
||||
iowrite32(val32, base + BK3710_UDMASTB);
|
||||
|
||||
/* udmatrp Ultra DMA Ready to Pause Time */
|
||||
val32 = ioread32(base + BK3710_UDMATRP) & (0xFF << (dev ? 0 : 8));
|
||||
val32 |= trp << (dev ? 8 : 0);
|
||||
iowrite32(val32, base + BK3710_UDMATRP);
|
||||
|
||||
/* udmaenv Ultra DMA envelop Time */
|
||||
val32 = ioread32(base + BK3710_UDMAENV) & (0xFF << (dev ? 0 : 8));
|
||||
val32 |= tenv << (dev ? 8 : 0);
|
||||
iowrite32(val32, base + BK3710_UDMAENV);
|
||||
|
||||
/* Enable UDMA for Device */
|
||||
val16 = ioread16(base + BK3710_UDMACTL) | (1 << dev);
|
||||
iowrite16(val16, base + BK3710_UDMACTL);
|
||||
}
|
||||
|
||||
static void pata_bk3710_setmwdmamode(void __iomem *base, unsigned int dev,
|
||||
unsigned short min_cycle,
|
||||
unsigned int mode)
|
||||
{
|
||||
const struct ata_timing *t;
|
||||
int cycletime;
|
||||
u32 val32;
|
||||
u16 val16;
|
||||
u8 td, tkw, t0;
|
||||
|
||||
t = ata_timing_find_mode(mode);
|
||||
cycletime = max_t(int, t->cycle, min_cycle);
|
||||
|
||||
/* DMA Data Setup */
|
||||
t0 = DIV_ROUND_UP(cycletime, ideclk_period);
|
||||
td = DIV_ROUND_UP(t->active, ideclk_period);
|
||||
tkw = t0 - td - 1;
|
||||
td--;
|
||||
|
||||
val32 = ioread32(base + BK3710_DMASTB) & (0xFF << (dev ? 0 : 8));
|
||||
val32 |= td << (dev ? 8 : 0);
|
||||
iowrite32(val32, base + BK3710_DMASTB);
|
||||
|
||||
val32 = ioread32(base + BK3710_DMARCVR) & (0xFF << (dev ? 0 : 8));
|
||||
val32 |= tkw << (dev ? 8 : 0);
|
||||
iowrite32(val32, base + BK3710_DMARCVR);
|
||||
|
||||
/* Disable UDMA for Device */
|
||||
val16 = ioread16(base + BK3710_UDMACTL) & ~(1 << dev);
|
||||
iowrite16(val16, base + BK3710_UDMACTL);
|
||||
}
|
||||
|
||||
static void pata_bk3710_set_dmamode(struct ata_port *ap,
|
||||
struct ata_device *adev)
|
||||
{
|
||||
void __iomem *base = (void __iomem *)ap->ioaddr.bmdma_addr;
|
||||
int is_slave = adev->devno;
|
||||
const u8 xferspeed = adev->dma_mode;
|
||||
|
||||
if (xferspeed >= XFER_UDMA_0)
|
||||
pata_bk3710_setudmamode(base, is_slave,
|
||||
xferspeed - XFER_UDMA_0);
|
||||
else
|
||||
pata_bk3710_setmwdmamode(base, is_slave,
|
||||
adev->id[ATA_ID_EIDE_DMA_MIN],
|
||||
xferspeed);
|
||||
}
|
||||
|
||||
static void pata_bk3710_setpiomode(void __iomem *base, struct ata_device *pair,
|
||||
unsigned int dev, unsigned int cycletime,
|
||||
unsigned int mode)
|
||||
{
|
||||
const struct ata_timing *t;
|
||||
u32 val32;
|
||||
u8 t2, t2i, t0;
|
||||
|
||||
t = ata_timing_find_mode(XFER_PIO_0 + mode);
|
||||
|
||||
/* PIO Data Setup */
|
||||
t0 = DIV_ROUND_UP(cycletime, ideclk_period);
|
||||
t2 = DIV_ROUND_UP(t->active, ideclk_period);
|
||||
|
||||
t2i = t0 - t2 - 1;
|
||||
t2--;
|
||||
|
||||
val32 = ioread32(base + BK3710_DATSTB) & (0xFF << (dev ? 0 : 8));
|
||||
val32 |= t2 << (dev ? 8 : 0);
|
||||
iowrite32(val32, base + BK3710_DATSTB);
|
||||
|
||||
val32 = ioread32(base + BK3710_DATRCVR) & (0xFF << (dev ? 0 : 8));
|
||||
val32 |= t2i << (dev ? 8 : 0);
|
||||
iowrite32(val32, base + BK3710_DATRCVR);
|
||||
|
||||
/* FIXME: this is broken also in the old driver */
|
||||
if (pair) {
|
||||
u8 mode2 = pair->pio_mode - XFER_PIO_0;
|
||||
|
||||
if (mode2 < mode)
|
||||
mode = mode2;
|
||||
}
|
||||
|
||||
/* TASKFILE Setup */
|
||||
t0 = DIV_ROUND_UP(t->cyc8b, ideclk_period);
|
||||
t2 = DIV_ROUND_UP(t->act8b, ideclk_period);
|
||||
|
||||
t2i = t0 - t2 - 1;
|
||||
t2--;
|
||||
|
||||
val32 = ioread32(base + BK3710_REGSTB) & (0xFF << (dev ? 0 : 8));
|
||||
val32 |= t2 << (dev ? 8 : 0);
|
||||
iowrite32(val32, base + BK3710_REGSTB);
|
||||
|
||||
val32 = ioread32(base + BK3710_REGRCVR) & (0xFF << (dev ? 0 : 8));
|
||||
val32 |= t2i << (dev ? 8 : 0);
|
||||
iowrite32(val32, base + BK3710_REGRCVR);
|
||||
}
|
||||
|
||||
static void pata_bk3710_set_piomode(struct ata_port *ap,
|
||||
struct ata_device *adev)
|
||||
{
|
||||
void __iomem *base = (void __iomem *)ap->ioaddr.bmdma_addr;
|
||||
struct ata_device *pair = ata_dev_pair(adev);
|
||||
const struct ata_timing *t = ata_timing_find_mode(adev->pio_mode);
|
||||
const u16 *id = adev->id;
|
||||
unsigned int cycle_time = 0;
|
||||
int is_slave = adev->devno;
|
||||
const u8 pio = adev->pio_mode - XFER_PIO_0;
|
||||
|
||||
if (id[ATA_ID_FIELD_VALID] & 2) {
|
||||
if (ata_id_has_iordy(id))
|
||||
cycle_time = id[ATA_ID_EIDE_PIO_IORDY];
|
||||
else
|
||||
cycle_time = id[ATA_ID_EIDE_PIO];
|
||||
|
||||
/* conservative "downgrade" for all pre-ATA2 drives */
|
||||
if (pio < 3 && cycle_time < t->cycle)
|
||||
cycle_time = 0; /* use standard timing */
|
||||
}
|
||||
|
||||
if (!cycle_time)
|
||||
cycle_time = t->cycle;
|
||||
|
||||
pata_bk3710_setpiomode(base, pair, is_slave, cycle_time, pio);
|
||||
}
|
||||
|
||||
static void pata_bk3710_chipinit(void __iomem *base)
|
||||
{
|
||||
/*
|
||||
* REVISIT: the ATA reset signal needs to be managed through a
|
||||
* GPIO, which means it should come from platform_data. Until
|
||||
* we get and use such information, we have to trust that things
|
||||
* have been reset before we get here.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program the IDETIMP Register Value based on the following assumptions
|
||||
*
|
||||
* (ATA_IDETIMP_IDEEN , ENABLE ) |
|
||||
* (ATA_IDETIMP_PREPOST1 , DISABLE) |
|
||||
* (ATA_IDETIMP_PREPOST0 , DISABLE) |
|
||||
*
|
||||
* DM6446 silicon rev 2.1 and earlier have no observed net benefit
|
||||
* from enabling prefetch/postwrite.
|
||||
*/
|
||||
iowrite16(BIT(15), base + BK3710_IDETIMP);
|
||||
|
||||
/*
|
||||
* UDMACTL Ultra-ATA DMA Control
|
||||
* (ATA_UDMACTL_UDMAP1 , 0 ) |
|
||||
* (ATA_UDMACTL_UDMAP0 , 0 )
|
||||
*
|
||||
*/
|
||||
iowrite16(0, base + BK3710_UDMACTL);
|
||||
|
||||
/*
|
||||
* MISCCTL Miscellaneous Conrol Register
|
||||
* (ATA_MISCCTL_HWNHLD1P , 1 cycle)
|
||||
* (ATA_MISCCTL_HWNHLD0P , 1 cycle)
|
||||
* (ATA_MISCCTL_TIMORIDE , 1)
|
||||
*/
|
||||
iowrite32(0x001, base + BK3710_MISCCTL);
|
||||
|
||||
/*
|
||||
* IORDYTMP IORDY Timer for Primary Register
|
||||
* (ATA_IORDYTMP_IORDYTMP , DISABLE)
|
||||
*/
|
||||
iowrite32(0, base + BK3710_IORDYTMP);
|
||||
|
||||
/*
|
||||
* Configure BMISP Register
|
||||
* (ATA_BMISP_DMAEN1 , DISABLE ) |
|
||||
* (ATA_BMISP_DMAEN0 , DISABLE ) |
|
||||
* (ATA_BMISP_IORDYINT , CLEAR) |
|
||||
* (ATA_BMISP_INTRSTAT , CLEAR) |
|
||||
* (ATA_BMISP_DMAERROR , CLEAR)
|
||||
*/
|
||||
iowrite16(0xE, base + BK3710_BMISP);
|
||||
|
||||
pata_bk3710_setpiomode(base, NULL, 0, 600, 0);
|
||||
pata_bk3710_setpiomode(base, NULL, 1, 600, 0);
|
||||
}
|
||||
|
||||
static struct ata_port_operations pata_bk3710_ports_ops = {
|
||||
.inherits = &ata_bmdma_port_ops,
|
||||
.cable_detect = ata_cable_80wire,
|
||||
|
||||
.set_piomode = pata_bk3710_set_piomode,
|
||||
.set_dmamode = pata_bk3710_set_dmamode,
|
||||
};
|
||||
|
||||
static int __init pata_bk3710_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct resource *mem;
|
||||
struct ata_host *host;
|
||||
struct ata_port *ap;
|
||||
void __iomem *base;
|
||||
unsigned long rate;
|
||||
int irq;
|
||||
|
||||
clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(clk))
|
||||
return -ENODEV;
|
||||
|
||||
clk_enable(clk);
|
||||
rate = clk_get_rate(clk);
|
||||
if (!rate)
|
||||
return -EINVAL;
|
||||
|
||||
/* NOTE: round *down* to meet minimum timings; we count in clocks */
|
||||
ideclk_period = 1000000000UL / rate;
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
pr_err(DRV_NAME ": failed to get IRQ resource\n");
|
||||
return irq;
|
||||
}
|
||||
|
||||
base = devm_ioremap_resource(&pdev->dev, mem);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
/* configure the Palmchip controller */
|
||||
pata_bk3710_chipinit(base);
|
||||
|
||||
/* allocate host */
|
||||
host = ata_host_alloc(&pdev->dev, 1);
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
ap = host->ports[0];
|
||||
|
||||
ap->ops = &pata_bk3710_ports_ops;
|
||||
ap->pio_mask = ATA_PIO4;
|
||||
ap->mwdma_mask = ATA_MWDMA2;
|
||||
ap->udma_mask = rate < 100000000 ? ATA_UDMA4 : ATA_UDMA5;
|
||||
ap->flags |= ATA_FLAG_SLAVE_POSS;
|
||||
|
||||
ap->ioaddr.data_addr = base + BK3710_TF_OFFSET;
|
||||
ap->ioaddr.error_addr = base + BK3710_TF_OFFSET + 1;
|
||||
ap->ioaddr.feature_addr = base + BK3710_TF_OFFSET + 1;
|
||||
ap->ioaddr.nsect_addr = base + BK3710_TF_OFFSET + 2;
|
||||
ap->ioaddr.lbal_addr = base + BK3710_TF_OFFSET + 3;
|
||||
ap->ioaddr.lbam_addr = base + BK3710_TF_OFFSET + 4;
|
||||
ap->ioaddr.lbah_addr = base + BK3710_TF_OFFSET + 5;
|
||||
ap->ioaddr.device_addr = base + BK3710_TF_OFFSET + 6;
|
||||
ap->ioaddr.status_addr = base + BK3710_TF_OFFSET + 7;
|
||||
ap->ioaddr.command_addr = base + BK3710_TF_OFFSET + 7;
|
||||
|
||||
ap->ioaddr.altstatus_addr = base + BK3710_CTL_OFFSET;
|
||||
ap->ioaddr.ctl_addr = base + BK3710_CTL_OFFSET;
|
||||
|
||||
ap->ioaddr.bmdma_addr = base;
|
||||
|
||||
ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx",
|
||||
(unsigned long)base + BK3710_TF_OFFSET,
|
||||
(unsigned long)base + BK3710_CTL_OFFSET);
|
||||
|
||||
/* activate */
|
||||
return ata_host_activate(host, irq, ata_sff_interrupt, 0,
|
||||
&pata_bk3710_sht);
|
||||
}
|
||||
|
||||
/* work with hotplug and coldplug */
|
||||
MODULE_ALIAS("platform:palm_bk3710");
|
||||
|
||||
static struct platform_driver pata_bk3710_driver = {
|
||||
.driver = {
|
||||
.name = "palm_bk3710",
|
||||
},
|
||||
};
|
||||
|
||||
static int __init pata_bk3710_init(void)
|
||||
{
|
||||
return platform_driver_probe(&pata_bk3710_driver, pata_bk3710_probe);
|
||||
}
|
||||
|
||||
module_init(pata_bk3710_init);
|
||||
MODULE_LICENSE("GPL");
|
|
@ -1636,8 +1636,6 @@ static struct generic_pm_domain *genpd_xlate_simple(
|
|||
struct of_phandle_args *genpdspec,
|
||||
void *data)
|
||||
{
|
||||
if (genpdspec->args_count != 0)
|
||||
return ERR_PTR(-EINVAL);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
|
|
@ -109,15 +109,18 @@ static void soc_release(struct device *dev)
|
|||
kfree(soc_dev);
|
||||
}
|
||||
|
||||
static struct soc_device_attribute *early_soc_dev_attr;
|
||||
|
||||
struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr)
|
||||
{
|
||||
struct soc_device *soc_dev;
|
||||
int ret;
|
||||
|
||||
if (!soc_bus_type.p) {
|
||||
ret = bus_register(&soc_bus_type);
|
||||
if (ret)
|
||||
goto out1;
|
||||
if (early_soc_dev_attr)
|
||||
return ERR_PTR(-EBUSY);
|
||||
early_soc_dev_attr = soc_dev_attr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
soc_dev = kzalloc(sizeof(*soc_dev), GFP_KERNEL);
|
||||
|
@ -159,43 +162,51 @@ void soc_device_unregister(struct soc_device *soc_dev)
|
|||
ida_simple_remove(&soc_ida, soc_dev->soc_dev_num);
|
||||
|
||||
device_unregister(&soc_dev->dev);
|
||||
early_soc_dev_attr = NULL;
|
||||
}
|
||||
|
||||
static int __init soc_bus_register(void)
|
||||
{
|
||||
if (soc_bus_type.p)
|
||||
return 0;
|
||||
int ret;
|
||||
|
||||
return bus_register(&soc_bus_type);
|
||||
ret = bus_register(&soc_bus_type);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (early_soc_dev_attr)
|
||||
return PTR_ERR(soc_device_register(early_soc_dev_attr));
|
||||
|
||||
return 0;
|
||||
}
|
||||
core_initcall(soc_bus_register);
|
||||
|
||||
static int soc_device_match_attr(const struct soc_device_attribute *attr,
|
||||
const struct soc_device_attribute *match)
|
||||
{
|
||||
if (match->machine &&
|
||||
(!attr->machine || !glob_match(match->machine, attr->machine)))
|
||||
return 0;
|
||||
|
||||
if (match->family &&
|
||||
(!attr->family || !glob_match(match->family, attr->family)))
|
||||
return 0;
|
||||
|
||||
if (match->revision &&
|
||||
(!attr->revision || !glob_match(match->revision, attr->revision)))
|
||||
return 0;
|
||||
|
||||
if (match->soc_id &&
|
||||
(!attr->soc_id || !glob_match(match->soc_id, attr->soc_id)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int soc_device_match_one(struct device *dev, void *arg)
|
||||
{
|
||||
struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
|
||||
const struct soc_device_attribute *match = arg;
|
||||
|
||||
if (match->machine &&
|
||||
(!soc_dev->attr->machine ||
|
||||
!glob_match(match->machine, soc_dev->attr->machine)))
|
||||
return 0;
|
||||
|
||||
if (match->family &&
|
||||
(!soc_dev->attr->family ||
|
||||
!glob_match(match->family, soc_dev->attr->family)))
|
||||
return 0;
|
||||
|
||||
if (match->revision &&
|
||||
(!soc_dev->attr->revision ||
|
||||
!glob_match(match->revision, soc_dev->attr->revision)))
|
||||
return 0;
|
||||
|
||||
if (match->soc_id &&
|
||||
(!soc_dev->attr->soc_id ||
|
||||
!glob_match(match->soc_id, soc_dev->attr->soc_id)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
return soc_device_match_attr(soc_dev->attr, arg);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -230,6 +241,11 @@ const struct soc_device_attribute *soc_device_match(
|
|||
break;
|
||||
ret = bus_for_each_dev(&soc_bus_type, NULL, (void *)matches,
|
||||
soc_device_match_one);
|
||||
if (ret < 0 && early_soc_dev_attr)
|
||||
ret = soc_device_match_attr(early_soc_dev_attr,
|
||||
matches);
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
if (!ret)
|
||||
matches++;
|
||||
else
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
config ICST
|
||||
bool
|
||||
|
||||
config COMMON_CLK_VERSATILE
|
||||
bool "Clock driver for ARM Reference designs"
|
||||
depends on ARCH_INTEGRATOR || ARCH_REALVIEW || \
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Makefile for Versatile-specific clocks
|
||||
obj-$(CONFIG_ICST) += clk-icst.o clk-versatile.o
|
||||
obj-$(CONFIG_ICST) += icst.o clk-icst.o clk-versatile.o
|
||||
obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o
|
||||
obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o
|
||||
obj-$(CONFIG_CLK_SP810) += clk-sp810.o
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/regmap.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
|
||||
#include "icst.h"
|
||||
#include "clk-icst.h"
|
||||
|
||||
/* Magic unlocking token used on all Versatile boards */
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#include <asm/hardware/icst.h>
|
||||
|
||||
/**
|
||||
* struct clk_icst_desc - descriptor for the ICST VCO
|
||||
* @params: ICST parameters
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/platform_data/clk-integrator.h>
|
||||
|
||||
#include "icst.h"
|
||||
#include "clk-icst.h"
|
||||
|
||||
#define IMPD1_OSC1 0x00
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
#include "icst.h"
|
||||
#include "clk-icst.h"
|
||||
|
||||
#define REALVIEW_SYS_OSC0_OFFSET 0x0C
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#include "icst.h"
|
||||
#include "clk-icst.h"
|
||||
|
||||
#define INTEGRATOR_HDR_LOCK_OFFSET 0x14
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/div64.h>
|
||||
#include <asm/hardware/icst.h>
|
||||
#include "icst.h"
|
||||
|
||||
/*
|
||||
* Divisors for each OD setting.
|
|
@ -1,6 +1,4 @@
|
|||
/*
|
||||
* arch/arm/include/asm/hardware/icst.h
|
||||
*
|
||||
* Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -11,8 +9,8 @@
|
|||
* clock generators. See http://www.idt.com/ for more information
|
||||
* on these devices.
|
||||
*/
|
||||
#ifndef ASMARM_HARDWARE_ICST_H
|
||||
#define ASMARM_HARDWARE_ICST_H
|
||||
#ifndef ICST_H
|
||||
#define ICST_H
|
||||
|
||||
struct icst_params {
|
||||
unsigned long ref;
|
|
@ -538,7 +538,7 @@ static int scpi_send_message(u8 idx, void *tx_buf, unsigned int tx_len,
|
|||
msg->tx_len = tx_len;
|
||||
msg->rx_buf = rx_buf;
|
||||
msg->rx_len = rx_len;
|
||||
init_completion(&msg->done);
|
||||
reinit_completion(&msg->done);
|
||||
|
||||
ret = mbox_send_message(scpi_chan->chan, msg);
|
||||
if (ret < 0 || !rx_buf)
|
||||
|
@ -872,8 +872,11 @@ static int scpi_alloc_xfer_list(struct device *dev, struct scpi_chan *ch)
|
|||
return -ENOMEM;
|
||||
|
||||
ch->xfers = xfers;
|
||||
for (i = 0; i < MAX_SCPI_XFERS; i++, xfers++)
|
||||
for (i = 0; i < MAX_SCPI_XFERS; i++, xfers++) {
|
||||
init_completion(&xfers->done);
|
||||
list_add_tail(&xfers->node, &ch->xfers_list);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -127,6 +127,7 @@ EXPORT_SYMBOL(meson_sm_call);
|
|||
* meson_sm_call_read - retrieve data from secure-monitor
|
||||
*
|
||||
* @buffer: Buffer to store the retrieved data
|
||||
* @bsize: Size of the buffer
|
||||
* @cmd_index: Index of the SMC32 function ID
|
||||
* @arg0: SMC32 Argument 0
|
||||
* @arg1: SMC32 Argument 1
|
||||
|
@ -135,11 +136,14 @@ EXPORT_SYMBOL(meson_sm_call);
|
|||
* @arg4: SMC32 Argument 4
|
||||
*
|
||||
* Return: size of read data on success, a negative value on error
|
||||
* When 0 is returned there is no guarantee about the amount of
|
||||
* data read and bsize bytes are copied in buffer.
|
||||
*/
|
||||
int meson_sm_call_read(void *buffer, unsigned int cmd_index, u32 arg0,
|
||||
u32 arg1, u32 arg2, u32 arg3, u32 arg4)
|
||||
int meson_sm_call_read(void *buffer, unsigned int bsize, unsigned int cmd_index,
|
||||
u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
|
||||
{
|
||||
u32 size;
|
||||
int ret;
|
||||
|
||||
if (!fw.chip)
|
||||
return -ENOENT;
|
||||
|
@ -147,16 +151,24 @@ int meson_sm_call_read(void *buffer, unsigned int cmd_index, u32 arg0,
|
|||
if (!fw.chip->cmd_shmem_out_base)
|
||||
return -EINVAL;
|
||||
|
||||
if (bsize > fw.chip->shmem_size)
|
||||
return -EINVAL;
|
||||
|
||||
if (meson_sm_call(cmd_index, &size, arg0, arg1, arg2, arg3, arg4) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (!size || size > fw.chip->shmem_size)
|
||||
if (size > bsize)
|
||||
return -EINVAL;
|
||||
|
||||
ret = size;
|
||||
|
||||
if (!size)
|
||||
size = bsize;
|
||||
|
||||
if (buffer)
|
||||
memcpy(buffer, fw.sm_shmem_out_base, size);
|
||||
|
||||
return size;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(meson_sm_call_read);
|
||||
|
||||
|
|
|
@ -578,3 +578,21 @@ int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id)
|
|||
|
||||
return ret ? : le32_to_cpu(scm_ret);
|
||||
}
|
||||
|
||||
int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id,
|
||||
u32 spare)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare,
|
||||
size_t *size)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size,
|
||||
u32 spare)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
|
|
@ -381,3 +381,61 @@ int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id)
|
|||
|
||||
return ret ? : res.a1;
|
||||
}
|
||||
|
||||
int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare)
|
||||
{
|
||||
struct qcom_scm_desc desc = {0};
|
||||
struct arm_smccc_res res;
|
||||
int ret;
|
||||
|
||||
desc.args[0] = device_id;
|
||||
desc.args[1] = spare;
|
||||
desc.arginfo = QCOM_SCM_ARGS(2);
|
||||
|
||||
ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP, QCOM_SCM_RESTORE_SEC_CFG,
|
||||
&desc, &res);
|
||||
|
||||
return ret ? : res.a1;
|
||||
}
|
||||
|
||||
int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare,
|
||||
size_t *size)
|
||||
{
|
||||
struct qcom_scm_desc desc = {0};
|
||||
struct arm_smccc_res res;
|
||||
int ret;
|
||||
|
||||
desc.args[0] = spare;
|
||||
desc.arginfo = QCOM_SCM_ARGS(1);
|
||||
|
||||
ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP,
|
||||
QCOM_SCM_IOMMU_SECURE_PTBL_SIZE, &desc, &res);
|
||||
|
||||
if (size)
|
||||
*size = res.a1;
|
||||
|
||||
return ret ? : res.a2;
|
||||
}
|
||||
|
||||
int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size,
|
||||
u32 spare)
|
||||
{
|
||||
struct qcom_scm_desc desc = {0};
|
||||
struct arm_smccc_res res;
|
||||
int ret;
|
||||
|
||||
desc.args[0] = addr;
|
||||
desc.args[1] = size;
|
||||
desc.args[2] = spare;
|
||||
desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_RW, QCOM_SCM_VAL,
|
||||
QCOM_SCM_VAL);
|
||||
|
||||
ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP,
|
||||
QCOM_SCM_IOMMU_SECURE_PTBL_INIT, &desc, &res);
|
||||
|
||||
/* the pg table has been initialized already, ignore the error */
|
||||
if (ret == -EPERM)
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -315,6 +315,24 @@ static const struct reset_control_ops qcom_scm_pas_reset_ops = {
|
|||
.deassert = qcom_scm_pas_reset_deassert,
|
||||
};
|
||||
|
||||
int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare)
|
||||
{
|
||||
return __qcom_scm_restore_sec_cfg(__scm->dev, device_id, spare);
|
||||
}
|
||||
EXPORT_SYMBOL(qcom_scm_restore_sec_cfg);
|
||||
|
||||
int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size)
|
||||
{
|
||||
return __qcom_scm_iommu_secure_ptbl_size(__scm->dev, spare, size);
|
||||
}
|
||||
EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_size);
|
||||
|
||||
int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare)
|
||||
{
|
||||
return __qcom_scm_iommu_secure_ptbl_init(__scm->dev, addr, size, spare);
|
||||
}
|
||||
EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_init);
|
||||
|
||||
/**
|
||||
* qcom_scm_is_available() - Checks if SCM is available
|
||||
*/
|
||||
|
|
|
@ -85,4 +85,15 @@ static inline int qcom_scm_remap_error(int err)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
#define QCOM_SCM_SVC_MP 0xc
|
||||
#define QCOM_SCM_RESTORE_SEC_CFG 2
|
||||
extern int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id,
|
||||
u32 spare);
|
||||
#define QCOM_SCM_IOMMU_SECURE_PTBL_SIZE 3
|
||||
#define QCOM_SCM_IOMMU_SECURE_PTBL_INIT 4
|
||||
extern int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare,
|
||||
size_t *size);
|
||||
extern int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr,
|
||||
u32 size, u32 spare);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -27,7 +27,7 @@ static int meson_efuse_read(void *context, unsigned int offset,
|
|||
u8 *buf = val;
|
||||
int ret;
|
||||
|
||||
ret = meson_sm_call_read(buf, SM_EFUSE_READ, offset,
|
||||
ret = meson_sm_call_read(buf, bytes, SM_EFUSE_READ, offset,
|
||||
bytes, 0, 0, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
|
@ -14,6 +14,13 @@ menuconfig RESET_CONTROLLER
|
|||
|
||||
if RESET_CONTROLLER
|
||||
|
||||
config RESET_A10SR
|
||||
tristate "Altera Arria10 System Resource Reset"
|
||||
depends on MFD_ALTERA_A10SR
|
||||
help
|
||||
This option enables support for the external reset functions for
|
||||
peripheral PHYs on the Altera Arria10 System Resource Chip.
|
||||
|
||||
config RESET_ATH79
|
||||
bool "AR71xx Reset Driver" if COMPILE_TEST
|
||||
default ATH79
|
||||
|
@ -27,6 +34,13 @@ config RESET_BERLIN
|
|||
help
|
||||
This enables the reset controller driver for Marvell Berlin SoCs.
|
||||
|
||||
config RESET_IMX7
|
||||
bool "i.MX7 Reset Driver" if COMPILE_TEST
|
||||
default SOC_IMX7D
|
||||
select MFD_SYSCON
|
||||
help
|
||||
This enables the reset controller driver for i.MX7 SoCs.
|
||||
|
||||
config RESET_LPC18XX
|
||||
bool "LPC18xx/43xx Reset Driver" if COMPILE_TEST
|
||||
default ARCH_LPC18XX
|
||||
|
|
|
@ -2,8 +2,10 @@ obj-y += core.o
|
|||
obj-y += hisilicon/
|
||||
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_BERLIN) += reset-berlin.o
|
||||
obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
|
||||
obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
|
||||
obj-$(CONFIG_RESET_MESON) += reset-meson.o
|
||||
obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
|
||||
|
@ -15,3 +17,4 @@ obj-$(CONFIG_TI_SYSCON_RESET) += 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
|
||||
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* Copyright Intel Corporation (C) 2017. 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/>.
|
||||
*
|
||||
* Reset driver for Altera Arria10 MAX5 System Resource Chip
|
||||
*
|
||||
* Adapted from reset-socfpga.c
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/mfd/altera-a10sr.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset-controller.h>
|
||||
|
||||
#include <dt-bindings/reset/altr,rst-mgr-a10sr.h>
|
||||
|
||||
struct a10sr_reset {
|
||||
struct reset_controller_dev rcdev;
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
static inline struct a10sr_reset *to_a10sr_rst(struct reset_controller_dev *rc)
|
||||
{
|
||||
return container_of(rc, struct a10sr_reset, rcdev);
|
||||
}
|
||||
|
||||
static inline int a10sr_reset_shift(unsigned long id)
|
||||
{
|
||||
switch (id) {
|
||||
case A10SR_RESET_ENET_HPS:
|
||||
return 1;
|
||||
case A10SR_RESET_PCIE:
|
||||
case A10SR_RESET_FILE:
|
||||
case A10SR_RESET_BQSPI:
|
||||
case A10SR_RESET_USB:
|
||||
return id + 11;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int a10sr_reset_update(struct reset_controller_dev *rcdev,
|
||||
unsigned long id, bool assert)
|
||||
{
|
||||
struct a10sr_reset *a10r = to_a10sr_rst(rcdev);
|
||||
int offset = a10sr_reset_shift(id);
|
||||
u8 mask = ALTR_A10SR_REG_BIT_MASK(offset);
|
||||
int index = ALTR_A10SR_HPS_RST_REG + ALTR_A10SR_REG_OFFSET(offset);
|
||||
|
||||
return regmap_update_bits(a10r->regmap, index, mask, assert ? 0 : mask);
|
||||
}
|
||||
|
||||
static int a10sr_reset_assert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
return a10sr_reset_update(rcdev, id, true);
|
||||
}
|
||||
|
||||
static int a10sr_reset_deassert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
return a10sr_reset_update(rcdev, id, false);
|
||||
}
|
||||
|
||||
static int a10sr_reset_status(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
int ret;
|
||||
struct a10sr_reset *a10r = to_a10sr_rst(rcdev);
|
||||
int offset = a10sr_reset_shift(id);
|
||||
u8 mask = ALTR_A10SR_REG_BIT_MASK(offset);
|
||||
int index = ALTR_A10SR_HPS_RST_REG + ALTR_A10SR_REG_OFFSET(offset);
|
||||
unsigned int value;
|
||||
|
||||
ret = regmap_read(a10r->regmap, index, &value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return !!(value & mask);
|
||||
}
|
||||
|
||||
static const struct reset_control_ops a10sr_reset_ops = {
|
||||
.assert = a10sr_reset_assert,
|
||||
.deassert = a10sr_reset_deassert,
|
||||
.status = a10sr_reset_status,
|
||||
};
|
||||
|
||||
static int a10sr_reset_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct altr_a10sr *a10sr = dev_get_drvdata(pdev->dev.parent);
|
||||
struct a10sr_reset *a10r;
|
||||
|
||||
a10r = devm_kzalloc(&pdev->dev, sizeof(struct a10sr_reset),
|
||||
GFP_KERNEL);
|
||||
if (!a10r)
|
||||
return -ENOMEM;
|
||||
|
||||
a10r->rcdev.owner = THIS_MODULE;
|
||||
a10r->rcdev.nr_resets = A10SR_RESET_NUM;
|
||||
a10r->rcdev.ops = &a10sr_reset_ops;
|
||||
a10r->rcdev.of_node = pdev->dev.of_node;
|
||||
a10r->regmap = a10sr->regmap;
|
||||
|
||||
platform_set_drvdata(pdev, a10r);
|
||||
|
||||
return devm_reset_controller_register(&pdev->dev, &a10r->rcdev);
|
||||
}
|
||||
|
||||
static const struct of_device_id a10sr_reset_of_match[] = {
|
||||
{ .compatible = "altr,a10sr-reset" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, a10sr_reset_of_match);
|
||||
|
||||
static struct platform_driver a10sr_reset_driver = {
|
||||
.probe = a10sr_reset_probe,
|
||||
.driver = {
|
||||
.name = "altr_a10sr_reset",
|
||||
},
|
||||
};
|
||||
module_platform_driver(a10sr_reset_driver);
|
||||
|
||||
MODULE_AUTHOR("Thor Thayer <thor.thayer@linux.intel.com>");
|
||||
MODULE_DESCRIPTION("Altera Arria10 System Resource Reset Controller Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -1,4 +1,7 @@
|
|||
/*
|
||||
* AR71xx Reset Controller Driver
|
||||
* Author: Alban Bedel
|
||||
*
|
||||
* Copyright (C) 2015 Alban Bedel <albeu@free.fr>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -13,7 +16,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/reboot.h>
|
||||
|
@ -127,31 +130,17 @@ static int ath79_reset_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ath79_reset_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ath79_reset *ath79_reset = platform_get_drvdata(pdev);
|
||||
|
||||
unregister_restart_handler(&ath79_reset->restart_nb);
|
||||
|
||||
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,
|
||||
.name = "ath79-reset",
|
||||
.of_match_table = ath79_reset_dt_ids,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
};
|
||||
module_platform_driver(ath79_reset_driver);
|
||||
|
||||
MODULE_AUTHOR("Alban Bedel <albeu@free.fr>");
|
||||
MODULE_DESCRIPTION("AR71xx Reset Controller Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
builtin_platform_driver(ath79_reset_driver);
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Impinj, Inc.
|
||||
*
|
||||
* i.MX7 System Reset Controller (SRC) driver
|
||||
*
|
||||
* Author: Andrey Smirnov <andrew.smirnov@gmail.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; version 2 of the License.
|
||||
*
|
||||
* 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/mfd/syscon.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <dt-bindings/reset/imx7-reset.h>
|
||||
|
||||
struct imx7_src {
|
||||
struct reset_controller_dev rcdev;
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
enum imx7_src_registers {
|
||||
SRC_A7RCR0 = 0x0004,
|
||||
SRC_M4RCR = 0x000c,
|
||||
SRC_ERCR = 0x0014,
|
||||
SRC_HSICPHY_RCR = 0x001c,
|
||||
SRC_USBOPHY1_RCR = 0x0020,
|
||||
SRC_USBOPHY2_RCR = 0x0024,
|
||||
SRC_MIPIPHY_RCR = 0x0028,
|
||||
SRC_PCIEPHY_RCR = 0x002c,
|
||||
SRC_DDRC_RCR = 0x1000,
|
||||
};
|
||||
|
||||
struct imx7_src_signal {
|
||||
unsigned int offset, bit;
|
||||
};
|
||||
|
||||
static const struct imx7_src_signal imx7_src_signals[IMX7_RESET_NUM] = {
|
||||
[IMX7_RESET_A7_CORE_POR_RESET0] = { SRC_A7RCR0, BIT(0) },
|
||||
[IMX7_RESET_A7_CORE_POR_RESET1] = { SRC_A7RCR0, BIT(1) },
|
||||
[IMX7_RESET_A7_CORE_RESET0] = { SRC_A7RCR0, BIT(4) },
|
||||
[IMX7_RESET_A7_CORE_RESET1] = { SRC_A7RCR0, BIT(5) },
|
||||
[IMX7_RESET_A7_DBG_RESET0] = { SRC_A7RCR0, BIT(8) },
|
||||
[IMX7_RESET_A7_DBG_RESET1] = { SRC_A7RCR0, BIT(9) },
|
||||
[IMX7_RESET_A7_ETM_RESET0] = { SRC_A7RCR0, BIT(12) },
|
||||
[IMX7_RESET_A7_ETM_RESET1] = { SRC_A7RCR0, BIT(13) },
|
||||
[IMX7_RESET_A7_SOC_DBG_RESET] = { SRC_A7RCR0, BIT(20) },
|
||||
[IMX7_RESET_A7_L2RESET] = { SRC_A7RCR0, BIT(21) },
|
||||
[IMX7_RESET_SW_M4C_RST] = { SRC_M4RCR, BIT(1) },
|
||||
[IMX7_RESET_SW_M4P_RST] = { SRC_M4RCR, BIT(2) },
|
||||
[IMX7_RESET_EIM_RST] = { SRC_ERCR, BIT(0) },
|
||||
[IMX7_RESET_HSICPHY_PORT_RST] = { SRC_HSICPHY_RCR, BIT(1) },
|
||||
[IMX7_RESET_USBPHY1_POR] = { SRC_USBOPHY1_RCR, BIT(0) },
|
||||
[IMX7_RESET_USBPHY1_PORT_RST] = { SRC_USBOPHY1_RCR, BIT(1) },
|
||||
[IMX7_RESET_USBPHY2_POR] = { SRC_USBOPHY2_RCR, BIT(0) },
|
||||
[IMX7_RESET_USBPHY2_PORT_RST] = { SRC_USBOPHY2_RCR, BIT(1) },
|
||||
[IMX7_RESET_MIPI_PHY_MRST] = { SRC_MIPIPHY_RCR, BIT(1) },
|
||||
[IMX7_RESET_MIPI_PHY_SRST] = { SRC_MIPIPHY_RCR, BIT(2) },
|
||||
[IMX7_RESET_PCIEPHY] = { SRC_PCIEPHY_RCR, BIT(2) | BIT(1) },
|
||||
[IMX7_RESET_PCIEPHY_PERST] = { SRC_PCIEPHY_RCR, BIT(3) },
|
||||
[IMX7_RESET_PCIE_CTRL_APPS_EN] = { SRC_PCIEPHY_RCR, BIT(6) },
|
||||
[IMX7_RESET_DDRC_PRST] = { SRC_DDRC_RCR, BIT(0) },
|
||||
[IMX7_RESET_DDRC_CORE_RST] = { SRC_DDRC_RCR, BIT(1) },
|
||||
};
|
||||
|
||||
static struct imx7_src *to_imx7_src(struct reset_controller_dev *rcdev)
|
||||
{
|
||||
return container_of(rcdev, struct imx7_src, rcdev);
|
||||
}
|
||||
|
||||
static int imx7_reset_set(struct reset_controller_dev *rcdev,
|
||||
unsigned long id, bool assert)
|
||||
{
|
||||
struct imx7_src *imx7src = to_imx7_src(rcdev);
|
||||
const struct imx7_src_signal *signal = &imx7_src_signals[id];
|
||||
unsigned int value = 0;
|
||||
|
||||
switch (id) {
|
||||
case IMX7_RESET_PCIEPHY:
|
||||
/*
|
||||
* wait for more than 10us to release phy g_rst and
|
||||
* btnrst
|
||||
*/
|
||||
if (!assert)
|
||||
udelay(10);
|
||||
break;
|
||||
|
||||
case IMX7_RESET_PCIE_CTRL_APPS_EN:
|
||||
value = (assert) ? 0 : signal->bit;
|
||||
break;
|
||||
}
|
||||
|
||||
return regmap_update_bits(imx7src->regmap,
|
||||
signal->offset, signal->bit, value);
|
||||
}
|
||||
|
||||
static int imx7_reset_assert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
return imx7_reset_set(rcdev, id, true);
|
||||
}
|
||||
|
||||
static int imx7_reset_deassert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
return imx7_reset_set(rcdev, id, false);
|
||||
}
|
||||
|
||||
static const struct reset_control_ops imx7_reset_ops = {
|
||||
.assert = imx7_reset_assert,
|
||||
.deassert = imx7_reset_deassert,
|
||||
};
|
||||
|
||||
static int imx7_reset_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct imx7_src *imx7src;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct regmap_config config = { .name = "src" };
|
||||
|
||||
imx7src = devm_kzalloc(dev, sizeof(*imx7src), GFP_KERNEL);
|
||||
if (!imx7src)
|
||||
return -ENOMEM;
|
||||
|
||||
imx7src->regmap = syscon_node_to_regmap(dev->of_node);
|
||||
if (IS_ERR(imx7src->regmap)) {
|
||||
dev_err(dev, "Unable to get imx7-src regmap");
|
||||
return PTR_ERR(imx7src->regmap);
|
||||
}
|
||||
regmap_attach_dev(dev, imx7src->regmap, &config);
|
||||
|
||||
imx7src->rcdev.owner = THIS_MODULE;
|
||||
imx7src->rcdev.nr_resets = IMX7_RESET_NUM;
|
||||
imx7src->rcdev.ops = &imx7_reset_ops;
|
||||
imx7src->rcdev.of_node = dev->of_node;
|
||||
|
||||
return devm_reset_controller_register(dev, &imx7src->rcdev);
|
||||
}
|
||||
|
||||
static const struct of_device_id imx7_reset_dt_ids[] = {
|
||||
{ .compatible = "fsl,imx7d-src", },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static struct platform_driver imx7_reset_driver = {
|
||||
.probe = imx7_reset_probe,
|
||||
.driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.of_match_table = imx7_reset_dt_ids,
|
||||
},
|
||||
};
|
||||
builtin_platform_driver(imx7_reset_driver);
|
|
@ -1,4 +1,6 @@
|
|||
/*
|
||||
* Amlogic Meson Reset Controller driver
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
|
@ -53,7 +55,7 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
@ -95,7 +97,6 @@ static const struct of_device_id meson_reset_dt_ids[] = {
|
|||
{ .compatible = "amlogic,meson-gxbb-reset", },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, meson_reset_dt_ids);
|
||||
|
||||
static int meson_reset_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
@ -128,9 +129,4 @@ static struct platform_driver meson_reset_driver = {
|
|||
.of_match_table = meson_reset_dt_ids,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(meson_reset_driver);
|
||||
|
||||
MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
|
||||
MODULE_DESCRIPTION("Amlogic Meson Reset Controller driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
builtin_platform_driver(meson_reset_driver);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset-controller.h>
|
||||
|
@ -83,7 +83,6 @@ static const struct of_device_id oxnas_reset_dt_ids[] = {
|
|||
{ .compatible = "oxsemi,ox820-reset", },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, oxnas_reset_dt_ids);
|
||||
|
||||
static int oxnas_reset_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
@ -123,5 +122,4 @@ static struct platform_driver oxnas_reset_driver = {
|
|||
.of_match_table = oxnas_reset_dt_ids,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(oxnas_reset_driver);
|
||||
builtin_platform_driver(oxnas_reset_driver);
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
* version 2, as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
@ -128,7 +128,6 @@ static const struct of_device_id pistachio_reset_dt_ids[] = {
|
|||
{ .compatible = "img,pistachio-reset", },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pistachio_reset_dt_ids);
|
||||
|
||||
static struct platform_driver pistachio_reset_driver = {
|
||||
.probe = pistachio_reset_probe,
|
||||
|
@ -137,8 +136,4 @@ static struct platform_driver pistachio_reset_driver = {
|
|||
.of_match_table = pistachio_reset_dt_ids,
|
||||
},
|
||||
};
|
||||
module_platform_driver(pistachio_reset_driver);
|
||||
|
||||
MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
|
||||
MODULE_DESCRIPTION("Pistacho Reset Controller Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
builtin_platform_driver(pistachio_reset_driver);
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
#include <linux/spinlock.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define NR_BANKS 4
|
||||
#define BANK_INCREMENT 4
|
||||
#define NR_BANKS 8
|
||||
|
||||
struct socfpga_reset_data {
|
||||
spinlock_t lock;
|
||||
|
@ -46,8 +47,8 @@ static int socfpga_reset_assert(struct reset_controller_dev *rcdev,
|
|||
|
||||
spin_lock_irqsave(&data->lock, flags);
|
||||
|
||||
reg = readl(data->membase + (bank * NR_BANKS));
|
||||
writel(reg | BIT(offset), data->membase + (bank * NR_BANKS));
|
||||
reg = readl(data->membase + (bank * BANK_INCREMENT));
|
||||
writel(reg | BIT(offset), data->membase + (bank * BANK_INCREMENT));
|
||||
spin_unlock_irqrestore(&data->lock, flags);
|
||||
|
||||
return 0;
|
||||
|
@ -67,8 +68,8 @@ static int socfpga_reset_deassert(struct reset_controller_dev *rcdev,
|
|||
|
||||
spin_lock_irqsave(&data->lock, flags);
|
||||
|
||||
reg = readl(data->membase + (bank * NR_BANKS));
|
||||
writel(reg & ~BIT(offset), data->membase + (bank * NR_BANKS));
|
||||
reg = readl(data->membase + (bank * BANK_INCREMENT));
|
||||
writel(reg & ~BIT(offset), data->membase + (bank * BANK_INCREMENT));
|
||||
|
||||
spin_unlock_irqrestore(&data->lock, flags);
|
||||
|
||||
|
@ -84,7 +85,7 @@ static int socfpga_reset_status(struct reset_controller_dev *rcdev,
|
|||
int offset = id % BITS_PER_LONG;
|
||||
u32 reg;
|
||||
|
||||
reg = readl(data->membase + (bank * NR_BANKS));
|
||||
reg = readl(data->membase + (bank * BANK_INCREMENT));
|
||||
|
||||
return !(reg & BIT(offset));
|
||||
}
|
||||
|
|
|
@ -34,15 +34,16 @@ static int sunxi_reset_assert(struct reset_controller_dev *rcdev,
|
|||
struct sunxi_reset_data *data = container_of(rcdev,
|
||||
struct sunxi_reset_data,
|
||||
rcdev);
|
||||
int bank = id / BITS_PER_LONG;
|
||||
int offset = id % BITS_PER_LONG;
|
||||
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 * 4));
|
||||
writel(reg & ~BIT(offset), data->membase + (bank * 4));
|
||||
reg = readl(data->membase + (bank * reg_width));
|
||||
writel(reg & ~BIT(offset), data->membase + (bank * reg_width));
|
||||
|
||||
spin_unlock_irqrestore(&data->lock, flags);
|
||||
|
||||
|
@ -55,15 +56,16 @@ static int sunxi_reset_deassert(struct reset_controller_dev *rcdev,
|
|||
struct sunxi_reset_data *data = container_of(rcdev,
|
||||
struct sunxi_reset_data,
|
||||
rcdev);
|
||||
int bank = id / BITS_PER_LONG;
|
||||
int offset = id % BITS_PER_LONG;
|
||||
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 * 4));
|
||||
writel(reg | BIT(offset), data->membase + (bank * 4));
|
||||
reg = readl(data->membase + (bank * reg_width));
|
||||
writel(reg | BIT(offset), data->membase + (bank * reg_width));
|
||||
|
||||
spin_unlock_irqrestore(&data->lock, flags);
|
||||
|
||||
|
|
|
@ -50,6 +50,15 @@ struct uniphier_reset_data {
|
|||
}
|
||||
|
||||
/* System reset data */
|
||||
#define UNIPHIER_SLD3_SYS_RESET_NAND(id) \
|
||||
UNIPHIER_RESETX((id), 0x2004, 2)
|
||||
|
||||
#define UNIPHIER_LD11_SYS_RESET_NAND(id) \
|
||||
UNIPHIER_RESETX((id), 0x200c, 0)
|
||||
|
||||
#define UNIPHIER_LD11_SYS_RESET_EMMC(id) \
|
||||
UNIPHIER_RESETX((id), 0x200c, 2)
|
||||
|
||||
#define UNIPHIER_SLD3_SYS_RESET_STDMAC(id) \
|
||||
UNIPHIER_RESETX((id), 0x2000, 10)
|
||||
|
||||
|
@ -65,12 +74,14 @@ struct uniphier_reset_data {
|
|||
#define UNIPHIER_PRO4_SYS_RESET_USB3(id, ch) \
|
||||
UNIPHIER_RESETX((id), 0x2000 + 0x4 * (ch), 17)
|
||||
|
||||
const struct uniphier_reset_data uniphier_sld3_sys_reset_data[] = {
|
||||
static const struct uniphier_reset_data uniphier_sld3_sys_reset_data[] = {
|
||||
UNIPHIER_SLD3_SYS_RESET_NAND(2),
|
||||
UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* Ether, HSC, MIO */
|
||||
UNIPHIER_RESET_END,
|
||||
};
|
||||
|
||||
const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
|
||||
static const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
|
||||
UNIPHIER_SLD3_SYS_RESET_NAND(2),
|
||||
UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC, MIO, RLE */
|
||||
UNIPHIER_PRO4_SYS_RESET_GIO(12), /* Ether, SATA, USB3 */
|
||||
UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
|
||||
|
@ -78,7 +89,8 @@ const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
|
|||
UNIPHIER_RESET_END,
|
||||
};
|
||||
|
||||
const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = {
|
||||
static const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = {
|
||||
UNIPHIER_SLD3_SYS_RESET_NAND(2),
|
||||
UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC */
|
||||
UNIPHIER_PRO4_SYS_RESET_GIO(12), /* PCIe, USB3 */
|
||||
UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
|
||||
|
@ -86,7 +98,8 @@ const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = {
|
|||
UNIPHIER_RESET_END,
|
||||
};
|
||||
|
||||
const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
|
||||
static const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
|
||||
UNIPHIER_SLD3_SYS_RESET_NAND(2),
|
||||
UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC, RLE */
|
||||
UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
|
||||
UNIPHIER_PRO4_SYS_RESET_USB3(15, 1),
|
||||
|
@ -100,12 +113,16 @@ const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
|
|||
UNIPHIER_RESET_END,
|
||||
};
|
||||
|
||||
const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = {
|
||||
static const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = {
|
||||
UNIPHIER_LD11_SYS_RESET_NAND(2),
|
||||
UNIPHIER_LD11_SYS_RESET_EMMC(4),
|
||||
UNIPHIER_LD11_SYS_RESET_STDMAC(8), /* HSC, MIO */
|
||||
UNIPHIER_RESET_END,
|
||||
};
|
||||
|
||||
const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
|
||||
static const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
|
||||
UNIPHIER_LD11_SYS_RESET_NAND(2),
|
||||
UNIPHIER_LD11_SYS_RESET_EMMC(4),
|
||||
UNIPHIER_LD11_SYS_RESET_STDMAC(8), /* HSC */
|
||||
UNIPHIER_LD20_SYS_RESET_GIO(12), /* PCIe, USB3 */
|
||||
UNIPHIER_RESETX(16, 0x200c, 12), /* USB30-PHY0 */
|
||||
|
@ -134,7 +151,7 @@ const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
|
|||
#define UNIPHIER_MIO_RESET_DMAC(id) \
|
||||
UNIPHIER_RESETX((id), 0x110, 17)
|
||||
|
||||
const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = {
|
||||
static const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = {
|
||||
UNIPHIER_MIO_RESET_SD(0, 0),
|
||||
UNIPHIER_MIO_RESET_SD(1, 1),
|
||||
UNIPHIER_MIO_RESET_SD(2, 2),
|
||||
|
@ -154,7 +171,7 @@ const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = {
|
|||
UNIPHIER_RESET_END,
|
||||
};
|
||||
|
||||
const struct uniphier_reset_data uniphier_pro5_sd_reset_data[] = {
|
||||
static const struct uniphier_reset_data uniphier_pro5_sd_reset_data[] = {
|
||||
UNIPHIER_MIO_RESET_SD(0, 0),
|
||||
UNIPHIER_MIO_RESET_SD(1, 1),
|
||||
UNIPHIER_MIO_RESET_EMMC_HW_RESET(6, 1),
|
||||
|
@ -171,7 +188,7 @@ const struct uniphier_reset_data uniphier_pro5_sd_reset_data[] = {
|
|||
#define UNIPHIER_PERI_RESET_FI2C(id, ch) \
|
||||
UNIPHIER_RESETX((id), 0x114, 24 + (ch))
|
||||
|
||||
const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
|
||||
static const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
|
||||
UNIPHIER_PERI_RESET_UART(0, 0),
|
||||
UNIPHIER_PERI_RESET_UART(1, 1),
|
||||
UNIPHIER_PERI_RESET_UART(2, 2),
|
||||
|
@ -184,7 +201,7 @@ const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
|
|||
UNIPHIER_RESET_END,
|
||||
};
|
||||
|
||||
const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = {
|
||||
static const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = {
|
||||
UNIPHIER_PERI_RESET_UART(0, 0),
|
||||
UNIPHIER_PERI_RESET_UART(1, 1),
|
||||
UNIPHIER_PERI_RESET_UART(2, 2),
|
||||
|
|
|
@ -3,6 +3,7 @@ menu "SOC (System On Chip) specific Drivers"
|
|||
source "drivers/soc/atmel/Kconfig"
|
||||
source "drivers/soc/bcm/Kconfig"
|
||||
source "drivers/soc/fsl/Kconfig"
|
||||
source "drivers/soc/imx/Kconfig"
|
||||
source "drivers/soc/mediatek/Kconfig"
|
||||
source "drivers/soc/qcom/Kconfig"
|
||||
source "drivers/soc/rockchip/Kconfig"
|
||||
|
|
|
@ -7,6 +7,7 @@ obj-y += bcm/
|
|||
obj-$(CONFIG_ARCH_DOVE) += dove/
|
||||
obj-$(CONFIG_MACH_DOVE) += dove/
|
||||
obj-y += fsl/
|
||||
obj-$(CONFIG_ARCH_MXC) += imx/
|
||||
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
|
||||
obj-$(CONFIG_ARCH_QCOM) += qcom/
|
||||
obj-$(CONFIG_ARCH_RENESAS) += renesas/
|
||||
|
|
|
@ -41,6 +41,15 @@ bool soc_is_brcmstb(void)
|
|||
}
|
||||
|
||||
static const struct of_device_id sun_top_ctrl_match[] = {
|
||||
{ .compatible = "brcm,bcm7125-sun-top-ctrl", },
|
||||
{ .compatible = "brcm,bcm7346-sun-top-ctrl", },
|
||||
{ .compatible = "brcm,bcm7358-sun-top-ctrl", },
|
||||
{ .compatible = "brcm,bcm7360-sun-top-ctrl", },
|
||||
{ .compatible = "brcm,bcm7362-sun-top-ctrl", },
|
||||
{ .compatible = "brcm,bcm7420-sun-top-ctrl", },
|
||||
{ .compatible = "brcm,bcm7425-sun-top-ctrl", },
|
||||
{ .compatible = "brcm,bcm7429-sun-top-ctrl", },
|
||||
{ .compatible = "brcm,bcm7425-sun-top-ctrl", },
|
||||
{ .compatible = "brcm,brcmstb-sun-top-ctrl", },
|
||||
{ }
|
||||
};
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
menu "i.MX SoC drivers"
|
||||
|
||||
config IMX7_PM_DOMAINS
|
||||
bool "i.MX7 PM domains"
|
||||
select PM_GENERIC_DOMAINS
|
||||
depends on SOC_IMX7D || (COMPILE_TEST && OF)
|
||||
default y if SOC_IMX7D
|
||||
|
||||
endmenu
|
|
@ -0,0 +1,2 @@
|
|||
obj-y += gpc.o
|
||||
obj-$(CONFIG_IMX7_PM_DOMAINS) += gpcv2.o
|
|
@ -0,0 +1,489 @@
|
|||
/*
|
||||
* Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
|
||||
* Copyright 2011-2013 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#define GPC_CNTR 0x000
|
||||
|
||||
#define GPC_PGC_CTRL_OFFS 0x0
|
||||
#define GPC_PGC_PUPSCR_OFFS 0x4
|
||||
#define GPC_PGC_PDNSCR_OFFS 0x8
|
||||
#define GPC_PGC_SW2ISO_SHIFT 0x8
|
||||
#define GPC_PGC_SW_SHIFT 0x0
|
||||
|
||||
#define GPC_PGC_GPU_PDN 0x260
|
||||
#define GPC_PGC_GPU_PUPSCR 0x264
|
||||
#define GPC_PGC_GPU_PDNSCR 0x268
|
||||
|
||||
#define GPU_VPU_PUP_REQ BIT(1)
|
||||
#define GPU_VPU_PDN_REQ BIT(0)
|
||||
|
||||
#define GPC_CLK_MAX 6
|
||||
|
||||
#define PGC_DOMAIN_FLAG_NO_PD BIT(0)
|
||||
|
||||
struct imx_pm_domain {
|
||||
struct generic_pm_domain base;
|
||||
struct regmap *regmap;
|
||||
struct regulator *supply;
|
||||
struct clk *clk[GPC_CLK_MAX];
|
||||
int num_clks;
|
||||
unsigned int reg_offs;
|
||||
signed char cntr_pdn_bit;
|
||||
unsigned int ipg_rate_mhz;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
static inline struct imx_pm_domain *
|
||||
to_imx_pm_domain(struct generic_pm_domain *genpd)
|
||||
{
|
||||
return container_of(genpd, struct imx_pm_domain, base);
|
||||
}
|
||||
|
||||
static int imx6_pm_domain_power_off(struct generic_pm_domain *genpd)
|
||||
{
|
||||
struct imx_pm_domain *pd = to_imx_pm_domain(genpd);
|
||||
int iso, iso2sw;
|
||||
u32 val;
|
||||
|
||||
if (pd->flags & PGC_DOMAIN_FLAG_NO_PD)
|
||||
return -EBUSY;
|
||||
|
||||
/* Read ISO and ISO2SW power down delays */
|
||||
regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PUPSCR_OFFS, &val);
|
||||
iso = val & 0x3f;
|
||||
iso2sw = (val >> 8) & 0x3f;
|
||||
|
||||
/* Gate off domain when powered down */
|
||||
regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS,
|
||||
0x1, 0x1);
|
||||
|
||||
/* Request GPC to power down domain */
|
||||
val = BIT(pd->cntr_pdn_bit);
|
||||
regmap_update_bits(pd->regmap, GPC_CNTR, val, val);
|
||||
|
||||
/* Wait ISO + ISO2SW IPG clock cycles */
|
||||
udelay(DIV_ROUND_UP(iso + iso2sw, pd->ipg_rate_mhz));
|
||||
|
||||
if (pd->supply)
|
||||
regulator_disable(pd->supply);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx6_pm_domain_power_on(struct generic_pm_domain *genpd)
|
||||
{
|
||||
struct imx_pm_domain *pd = to_imx_pm_domain(genpd);
|
||||
int i, ret, sw, sw2iso;
|
||||
u32 val;
|
||||
|
||||
if (pd->supply) {
|
||||
ret = regulator_enable(pd->supply);
|
||||
if (ret) {
|
||||
pr_err("%s: failed to enable regulator: %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable reset clocks for all devices in the domain */
|
||||
for (i = 0; i < pd->num_clks; i++)
|
||||
clk_prepare_enable(pd->clk[i]);
|
||||
|
||||
/* Gate off domain when powered down */
|
||||
regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS,
|
||||
0x1, 0x1);
|
||||
|
||||
/* Read ISO and ISO2SW power up delays */
|
||||
regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PUPSCR_OFFS, &val);
|
||||
sw = val & 0x3f;
|
||||
sw2iso = (val >> 8) & 0x3f;
|
||||
|
||||
/* Request GPC to power up domain */
|
||||
val = BIT(pd->cntr_pdn_bit + 1);
|
||||
regmap_update_bits(pd->regmap, GPC_CNTR, val, val);
|
||||
|
||||
/* Wait ISO + ISO2SW IPG clock cycles */
|
||||
udelay(DIV_ROUND_UP(sw + sw2iso, pd->ipg_rate_mhz));
|
||||
|
||||
/* Disable reset clocks for all devices in the domain */
|
||||
for (i = 0; i < pd->num_clks; i++)
|
||||
clk_disable_unprepare(pd->clk[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx_pgc_get_clocks(struct device *dev, struct imx_pm_domain *domain)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
struct clk *clk = of_clk_get(dev->of_node, i);
|
||||
if (IS_ERR(clk))
|
||||
break;
|
||||
if (i >= GPC_CLK_MAX) {
|
||||
dev_err(dev, "more than %d clocks\n", GPC_CLK_MAX);
|
||||
ret = -EINVAL;
|
||||
goto clk_err;
|
||||
}
|
||||
domain->clk[i] = clk;
|
||||
}
|
||||
domain->num_clks = i;
|
||||
|
||||
return 0;
|
||||
|
||||
clk_err:
|
||||
while (i--)
|
||||
clk_put(domain->clk[i]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void imx_pgc_put_clocks(struct imx_pm_domain *domain)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = domain->num_clks - 1; i >= 0; i--)
|
||||
clk_put(domain->clk[i]);
|
||||
}
|
||||
|
||||
static int imx_pgc_parse_dt(struct device *dev, struct imx_pm_domain *domain)
|
||||
{
|
||||
/* try to get the domain supply regulator */
|
||||
domain->supply = devm_regulator_get_optional(dev, "power");
|
||||
if (IS_ERR(domain->supply)) {
|
||||
if (PTR_ERR(domain->supply) == -ENODEV)
|
||||
domain->supply = NULL;
|
||||
else
|
||||
return PTR_ERR(domain->supply);
|
||||
}
|
||||
|
||||
/* try to get all clocks needed for reset propagation */
|
||||
return imx_pgc_get_clocks(dev, domain);
|
||||
}
|
||||
|
||||
static int imx_pgc_power_domain_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct imx_pm_domain *domain = pdev->dev.platform_data;
|
||||
struct device *dev = &pdev->dev;
|
||||
int ret;
|
||||
|
||||
/* if this PD is associated with a DT node try to parse it */
|
||||
if (dev->of_node) {
|
||||
ret = imx_pgc_parse_dt(dev, domain);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* initially power on the domain */
|
||||
if (domain->base.power_on)
|
||||
domain->base.power_on(&domain->base);
|
||||
|
||||
if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
|
||||
pm_genpd_init(&domain->base, NULL, false);
|
||||
ret = of_genpd_add_provider_simple(dev->of_node, &domain->base);
|
||||
if (ret)
|
||||
goto genpd_err;
|
||||
}
|
||||
|
||||
device_link_add(dev, dev->parent, DL_FLAG_AUTOREMOVE);
|
||||
|
||||
return 0;
|
||||
|
||||
genpd_err:
|
||||
pm_genpd_remove(&domain->base);
|
||||
imx_pgc_put_clocks(domain);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int imx_pgc_power_domain_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct imx_pm_domain *domain = pdev->dev.platform_data;
|
||||
|
||||
if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
|
||||
of_genpd_del_provider(pdev->dev.of_node);
|
||||
pm_genpd_remove(&domain->base);
|
||||
imx_pgc_put_clocks(domain);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct platform_device_id imx_pgc_power_domain_id[] = {
|
||||
{ "imx-pgc-power-domain"},
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_driver imx_pgc_power_domain_driver = {
|
||||
.driver = {
|
||||
.name = "imx-pgc-pd",
|
||||
},
|
||||
.probe = imx_pgc_power_domain_probe,
|
||||
.remove = imx_pgc_power_domain_remove,
|
||||
.id_table = imx_pgc_power_domain_id,
|
||||
};
|
||||
builtin_platform_driver(imx_pgc_power_domain_driver)
|
||||
|
||||
#define GPC_PGC_DOMAIN_ARM 0
|
||||
#define GPC_PGC_DOMAIN_PU 1
|
||||
#define GPC_PGC_DOMAIN_DISPLAY 2
|
||||
|
||||
static struct genpd_power_state imx6_pm_domain_pu_state = {
|
||||
.power_off_latency_ns = 25000,
|
||||
.power_on_latency_ns = 2000000,
|
||||
};
|
||||
|
||||
static struct imx_pm_domain imx_gpc_domains[] = {
|
||||
{
|
||||
.base = {
|
||||
.name = "ARM",
|
||||
},
|
||||
}, {
|
||||
.base = {
|
||||
.name = "PU",
|
||||
.power_off = imx6_pm_domain_power_off,
|
||||
.power_on = imx6_pm_domain_power_on,
|
||||
.states = &imx6_pm_domain_pu_state,
|
||||
.state_count = 1,
|
||||
},
|
||||
.reg_offs = 0x260,
|
||||
.cntr_pdn_bit = 0,
|
||||
}, {
|
||||
.base = {
|
||||
.name = "DISPLAY",
|
||||
.power_off = imx6_pm_domain_power_off,
|
||||
.power_on = imx6_pm_domain_power_on,
|
||||
},
|
||||
.reg_offs = 0x240,
|
||||
.cntr_pdn_bit = 4,
|
||||
}
|
||||
};
|
||||
|
||||
struct imx_gpc_dt_data {
|
||||
int num_domains;
|
||||
bool err009619_present;
|
||||
};
|
||||
|
||||
static const struct imx_gpc_dt_data imx6q_dt_data = {
|
||||
.num_domains = 2,
|
||||
.err009619_present = false,
|
||||
};
|
||||
|
||||
static const struct imx_gpc_dt_data imx6qp_dt_data = {
|
||||
.num_domains = 2,
|
||||
.err009619_present = true,
|
||||
};
|
||||
|
||||
static const struct imx_gpc_dt_data imx6sl_dt_data = {
|
||||
.num_domains = 3,
|
||||
.err009619_present = false,
|
||||
};
|
||||
|
||||
static const struct of_device_id imx_gpc_dt_ids[] = {
|
||||
{ .compatible = "fsl,imx6q-gpc", .data = &imx6q_dt_data },
|
||||
{ .compatible = "fsl,imx6qp-gpc", .data = &imx6qp_dt_data },
|
||||
{ .compatible = "fsl,imx6sl-gpc", .data = &imx6sl_dt_data },
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct regmap_config imx_gpc_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.max_register = 0x2ac,
|
||||
};
|
||||
|
||||
static struct generic_pm_domain *imx_gpc_onecell_domains[] = {
|
||||
&imx_gpc_domains[0].base,
|
||||
&imx_gpc_domains[1].base,
|
||||
};
|
||||
|
||||
static struct genpd_onecell_data imx_gpc_onecell_data = {
|
||||
.domains = imx_gpc_onecell_domains,
|
||||
.num_domains = 2,
|
||||
};
|
||||
|
||||
static int imx_gpc_old_dt_init(struct device *dev, struct regmap *regmap,
|
||||
unsigned int num_domains)
|
||||
{
|
||||
struct imx_pm_domain *domain;
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < num_domains; i++) {
|
||||
domain = &imx_gpc_domains[i];
|
||||
domain->regmap = regmap;
|
||||
domain->ipg_rate_mhz = 66;
|
||||
|
||||
if (i == 1) {
|
||||
domain->supply = devm_regulator_get(dev, "pu");
|
||||
if (IS_ERR(domain->supply))
|
||||
return PTR_ERR(domain->supply);;
|
||||
|
||||
ret = imx_pgc_get_clocks(dev, domain);
|
||||
if (ret)
|
||||
goto clk_err;
|
||||
|
||||
domain->base.power_on(&domain->base);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < num_domains; i++)
|
||||
pm_genpd_init(&imx_gpc_domains[i].base, NULL, false);
|
||||
|
||||
if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
|
||||
ret = of_genpd_add_provider_onecell(dev->of_node,
|
||||
&imx_gpc_onecell_data);
|
||||
if (ret)
|
||||
goto genpd_err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
genpd_err:
|
||||
for (i = 0; i < num_domains; i++)
|
||||
pm_genpd_remove(&imx_gpc_domains[i].base);
|
||||
imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]);
|
||||
clk_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int imx_gpc_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct of_device_id *of_id =
|
||||
of_match_device(imx_gpc_dt_ids, &pdev->dev);
|
||||
const struct imx_gpc_dt_data *of_id_data = of_id->data;
|
||||
struct device_node *pgc_node;
|
||||
struct regmap *regmap;
|
||||
struct resource *res;
|
||||
void __iomem *base;
|
||||
int ret;
|
||||
|
||||
pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
|
||||
|
||||
/* bail out if DT too old and doesn't provide the necessary info */
|
||||
if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") &&
|
||||
!pgc_node)
|
||||
return 0;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base,
|
||||
&imx_gpc_regmap_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
ret = PTR_ERR(regmap);
|
||||
dev_err(&pdev->dev, "failed to init regmap: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Disable PU power down in normal operation if ERR009619 is present */
|
||||
if (of_id_data->err009619_present)
|
||||
imx_gpc_domains[GPC_PGC_DOMAIN_PU].flags |=
|
||||
PGC_DOMAIN_FLAG_NO_PD;
|
||||
|
||||
if (!pgc_node) {
|
||||
ret = imx_gpc_old_dt_init(&pdev->dev, regmap,
|
||||
of_id_data->num_domains);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
struct imx_pm_domain *domain;
|
||||
struct platform_device *pd_pdev;
|
||||
struct device_node *np;
|
||||
struct clk *ipg_clk;
|
||||
unsigned int ipg_rate_mhz;
|
||||
int domain_index;
|
||||
|
||||
ipg_clk = devm_clk_get(&pdev->dev, "ipg");
|
||||
if (IS_ERR(ipg_clk))
|
||||
return PTR_ERR(ipg_clk);
|
||||
ipg_rate_mhz = clk_get_rate(ipg_clk) / 1000000;
|
||||
|
||||
for_each_child_of_node(pgc_node, np) {
|
||||
ret = of_property_read_u32(np, "reg", &domain_index);
|
||||
if (ret) {
|
||||
of_node_put(np);
|
||||
return ret;
|
||||
}
|
||||
if (domain_index >= of_id_data->num_domains)
|
||||
continue;
|
||||
|
||||
domain = &imx_gpc_domains[domain_index];
|
||||
domain->regmap = regmap;
|
||||
domain->ipg_rate_mhz = ipg_rate_mhz;
|
||||
|
||||
pd_pdev = platform_device_alloc("imx-pgc-power-domain",
|
||||
domain_index);
|
||||
if (!pd_pdev) {
|
||||
of_node_put(np);
|
||||
return -ENOMEM;
|
||||
}
|
||||
pd_pdev->dev.platform_data = domain;
|
||||
pd_pdev->dev.parent = &pdev->dev;
|
||||
pd_pdev->dev.of_node = np;
|
||||
|
||||
ret = platform_device_add(pd_pdev);
|
||||
if (ret) {
|
||||
platform_device_put(pd_pdev);
|
||||
of_node_put(np);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx_gpc_remove(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* If the old DT binding is used the toplevel driver needs to
|
||||
* de-register the power domains
|
||||
*/
|
||||
if (!of_get_child_by_name(pdev->dev.of_node, "pgc")) {
|
||||
of_genpd_del_provider(pdev->dev.of_node);
|
||||
|
||||
ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_PU].base);
|
||||
if (ret)
|
||||
return ret;
|
||||
imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]);
|
||||
|
||||
ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver imx_gpc_driver = {
|
||||
.driver = {
|
||||
.name = "imx-gpc",
|
||||
.of_match_table = imx_gpc_dt_ids,
|
||||
},
|
||||
.probe = imx_gpc_probe,
|
||||
.remove = imx_gpc_remove,
|
||||
};
|
||||
builtin_platform_driver(imx_gpc_driver)
|
|
@ -0,0 +1,363 @@
|
|||
/*
|
||||
* Copyright 2017 Impinj, Inc
|
||||
* Author: Andrey Smirnov <andrew.smirnov@gmail.com>
|
||||
*
|
||||
* Based on the code of analogus driver:
|
||||
*
|
||||
* Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
|
||||
*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <dt-bindings/power/imx7-power.h>
|
||||
|
||||
#define GPC_LPCR_A7_BSC 0x000
|
||||
|
||||
#define GPC_PGC_CPU_MAPPING 0x0ec
|
||||
#define USB_HSIC_PHY_A7_DOMAIN BIT(6)
|
||||
#define USB_OTG2_PHY_A7_DOMAIN BIT(5)
|
||||
#define USB_OTG1_PHY_A7_DOMAIN BIT(4)
|
||||
#define PCIE_PHY_A7_DOMAIN BIT(3)
|
||||
#define MIPI_PHY_A7_DOMAIN BIT(2)
|
||||
|
||||
#define GPC_PU_PGC_SW_PUP_REQ 0x0f8
|
||||
#define GPC_PU_PGC_SW_PDN_REQ 0x104
|
||||
#define USB_HSIC_PHY_SW_Pxx_REQ BIT(4)
|
||||
#define USB_OTG2_PHY_SW_Pxx_REQ BIT(3)
|
||||
#define USB_OTG1_PHY_SW_Pxx_REQ BIT(2)
|
||||
#define PCIE_PHY_SW_Pxx_REQ BIT(1)
|
||||
#define MIPI_PHY_SW_Pxx_REQ BIT(0)
|
||||
|
||||
#define GPC_M4_PU_PDN_FLG 0x1bc
|
||||
|
||||
|
||||
#define PGC_MIPI 4
|
||||
#define PGC_PCIE 5
|
||||
#define PGC_USB_HSIC 8
|
||||
#define GPC_PGC_CTRL(n) (0x800 + (n) * 0x40)
|
||||
#define GPC_PGC_SR(n) (GPC_PGC_CTRL(n) + 0xc)
|
||||
|
||||
#define GPC_PGC_CTRL_PCR BIT(0)
|
||||
|
||||
struct imx7_pgc_domain {
|
||||
struct generic_pm_domain genpd;
|
||||
struct regmap *regmap;
|
||||
struct regulator *regulator;
|
||||
|
||||
unsigned int pgc;
|
||||
|
||||
const struct {
|
||||
u32 pxx;
|
||||
u32 map;
|
||||
} bits;
|
||||
|
||||
const int voltage;
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
static int imx7_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
|
||||
bool on)
|
||||
{
|
||||
struct imx7_pgc_domain *domain = container_of(genpd,
|
||||
struct imx7_pgc_domain,
|
||||
genpd);
|
||||
unsigned int offset = on ?
|
||||
GPC_PU_PGC_SW_PUP_REQ : GPC_PU_PGC_SW_PDN_REQ;
|
||||
const bool enable_power_control = !on;
|
||||
const bool has_regulator = !IS_ERR(domain->regulator);
|
||||
unsigned long deadline;
|
||||
int ret = 0;
|
||||
|
||||
regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
|
||||
domain->bits.map, domain->bits.map);
|
||||
|
||||
if (has_regulator && on) {
|
||||
ret = regulator_enable(domain->regulator);
|
||||
if (ret) {
|
||||
dev_err(domain->dev, "failed to enable regulator\n");
|
||||
goto unmap;
|
||||
}
|
||||
}
|
||||
|
||||
if (enable_power_control)
|
||||
regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
|
||||
GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR);
|
||||
|
||||
regmap_update_bits(domain->regmap, offset,
|
||||
domain->bits.pxx, domain->bits.pxx);
|
||||
|
||||
/*
|
||||
* As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
|
||||
* for PUP_REQ/PDN_REQ bit to be cleared
|
||||
*/
|
||||
deadline = jiffies + msecs_to_jiffies(1);
|
||||
while (true) {
|
||||
u32 pxx_req;
|
||||
|
||||
regmap_read(domain->regmap, offset, &pxx_req);
|
||||
|
||||
if (!(pxx_req & domain->bits.pxx))
|
||||
break;
|
||||
|
||||
if (time_after(jiffies, deadline)) {
|
||||
dev_err(domain->dev, "falied to command PGC\n");
|
||||
ret = -ETIMEDOUT;
|
||||
/*
|
||||
* If we were in a process of enabling a
|
||||
* domain and failed we might as well disable
|
||||
* the regulator we just enabled. And if it
|
||||
* was the opposite situation and we failed to
|
||||
* power down -- keep the regulator on
|
||||
*/
|
||||
on = !on;
|
||||
break;
|
||||
}
|
||||
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
if (enable_power_control)
|
||||
regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
|
||||
GPC_PGC_CTRL_PCR, 0);
|
||||
|
||||
if (has_regulator && !on) {
|
||||
int err;
|
||||
|
||||
err = regulator_disable(domain->regulator);
|
||||
if (err)
|
||||
dev_err(domain->dev,
|
||||
"failed to disable regulator: %d\n", ret);
|
||||
/* Preserve earlier error code */
|
||||
ret = ret ?: err;
|
||||
}
|
||||
unmap:
|
||||
regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
|
||||
domain->bits.map, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int imx7_gpc_pu_pgc_sw_pup_req(struct generic_pm_domain *genpd)
|
||||
{
|
||||
return imx7_gpc_pu_pgc_sw_pxx_req(genpd, true);
|
||||
}
|
||||
|
||||
static int imx7_gpc_pu_pgc_sw_pdn_req(struct generic_pm_domain *genpd)
|
||||
{
|
||||
return imx7_gpc_pu_pgc_sw_pxx_req(genpd, false);
|
||||
}
|
||||
|
||||
static struct imx7_pgc_domain imx7_pgc_domains[] = {
|
||||
[IMX7_POWER_DOMAIN_MIPI_PHY] = {
|
||||
.genpd = {
|
||||
.name = "mipi-phy",
|
||||
},
|
||||
.bits = {
|
||||
.pxx = MIPI_PHY_SW_Pxx_REQ,
|
||||
.map = MIPI_PHY_A7_DOMAIN,
|
||||
},
|
||||
.voltage = 1000000,
|
||||
.pgc = PGC_MIPI,
|
||||
},
|
||||
|
||||
[IMX7_POWER_DOMAIN_PCIE_PHY] = {
|
||||
.genpd = {
|
||||
.name = "pcie-phy",
|
||||
},
|
||||
.bits = {
|
||||
.pxx = PCIE_PHY_SW_Pxx_REQ,
|
||||
.map = PCIE_PHY_A7_DOMAIN,
|
||||
},
|
||||
.voltage = 1000000,
|
||||
.pgc = PGC_PCIE,
|
||||
},
|
||||
|
||||
[IMX7_POWER_DOMAIN_USB_HSIC_PHY] = {
|
||||
.genpd = {
|
||||
.name = "usb-hsic-phy",
|
||||
},
|
||||
.bits = {
|
||||
.pxx = USB_HSIC_PHY_SW_Pxx_REQ,
|
||||
.map = USB_HSIC_PHY_A7_DOMAIN,
|
||||
},
|
||||
.voltage = 1200000,
|
||||
.pgc = PGC_USB_HSIC,
|
||||
},
|
||||
};
|
||||
|
||||
static int imx7_pgc_domain_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct imx7_pgc_domain *domain = pdev->dev.platform_data;
|
||||
int ret;
|
||||
|
||||
domain->dev = &pdev->dev;
|
||||
|
||||
ret = pm_genpd_init(&domain->genpd, NULL, true);
|
||||
if (ret) {
|
||||
dev_err(domain->dev, "Failed to init power domain\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
domain->regulator = devm_regulator_get_optional(domain->dev, "power");
|
||||
if (IS_ERR(domain->regulator)) {
|
||||
if (PTR_ERR(domain->regulator) != -ENODEV) {
|
||||
dev_err(domain->dev, "Failed to get domain's regulator\n");
|
||||
return PTR_ERR(domain->regulator);
|
||||
}
|
||||
} else {
|
||||
regulator_set_voltage(domain->regulator,
|
||||
domain->voltage, domain->voltage);
|
||||
}
|
||||
|
||||
ret = of_genpd_add_provider_simple(domain->dev->of_node,
|
||||
&domain->genpd);
|
||||
if (ret) {
|
||||
dev_err(domain->dev, "Failed to add genpd provider\n");
|
||||
pm_genpd_remove(&domain->genpd);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int imx7_pgc_domain_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct imx7_pgc_domain *domain = pdev->dev.platform_data;
|
||||
|
||||
of_genpd_del_provider(domain->dev->of_node);
|
||||
pm_genpd_remove(&domain->genpd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct platform_device_id imx7_pgc_domain_id[] = {
|
||||
{ "imx7-pgc-domain", },
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_driver imx7_pgc_domain_driver = {
|
||||
.driver = {
|
||||
.name = "imx7-pgc",
|
||||
},
|
||||
.probe = imx7_pgc_domain_probe,
|
||||
.remove = imx7_pgc_domain_remove,
|
||||
.id_table = imx7_pgc_domain_id,
|
||||
};
|
||||
builtin_platform_driver(imx7_pgc_domain_driver)
|
||||
|
||||
static int imx_gpcv2_probe(struct platform_device *pdev)
|
||||
{
|
||||
static const struct regmap_range yes_ranges[] = {
|
||||
regmap_reg_range(GPC_LPCR_A7_BSC,
|
||||
GPC_M4_PU_PDN_FLG),
|
||||
regmap_reg_range(GPC_PGC_CTRL(PGC_MIPI),
|
||||
GPC_PGC_SR(PGC_MIPI)),
|
||||
regmap_reg_range(GPC_PGC_CTRL(PGC_PCIE),
|
||||
GPC_PGC_SR(PGC_PCIE)),
|
||||
regmap_reg_range(GPC_PGC_CTRL(PGC_USB_HSIC),
|
||||
GPC_PGC_SR(PGC_USB_HSIC)),
|
||||
};
|
||||
static const struct regmap_access_table access_table = {
|
||||
.yes_ranges = yes_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(yes_ranges),
|
||||
};
|
||||
static const struct regmap_config regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.rd_table = &access_table,
|
||||
.wr_table = &access_table,
|
||||
.max_register = SZ_4K,
|
||||
};
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *pgc_np, *np;
|
||||
struct regmap *regmap;
|
||||
struct resource *res;
|
||||
void __iomem *base;
|
||||
int ret;
|
||||
|
||||
pgc_np = of_get_child_by_name(dev->of_node, "pgc");
|
||||
if (!pgc_np) {
|
||||
dev_err(dev, "No power domains specified in DT\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
regmap = devm_regmap_init_mmio(dev, base, ®map_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
ret = PTR_ERR(regmap);
|
||||
dev_err(dev, "failed to init regmap (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for_each_child_of_node(pgc_np, np) {
|
||||
struct platform_device *pd_pdev;
|
||||
struct imx7_pgc_domain *domain;
|
||||
u32 domain_index;
|
||||
|
||||
ret = of_property_read_u32(np, "reg", &domain_index);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read 'reg' property\n");
|
||||
of_node_put(np);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (domain_index >= ARRAY_SIZE(imx7_pgc_domains)) {
|
||||
dev_warn(dev,
|
||||
"Domain index %d is out of bounds\n",
|
||||
domain_index);
|
||||
continue;
|
||||
}
|
||||
|
||||
domain = &imx7_pgc_domains[domain_index];
|
||||
domain->regmap = regmap;
|
||||
domain->genpd.power_on = imx7_gpc_pu_pgc_sw_pup_req;
|
||||
domain->genpd.power_off = imx7_gpc_pu_pgc_sw_pdn_req;
|
||||
|
||||
pd_pdev = platform_device_alloc("imx7-pgc-domain",
|
||||
domain_index);
|
||||
if (!pd_pdev) {
|
||||
dev_err(dev, "Failed to allocate platform device\n");
|
||||
of_node_put(np);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pd_pdev->dev.platform_data = domain;
|
||||
pd_pdev->dev.parent = dev;
|
||||
pd_pdev->dev.of_node = np;
|
||||
|
||||
ret = platform_device_add(pd_pdev);
|
||||
if (ret) {
|
||||
platform_device_put(pd_pdev);
|
||||
of_node_put(np);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id imx_gpcv2_dt_ids[] = {
|
||||
{ .compatible = "fsl,imx7d-gpc" },
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct platform_driver imx_gpc_driver = {
|
||||
.driver = {
|
||||
.name = "imx-gpcv2",
|
||||
.of_match_table = imx_gpcv2_dt_ids,
|
||||
},
|
||||
.probe = imx_gpcv2_probe,
|
||||
};
|
||||
builtin_platform_driver(imx_gpc_driver)
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Renesas R-Car H3 System Controller
|
||||
*
|
||||
* Copyright (C) 2016 Glider bvba
|
||||
* Copyright (C) 2016-2017 Glider bvba
|
||||
*
|
||||
* 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
|
||||
|
@ -10,12 +10,13 @@
|
|||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sys_soc.h>
|
||||
|
||||
#include <dt-bindings/power/r8a7795-sysc.h>
|
||||
|
||||
#include "rcar-sysc.h"
|
||||
|
||||
static const struct rcar_sysc_area r8a7795_areas[] __initconst = {
|
||||
static struct rcar_sysc_area r8a7795_areas[] __initdata = {
|
||||
{ "always-on", 0, 0, R8A7795_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
|
||||
{ "ca57-scu", 0x1c0, 0, R8A7795_PD_CA57_SCU, R8A7795_PD_ALWAYS_ON,
|
||||
PD_SCU },
|
||||
|
@ -40,6 +41,7 @@ static const struct rcar_sysc_area r8a7795_areas[] __initconst = {
|
|||
{ "a3vp", 0x340, 0, R8A7795_PD_A3VP, R8A7795_PD_ALWAYS_ON },
|
||||
{ "cr7", 0x240, 0, R8A7795_PD_CR7, R8A7795_PD_ALWAYS_ON },
|
||||
{ "a3vc", 0x380, 0, R8A7795_PD_A3VC, R8A7795_PD_ALWAYS_ON },
|
||||
/* A2VC0 exists on ES1.x only */
|
||||
{ "a2vc0", 0x3c0, 0, R8A7795_PD_A2VC0, R8A7795_PD_A3VC },
|
||||
{ "a2vc1", 0x3c0, 1, R8A7795_PD_A2VC1, R8A7795_PD_A3VC },
|
||||
{ "3dg-a", 0x100, 0, R8A7795_PD_3DG_A, R8A7795_PD_ALWAYS_ON },
|
||||
|
@ -50,7 +52,27 @@ static const struct rcar_sysc_area r8a7795_areas[] __initconst = {
|
|||
{ "a3ir", 0x180, 0, R8A7795_PD_A3IR, R8A7795_PD_ALWAYS_ON },
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Fixups for R-Car H3 revisions after ES1.x
|
||||
*/
|
||||
|
||||
static const struct soc_device_attribute r8a7795es1[] __initconst = {
|
||||
{ .soc_id = "r8a7795", .revision = "ES1.*" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static int __init r8a7795_sysc_init(void)
|
||||
{
|
||||
if (!soc_device_match(r8a7795es1))
|
||||
rcar_sysc_nullify(r8a7795_areas, ARRAY_SIZE(r8a7795_areas),
|
||||
R8A7795_PD_A2VC0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct rcar_sysc_info r8a7795_sysc_info __initconst = {
|
||||
.init = r8a7795_sysc_init,
|
||||
.areas = r8a7795_areas,
|
||||
.num_areas = ARRAY_SIZE(r8a7795_areas),
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* R-Car SYSC Power management support
|
||||
*
|
||||
* Copyright (C) 2014 Magnus Damm
|
||||
* Copyright (C) 2015-2016 Glider bvba
|
||||
* Copyright (C) 2015-2017 Glider bvba
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
|
@ -334,6 +334,12 @@ static int __init rcar_sysc_pd_init(void)
|
|||
|
||||
info = match->data;
|
||||
|
||||
if (info->init) {
|
||||
error = info->init();
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
has_cpg_mstp = of_find_compatible_node(NULL, NULL,
|
||||
"renesas,cpg-mstp-clocks");
|
||||
|
||||
|
@ -377,6 +383,11 @@ static int __init rcar_sysc_pd_init(void)
|
|||
const struct rcar_sysc_area *area = &info->areas[i];
|
||||
struct rcar_sysc_pd *pd;
|
||||
|
||||
if (!area->name) {
|
||||
/* Skip NULLified area */
|
||||
continue;
|
||||
}
|
||||
|
||||
pd = kzalloc(sizeof(*pd) + strlen(area->name) + 1, GFP_KERNEL);
|
||||
if (!pd) {
|
||||
error = -ENOMEM;
|
||||
|
@ -406,6 +417,18 @@ static int __init rcar_sysc_pd_init(void)
|
|||
}
|
||||
early_initcall(rcar_sysc_pd_init);
|
||||
|
||||
void __init rcar_sysc_nullify(struct rcar_sysc_area *areas,
|
||||
unsigned int num_areas, u8 id)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < num_areas; i++)
|
||||
if (areas[i].isr_bit == id) {
|
||||
areas[i].name = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void __init rcar_sysc_init(phys_addr_t base, u32 syscier)
|
||||
{
|
||||
u32 syscimr;
|
||||
|
|
|
@ -46,6 +46,7 @@ struct rcar_sysc_area {
|
|||
*/
|
||||
|
||||
struct rcar_sysc_info {
|
||||
int (*init)(void); /* Optional */
|
||||
const struct rcar_sysc_area *areas;
|
||||
unsigned int num_areas;
|
||||
};
|
||||
|
@ -59,4 +60,13 @@ extern const struct rcar_sysc_info r8a7792_sysc_info;
|
|||
extern const struct rcar_sysc_info r8a7794_sysc_info;
|
||||
extern const struct rcar_sysc_info r8a7795_sysc_info;
|
||||
extern const struct rcar_sysc_info r8a7796_sysc_info;
|
||||
|
||||
|
||||
/*
|
||||
* Helpers for fixing up power area tables depending on SoC revision
|
||||
*/
|
||||
|
||||
extern void rcar_sysc_nullify(struct rcar_sysc_area *areas,
|
||||
unsigned int num_areas, u8 id);
|
||||
|
||||
#endif /* __SOC_RENESAS_RCAR_SYSC_H__ */
|
||||
|
|
|
@ -80,11 +80,21 @@ static const struct renesas_soc soc_rmobile_a1 __initconst __maybe_unused = {
|
|||
.id = 0x40,
|
||||
};
|
||||
|
||||
static const struct renesas_soc soc_rz_g1h __initconst __maybe_unused = {
|
||||
.family = &fam_rzg,
|
||||
.id = 0x45,
|
||||
};
|
||||
|
||||
static const struct renesas_soc soc_rz_g1m __initconst __maybe_unused = {
|
||||
.family = &fam_rzg,
|
||||
.id = 0x47,
|
||||
};
|
||||
|
||||
static const struct renesas_soc soc_rz_g1n __initconst __maybe_unused = {
|
||||
.family = &fam_rzg,
|
||||
.id = 0x4b,
|
||||
};
|
||||
|
||||
static const struct renesas_soc soc_rz_g1e __initconst __maybe_unused = {
|
||||
.family = &fam_rzg,
|
||||
.id = 0x4c,
|
||||
|
@ -150,9 +160,15 @@ static const struct of_device_id renesas_socs[] __initconst = {
|
|||
#ifdef CONFIG_ARCH_R8A7740
|
||||
{ .compatible = "renesas,r8a7740", .data = &soc_rmobile_a1 },
|
||||
#endif
|
||||
#ifdef CONFIG_ARCH_R8A7742
|
||||
{ .compatible = "renesas,r8a7742", .data = &soc_rz_g1h },
|
||||
#endif
|
||||
#ifdef CONFIG_ARCH_R8A7743
|
||||
{ .compatible = "renesas,r8a7743", .data = &soc_rz_g1m },
|
||||
#endif
|
||||
#ifdef CONFIG_ARCH_R8A7744
|
||||
{ .compatible = "renesas,r8a7744", .data = &soc_rz_g1n },
|
||||
#endif
|
||||
#ifdef CONFIG_ARCH_R8A7745
|
||||
{ .compatible = "renesas,r8a7745", .data = &soc_rz_g1e },
|
||||
#endif
|
||||
|
@ -254,4 +270,4 @@ static int __init renesas_soc_init(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
core_initcall(renesas_soc_init);
|
||||
early_initcall(renesas_soc_init);
|
||||
|
|
|
@ -8,7 +8,13 @@ if SOC_SAMSUNG
|
|||
|
||||
config EXYNOS_PMU
|
||||
bool "Exynos PMU controller driver" if COMPILE_TEST
|
||||
depends on (ARM && ARCH_EXYNOS) || ((ARM || ARM64) && COMPILE_TEST)
|
||||
depends on ARCH_EXYNOS || ((ARM || ARM64) && COMPILE_TEST)
|
||||
select EXYNOS_PMU_ARM_DRIVERS if ARM && ARCH_EXYNOS
|
||||
|
||||
# There is no need to enable these drivers for ARMv8
|
||||
config EXYNOS_PMU_ARM_DRIVERS
|
||||
bool "Exynos PMU ARMv7-specific driver extensions" if COMPILE_TEST
|
||||
depends on EXYNOS_PMU
|
||||
|
||||
config EXYNOS_PM_DOMAINS
|
||||
bool "Exynos PM domains" if COMPILE_TEST
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o exynos3250-pmu.o exynos4-pmu.o \
|
||||
obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o
|
||||
|
||||
obj-$(CONFIG_EXYNOS_PMU_ARM_DRIVERS) += exynos3250-pmu.o exynos4-pmu.o \
|
||||
exynos5250-pmu.o exynos5420-pmu.o
|
||||
obj-$(CONFIG_EXYNOS_PM_DOMAINS) += pm_domains.o
|
||||
|
|
|
@ -68,28 +68,38 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Split the data between ARM architectures because it is relatively big
|
||||
* and useless on other arch.
|
||||
*/
|
||||
#ifdef CONFIG_EXYNOS_PMU_ARM_DRIVERS
|
||||
#define exynos_pmu_data_arm_ptr(data) (&data)
|
||||
#else
|
||||
#define exynos_pmu_data_arm_ptr(data) NULL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* PMU platform driver and devicetree bindings.
|
||||
*/
|
||||
static const struct of_device_id exynos_pmu_of_device_ids[] = {
|
||||
{
|
||||
.compatible = "samsung,exynos3250-pmu",
|
||||
.data = &exynos3250_pmu_data,
|
||||
.data = exynos_pmu_data_arm_ptr(exynos3250_pmu_data),
|
||||
}, {
|
||||
.compatible = "samsung,exynos4210-pmu",
|
||||
.data = &exynos4210_pmu_data,
|
||||
.data = exynos_pmu_data_arm_ptr(exynos4210_pmu_data),
|
||||
}, {
|
||||
.compatible = "samsung,exynos4212-pmu",
|
||||
.data = &exynos4212_pmu_data,
|
||||
.data = exynos_pmu_data_arm_ptr(exynos4212_pmu_data),
|
||||
}, {
|
||||
.compatible = "samsung,exynos4412-pmu",
|
||||
.data = &exynos4412_pmu_data,
|
||||
.data = exynos_pmu_data_arm_ptr(exynos4412_pmu_data),
|
||||
}, {
|
||||
.compatible = "samsung,exynos5250-pmu",
|
||||
.data = &exynos5250_pmu_data,
|
||||
.data = exynos_pmu_data_arm_ptr(exynos5250_pmu_data),
|
||||
}, {
|
||||
.compatible = "samsung,exynos5420-pmu",
|
||||
.data = &exynos5420_pmu_data,
|
||||
.data = exynos_pmu_data_arm_ptr(exynos5420_pmu_data),
|
||||
}, {
|
||||
.compatible = "samsung,exynos5433-pmu",
|
||||
},
|
||||
|
|
|
@ -31,6 +31,8 @@ struct exynos_pmu_data {
|
|||
};
|
||||
|
||||
extern void __iomem *pmu_base_addr;
|
||||
|
||||
#ifdef CONFIG_EXYNOS_PMU_ARM_DRIVERS
|
||||
/* list of all exported SoC specific data */
|
||||
extern const struct exynos_pmu_data exynos3250_pmu_data;
|
||||
extern const struct exynos_pmu_data exynos4210_pmu_data;
|
||||
|
@ -38,6 +40,7 @@ extern const struct exynos_pmu_data exynos4212_pmu_data;
|
|||
extern const struct exynos_pmu_data exynos4412_pmu_data;
|
||||
extern const struct exynos_pmu_data exynos5250_pmu_data;
|
||||
extern const struct exynos_pmu_data exynos5420_pmu_data;
|
||||
#endif
|
||||
|
||||
extern void pmu_raw_writel(u32 val, u32 offset);
|
||||
extern u32 pmu_raw_readl(u32 offset);
|
||||
|
|
|
@ -12,6 +12,8 @@ config ARCH_TEGRA_2x_SOC
|
|||
select PINCTRL_TEGRA20
|
||||
select PL310_ERRATA_727915 if CACHE_L2X0
|
||||
select PL310_ERRATA_769419 if CACHE_L2X0
|
||||
select SOC_TEGRA_FLOWCTRL
|
||||
select SOC_TEGRA_PMC
|
||||
select TEGRA_TIMER
|
||||
help
|
||||
Support for NVIDIA Tegra AP20 and T20 processors, based on the
|
||||
|
@ -23,6 +25,8 @@ config ARCH_TEGRA_3x_SOC
|
|||
select ARM_ERRATA_764369 if SMP
|
||||
select PINCTRL_TEGRA30
|
||||
select PL310_ERRATA_769419 if CACHE_L2X0
|
||||
select SOC_TEGRA_FLOWCTRL
|
||||
select SOC_TEGRA_PMC
|
||||
select TEGRA_TIMER
|
||||
help
|
||||
Support for NVIDIA Tegra T30 processor family, based on the
|
||||
|
@ -33,6 +37,8 @@ config ARCH_TEGRA_114_SOC
|
|||
select ARM_ERRATA_798181 if SMP
|
||||
select HAVE_ARM_ARCH_TIMER
|
||||
select PINCTRL_TEGRA114
|
||||
select SOC_TEGRA_FLOWCTRL
|
||||
select SOC_TEGRA_PMC
|
||||
select TEGRA_TIMER
|
||||
help
|
||||
Support for NVIDIA Tegra T114 processor family, based on the
|
||||
|
@ -42,6 +48,8 @@ config ARCH_TEGRA_124_SOC
|
|||
bool "Enable support for Tegra124 family"
|
||||
select HAVE_ARM_ARCH_TIMER
|
||||
select PINCTRL_TEGRA124
|
||||
select SOC_TEGRA_FLOWCTRL
|
||||
select SOC_TEGRA_PMC
|
||||
select TEGRA_TIMER
|
||||
help
|
||||
Support for NVIDIA Tegra T124 processor family, based on the
|
||||
|
@ -55,6 +63,8 @@ if ARM64
|
|||
config ARCH_TEGRA_132_SOC
|
||||
bool "NVIDIA Tegra132 SoC"
|
||||
select PINCTRL_TEGRA124
|
||||
select SOC_TEGRA_FLOWCTRL
|
||||
select SOC_TEGRA_PMC
|
||||
help
|
||||
Enable support for NVIDIA Tegra132 SoC, based on the Denver
|
||||
ARMv8 CPU. The Tegra132 SoC is similar to the Tegra124 SoC,
|
||||
|
@ -64,6 +74,8 @@ config ARCH_TEGRA_132_SOC
|
|||
config ARCH_TEGRA_210_SOC
|
||||
bool "NVIDIA Tegra210 SoC"
|
||||
select PINCTRL_TEGRA210
|
||||
select SOC_TEGRA_FLOWCTRL
|
||||
select SOC_TEGRA_PMC
|
||||
help
|
||||
Enable support for the NVIDIA Tegra210 SoC. Also known as Tegra X1,
|
||||
the Tegra210 has four Cortex-A57 cores paired with four Cortex-A53
|
||||
|
@ -83,6 +95,7 @@ config ARCH_TEGRA_186_SOC
|
|||
select TEGRA_BPMP
|
||||
select TEGRA_HSP_MBOX
|
||||
select TEGRA_IVC
|
||||
select SOC_TEGRA_PMC_TEGRA186
|
||||
help
|
||||
Enable support for the NVIDIA Tegar186 SoC. The Tegra186 features a
|
||||
combination of Denver and Cortex-A57 CPU cores and a GPU based on
|
||||
|
@ -93,3 +106,12 @@ config ARCH_TEGRA_186_SOC
|
|||
|
||||
endif
|
||||
endif
|
||||
|
||||
config SOC_TEGRA_FLOWCTRL
|
||||
bool
|
||||
|
||||
config SOC_TEGRA_PMC
|
||||
bool
|
||||
|
||||
config SOC_TEGRA_PMC_TEGRA186
|
||||
bool
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
obj-y += fuse/
|
||||
|
||||
obj-y += common.o
|
||||
obj-y += pmc.o
|
||||
obj-$(CONFIG_SOC_TEGRA_FLOWCTRL) += flowctrl.o
|
||||
obj-$(CONFIG_SOC_TEGRA_PMC) += pmc.o
|
||||
obj-$(CONFIG_SOC_TEGRA_PMC_TEGRA186) += pmc-tegra186.o
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* arch/arm/mach-tegra/flowctrl.c
|
||||
* drivers/soc/tegra/flowctrl.c
|
||||
*
|
||||
* functions and macros to control the flowcontroller
|
||||
* Functions and macros to control the flowcontroller
|
||||
*
|
||||
* Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
|
||||
*
|
||||
|
@ -24,11 +24,12 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <soc/tegra/common.h>
|
||||
#include <soc/tegra/flowctrl.h>
|
||||
#include <soc/tegra/fuse.h>
|
||||
|
||||
#include "flowctrl.h"
|
||||
|
||||
static u8 flowctrl_offset_halt_cpu[] = {
|
||||
FLOW_CTRL_HALT_CPU0_EVENTS,
|
||||
FLOW_CTRL_HALT_CPU1_EVENTS,
|
||||
|
@ -47,6 +48,10 @@ static void __iomem *tegra_flowctrl_base;
|
|||
|
||||
static void flowctrl_update(u8 offset, u32 value)
|
||||
{
|
||||
if (WARN_ONCE(IS_ERR_OR_NULL(tegra_flowctrl_base),
|
||||
"Tegra flowctrl not initialised!\n"))
|
||||
return;
|
||||
|
||||
writel(value, tegra_flowctrl_base + offset);
|
||||
|
||||
/* ensure the update has reached the flow controller */
|
||||
|
@ -58,6 +63,10 @@ u32 flowctrl_read_cpu_csr(unsigned int cpuid)
|
|||
{
|
||||
u8 offset = flowctrl_offset_cpu_csr[cpuid];
|
||||
|
||||
if (WARN_ONCE(IS_ERR_OR_NULL(tegra_flowctrl_base),
|
||||
"Tegra flowctrl not initialised!\n"))
|
||||
return 0;
|
||||
|
||||
return readl(tegra_flowctrl_base + offset);
|
||||
}
|
||||
|
||||
|
@ -140,7 +149,23 @@ void flowctrl_cpu_suspend_exit(unsigned int cpuid)
|
|||
flowctrl_write_cpu_csr(cpuid, reg);
|
||||
}
|
||||
|
||||
static const struct of_device_id matches[] __initconst = {
|
||||
static int tegra_flowctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
void __iomem *base = tegra_flowctrl_base;
|
||||
struct resource *res;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
tegra_flowctrl_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(tegra_flowctrl_base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
iounmap(base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id tegra_flowctrl_match[] = {
|
||||
{ .compatible = "nvidia,tegra210-flowctrl" },
|
||||
{ .compatible = "nvidia,tegra124-flowctrl" },
|
||||
{ .compatible = "nvidia,tegra114-flowctrl" },
|
||||
{ .compatible = "nvidia,tegra30-flowctrl" },
|
||||
|
@ -148,24 +173,52 @@ static const struct of_device_id matches[] __initconst = {
|
|||
{ }
|
||||
};
|
||||
|
||||
void __init tegra_flowctrl_init(void)
|
||||
static struct platform_driver tegra_flowctrl_driver = {
|
||||
.driver = {
|
||||
.name = "tegra-flowctrl",
|
||||
.suppress_bind_attrs = true,
|
||||
.of_match_table = tegra_flowctrl_match,
|
||||
},
|
||||
.probe = tegra_flowctrl_probe,
|
||||
};
|
||||
builtin_platform_driver(tegra_flowctrl_driver);
|
||||
|
||||
static int __init tegra_flowctrl_init(void)
|
||||
{
|
||||
/* hardcoded fallback if device tree node is missing */
|
||||
unsigned long base = 0x60007000;
|
||||
unsigned long size = SZ_4K;
|
||||
struct resource res;
|
||||
struct device_node *np;
|
||||
|
||||
np = of_find_matching_node(NULL, matches);
|
||||
if (!soc_is_tegra())
|
||||
return 0;
|
||||
|
||||
np = of_find_matching_node(NULL, tegra_flowctrl_match);
|
||||
if (np) {
|
||||
struct resource res;
|
||||
|
||||
if (of_address_to_resource(np, 0, &res) == 0) {
|
||||
size = resource_size(&res);
|
||||
base = res.start;
|
||||
if (of_address_to_resource(np, 0, &res) < 0) {
|
||||
pr_err("failed to get flowctrl register\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
of_node_put(np);
|
||||
} else if (IS_ENABLED(CONFIG_ARM)) {
|
||||
/*
|
||||
* Hardcoded fallback for 32-bit Tegra
|
||||
* devices if device tree node is missing.
|
||||
*/
|
||||
res.start = 0x60007000;
|
||||
res.end = 0x60007fff;
|
||||
res.flags = IORESOURCE_MEM;
|
||||
} else {
|
||||
/*
|
||||
* At this point we're running on a Tegra,
|
||||
* that doesn't support the flow controller
|
||||
* (eg. Tegra186), so just return.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
tegra_flowctrl_base = ioremap_nocache(base, size);
|
||||
tegra_flowctrl_base = ioremap_nocache(res.start, resource_size(&res));
|
||||
if (!tegra_flowctrl_base)
|
||||
return -ENXIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
early_initcall(tegra_flowctrl_init);
|
|
@ -18,7 +18,7 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
@ -168,7 +168,7 @@ static struct platform_driver tegra_fuse_driver = {
|
|||
},
|
||||
.probe = tegra_fuse_probe,
|
||||
};
|
||||
module_platform_driver(tegra_fuse_driver);
|
||||
builtin_platform_driver(tegra_fuse_driver);
|
||||
|
||||
bool __init tegra_fuse_read_spare(unsigned int spare)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 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.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "tegra-pmc: " fmt
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
#include <asm/system_misc.h>
|
||||
|
||||
#define PMC_CNTRL 0x000
|
||||
#define PMC_CNTRL_MAIN_RST BIT(4)
|
||||
|
||||
#define PMC_RST_STATUS 0x070
|
||||
|
||||
#define WAKE_AOWAKE_CTRL 0x4f4
|
||||
#define WAKE_AOWAKE_CTRL_INTR_POLARITY BIT(0)
|
||||
|
||||
#define SCRATCH_SCRATCH0 0x2000
|
||||
#define SCRATCH_SCRATCH0_MODE_RECOVERY BIT(31)
|
||||
#define SCRATCH_SCRATCH0_MODE_BOOTLOADER BIT(30)
|
||||
#define SCRATCH_SCRATCH0_MODE_RCM BIT(1)
|
||||
#define SCRATCH_SCRATCH0_MODE_MASK (SCRATCH_SCRATCH0_MODE_RECOVERY | \
|
||||
SCRATCH_SCRATCH0_MODE_BOOTLOADER | \
|
||||
SCRATCH_SCRATCH0_MODE_RCM)
|
||||
|
||||
struct tegra_pmc {
|
||||
struct device *dev;
|
||||
void __iomem *regs;
|
||||
void __iomem *wake;
|
||||
void __iomem *aotag;
|
||||
void __iomem *scratch;
|
||||
|
||||
void (*system_restart)(enum reboot_mode mode, const char *cmd);
|
||||
struct notifier_block restart;
|
||||
};
|
||||
|
||||
static int tegra186_pmc_restart_notify(struct notifier_block *nb,
|
||||
unsigned long action,
|
||||
void *data)
|
||||
{
|
||||
struct tegra_pmc *pmc = container_of(nb, struct tegra_pmc, restart);
|
||||
const char *cmd = data;
|
||||
u32 value;
|
||||
|
||||
value = readl(pmc->scratch + SCRATCH_SCRATCH0);
|
||||
value &= ~SCRATCH_SCRATCH0_MODE_MASK;
|
||||
|
||||
if (cmd) {
|
||||
if (strcmp(cmd, "recovery") == 0)
|
||||
value |= SCRATCH_SCRATCH0_MODE_RECOVERY;
|
||||
|
||||
if (strcmp(cmd, "bootloader") == 0)
|
||||
value |= SCRATCH_SCRATCH0_MODE_BOOTLOADER;
|
||||
|
||||
if (strcmp(cmd, "forced-recovery") == 0)
|
||||
value |= SCRATCH_SCRATCH0_MODE_RCM;
|
||||
}
|
||||
|
||||
writel(value, pmc->scratch + SCRATCH_SCRATCH0);
|
||||
|
||||
/*
|
||||
* If available, call the system restart implementation that was
|
||||
* registered earlier (typically PSCI).
|
||||
*/
|
||||
if (pmc->system_restart) {
|
||||
pmc->system_restart(reboot_mode, cmd);
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
/* reset everything but SCRATCH0_SCRATCH0 and PMC_RST_STATUS */
|
||||
value = readl(pmc->regs + PMC_CNTRL);
|
||||
value |= PMC_CNTRL_MAIN_RST;
|
||||
writel(value, pmc->regs + PMC_CNTRL);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static int tegra186_pmc_setup(struct tegra_pmc *pmc)
|
||||
{
|
||||
struct device_node *np = pmc->dev->of_node;
|
||||
bool invert;
|
||||
u32 value;
|
||||
|
||||
invert = of_property_read_bool(np, "nvidia,invert-interrupt");
|
||||
|
||||
value = readl(pmc->wake + WAKE_AOWAKE_CTRL);
|
||||
|
||||
if (invert)
|
||||
value |= WAKE_AOWAKE_CTRL_INTR_POLARITY;
|
||||
else
|
||||
value &= ~WAKE_AOWAKE_CTRL_INTR_POLARITY;
|
||||
|
||||
writel(value, pmc->wake + WAKE_AOWAKE_CTRL);
|
||||
|
||||
/*
|
||||
* We need to hook any system restart implementation registered
|
||||
* previously so we can write SCRATCH_SCRATCH0 before reset.
|
||||
*/
|
||||
pmc->system_restart = arm_pm_restart;
|
||||
arm_pm_restart = NULL;
|
||||
|
||||
pmc->restart.notifier_call = tegra186_pmc_restart_notify;
|
||||
pmc->restart.priority = 128;
|
||||
|
||||
return register_restart_handler(&pmc->restart);
|
||||
}
|
||||
|
||||
static int tegra186_pmc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tegra_pmc *pmc;
|
||||
struct resource *res;
|
||||
|
||||
pmc = devm_kzalloc(&pdev->dev, sizeof(*pmc), GFP_KERNEL);
|
||||
if (!pmc)
|
||||
return -ENOMEM;
|
||||
|
||||
pmc->dev = &pdev->dev;
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pmc");
|
||||
pmc->regs = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(pmc->regs))
|
||||
return PTR_ERR(pmc->regs);
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wake");
|
||||
pmc->wake = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(pmc->wake))
|
||||
return PTR_ERR(pmc->wake);
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aotag");
|
||||
pmc->aotag = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(pmc->aotag))
|
||||
return PTR_ERR(pmc->aotag);
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "scratch");
|
||||
pmc->scratch = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(pmc->scratch))
|
||||
return PTR_ERR(pmc->scratch);
|
||||
|
||||
return tegra186_pmc_setup(pmc);
|
||||
}
|
||||
|
||||
static const struct of_device_id tegra186_pmc_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra186-pmc" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra186_pmc_of_match);
|
||||
|
||||
static struct platform_driver tegra186_pmc_driver = {
|
||||
.driver = {
|
||||
.name = "tegra186-pmc",
|
||||
.of_match_table = tegra186_pmc_of_match,
|
||||
},
|
||||
.probe = tegra186_pmc_probe,
|
||||
};
|
||||
builtin_platform_driver(tegra186_pmc_driver);
|
|
@ -38,4 +38,16 @@ config WKUP_M3_IPC
|
|||
to communicate and use the Wakeup M3 for PM features like suspend
|
||||
resume and boots it using wkup_m3_rproc driver.
|
||||
|
||||
config TI_SCI_PM_DOMAINS
|
||||
tristate "TI SCI PM Domains Driver"
|
||||
depends on TI_SCI_PROTOCOL
|
||||
depends on PM_GENERIC_DOMAINS
|
||||
help
|
||||
Generic power domain implementation for TI device implementing
|
||||
the TI SCI protocol.
|
||||
|
||||
To compile this as a module, choose M here. The module will be
|
||||
called ti_sci_pm_domains. Note this is needed early in boot before
|
||||
rootfs may be available.
|
||||
|
||||
endif # SOC_TI
|
||||
|
|
|
@ -5,3 +5,4 @@ obj-$(CONFIG_KEYSTONE_NAVIGATOR_QMSS) += knav_qmss.o
|
|||
knav_qmss-y := knav_qmss_queue.o knav_qmss_acc.o
|
||||
obj-$(CONFIG_KEYSTONE_NAVIGATOR_DMA) += knav_dma.o
|
||||
obj-$(CONFIG_WKUP_M3_IPC) += wkup_m3_ipc.o
|
||||
obj-$(CONFIG_TI_SCI_PM_DOMAINS) += ti_sci_pm_domains.o
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
* TI SCI Generic Power Domain Driver
|
||||
*
|
||||
* Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* J Keerthy <j-keerthy@ti.com>
|
||||
* Dave Gerlach <d-gerlach@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 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/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/soc/ti/ti_sci_protocol.h>
|
||||
|
||||
/**
|
||||
* struct ti_sci_genpd_dev_data: holds data needed for every device attached
|
||||
* to this genpd
|
||||
* @idx: index of the device that identifies it with the system
|
||||
* control processor.
|
||||
*/
|
||||
struct ti_sci_genpd_dev_data {
|
||||
int idx;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ti_sci_pm_domain: TI specific data needed for power domain
|
||||
* @ti_sci: handle to TI SCI protocol driver that provides ops to
|
||||
* communicate with system control processor.
|
||||
* @dev: pointer to dev for the driver for devm allocs
|
||||
* @pd: generic_pm_domain for use with the genpd framework
|
||||
*/
|
||||
struct ti_sci_pm_domain {
|
||||
const struct ti_sci_handle *ti_sci;
|
||||
struct device *dev;
|
||||
struct generic_pm_domain pd;
|
||||
};
|
||||
|
||||
#define genpd_to_ti_sci_pd(gpd) container_of(gpd, struct ti_sci_pm_domain, pd)
|
||||
|
||||
/**
|
||||
* ti_sci_dev_id(): get prepopulated ti_sci id from struct dev
|
||||
* @dev: pointer to device associated with this genpd
|
||||
*
|
||||
* Returns device_id stored from ti,sci_id property
|
||||
*/
|
||||
static int ti_sci_dev_id(struct device *dev)
|
||||
{
|
||||
struct generic_pm_domain_data *genpd_data = dev_gpd_data(dev);
|
||||
struct ti_sci_genpd_dev_data *sci_dev_data = genpd_data->data;
|
||||
|
||||
return sci_dev_data->idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* ti_sci_dev_to_sci_handle(): get pointer to ti_sci_handle
|
||||
* @dev: pointer to device associated with this genpd
|
||||
*
|
||||
* Returns ti_sci_handle to be used to communicate with system
|
||||
* control processor.
|
||||
*/
|
||||
static const struct ti_sci_handle *ti_sci_dev_to_sci_handle(struct device *dev)
|
||||
{
|
||||
struct generic_pm_domain *pd = pd_to_genpd(dev->pm_domain);
|
||||
struct ti_sci_pm_domain *ti_sci_genpd = genpd_to_ti_sci_pd(pd);
|
||||
|
||||
return ti_sci_genpd->ti_sci;
|
||||
}
|
||||
|
||||
/**
|
||||
* ti_sci_dev_start(): genpd device start hook called to turn device on
|
||||
* @dev: pointer to device associated with this genpd to be powered on
|
||||
*/
|
||||
static int ti_sci_dev_start(struct device *dev)
|
||||
{
|
||||
const struct ti_sci_handle *ti_sci = ti_sci_dev_to_sci_handle(dev);
|
||||
int idx = ti_sci_dev_id(dev);
|
||||
|
||||
return ti_sci->ops.dev_ops.get_device(ti_sci, idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* ti_sci_dev_stop(): genpd device stop hook called to turn device off
|
||||
* @dev: pointer to device associated with this genpd to be powered off
|
||||
*/
|
||||
static int ti_sci_dev_stop(struct device *dev)
|
||||
{
|
||||
const struct ti_sci_handle *ti_sci = ti_sci_dev_to_sci_handle(dev);
|
||||
int idx = ti_sci_dev_id(dev);
|
||||
|
||||
return ti_sci->ops.dev_ops.put_device(ti_sci, idx);
|
||||
}
|
||||
|
||||
static int ti_sci_pd_attach_dev(struct generic_pm_domain *domain,
|
||||
struct device *dev)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
struct of_phandle_args pd_args;
|
||||
struct ti_sci_pm_domain *ti_sci_genpd = genpd_to_ti_sci_pd(domain);
|
||||
const struct ti_sci_handle *ti_sci = ti_sci_genpd->ti_sci;
|
||||
struct ti_sci_genpd_dev_data *sci_dev_data;
|
||||
struct generic_pm_domain_data *genpd_data;
|
||||
int idx, ret = 0;
|
||||
|
||||
ret = of_parse_phandle_with_args(np, "power-domains",
|
||||
"#power-domain-cells", 0, &pd_args);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (pd_args.args_count != 1)
|
||||
return -EINVAL;
|
||||
|
||||
idx = pd_args.args[0];
|
||||
|
||||
/*
|
||||
* Check the validity of the requested idx, if the index is not valid
|
||||
* the PMMC will return a NAK here and we will not allocate it.
|
||||
*/
|
||||
ret = ti_sci->ops.dev_ops.is_valid(ti_sci, idx);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
sci_dev_data = kzalloc(sizeof(*sci_dev_data), GFP_KERNEL);
|
||||
if (!sci_dev_data)
|
||||
return -ENOMEM;
|
||||
|
||||
sci_dev_data->idx = idx;
|
||||
|
||||
genpd_data = dev_gpd_data(dev);
|
||||
genpd_data->data = sci_dev_data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ti_sci_pd_detach_dev(struct generic_pm_domain *domain,
|
||||
struct device *dev)
|
||||
{
|
||||
struct generic_pm_domain_data *genpd_data = dev_gpd_data(dev);
|
||||
struct ti_sci_genpd_dev_data *sci_dev_data = genpd_data->data;
|
||||
|
||||
kfree(sci_dev_data);
|
||||
genpd_data->data = NULL;
|
||||
}
|
||||
|
||||
static const struct of_device_id ti_sci_pm_domain_matches[] = {
|
||||
{ .compatible = "ti,sci-pm-domain", },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ti_sci_pm_domain_matches);
|
||||
|
||||
static int ti_sci_pm_domain_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct ti_sci_pm_domain *ti_sci_pd;
|
||||
int ret;
|
||||
|
||||
ti_sci_pd = devm_kzalloc(dev, sizeof(*ti_sci_pd), GFP_KERNEL);
|
||||
if (!ti_sci_pd)
|
||||
return -ENOMEM;
|
||||
|
||||
ti_sci_pd->ti_sci = devm_ti_sci_get_handle(dev);
|
||||
if (IS_ERR(ti_sci_pd->ti_sci))
|
||||
return PTR_ERR(ti_sci_pd->ti_sci);
|
||||
|
||||
ti_sci_pd->dev = dev;
|
||||
|
||||
ti_sci_pd->pd.attach_dev = ti_sci_pd_attach_dev;
|
||||
ti_sci_pd->pd.detach_dev = ti_sci_pd_detach_dev;
|
||||
|
||||
ti_sci_pd->pd.dev_ops.start = ti_sci_dev_start;
|
||||
ti_sci_pd->pd.dev_ops.stop = ti_sci_dev_stop;
|
||||
|
||||
pm_genpd_init(&ti_sci_pd->pd, NULL, true);
|
||||
|
||||
ret = of_genpd_add_provider_simple(np, &ti_sci_pd->pd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct platform_driver ti_sci_pm_domains_driver = {
|
||||
.probe = ti_sci_pm_domain_probe,
|
||||
.driver = {
|
||||
.name = "ti_sci_pm_domains",
|
||||
.of_match_table = ti_sci_pm_domain_matches,
|
||||
},
|
||||
};
|
||||
module_platform_driver(ti_sci_pm_domains_driver);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("TI System Control Interface (SCI) Power Domain driver");
|
||||
MODULE_AUTHOR("Dave Gerlach");
|
|
@ -169,7 +169,6 @@ static const struct of_device_id zx296718_pm_domain_matches[] = {
|
|||
static struct platform_driver zx296718_pd_driver = {
|
||||
.driver = {
|
||||
.name = "zx296718-powerdomain",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = zx296718_pm_domain_matches,
|
||||
},
|
||||
.probe = zx296718_pd_probe,
|
||||
|
|
|
@ -125,10 +125,8 @@ int zx2967_pd_probe(struct platform_device *pdev,
|
|||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
pcubase = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(pcubase)) {
|
||||
dev_err(&pdev->dev, "ioremap fail.\n");
|
||||
if (IS_ERR(pcubase))
|
||||
return PTR_ERR(pcubase);
|
||||
}
|
||||
|
||||
for (i = 0; i < domain_num; ++i) {
|
||||
zx_pm_domains[i]->power_on = zx2967_power_on;
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* TI K2G SoC Device definitions
|
||||
*
|
||||
* Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_GENPD_K2G_H
|
||||
#define _DT_BINDINGS_GENPD_K2G_H
|
||||
|
||||
/* Documented in http://processors.wiki.ti.com/index.php/TISCI */
|
||||
|
||||
#define K2G_DEV_PMMC0 0x0000
|
||||
#define K2G_DEV_MLB0 0x0001
|
||||
#define K2G_DEV_DSS0 0x0002
|
||||
#define K2G_DEV_MCBSP0 0x0003
|
||||
#define K2G_DEV_MCASP0 0x0004
|
||||
#define K2G_DEV_MCASP1 0x0005
|
||||
#define K2G_DEV_MCASP2 0x0006
|
||||
#define K2G_DEV_DCAN0 0x0008
|
||||
#define K2G_DEV_DCAN1 0x0009
|
||||
#define K2G_DEV_EMIF0 0x000a
|
||||
#define K2G_DEV_MMCHS0 0x000b
|
||||
#define K2G_DEV_MMCHS1 0x000c
|
||||
#define K2G_DEV_GPMC0 0x000d
|
||||
#define K2G_DEV_ELM0 0x000e
|
||||
#define K2G_DEV_SPI0 0x0010
|
||||
#define K2G_DEV_SPI1 0x0011
|
||||
#define K2G_DEV_SPI2 0x0012
|
||||
#define K2G_DEV_SPI3 0x0013
|
||||
#define K2G_DEV_ICSS0 0x0014
|
||||
#define K2G_DEV_ICSS1 0x0015
|
||||
#define K2G_DEV_USB0 0x0016
|
||||
#define K2G_DEV_USB1 0x0017
|
||||
#define K2G_DEV_NSS0 0x0018
|
||||
#define K2G_DEV_PCIE0 0x0019
|
||||
#define K2G_DEV_GPIO0 0x001b
|
||||
#define K2G_DEV_GPIO1 0x001c
|
||||
#define K2G_DEV_TIMER64_0 0x001d
|
||||
#define K2G_DEV_TIMER64_1 0x001e
|
||||
#define K2G_DEV_TIMER64_2 0x001f
|
||||
#define K2G_DEV_TIMER64_3 0x0020
|
||||
#define K2G_DEV_TIMER64_4 0x0021
|
||||
#define K2G_DEV_TIMER64_5 0x0022
|
||||
#define K2G_DEV_TIMER64_6 0x0023
|
||||
#define K2G_DEV_MSGMGR0 0x0025
|
||||
#define K2G_DEV_BOOTCFG0 0x0026
|
||||
#define K2G_DEV_ARM_BOOTROM0 0x0027
|
||||
#define K2G_DEV_DSP_BOOTROM0 0x0029
|
||||
#define K2G_DEV_DEBUGSS0 0x002b
|
||||
#define K2G_DEV_UART0 0x002c
|
||||
#define K2G_DEV_UART1 0x002d
|
||||
#define K2G_DEV_UART2 0x002e
|
||||
#define K2G_DEV_EHRPWM0 0x002f
|
||||
#define K2G_DEV_EHRPWM1 0x0030
|
||||
#define K2G_DEV_EHRPWM2 0x0031
|
||||
#define K2G_DEV_EHRPWM3 0x0032
|
||||
#define K2G_DEV_EHRPWM4 0x0033
|
||||
#define K2G_DEV_EHRPWM5 0x0034
|
||||
#define K2G_DEV_EQEP0 0x0035
|
||||
#define K2G_DEV_EQEP1 0x0036
|
||||
#define K2G_DEV_EQEP2 0x0037
|
||||
#define K2G_DEV_ECAP0 0x0038
|
||||
#define K2G_DEV_ECAP1 0x0039
|
||||
#define K2G_DEV_I2C0 0x003a
|
||||
#define K2G_DEV_I2C1 0x003b
|
||||
#define K2G_DEV_I2C2 0x003c
|
||||
#define K2G_DEV_EDMA0 0x003f
|
||||
#define K2G_DEV_SEMAPHORE0 0x0040
|
||||
#define K2G_DEV_INTC0 0x0041
|
||||
#define K2G_DEV_GIC0 0x0042
|
||||
#define K2G_DEV_QSPI0 0x0043
|
||||
#define K2G_DEV_ARM_64B_COUNTER0 0x0044
|
||||
#define K2G_DEV_TETRIS0 0x0045
|
||||
#define K2G_DEV_CGEM0 0x0046
|
||||
#define K2G_DEV_MSMC0 0x0047
|
||||
#define K2G_DEV_CBASS0 0x0049
|
||||
#define K2G_DEV_BOARD0 0x004c
|
||||
#define K2G_DEV_EDMA1 0x004f
|
||||
|
||||
#endif
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Impinj
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __DT_BINDINGS_IMX7_POWER_H__
|
||||
#define __DT_BINDINGS_IMX7_POWER_H__
|
||||
|
||||
#define IMX7_POWER_DOMAIN_MIPI_PHY 0
|
||||
#define IMX7_POWER_DOMAIN_PCIE_PHY 1
|
||||
#define IMX7_POWER_DOMAIN_USB_HSIC_PHY 2
|
||||
|
||||
#endif
|
|
@ -33,7 +33,7 @@
|
|||
#define R8A7795_PD_CA53_SCU 21
|
||||
#define R8A7795_PD_3DG_E 22
|
||||
#define R8A7795_PD_A3IR 24
|
||||
#define R8A7795_PD_A2VC0 25
|
||||
#define R8A7795_PD_A2VC0 25 /* ES1.x only */
|
||||
#define R8A7795_PD_A2VC1 26
|
||||
|
||||
/* Always-on power area */
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright Intel Corporation (C) 2017. 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/>.
|
||||
*
|
||||
* Reset binding definitions for Altera Arria10 MAX5 System Resource Chip
|
||||
*
|
||||
* Adapted from altr,rst-mgr-a10.h
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_RESET_ALTR_RST_MGR_A10SR_H
|
||||
#define _DT_BINDINGS_RESET_ALTR_RST_MGR_A10SR_H
|
||||
|
||||
/* Peripheral PHY resets */
|
||||
#define A10SR_RESET_ENET_HPS 0
|
||||
#define A10SR_RESET_PCIE 1
|
||||
#define A10SR_RESET_FILE 2
|
||||
#define A10SR_RESET_BQSPI 3
|
||||
#define A10SR_RESET_USB 4
|
||||
|
||||
#define A10SR_RESET_NUM 5
|
||||
|
||||
#endif
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Impinj, Inc.
|
||||
*
|
||||
* Author: Andrey Smirnov <andrew.smirnov@gmail.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef DT_BINDING_RESET_IMX7_H
|
||||
#define DT_BINDING_RESET_IMX7_H
|
||||
|
||||
#define IMX7_RESET_A7_CORE_POR_RESET0 0
|
||||
#define IMX7_RESET_A7_CORE_POR_RESET1 1
|
||||
#define IMX7_RESET_A7_CORE_RESET0 2
|
||||
#define IMX7_RESET_A7_CORE_RESET1 3
|
||||
#define IMX7_RESET_A7_DBG_RESET0 4
|
||||
#define IMX7_RESET_A7_DBG_RESET1 5
|
||||
#define IMX7_RESET_A7_ETM_RESET0 6
|
||||
#define IMX7_RESET_A7_ETM_RESET1 7
|
||||
#define IMX7_RESET_A7_SOC_DBG_RESET 8
|
||||
#define IMX7_RESET_A7_L2RESET 9
|
||||
#define IMX7_RESET_SW_M4C_RST 10
|
||||
#define IMX7_RESET_SW_M4P_RST 11
|
||||
#define IMX7_RESET_EIM_RST 12
|
||||
#define IMX7_RESET_HSICPHY_PORT_RST 13
|
||||
#define IMX7_RESET_USBPHY1_POR 14
|
||||
#define IMX7_RESET_USBPHY1_PORT_RST 15
|
||||
#define IMX7_RESET_USBPHY2_POR 16
|
||||
#define IMX7_RESET_USBPHY2_PORT_RST 17
|
||||
#define IMX7_RESET_MIPI_PHY_MRST 18
|
||||
#define IMX7_RESET_MIPI_PHY_SRST 19
|
||||
|
||||
/*
|
||||
* IMX7_RESET_PCIEPHY is a logical reset line combining PCIEPHY_BTN
|
||||
* and PCIEPHY_G_RST
|
||||
*/
|
||||
#define IMX7_RESET_PCIEPHY 20
|
||||
#define IMX7_RESET_PCIEPHY_PERST 21
|
||||
|
||||
/*
|
||||
* IMX7_RESET_PCIE_CTRL_APPS_EN is not strictly a reset line, but it
|
||||
* can be used to inhibit PCIe LTTSM, so, in a way, it can be thoguht
|
||||
* of as one
|
||||
*/
|
||||
#define IMX7_RESET_PCIE_CTRL_APPS_EN 22
|
||||
#define IMX7_RESET_DDRC_PRST 23
|
||||
#define IMX7_RESET_DDRC_CORE_RST 24
|
||||
|
||||
#define IMX7_RESET_NUM 25
|
||||
|
||||
#endif
|
||||
|
|
@ -25,7 +25,7 @@ int meson_sm_call(unsigned int cmd_index, u32 *ret, u32 arg0, u32 arg1,
|
|||
u32 arg2, u32 arg3, u32 arg4);
|
||||
int meson_sm_call_write(void *buffer, unsigned int b_size, unsigned int cmd_index,
|
||||
u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
|
||||
int meson_sm_call_read(void *buffer, unsigned int cmd_index, u32 arg0, u32 arg1,
|
||||
u32 arg2, u32 arg3, u32 arg4);
|
||||
int meson_sm_call_read(void *buffer, unsigned int bsize, unsigned int cmd_index,
|
||||
u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
|
||||
|
||||
#endif /* _MESON_SM_FW_H_ */
|
||||
|
|
|
@ -118,6 +118,7 @@ struct generic_pm_domain_data {
|
|||
struct pm_domain_data base;
|
||||
struct gpd_timing_data td;
|
||||
struct notifier_block nb;
|
||||
void *data;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM_GENERIC_DOMAINS
|
||||
|
|
|
@ -40,6 +40,9 @@ extern int qcom_scm_pas_shutdown(u32 peripheral);
|
|||
extern void qcom_scm_cpu_power_down(u32 flags);
|
||||
extern u32 qcom_scm_get_version(void);
|
||||
extern int qcom_scm_set_remote_state(u32 state, u32 id);
|
||||
extern int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare);
|
||||
extern int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size);
|
||||
extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare);
|
||||
#else
|
||||
static inline
|
||||
int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
|
||||
|
@ -67,5 +70,8 @@ static inline void qcom_scm_cpu_power_down(u32 flags) {}
|
|||
static inline u32 qcom_scm_get_version(void) { return 0; }
|
||||
static inline u32
|
||||
qcom_scm_set_remote_state(u32 state,u32 id) { return -ENODEV; }
|
||||
static inline int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare) { return -ENODEV; }
|
||||
static inline int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size) { return -ENODEV; }
|
||||
static inline int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) { return -ENODEV; }
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/*
|
||||
* arch/arm/mach-tegra/flowctrl.h
|
||||
*
|
||||
* functions and macros to control the flowcontroller
|
||||
* Functions and macros to control the flowcontroller
|
||||
*
|
||||
* Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
|
||||
*
|
||||
|
@ -18,8 +16,8 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_TEGRA_FLOWCTRL_H
|
||||
#define __MACH_TEGRA_FLOWCTRL_H
|
||||
#ifndef __SOC_TEGRA_FLOWCTRL_H__
|
||||
#define __SOC_TEGRA_FLOWCTRL_H__
|
||||
|
||||
#define FLOW_CTRL_HALT_CPU0_EVENTS 0x0
|
||||
#define FLOW_CTRL_WAITEVENT (2 << 29)
|
||||
|
@ -53,14 +51,32 @@
|
|||
#define TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP (0xF << 8)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifdef CONFIG_SOC_TEGRA_FLOWCTRL
|
||||
u32 flowctrl_read_cpu_csr(unsigned int cpuid);
|
||||
void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value);
|
||||
void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value);
|
||||
|
||||
void flowctrl_cpu_suspend_enter(unsigned int cpuid);
|
||||
void flowctrl_cpu_suspend_exit(unsigned int cpuid);
|
||||
#else
|
||||
static inline u32 flowctrl_read_cpu_csr(unsigned int cpuid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tegra_flowctrl_init(void);
|
||||
#endif
|
||||
static inline void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
static inline void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value) {}
|
||||
|
||||
static inline void flowctrl_cpu_suspend_enter(unsigned int cpuid)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void flowctrl_cpu_suspend_exit(unsigned int cpuid)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_SOC_TEGRA_FLOWCTRL */
|
||||
#endif /* __ASSEMBLY */
|
||||
#endif /* __SOC_TEGRA_FLOWCTRL_H__ */
|
|
@ -26,12 +26,6 @@
|
|||
struct clk;
|
||||
struct reset_control;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void);
|
||||
void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode);
|
||||
void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode);
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
bool tegra_pmc_cpu_is_powered(unsigned int cpuid);
|
||||
int tegra_pmc_cpu_power_on(unsigned int cpuid);
|
||||
|
@ -144,7 +138,7 @@ enum tegra_io_pad_voltage {
|
|||
TEGRA_IO_PAD_3300000UV,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ARCH_TEGRA
|
||||
#ifdef CONFIG_SOC_TEGRA_PMC
|
||||
int tegra_powergate_is_powered(unsigned int id);
|
||||
int tegra_powergate_power_on(unsigned int id);
|
||||
int tegra_powergate_power_off(unsigned int id);
|
||||
|
@ -163,6 +157,11 @@ int tegra_io_pad_get_voltage(enum tegra_io_pad id);
|
|||
/* deprecated, use tegra_io_pad_power_{enable,disable}() instead */
|
||||
int tegra_io_rail_power_on(unsigned int id);
|
||||
int tegra_io_rail_power_off(unsigned int id);
|
||||
|
||||
enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void);
|
||||
void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode);
|
||||
void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode);
|
||||
|
||||
#else
|
||||
static inline int tegra_powergate_is_powered(unsigned int id)
|
||||
{
|
||||
|
@ -221,6 +220,20 @@ static inline int tegra_io_rail_power_off(unsigned int id)
|
|||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif /* CONFIG_ARCH_TEGRA */
|
||||
|
||||
static inline enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void)
|
||||
{
|
||||
return TEGRA_SUSPEND_NONE;
|
||||
}
|
||||
|
||||
static inline void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SOC_TEGRA_PMC */
|
||||
|
||||
#endif /* __SOC_TEGRA_PMC_H__ */
|
||||
|
|
Loading…
Reference in New Issue