ARM: SoC driver updates for v4.7
Driver updates for ARM SoCs, these contain various things that touch the drivers/ directory but got merged through arm-soc for practical reasons. For the most part, this is now related to power management controllers, which have not yet been abstracted into a separate subsystem, and typically require some code in drivers/soc or arch/arm to control the power domains. Another large chunk here is a rework of the NVIDIA Tegra USB3.0 support, which was surprisingly tricky and took a long time to get done. Finally, reset controller handling as always gets merged through here as well. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIVAwUAVzuXkGCrR//JCVInAQKb5BAAv2HuJ/tDjC8nNfYi0/aIt4uaRfRWE84t +nIpdKl/pB9AQo+HdG9WNihHs2GN44PdQRrDZ1enQX8nvTzc+dUl0AI1GZmUDpF/ zCV2UJ39HMZcEPwf8lZk9X/JP4VOkJDM5pDgNZnnqdvkq0oqtKzmh0Kt6m2g6fIS LR3FVtCRxJDeT+pT+EpoN4jpW0cb3mjTWbn/a8Ar3BH07KBA3U22MVJhHArLjS30 /aXP+AkgdvlgmBher5z44N6Qd/KOLn78rnE4LCRC4FwSCqA+qqPJQNGNblV5MHjE s5CYTqlihqLiGapqJ4zGBhmqj0XU/3kFVboGqYlTGjzMkOFgjddTpMdfkBUoG5oJ UubJ51zzSLXTcMwILGNXVls4YjJRKwNH7jeSjuMqpWrAYP4qBcMn/HQ1GqUjkNv+ yWkheHiLDYgYkIDOBDuFUtJ7OXiVumGGxIE+r2K/sXeNI7gFcDxFExMIo11vPAWP WJ8ydTchyb/RUQbzhjEXhoIeCZwXQfe9s11qsyFQDCZLleWYQGs3gFKdEI1E7+BE oe018BSP+uaVXdaV18Ne4smwzydLAU9/ieUoO45PAUSN2reV4lWhFTlNiiiMd3Id IWoYwpxqP2VW9zJvLz6QGF/P+3cZ00m/1lecJCKHHPBmbUijCHWJmgLT73AdSXmR YIJ2UM5QMiY= =x+iD -----END PGP SIGNATURE----- Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc Pull ARM SoC driver updates from Arnd Bergmann: "Driver updates for ARM SoCs, these contain various things that touch the drivers/ directory but got merged through arm-soc for practical reasons. For the most part, this is now related to power management controllers, which have not yet been abstracted into a separate subsystem, and typically require some code in drivers/soc or arch/arm to control the power domains. Another large chunk here is a rework of the NVIDIA Tegra USB3.0 support, which was surprisingly tricky and took a long time to get done. Finally, reset controller handling as always gets merged through here as well" * tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (97 commits) arm-ccn: Enable building as module soc/tegra: pmc: Add generic PM domain support usb: xhci: tegra: Add Tegra210 support usb: xhci: Add NVIDIA Tegra XUSB controller driver dt-bindings: usb: xhci-tegra: Add Tegra210 XUSB controller support dt-bindings: usb: Add NVIDIA Tegra XUSB controller binding PCI: tegra: Support per-lane PHYs dt-bindings: pci: tegra: Update for per-lane PHYs phy: tegra: Add Tegra210 support phy: Add Tegra XUSB pad controller support dt-bindings: phy: tegra-xusb-padctl: Add Tegra210 support dt-bindings: phy: Add NVIDIA Tegra XUSB pad controller binding phy: core: Allow children node to be overridden clk: tegra: Add interface to enable hardware control of SATA/XUSB PLLs drivers: firmware: psci: make two helper functions inline soc: renesas: rcar-sysc: Add support for R-Car H3 power areas soc: renesas: rcar-sysc: Add support for R-Car E2 power areas soc: renesas: rcar-sysc: Add support for R-Car M2-N power areas soc: renesas: rcar-sysc: Add support for R-Car M2-W power areas soc: renesas: rcar-sysc: Add support for R-Car H2 power areas ...
This commit is contained in:
commit
4a5219edcd
|
@ -1,16 +1,20 @@
|
|||
NVIDIA Tegra Power Management Controller (PMC)
|
||||
|
||||
== Power Management Controller Node ==
|
||||
|
||||
The PMC block interacts with an external Power Management Unit. The PMC
|
||||
mostly controls the entry and exit of the system from different sleep
|
||||
modes. It provides power-gating controllers for SoC and CPU power-islands.
|
||||
|
||||
Required properties:
|
||||
- name : Should be pmc
|
||||
- compatible : For Tegra20, must contain "nvidia,tegra20-pmc". For Tegra30,
|
||||
must contain "nvidia,tegra30-pmc". For Tegra114, must contain
|
||||
"nvidia,tegra114-pmc". For Tegra124, must contain "nvidia,tegra124-pmc".
|
||||
Otherwise, must contain "nvidia,<chip>-pmc", plus at least one of the
|
||||
above, where <chip> is tegra132.
|
||||
- compatible : Should contain one of the following:
|
||||
For Tegra20 must contain "nvidia,tegra20-pmc".
|
||||
For Tegra30 must contain "nvidia,tegra30-pmc".
|
||||
For Tegra114 must contain "nvidia,tegra114-pmc"
|
||||
For Tegra124 must contain "nvidia,tegra124-pmc"
|
||||
For Tegra132 must contain "nvidia,tegra124-pmc"
|
||||
For Tegra210 must contain "nvidia,tegra210-pmc"
|
||||
- reg : Offset and length of the register set for the device
|
||||
- clocks : Must contain an entry for each entry in clock-names.
|
||||
See ../clocks/clock-bindings.txt for details.
|
||||
|
@ -68,6 +72,11 @@ Optional properties for hardware-triggered thermal reset (inside 'i2c-thermtrip'
|
|||
Defaults to 0. Valid values are described in section 12.5.2
|
||||
"Pinmux Support" of the Tegra4 Technical Reference Manual.
|
||||
|
||||
Optional nodes:
|
||||
- powergates : This node contains a hierarchy of power domain nodes, which
|
||||
should match the powergates on the Tegra SoC. See "Powergate
|
||||
Nodes" below.
|
||||
|
||||
Example:
|
||||
|
||||
/ SoC dts including file
|
||||
|
@ -113,3 +122,76 @@ pmc@7000f400 {
|
|||
};
|
||||
...
|
||||
};
|
||||
|
||||
|
||||
== Powergate Nodes ==
|
||||
|
||||
Each of the powergate nodes represents a power-domain on the Tegra SoC
|
||||
that can be power-gated by the Tegra PMC. The name of the powergate node
|
||||
should be one of the below. Note that not every powergate is applicable
|
||||
to all Tegra devices and the following list shows which powergates are
|
||||
applicable to which devices. Please refer to the Tegra TRM for more
|
||||
details on the various powergates.
|
||||
|
||||
Name Description Devices Applicable
|
||||
3d 3D Graphics Tegra20/114/124/210
|
||||
3d0 3D Graphics 0 Tegra30
|
||||
3d1 3D Graphics 1 Tegra30
|
||||
aud Audio Tegra210
|
||||
dfd Debug Tegra210
|
||||
dis Display A Tegra114/124/210
|
||||
disb Display B Tegra114/124/210
|
||||
heg 2D Graphics Tegra30/114/124/210
|
||||
iram Internal RAM Tegra124/210
|
||||
mpe MPEG Encode All
|
||||
nvdec NVIDIA Video Decode Engine Tegra210
|
||||
nvjpg NVIDIA JPEG Engine Tegra210
|
||||
pcie PCIE Tegra20/30/124/210
|
||||
sata SATA Tegra30/124/210
|
||||
sor Display interfaces Tegra124/210
|
||||
ve2 Video Encode Engine 2 Tegra210
|
||||
venc Video Encode Engine All
|
||||
vdec Video Decode Engine Tegra20/30/114/124
|
||||
vic Video Imaging Compositor Tegra124/210
|
||||
xusba USB Partition A Tegra114/124/210
|
||||
xusbb USB Partition B Tegra114/124/210
|
||||
xusbc USB Partition C Tegra114/124/210
|
||||
|
||||
Required properties:
|
||||
- clocks: Must contain an entry for each clock required by the PMC for
|
||||
controlling a power-gate. See ../clocks/clock-bindings.txt for details.
|
||||
- resets: Must contain an entry for each reset required by the PMC for
|
||||
controlling a power-gate. See ../reset/reset.txt for details.
|
||||
- #power-domain-cells: Must be 0.
|
||||
|
||||
Example:
|
||||
|
||||
pmc: pmc@7000e400 {
|
||||
compatible = "nvidia,tegra210-pmc";
|
||||
reg = <0x0 0x7000e400 0x0 0x400>;
|
||||
clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>;
|
||||
clock-names = "pclk", "clk32k_in";
|
||||
|
||||
powergates {
|
||||
pd_audio: aud {
|
||||
clocks = <&tegra_car TEGRA210_CLK_APE>,
|
||||
<&tegra_car TEGRA210_CLK_APB2APE>;
|
||||
resets = <&tegra_car 198>;
|
||||
#power-domain-cells = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
== Powergate Clients ==
|
||||
|
||||
Hardware blocks belonging to a power domain should contain a "power-domains"
|
||||
property that is a phandle pointing to the corresponding powergate node.
|
||||
|
||||
Example:
|
||||
|
||||
adma: adma@702e2000 {
|
||||
...
|
||||
power-domains = <&pd_audio>;
|
||||
...
|
||||
};
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
SAMSUNG Exynos SoCs SROM Controller driver.
|
||||
|
||||
Required properties:
|
||||
- compatible : Should contain "samsung,exynos4210-srom".
|
||||
|
||||
- reg: offset and length of the register set
|
||||
|
||||
Optional properties:
|
||||
The SROM controller can be used to attach external peripherals. In this case
|
||||
extra properties, describing the bus behind it, should be specified as below:
|
||||
|
||||
- #address-cells: Must be set to 2 to allow device address translation.
|
||||
Address is specified as (bank#, offset).
|
||||
|
||||
- #size-cells: Must be set to 1 to allow device size passing
|
||||
|
||||
- ranges: Must be set up to reflect the memory layout with four integer values
|
||||
per bank:
|
||||
<bank-number> 0 <parent address of bank> <size>
|
||||
|
||||
Sub-nodes:
|
||||
The actual device nodes should be added as subnodes to the SROMc node. These
|
||||
subnodes, in addition to regular device specification, should contain the following
|
||||
properties, describing configuration of the relevant SROM bank:
|
||||
|
||||
Required properties:
|
||||
- reg: bank number, base address (relative to start of the bank) and size of
|
||||
the memory mapped for the device. Note that base address will be
|
||||
typically 0 as this is the start of the bank.
|
||||
|
||||
- samsung,srom-timing : array of 6 integers, specifying bank timings in the
|
||||
following order: Tacp, Tcah, Tcoh, Tacc, Tcos, Tacs.
|
||||
Each value is specified in cycles and has the following
|
||||
meaning and valid range:
|
||||
Tacp : Page mode access cycle at Page mode (0 - 15)
|
||||
Tcah : Address holding time after CSn (0 - 15)
|
||||
Tcoh : Chip selection hold on OEn (0 - 15)
|
||||
Tacc : Access cycle (0 - 31, the actual time is N + 1)
|
||||
Tcos : Chip selection set-up before OEn (0 - 15)
|
||||
Tacs : Address set-up before CSn (0 - 15)
|
||||
|
||||
Optional properties:
|
||||
- reg-io-width : data width in bytes (1 or 2). If omitted, default of 1 is used.
|
||||
|
||||
- samsung,srom-page-mode : if page mode is set, 4 data page mode will be configured,
|
||||
else normal (1 data) page mode will be set.
|
||||
|
||||
Example: basic definition, no banks are configured
|
||||
memory-controller@12570000 {
|
||||
compatible = "samsung,exynos4210-srom";
|
||||
reg = <0x12570000 0x14>;
|
||||
};
|
||||
|
||||
Example: SROMc with SMSC911x ethernet chip on bank 3
|
||||
memory-controller@12570000 {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0 0 0x04000000 0x20000 // Bank0
|
||||
1 0 0x05000000 0x20000 // Bank1
|
||||
2 0 0x06000000 0x20000 // Bank2
|
||||
3 0 0x07000000 0x20000>; // Bank3
|
||||
|
||||
compatible = "samsung,exynos4210-srom";
|
||||
reg = <0x12570000 0x14>;
|
||||
|
||||
ethernet@3,0 {
|
||||
compatible = "smsc,lan9115";
|
||||
reg = <3 0 0x10000>; // Bank 3, offset = 0
|
||||
phy-mode = "mii";
|
||||
interrupt-parent = <&gpx0>;
|
||||
interrupts = <5 8>;
|
||||
reg-io-width = <2>;
|
||||
smsc,irq-push-pull;
|
||||
smsc,force-internal-phy;
|
||||
|
||||
samsung,srom-page-mode;
|
||||
samsung,srom-timing = <9 12 1 9 1 1>;
|
||||
};
|
||||
};
|
|
@ -1,8 +1,26 @@
|
|||
Flash device on ARM Versatile board
|
||||
|
||||
These flash chips are found in the ARM reference designs like Integrator,
|
||||
Versatile, RealView, Versatile Express etc.
|
||||
|
||||
They are regular CFI compatible (Intel or AMD extended) flash chips with
|
||||
some special write protect/VPP bits that can be controlled by the machine's
|
||||
system controller.
|
||||
|
||||
Required properties:
|
||||
- compatible : must be "arm,versatile-flash";
|
||||
- compatible : must be "arm,versatile-flash", "cfi-flash";
|
||||
- reg : memory address for the flash chip
|
||||
- bank-width : width in bytes of flash interface.
|
||||
|
||||
For the rest of the properties, see mtd-physmap.txt.
|
||||
|
||||
The device tree may optionally contain sub-nodes describing partitions of the
|
||||
address space. See partition.txt for more detail.
|
||||
|
||||
Example:
|
||||
|
||||
flash@34000000 {
|
||||
compatible = "arm,versatile-flash", "cfi-flash";
|
||||
reg = <0x34000000 0x4000000>;
|
||||
bank-width = <4>;
|
||||
};
|
||||
|
|
|
@ -60,11 +60,14 @@ Required properties:
|
|||
- afi
|
||||
- pcie_x
|
||||
|
||||
Required properties on Tegra124 and later:
|
||||
Required properties on Tegra124 and later (deprecated):
|
||||
- phys: Must contain an entry for each entry in phy-names.
|
||||
- phy-names: Must include the following entries:
|
||||
- pcie
|
||||
|
||||
These properties are deprecated in favour of per-lane PHYs define in each of
|
||||
the root ports (see below).
|
||||
|
||||
Power supplies for Tegra20:
|
||||
- avdd-pex-supply: Power supply for analog PCIe logic. Must supply 1.05 V.
|
||||
- vdd-pex-supply: Power supply for digital PCIe I/O. Must supply 1.05 V.
|
||||
|
@ -122,11 +125,22 @@ Required properties:
|
|||
- Root port 0 uses 4 lanes, root port 1 is unused.
|
||||
- Both root ports use 2 lanes.
|
||||
|
||||
Example:
|
||||
Required properties for Tegra124 and later:
|
||||
- phys: Must contain an phandle to a PHY for each entry in phy-names.
|
||||
- phy-names: Must include an entry for each active lane. Note that the number
|
||||
of entries does not have to (though usually will) be equal to the specified
|
||||
number of lanes in the nvidia,num-lanes property. Entries are of the form
|
||||
"pcie-N": where N ranges from 0 to the value specified in nvidia,num-lanes.
|
||||
|
||||
Examples:
|
||||
=========
|
||||
|
||||
Tegra20:
|
||||
--------
|
||||
|
||||
SoC DTSI:
|
||||
|
||||
pcie-controller {
|
||||
pcie-controller@80003000 {
|
||||
compatible = "nvidia,tegra20-pcie";
|
||||
device_type = "pci";
|
||||
reg = <0x80003000 0x00000800 /* PADS registers */
|
||||
|
@ -186,10 +200,9 @@ SoC DTSI:
|
|||
};
|
||||
};
|
||||
|
||||
|
||||
Board DTS:
|
||||
|
||||
pcie-controller {
|
||||
pcie-controller@80003000 {
|
||||
status = "okay";
|
||||
|
||||
vdd-supply = <&pci_vdd_reg>;
|
||||
|
@ -222,3 +235,204 @@ if a device on the PCI bus provides a non-probeable bus such as I2C or SPI,
|
|||
device nodes need to be added in order to allow the bus' children to be
|
||||
instantiated at the proper location in the operating system's device tree (as
|
||||
illustrated by the optional nodes in the example above).
|
||||
|
||||
Tegra30:
|
||||
--------
|
||||
|
||||
SoC DTSI:
|
||||
|
||||
pcie-controller@00003000 {
|
||||
compatible = "nvidia,tegra30-pcie";
|
||||
device_type = "pci";
|
||||
reg = <0x00003000 0x00000800 /* PADS registers */
|
||||
0x00003800 0x00000200 /* AFI registers */
|
||||
0x10000000 0x10000000>; /* configuration space */
|
||||
reg-names = "pads", "afi", "cs";
|
||||
interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH /* controller interrupt */
|
||||
GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; /* MSI interrupt */
|
||||
interrupt-names = "intr", "msi";
|
||||
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 0 &intc GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
bus-range = <0x00 0xff>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
|
||||
ranges = <0x82000000 0 0x00000000 0x00000000 0 0x00001000 /* port 0 configuration space */
|
||||
0x82000000 0 0x00001000 0x00001000 0 0x00001000 /* port 1 configuration space */
|
||||
0x82000000 0 0x00004000 0x00004000 0 0x00001000 /* port 2 configuration space */
|
||||
0x81000000 0 0 0x02000000 0 0x00010000 /* downstream I/O */
|
||||
0x82000000 0 0x20000000 0x20000000 0 0x08000000 /* non-prefetchable memory */
|
||||
0xc2000000 0 0x28000000 0x28000000 0 0x18000000>; /* prefetchable memory */
|
||||
|
||||
clocks = <&tegra_car TEGRA30_CLK_PCIE>,
|
||||
<&tegra_car TEGRA30_CLK_AFI>,
|
||||
<&tegra_car TEGRA30_CLK_PLL_E>,
|
||||
<&tegra_car TEGRA30_CLK_CML0>;
|
||||
clock-names = "pex", "afi", "pll_e", "cml";
|
||||
resets = <&tegra_car 70>,
|
||||
<&tegra_car 72>,
|
||||
<&tegra_car 74>;
|
||||
reset-names = "pex", "afi", "pcie_x";
|
||||
status = "disabled";
|
||||
|
||||
pci@1,0 {
|
||||
device_type = "pci";
|
||||
assigned-addresses = <0x82000800 0 0x00000000 0 0x1000>;
|
||||
reg = <0x000800 0 0 0 0>;
|
||||
status = "disabled";
|
||||
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
nvidia,num-lanes = <2>;
|
||||
};
|
||||
|
||||
pci@2,0 {
|
||||
device_type = "pci";
|
||||
assigned-addresses = <0x82001000 0 0x00001000 0 0x1000>;
|
||||
reg = <0x001000 0 0 0 0>;
|
||||
status = "disabled";
|
||||
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
nvidia,num-lanes = <2>;
|
||||
};
|
||||
|
||||
pci@3,0 {
|
||||
device_type = "pci";
|
||||
assigned-addresses = <0x82001800 0 0x00004000 0 0x1000>;
|
||||
reg = <0x001800 0 0 0 0>;
|
||||
status = "disabled";
|
||||
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
nvidia,num-lanes = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
Board DTS:
|
||||
|
||||
pcie-controller@00003000 {
|
||||
status = "okay";
|
||||
|
||||
avdd-pexa-supply = <&ldo1_reg>;
|
||||
vdd-pexa-supply = <&ldo1_reg>;
|
||||
avdd-pexb-supply = <&ldo1_reg>;
|
||||
vdd-pexb-supply = <&ldo1_reg>;
|
||||
avdd-pex-pll-supply = <&ldo1_reg>;
|
||||
avdd-plle-supply = <&ldo1_reg>;
|
||||
vddio-pex-ctl-supply = <&sys_3v3_reg>;
|
||||
hvdd-pex-supply = <&sys_3v3_pexs_reg>;
|
||||
|
||||
pci@1,0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pci@3,0 {
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
Tegra124:
|
||||
---------
|
||||
|
||||
SoC DTSI:
|
||||
|
||||
pcie-controller@01003000 {
|
||||
compatible = "nvidia,tegra124-pcie";
|
||||
device_type = "pci";
|
||||
reg = <0x0 0x01003000 0x0 0x00000800 /* PADS registers */
|
||||
0x0 0x01003800 0x0 0x00000800 /* AFI registers */
|
||||
0x0 0x02000000 0x0 0x10000000>; /* configuration space */
|
||||
reg-names = "pads", "afi", "cs";
|
||||
interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>, /* controller interrupt */
|
||||
<GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; /* MSI interrupt */
|
||||
interrupt-names = "intr", "msi";
|
||||
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 0 &gic GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
bus-range = <0x00 0xff>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
|
||||
ranges = <0x82000000 0 0x01000000 0x0 0x01000000 0 0x00001000 /* port 0 configuration space */
|
||||
0x82000000 0 0x01001000 0x0 0x01001000 0 0x00001000 /* port 1 configuration space */
|
||||
0x81000000 0 0x0 0x0 0x12000000 0 0x00010000 /* downstream I/O (64 KiB) */
|
||||
0x82000000 0 0x13000000 0x0 0x13000000 0 0x0d000000 /* non-prefetchable memory (208 MiB) */
|
||||
0xc2000000 0 0x20000000 0x0 0x20000000 0 0x20000000>; /* prefetchable memory (512 MiB) */
|
||||
|
||||
clocks = <&tegra_car TEGRA124_CLK_PCIE>,
|
||||
<&tegra_car TEGRA124_CLK_AFI>,
|
||||
<&tegra_car TEGRA124_CLK_PLL_E>,
|
||||
<&tegra_car TEGRA124_CLK_CML0>;
|
||||
clock-names = "pex", "afi", "pll_e", "cml";
|
||||
resets = <&tegra_car 70>,
|
||||
<&tegra_car 72>,
|
||||
<&tegra_car 74>;
|
||||
reset-names = "pex", "afi", "pcie_x";
|
||||
status = "disabled";
|
||||
|
||||
pci@1,0 {
|
||||
device_type = "pci";
|
||||
assigned-addresses = <0x82000800 0 0x01000000 0 0x1000>;
|
||||
reg = <0x000800 0 0 0 0>;
|
||||
status = "disabled";
|
||||
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
nvidia,num-lanes = <2>;
|
||||
};
|
||||
|
||||
pci@2,0 {
|
||||
device_type = "pci";
|
||||
assigned-addresses = <0x82001000 0 0x01001000 0 0x1000>;
|
||||
reg = <0x001000 0 0 0 0>;
|
||||
status = "disabled";
|
||||
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
nvidia,num-lanes = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
Board DTS:
|
||||
|
||||
pcie-controller@01003000 {
|
||||
status = "okay";
|
||||
|
||||
avddio-pex-supply = <&vdd_1v05_run>;
|
||||
dvddio-pex-supply = <&vdd_1v05_run>;
|
||||
avdd-pex-pll-supply = <&vdd_1v05_run>;
|
||||
hvdd-pex-supply = <&vdd_3v3_lp0>;
|
||||
hvdd-pex-pll-e-supply = <&vdd_3v3_lp0>;
|
||||
vddio-pex-ctl-supply = <&vdd_3v3_lp0>;
|
||||
avdd-pll-erefe-supply = <&avdd_1v05_run>;
|
||||
|
||||
/* Mini PCIe */
|
||||
pci@1,0 {
|
||||
phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-4}>;
|
||||
phy-names = "pcie-0";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* Gigabit Ethernet */
|
||||
pci@2,0 {
|
||||
phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-2}>;
|
||||
phy-names = "pcie-0";
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -0,0 +1,733 @@
|
|||
Device tree binding for NVIDIA Tegra XUSB pad controller
|
||||
========================================================
|
||||
|
||||
The Tegra XUSB pad controller manages a set of I/O lanes (with differential
|
||||
signals) which connect directly to pins/pads on the SoC package. Each lane
|
||||
is controlled by a HW block referred to as a "pad" in the Tegra hardware
|
||||
documentation. Each such "pad" may control either one or multiple lanes,
|
||||
and thus contains any logic common to all its lanes. Each lane can be
|
||||
separately configured and powered up.
|
||||
|
||||
Some of the lanes are high-speed lanes, which can be used for PCIe, SATA or
|
||||
super-speed USB. Other lanes are for various types of low-speed, full-speed
|
||||
or high-speed USB (such as UTMI, ULPI and HSIC). The XUSB pad controller
|
||||
contains a software-configurable mux that sits between the I/O controller
|
||||
ports (e.g. PCIe) and the lanes.
|
||||
|
||||
In addition to per-lane configuration, USB 3.0 ports may require additional
|
||||
settings on a per-board basis.
|
||||
|
||||
Pads will be represented as children of the top-level XUSB pad controller
|
||||
device tree node. Each lane exposed by the pad will be represented by its
|
||||
own subnode and can be referenced by users of the lane using the standard
|
||||
PHY bindings, as described by the phy-bindings.txt file in this directory.
|
||||
|
||||
The Tegra hardware documentation refers to the connection between the XUSB
|
||||
pad controller and the XUSB controller as "ports". This is confusing since
|
||||
"port" is typically used to denote the physical USB receptacle. The device
|
||||
tree binding in this document uses the term "port" to refer to the logical
|
||||
abstraction of the signals that are routed to a USB receptacle (i.e. a PHY
|
||||
for the USB signal, the VBUS power supply, the USB 2.0 companion port for
|
||||
USB 3.0 receptacles, ...).
|
||||
|
||||
Required properties:
|
||||
--------------------
|
||||
- compatible: Must be:
|
||||
- Tegra124: "nvidia,tegra124-xusb-padctl"
|
||||
- Tegra132: "nvidia,tegra132-xusb-padctl", "nvidia,tegra124-xusb-padctl"
|
||||
- Tegra210: "nvidia,tegra210-xusb-padctl"
|
||||
- reg: Physical base address and length of the controller's registers.
|
||||
- resets: Must contain an entry for each entry in reset-names.
|
||||
- reset-names: Must include the following entries:
|
||||
- "padctl"
|
||||
|
||||
|
||||
Pad nodes:
|
||||
==========
|
||||
|
||||
A required child node named "pads" contains a list of subnodes, one for each
|
||||
of the pads exposed by the XUSB pad controller. Each pad may need additional
|
||||
resources that can be referenced in its pad node.
|
||||
|
||||
The "status" property is used to enable or disable the use of a pad. If set
|
||||
to "disabled", the pad will not be used on the given board. In order to use
|
||||
the pad and any of its lanes, this property must be set to "okay".
|
||||
|
||||
For Tegra124 and Tegra132, the following pads exist: usb2, ulpi, hsic, pcie
|
||||
and sata. No extra resources are required for operation of these pads.
|
||||
|
||||
For Tegra210, the following pads exist: usb2, hsic, pcie and sata. Below is
|
||||
a description of the properties of each pad.
|
||||
|
||||
UTMI pad:
|
||||
---------
|
||||
|
||||
Required properties:
|
||||
- clocks: Must contain an entry for each entry in clock-names.
|
||||
- clock-names: Must contain the following entries:
|
||||
- "trk": phandle and specifier referring to the USB2 tracking clock
|
||||
|
||||
HSIC pad:
|
||||
---------
|
||||
|
||||
Required properties:
|
||||
- clocks: Must contain an entry for each entry in clock-names.
|
||||
- clock-names: Must contain the following entries:
|
||||
- "trk": phandle and specifier referring to the HSIC tracking clock
|
||||
|
||||
PCIe pad:
|
||||
---------
|
||||
|
||||
Required properties:
|
||||
- clocks: Must contain an entry for each entry in clock-names.
|
||||
- clock-names: Must contain the following entries:
|
||||
- "pll": phandle and specifier referring to the PLLE
|
||||
- resets: Must contain an entry for each entry in reset-names.
|
||||
- reset-names: Must contain the following entries:
|
||||
- "phy": reset for the PCIe UPHY block
|
||||
|
||||
SATA pad:
|
||||
---------
|
||||
|
||||
Required properties:
|
||||
- resets: Must contain an entry for each entry in reset-names.
|
||||
- reset-names: Must contain the following entries:
|
||||
- "phy": reset for the SATA UPHY block
|
||||
|
||||
|
||||
PHY nodes:
|
||||
==========
|
||||
|
||||
Each pad node has a child named "lanes" that contains one or more children of
|
||||
its own, each representing one of the lanes controlled by the pad.
|
||||
|
||||
Required properties:
|
||||
--------------------
|
||||
- status: Defines the operation status of the PHY. Valid values are:
|
||||
- "disabled": the PHY is disabled
|
||||
- "okay": the PHY is enabled
|
||||
- #phy-cells: Should be 0. Since each lane represents a single PHY, there is
|
||||
no need for an additional specifier.
|
||||
- nvidia,function: The output function of the PHY. See below for a list of
|
||||
valid functions per SoC generation.
|
||||
|
||||
For Tegra124 and Tegra132, the list of valid PHY nodes is given below:
|
||||
- usb2: usb2-0, usb2-1, usb2-2
|
||||
- functions: "snps", "xusb", "uart"
|
||||
- ulpi: ulpi-0
|
||||
- functions: "snps", "xusb"
|
||||
- hsic: hsic-0, hsic-1
|
||||
- functions: "snps", "xusb"
|
||||
- pcie: pcie-0, pcie-1, pcie-2, pcie-3, pcie-4
|
||||
- functions: "pcie", "usb3-ss"
|
||||
- sata: sata-0
|
||||
- functions: "usb3-ss", "sata"
|
||||
|
||||
For Tegra210, the list of valid PHY nodes is given below:
|
||||
- utmi: utmi-0, utmi-1, utmi-2, utmi-3
|
||||
- functions: "snps", "xusb", "uart"
|
||||
- hsic: hsic-0, hsic-1
|
||||
- functions: "snps", "xusb"
|
||||
- pcie: pcie-0, pcie-1, pcie-2, pcie-3, pcie-4, pcie-5, pcie-6
|
||||
- functions: "pcie-x1", "usb3-ss", "pcie-x4"
|
||||
- sata: sata-0
|
||||
- functions: "usb3-ss", "sata"
|
||||
|
||||
|
||||
Port nodes:
|
||||
===========
|
||||
|
||||
A required child node named "ports" contains a list of all the ports exposed
|
||||
by the XUSB pad controller. Per-port configuration is only required for USB.
|
||||
|
||||
USB2 ports:
|
||||
-----------
|
||||
|
||||
Required properties:
|
||||
- status: Defines the operation status of the port. Valid values are:
|
||||
- "disabled": the port is disabled
|
||||
- "okay": the port is enabled
|
||||
- mode: A string that determines the mode in which to run the port. Valid
|
||||
values are:
|
||||
- "host": for USB host mode
|
||||
- "device": for USB device mode
|
||||
- "otg": for USB OTG mode
|
||||
|
||||
Optional properties:
|
||||
- nvidia,internal: A boolean property whose presence determines that a port
|
||||
is internal. In the absence of this property the port is considered to be
|
||||
external.
|
||||
- vbus-supply: phandle to a regulator supplying the VBUS voltage.
|
||||
|
||||
ULPI ports:
|
||||
-----------
|
||||
|
||||
Optional properties:
|
||||
- status: Defines the operation status of the port. Valid values are:
|
||||
- "disabled": the port is disabled
|
||||
- "okay": the port is enabled
|
||||
- nvidia,internal: A boolean property whose presence determines that a port
|
||||
is internal. In the absence of this property the port is considered to be
|
||||
external.
|
||||
- vbus-supply: phandle to a regulator supplying the VBUS voltage.
|
||||
|
||||
HSIC ports:
|
||||
-----------
|
||||
|
||||
Required properties:
|
||||
- status: Defines the operation status of the port. Valid values are:
|
||||
- "disabled": the port is disabled
|
||||
- "okay": the port is enabled
|
||||
|
||||
Optional properties:
|
||||
- vbus-supply: phandle to a regulator supplying the VBUS voltage.
|
||||
|
||||
Super-speed USB ports:
|
||||
----------------------
|
||||
|
||||
Required properties:
|
||||
- status: Defines the operation status of the port. Valid values are:
|
||||
- "disabled": the port is disabled
|
||||
- "okay": the port is enabled
|
||||
- nvidia,usb2-companion: A single cell that specifies the physical port number
|
||||
to map this super-speed USB port to. The range of valid port numbers varies
|
||||
with the SoC generation:
|
||||
- 0-2: for Tegra124 and Tegra132
|
||||
- 0-3: for Tegra210
|
||||
|
||||
Optional properties:
|
||||
- nvidia,internal: A boolean property whose presence determines that a port
|
||||
is internal. In the absence of this property the port is considered to be
|
||||
external.
|
||||
|
||||
For Tegra124 and Tegra132, the XUSB pad controller exposes the following
|
||||
ports:
|
||||
- 3x USB2: usb2-0, usb2-1, usb2-2
|
||||
- 1x ULPI: ulpi-0
|
||||
- 2x HSIC: hsic-0, hsic-1
|
||||
- 2x super-speed USB: usb3-0, usb3-1
|
||||
|
||||
For Tegra210, the XUSB pad controller exposes the following ports:
|
||||
- 4x USB2: usb2-0, usb2-1, usb2-2, usb2-3
|
||||
- 2x HSIC: hsic-0, hsic-1
|
||||
- 4x super-speed USB: usb3-0, usb3-1, usb3-2, usb3-3
|
||||
|
||||
|
||||
Examples:
|
||||
=========
|
||||
|
||||
Tegra124 and Tegra132:
|
||||
----------------------
|
||||
|
||||
SoC include:
|
||||
|
||||
padctl@7009f000 {
|
||||
/* for Tegra124 */
|
||||
compatible = "nvidia,tegra124-xusb-padctl";
|
||||
/* for Tegra132 */
|
||||
compatible = "nvidia,tegra132-xusb-padctl",
|
||||
"nvidia,tegra124-xusb-padctl";
|
||||
reg = <0x0 0x7009f000 0x0 0x1000>;
|
||||
resets = <&tegra_car 142>;
|
||||
reset-names = "padctl";
|
||||
|
||||
pads {
|
||||
usb2 {
|
||||
status = "disabled";
|
||||
|
||||
lanes {
|
||||
usb2-0 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
|
||||
usb2-1 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
|
||||
usb2-2 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ulpi {
|
||||
status = "disabled";
|
||||
|
||||
lanes {
|
||||
ulpi-0 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
hsic {
|
||||
status = "disabled";
|
||||
|
||||
lanes {
|
||||
hsic-0 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
|
||||
hsic-1 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pcie {
|
||||
status = "disabled";
|
||||
|
||||
lanes {
|
||||
pcie-0 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
|
||||
pcie-1 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
|
||||
pcie-2 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
|
||||
pcie-3 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
|
||||
pcie-4 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
sata {
|
||||
status = "disabled";
|
||||
|
||||
lanes {
|
||||
sata-0 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ports {
|
||||
usb2-0 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usb2-1 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usb2-2 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
ulpi-0 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
hsic-0 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
hsic-1 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usb3-0 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usb3-1 {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Board file:
|
||||
|
||||
padctl@7009f000 {
|
||||
status = "okay";
|
||||
|
||||
pads {
|
||||
usb2 {
|
||||
status = "okay";
|
||||
|
||||
lanes {
|
||||
usb2-0 {
|
||||
nvidia,function = "xusb";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb2-1 {
|
||||
nvidia,function = "xusb";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb2-2 {
|
||||
nvidia,function = "xusb";
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pcie {
|
||||
status = "okay";
|
||||
|
||||
lanes {
|
||||
pcie-0 {
|
||||
nvidia,function = "usb3-ss";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pcie-2 {
|
||||
nvidia,function = "pcie";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pcie-4 {
|
||||
nvidia,function = "pcie";
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
sata {
|
||||
status = "okay";
|
||||
|
||||
lanes {
|
||||
sata-0 {
|
||||
nvidia,function = "sata";
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ports {
|
||||
/* Micro A/B */
|
||||
usb2-0 {
|
||||
status = "okay";
|
||||
mode = "otg";
|
||||
};
|
||||
|
||||
/* Mini PCIe */
|
||||
usb2-1 {
|
||||
status = "okay";
|
||||
mode = "host";
|
||||
};
|
||||
|
||||
/* USB3 */
|
||||
usb2-2 {
|
||||
status = "okay";
|
||||
mode = "host";
|
||||
|
||||
vbus-supply = <&vdd_usb3_vbus>;
|
||||
};
|
||||
|
||||
usb3-0 {
|
||||
nvidia,port = <2>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Tegra210:
|
||||
---------
|
||||
|
||||
SoC include:
|
||||
|
||||
padctl@7009f000 {
|
||||
compatible = "nvidia,tegra210-xusb-padctl";
|
||||
reg = <0x0 0x7009f000 0x0 0x1000>;
|
||||
resets = <&tegra_car 142>;
|
||||
reset-names = "padctl";
|
||||
|
||||
status = "disabled";
|
||||
|
||||
pads {
|
||||
usb2 {
|
||||
clocks = <&tegra_car TEGRA210_CLK_USB2_TRK>;
|
||||
clock-names = "trk";
|
||||
status = "disabled";
|
||||
|
||||
lanes {
|
||||
usb2-0 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
|
||||
usb2-1 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
|
||||
usb2-2 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
|
||||
usb2-3 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
hsic {
|
||||
clocks = <&tegra_car TEGRA210_CLK_HSIC_TRK>;
|
||||
clock-names = "trk";
|
||||
status = "disabled";
|
||||
|
||||
lanes {
|
||||
hsic-0 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
|
||||
hsic-1 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pcie {
|
||||
clocks = <&tegra_car TEGRA210_CLK_PLL_E>;
|
||||
clock-names = "pll";
|
||||
resets = <&tegra_car 205>;
|
||||
reset-names = "phy";
|
||||
status = "disabled";
|
||||
|
||||
lanes {
|
||||
pcie-0 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
|
||||
pcie-1 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
|
||||
pcie-2 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
|
||||
pcie-3 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
|
||||
pcie-4 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
|
||||
pcie-5 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
|
||||
pcie-6 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
sata {
|
||||
clocks = <&tegra_car TEGRA210_CLK_PLL_E>;
|
||||
clock-names = "pll";
|
||||
resets = <&tegra_car 204>;
|
||||
reset-names = "phy";
|
||||
status = "disabled";
|
||||
|
||||
lanes {
|
||||
sata-0 {
|
||||
status = "disabled";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ports {
|
||||
usb2-0 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usb2-1 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usb2-2 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usb2-3 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
hsic-0 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
hsic-1 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usb3-0 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usb3-1 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usb3-2 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usb3-3 {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Board file:
|
||||
|
||||
padctl@7009f000 {
|
||||
status = "okay";
|
||||
|
||||
pads {
|
||||
usb2 {
|
||||
status = "okay";
|
||||
|
||||
lanes {
|
||||
usb2-0 {
|
||||
nvidia,function = "xusb";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb2-1 {
|
||||
nvidia,function = "xusb";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb2-2 {
|
||||
nvidia,function = "xusb";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb2-3 {
|
||||
nvidia,function = "xusb";
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pcie {
|
||||
status = "okay";
|
||||
|
||||
lanes {
|
||||
pcie-0 {
|
||||
nvidia,function = "pcie-x1";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pcie-1 {
|
||||
nvidia,function = "pcie-x4";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pcie-2 {
|
||||
nvidia,function = "pcie-x4";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pcie-3 {
|
||||
nvidia,function = "pcie-x4";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pcie-4 {
|
||||
nvidia,function = "pcie-x4";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pcie-5 {
|
||||
nvidia,function = "usb3-ss";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pcie-6 {
|
||||
nvidia,function = "usb3-ss";
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
sata {
|
||||
status = "okay";
|
||||
|
||||
lanes {
|
||||
sata-0 {
|
||||
nvidia,function = "sata";
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ports {
|
||||
usb2-0 {
|
||||
status = "okay";
|
||||
mode = "otg";
|
||||
};
|
||||
|
||||
usb2-1 {
|
||||
status = "okay";
|
||||
vbus-supply = <&vdd_5v0_rtl>;
|
||||
mode = "host";
|
||||
};
|
||||
|
||||
usb2-2 {
|
||||
status = "okay";
|
||||
vbus-supply = <&vdd_usb_vbus>;
|
||||
mode = "host";
|
||||
};
|
||||
|
||||
usb2-3 {
|
||||
status = "okay";
|
||||
mode = "host";
|
||||
};
|
||||
|
||||
usb3-0 {
|
||||
status = "okay";
|
||||
nvidia,lanes = "pcie-6";
|
||||
nvidia,port = <1>;
|
||||
};
|
||||
|
||||
usb3-1 {
|
||||
status = "okay";
|
||||
nvidia,lanes = "pcie-5";
|
||||
nvidia,port = <2>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -1,6 +1,12 @@
|
|||
Device tree binding for NVIDIA Tegra XUSB pad controller
|
||||
========================================================
|
||||
|
||||
NOTE: It turns out that this binding isn't an accurate description of the XUSB
|
||||
pad controller. While the description is good enough for the functional subset
|
||||
required for PCIe and SATA, it lacks the flexibility to represent the features
|
||||
needed for USB. For the new binding, see ../phy/nvidia,tegra-xusb-padctl.txt.
|
||||
The binding described in this file is deprecated and should not be used.
|
||||
|
||||
The Tegra XUSB pad controller manages a set of lanes, each of which can be
|
||||
assigned to one out of a set of different pads. Some of these pads have an
|
||||
associated PHY that must be powered up before the pad can be used.
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
Oxford Semiconductor OXNAS SoC Family RESET Controller
|
||||
================================================
|
||||
|
||||
Please also refer to reset.txt in this directory for common reset
|
||||
controller binding usage.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "oxsemi,ox810se-reset"
|
||||
- #reset-cells: 1, see below
|
||||
|
||||
Parent node should have the following properties :
|
||||
- compatible: Should be "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd"
|
||||
|
||||
For OX810SE, the indices are :
|
||||
- 0 : ARM
|
||||
- 1 : COPRO
|
||||
- 2 : Reserved
|
||||
- 3 : Reserved
|
||||
- 4 : USBHS
|
||||
- 5 : USBHSPHY
|
||||
- 6 : MAC
|
||||
- 7 : PCI
|
||||
- 8 : DMA
|
||||
- 9 : DPE
|
||||
- 10 : DDR
|
||||
- 11 : SATA
|
||||
- 12 : SATA_LINK
|
||||
- 13 : SATA_PHY
|
||||
- 14 : Reserved
|
||||
- 15 : NAND
|
||||
- 16 : GPIO
|
||||
- 17 : UART1
|
||||
- 18 : UART2
|
||||
- 19 : MISC
|
||||
- 20 : I2S
|
||||
- 21 : AHB_MON
|
||||
- 22 : UART3
|
||||
- 23 : UART4
|
||||
- 24 : SGDMA
|
||||
- 25 : Reserved
|
||||
- 26 : Reserved
|
||||
- 27 : Reserved
|
||||
- 28 : Reserved
|
||||
- 29 : Reserved
|
||||
- 30 : Reserved
|
||||
- 31 : BUS
|
||||
|
||||
example:
|
||||
|
||||
sys: sys-ctrl@000000 {
|
||||
compatible = "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd";
|
||||
reg = <0x000000 0x100000>;
|
||||
|
||||
reset: reset-controller {
|
||||
compatible = "oxsemi,ox810se-reset";
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
};
|
|
@ -7,6 +7,7 @@ Required properties for power domain controller:
|
|||
- compatible: Should be one of the following.
|
||||
"rockchip,rk3288-power-controller" - for RK3288 SoCs.
|
||||
"rockchip,rk3368-power-controller" - for RK3368 SoCs.
|
||||
"rockchip,rk3399-power-controller" - for RK3399 SoCs.
|
||||
- #power-domain-cells: Number of cells in a power-domain specifier.
|
||||
Should be 1 for multiple PM domains.
|
||||
- #address-cells: Should be 1.
|
||||
|
@ -16,8 +17,18 @@ Required properties for power domain sub nodes:
|
|||
- reg: index of the power domain, should use macros in:
|
||||
"include/dt-bindings/power/rk3288-power.h" - for RK3288 type power domain.
|
||||
"include/dt-bindings/power/rk3368-power.h" - for RK3368 type power domain.
|
||||
"include/dt-bindings/power/rk3399-power.h" - for RK3399 type power domain.
|
||||
- clocks (optional): phandles to clocks which need to be enabled while power domain
|
||||
switches state.
|
||||
- pm_qos (optional): phandles to qos blocks which need to be saved and restored
|
||||
while power domain switches state.
|
||||
|
||||
Qos Example:
|
||||
|
||||
qos_gpu: qos_gpu@ffaf0000 {
|
||||
compatible ="syscon";
|
||||
reg = <0x0 0xffaf0000 0x0 0x20>;
|
||||
};
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -30,6 +41,7 @@ Example:
|
|||
pd_gpu {
|
||||
reg = <RK3288_PD_GPU>;
|
||||
clocks = <&cru ACLK_GPU>;
|
||||
pm_qos = <&qos_gpu>;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -45,12 +57,41 @@ Example:
|
|||
};
|
||||
};
|
||||
|
||||
Example 2:
|
||||
power: power-controller {
|
||||
compatible = "rockchip,rk3399-power-controller";
|
||||
#power-domain-cells = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pd_vio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <RK3399_PD_VIO>;
|
||||
|
||||
pd_vo {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <RK3399_PD_VO>;
|
||||
|
||||
pd_vopb {
|
||||
reg = <RK3399_PD_VOPB>;
|
||||
};
|
||||
|
||||
pd_vopl {
|
||||
reg = <RK3399_PD_VOPL>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Node of a device using power domains must have a power-domains property,
|
||||
containing a phandle to the power device node and an index specifying which
|
||||
power domain to use.
|
||||
The index should use macros in:
|
||||
"include/dt-bindings/power/rk3288-power.h" - for rk3288 type power domain.
|
||||
"include/dt-bindings/power/rk3368-power.h" - for rk3368 type power domain.
|
||||
"include/dt-bindings/power/rk3399-power.h" - for rk3399 type power domain.
|
||||
|
||||
Example of the node using power domain:
|
||||
|
||||
|
@ -65,3 +106,9 @@ Example of the node using power domain:
|
|||
power-domains = <&power RK3368_PD_GPU_1>;
|
||||
/* ... */
|
||||
};
|
||||
|
||||
node {
|
||||
/* ... */
|
||||
power-domains = <&power RK3399_PD_VOPB>;
|
||||
/* ... */
|
||||
};
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
NVIDIA Tegra xHCI controller
|
||||
============================
|
||||
|
||||
The Tegra xHCI controller supports both USB2 and USB3 interfaces exposed by
|
||||
the Tegra XUSB pad controller.
|
||||
|
||||
Required properties:
|
||||
--------------------
|
||||
- compatible: Must be:
|
||||
- Tegra124: "nvidia,tegra124-xusb"
|
||||
- Tegra132: "nvidia,tegra132-xusb", "nvidia,tegra124-xusb"
|
||||
- Tegra210: "nvidia,tegra210-xusb"
|
||||
- reg: Must contain the base and length of the xHCI host registers, XUSB FPCI
|
||||
registers and XUSB IPFS registers.
|
||||
- reg-names: Must contain the following entries:
|
||||
- "hcd"
|
||||
- "fpci"
|
||||
- "ipfs"
|
||||
- interrupts: Must contain the xHCI host interrupt and the mailbox interrupt.
|
||||
- clocks: Must contain an entry for each entry in clock-names.
|
||||
See ../clock/clock-bindings.txt for details.
|
||||
- clock-names: Must include the following entries:
|
||||
- xusb_host
|
||||
- xusb_host_src
|
||||
- xusb_falcon_src
|
||||
- xusb_ss
|
||||
- xusb_ss_src
|
||||
- xusb_ss_div2
|
||||
- xusb_hs_src
|
||||
- xusb_fs_src
|
||||
- pll_u_480m
|
||||
- clk_m
|
||||
- pll_e
|
||||
- resets: Must contain an entry for each entry in reset-names.
|
||||
See ../reset/reset.txt for details.
|
||||
- reset-names: Must include the following entries:
|
||||
- xusb_host
|
||||
- xusb_ss
|
||||
- xusb_src
|
||||
Note that xusb_src is the shared reset for xusb_{ss,hs,fs,falcon,host}_src.
|
||||
- nvidia,xusb-padctl: phandle to the XUSB pad controller that is used to
|
||||
configure the USB pads used by the XHCI controller
|
||||
|
||||
For Tegra124 and Tegra132:
|
||||
- avddio-pex-supply: PCIe/USB3 analog logic power supply. Must supply 1.05 V.
|
||||
- dvddio-pex-supply: PCIe/USB3 digital logic power supply. Must supply 1.05 V.
|
||||
- avdd-usb-supply: USB controller power supply. Must supply 3.3 V.
|
||||
- avdd-pll-utmip-supply: UTMI PLL power supply. Must supply 1.8 V.
|
||||
- avdd-pll-erefe-supply: PLLE reference PLL power supply. Must supply 1.05 V.
|
||||
- avdd-usb-ss-pll-supply: PCIe/USB3 PLL power supply. Must supply 1.05 V.
|
||||
- hvdd-usb-ss-supply: High-voltage PCIe/USB3 power supply. Must supply 3.3 V.
|
||||
- hvdd-usb-ss-pll-e-supply: High-voltage PLLE power supply. Must supply 3.3 V.
|
||||
|
||||
For Tegra210:
|
||||
- dvddio-pex-supply: PCIe/USB3 analog logic power supply. Must supply 1.05 V.
|
||||
- hvddio-pex-supply: High-voltage PCIe/USB3 power supply. Must supply 1.8 V.
|
||||
- avdd-usb-supply: USB controller power supply. Must supply 3.3 V.
|
||||
- avdd-pll-utmip-supply: UTMI PLL power supply. Must supply 1.8 V.
|
||||
- avdd-pll-uerefe-supply: PLLE reference PLL power supply. Must supply 1.05 V.
|
||||
- dvdd-pex-pll-supply: PCIe/USB3 PLL power supply. Must supply 1.05 V.
|
||||
- hvdd-pex-pll-e-supply: High-voltage PLLE power supply. Must supply 1.8 V.
|
||||
|
||||
Optional properties:
|
||||
--------------------
|
||||
- phys: Must contain an entry for each entry in phy-names.
|
||||
See ../phy/phy-bindings.txt for details.
|
||||
- phy-names: Should include an entry for each PHY used by the controller. The
|
||||
following PHYs are available:
|
||||
- Tegra124: usb2-0, usb2-1, usb2-2, hsic-0, hsic-1, usb3-0, usb3-1
|
||||
- Tegra132: usb2-0, usb2-1, usb2-2, hsic-0, hsic-1, usb3-0, usb3-1
|
||||
- Tegra210: usb2-0, usb2-1, usb2-2, usb2-3, hsic-0, usb3-0, usb3-1, usb3-2,
|
||||
usb3-3
|
||||
|
||||
Example:
|
||||
--------
|
||||
|
||||
usb@0,70090000 {
|
||||
compatible = "nvidia,tegra124-xusb";
|
||||
reg = <0x0 0x70090000 0x0 0x8000>,
|
||||
<0x0 0x70098000 0x0 0x1000>,
|
||||
<0x0 0x70099000 0x0 0x1000>;
|
||||
reg-names = "hcd", "fpci", "ipfs";
|
||||
|
||||
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
clocks = <&tegra_car TEGRA124_CLK_XUSB_HOST>,
|
||||
<&tegra_car TEGRA124_CLK_XUSB_HOST_SRC>,
|
||||
<&tegra_car TEGRA124_CLK_XUSB_FALCON_SRC>,
|
||||
<&tegra_car TEGRA124_CLK_XUSB_SS>,
|
||||
<&tegra_car TEGRA124_CLK_XUSB_SS_DIV2>,
|
||||
<&tegra_car TEGRA124_CLK_XUSB_SS_SRC>,
|
||||
<&tegra_car TEGRA124_CLK_XUSB_HS_SRC>,
|
||||
<&tegra_car TEGRA124_CLK_XUSB_FS_SRC>,
|
||||
<&tegra_car TEGRA124_CLK_PLL_U_480M>,
|
||||
<&tegra_car TEGRA124_CLK_CLK_M>,
|
||||
<&tegra_car TEGRA124_CLK_PLL_E>;
|
||||
clock-names = "xusb_host", "xusb_host_src", "xusb_falcon_src",
|
||||
"xusb_ss", "xusb_ss_div2", "xusb_ss_src",
|
||||
"xusb_hs_src", "xusb_fs_src", "pll_u_480m",
|
||||
"clk_m", "pll_e";
|
||||
resets = <&tegra_car 89>, <&tegra_car 156>, <&tegra_car 143>;
|
||||
reset-names = "xusb_host", "xusb_ss", "xusb_src";
|
||||
|
||||
nvidia,xusb-padctl = <&padctl>;
|
||||
|
||||
phys = <&{/padctl@0,7009f000/pads/usb2/usb2-1}>, /* mini-PCIe USB */
|
||||
<&{/padctl@0,7009f000/pads/usb2/usb2-2}>, /* USB A */
|
||||
<&{/padctl@0,7009f000/pads/pcie/pcie-0}>; /* USB A */
|
||||
phy-names = "utmi-1", "utmi-2", "usb3-0";
|
||||
|
||||
avddio-pex-supply = <&vdd_1v05_run>;
|
||||
dvddio-pex-supply = <&vdd_1v05_run>;
|
||||
avdd-usb-supply = <&vdd_3v3_lp0>;
|
||||
avdd-pll-utmip-supply = <&vddio_1v8>;
|
||||
avdd-pll-erefe-supply = <&avdd_1v05_run>;
|
||||
avdd-usb-ss-pll-supply = <&vdd_1v05_run>;
|
||||
hvdd-usb-ss-supply = <&vdd_3v3_lp0>;
|
||||
hvdd-usb-ss-pll-e-supply = <&vdd_3v3_lp0>;
|
||||
};
|
|
@ -31,16 +31,28 @@ should provide its own implementation of of_xlate. of_xlate is used only for
|
|||
dt boot case.
|
||||
|
||||
#define of_phy_provider_register(dev, xlate) \
|
||||
__of_phy_provider_register((dev), THIS_MODULE, (xlate))
|
||||
__of_phy_provider_register((dev), NULL, THIS_MODULE, (xlate))
|
||||
|
||||
#define devm_of_phy_provider_register(dev, xlate) \
|
||||
__devm_of_phy_provider_register((dev), THIS_MODULE, (xlate))
|
||||
__devm_of_phy_provider_register((dev), NULL, THIS_MODULE, (xlate))
|
||||
|
||||
of_phy_provider_register and devm_of_phy_provider_register macros can be used to
|
||||
register the phy_provider and it takes device and of_xlate as
|
||||
arguments. For the dt boot case, all PHY providers should use one of the above
|
||||
2 macros to register the PHY provider.
|
||||
|
||||
Often the device tree nodes associated with a PHY provider will contain a set
|
||||
of children that each represent a single PHY. Some bindings may nest the child
|
||||
nodes within extra levels for context and extensibility, in which case the low
|
||||
level of_phy_provider_register_full() and devm_of_phy_provider_register_full()
|
||||
macros can be used to override the node containing the children.
|
||||
|
||||
#define of_phy_provider_register_full(dev, children, xlate) \
|
||||
__of_phy_provider_register(dev, children, THIS_MODULE, xlate)
|
||||
|
||||
#define devm_of_phy_provider_register_full(dev, children, xlate) \
|
||||
__devm_of_phy_provider_register_full(dev, children, THIS_MODULE, xlate)
|
||||
|
||||
void devm_of_phy_provider_unregister(struct device *dev,
|
||||
struct phy_provider *phy_provider);
|
||||
void of_phy_provider_unregister(struct phy_provider *phy_provider);
|
||||
|
|
|
@ -1535,6 +1535,8 @@ Q: http://patchwork.kernel.org/project/linux-renesas-soc/list/
|
|||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git next
|
||||
S: Supported
|
||||
F: arch/arm64/boot/dts/renesas/
|
||||
F: drivers/soc/renesas/
|
||||
F: include/linux/soc/renesas/
|
||||
|
||||
ARM/RISCPC ARCHITECTURE
|
||||
M: Russell King <linux@armlinux.org.uk>
|
||||
|
@ -1584,6 +1586,7 @@ F: arch/arm/mach-s5p*/
|
|||
F: arch/arm/mach-exynos*/
|
||||
F: drivers/*/*s3c2410*
|
||||
F: drivers/*/*/*s3c2410*
|
||||
F: drivers/memory/samsung/*
|
||||
F: drivers/soc/samsung/*
|
||||
F: drivers/spi/spi-s3c*
|
||||
F: sound/soc/samsung/*
|
||||
|
@ -1648,6 +1651,8 @@ F: arch/arm/configs/shmobile_defconfig
|
|||
F: arch/arm/include/debug/renesas-scif.S
|
||||
F: arch/arm/mach-shmobile/
|
||||
F: drivers/sh/
|
||||
F: drivers/soc/renesas/
|
||||
F: include/linux/soc/renesas/
|
||||
|
||||
ARM/SOCFPGA ARCHITECTURE
|
||||
M: Dinh Nguyen <dinguyen@opensource.altera.com>
|
||||
|
|
|
@ -52,8 +52,9 @@ pic@14000000 {
|
|||
};
|
||||
|
||||
flash@24000000 {
|
||||
compatible = "cfi-flash";
|
||||
compatible = "arm,versatile-flash", "cfi-flash";
|
||||
reg = <0x24000000 0x02000000>;
|
||||
bank-width = <4>;
|
||||
};
|
||||
|
||||
fpga {
|
||||
|
|
|
@ -119,8 +119,9 @@ pclk: pclk@24M {
|
|||
};
|
||||
|
||||
flash@34000000 {
|
||||
compatible = "arm,versatile-flash";
|
||||
reg = <0x34000000 0x4000000>;
|
||||
/* 64 MiB NOR flash in non-interleaved chips */
|
||||
compatible = "arm,versatile-flash", "cfi-flash";
|
||||
reg = <0x34000000 0x04000000>;
|
||||
bank-width = <4>;
|
||||
};
|
||||
|
||||
|
|
|
@ -173,12 +173,12 @@ config ARCH_BRCMSTB
|
|||
select ARM_GIC
|
||||
select ARM_ERRATA_798181 if SMP
|
||||
select HAVE_ARM_ARCH_TIMER
|
||||
select BRCMSTB_GISB_ARB
|
||||
select BRCMSTB_L2_IRQ
|
||||
select BCM7120_L2_IRQ
|
||||
select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
|
||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||
select SOC_BRCMSTB
|
||||
select SOC_BUS
|
||||
help
|
||||
Say Y if you intend to run the kernel on a Broadcom ARM-based STB
|
||||
chipset.
|
||||
|
|
|
@ -18,6 +18,7 @@ menuconfig ARCH_EXYNOS
|
|||
select COMMON_CLK_SAMSUNG
|
||||
select EXYNOS_THERMAL
|
||||
select EXYNOS_PMU
|
||||
select EXYNOS_SROM
|
||||
select HAVE_ARM_SCU if SMP
|
||||
select HAVE_S3C2410_I2C if I2C
|
||||
select HAVE_S3C2410_WATCHDOG if WATCHDOG
|
||||
|
@ -26,11 +27,13 @@ menuconfig ARCH_EXYNOS
|
|||
select PINCTRL_EXYNOS
|
||||
select PM_GENERIC_DOMAINS if PM
|
||||
select S5P_DEV_MFC
|
||||
select SAMSUNG_MC
|
||||
select SOC_SAMSUNG
|
||||
select SRAM
|
||||
select THERMAL
|
||||
select THERMAL_OF
|
||||
select MFD_SYSCON
|
||||
select MEMORY
|
||||
select CLKSRC_EXYNOS_MCT
|
||||
select POWER_RESET
|
||||
select POWER_RESET_SYSCON
|
||||
|
|
|
@ -31,11 +31,6 @@
|
|||
|
||||
static struct map_desc exynos4_iodesc[] __initdata = {
|
||||
{
|
||||
.virtual = (unsigned long)S5P_VA_SROMC,
|
||||
.pfn = __phys_to_pfn(EXYNOS4_PA_SROMC),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)S5P_VA_CMU,
|
||||
.pfn = __phys_to_pfn(EXYNOS4_PA_CMU),
|
||||
.length = SZ_128K,
|
||||
|
@ -58,15 +53,6 @@ static struct map_desc exynos4_iodesc[] __initdata = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct map_desc exynos5_iodesc[] __initdata = {
|
||||
{
|
||||
.virtual = (unsigned long)S5P_VA_SROMC,
|
||||
.pfn = __phys_to_pfn(EXYNOS5_PA_SROMC),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device exynos_cpuidle = {
|
||||
.name = "exynos_cpuidle",
|
||||
#ifdef CONFIG_ARM_EXYNOS_CPUIDLE
|
||||
|
@ -138,9 +124,6 @@ static void __init exynos_map_io(void)
|
|||
{
|
||||
if (soc_is_exynos4())
|
||||
iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
|
||||
|
||||
if (soc_is_exynos5())
|
||||
iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
|
||||
}
|
||||
|
||||
static void __init exynos_init_io(void)
|
||||
|
|
|
@ -25,7 +25,4 @@
|
|||
|
||||
#define EXYNOS4_PA_COREPERI 0x10500000
|
||||
|
||||
#define EXYNOS4_PA_SROMC 0x12570000
|
||||
#define EXYNOS5_PA_SROMC 0x12250000
|
||||
|
||||
#endif /* __ASM_ARCH_MAP_H */
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* S5P SROMC register definitions
|
||||
*
|
||||
* 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 __PLAT_SAMSUNG_REGS_SROM_H
|
||||
#define __PLAT_SAMSUNG_REGS_SROM_H __FILE__
|
||||
|
||||
#include <mach/map.h>
|
||||
|
||||
#define S5P_SROMREG(x) (S5P_VA_SROMC + (x))
|
||||
|
||||
#define S5P_SROM_BW S5P_SROMREG(0x0)
|
||||
#define S5P_SROM_BC0 S5P_SROMREG(0x4)
|
||||
#define S5P_SROM_BC1 S5P_SROMREG(0x8)
|
||||
#define S5P_SROM_BC2 S5P_SROMREG(0xc)
|
||||
#define S5P_SROM_BC3 S5P_SROMREG(0x10)
|
||||
#define S5P_SROM_BC4 S5P_SROMREG(0x14)
|
||||
#define S5P_SROM_BC5 S5P_SROMREG(0x18)
|
||||
|
||||
/* one register BW holds 4 x 4-bit packed settings for NCS0 - NCS3 */
|
||||
|
||||
#define S5P_SROM_BW__DATAWIDTH__SHIFT 0
|
||||
#define S5P_SROM_BW__ADDRMODE__SHIFT 1
|
||||
#define S5P_SROM_BW__WAITENABLE__SHIFT 2
|
||||
#define S5P_SROM_BW__BYTEENABLE__SHIFT 3
|
||||
|
||||
#define S5P_SROM_BW__CS_MASK 0xf
|
||||
|
||||
#define S5P_SROM_BW__NCS0__SHIFT 0
|
||||
#define S5P_SROM_BW__NCS1__SHIFT 4
|
||||
#define S5P_SROM_BW__NCS2__SHIFT 8
|
||||
#define S5P_SROM_BW__NCS3__SHIFT 12
|
||||
#define S5P_SROM_BW__NCS4__SHIFT 16
|
||||
#define S5P_SROM_BW__NCS5__SHIFT 20
|
||||
|
||||
/* applies to same to BCS0 - BCS3 */
|
||||
|
||||
#define S5P_SROM_BCX__PMC__SHIFT 0
|
||||
#define S5P_SROM_BCX__TACP__SHIFT 4
|
||||
#define S5P_SROM_BCX__TCAH__SHIFT 8
|
||||
#define S5P_SROM_BCX__TCOH__SHIFT 12
|
||||
#define S5P_SROM_BCX__TACC__SHIFT 16
|
||||
#define S5P_SROM_BCX__TCOS__SHIFT 24
|
||||
#define S5P_SROM_BCX__TACS__SHIFT 28
|
||||
|
||||
#endif /* __PLAT_SAMSUNG_REGS_SROM_H */
|
|
@ -34,10 +34,11 @@
|
|||
#include <asm/smp_scu.h>
|
||||
#include <asm/suspend.h>
|
||||
|
||||
#include <mach/map.h>
|
||||
|
||||
#include <plat/pm-common.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "regs-srom.h"
|
||||
|
||||
#define REG_TABLE_END (-1U)
|
||||
|
||||
|
@ -53,15 +54,6 @@ struct exynos_wkup_irq {
|
|||
u32 mask;
|
||||
};
|
||||
|
||||
static struct sleep_save exynos_core_save[] = {
|
||||
/* SROM side */
|
||||
SAVE_ITEM(S5P_SROM_BW),
|
||||
SAVE_ITEM(S5P_SROM_BC0),
|
||||
SAVE_ITEM(S5P_SROM_BC1),
|
||||
SAVE_ITEM(S5P_SROM_BC2),
|
||||
SAVE_ITEM(S5P_SROM_BC3),
|
||||
};
|
||||
|
||||
struct exynos_pm_data {
|
||||
const struct exynos_wkup_irq *wkup_irq;
|
||||
unsigned int wake_disable_mask;
|
||||
|
@ -343,8 +335,6 @@ static void exynos_pm_prepare(void)
|
|||
/* Set wake-up mask registers */
|
||||
exynos_pm_set_wakeup_mask();
|
||||
|
||||
s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
|
||||
|
||||
exynos_pm_enter_sleep_mode();
|
||||
|
||||
/* ensure at least INFORM0 has the resume address */
|
||||
|
@ -375,8 +365,6 @@ static void exynos5420_pm_prepare(void)
|
|||
/* Set wake-up mask registers */
|
||||
exynos_pm_set_wakeup_mask();
|
||||
|
||||
s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
|
||||
|
||||
exynos_pmu_spare3 = pmu_raw_readl(S5P_PMU_SPARE3);
|
||||
/*
|
||||
* The cpu state needs to be saved and restored so that the
|
||||
|
@ -467,8 +455,6 @@ static void exynos_pm_resume(void)
|
|||
/* For release retention */
|
||||
exynos_pm_release_retention();
|
||||
|
||||
s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
|
||||
|
||||
if (cpuid == ARM_CPU_PART_CORTEX_A9)
|
||||
scu_enable(S5P_VA_SCU);
|
||||
|
||||
|
@ -535,8 +521,6 @@ static void exynos5420_pm_resume(void)
|
|||
|
||||
pmu_raw_writel(exynos_pmu_spare3, S5P_PMU_SPARE3);
|
||||
|
||||
s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
|
||||
|
||||
early_wakeup:
|
||||
|
||||
tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1);
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include <linux/amba/kmi.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irqchip.h>
|
||||
#include <linux/mtd/physmap.h>
|
||||
#include <linux/platform_data/clk-integrator.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_address.h>
|
||||
|
@ -146,65 +145,6 @@ static int __init irq_syscore_init(void)
|
|||
|
||||
device_initcall(irq_syscore_init);
|
||||
|
||||
/*
|
||||
* Flash handling.
|
||||
*/
|
||||
static int ap_flash_init(struct platform_device *dev)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP,
|
||||
ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET);
|
||||
|
||||
tmp = readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET) |
|
||||
INTEGRATOR_EBI_WRITE_ENABLE;
|
||||
writel(tmp, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET);
|
||||
|
||||
if (!(readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET)
|
||||
& INTEGRATOR_EBI_WRITE_ENABLE)) {
|
||||
writel(0xa05f, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET);
|
||||
writel(tmp, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET);
|
||||
writel(0, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ap_flash_exit(struct platform_device *dev)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP,
|
||||
ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET);
|
||||
|
||||
tmp = readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET) &
|
||||
~INTEGRATOR_EBI_WRITE_ENABLE;
|
||||
writel(tmp, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET);
|
||||
|
||||
if (readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET) &
|
||||
INTEGRATOR_EBI_WRITE_ENABLE) {
|
||||
writel(0xa05f, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET);
|
||||
writel(tmp, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET);
|
||||
writel(0, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET);
|
||||
}
|
||||
}
|
||||
|
||||
static void ap_flash_set_vpp(struct platform_device *pdev, int on)
|
||||
{
|
||||
if (on)
|
||||
writel(INTEGRATOR_SC_CTRL_nFLVPPEN,
|
||||
ap_syscon_base + INTEGRATOR_SC_CTRLS_OFFSET);
|
||||
else
|
||||
writel(INTEGRATOR_SC_CTRL_nFLVPPEN,
|
||||
ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET);
|
||||
}
|
||||
|
||||
static struct physmap_flash_data ap_flash_data = {
|
||||
.width = 4,
|
||||
.init = ap_flash_init,
|
||||
.exit = ap_flash_exit,
|
||||
.set_vpp = ap_flash_set_vpp,
|
||||
};
|
||||
|
||||
/*
|
||||
* For the PL010 found in the Integrator/AP some of the UART control is
|
||||
* implemented in the system controller and accessed using a callback
|
||||
|
@ -266,8 +206,6 @@ static struct of_dev_auxdata ap_auxdata_lookup[] __initdata = {
|
|||
"kmi0", NULL),
|
||||
OF_DEV_AUXDATA("arm,primecell", KMI1_BASE,
|
||||
"kmi1", NULL),
|
||||
OF_DEV_AUXDATA("cfi-flash", INTEGRATOR_FLASH_BASE,
|
||||
"physmap-flash", &ap_flash_data),
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/irqchip.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/mtd/physmap.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
@ -43,14 +42,8 @@
|
|||
/* Base address to the CP controller */
|
||||
static void __iomem *intcp_con_base;
|
||||
|
||||
#define INTCP_PA_FLASH_BASE 0x24000000
|
||||
|
||||
#define INTCP_PA_CLCD_BASE 0xc0000000
|
||||
|
||||
#define INTCP_FLASHPROG 0x04
|
||||
#define CINTEGRATOR_FLASHPROG_FLVPPEN (1 << 0)
|
||||
#define CINTEGRATOR_FLASHPROG_FLWREN (1 << 1)
|
||||
|
||||
/*
|
||||
* Logical Physical
|
||||
* f1000000 10000000 Core module registers
|
||||
|
@ -107,48 +100,6 @@ static void __init intcp_map_io(void)
|
|||
iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc));
|
||||
}
|
||||
|
||||
/*
|
||||
* Flash handling.
|
||||
*/
|
||||
static int intcp_flash_init(struct platform_device *dev)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(intcp_con_base + INTCP_FLASHPROG);
|
||||
val |= CINTEGRATOR_FLASHPROG_FLWREN;
|
||||
writel(val, intcp_con_base + INTCP_FLASHPROG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void intcp_flash_exit(struct platform_device *dev)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(intcp_con_base + INTCP_FLASHPROG);
|
||||
val &= ~(CINTEGRATOR_FLASHPROG_FLVPPEN|CINTEGRATOR_FLASHPROG_FLWREN);
|
||||
writel(val, intcp_con_base + INTCP_FLASHPROG);
|
||||
}
|
||||
|
||||
static void intcp_flash_set_vpp(struct platform_device *pdev, int on)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(intcp_con_base + INTCP_FLASHPROG);
|
||||
if (on)
|
||||
val |= CINTEGRATOR_FLASHPROG_FLVPPEN;
|
||||
else
|
||||
val &= ~CINTEGRATOR_FLASHPROG_FLVPPEN;
|
||||
writel(val, intcp_con_base + INTCP_FLASHPROG);
|
||||
}
|
||||
|
||||
static struct physmap_flash_data intcp_flash_data = {
|
||||
.width = 4,
|
||||
.init = intcp_flash_init,
|
||||
.exit = intcp_flash_exit,
|
||||
.set_vpp = intcp_flash_set_vpp,
|
||||
};
|
||||
|
||||
/*
|
||||
* It seems that the card insertion interrupt remains active after
|
||||
* we've acknowledged it. We therefore ignore the interrupt, and
|
||||
|
@ -260,8 +211,6 @@ static struct of_dev_auxdata intcp_auxdata_lookup[] __initdata = {
|
|||
"aaci", &mmc_data),
|
||||
OF_DEV_AUXDATA("arm,primecell", INTCP_PA_CLCD_BASE,
|
||||
"clcd", &clcd_data),
|
||||
OF_DEV_AUXDATA("cfi-flash", INTCP_PA_FLASH_BASE,
|
||||
"physmap-flash", &intcp_flash_data),
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ static void __init mediatek_timer_init(void)
|
|||
void __iomem *gpt_base;
|
||||
|
||||
if (of_machine_is_compatible("mediatek,mt6589") ||
|
||||
of_machine_is_compatible("mediatek,mt7623") ||
|
||||
of_machine_is_compatible("mediatek,mt8135") ||
|
||||
of_machine_is_compatible("mediatek,mt8127")) {
|
||||
/* turn on GPT6 which ungates arch timer clocks */
|
||||
|
|
|
@ -4,11 +4,6 @@ config ARCH_SHMOBILE
|
|||
config ARCH_SHMOBILE_MULTI
|
||||
bool
|
||||
|
||||
config PM_RCAR
|
||||
bool
|
||||
select PM
|
||||
select PM_GENERIC_DOMAINS
|
||||
|
||||
config PM_RMOBILE
|
||||
bool
|
||||
select PM
|
||||
|
@ -16,13 +11,15 @@ config PM_RMOBILE
|
|||
|
||||
config ARCH_RCAR_GEN1
|
||||
bool
|
||||
select PM_RCAR
|
||||
select PM
|
||||
select PM_GENERIC_DOMAINS
|
||||
select RENESAS_INTC_IRQPIN
|
||||
select SYS_SUPPORTS_SH_TMU
|
||||
|
||||
config ARCH_RCAR_GEN2
|
||||
bool
|
||||
select PM_RCAR
|
||||
select PM
|
||||
select PM_GENERIC_DOMAINS
|
||||
select RENESAS_IRQC
|
||||
select SYS_SUPPORTS_SH_CMT
|
||||
select PCI_DOMAINS if PCI
|
||||
|
|
|
@ -38,7 +38,6 @@ smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o headsmp-scu.o platsmp-scu.o
|
|||
|
||||
# PM objects
|
||||
obj-$(CONFIG_SUSPEND) += suspend.o
|
||||
obj-$(CONFIG_PM_RCAR) += pm-rcar.o
|
||||
obj-$(CONFIG_PM_RMOBILE) += pm-rmobile.o
|
||||
obj-$(CONFIG_ARCH_RCAR_GEN2) += pm-rcar-gen2.o
|
||||
|
||||
|
|
|
@ -9,9 +9,10 @@
|
|||
* for more details.
|
||||
*/
|
||||
|
||||
#include <linux/soc/renesas/rcar-sysc.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#include "pm-rcar.h"
|
||||
#include "r8a7779.h"
|
||||
|
||||
/* SYSC */
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/soc/renesas/rcar-sysc.h>
|
||||
#include <asm/io.h>
|
||||
#include "common.h"
|
||||
#include "pm-rcar.h"
|
||||
#include "rcar-gen2.h"
|
||||
|
||||
/* RST */
|
||||
|
|
|
@ -1,164 +0,0 @@
|
|||
/*
|
||||
* R-Car SYSC Power management support
|
||||
*
|
||||
* Copyright (C) 2014 Magnus Damm
|
||||
*
|
||||
* 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/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/io.h>
|
||||
#include "pm-rcar.h"
|
||||
|
||||
/* SYSC Common */
|
||||
#define SYSCSR 0x00 /* SYSC Status Register */
|
||||
#define SYSCISR 0x04 /* Interrupt Status Register */
|
||||
#define SYSCISCR 0x08 /* Interrupt Status Clear Register */
|
||||
#define SYSCIER 0x0c /* Interrupt Enable Register */
|
||||
#define SYSCIMR 0x10 /* Interrupt Mask Register */
|
||||
|
||||
/* SYSC Status Register */
|
||||
#define SYSCSR_PONENB 1 /* Ready for power resume requests */
|
||||
#define SYSCSR_POFFENB 0 /* Ready for power shutoff requests */
|
||||
|
||||
/*
|
||||
* Power Control Register Offsets inside the register block for each domain
|
||||
* Note: The "CR" registers for ARM cores exist on H1 only
|
||||
* Use WFI to power off, CPG/APMU to resume ARM cores on R-Car Gen2
|
||||
*/
|
||||
#define PWRSR_OFFS 0x00 /* Power Status Register */
|
||||
#define PWROFFCR_OFFS 0x04 /* Power Shutoff Control Register */
|
||||
#define PWROFFSR_OFFS 0x08 /* Power Shutoff Status Register */
|
||||
#define PWRONCR_OFFS 0x0c /* Power Resume Control Register */
|
||||
#define PWRONSR_OFFS 0x10 /* Power Resume Status Register */
|
||||
#define PWRER_OFFS 0x14 /* Power Shutoff/Resume Error */
|
||||
|
||||
|
||||
#define SYSCSR_RETRIES 100
|
||||
#define SYSCSR_DELAY_US 1
|
||||
|
||||
#define PWRER_RETRIES 100
|
||||
#define PWRER_DELAY_US 1
|
||||
|
||||
#define SYSCISR_RETRIES 1000
|
||||
#define SYSCISR_DELAY_US 1
|
||||
|
||||
static void __iomem *rcar_sysc_base;
|
||||
static DEFINE_SPINLOCK(rcar_sysc_lock); /* SMP CPUs + I/O devices */
|
||||
|
||||
static int rcar_sysc_pwr_on_off(const struct rcar_sysc_ch *sysc_ch, bool on)
|
||||
{
|
||||
unsigned int sr_bit, reg_offs;
|
||||
int k;
|
||||
|
||||
if (on) {
|
||||
sr_bit = SYSCSR_PONENB;
|
||||
reg_offs = PWRONCR_OFFS;
|
||||
} else {
|
||||
sr_bit = SYSCSR_POFFENB;
|
||||
reg_offs = PWROFFCR_OFFS;
|
||||
}
|
||||
|
||||
/* Wait until SYSC is ready to accept a power request */
|
||||
for (k = 0; k < SYSCSR_RETRIES; k++) {
|
||||
if (ioread32(rcar_sysc_base + SYSCSR) & BIT(sr_bit))
|
||||
break;
|
||||
udelay(SYSCSR_DELAY_US);
|
||||
}
|
||||
|
||||
if (k == SYSCSR_RETRIES)
|
||||
return -EAGAIN;
|
||||
|
||||
/* Submit power shutoff or power resume request */
|
||||
iowrite32(BIT(sysc_ch->chan_bit),
|
||||
rcar_sysc_base + sysc_ch->chan_offs + reg_offs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on)
|
||||
{
|
||||
unsigned int isr_mask = BIT(sysc_ch->isr_bit);
|
||||
unsigned int chan_mask = BIT(sysc_ch->chan_bit);
|
||||
unsigned int status;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
int k;
|
||||
|
||||
spin_lock_irqsave(&rcar_sysc_lock, flags);
|
||||
|
||||
iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
|
||||
|
||||
/* Submit power shutoff or resume request until it was accepted */
|
||||
for (k = 0; k < PWRER_RETRIES; k++) {
|
||||
ret = rcar_sysc_pwr_on_off(sysc_ch, on);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
status = ioread32(rcar_sysc_base +
|
||||
sysc_ch->chan_offs + PWRER_OFFS);
|
||||
if (!(status & chan_mask))
|
||||
break;
|
||||
|
||||
udelay(PWRER_DELAY_US);
|
||||
}
|
||||
|
||||
if (k == PWRER_RETRIES) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Wait until the power shutoff or resume request has completed * */
|
||||
for (k = 0; k < SYSCISR_RETRIES; k++) {
|
||||
if (ioread32(rcar_sysc_base + SYSCISR) & isr_mask)
|
||||
break;
|
||||
udelay(SYSCISR_DELAY_US);
|
||||
}
|
||||
|
||||
if (k == SYSCISR_RETRIES)
|
||||
ret = -EIO;
|
||||
|
||||
iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&rcar_sysc_lock, flags);
|
||||
|
||||
pr_debug("sysc power domain %d: %08x -> %d\n",
|
||||
sysc_ch->isr_bit, ioread32(rcar_sysc_base + SYSCISR), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch)
|
||||
{
|
||||
return rcar_sysc_power(sysc_ch, false);
|
||||
}
|
||||
|
||||
int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch)
|
||||
{
|
||||
return rcar_sysc_power(sysc_ch, true);
|
||||
}
|
||||
|
||||
bool rcar_sysc_power_is_off(const struct rcar_sysc_ch *sysc_ch)
|
||||
{
|
||||
unsigned int st;
|
||||
|
||||
st = ioread32(rcar_sysc_base + sysc_ch->chan_offs + PWRSR_OFFS);
|
||||
if (st & BIT(sysc_ch->chan_bit))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void __iomem *rcar_sysc_init(phys_addr_t base)
|
||||
{
|
||||
rcar_sysc_base = ioremap_nocache(base, PAGE_SIZE);
|
||||
if (!rcar_sysc_base)
|
||||
panic("unable to ioremap R-Car SYSC hardware block\n");
|
||||
|
||||
return rcar_sysc_base;
|
||||
}
|
|
@ -19,13 +19,13 @@
|
|||
#include <linux/spinlock.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/soc/renesas/rcar-sysc.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/smp_plat.h>
|
||||
#include <asm/smp_scu.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "pm-rcar.h"
|
||||
#include "r8a7779.h"
|
||||
|
||||
#define AVECR IOMEM(0xfe700040)
|
||||
|
|
|
@ -17,12 +17,12 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/soc/renesas/rcar-sysc.h>
|
||||
|
||||
#include <asm/smp_plat.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "platsmp-apmu.h"
|
||||
#include "pm-rcar.h"
|
||||
#include "rcar-gen2.h"
|
||||
#include "r8a7790.h"
|
||||
|
||||
|
|
|
@ -108,20 +108,10 @@ static int tegra30_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
|||
* be un-gated by un-toggling the power gate register
|
||||
* manually.
|
||||
*/
|
||||
if (!tegra_pmc_cpu_is_powered(cpu)) {
|
||||
ret = tegra_pmc_cpu_power_on(cpu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Wait for the power to come up. */
|
||||
timeout = jiffies + msecs_to_jiffies(100);
|
||||
while (!tegra_pmc_cpu_is_powered(cpu)) {
|
||||
if (time_after(jiffies, timeout))
|
||||
return -ETIMEDOUT;
|
||||
udelay(10);
|
||||
}
|
||||
}
|
||||
|
||||
remove_clamps:
|
||||
/* CPU partition is powered. Enable the CPU clock. */
|
||||
tegra_enable_cpu_clock(cpu);
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include <linux/amba/clcd.h>
|
||||
#include <linux/platform_data/video-clcd-versatile.h>
|
||||
#include <linux/amba/mmci.h>
|
||||
#include <linux/mtd/physmap.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
@ -41,12 +40,6 @@
|
|||
#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
|
||||
#define __io_address(n) ((void __iomem __force *)IO_ADDRESS(n))
|
||||
|
||||
/*
|
||||
* Memory definitions
|
||||
*/
|
||||
#define VERSATILE_FLASH_BASE 0x34000000
|
||||
#define VERSATILE_FLASH_SIZE SZ_64M
|
||||
|
||||
/*
|
||||
* ------------------------------------------------------------------------
|
||||
* Versatile Registers
|
||||
|
@ -54,14 +47,8 @@
|
|||
*/
|
||||
#define VERSATILE_SYS_PCICTL_OFFSET 0x44
|
||||
#define VERSATILE_SYS_MCI_OFFSET 0x48
|
||||
#define VERSATILE_SYS_FLASH_OFFSET 0x4C
|
||||
#define VERSATILE_SYS_CLCD_OFFSET 0x50
|
||||
|
||||
/*
|
||||
* VERSATILE_SYS_FLASH
|
||||
*/
|
||||
#define VERSATILE_FLASHPROG_FLVPPEN (1 << 0) /* Enable writing to flash */
|
||||
|
||||
/*
|
||||
* VERSATILE peripheral addresses
|
||||
*/
|
||||
|
@ -86,39 +73,6 @@
|
|||
static void __iomem *versatile_sys_base;
|
||||
static void __iomem *versatile_ib2_ctrl;
|
||||
|
||||
static void versatile_flash_set_vpp(struct platform_device *pdev, int on)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(versatile_sys_base + VERSATILE_SYS_FLASH_OFFSET);
|
||||
if (on)
|
||||
val |= VERSATILE_FLASHPROG_FLVPPEN;
|
||||
else
|
||||
val &= ~VERSATILE_FLASHPROG_FLVPPEN;
|
||||
writel(val, versatile_sys_base + VERSATILE_SYS_FLASH_OFFSET);
|
||||
}
|
||||
|
||||
static struct physmap_flash_data versatile_flash_data = {
|
||||
.width = 4,
|
||||
.set_vpp = versatile_flash_set_vpp,
|
||||
};
|
||||
|
||||
static struct resource versatile_flash_resource = {
|
||||
.start = VERSATILE_FLASH_BASE,
|
||||
.end = VERSATILE_FLASH_BASE + VERSATILE_FLASH_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
struct platform_device versatile_flash_device = {
|
||||
.name = "physmap-flash",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &versatile_flash_data,
|
||||
},
|
||||
.num_resources = 1,
|
||||
.resource = &versatile_flash_resource,
|
||||
};
|
||||
|
||||
unsigned int mmc_status(struct device *dev)
|
||||
{
|
||||
struct amba_device *adev = container_of(dev, struct amba_device, dev);
|
||||
|
@ -390,7 +344,6 @@ static void __init versatile_dt_init(void)
|
|||
|
||||
versatile_dt_pci_init();
|
||||
|
||||
platform_device_register(&versatile_flash_device);
|
||||
of_platform_populate(NULL, of_default_bus_match_table,
|
||||
versatile_auxdata_lookup, NULL);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
#define S5P_VA_DMC0 S3C_ADDR(0x02440000)
|
||||
#define S5P_VA_DMC1 S3C_ADDR(0x02480000)
|
||||
#define S5P_VA_SROMC S3C_ADDR(0x024C0000)
|
||||
|
||||
#define S5P_VA_COREPERI_BASE S3C_ADDR(0x02800000)
|
||||
#define S5P_VA_COREPERI(x) (S5P_VA_COREPERI_BASE + (x))
|
||||
|
|
|
@ -48,7 +48,7 @@ config ARM_CCI5xx_PMU
|
|||
If unsure, say Y
|
||||
|
||||
config ARM_CCN
|
||||
bool "ARM CCN driver support"
|
||||
tristate "ARM CCN driver support"
|
||||
depends on ARM || ARM64
|
||||
depends on PERF_EVENTS
|
||||
help
|
||||
|
@ -58,6 +58,7 @@ config ARM_CCN
|
|||
config BRCMSTB_GISB_ARB
|
||||
bool "Broadcom STB GISB bus arbiter"
|
||||
depends on ARM || MIPS
|
||||
default ARCH_BRCMSTB || BMIPS_GENERIC
|
||||
help
|
||||
Driver for the Broadcom Set Top Box System-on-a-chip internal bus
|
||||
arbiter. This driver provides timeout and target abort error handling
|
||||
|
@ -110,7 +111,7 @@ config OMAP_OCP2SCP
|
|||
config SIMPLE_PM_BUS
|
||||
bool "Simple Power-Managed Bus Driver"
|
||||
depends on OF && PM
|
||||
depends on ARCH_SHMOBILE || COMPILE_TEST
|
||||
depends on ARCH_RENESAS || COMPILE_TEST
|
||||
help
|
||||
Driver for transparent busses that don't need a real driver, but
|
||||
where the bus controller is part of a PM domain, or under the control
|
||||
|
|
|
@ -1189,7 +1189,7 @@ static int arm_ccn_pmu_cpu_notifier(struct notifier_block *nb,
|
|||
perf_pmu_migrate_context(&dt->pmu, cpu, target);
|
||||
cpumask_set_cpu(target, &dt->cpu);
|
||||
if (ccn->irq)
|
||||
WARN_ON(irq_set_affinity(ccn->irq, &dt->cpu) != 0);
|
||||
WARN_ON(irq_set_affinity_hint(ccn->irq, &dt->cpu) != 0);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1278,7 +1278,7 @@ static int arm_ccn_pmu_init(struct arm_ccn *ccn)
|
|||
|
||||
/* Also make sure that the overflow interrupt is handled by this CPU */
|
||||
if (ccn->irq) {
|
||||
err = irq_set_affinity(ccn->irq, &ccn->dt.cpu);
|
||||
err = irq_set_affinity_hint(ccn->irq, &ccn->dt.cpu);
|
||||
if (err) {
|
||||
dev_err(ccn->dev, "Failed to set interrupt affinity!\n");
|
||||
goto error_set_affinity;
|
||||
|
@ -1306,7 +1306,8 @@ static void arm_ccn_pmu_cleanup(struct arm_ccn *ccn)
|
|||
{
|
||||
int i;
|
||||
|
||||
irq_set_affinity(ccn->irq, cpu_possible_mask);
|
||||
if (ccn->irq)
|
||||
irq_set_affinity_hint(ccn->irq, NULL);
|
||||
unregister_cpu_notifier(&ccn->dt.cpu_nb);
|
||||
for (i = 0; i < ccn->num_xps; i++)
|
||||
writel(0, ccn->xp[i].base + CCN_XP_DT_CONTROL);
|
||||
|
|
|
@ -201,6 +201,7 @@ source "drivers/clk/bcm/Kconfig"
|
|||
source "drivers/clk/hisilicon/Kconfig"
|
||||
source "drivers/clk/mvebu/Kconfig"
|
||||
source "drivers/clk/qcom/Kconfig"
|
||||
source "drivers/clk/renesas/Kconfig"
|
||||
source "drivers/clk/samsung/Kconfig"
|
||||
source "drivers/clk/tegra/Kconfig"
|
||||
source "drivers/clk/ti/Kconfig"
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
config CLK_RENESAS_CPG_MSSR
|
||||
bool
|
||||
default y if ARCH_R8A7795
|
||||
|
||||
config CLK_RENESAS_CPG_MSTP
|
||||
bool
|
||||
default y if ARCH_R7S72100
|
||||
default y if ARCH_R8A73A4
|
||||
default y if ARCH_R8A7740
|
||||
default y if ARCH_R8A7778
|
||||
default y if ARCH_R8A7779
|
||||
default y if ARCH_R8A7790
|
||||
default y if ARCH_R8A7791
|
||||
default y if ARCH_R8A7793
|
||||
default y if ARCH_R8A7794
|
||||
default y if ARCH_SH73A0
|
|
@ -1,13 +1,15 @@
|
|||
obj-$(CONFIG_ARCH_EMEV2) += clk-emev2.o
|
||||
obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o clk-mstp.o
|
||||
obj-$(CONFIG_ARCH_R8A73A4) += clk-r8a73a4.o clk-mstp.o clk-div6.o
|
||||
obj-$(CONFIG_ARCH_R8A7740) += clk-r8a7740.o clk-mstp.o clk-div6.o
|
||||
obj-$(CONFIG_ARCH_R8A7778) += clk-r8a7778.o clk-mstp.o
|
||||
obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o clk-mstp.o
|
||||
obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o clk-mstp.o clk-div6.o
|
||||
obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o clk-mstp.o clk-div6.o
|
||||
obj-$(CONFIG_ARCH_R8A7793) += clk-rcar-gen2.o clk-mstp.o clk-div6.o
|
||||
obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o clk-mstp.o clk-div6.o
|
||||
obj-$(CONFIG_ARCH_R8A7795) += renesas-cpg-mssr.o \
|
||||
r8a7795-cpg-mssr.o clk-div6.o
|
||||
obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o clk-mstp.o clk-div6.o
|
||||
obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o
|
||||
obj-$(CONFIG_ARCH_R8A73A4) += clk-r8a73a4.o clk-div6.o
|
||||
obj-$(CONFIG_ARCH_R8A7740) += clk-r8a7740.o clk-div6.o
|
||||
obj-$(CONFIG_ARCH_R8A7778) += clk-r8a7778.o
|
||||
obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o
|
||||
obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o clk-div6.o
|
||||
obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o clk-div6.o
|
||||
obj-$(CONFIG_ARCH_R8A7793) += clk-rcar-gen2.o clk-div6.o
|
||||
obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o clk-div6.o
|
||||
obj-$(CONFIG_ARCH_R8A7795) += r8a7795-cpg-mssr.o
|
||||
obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o clk-div6.o
|
||||
|
||||
obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o clk-div6.o
|
||||
obj-$(CONFIG_CLK_RENESAS_CPG_MSTP) += clk-mstp.o
|
||||
|
|
|
@ -243,9 +243,7 @@ static void __init cpg_mstp_clocks_init(struct device_node *np)
|
|||
}
|
||||
CLK_OF_DECLARE(cpg_mstp_clks, "renesas,cpg-mstp-clocks", cpg_mstp_clocks_init);
|
||||
|
||||
|
||||
#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
|
||||
int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev)
|
||||
int cpg_mstp_attach_dev(struct generic_pm_domain *unused, struct device *dev)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
struct of_phandle_args clkspec;
|
||||
|
@ -297,7 +295,7 @@ int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev)
|
|||
return error;
|
||||
}
|
||||
|
||||
void cpg_mstp_detach_dev(struct generic_pm_domain *domain, struct device *dev)
|
||||
void cpg_mstp_detach_dev(struct generic_pm_domain *unused, struct device *dev)
|
||||
{
|
||||
if (!list_empty(&dev->power.subsys_data->clock_list))
|
||||
pm_clk_destroy(dev);
|
||||
|
@ -326,4 +324,3 @@ void __init cpg_mstp_add_clk_domain(struct device_node *np)
|
|||
|
||||
of_genpd_add_provider_simple(np, pd);
|
||||
}
|
||||
#endif /* !CONFIG_PM_GENERIC_DOMAINS_OF */
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
|
@ -26,6 +27,7 @@
|
|||
|
||||
#include "renesas-cpg-mssr.h"
|
||||
|
||||
#define CPG_RCKCR 0x240
|
||||
|
||||
enum clk_ids {
|
||||
/* Core Clock Outputs exported to DT */
|
||||
|
@ -50,6 +52,7 @@ enum clk_ids {
|
|||
CLK_S3,
|
||||
CLK_SDSRC,
|
||||
CLK_SSPSRC,
|
||||
CLK_RINT,
|
||||
|
||||
/* Module Clocks */
|
||||
MOD_CLK_BASE
|
||||
|
@ -63,8 +66,12 @@ enum r8a7795_clk_types {
|
|||
CLK_TYPE_GEN3_PLL3,
|
||||
CLK_TYPE_GEN3_PLL4,
|
||||
CLK_TYPE_GEN3_SD,
|
||||
CLK_TYPE_GEN3_R,
|
||||
};
|
||||
|
||||
#define DEF_GEN3_SD(_name, _id, _parent, _offset) \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset)
|
||||
|
||||
static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
|
||||
/* External Clock Inputs */
|
||||
DEF_INPUT("extal", CLK_EXTAL),
|
||||
|
@ -102,10 +109,10 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
|
|||
DEF_FIXED("s3d2", R8A7795_CLK_S3D2, CLK_S3, 2, 1),
|
||||
DEF_FIXED("s3d4", R8A7795_CLK_S3D4, CLK_S3, 4, 1),
|
||||
|
||||
DEF_SD("sd0", R8A7795_CLK_SD0, CLK_PLL1_DIV2, 0x0074),
|
||||
DEF_SD("sd1", R8A7795_CLK_SD1, CLK_PLL1_DIV2, 0x0078),
|
||||
DEF_SD("sd2", R8A7795_CLK_SD2, CLK_PLL1_DIV2, 0x0268),
|
||||
DEF_SD("sd3", R8A7795_CLK_SD3, CLK_PLL1_DIV2, 0x026c),
|
||||
DEF_GEN3_SD("sd0", R8A7795_CLK_SD0, CLK_PLL1_DIV2, 0x0074),
|
||||
DEF_GEN3_SD("sd1", R8A7795_CLK_SD1, CLK_PLL1_DIV2, 0x0078),
|
||||
DEF_GEN3_SD("sd2", R8A7795_CLK_SD2, CLK_PLL1_DIV2, 0x0268),
|
||||
DEF_GEN3_SD("sd3", R8A7795_CLK_SD3, CLK_PLL1_DIV2, 0x026c),
|
||||
|
||||
DEF_FIXED("cl", R8A7795_CLK_CL, CLK_PLL1_DIV2, 48, 1),
|
||||
DEF_FIXED("cp", R8A7795_CLK_CP, CLK_EXTAL, 2, 1),
|
||||
|
@ -113,6 +120,11 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
|
|||
DEF_DIV6P1("mso", R8A7795_CLK_MSO, CLK_PLL1_DIV4, 0x014),
|
||||
DEF_DIV6P1("hdmi", R8A7795_CLK_HDMI, CLK_PLL1_DIV2, 0x250),
|
||||
DEF_DIV6P1("canfd", R8A7795_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
|
||||
|
||||
DEF_DIV6_RO("osc", R8A7795_CLK_OSC, CLK_EXTAL, CPG_RCKCR, 8),
|
||||
DEF_DIV6_RO("r_int", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32),
|
||||
|
||||
DEF_BASE("r", R8A7795_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT),
|
||||
};
|
||||
|
||||
static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
|
||||
|
@ -139,6 +151,7 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
|
|||
DEF_MOD("usb3-if0", 328, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("usb-dmac0", 330, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("usb-dmac1", 331, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("rwdt0", 402, R8A7795_CLK_R),
|
||||
DEF_MOD("intc-ex", 407, R8A7795_CLK_CP),
|
||||
DEF_MOD("intc-ap", 408, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("audmac0", 502, R8A7795_CLK_S3D4),
|
||||
|
@ -148,6 +161,7 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
|
|||
DEF_MOD("hscif2", 518, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("hscif1", 519, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("hscif0", 520, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("pwm", 523, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("fcpvd3", 600, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("fcpvd2", 601, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("fcpvd1", 602, R8A7795_CLK_S2D1),
|
||||
|
@ -578,6 +592,18 @@ struct clk * __init r8a7795_cpg_clk_register(struct device *dev,
|
|||
case CLK_TYPE_GEN3_SD:
|
||||
return cpg_sd_clk_register(core, base, __clk_get_name(parent));
|
||||
|
||||
case CLK_TYPE_GEN3_R:
|
||||
/* RINT is default. Only if EXTALR is populated, we switch to it */
|
||||
value = readl(base + CPG_RCKCR) & 0x3f;
|
||||
|
||||
if (clk_get_rate(clks[CLK_EXTALR])) {
|
||||
parent = clks[CLK_EXTALR];
|
||||
value |= BIT(15);
|
||||
}
|
||||
|
||||
writel(value, base + CPG_RCKCR);
|
||||
break;
|
||||
|
||||
default:
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clk/renesas.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
|
@ -253,7 +254,7 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
|
|||
{
|
||||
struct clk *clk = NULL, *parent;
|
||||
struct device *dev = priv->dev;
|
||||
unsigned int id = core->id;
|
||||
unsigned int id = core->id, div = core->div;
|
||||
const char *parent_name;
|
||||
|
||||
WARN_DEBUG(id >= priv->num_core_clks);
|
||||
|
@ -266,6 +267,7 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
|
|||
|
||||
case CLK_TYPE_FF:
|
||||
case CLK_TYPE_DIV6P1:
|
||||
case CLK_TYPE_DIV6_RO:
|
||||
WARN_DEBUG(core->parent >= priv->num_core_clks);
|
||||
parent = priv->clks[core->parent];
|
||||
if (IS_ERR(parent)) {
|
||||
|
@ -274,13 +276,18 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
|
|||
}
|
||||
|
||||
parent_name = __clk_get_name(parent);
|
||||
if (core->type == CLK_TYPE_FF) {
|
||||
clk = clk_register_fixed_factor(NULL, core->name,
|
||||
parent_name, 0,
|
||||
core->mult, core->div);
|
||||
} else {
|
||||
|
||||
if (core->type == CLK_TYPE_DIV6_RO)
|
||||
/* Multiply with the DIV6 register value */
|
||||
div *= (readl(priv->base + core->offset) & 0x3f) + 1;
|
||||
|
||||
if (core->type == CLK_TYPE_DIV6P1) {
|
||||
clk = cpg_div6_register(core->name, 1, &parent_name,
|
||||
priv->base + core->offset);
|
||||
} else {
|
||||
clk = clk_register_fixed_factor(NULL, core->name,
|
||||
parent_name, 0,
|
||||
core->mult, div);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -375,8 +382,6 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod,
|
|||
kfree(clock);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
|
||||
struct cpg_mssr_clk_domain {
|
||||
struct generic_pm_domain genpd;
|
||||
struct device_node *np;
|
||||
|
@ -384,6 +389,8 @@ struct cpg_mssr_clk_domain {
|
|||
unsigned int core_pm_clks[0];
|
||||
};
|
||||
|
||||
static struct cpg_mssr_clk_domain *cpg_mssr_clk_domain;
|
||||
|
||||
static bool cpg_mssr_is_pm_clk(const struct of_phandle_args *clkspec,
|
||||
struct cpg_mssr_clk_domain *pd)
|
||||
{
|
||||
|
@ -407,17 +414,20 @@ static bool cpg_mssr_is_pm_clk(const struct of_phandle_args *clkspec,
|
|||
}
|
||||
}
|
||||
|
||||
static int cpg_mssr_attach_dev(struct generic_pm_domain *genpd,
|
||||
struct device *dev)
|
||||
int cpg_mssr_attach_dev(struct generic_pm_domain *unused, struct device *dev)
|
||||
{
|
||||
struct cpg_mssr_clk_domain *pd =
|
||||
container_of(genpd, struct cpg_mssr_clk_domain, genpd);
|
||||
struct cpg_mssr_clk_domain *pd = cpg_mssr_clk_domain;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct of_phandle_args clkspec;
|
||||
struct clk *clk;
|
||||
int i = 0;
|
||||
int error;
|
||||
|
||||
if (!pd) {
|
||||
dev_dbg(dev, "CPG/MSSR clock domain not yet available\n");
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i,
|
||||
&clkspec)) {
|
||||
if (cpg_mssr_is_pm_clk(&clkspec, pd))
|
||||
|
@ -457,8 +467,7 @@ static int cpg_mssr_attach_dev(struct generic_pm_domain *genpd,
|
|||
return error;
|
||||
}
|
||||
|
||||
static void cpg_mssr_detach_dev(struct generic_pm_domain *genpd,
|
||||
struct device *dev)
|
||||
void cpg_mssr_detach_dev(struct generic_pm_domain *unused, struct device *dev)
|
||||
{
|
||||
if (!list_empty(&dev->power.subsys_data->clock_list))
|
||||
pm_clk_destroy(dev);
|
||||
|
@ -487,19 +496,11 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev,
|
|||
pm_genpd_init(genpd, &simple_qos_governor, false);
|
||||
genpd->attach_dev = cpg_mssr_attach_dev;
|
||||
genpd->detach_dev = cpg_mssr_detach_dev;
|
||||
cpg_mssr_clk_domain = pd;
|
||||
|
||||
of_genpd_add_provider_simple(np, genpd);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline int cpg_mssr_add_clk_domain(struct device *dev,
|
||||
const unsigned int *core_pm_clks,
|
||||
unsigned int num_core_pm_clks)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* !CONFIG_PM_GENERIC_DOMAINS_OF */
|
||||
|
||||
|
||||
static const struct of_device_id cpg_mssr_match[] = {
|
||||
#ifdef CONFIG_ARCH_R8A7795
|
||||
|
|
|
@ -37,6 +37,7 @@ enum clk_types {
|
|||
CLK_TYPE_IN, /* External Clock Input */
|
||||
CLK_TYPE_FF, /* Fixed Factor Clock */
|
||||
CLK_TYPE_DIV6P1, /* DIV6 Clock with 1 parent clock */
|
||||
CLK_TYPE_DIV6_RO, /* DIV6 Clock read only with extra divisor */
|
||||
|
||||
/* Custom definitions start here */
|
||||
CLK_TYPE_CUSTOM,
|
||||
|
@ -53,9 +54,8 @@ enum clk_types {
|
|||
DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult)
|
||||
#define DEF_DIV6P1(_name, _id, _parent, _offset) \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_DIV6P1, _parent, .offset = _offset)
|
||||
#define DEF_SD(_name, _id, _parent, _offset) \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset)
|
||||
|
||||
#define DEF_DIV6_RO(_name, _id, _parent, _offset, _div) \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_DIV6_RO, _parent, .offset = _offset, .div = _div, .mult = 1)
|
||||
|
||||
/*
|
||||
* Definitions of Module Clocks
|
||||
|
|
|
@ -175,6 +175,19 @@
|
|||
#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14)
|
||||
#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12)
|
||||
|
||||
#define SATA_PLL_CFG0 0x490
|
||||
#define SATA_PLL_CFG0_PADPLL_RESET_SWCTL BIT(0)
|
||||
#define SATA_PLL_CFG0_PADPLL_USE_LOCKDET BIT(2)
|
||||
#define SATA_PLL_CFG0_PADPLL_SLEEP_IDDQ BIT(13)
|
||||
#define SATA_PLL_CFG0_SEQ_ENABLE BIT(24)
|
||||
|
||||
#define XUSBIO_PLL_CFG0 0x51c
|
||||
#define XUSBIO_PLL_CFG0_PADPLL_RESET_SWCTL BIT(0)
|
||||
#define XUSBIO_PLL_CFG0_CLK_ENABLE_SWCTL BIT(2)
|
||||
#define XUSBIO_PLL_CFG0_PADPLL_USE_LOCKDET BIT(6)
|
||||
#define XUSBIO_PLL_CFG0_PADPLL_SLEEP_IDDQ BIT(13)
|
||||
#define XUSBIO_PLL_CFG0_SEQ_ENABLE BIT(24)
|
||||
|
||||
#define UTMIPLL_HW_PWRDN_CFG0 0x52c
|
||||
#define UTMIPLL_HW_PWRDN_CFG0_UTMIPLL_LOCK BIT(31)
|
||||
#define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE BIT(25)
|
||||
|
@ -416,6 +429,51 @@ static const char *mux_pllmcp_clkm[] = {
|
|||
#define PLLU_MISC0_WRITE_MASK 0xbfffffff
|
||||
#define PLLU_MISC1_WRITE_MASK 0x00000007
|
||||
|
||||
void tegra210_xusb_pll_hw_control_enable(void)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl_relaxed(clk_base + XUSBIO_PLL_CFG0);
|
||||
val &= ~(XUSBIO_PLL_CFG0_CLK_ENABLE_SWCTL |
|
||||
XUSBIO_PLL_CFG0_PADPLL_RESET_SWCTL);
|
||||
val |= XUSBIO_PLL_CFG0_PADPLL_USE_LOCKDET |
|
||||
XUSBIO_PLL_CFG0_PADPLL_SLEEP_IDDQ;
|
||||
writel_relaxed(val, clk_base + XUSBIO_PLL_CFG0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra210_xusb_pll_hw_control_enable);
|
||||
|
||||
void tegra210_xusb_pll_hw_sequence_start(void)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl_relaxed(clk_base + XUSBIO_PLL_CFG0);
|
||||
val |= XUSBIO_PLL_CFG0_SEQ_ENABLE;
|
||||
writel_relaxed(val, clk_base + XUSBIO_PLL_CFG0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra210_xusb_pll_hw_sequence_start);
|
||||
|
||||
void tegra210_sata_pll_hw_control_enable(void)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl_relaxed(clk_base + SATA_PLL_CFG0);
|
||||
val &= ~SATA_PLL_CFG0_PADPLL_RESET_SWCTL;
|
||||
val |= SATA_PLL_CFG0_PADPLL_USE_LOCKDET |
|
||||
SATA_PLL_CFG0_PADPLL_SLEEP_IDDQ;
|
||||
writel_relaxed(val, clk_base + SATA_PLL_CFG0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra210_sata_pll_hw_control_enable);
|
||||
|
||||
void tegra210_sata_pll_hw_sequence_start(void)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl_relaxed(clk_base + SATA_PLL_CFG0);
|
||||
val |= SATA_PLL_CFG0_SEQ_ENABLE;
|
||||
writel_relaxed(val, clk_base + SATA_PLL_CFG0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra210_sata_pll_hw_sequence_start);
|
||||
|
||||
static inline void _pll_misc_chk_default(void __iomem *base,
|
||||
struct tegra_clk_pll_params *params,
|
||||
u8 misc_num, u32 default_val, u32 mask)
|
||||
|
|
|
@ -91,7 +91,7 @@ static inline bool psci_has_ext_power_state(void)
|
|||
PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK;
|
||||
}
|
||||
|
||||
bool psci_power_state_loses_context(u32 state)
|
||||
static inline bool psci_power_state_loses_context(u32 state)
|
||||
{
|
||||
const u32 mask = psci_has_ext_power_state() ?
|
||||
PSCI_1_0_EXT_POWER_STATE_TYPE_MASK :
|
||||
|
@ -100,7 +100,7 @@ bool psci_power_state_loses_context(u32 state)
|
|||
return state & mask;
|
||||
}
|
||||
|
||||
bool psci_power_state_is_valid(u32 state)
|
||||
static inline bool psci_power_state_is_valid(u32 state)
|
||||
{
|
||||
const u32 valid_mask = psci_has_ext_power_state() ?
|
||||
PSCI_1_0_EXT_POWER_STATE_MASK :
|
||||
|
@ -563,7 +563,7 @@ static int __init psci_0_1_init(struct device_node *np)
|
|||
return err;
|
||||
}
|
||||
|
||||
static const struct of_device_id const psci_of_match[] __initconst = {
|
||||
static const struct of_device_id psci_of_match[] __initconst = {
|
||||
{ .compatible = "arm,psci", .data = psci_0_1_init},
|
||||
{ .compatible = "arm,psci-0.2", .data = psci_0_2_init},
|
||||
{ .compatible = "arm,psci-1.0", .data = psci_0_2_init},
|
||||
|
|
|
@ -121,7 +121,7 @@ struct tegra_dc {
|
|||
spinlock_t lock;
|
||||
|
||||
struct drm_crtc base;
|
||||
int powergate;
|
||||
unsigned int powergate;
|
||||
int pipe;
|
||||
|
||||
struct clk *clk;
|
||||
|
|
|
@ -122,6 +122,7 @@ config MTK_SMI
|
|||
mainly help enable/disable iommu and control the power domain and
|
||||
clocks for each local arbiter.
|
||||
|
||||
source "drivers/memory/samsung/Kconfig"
|
||||
source "drivers/memory/tegra/Kconfig"
|
||||
|
||||
endif
|
||||
|
|
|
@ -17,4 +17,5 @@ obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o
|
|||
obj-$(CONFIG_JZ4780_NEMC) += jz4780-nemc.o
|
||||
obj-$(CONFIG_MTK_SMI) += mtk-smi.o
|
||||
|
||||
obj-$(CONFIG_SAMSUNG_MC) += samsung/
|
||||
obj-$(CONFIG_TEGRA_MC) += tegra/
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
config SAMSUNG_MC
|
||||
bool "Samsung Exynos Memory Controller support" if COMPILE_TEST
|
||||
help
|
||||
Support for the Memory Controller (MC) devices found on
|
||||
Samsung Exynos SoCs.
|
||||
|
||||
if SAMSUNG_MC
|
||||
|
||||
config EXYNOS_SROM
|
||||
bool "Exynos SROM controller driver" if COMPILE_TEST
|
||||
depends on (ARM && ARCH_EXYNOS) || (COMPILE_TEST && HAS_IOMEM)
|
||||
|
||||
endif
|
|
@ -0,0 +1 @@
|
|||
obj-$(CONFIG_EXYNOS_SROM) += exynos-srom.o
|
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com/
|
||||
*
|
||||
* EXYNOS - SROM Controller support
|
||||
* Author: Pankaj Dubey <pankaj.dubey@samsung.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.
|
||||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "exynos-srom.h"
|
||||
|
||||
static const unsigned long exynos_srom_offsets[] = {
|
||||
/* SROM side */
|
||||
EXYNOS_SROM_BW,
|
||||
EXYNOS_SROM_BC0,
|
||||
EXYNOS_SROM_BC1,
|
||||
EXYNOS_SROM_BC2,
|
||||
EXYNOS_SROM_BC3,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct exynos_srom_reg_dump: register dump of SROM Controller registers.
|
||||
* @offset: srom register offset from the controller base address.
|
||||
* @value: the value of register under the offset.
|
||||
*/
|
||||
struct exynos_srom_reg_dump {
|
||||
u32 offset;
|
||||
u32 value;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct exynos_srom: platform data for exynos srom controller driver.
|
||||
* @dev: platform device pointer
|
||||
* @reg_base: srom base address
|
||||
* @reg_offset: exynos_srom_reg_dump pointer to hold offset and its value.
|
||||
*/
|
||||
struct exynos_srom {
|
||||
struct device *dev;
|
||||
void __iomem *reg_base;
|
||||
struct exynos_srom_reg_dump *reg_offset;
|
||||
};
|
||||
|
||||
static struct exynos_srom_reg_dump *exynos_srom_alloc_reg_dump(
|
||||
const unsigned long *rdump,
|
||||
unsigned long nr_rdump)
|
||||
{
|
||||
struct exynos_srom_reg_dump *rd;
|
||||
unsigned int i;
|
||||
|
||||
rd = kcalloc(nr_rdump, sizeof(*rd), GFP_KERNEL);
|
||||
if (!rd)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < nr_rdump; ++i)
|
||||
rd[i].offset = rdump[i];
|
||||
|
||||
return rd;
|
||||
}
|
||||
|
||||
static int exynos_srom_configure_bank(struct exynos_srom *srom,
|
||||
struct device_node *np)
|
||||
{
|
||||
u32 bank, width, pmc = 0;
|
||||
u32 timing[6];
|
||||
u32 cs, bw;
|
||||
|
||||
if (of_property_read_u32(np, "reg", &bank))
|
||||
return -EINVAL;
|
||||
if (of_property_read_u32(np, "reg-io-width", &width))
|
||||
width = 1;
|
||||
if (of_property_read_bool(np, "samsung,srom-page-mode"))
|
||||
pmc = 1 << EXYNOS_SROM_BCX__PMC__SHIFT;
|
||||
if (of_property_read_u32_array(np, "samsung,srom-timing", timing,
|
||||
ARRAY_SIZE(timing)))
|
||||
return -EINVAL;
|
||||
|
||||
bank *= 4; /* Convert bank into shift/offset */
|
||||
|
||||
cs = 1 << EXYNOS_SROM_BW__BYTEENABLE__SHIFT;
|
||||
if (width == 2)
|
||||
cs |= 1 << EXYNOS_SROM_BW__DATAWIDTH__SHIFT;
|
||||
|
||||
bw = __raw_readl(srom->reg_base + EXYNOS_SROM_BW);
|
||||
bw = (bw & ~(EXYNOS_SROM_BW__CS_MASK << bank)) | (cs << bank);
|
||||
__raw_writel(bw, srom->reg_base + EXYNOS_SROM_BW);
|
||||
|
||||
__raw_writel(pmc | (timing[0] << EXYNOS_SROM_BCX__TACP__SHIFT) |
|
||||
(timing[1] << EXYNOS_SROM_BCX__TCAH__SHIFT) |
|
||||
(timing[2] << EXYNOS_SROM_BCX__TCOH__SHIFT) |
|
||||
(timing[3] << EXYNOS_SROM_BCX__TACC__SHIFT) |
|
||||
(timing[4] << EXYNOS_SROM_BCX__TCOS__SHIFT) |
|
||||
(timing[5] << EXYNOS_SROM_BCX__TACS__SHIFT),
|
||||
srom->reg_base + EXYNOS_SROM_BC0 + bank);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_srom_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np, *child;
|
||||
struct exynos_srom *srom;
|
||||
struct device *dev = &pdev->dev;
|
||||
bool bad_bank_config = false;
|
||||
|
||||
np = dev->of_node;
|
||||
if (!np) {
|
||||
dev_err(&pdev->dev, "could not find device info\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
srom = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct exynos_srom), GFP_KERNEL);
|
||||
if (!srom)
|
||||
return -ENOMEM;
|
||||
|
||||
srom->dev = dev;
|
||||
srom->reg_base = of_iomap(np, 0);
|
||||
if (!srom->reg_base) {
|
||||
dev_err(&pdev->dev, "iomap of exynos srom controller failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, srom);
|
||||
|
||||
srom->reg_offset = exynos_srom_alloc_reg_dump(exynos_srom_offsets,
|
||||
sizeof(exynos_srom_offsets));
|
||||
if (!srom->reg_offset) {
|
||||
iounmap(srom->reg_base);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for_each_child_of_node(np, child) {
|
||||
if (exynos_srom_configure_bank(srom, child)) {
|
||||
dev_err(dev,
|
||||
"Could not decode bank configuration for %s\n",
|
||||
child->name);
|
||||
bad_bank_config = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If any bank failed to configure, we still provide suspend/resume,
|
||||
* but do not probe child devices
|
||||
*/
|
||||
if (bad_bank_config)
|
||||
return 0;
|
||||
|
||||
return of_platform_populate(np, NULL, NULL, dev);
|
||||
}
|
||||
|
||||
static int exynos_srom_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct exynos_srom *srom = platform_get_drvdata(pdev);
|
||||
|
||||
kfree(srom->reg_offset);
|
||||
iounmap(srom->reg_base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static void exynos_srom_save(void __iomem *base,
|
||||
struct exynos_srom_reg_dump *rd,
|
||||
unsigned int num_regs)
|
||||
{
|
||||
for (; num_regs > 0; --num_regs, ++rd)
|
||||
rd->value = readl(base + rd->offset);
|
||||
}
|
||||
|
||||
static void exynos_srom_restore(void __iomem *base,
|
||||
const struct exynos_srom_reg_dump *rd,
|
||||
unsigned int num_regs)
|
||||
{
|
||||
for (; num_regs > 0; --num_regs, ++rd)
|
||||
writel(rd->value, base + rd->offset);
|
||||
}
|
||||
|
||||
static int exynos_srom_suspend(struct device *dev)
|
||||
{
|
||||
struct exynos_srom *srom = dev_get_drvdata(dev);
|
||||
|
||||
exynos_srom_save(srom->reg_base, srom->reg_offset,
|
||||
ARRAY_SIZE(exynos_srom_offsets));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_srom_resume(struct device *dev)
|
||||
{
|
||||
struct exynos_srom *srom = dev_get_drvdata(dev);
|
||||
|
||||
exynos_srom_restore(srom->reg_base, srom->reg_offset,
|
||||
ARRAY_SIZE(exynos_srom_offsets));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct of_device_id of_exynos_srom_ids[] = {
|
||||
{
|
||||
.compatible = "samsung,exynos4210-srom",
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_exynos_srom_ids);
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(exynos_srom_pm_ops, exynos_srom_suspend, exynos_srom_resume);
|
||||
|
||||
static struct platform_driver exynos_srom_driver = {
|
||||
.probe = exynos_srom_probe,
|
||||
.remove = exynos_srom_remove,
|
||||
.driver = {
|
||||
.name = "exynos-srom",
|
||||
.of_match_table = of_exynos_srom_ids,
|
||||
.pm = &exynos_srom_pm_ops,
|
||||
},
|
||||
};
|
||||
module_platform_driver(exynos_srom_driver);
|
||||
|
||||
MODULE_AUTHOR("Pankaj Dubey <pankaj.dubey@samsung.com>");
|
||||
MODULE_DESCRIPTION("Exynos SROM Controller Driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Exynos SROMC register definitions
|
||||
*
|
||||
* 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 __EXYNOS_SROM_H
|
||||
#define __EXYNOS_SROM_H __FILE__
|
||||
|
||||
#define EXYNOS_SROMREG(x) (x)
|
||||
|
||||
#define EXYNOS_SROM_BW EXYNOS_SROMREG(0x0)
|
||||
#define EXYNOS_SROM_BC0 EXYNOS_SROMREG(0x4)
|
||||
#define EXYNOS_SROM_BC1 EXYNOS_SROMREG(0x8)
|
||||
#define EXYNOS_SROM_BC2 EXYNOS_SROMREG(0xc)
|
||||
#define EXYNOS_SROM_BC3 EXYNOS_SROMREG(0x10)
|
||||
#define EXYNOS_SROM_BC4 EXYNOS_SROMREG(0x14)
|
||||
#define EXYNOS_SROM_BC5 EXYNOS_SROMREG(0x18)
|
||||
|
||||
/* one register BW holds 4 x 4-bit packed settings for NCS0 - NCS3 */
|
||||
|
||||
#define EXYNOS_SROM_BW__DATAWIDTH__SHIFT 0
|
||||
#define EXYNOS_SROM_BW__ADDRMODE__SHIFT 1
|
||||
#define EXYNOS_SROM_BW__WAITENABLE__SHIFT 2
|
||||
#define EXYNOS_SROM_BW__BYTEENABLE__SHIFT 3
|
||||
|
||||
#define EXYNOS_SROM_BW__CS_MASK 0xf
|
||||
|
||||
#define EXYNOS_SROM_BW__NCS0__SHIFT 0
|
||||
#define EXYNOS_SROM_BW__NCS1__SHIFT 4
|
||||
#define EXYNOS_SROM_BW__NCS2__SHIFT 8
|
||||
#define EXYNOS_SROM_BW__NCS3__SHIFT 12
|
||||
#define EXYNOS_SROM_BW__NCS4__SHIFT 16
|
||||
#define EXYNOS_SROM_BW__NCS5__SHIFT 20
|
||||
|
||||
/* applies to same to BCS0 - BCS3 */
|
||||
|
||||
#define EXYNOS_SROM_BCX__PMC__SHIFT 0
|
||||
#define EXYNOS_SROM_BCX__TACP__SHIFT 4
|
||||
#define EXYNOS_SROM_BCX__TCAH__SHIFT 8
|
||||
#define EXYNOS_SROM_BCX__TCOH__SHIFT 12
|
||||
#define EXYNOS_SROM_BCX__TACC__SHIFT 16
|
||||
#define EXYNOS_SROM_BCX__TCOS__SHIFT 24
|
||||
#define EXYNOS_SROM_BCX__TACS__SHIFT 28
|
||||
|
||||
#endif /* __EXYNOS_SROM_H */
|
|
@ -74,6 +74,16 @@ config MTD_PHYSMAP_OF
|
|||
physically into the CPU's memory. The mapping description here is
|
||||
taken from OF device tree.
|
||||
|
||||
config MTD_PHYSMAP_OF_VERSATILE
|
||||
bool "Support ARM Versatile physmap OF"
|
||||
depends on MTD_PHYSMAP_OF
|
||||
depends on MFD_SYSCON
|
||||
default y if (ARCH_INTEGRATOR || ARCH_VERSATILE || REALVIEW_DT)
|
||||
help
|
||||
This provides some extra DT physmap parsing for the ARM Versatile
|
||||
platforms, basically to add a VPP (write protection) callback so
|
||||
the flash can be taken out of write protection.
|
||||
|
||||
config MTD_PMC_MSP_EVM
|
||||
tristate "CFI Flash device mapped on PMC-Sierra MSP"
|
||||
depends on PMC_MSP && MTD_CFI
|
||||
|
|
|
@ -18,6 +18,9 @@ obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o
|
|||
obj-$(CONFIG_MTD_PXA2XX) += pxa2xx-flash.o
|
||||
obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
|
||||
obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of.o
|
||||
ifdef CONFIG_MTD_PHYSMAP_OF_VERSATILE
|
||||
obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of_versatile.o
|
||||
endif
|
||||
obj-$(CONFIG_MTD_PISMO) += pismo.o
|
||||
obj-$(CONFIG_MTD_PMC_MSP_EVM) += pmcmsp-flash.o
|
||||
obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/slab.h>
|
||||
#include "physmap_of_versatile.h"
|
||||
|
||||
struct of_flash_list {
|
||||
struct mtd_info *mtd;
|
||||
|
@ -240,6 +241,11 @@ static int of_flash_probe(struct platform_device *dev)
|
|||
info->list[i].map.size = res_size;
|
||||
info->list[i].map.bankwidth = be32_to_cpup(width);
|
||||
info->list[i].map.device_node = dp;
|
||||
err = of_flash_probe_versatile(dev, dp, &info->list[i].map);
|
||||
if (err) {
|
||||
dev_err(&dev->dev, "Can't probe Versatile VPP\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = -ENOMEM;
|
||||
info->list[i].map.virt = ioremap(info->list[i].map.phys,
|
||||
|
|
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
* Versatile OF physmap driver add-on
|
||||
*
|
||||
* Copyright (c) 2016, Linaro Limited
|
||||
* Author: Linus Walleij <linus.walleij@linaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
#include <linux/export.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/mtd/map.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/bitops.h>
|
||||
#include "physmap_of_versatile.h"
|
||||
|
||||
static struct regmap *syscon_regmap;
|
||||
|
||||
enum versatile_flashprot {
|
||||
INTEGRATOR_AP_FLASHPROT,
|
||||
INTEGRATOR_CP_FLASHPROT,
|
||||
VERSATILE_FLASHPROT,
|
||||
REALVIEW_FLASHPROT,
|
||||
};
|
||||
|
||||
static const struct of_device_id syscon_match[] = {
|
||||
{
|
||||
.compatible = "arm,integrator-ap-syscon",
|
||||
.data = (void *)INTEGRATOR_AP_FLASHPROT,
|
||||
},
|
||||
{
|
||||
.compatible = "arm,integrator-cp-syscon",
|
||||
.data = (void *)INTEGRATOR_CP_FLASHPROT,
|
||||
},
|
||||
{
|
||||
.compatible = "arm,core-module-versatile",
|
||||
.data = (void *)VERSATILE_FLASHPROT,
|
||||
},
|
||||
{
|
||||
.compatible = "arm,realview-eb-syscon",
|
||||
.data = (void *)REALVIEW_FLASHPROT,
|
||||
},
|
||||
{
|
||||
.compatible = "arm,realview-pb1176-syscon",
|
||||
.data = (void *)REALVIEW_FLASHPROT,
|
||||
},
|
||||
{
|
||||
.compatible = "arm,realview-pb11mp-syscon",
|
||||
.data = (void *)REALVIEW_FLASHPROT,
|
||||
},
|
||||
{
|
||||
.compatible = "arm,realview-pba8-syscon",
|
||||
.data = (void *)REALVIEW_FLASHPROT,
|
||||
},
|
||||
{
|
||||
.compatible = "arm,realview-pbx-syscon",
|
||||
.data = (void *)REALVIEW_FLASHPROT,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
/*
|
||||
* Flash protection handling for the Integrator/AP
|
||||
*/
|
||||
#define INTEGRATOR_SC_CTRLS_OFFSET 0x08
|
||||
#define INTEGRATOR_SC_CTRLC_OFFSET 0x0C
|
||||
#define INTEGRATOR_SC_CTRL_FLVPPEN BIT(1)
|
||||
#define INTEGRATOR_SC_CTRL_FLWP BIT(2)
|
||||
|
||||
#define INTEGRATOR_EBI_CSR1_OFFSET 0x04
|
||||
/* The manual says bit 2, the code says bit 3, trust the code */
|
||||
#define INTEGRATOR_EBI_WRITE_ENABLE BIT(3)
|
||||
#define INTEGRATOR_EBI_LOCK_OFFSET 0x20
|
||||
#define INTEGRATOR_EBI_LOCK_VAL 0xA05F
|
||||
|
||||
static const struct of_device_id ebi_match[] = {
|
||||
{ .compatible = "arm,external-bus-interface"},
|
||||
{ },
|
||||
};
|
||||
|
||||
static int ap_flash_init(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *ebi;
|
||||
static void __iomem *ebi_base;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
/* Look up the EBI */
|
||||
ebi = of_find_matching_node(NULL, ebi_match);
|
||||
if (!ebi) {
|
||||
return -ENODEV;
|
||||
}
|
||||
ebi_base = of_iomap(ebi, 0);
|
||||
if (!ebi_base)
|
||||
return -ENODEV;
|
||||
|
||||
/* Clear VPP and write protection bits */
|
||||
ret = regmap_write(syscon_regmap,
|
||||
INTEGRATOR_SC_CTRLC_OFFSET,
|
||||
INTEGRATOR_SC_CTRL_FLVPPEN | INTEGRATOR_SC_CTRL_FLWP);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "error clearing Integrator VPP/WP\n");
|
||||
|
||||
/* Unlock the EBI */
|
||||
writel(INTEGRATOR_EBI_LOCK_VAL, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET);
|
||||
|
||||
/* Enable write cycles on the EBI, CSR1 (flash) */
|
||||
val = readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET);
|
||||
val |= INTEGRATOR_EBI_WRITE_ENABLE;
|
||||
writel(val, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET);
|
||||
|
||||
/* Lock the EBI again */
|
||||
writel(0, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET);
|
||||
iounmap(ebi_base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ap_flash_set_vpp(struct map_info *map, int on)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (on) {
|
||||
ret = regmap_write(syscon_regmap,
|
||||
INTEGRATOR_SC_CTRLS_OFFSET,
|
||||
INTEGRATOR_SC_CTRL_FLVPPEN | INTEGRATOR_SC_CTRL_FLWP);
|
||||
if (ret)
|
||||
pr_err("error enabling AP VPP\n");
|
||||
} else {
|
||||
ret = regmap_write(syscon_regmap,
|
||||
INTEGRATOR_SC_CTRLC_OFFSET,
|
||||
INTEGRATOR_SC_CTRL_FLVPPEN | INTEGRATOR_SC_CTRL_FLWP);
|
||||
if (ret)
|
||||
pr_err("error disabling AP VPP\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Flash protection handling for the Integrator/CP
|
||||
*/
|
||||
|
||||
#define INTCP_FLASHPROG_OFFSET 0x04
|
||||
#define CINTEGRATOR_FLVPPEN BIT(0)
|
||||
#define CINTEGRATOR_FLWREN BIT(1)
|
||||
#define CINTEGRATOR_FLMASK BIT(0)|BIT(1)
|
||||
|
||||
static void cp_flash_set_vpp(struct map_info *map, int on)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (on) {
|
||||
ret = regmap_update_bits(syscon_regmap,
|
||||
INTCP_FLASHPROG_OFFSET,
|
||||
CINTEGRATOR_FLMASK,
|
||||
CINTEGRATOR_FLVPPEN | CINTEGRATOR_FLWREN);
|
||||
if (ret)
|
||||
pr_err("error setting CP VPP\n");
|
||||
} else {
|
||||
ret = regmap_update_bits(syscon_regmap,
|
||||
INTCP_FLASHPROG_OFFSET,
|
||||
CINTEGRATOR_FLMASK,
|
||||
0);
|
||||
if (ret)
|
||||
pr_err("error setting CP VPP\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Flash protection handling for the Versatiles and RealViews
|
||||
*/
|
||||
|
||||
#define VERSATILE_SYS_FLASH_OFFSET 0x4C
|
||||
|
||||
static void versatile_flash_set_vpp(struct map_info *map, int on)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(syscon_regmap, VERSATILE_SYS_FLASH_OFFSET,
|
||||
0x01, !!on);
|
||||
if (ret)
|
||||
pr_err("error setting Versatile VPP\n");
|
||||
}
|
||||
|
||||
int of_flash_probe_versatile(struct platform_device *pdev,
|
||||
struct device_node *np,
|
||||
struct map_info *map)
|
||||
{
|
||||
struct device_node *sysnp;
|
||||
const struct of_device_id *devid;
|
||||
struct regmap *rmap;
|
||||
static enum versatile_flashprot versatile_flashprot;
|
||||
int ret;
|
||||
|
||||
/* Not all flash chips use this protection line */
|
||||
if (!of_device_is_compatible(np, "arm,versatile-flash"))
|
||||
return 0;
|
||||
|
||||
/* For first chip probed, look up the syscon regmap */
|
||||
if (!syscon_regmap) {
|
||||
sysnp = of_find_matching_node_and_match(NULL,
|
||||
syscon_match,
|
||||
&devid);
|
||||
if (!sysnp)
|
||||
return -ENODEV;
|
||||
|
||||
versatile_flashprot = (enum versatile_flashprot)devid->data;
|
||||
rmap = syscon_node_to_regmap(sysnp);
|
||||
if (IS_ERR(rmap))
|
||||
return PTR_ERR(rmap);
|
||||
|
||||
syscon_regmap = rmap;
|
||||
}
|
||||
|
||||
switch (versatile_flashprot) {
|
||||
case INTEGRATOR_AP_FLASHPROT:
|
||||
ret = ap_flash_init(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
map->set_vpp = ap_flash_set_vpp;
|
||||
dev_info(&pdev->dev, "Integrator/AP flash protection\n");
|
||||
break;
|
||||
case INTEGRATOR_CP_FLASHPROT:
|
||||
map->set_vpp = cp_flash_set_vpp;
|
||||
dev_info(&pdev->dev, "Integrator/CP flash protection\n");
|
||||
break;
|
||||
case VERSATILE_FLASHPROT:
|
||||
case REALVIEW_FLASHPROT:
|
||||
map->set_vpp = versatile_flash_set_vpp;
|
||||
dev_info(&pdev->dev, "versatile/realview flash protection\n");
|
||||
break;
|
||||
default:
|
||||
dev_info(&pdev->dev, "device marked as Versatile flash "
|
||||
"but no system controller was found\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_flash_probe_versatile);
|
|
@ -0,0 +1,16 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/mtd/map.h>
|
||||
|
||||
#ifdef CONFIG_MTD_PHYSMAP_OF_VERSATILE
|
||||
int of_flash_probe_versatile(struct platform_device *pdev,
|
||||
struct device_node *np,
|
||||
struct map_info *map);
|
||||
#else
|
||||
static inline
|
||||
int of_flash_probe_versatile(struct platform_device *pdev,
|
||||
struct device_node *np,
|
||||
struct map_info *map)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
|
@ -295,6 +295,7 @@ struct tegra_pcie {
|
|||
struct reset_control *afi_rst;
|
||||
struct reset_control *pcie_xrst;
|
||||
|
||||
bool legacy_phy;
|
||||
struct phy *phy;
|
||||
|
||||
struct tegra_msi msi;
|
||||
|
@ -311,11 +312,14 @@ struct tegra_pcie {
|
|||
|
||||
struct tegra_pcie_port {
|
||||
struct tegra_pcie *pcie;
|
||||
struct device_node *np;
|
||||
struct list_head list;
|
||||
struct resource regs;
|
||||
void __iomem *base;
|
||||
unsigned int index;
|
||||
unsigned int lanes;
|
||||
|
||||
struct phy **phys;
|
||||
};
|
||||
|
||||
struct tegra_pcie_bus {
|
||||
|
@ -860,6 +864,128 @@ static int tegra_pcie_phy_enable(struct tegra_pcie *pcie)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_pcie_phy_disable(struct tegra_pcie *pcie)
|
||||
{
|
||||
const struct tegra_pcie_soc_data *soc = pcie->soc_data;
|
||||
u32 value;
|
||||
|
||||
/* disable TX/RX data */
|
||||
value = pads_readl(pcie, PADS_CTL);
|
||||
value &= ~(PADS_CTL_TX_DATA_EN_1L | PADS_CTL_RX_DATA_EN_1L);
|
||||
pads_writel(pcie, value, PADS_CTL);
|
||||
|
||||
/* override IDDQ */
|
||||
value = pads_readl(pcie, PADS_CTL);
|
||||
value |= PADS_CTL_IDDQ_1L;
|
||||
pads_writel(pcie, PADS_CTL, value);
|
||||
|
||||
/* reset PLL */
|
||||
value = pads_readl(pcie, soc->pads_pll_ctl);
|
||||
value &= ~PADS_PLL_CTL_RST_B4SM;
|
||||
pads_writel(pcie, value, soc->pads_pll_ctl);
|
||||
|
||||
usleep_range(20, 100);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_pcie_port_phy_power_on(struct tegra_pcie_port *port)
|
||||
{
|
||||
struct device *dev = port->pcie->dev;
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
for (i = 0; i < port->lanes; i++) {
|
||||
err = phy_power_on(port->phys[i]);
|
||||
if (err < 0) {
|
||||
dev_err(dev, "failed to power on PHY#%u: %d\n", i,
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_pcie_port_phy_power_off(struct tegra_pcie_port *port)
|
||||
{
|
||||
struct device *dev = port->pcie->dev;
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
for (i = 0; i < port->lanes; i++) {
|
||||
err = phy_power_off(port->phys[i]);
|
||||
if (err < 0) {
|
||||
dev_err(dev, "failed to power off PHY#%u: %d\n", i,
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_pcie_phy_power_on(struct tegra_pcie *pcie)
|
||||
{
|
||||
struct tegra_pcie_port *port;
|
||||
int err;
|
||||
|
||||
if (pcie->legacy_phy) {
|
||||
if (pcie->phy)
|
||||
err = phy_power_on(pcie->phy);
|
||||
else
|
||||
err = tegra_pcie_phy_enable(pcie);
|
||||
|
||||
if (err < 0)
|
||||
dev_err(pcie->dev, "failed to power on PHY: %d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
list_for_each_entry(port, &pcie->ports, list) {
|
||||
err = tegra_pcie_port_phy_power_on(port);
|
||||
if (err < 0) {
|
||||
dev_err(pcie->dev,
|
||||
"failed to power on PCIe port %u PHY: %d\n",
|
||||
port->index, err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_pcie_phy_power_off(struct tegra_pcie *pcie)
|
||||
{
|
||||
struct tegra_pcie_port *port;
|
||||
int err;
|
||||
|
||||
if (pcie->legacy_phy) {
|
||||
if (pcie->phy)
|
||||
err = phy_power_off(pcie->phy);
|
||||
else
|
||||
err = tegra_pcie_phy_disable(pcie);
|
||||
|
||||
if (err < 0)
|
||||
dev_err(pcie->dev, "failed to power off PHY: %d\n",
|
||||
err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
list_for_each_entry(port, &pcie->ports, list) {
|
||||
err = tegra_pcie_port_phy_power_off(port);
|
||||
if (err < 0) {
|
||||
dev_err(pcie->dev,
|
||||
"failed to power off PCIe port %u PHY: %d\n",
|
||||
port->index, err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
|
||||
{
|
||||
const struct tegra_pcie_soc_data *soc = pcie->soc_data;
|
||||
|
@ -899,13 +1025,9 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
|
|||
afi_writel(pcie, value, AFI_FUSE);
|
||||
}
|
||||
|
||||
if (!pcie->phy)
|
||||
err = tegra_pcie_phy_enable(pcie);
|
||||
else
|
||||
err = phy_power_on(pcie->phy);
|
||||
|
||||
err = tegra_pcie_phy_power_on(pcie);
|
||||
if (err < 0) {
|
||||
dev_err(pcie->dev, "failed to power on PHY: %d\n", err);
|
||||
dev_err(pcie->dev, "failed to power on PHY(s): %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -942,9 +1064,9 @@ static void tegra_pcie_power_off(struct tegra_pcie *pcie)
|
|||
|
||||
/* TODO: disable and unprepare clocks? */
|
||||
|
||||
err = phy_power_off(pcie->phy);
|
||||
err = tegra_pcie_phy_power_off(pcie);
|
||||
if (err < 0)
|
||||
dev_warn(pcie->dev, "failed to power off PHY: %d\n", err);
|
||||
dev_err(pcie->dev, "failed to power off PHY(s): %d\n", err);
|
||||
|
||||
reset_control_assert(pcie->pcie_xrst);
|
||||
reset_control_assert(pcie->afi_rst);
|
||||
|
@ -1049,6 +1171,100 @@ static int tegra_pcie_resets_get(struct tegra_pcie *pcie)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_pcie_phys_get_legacy(struct tegra_pcie *pcie)
|
||||
{
|
||||
int err;
|
||||
|
||||
pcie->phy = devm_phy_optional_get(pcie->dev, "pcie");
|
||||
if (IS_ERR(pcie->phy)) {
|
||||
err = PTR_ERR(pcie->phy);
|
||||
dev_err(pcie->dev, "failed to get PHY: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = phy_init(pcie->phy);
|
||||
if (err < 0) {
|
||||
dev_err(pcie->dev, "failed to initialize PHY: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
pcie->legacy_phy = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct phy *devm_of_phy_optional_get_index(struct device *dev,
|
||||
struct device_node *np,
|
||||
const char *consumer,
|
||||
unsigned int index)
|
||||
{
|
||||
struct phy *phy;
|
||||
char *name;
|
||||
|
||||
name = kasprintf(GFP_KERNEL, "%s-%u", consumer, index);
|
||||
if (!name)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
phy = devm_of_phy_get(dev, np, name);
|
||||
kfree(name);
|
||||
|
||||
if (IS_ERR(phy) && PTR_ERR(phy) == -ENODEV)
|
||||
phy = NULL;
|
||||
|
||||
return phy;
|
||||
}
|
||||
|
||||
static int tegra_pcie_port_get_phys(struct tegra_pcie_port *port)
|
||||
{
|
||||
struct device *dev = port->pcie->dev;
|
||||
struct phy *phy;
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
port->phys = devm_kcalloc(dev, sizeof(phy), port->lanes, GFP_KERNEL);
|
||||
if (!port->phys)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < port->lanes; i++) {
|
||||
phy = devm_of_phy_optional_get_index(dev, port->np, "pcie", i);
|
||||
if (IS_ERR(phy)) {
|
||||
dev_err(dev, "failed to get PHY#%u: %ld\n", i,
|
||||
PTR_ERR(phy));
|
||||
return PTR_ERR(phy);
|
||||
}
|
||||
|
||||
err = phy_init(phy);
|
||||
if (err < 0) {
|
||||
dev_err(dev, "failed to initialize PHY#%u: %d\n", i,
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
|
||||
port->phys[i] = phy;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_pcie_phys_get(struct tegra_pcie *pcie)
|
||||
{
|
||||
const struct tegra_pcie_soc_data *soc = pcie->soc_data;
|
||||
struct device_node *np = pcie->dev->of_node;
|
||||
struct tegra_pcie_port *port;
|
||||
int err;
|
||||
|
||||
if (!soc->has_gen2 || of_find_property(np, "phys", NULL) != NULL)
|
||||
return tegra_pcie_phys_get_legacy(pcie);
|
||||
|
||||
list_for_each_entry(port, &pcie->ports, list) {
|
||||
err = tegra_pcie_port_get_phys(port);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_pcie_get_resources(struct tegra_pcie *pcie)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(pcie->dev);
|
||||
|
@ -1067,16 +1283,9 @@ static int tegra_pcie_get_resources(struct tegra_pcie *pcie)
|
|||
return err;
|
||||
}
|
||||
|
||||
pcie->phy = devm_phy_optional_get(pcie->dev, "pcie");
|
||||
if (IS_ERR(pcie->phy)) {
|
||||
err = PTR_ERR(pcie->phy);
|
||||
dev_err(&pdev->dev, "failed to get PHY: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = phy_init(pcie->phy);
|
||||
err = tegra_pcie_phys_get(pcie);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to initialize PHY: %d\n", err);
|
||||
dev_err(&pdev->dev, "failed to get PHYs: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -1752,6 +1961,7 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
|
|||
rp->index = index;
|
||||
rp->lanes = value;
|
||||
rp->pcie = pcie;
|
||||
rp->np = port;
|
||||
|
||||
rp->base = devm_ioremap_resource(pcie->dev, &rp->regs);
|
||||
if (IS_ERR(rp->base))
|
||||
|
|
|
@ -421,4 +421,6 @@ config PHY_CYGNUS_PCIE
|
|||
Enable this to support the Broadcom Cygnus PCIe PHY.
|
||||
If unsure, say N.
|
||||
|
||||
source "drivers/phy/tegra/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -52,3 +52,5 @@ obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o
|
|||
obj-$(CONFIG_PHY_BRCMSTB_SATA) += phy-brcmstb-sata.o
|
||||
obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
|
||||
obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o
|
||||
|
||||
obj-$(CONFIG_ARCH_TEGRA) += tegra/
|
||||
|
|
|
@ -141,7 +141,7 @@ static struct phy_provider *of_phy_provider_lookup(struct device_node *node)
|
|||
if (phy_provider->dev->of_node == node)
|
||||
return phy_provider;
|
||||
|
||||
for_each_child_of_node(phy_provider->dev->of_node, child)
|
||||
for_each_child_of_node(phy_provider->children, child)
|
||||
if (child == node)
|
||||
return phy_provider;
|
||||
}
|
||||
|
@ -811,24 +811,59 @@ EXPORT_SYMBOL_GPL(devm_phy_destroy);
|
|||
/**
|
||||
* __of_phy_provider_register() - create/register phy provider with the framework
|
||||
* @dev: struct device of the phy provider
|
||||
* @children: device node containing children (if different from dev->of_node)
|
||||
* @owner: the module owner containing of_xlate
|
||||
* @of_xlate: function pointer to obtain phy instance from phy provider
|
||||
*
|
||||
* Creates struct phy_provider from dev and of_xlate function pointer.
|
||||
* This is used in the case of dt boot for finding the phy instance from
|
||||
* phy provider.
|
||||
*
|
||||
* If the PHY provider doesn't nest children directly but uses a separate
|
||||
* child node to contain the individual children, the @children parameter
|
||||
* can be used to override the default. If NULL, the default (dev->of_node)
|
||||
* will be used. If non-NULL, the device node must be a child (or further
|
||||
* descendant) of dev->of_node. Otherwise an ERR_PTR()-encoded -EINVAL
|
||||
* error code is returned.
|
||||
*/
|
||||
struct phy_provider *__of_phy_provider_register(struct device *dev,
|
||||
struct module *owner, struct phy * (*of_xlate)(struct device *dev,
|
||||
struct device_node *children, struct module *owner,
|
||||
struct phy * (*of_xlate)(struct device *dev,
|
||||
struct of_phandle_args *args))
|
||||
{
|
||||
struct phy_provider *phy_provider;
|
||||
|
||||
/*
|
||||
* If specified, the device node containing the children must itself
|
||||
* be the provider's device node or a child (or further descendant)
|
||||
* thereof.
|
||||
*/
|
||||
if (children) {
|
||||
struct device_node *parent = of_node_get(children), *next;
|
||||
|
||||
while (parent) {
|
||||
if (parent == dev->of_node)
|
||||
break;
|
||||
|
||||
next = of_get_parent(parent);
|
||||
of_node_put(parent);
|
||||
parent = next;
|
||||
}
|
||||
|
||||
if (!parent)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
of_node_put(parent);
|
||||
} else {
|
||||
children = dev->of_node;
|
||||
}
|
||||
|
||||
phy_provider = kzalloc(sizeof(*phy_provider), GFP_KERNEL);
|
||||
if (!phy_provider)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
phy_provider->dev = dev;
|
||||
phy_provider->children = of_node_get(children);
|
||||
phy_provider->owner = owner;
|
||||
phy_provider->of_xlate = of_xlate;
|
||||
|
||||
|
@ -854,7 +889,8 @@ EXPORT_SYMBOL_GPL(__of_phy_provider_register);
|
|||
* on the devres data, then, devres data is freed.
|
||||
*/
|
||||
struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
|
||||
struct module *owner, struct phy * (*of_xlate)(struct device *dev,
|
||||
struct device_node *children, struct module *owner,
|
||||
struct phy * (*of_xlate)(struct device *dev,
|
||||
struct of_phandle_args *args))
|
||||
{
|
||||
struct phy_provider **ptr, *phy_provider;
|
||||
|
@ -863,7 +899,8 @@ struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
|
|||
if (!ptr)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
phy_provider = __of_phy_provider_register(dev, owner, of_xlate);
|
||||
phy_provider = __of_phy_provider_register(dev, children, owner,
|
||||
of_xlate);
|
||||
if (!IS_ERR(phy_provider)) {
|
||||
*ptr = phy_provider;
|
||||
devres_add(dev, ptr);
|
||||
|
@ -888,6 +925,7 @@ void of_phy_provider_unregister(struct phy_provider *phy_provider)
|
|||
|
||||
mutex_lock(&phy_provider_mutex);
|
||||
list_del(&phy_provider->list);
|
||||
of_node_put(phy_provider->children);
|
||||
kfree(phy_provider);
|
||||
mutex_unlock(&phy_provider_mutex);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
config PHY_TEGRA_XUSB
|
||||
tristate "NVIDIA Tegra XUSB pad controller driver"
|
||||
depends on ARCH_TEGRA
|
||||
help
|
||||
Choose this option if you have an NVIDIA Tegra SoC.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will
|
||||
be called phy-tegra-xusb.
|
|
@ -0,0 +1,6 @@
|
|||
obj-$(CONFIG_PHY_TEGRA_XUSB) += phy-tegra-xusb.o
|
||||
|
||||
phy-tegra-xusb-y += xusb.o
|
||||
phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_124_SOC) += xusb-tegra124.o
|
||||
phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_132_SOC) += xusb-tegra124.o
|
||||
phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_210_SOC) += xusb-tegra210.o
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,421 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2015, Google Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __PHY_TEGRA_XUSB_H
|
||||
#define __PHY_TEGRA_XUSB_H
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
/* legacy entry points for backwards-compatibility */
|
||||
int tegra_xusb_padctl_legacy_probe(struct platform_device *pdev);
|
||||
int tegra_xusb_padctl_legacy_remove(struct platform_device *pdev);
|
||||
|
||||
struct phy;
|
||||
struct phy_provider;
|
||||
struct platform_device;
|
||||
struct regulator;
|
||||
|
||||
/*
|
||||
* lanes
|
||||
*/
|
||||
struct tegra_xusb_lane_soc {
|
||||
const char *name;
|
||||
|
||||
unsigned int offset;
|
||||
unsigned int shift;
|
||||
unsigned int mask;
|
||||
|
||||
const char * const *funcs;
|
||||
unsigned int num_funcs;
|
||||
};
|
||||
|
||||
struct tegra_xusb_lane {
|
||||
const struct tegra_xusb_lane_soc *soc;
|
||||
struct tegra_xusb_pad *pad;
|
||||
struct device_node *np;
|
||||
struct list_head list;
|
||||
unsigned int function;
|
||||
unsigned int index;
|
||||
};
|
||||
|
||||
int tegra_xusb_lane_parse_dt(struct tegra_xusb_lane *lane,
|
||||
struct device_node *np);
|
||||
|
||||
struct tegra_xusb_usb2_lane {
|
||||
struct tegra_xusb_lane base;
|
||||
|
||||
u32 hs_curr_level_offset;
|
||||
};
|
||||
|
||||
static inline struct tegra_xusb_usb2_lane *
|
||||
to_usb2_lane(struct tegra_xusb_lane *lane)
|
||||
{
|
||||
return container_of(lane, struct tegra_xusb_usb2_lane, base);
|
||||
}
|
||||
|
||||
struct tegra_xusb_ulpi_lane {
|
||||
struct tegra_xusb_lane base;
|
||||
};
|
||||
|
||||
static inline struct tegra_xusb_ulpi_lane *
|
||||
to_ulpi_lane(struct tegra_xusb_lane *lane)
|
||||
{
|
||||
return container_of(lane, struct tegra_xusb_ulpi_lane, base);
|
||||
}
|
||||
|
||||
struct tegra_xusb_hsic_lane {
|
||||
struct tegra_xusb_lane base;
|
||||
|
||||
u32 strobe_trim;
|
||||
u32 rx_strobe_trim;
|
||||
u32 rx_data_trim;
|
||||
u32 tx_rtune_n;
|
||||
u32 tx_rtune_p;
|
||||
u32 tx_rslew_n;
|
||||
u32 tx_rslew_p;
|
||||
bool auto_term;
|
||||
};
|
||||
|
||||
static inline struct tegra_xusb_hsic_lane *
|
||||
to_hsic_lane(struct tegra_xusb_lane *lane)
|
||||
{
|
||||
return container_of(lane, struct tegra_xusb_hsic_lane, base);
|
||||
}
|
||||
|
||||
struct tegra_xusb_pcie_lane {
|
||||
struct tegra_xusb_lane base;
|
||||
};
|
||||
|
||||
static inline struct tegra_xusb_pcie_lane *
|
||||
to_pcie_lane(struct tegra_xusb_lane *lane)
|
||||
{
|
||||
return container_of(lane, struct tegra_xusb_pcie_lane, base);
|
||||
}
|
||||
|
||||
struct tegra_xusb_sata_lane {
|
||||
struct tegra_xusb_lane base;
|
||||
};
|
||||
|
||||
static inline struct tegra_xusb_sata_lane *
|
||||
to_sata_lane(struct tegra_xusb_lane *lane)
|
||||
{
|
||||
return container_of(lane, struct tegra_xusb_sata_lane, base);
|
||||
}
|
||||
|
||||
struct tegra_xusb_lane_ops {
|
||||
struct tegra_xusb_lane *(*probe)(struct tegra_xusb_pad *pad,
|
||||
struct device_node *np,
|
||||
unsigned int index);
|
||||
void (*remove)(struct tegra_xusb_lane *lane);
|
||||
};
|
||||
|
||||
/*
|
||||
* pads
|
||||
*/
|
||||
struct tegra_xusb_pad_soc;
|
||||
struct tegra_xusb_padctl;
|
||||
|
||||
struct tegra_xusb_pad_ops {
|
||||
struct tegra_xusb_pad *(*probe)(struct tegra_xusb_padctl *padctl,
|
||||
const struct tegra_xusb_pad_soc *soc,
|
||||
struct device_node *np);
|
||||
void (*remove)(struct tegra_xusb_pad *pad);
|
||||
};
|
||||
|
||||
struct tegra_xusb_pad_soc {
|
||||
const char *name;
|
||||
|
||||
const struct tegra_xusb_lane_soc *lanes;
|
||||
unsigned int num_lanes;
|
||||
|
||||
const struct tegra_xusb_pad_ops *ops;
|
||||
};
|
||||
|
||||
struct tegra_xusb_pad {
|
||||
const struct tegra_xusb_pad_soc *soc;
|
||||
struct tegra_xusb_padctl *padctl;
|
||||
struct phy_provider *provider;
|
||||
struct phy **lanes;
|
||||
struct device dev;
|
||||
|
||||
const struct tegra_xusb_lane_ops *ops;
|
||||
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
static inline struct tegra_xusb_pad *to_tegra_xusb_pad(struct device *dev)
|
||||
{
|
||||
return container_of(dev, struct tegra_xusb_pad, dev);
|
||||
}
|
||||
|
||||
int tegra_xusb_pad_init(struct tegra_xusb_pad *pad,
|
||||
struct tegra_xusb_padctl *padctl,
|
||||
struct device_node *np);
|
||||
int tegra_xusb_pad_register(struct tegra_xusb_pad *pad,
|
||||
const struct phy_ops *ops);
|
||||
void tegra_xusb_pad_unregister(struct tegra_xusb_pad *pad);
|
||||
|
||||
struct tegra_xusb_usb2_pad {
|
||||
struct tegra_xusb_pad base;
|
||||
|
||||
struct clk *clk;
|
||||
unsigned int enable;
|
||||
struct mutex lock;
|
||||
};
|
||||
|
||||
static inline struct tegra_xusb_usb2_pad *
|
||||
to_usb2_pad(struct tegra_xusb_pad *pad)
|
||||
{
|
||||
return container_of(pad, struct tegra_xusb_usb2_pad, base);
|
||||
}
|
||||
|
||||
struct tegra_xusb_ulpi_pad {
|
||||
struct tegra_xusb_pad base;
|
||||
};
|
||||
|
||||
static inline struct tegra_xusb_ulpi_pad *
|
||||
to_ulpi_pad(struct tegra_xusb_pad *pad)
|
||||
{
|
||||
return container_of(pad, struct tegra_xusb_ulpi_pad, base);
|
||||
}
|
||||
|
||||
struct tegra_xusb_hsic_pad {
|
||||
struct tegra_xusb_pad base;
|
||||
|
||||
struct regulator *supply;
|
||||
struct clk *clk;
|
||||
};
|
||||
|
||||
static inline struct tegra_xusb_hsic_pad *
|
||||
to_hsic_pad(struct tegra_xusb_pad *pad)
|
||||
{
|
||||
return container_of(pad, struct tegra_xusb_hsic_pad, base);
|
||||
}
|
||||
|
||||
struct tegra_xusb_pcie_pad {
|
||||
struct tegra_xusb_pad base;
|
||||
|
||||
struct reset_control *rst;
|
||||
struct clk *pll;
|
||||
|
||||
unsigned int enable;
|
||||
};
|
||||
|
||||
static inline struct tegra_xusb_pcie_pad *
|
||||
to_pcie_pad(struct tegra_xusb_pad *pad)
|
||||
{
|
||||
return container_of(pad, struct tegra_xusb_pcie_pad, base);
|
||||
}
|
||||
|
||||
struct tegra_xusb_sata_pad {
|
||||
struct tegra_xusb_pad base;
|
||||
|
||||
struct reset_control *rst;
|
||||
struct clk *pll;
|
||||
|
||||
unsigned int enable;
|
||||
};
|
||||
|
||||
static inline struct tegra_xusb_sata_pad *
|
||||
to_sata_pad(struct tegra_xusb_pad *pad)
|
||||
{
|
||||
return container_of(pad, struct tegra_xusb_sata_pad, base);
|
||||
}
|
||||
|
||||
/*
|
||||
* ports
|
||||
*/
|
||||
struct tegra_xusb_port_ops;
|
||||
|
||||
struct tegra_xusb_port {
|
||||
struct tegra_xusb_padctl *padctl;
|
||||
struct tegra_xusb_lane *lane;
|
||||
unsigned int index;
|
||||
|
||||
struct list_head list;
|
||||
struct device dev;
|
||||
|
||||
const struct tegra_xusb_port_ops *ops;
|
||||
};
|
||||
|
||||
struct tegra_xusb_lane_map {
|
||||
unsigned int port;
|
||||
const char *type;
|
||||
unsigned int index;
|
||||
const char *func;
|
||||
};
|
||||
|
||||
struct tegra_xusb_lane *
|
||||
tegra_xusb_port_find_lane(struct tegra_xusb_port *port,
|
||||
const struct tegra_xusb_lane_map *map,
|
||||
const char *function);
|
||||
|
||||
struct tegra_xusb_port *
|
||||
tegra_xusb_find_port(struct tegra_xusb_padctl *padctl, const char *type,
|
||||
unsigned int index);
|
||||
|
||||
struct tegra_xusb_usb2_port {
|
||||
struct tegra_xusb_port base;
|
||||
|
||||
struct regulator *supply;
|
||||
bool internal;
|
||||
};
|
||||
|
||||
static inline struct tegra_xusb_usb2_port *
|
||||
to_usb2_port(struct tegra_xusb_port *port)
|
||||
{
|
||||
return container_of(port, struct tegra_xusb_usb2_port, base);
|
||||
}
|
||||
|
||||
struct tegra_xusb_usb2_port *
|
||||
tegra_xusb_find_usb2_port(struct tegra_xusb_padctl *padctl,
|
||||
unsigned int index);
|
||||
|
||||
struct tegra_xusb_ulpi_port {
|
||||
struct tegra_xusb_port base;
|
||||
|
||||
struct regulator *supply;
|
||||
bool internal;
|
||||
};
|
||||
|
||||
static inline struct tegra_xusb_ulpi_port *
|
||||
to_ulpi_port(struct tegra_xusb_port *port)
|
||||
{
|
||||
return container_of(port, struct tegra_xusb_ulpi_port, base);
|
||||
}
|
||||
|
||||
struct tegra_xusb_hsic_port {
|
||||
struct tegra_xusb_port base;
|
||||
};
|
||||
|
||||
static inline struct tegra_xusb_hsic_port *
|
||||
to_hsic_port(struct tegra_xusb_port *port)
|
||||
{
|
||||
return container_of(port, struct tegra_xusb_hsic_port, base);
|
||||
}
|
||||
|
||||
struct tegra_xusb_usb3_port {
|
||||
struct tegra_xusb_port base;
|
||||
struct regulator *supply;
|
||||
bool context_saved;
|
||||
unsigned int port;
|
||||
bool internal;
|
||||
|
||||
u32 tap1;
|
||||
u32 amp;
|
||||
u32 ctle_z;
|
||||
u32 ctle_g;
|
||||
};
|
||||
|
||||
static inline struct tegra_xusb_usb3_port *
|
||||
to_usb3_port(struct tegra_xusb_port *port)
|
||||
{
|
||||
return container_of(port, struct tegra_xusb_usb3_port, base);
|
||||
}
|
||||
|
||||
struct tegra_xusb_usb3_port *
|
||||
tegra_xusb_find_usb3_port(struct tegra_xusb_padctl *padctl,
|
||||
unsigned int index);
|
||||
|
||||
struct tegra_xusb_port_ops {
|
||||
int (*enable)(struct tegra_xusb_port *port);
|
||||
void (*disable)(struct tegra_xusb_port *port);
|
||||
struct tegra_xusb_lane *(*map)(struct tegra_xusb_port *port);
|
||||
};
|
||||
|
||||
/*
|
||||
* pad controller
|
||||
*/
|
||||
struct tegra_xusb_padctl_soc;
|
||||
|
||||
struct tegra_xusb_padctl_ops {
|
||||
struct tegra_xusb_padctl *
|
||||
(*probe)(struct device *dev,
|
||||
const struct tegra_xusb_padctl_soc *soc);
|
||||
void (*remove)(struct tegra_xusb_padctl *padctl);
|
||||
|
||||
int (*usb3_save_context)(struct tegra_xusb_padctl *padctl,
|
||||
unsigned int index);
|
||||
int (*hsic_set_idle)(struct tegra_xusb_padctl *padctl,
|
||||
unsigned int index, bool idle);
|
||||
int (*usb3_set_lfps_detect)(struct tegra_xusb_padctl *padctl,
|
||||
unsigned int index, bool enable);
|
||||
};
|
||||
|
||||
struct tegra_xusb_padctl_soc {
|
||||
const struct tegra_xusb_pad_soc * const *pads;
|
||||
unsigned int num_pads;
|
||||
|
||||
struct {
|
||||
struct {
|
||||
const struct tegra_xusb_port_ops *ops;
|
||||
unsigned int count;
|
||||
} usb2, ulpi, hsic, usb3;
|
||||
} ports;
|
||||
|
||||
const struct tegra_xusb_padctl_ops *ops;
|
||||
};
|
||||
|
||||
struct tegra_xusb_padctl {
|
||||
struct device *dev;
|
||||
void __iomem *regs;
|
||||
struct mutex lock;
|
||||
struct reset_control *rst;
|
||||
|
||||
const struct tegra_xusb_padctl_soc *soc;
|
||||
|
||||
struct tegra_xusb_pad *pcie;
|
||||
struct tegra_xusb_pad *sata;
|
||||
struct tegra_xusb_pad *ulpi;
|
||||
struct tegra_xusb_pad *usb2;
|
||||
struct tegra_xusb_pad *hsic;
|
||||
|
||||
struct list_head ports;
|
||||
struct list_head lanes;
|
||||
struct list_head pads;
|
||||
|
||||
unsigned int enable;
|
||||
|
||||
struct clk *clk;
|
||||
};
|
||||
|
||||
static inline void padctl_writel(struct tegra_xusb_padctl *padctl, u32 value,
|
||||
unsigned long offset)
|
||||
{
|
||||
dev_dbg(padctl->dev, "%08lx < %08x\n", offset, value);
|
||||
writel(value, padctl->regs + offset);
|
||||
}
|
||||
|
||||
static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl,
|
||||
unsigned long offset)
|
||||
{
|
||||
u32 value = readl(padctl->regs + offset);
|
||||
dev_dbg(padctl->dev, "%08lx > %08x\n", offset, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
struct tegra_xusb_lane *tegra_xusb_find_lane(struct tegra_xusb_padctl *padctl,
|
||||
const char *name,
|
||||
unsigned int index);
|
||||
|
||||
#if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC)
|
||||
extern const struct tegra_xusb_padctl_soc tegra124_xusb_padctl_soc;
|
||||
#endif
|
||||
#if defined(CONFIG_ARCH_TEGRA_210_SOC)
|
||||
extern const struct tegra_xusb_padctl_soc tegra210_xusb_padctl_soc;
|
||||
#endif
|
||||
|
||||
#endif /* __PHY_TEGRA_XUSB_H */
|
|
@ -873,7 +873,7 @@ static const struct of_device_id tegra_xusb_padctl_of_match[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_xusb_padctl_of_match);
|
||||
|
||||
static int tegra_xusb_padctl_probe(struct platform_device *pdev)
|
||||
int tegra_xusb_padctl_legacy_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tegra_xusb_padctl *padctl;
|
||||
const struct of_device_id *match;
|
||||
|
@ -955,8 +955,9 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev)
|
|||
reset_control_assert(padctl->rst);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra_xusb_padctl_legacy_probe);
|
||||
|
||||
static int tegra_xusb_padctl_remove(struct platform_device *pdev)
|
||||
int tegra_xusb_padctl_legacy_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tegra_xusb_padctl *padctl = platform_get_drvdata(pdev);
|
||||
int err;
|
||||
|
@ -969,17 +970,4 @@ static int tegra_xusb_padctl_remove(struct platform_device *pdev)
|
|||
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct platform_driver tegra_xusb_padctl_driver = {
|
||||
.driver = {
|
||||
.name = "tegra-xusb-padctl",
|
||||
.of_match_table = tegra_xusb_padctl_of_match,
|
||||
},
|
||||
.probe = tegra_xusb_padctl_probe,
|
||||
.remove = tegra_xusb_padctl_remove,
|
||||
};
|
||||
module_platform_driver(tegra_xusb_padctl_driver);
|
||||
|
||||
MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
|
||||
MODULE_DESCRIPTION("Tegra 124 XUSB Pad Control driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
EXPORT_SYMBOL_GPL(tegra_xusb_padctl_legacy_remove);
|
||||
|
|
|
@ -12,5 +12,8 @@ menuconfig RESET_CONTROLLER
|
|||
|
||||
If unsure, say no.
|
||||
|
||||
config RESET_OXNAS
|
||||
bool
|
||||
|
||||
source "drivers/reset/sti/Kconfig"
|
||||
source "drivers/reset/hisilicon/Kconfig"
|
||||
|
|
|
@ -8,3 +8,4 @@ obj-$(CONFIG_ARCH_STI) += sti/
|
|||
obj-$(CONFIG_ARCH_HISI) += hisilicon/
|
||||
obj-$(CONFIG_ARCH_ZYNQ) += reset-zynq.o
|
||||
obj-$(CONFIG_ATH79) += reset-ath79.o
|
||||
obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/export.h>
|
||||
|
@ -18,19 +19,27 @@
|
|||
#include <linux/reset-controller.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
static DEFINE_MUTEX(reset_controller_list_mutex);
|
||||
static DEFINE_MUTEX(reset_list_mutex);
|
||||
static LIST_HEAD(reset_controller_list);
|
||||
|
||||
/**
|
||||
* struct reset_control - a reset control
|
||||
* @rcdev: a pointer to the reset controller device
|
||||
* this reset control belongs to
|
||||
* @list: list entry for the rcdev's reset controller list
|
||||
* @id: ID of the reset controller in the reset
|
||||
* controller device
|
||||
* @refcnt: Number of gets of this reset_control
|
||||
* @shared: Is this a shared (1), or an exclusive (0) reset_control?
|
||||
* @deassert_cnt: Number of times this reset line has been deasserted
|
||||
*/
|
||||
struct reset_control {
|
||||
struct reset_controller_dev *rcdev;
|
||||
struct list_head list;
|
||||
unsigned int id;
|
||||
unsigned int refcnt;
|
||||
int shared;
|
||||
atomic_t deassert_count;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -62,9 +71,11 @@ int reset_controller_register(struct reset_controller_dev *rcdev)
|
|||
rcdev->of_xlate = of_reset_simple_xlate;
|
||||
}
|
||||
|
||||
mutex_lock(&reset_controller_list_mutex);
|
||||
INIT_LIST_HEAD(&rcdev->reset_control_head);
|
||||
|
||||
mutex_lock(&reset_list_mutex);
|
||||
list_add(&rcdev->list, &reset_controller_list);
|
||||
mutex_unlock(&reset_controller_list_mutex);
|
||||
mutex_unlock(&reset_list_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -76,18 +87,23 @@ EXPORT_SYMBOL_GPL(reset_controller_register);
|
|||
*/
|
||||
void reset_controller_unregister(struct reset_controller_dev *rcdev)
|
||||
{
|
||||
mutex_lock(&reset_controller_list_mutex);
|
||||
mutex_lock(&reset_list_mutex);
|
||||
list_del(&rcdev->list);
|
||||
mutex_unlock(&reset_controller_list_mutex);
|
||||
mutex_unlock(&reset_list_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reset_controller_unregister);
|
||||
|
||||
/**
|
||||
* reset_control_reset - reset the controlled device
|
||||
* @rstc: reset controller
|
||||
*
|
||||
* Calling this on a shared reset controller is an error.
|
||||
*/
|
||||
int reset_control_reset(struct reset_control *rstc)
|
||||
{
|
||||
if (WARN_ON(rstc->shared))
|
||||
return -EINVAL;
|
||||
|
||||
if (rstc->rcdev->ops->reset)
|
||||
return rstc->rcdev->ops->reset(rstc->rcdev, rstc->id);
|
||||
|
||||
|
@ -98,26 +114,48 @@ EXPORT_SYMBOL_GPL(reset_control_reset);
|
|||
/**
|
||||
* reset_control_assert - asserts the reset line
|
||||
* @rstc: reset controller
|
||||
*
|
||||
* Calling this on an exclusive reset controller guarantees that the reset
|
||||
* will be asserted. When called on a shared reset controller the line may
|
||||
* still be deasserted, as long as other users keep it so.
|
||||
*
|
||||
* For shared reset controls a driver cannot expect the hw's registers and
|
||||
* internal state to be reset, but must be prepared for this to happen.
|
||||
*/
|
||||
int reset_control_assert(struct reset_control *rstc)
|
||||
{
|
||||
if (rstc->rcdev->ops->assert)
|
||||
return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id);
|
||||
|
||||
if (!rstc->rcdev->ops->assert)
|
||||
return -ENOTSUPP;
|
||||
|
||||
if (rstc->shared) {
|
||||
if (WARN_ON(atomic_read(&rstc->deassert_count) == 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (atomic_dec_return(&rstc->deassert_count) != 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reset_control_assert);
|
||||
|
||||
/**
|
||||
* reset_control_deassert - deasserts the reset line
|
||||
* @rstc: reset controller
|
||||
*
|
||||
* After calling this function, the reset is guaranteed to be deasserted.
|
||||
*/
|
||||
int reset_control_deassert(struct reset_control *rstc)
|
||||
{
|
||||
if (rstc->rcdev->ops->deassert)
|
||||
return rstc->rcdev->ops->deassert(rstc->rcdev, rstc->id);
|
||||
|
||||
if (!rstc->rcdev->ops->deassert)
|
||||
return -ENOTSUPP;
|
||||
|
||||
if (rstc->shared) {
|
||||
if (atomic_inc_return(&rstc->deassert_count) != 1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rstc->rcdev->ops->deassert(rstc->rcdev, rstc->id);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reset_control_deassert);
|
||||
|
||||
|
@ -136,18 +174,54 @@ int reset_control_status(struct reset_control *rstc)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(reset_control_status);
|
||||
|
||||
/**
|
||||
* of_reset_control_get_by_index - Lookup and obtain a reference to a reset
|
||||
* controller by index.
|
||||
* @node: device to be reset by the controller
|
||||
* @index: index of the reset controller
|
||||
*
|
||||
* This is to be used to perform a list of resets for a device or power domain
|
||||
* in whatever order. Returns a struct reset_control or IS_ERR() condition
|
||||
* containing errno.
|
||||
*/
|
||||
struct reset_control *of_reset_control_get_by_index(struct device_node *node,
|
||||
int index)
|
||||
static struct reset_control *__reset_control_get(
|
||||
struct reset_controller_dev *rcdev,
|
||||
unsigned int index, int shared)
|
||||
{
|
||||
struct reset_control *rstc;
|
||||
|
||||
lockdep_assert_held(&reset_list_mutex);
|
||||
|
||||
list_for_each_entry(rstc, &rcdev->reset_control_head, list) {
|
||||
if (rstc->id == index) {
|
||||
if (WARN_ON(!rstc->shared || !shared))
|
||||
return ERR_PTR(-EBUSY);
|
||||
|
||||
rstc->refcnt++;
|
||||
return rstc;
|
||||
}
|
||||
}
|
||||
|
||||
rstc = kzalloc(sizeof(*rstc), GFP_KERNEL);
|
||||
if (!rstc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
try_module_get(rcdev->owner);
|
||||
|
||||
rstc->rcdev = rcdev;
|
||||
list_add(&rstc->list, &rcdev->reset_control_head);
|
||||
rstc->id = index;
|
||||
rstc->refcnt = 1;
|
||||
rstc->shared = shared;
|
||||
|
||||
return rstc;
|
||||
}
|
||||
|
||||
static void __reset_control_put(struct reset_control *rstc)
|
||||
{
|
||||
lockdep_assert_held(&reset_list_mutex);
|
||||
|
||||
if (--rstc->refcnt)
|
||||
return;
|
||||
|
||||
module_put(rstc->rcdev->owner);
|
||||
|
||||
list_del(&rstc->list);
|
||||
kfree(rstc);
|
||||
}
|
||||
|
||||
struct reset_control *__of_reset_control_get(struct device_node *node,
|
||||
const char *id, int index, int shared)
|
||||
{
|
||||
struct reset_control *rstc;
|
||||
struct reset_controller_dev *r, *rcdev;
|
||||
|
@ -155,12 +229,22 @@ struct reset_control *of_reset_control_get_by_index(struct device_node *node,
|
|||
int rstc_id;
|
||||
int ret;
|
||||
|
||||
if (!node)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (id) {
|
||||
index = of_property_match_string(node,
|
||||
"reset-names", id);
|
||||
if (index < 0)
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
||||
ret = of_parse_phandle_with_args(node, "resets", "#reset-cells",
|
||||
index, &args);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
mutex_lock(&reset_controller_list_mutex);
|
||||
mutex_lock(&reset_list_mutex);
|
||||
rcdev = NULL;
|
||||
list_for_each_entry(r, &reset_controller_list, list) {
|
||||
if (args.np == r->of_node) {
|
||||
|
@ -171,78 +255,29 @@ struct reset_control *of_reset_control_get_by_index(struct device_node *node,
|
|||
of_node_put(args.np);
|
||||
|
||||
if (!rcdev) {
|
||||
mutex_unlock(&reset_controller_list_mutex);
|
||||
mutex_unlock(&reset_list_mutex);
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
|
||||
if (WARN_ON(args.args_count != rcdev->of_reset_n_cells)) {
|
||||
mutex_unlock(&reset_controller_list_mutex);
|
||||
mutex_unlock(&reset_list_mutex);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
rstc_id = rcdev->of_xlate(rcdev, &args);
|
||||
if (rstc_id < 0) {
|
||||
mutex_unlock(&reset_controller_list_mutex);
|
||||
mutex_unlock(&reset_list_mutex);
|
||||
return ERR_PTR(rstc_id);
|
||||
}
|
||||
|
||||
try_module_get(rcdev->owner);
|
||||
mutex_unlock(&reset_controller_list_mutex);
|
||||
/* reset_list_mutex also protects the rcdev's reset_control list */
|
||||
rstc = __reset_control_get(rcdev, rstc_id, shared);
|
||||
|
||||
rstc = kzalloc(sizeof(*rstc), GFP_KERNEL);
|
||||
if (!rstc) {
|
||||
module_put(rcdev->owner);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
rstc->rcdev = rcdev;
|
||||
rstc->id = rstc_id;
|
||||
mutex_unlock(&reset_list_mutex);
|
||||
|
||||
return rstc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_reset_control_get_by_index);
|
||||
|
||||
/**
|
||||
* of_reset_control_get - Lookup and obtain a reference to a reset controller.
|
||||
* @node: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Returns a struct reset_control or IS_ERR() condition containing errno.
|
||||
*
|
||||
* Use of id names is optional.
|
||||
*/
|
||||
struct reset_control *of_reset_control_get(struct device_node *node,
|
||||
const char *id)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
if (id) {
|
||||
index = of_property_match_string(node,
|
||||
"reset-names", id);
|
||||
if (index < 0)
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
return of_reset_control_get_by_index(node, index);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_reset_control_get);
|
||||
|
||||
/**
|
||||
* reset_control_get - Lookup and obtain a reference to a reset controller.
|
||||
* @dev: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Returns a struct reset_control or IS_ERR() condition containing errno.
|
||||
*
|
||||
* Use of id names is optional.
|
||||
*/
|
||||
struct reset_control *reset_control_get(struct device *dev, const char *id)
|
||||
{
|
||||
if (!dev)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return of_reset_control_get(dev->of_node, id);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reset_control_get);
|
||||
EXPORT_SYMBOL_GPL(__of_reset_control_get);
|
||||
|
||||
/**
|
||||
* reset_control_put - free the reset controller
|
||||
|
@ -254,8 +289,9 @@ void reset_control_put(struct reset_control *rstc)
|
|||
if (IS_ERR(rstc))
|
||||
return;
|
||||
|
||||
module_put(rstc->rcdev->owner);
|
||||
kfree(rstc);
|
||||
mutex_lock(&reset_list_mutex);
|
||||
__reset_control_put(rstc);
|
||||
mutex_unlock(&reset_list_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reset_control_put);
|
||||
|
||||
|
@ -264,16 +300,8 @@ static void devm_reset_control_release(struct device *dev, void *res)
|
|||
reset_control_put(*(struct reset_control **)res);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_get - resource managed reset_control_get()
|
||||
* @dev: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Managed reset_control_get(). For reset controllers returned from this
|
||||
* function, reset_control_put() is called automatically on driver detach.
|
||||
* See reset_control_get() for more information.
|
||||
*/
|
||||
struct reset_control *devm_reset_control_get(struct device *dev, const char *id)
|
||||
struct reset_control *__devm_reset_control_get(struct device *dev,
|
||||
const char *id, int index, int shared)
|
||||
{
|
||||
struct reset_control **ptr, *rstc;
|
||||
|
||||
|
@ -282,7 +310,8 @@ struct reset_control *devm_reset_control_get(struct device *dev, const char *id)
|
|||
if (!ptr)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
rstc = reset_control_get(dev, id);
|
||||
rstc = __of_reset_control_get(dev ? dev->of_node : NULL,
|
||||
id, index, shared);
|
||||
if (!IS_ERR(rstc)) {
|
||||
*ptr = rstc;
|
||||
devres_add(dev, ptr);
|
||||
|
@ -292,7 +321,7 @@ struct reset_control *devm_reset_control_get(struct device *dev, const char *id)
|
|||
|
||||
return rstc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_reset_control_get);
|
||||
EXPORT_SYMBOL_GPL(__devm_reset_control_get);
|
||||
|
||||
/**
|
||||
* device_reset - find reset controller associated with the device
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
struct lpc18xx_rgu_data {
|
||||
struct reset_controller_dev rcdev;
|
||||
struct notifier_block restart_nb;
|
||||
struct clk *clk_delay;
|
||||
struct clk *clk_reg;
|
||||
void __iomem *base;
|
||||
|
@ -44,12 +45,13 @@ struct lpc18xx_rgu_data {
|
|||
|
||||
#define to_rgu_data(p) container_of(p, struct lpc18xx_rgu_data, rcdev)
|
||||
|
||||
static void __iomem *rgu_base;
|
||||
|
||||
static int lpc18xx_rgu_restart(struct notifier_block *this, unsigned long mode,
|
||||
static int lpc18xx_rgu_restart(struct notifier_block *nb, unsigned long mode,
|
||||
void *cmd)
|
||||
{
|
||||
writel(BIT(LPC18XX_RGU_CORE_RST), rgu_base + LPC18XX_RGU_CTRL0);
|
||||
struct lpc18xx_rgu_data *rc = container_of(nb, struct lpc18xx_rgu_data,
|
||||
restart_nb);
|
||||
|
||||
writel(BIT(LPC18XX_RGU_CORE_RST), rc->base + LPC18XX_RGU_CTRL0);
|
||||
mdelay(2000);
|
||||
|
||||
pr_emerg("%s: unable to restart system\n", __func__);
|
||||
|
@ -57,11 +59,6 @@ static int lpc18xx_rgu_restart(struct notifier_block *this, unsigned long mode,
|
|||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block lpc18xx_rgu_restart_nb = {
|
||||
.notifier_call = lpc18xx_rgu_restart,
|
||||
.priority = 192,
|
||||
};
|
||||
|
||||
/*
|
||||
* The LPC18xx RGU has mostly self-deasserting resets except for the
|
||||
* two reset lines going to the internal Cortex-M0 cores.
|
||||
|
@ -205,8 +202,9 @@ static int lpc18xx_rgu_probe(struct platform_device *pdev)
|
|||
goto dis_clks;
|
||||
}
|
||||
|
||||
rgu_base = rc->base;
|
||||
ret = register_restart_handler(&lpc18xx_rgu_restart_nb);
|
||||
rc->restart_nb.priority = 192,
|
||||
rc->restart_nb.notifier_call = lpc18xx_rgu_restart,
|
||||
ret = register_restart_handler(&rc->restart_nb);
|
||||
if (ret)
|
||||
dev_warn(&pdev->dev, "failed to register restart handler\n");
|
||||
|
||||
|
@ -225,7 +223,7 @@ static int lpc18xx_rgu_remove(struct platform_device *pdev)
|
|||
struct lpc18xx_rgu_data *rc = platform_get_drvdata(pdev);
|
||||
int ret;
|
||||
|
||||
ret = unregister_restart_handler(&lpc18xx_rgu_restart_nb);
|
||||
ret = unregister_restart_handler(&rc->restart_nb);
|
||||
if (ret)
|
||||
dev_warn(&pdev->dev, "failed to unregister restart handler\n");
|
||||
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* drivers/reset/reset-oxnas.c
|
||||
*
|
||||
* Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
|
||||
* Copyright (C) 2014 Ma Haijun <mahaijuns@gmail.com>
|
||||
* Copyright (C) 2009 Oxford Semiconductor Ltd
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
|
||||
/* Regmap offsets */
|
||||
#define RST_SET_REGOFFSET 0x34
|
||||
#define RST_CLR_REGOFFSET 0x38
|
||||
|
||||
struct oxnas_reset {
|
||||
struct regmap *regmap;
|
||||
struct reset_controller_dev rcdev;
|
||||
};
|
||||
|
||||
static int oxnas_reset_reset(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct oxnas_reset *data =
|
||||
container_of(rcdev, struct oxnas_reset, rcdev);
|
||||
|
||||
regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
|
||||
msleep(50);
|
||||
regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int oxnas_reset_assert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct oxnas_reset *data =
|
||||
container_of(rcdev, struct oxnas_reset, rcdev);
|
||||
|
||||
regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int oxnas_reset_deassert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct oxnas_reset *data =
|
||||
container_of(rcdev, struct oxnas_reset, rcdev);
|
||||
|
||||
regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct reset_control_ops oxnas_reset_ops = {
|
||||
.reset = oxnas_reset_reset,
|
||||
.assert = oxnas_reset_assert,
|
||||
.deassert = oxnas_reset_deassert,
|
||||
};
|
||||
|
||||
static const struct of_device_id oxnas_reset_dt_ids[] = {
|
||||
{ .compatible = "oxsemi,ox810se-reset", },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, oxnas_reset_dt_ids);
|
||||
|
||||
static int oxnas_reset_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct oxnas_reset *data;
|
||||
struct device *parent;
|
||||
|
||||
parent = pdev->dev.parent;
|
||||
if (!parent) {
|
||||
dev_err(&pdev->dev, "no parent\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->regmap = syscon_node_to_regmap(parent->of_node);
|
||||
if (IS_ERR(data->regmap)) {
|
||||
dev_err(&pdev->dev, "failed to get parent regmap\n");
|
||||
return PTR_ERR(data->regmap);
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, data);
|
||||
|
||||
data->rcdev.owner = THIS_MODULE;
|
||||
data->rcdev.nr_resets = 32;
|
||||
data->rcdev.ops = &oxnas_reset_ops;
|
||||
data->rcdev.of_node = pdev->dev.of_node;
|
||||
|
||||
return reset_controller_register(&data->rcdev);
|
||||
}
|
||||
|
||||
static int oxnas_reset_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct oxnas_reset *data = platform_get_drvdata(pdev);
|
||||
|
||||
reset_controller_unregister(&data->rcdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver oxnas_reset_driver = {
|
||||
.probe = oxnas_reset_probe,
|
||||
.remove = oxnas_reset_remove,
|
||||
.driver = {
|
||||
.name = "oxnas-reset",
|
||||
.of_match_table = oxnas_reset_dt_ids,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(oxnas_reset_driver);
|
|
@ -9,6 +9,7 @@ obj-$(CONFIG_MACH_DOVE) += dove/
|
|||
obj-y += fsl/
|
||||
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
|
||||
obj-$(CONFIG_ARCH_QCOM) += qcom/
|
||||
obj-$(CONFIG_ARCH_RENESAS) += renesas/
|
||||
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
|
||||
obj-$(CONFIG_SOC_SAMSUNG) += samsung/
|
||||
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
menuconfig SOC_BRCMSTB
|
||||
bool "Broadcom STB SoC drivers"
|
||||
depends on ARM
|
||||
select SOC_BUS
|
||||
help
|
||||
Enables drivers for the Broadcom Set-Top Box (STB) series of chips.
|
||||
This option alone enables only some support code, while the drivers
|
||||
|
|
|
@ -12,10 +12,18 @@
|
|||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/soc/brcmstb/brcmstb.h>
|
||||
#include <linux/sys_soc.h>
|
||||
|
||||
#include <soc/brcmstb/common.h>
|
||||
|
||||
static u32 family_id;
|
||||
static u32 product_id;
|
||||
|
||||
static const struct of_device_id brcmstb_machine_match[] = {
|
||||
{ .compatible = "brcm,brcmstb", },
|
||||
{ }
|
||||
|
@ -31,3 +39,61 @@ bool soc_is_brcmstb(void)
|
|||
|
||||
return of_match_node(brcmstb_machine_match, root) != NULL;
|
||||
}
|
||||
|
||||
static const struct of_device_id sun_top_ctrl_match[] = {
|
||||
{ .compatible = "brcm,brcmstb-sun-top-ctrl", },
|
||||
{ }
|
||||
};
|
||||
|
||||
static int __init brcmstb_soc_device_init(void)
|
||||
{
|
||||
struct soc_device_attribute *soc_dev_attr;
|
||||
struct soc_device *soc_dev;
|
||||
struct device_node *sun_top_ctrl;
|
||||
void __iomem *sun_top_ctrl_base;
|
||||
int ret = 0;
|
||||
|
||||
sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match);
|
||||
if (!sun_top_ctrl)
|
||||
return -ENODEV;
|
||||
|
||||
sun_top_ctrl_base = of_iomap(sun_top_ctrl, 0);
|
||||
if (!sun_top_ctrl_base)
|
||||
return -ENODEV;
|
||||
|
||||
family_id = readl(sun_top_ctrl_base);
|
||||
product_id = readl(sun_top_ctrl_base + 0x4);
|
||||
|
||||
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
|
||||
if (!soc_dev_attr) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
soc_dev_attr->family = kasprintf(GFP_KERNEL, "%x",
|
||||
family_id >> 28 ?
|
||||
family_id >> 16 : family_id >> 8);
|
||||
soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%x",
|
||||
product_id >> 28 ?
|
||||
product_id >> 16 : product_id >> 8);
|
||||
soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c%d",
|
||||
((product_id & 0xf0) >> 4) + 'A',
|
||||
product_id & 0xf);
|
||||
|
||||
soc_dev = soc_device_register(soc_dev_attr);
|
||||
if (IS_ERR(soc_dev)) {
|
||||
kfree(soc_dev_attr->family);
|
||||
kfree(soc_dev_attr->soc_id);
|
||||
kfree(soc_dev_attr->revision);
|
||||
kfree(soc_dev_attr);
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
iounmap(sun_top_ctrl_base);
|
||||
return ret;
|
||||
}
|
||||
arch_initcall(brcmstb_soc_device_init);
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#define PWRAP_DEW_WRITE_TEST_VAL 0xa55a
|
||||
|
||||
/* macro for manual command */
|
||||
#define PWRAP_MAN_CMD_SPI_WRITE_NEW (1 << 14)
|
||||
#define PWRAP_MAN_CMD_SPI_WRITE (1 << 13)
|
||||
#define PWRAP_MAN_CMD_OP_CSH (0x0 << 8)
|
||||
#define PWRAP_MAN_CMD_OP_CSL (0x1 << 8)
|
||||
|
@ -69,33 +70,75 @@
|
|||
PWRAP_WDT_SRC_EN_HARB_STAUPD_DLE | \
|
||||
PWRAP_WDT_SRC_EN_HARB_STAUPD_ALE)
|
||||
|
||||
/* macro for slave device wrapper registers */
|
||||
#define PWRAP_DEW_BASE 0xbc00
|
||||
#define PWRAP_DEW_EVENT_OUT_EN (PWRAP_DEW_BASE + 0x0)
|
||||
#define PWRAP_DEW_DIO_EN (PWRAP_DEW_BASE + 0x2)
|
||||
#define PWRAP_DEW_EVENT_SRC_EN (PWRAP_DEW_BASE + 0x4)
|
||||
#define PWRAP_DEW_EVENT_SRC (PWRAP_DEW_BASE + 0x6)
|
||||
#define PWRAP_DEW_EVENT_FLAG (PWRAP_DEW_BASE + 0x8)
|
||||
#define PWRAP_DEW_READ_TEST (PWRAP_DEW_BASE + 0xa)
|
||||
#define PWRAP_DEW_WRITE_TEST (PWRAP_DEW_BASE + 0xc)
|
||||
#define PWRAP_DEW_CRC_EN (PWRAP_DEW_BASE + 0xe)
|
||||
#define PWRAP_DEW_CRC_VAL (PWRAP_DEW_BASE + 0x10)
|
||||
#define PWRAP_DEW_MON_GRP_SEL (PWRAP_DEW_BASE + 0x12)
|
||||
#define PWRAP_DEW_MON_FLAG_SEL (PWRAP_DEW_BASE + 0x14)
|
||||
#define PWRAP_DEW_EVENT_TEST (PWRAP_DEW_BASE + 0x16)
|
||||
#define PWRAP_DEW_CIPHER_KEY_SEL (PWRAP_DEW_BASE + 0x18)
|
||||
#define PWRAP_DEW_CIPHER_IV_SEL (PWRAP_DEW_BASE + 0x1a)
|
||||
#define PWRAP_DEW_CIPHER_LOAD (PWRAP_DEW_BASE + 0x1c)
|
||||
#define PWRAP_DEW_CIPHER_START (PWRAP_DEW_BASE + 0x1e)
|
||||
#define PWRAP_DEW_CIPHER_RDY (PWRAP_DEW_BASE + 0x20)
|
||||
#define PWRAP_DEW_CIPHER_MODE (PWRAP_DEW_BASE + 0x22)
|
||||
#define PWRAP_DEW_CIPHER_SWRST (PWRAP_DEW_BASE + 0x24)
|
||||
#define PWRAP_MT8173_DEW_CIPHER_IV0 (PWRAP_DEW_BASE + 0x26)
|
||||
#define PWRAP_MT8173_DEW_CIPHER_IV1 (PWRAP_DEW_BASE + 0x28)
|
||||
#define PWRAP_MT8173_DEW_CIPHER_IV2 (PWRAP_DEW_BASE + 0x2a)
|
||||
#define PWRAP_MT8173_DEW_CIPHER_IV3 (PWRAP_DEW_BASE + 0x2c)
|
||||
#define PWRAP_MT8173_DEW_CIPHER_IV4 (PWRAP_DEW_BASE + 0x2e)
|
||||
#define PWRAP_MT8173_DEW_CIPHER_IV5 (PWRAP_DEW_BASE + 0x30)
|
||||
/* defines for slave device wrapper registers */
|
||||
enum dew_regs {
|
||||
PWRAP_DEW_BASE,
|
||||
PWRAP_DEW_DIO_EN,
|
||||
PWRAP_DEW_READ_TEST,
|
||||
PWRAP_DEW_WRITE_TEST,
|
||||
PWRAP_DEW_CRC_EN,
|
||||
PWRAP_DEW_CRC_VAL,
|
||||
PWRAP_DEW_MON_GRP_SEL,
|
||||
PWRAP_DEW_CIPHER_KEY_SEL,
|
||||
PWRAP_DEW_CIPHER_IV_SEL,
|
||||
PWRAP_DEW_CIPHER_RDY,
|
||||
PWRAP_DEW_CIPHER_MODE,
|
||||
PWRAP_DEW_CIPHER_SWRST,
|
||||
|
||||
/* MT6397 only regs */
|
||||
PWRAP_DEW_EVENT_OUT_EN,
|
||||
PWRAP_DEW_EVENT_SRC_EN,
|
||||
PWRAP_DEW_EVENT_SRC,
|
||||
PWRAP_DEW_EVENT_FLAG,
|
||||
PWRAP_DEW_MON_FLAG_SEL,
|
||||
PWRAP_DEW_EVENT_TEST,
|
||||
PWRAP_DEW_CIPHER_LOAD,
|
||||
PWRAP_DEW_CIPHER_START,
|
||||
|
||||
/* MT6323 only regs */
|
||||
PWRAP_DEW_CIPHER_EN,
|
||||
PWRAP_DEW_RDDMY_NO,
|
||||
};
|
||||
|
||||
static const u32 mt6323_regs[] = {
|
||||
[PWRAP_DEW_BASE] = 0x0000,
|
||||
[PWRAP_DEW_DIO_EN] = 0x018a,
|
||||
[PWRAP_DEW_READ_TEST] = 0x018c,
|
||||
[PWRAP_DEW_WRITE_TEST] = 0x018e,
|
||||
[PWRAP_DEW_CRC_EN] = 0x0192,
|
||||
[PWRAP_DEW_CRC_VAL] = 0x0194,
|
||||
[PWRAP_DEW_MON_GRP_SEL] = 0x0196,
|
||||
[PWRAP_DEW_CIPHER_KEY_SEL] = 0x0198,
|
||||
[PWRAP_DEW_CIPHER_IV_SEL] = 0x019a,
|
||||
[PWRAP_DEW_CIPHER_EN] = 0x019c,
|
||||
[PWRAP_DEW_CIPHER_RDY] = 0x019e,
|
||||
[PWRAP_DEW_CIPHER_MODE] = 0x01a0,
|
||||
[PWRAP_DEW_CIPHER_SWRST] = 0x01a2,
|
||||
[PWRAP_DEW_RDDMY_NO] = 0x01a4,
|
||||
};
|
||||
|
||||
static const u32 mt6397_regs[] = {
|
||||
[PWRAP_DEW_BASE] = 0xbc00,
|
||||
[PWRAP_DEW_EVENT_OUT_EN] = 0xbc00,
|
||||
[PWRAP_DEW_DIO_EN] = 0xbc02,
|
||||
[PWRAP_DEW_EVENT_SRC_EN] = 0xbc04,
|
||||
[PWRAP_DEW_EVENT_SRC] = 0xbc06,
|
||||
[PWRAP_DEW_EVENT_FLAG] = 0xbc08,
|
||||
[PWRAP_DEW_READ_TEST] = 0xbc0a,
|
||||
[PWRAP_DEW_WRITE_TEST] = 0xbc0c,
|
||||
[PWRAP_DEW_CRC_EN] = 0xbc0e,
|
||||
[PWRAP_DEW_CRC_VAL] = 0xbc10,
|
||||
[PWRAP_DEW_MON_GRP_SEL] = 0xbc12,
|
||||
[PWRAP_DEW_MON_FLAG_SEL] = 0xbc14,
|
||||
[PWRAP_DEW_EVENT_TEST] = 0xbc16,
|
||||
[PWRAP_DEW_CIPHER_KEY_SEL] = 0xbc18,
|
||||
[PWRAP_DEW_CIPHER_IV_SEL] = 0xbc1a,
|
||||
[PWRAP_DEW_CIPHER_LOAD] = 0xbc1c,
|
||||
[PWRAP_DEW_CIPHER_START] = 0xbc1e,
|
||||
[PWRAP_DEW_CIPHER_RDY] = 0xbc20,
|
||||
[PWRAP_DEW_CIPHER_MODE] = 0xbc22,
|
||||
[PWRAP_DEW_CIPHER_SWRST] = 0xbc24,
|
||||
};
|
||||
|
||||
enum pwrap_regs {
|
||||
PWRAP_MUX_SEL,
|
||||
|
@ -158,6 +201,13 @@ enum pwrap_regs {
|
|||
PWRAP_DCM_EN,
|
||||
PWRAP_DCM_DBC_PRD,
|
||||
|
||||
/* MT2701 only regs */
|
||||
PWRAP_ADC_CMD_ADDR,
|
||||
PWRAP_PWRAP_ADC_CMD,
|
||||
PWRAP_ADC_RDY_ADDR,
|
||||
PWRAP_ADC_RDATA_ADDR1,
|
||||
PWRAP_ADC_RDATA_ADDR2,
|
||||
|
||||
/* MT8135 only regs */
|
||||
PWRAP_CSHEXT,
|
||||
PWRAP_EVENT_IN_EN,
|
||||
|
@ -194,6 +244,92 @@ enum pwrap_regs {
|
|||
PWRAP_CIPHER_EN,
|
||||
};
|
||||
|
||||
static int mt2701_regs[] = {
|
||||
[PWRAP_MUX_SEL] = 0x0,
|
||||
[PWRAP_WRAP_EN] = 0x4,
|
||||
[PWRAP_DIO_EN] = 0x8,
|
||||
[PWRAP_SIDLY] = 0xc,
|
||||
[PWRAP_RDDMY] = 0x18,
|
||||
[PWRAP_SI_CK_CON] = 0x1c,
|
||||
[PWRAP_CSHEXT_WRITE] = 0x20,
|
||||
[PWRAP_CSHEXT_READ] = 0x24,
|
||||
[PWRAP_CSLEXT_START] = 0x28,
|
||||
[PWRAP_CSLEXT_END] = 0x2c,
|
||||
[PWRAP_STAUPD_PRD] = 0x30,
|
||||
[PWRAP_STAUPD_GRPEN] = 0x34,
|
||||
[PWRAP_STAUPD_MAN_TRIG] = 0x38,
|
||||
[PWRAP_STAUPD_STA] = 0x3c,
|
||||
[PWRAP_WRAP_STA] = 0x44,
|
||||
[PWRAP_HARB_INIT] = 0x48,
|
||||
[PWRAP_HARB_HPRIO] = 0x4c,
|
||||
[PWRAP_HIPRIO_ARB_EN] = 0x50,
|
||||
[PWRAP_HARB_STA0] = 0x54,
|
||||
[PWRAP_HARB_STA1] = 0x58,
|
||||
[PWRAP_MAN_EN] = 0x5c,
|
||||
[PWRAP_MAN_CMD] = 0x60,
|
||||
[PWRAP_MAN_RDATA] = 0x64,
|
||||
[PWRAP_MAN_VLDCLR] = 0x68,
|
||||
[PWRAP_WACS0_EN] = 0x6c,
|
||||
[PWRAP_INIT_DONE0] = 0x70,
|
||||
[PWRAP_WACS0_CMD] = 0x74,
|
||||
[PWRAP_WACS0_RDATA] = 0x78,
|
||||
[PWRAP_WACS0_VLDCLR] = 0x7c,
|
||||
[PWRAP_WACS1_EN] = 0x80,
|
||||
[PWRAP_INIT_DONE1] = 0x84,
|
||||
[PWRAP_WACS1_CMD] = 0x88,
|
||||
[PWRAP_WACS1_RDATA] = 0x8c,
|
||||
[PWRAP_WACS1_VLDCLR] = 0x90,
|
||||
[PWRAP_WACS2_EN] = 0x94,
|
||||
[PWRAP_INIT_DONE2] = 0x98,
|
||||
[PWRAP_WACS2_CMD] = 0x9c,
|
||||
[PWRAP_WACS2_RDATA] = 0xa0,
|
||||
[PWRAP_WACS2_VLDCLR] = 0xa4,
|
||||
[PWRAP_INT_EN] = 0xa8,
|
||||
[PWRAP_INT_FLG_RAW] = 0xac,
|
||||
[PWRAP_INT_FLG] = 0xb0,
|
||||
[PWRAP_INT_CLR] = 0xb4,
|
||||
[PWRAP_SIG_ADR] = 0xb8,
|
||||
[PWRAP_SIG_MODE] = 0xbc,
|
||||
[PWRAP_SIG_VALUE] = 0xc0,
|
||||
[PWRAP_SIG_ERRVAL] = 0xc4,
|
||||
[PWRAP_CRC_EN] = 0xc8,
|
||||
[PWRAP_TIMER_EN] = 0xcc,
|
||||
[PWRAP_TIMER_STA] = 0xd0,
|
||||
[PWRAP_WDT_UNIT] = 0xd4,
|
||||
[PWRAP_WDT_SRC_EN] = 0xd8,
|
||||
[PWRAP_WDT_FLG] = 0xdc,
|
||||
[PWRAP_DEBUG_INT_SEL] = 0xe0,
|
||||
[PWRAP_DVFS_ADR0] = 0xe4,
|
||||
[PWRAP_DVFS_WDATA0] = 0xe8,
|
||||
[PWRAP_DVFS_ADR1] = 0xec,
|
||||
[PWRAP_DVFS_WDATA1] = 0xf0,
|
||||
[PWRAP_DVFS_ADR2] = 0xf4,
|
||||
[PWRAP_DVFS_WDATA2] = 0xf8,
|
||||
[PWRAP_DVFS_ADR3] = 0xfc,
|
||||
[PWRAP_DVFS_WDATA3] = 0x100,
|
||||
[PWRAP_DVFS_ADR4] = 0x104,
|
||||
[PWRAP_DVFS_WDATA4] = 0x108,
|
||||
[PWRAP_DVFS_ADR5] = 0x10c,
|
||||
[PWRAP_DVFS_WDATA5] = 0x110,
|
||||
[PWRAP_DVFS_ADR6] = 0x114,
|
||||
[PWRAP_DVFS_WDATA6] = 0x118,
|
||||
[PWRAP_DVFS_ADR7] = 0x11c,
|
||||
[PWRAP_DVFS_WDATA7] = 0x120,
|
||||
[PWRAP_CIPHER_KEY_SEL] = 0x124,
|
||||
[PWRAP_CIPHER_IV_SEL] = 0x128,
|
||||
[PWRAP_CIPHER_EN] = 0x12c,
|
||||
[PWRAP_CIPHER_RDY] = 0x130,
|
||||
[PWRAP_CIPHER_MODE] = 0x134,
|
||||
[PWRAP_CIPHER_SWRST] = 0x138,
|
||||
[PWRAP_DCM_EN] = 0x13c,
|
||||
[PWRAP_DCM_DBC_PRD] = 0x140,
|
||||
[PWRAP_ADC_CMD_ADDR] = 0x144,
|
||||
[PWRAP_PWRAP_ADC_CMD] = 0x148,
|
||||
[PWRAP_ADC_RDY_ADDR] = 0x14c,
|
||||
[PWRAP_ADC_RDATA_ADDR1] = 0x150,
|
||||
[PWRAP_ADC_RDATA_ADDR2] = 0x154,
|
||||
};
|
||||
|
||||
static int mt8173_regs[] = {
|
||||
[PWRAP_MUX_SEL] = 0x0,
|
||||
[PWRAP_WRAP_EN] = 0x4,
|
||||
|
@ -349,36 +485,28 @@ static int mt8135_regs[] = {
|
|||
[PWRAP_DCM_DBC_PRD] = 0x160,
|
||||
};
|
||||
|
||||
enum pmic_type {
|
||||
PMIC_MT6323,
|
||||
PMIC_MT6397,
|
||||
};
|
||||
|
||||
enum pwrap_type {
|
||||
PWRAP_MT2701,
|
||||
PWRAP_MT8135,
|
||||
PWRAP_MT8173,
|
||||
};
|
||||
|
||||
struct pmic_wrapper_type {
|
||||
int *regs;
|
||||
enum pwrap_type type;
|
||||
u32 arb_en_all;
|
||||
};
|
||||
|
||||
static struct pmic_wrapper_type pwrap_mt8135 = {
|
||||
.regs = mt8135_regs,
|
||||
.type = PWRAP_MT8135,
|
||||
.arb_en_all = 0x1ff,
|
||||
};
|
||||
|
||||
static struct pmic_wrapper_type pwrap_mt8173 = {
|
||||
.regs = mt8173_regs,
|
||||
.type = PWRAP_MT8173,
|
||||
.arb_en_all = 0x3f,
|
||||
struct pwrap_slv_type {
|
||||
const u32 *dew_regs;
|
||||
enum pmic_type type;
|
||||
};
|
||||
|
||||
struct pmic_wrapper {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
struct regmap *regmap;
|
||||
int *regs;
|
||||
enum pwrap_type type;
|
||||
u32 arb_en_all;
|
||||
const struct pmic_wrapper_type *master;
|
||||
const struct pwrap_slv_type *slave;
|
||||
struct clk *clk_spi;
|
||||
struct clk *clk_wrap;
|
||||
struct reset_control *rstc;
|
||||
|
@ -387,24 +515,26 @@ struct pmic_wrapper {
|
|||
void __iomem *bridge_base;
|
||||
};
|
||||
|
||||
static inline int pwrap_is_mt8135(struct pmic_wrapper *wrp)
|
||||
{
|
||||
return wrp->type == PWRAP_MT8135;
|
||||
}
|
||||
|
||||
static inline int pwrap_is_mt8173(struct pmic_wrapper *wrp)
|
||||
{
|
||||
return wrp->type == PWRAP_MT8173;
|
||||
}
|
||||
struct pmic_wrapper_type {
|
||||
int *regs;
|
||||
enum pwrap_type type;
|
||||
u32 arb_en_all;
|
||||
u32 int_en_all;
|
||||
u32 spi_w;
|
||||
u32 wdt_src;
|
||||
int has_bridge:1;
|
||||
int (*init_reg_clock)(struct pmic_wrapper *wrp);
|
||||
int (*init_soc_specific)(struct pmic_wrapper *wrp);
|
||||
};
|
||||
|
||||
static u32 pwrap_readl(struct pmic_wrapper *wrp, enum pwrap_regs reg)
|
||||
{
|
||||
return readl(wrp->base + wrp->regs[reg]);
|
||||
return readl(wrp->base + wrp->master->regs[reg]);
|
||||
}
|
||||
|
||||
static void pwrap_writel(struct pmic_wrapper *wrp, u32 val, enum pwrap_regs reg)
|
||||
{
|
||||
writel(val, wrp->base + wrp->regs[reg]);
|
||||
writel(val, wrp->base + wrp->master->regs[reg]);
|
||||
}
|
||||
|
||||
static bool pwrap_is_fsm_idle(struct pmic_wrapper *wrp)
|
||||
|
@ -522,15 +652,15 @@ static int pwrap_reset_spislave(struct pmic_wrapper *wrp)
|
|||
pwrap_writel(wrp, 1, PWRAP_MAN_EN);
|
||||
pwrap_writel(wrp, 0, PWRAP_DIO_EN);
|
||||
|
||||
pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_CSL,
|
||||
pwrap_writel(wrp, wrp->master->spi_w | PWRAP_MAN_CMD_OP_CSL,
|
||||
PWRAP_MAN_CMD);
|
||||
pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_OUTS,
|
||||
pwrap_writel(wrp, wrp->master->spi_w | PWRAP_MAN_CMD_OP_OUTS,
|
||||
PWRAP_MAN_CMD);
|
||||
pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_CSH,
|
||||
pwrap_writel(wrp, wrp->master->spi_w | PWRAP_MAN_CMD_OP_CSH,
|
||||
PWRAP_MAN_CMD);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_OUTS,
|
||||
pwrap_writel(wrp, wrp->master->spi_w | PWRAP_MAN_CMD_OP_OUTS,
|
||||
PWRAP_MAN_CMD);
|
||||
|
||||
ret = pwrap_wait_for_state(wrp, pwrap_is_sync_idle);
|
||||
|
@ -562,7 +692,8 @@ static int pwrap_init_sidly(struct pmic_wrapper *wrp)
|
|||
|
||||
for (i = 0; i < 4; i++) {
|
||||
pwrap_writel(wrp, i, PWRAP_SIDLY);
|
||||
pwrap_read(wrp, PWRAP_DEW_READ_TEST, &rdata);
|
||||
pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_READ_TEST],
|
||||
&rdata);
|
||||
if (rdata == PWRAP_DEW_READ_TEST_VAL) {
|
||||
dev_dbg(wrp->dev, "[Read Test] pass, SIDLY=%x\n", i);
|
||||
pass |= 1 << i;
|
||||
|
@ -580,19 +711,47 @@ static int pwrap_init_sidly(struct pmic_wrapper *wrp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int pwrap_init_reg_clock(struct pmic_wrapper *wrp)
|
||||
static int pwrap_mt8135_init_reg_clock(struct pmic_wrapper *wrp)
|
||||
{
|
||||
if (pwrap_is_mt8135(wrp)) {
|
||||
pwrap_writel(wrp, 0x4, PWRAP_CSHEXT);
|
||||
pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_WRITE);
|
||||
pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_READ);
|
||||
pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_START);
|
||||
pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_END);
|
||||
} else {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pwrap_mt8173_init_reg_clock(struct pmic_wrapper *wrp)
|
||||
{
|
||||
pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_WRITE);
|
||||
pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_READ);
|
||||
pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_START);
|
||||
pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_END);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pwrap_mt2701_init_reg_clock(struct pmic_wrapper *wrp)
|
||||
{
|
||||
switch (wrp->slave->type) {
|
||||
case PMIC_MT6397:
|
||||
pwrap_writel(wrp, 0xc, PWRAP_RDDMY);
|
||||
pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_WRITE);
|
||||
pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_READ);
|
||||
pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_START);
|
||||
pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_END);
|
||||
break;
|
||||
|
||||
case PMIC_MT6323:
|
||||
pwrap_writel(wrp, 0x8, PWRAP_RDDMY);
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_RDDMY_NO],
|
||||
0x8);
|
||||
pwrap_writel(wrp, 0x5, PWRAP_CSHEXT_WRITE);
|
||||
pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_READ);
|
||||
pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_START);
|
||||
pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_END);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -608,7 +767,8 @@ static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp)
|
|||
u32 rdata;
|
||||
int ret;
|
||||
|
||||
ret = pwrap_read(wrp, PWRAP_DEW_CIPHER_RDY, &rdata);
|
||||
ret = pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_RDY],
|
||||
&rdata);
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
|
@ -625,20 +785,37 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
|
|||
pwrap_writel(wrp, 0x1, PWRAP_CIPHER_KEY_SEL);
|
||||
pwrap_writel(wrp, 0x2, PWRAP_CIPHER_IV_SEL);
|
||||
|
||||
if (pwrap_is_mt8135(wrp)) {
|
||||
switch (wrp->master->type) {
|
||||
case PWRAP_MT8135:
|
||||
pwrap_writel(wrp, 1, PWRAP_CIPHER_LOAD);
|
||||
pwrap_writel(wrp, 1, PWRAP_CIPHER_START);
|
||||
} else {
|
||||
break;
|
||||
case PWRAP_MT2701:
|
||||
case PWRAP_MT8173:
|
||||
pwrap_writel(wrp, 1, PWRAP_CIPHER_EN);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Config cipher mode @PMIC */
|
||||
pwrap_write(wrp, PWRAP_DEW_CIPHER_SWRST, 0x1);
|
||||
pwrap_write(wrp, PWRAP_DEW_CIPHER_SWRST, 0x0);
|
||||
pwrap_write(wrp, PWRAP_DEW_CIPHER_KEY_SEL, 0x1);
|
||||
pwrap_write(wrp, PWRAP_DEW_CIPHER_IV_SEL, 0x2);
|
||||
pwrap_write(wrp, PWRAP_DEW_CIPHER_LOAD, 0x1);
|
||||
pwrap_write(wrp, PWRAP_DEW_CIPHER_START, 0x1);
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x1);
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x0);
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_KEY_SEL], 0x1);
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_IV_SEL], 0x2);
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_LOAD], 0x1);
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_START], 0x1);
|
||||
|
||||
switch (wrp->slave->type) {
|
||||
case PMIC_MT6397:
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_LOAD],
|
||||
0x1);
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_START],
|
||||
0x1);
|
||||
break;
|
||||
case PMIC_MT6323:
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_EN],
|
||||
0x1);
|
||||
break;
|
||||
}
|
||||
|
||||
/* wait for cipher data ready@AP */
|
||||
ret = pwrap_wait_for_state(wrp, pwrap_is_cipher_ready);
|
||||
|
@ -655,7 +832,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
|
|||
}
|
||||
|
||||
/* wait for cipher mode idle */
|
||||
pwrap_write(wrp, PWRAP_DEW_CIPHER_MODE, 0x1);
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_MODE], 0x1);
|
||||
ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle_and_sync_idle);
|
||||
if (ret) {
|
||||
dev_err(wrp->dev, "cipher mode idle fail, ret=%d\n", ret);
|
||||
|
@ -665,8 +842,10 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
|
|||
pwrap_writel(wrp, 1, PWRAP_CIPHER_MODE);
|
||||
|
||||
/* Write Test */
|
||||
if (pwrap_write(wrp, PWRAP_DEW_WRITE_TEST, PWRAP_DEW_WRITE_TEST_VAL) ||
|
||||
pwrap_read(wrp, PWRAP_DEW_WRITE_TEST, &rdata) ||
|
||||
if (pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_WRITE_TEST],
|
||||
PWRAP_DEW_WRITE_TEST_VAL) ||
|
||||
pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_WRITE_TEST],
|
||||
&rdata) ||
|
||||
(rdata != PWRAP_DEW_WRITE_TEST_VAL)) {
|
||||
dev_err(wrp->dev, "rdata=0x%04X\n", rdata);
|
||||
return -EFAULT;
|
||||
|
@ -675,6 +854,63 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int pwrap_mt8135_init_soc_specific(struct pmic_wrapper *wrp)
|
||||
{
|
||||
/* enable pwrap events and pwrap bridge in AP side */
|
||||
pwrap_writel(wrp, 0x1, PWRAP_EVENT_IN_EN);
|
||||
pwrap_writel(wrp, 0xffff, PWRAP_EVENT_DST_EN);
|
||||
writel(0x7f, wrp->bridge_base + PWRAP_MT8135_BRIDGE_IORD_ARB_EN);
|
||||
writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WACS3_EN);
|
||||
writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WACS4_EN);
|
||||
writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WDT_UNIT);
|
||||
writel(0xffff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WDT_SRC_EN);
|
||||
writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_TIMER_EN);
|
||||
writel(0x7ff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INT_EN);
|
||||
|
||||
/* enable PMIC event out and sources */
|
||||
if (pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_EVENT_OUT_EN],
|
||||
0x1) ||
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_EVENT_SRC_EN],
|
||||
0xffff)) {
|
||||
dev_err(wrp->dev, "enable dewrap fail\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pwrap_mt8173_init_soc_specific(struct pmic_wrapper *wrp)
|
||||
{
|
||||
/* PMIC_DEWRAP enables */
|
||||
if (pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_EVENT_OUT_EN],
|
||||
0x1) ||
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_EVENT_SRC_EN],
|
||||
0xffff)) {
|
||||
dev_err(wrp->dev, "enable dewrap fail\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pwrap_mt2701_init_soc_specific(struct pmic_wrapper *wrp)
|
||||
{
|
||||
/* GPS_INTF initialization */
|
||||
switch (wrp->slave->type) {
|
||||
case PMIC_MT6323:
|
||||
pwrap_writel(wrp, 0x076c, PWRAP_ADC_CMD_ADDR);
|
||||
pwrap_writel(wrp, 0x8000, PWRAP_PWRAP_ADC_CMD);
|
||||
pwrap_writel(wrp, 0x072c, PWRAP_ADC_RDY_ADDR);
|
||||
pwrap_writel(wrp, 0x072e, PWRAP_ADC_RDATA_ADDR1);
|
||||
pwrap_writel(wrp, 0x0730, PWRAP_ADC_RDATA_ADDR2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pwrap_init(struct pmic_wrapper *wrp)
|
||||
{
|
||||
int ret;
|
||||
|
@ -684,7 +920,7 @@ static int pwrap_init(struct pmic_wrapper *wrp)
|
|||
if (wrp->rstc_bridge)
|
||||
reset_control_reset(wrp->rstc_bridge);
|
||||
|
||||
if (pwrap_is_mt8173(wrp)) {
|
||||
if (wrp->master->type == PWRAP_MT8173) {
|
||||
/* Enable DCM */
|
||||
pwrap_writel(wrp, 3, PWRAP_DCM_EN);
|
||||
pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD);
|
||||
|
@ -697,11 +933,11 @@ static int pwrap_init(struct pmic_wrapper *wrp)
|
|||
|
||||
pwrap_writel(wrp, 1, PWRAP_WRAP_EN);
|
||||
|
||||
pwrap_writel(wrp, wrp->arb_en_all, PWRAP_HIPRIO_ARB_EN);
|
||||
pwrap_writel(wrp, wrp->master->arb_en_all, PWRAP_HIPRIO_ARB_EN);
|
||||
|
||||
pwrap_writel(wrp, 1, PWRAP_WACS2_EN);
|
||||
|
||||
ret = pwrap_init_reg_clock(wrp);
|
||||
ret = wrp->master->init_reg_clock(wrp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -711,7 +947,7 @@ static int pwrap_init(struct pmic_wrapper *wrp)
|
|||
return ret;
|
||||
|
||||
/* Enable dual IO mode */
|
||||
pwrap_write(wrp, PWRAP_DEW_DIO_EN, 1);
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_DIO_EN], 1);
|
||||
|
||||
/* Check IDLE & INIT_DONE in advance */
|
||||
ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle_and_sync_idle);
|
||||
|
@ -723,7 +959,7 @@ static int pwrap_init(struct pmic_wrapper *wrp)
|
|||
pwrap_writel(wrp, 1, PWRAP_DIO_EN);
|
||||
|
||||
/* Read Test */
|
||||
pwrap_read(wrp, PWRAP_DEW_READ_TEST, &rdata);
|
||||
pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_READ_TEST], &rdata);
|
||||
if (rdata != PWRAP_DEW_READ_TEST_VAL) {
|
||||
dev_err(wrp->dev, "Read test failed after switch to DIO mode: 0x%04x != 0x%04x\n",
|
||||
PWRAP_DEW_READ_TEST_VAL, rdata);
|
||||
|
@ -736,15 +972,16 @@ static int pwrap_init(struct pmic_wrapper *wrp)
|
|||
return ret;
|
||||
|
||||
/* Signature checking - using CRC */
|
||||
if (pwrap_write(wrp, PWRAP_DEW_CRC_EN, 0x1))
|
||||
if (pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_EN], 0x1))
|
||||
return -EFAULT;
|
||||
|
||||
pwrap_writel(wrp, 0x1, PWRAP_CRC_EN);
|
||||
pwrap_writel(wrp, 0x0, PWRAP_SIG_MODE);
|
||||
pwrap_writel(wrp, PWRAP_DEW_CRC_VAL, PWRAP_SIG_ADR);
|
||||
pwrap_writel(wrp, wrp->arb_en_all, PWRAP_HIPRIO_ARB_EN);
|
||||
pwrap_writel(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_VAL],
|
||||
PWRAP_SIG_ADR);
|
||||
pwrap_writel(wrp, wrp->master->arb_en_all, PWRAP_HIPRIO_ARB_EN);
|
||||
|
||||
if (pwrap_is_mt8135(wrp))
|
||||
if (wrp->master->type == PWRAP_MT8135)
|
||||
pwrap_writel(wrp, 0x7, PWRAP_RRARB_EN);
|
||||
|
||||
pwrap_writel(wrp, 0x1, PWRAP_WACS0_EN);
|
||||
|
@ -753,31 +990,10 @@ static int pwrap_init(struct pmic_wrapper *wrp)
|
|||
pwrap_writel(wrp, 0x5, PWRAP_STAUPD_PRD);
|
||||
pwrap_writel(wrp, 0xff, PWRAP_STAUPD_GRPEN);
|
||||
|
||||
if (pwrap_is_mt8135(wrp)) {
|
||||
/* enable pwrap events and pwrap bridge in AP side */
|
||||
pwrap_writel(wrp, 0x1, PWRAP_EVENT_IN_EN);
|
||||
pwrap_writel(wrp, 0xffff, PWRAP_EVENT_DST_EN);
|
||||
writel(0x7f, wrp->bridge_base + PWRAP_MT8135_BRIDGE_IORD_ARB_EN);
|
||||
writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WACS3_EN);
|
||||
writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WACS4_EN);
|
||||
writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WDT_UNIT);
|
||||
writel(0xffff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WDT_SRC_EN);
|
||||
writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_TIMER_EN);
|
||||
writel(0x7ff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INT_EN);
|
||||
|
||||
/* enable PMIC event out and sources */
|
||||
if (pwrap_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) ||
|
||||
pwrap_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) {
|
||||
dev_err(wrp->dev, "enable dewrap fail\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
} else {
|
||||
/* PMIC_DEWRAP enables */
|
||||
if (pwrap_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) ||
|
||||
pwrap_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) {
|
||||
dev_err(wrp->dev, "enable dewrap fail\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
if (wrp->master->init_soc_specific) {
|
||||
ret = wrp->master->init_soc_specific(wrp);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Setup the init done registers */
|
||||
|
@ -785,7 +1001,7 @@ static int pwrap_init(struct pmic_wrapper *wrp)
|
|||
pwrap_writel(wrp, 1, PWRAP_INIT_DONE0);
|
||||
pwrap_writel(wrp, 1, PWRAP_INIT_DONE1);
|
||||
|
||||
if (pwrap_is_mt8135(wrp)) {
|
||||
if (wrp->master->has_bridge) {
|
||||
writel(1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INIT_DONE3);
|
||||
writel(1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INIT_DONE4);
|
||||
}
|
||||
|
@ -816,8 +1032,70 @@ static const struct regmap_config pwrap_regmap_config = {
|
|||
.max_register = 0xffff,
|
||||
};
|
||||
|
||||
static const struct pwrap_slv_type pmic_mt6323 = {
|
||||
.dew_regs = mt6323_regs,
|
||||
.type = PMIC_MT6323,
|
||||
};
|
||||
|
||||
static const struct pwrap_slv_type pmic_mt6397 = {
|
||||
.dew_regs = mt6397_regs,
|
||||
.type = PMIC_MT6397,
|
||||
};
|
||||
|
||||
static const struct of_device_id of_slave_match_tbl[] = {
|
||||
{
|
||||
.compatible = "mediatek,mt6323",
|
||||
.data = &pmic_mt6323,
|
||||
}, {
|
||||
.compatible = "mediatek,mt6397",
|
||||
.data = &pmic_mt6397,
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_slave_match_tbl);
|
||||
|
||||
static const struct pmic_wrapper_type pwrap_mt2701 = {
|
||||
.regs = mt2701_regs,
|
||||
.type = PWRAP_MT2701,
|
||||
.arb_en_all = 0x3f,
|
||||
.int_en_all = ~(BIT(31) | BIT(2)),
|
||||
.spi_w = PWRAP_MAN_CMD_SPI_WRITE_NEW,
|
||||
.wdt_src = PWRAP_WDT_SRC_MASK_ALL,
|
||||
.has_bridge = 0,
|
||||
.init_reg_clock = pwrap_mt2701_init_reg_clock,
|
||||
.init_soc_specific = pwrap_mt2701_init_soc_specific,
|
||||
};
|
||||
|
||||
static struct pmic_wrapper_type pwrap_mt8135 = {
|
||||
.regs = mt8135_regs,
|
||||
.type = PWRAP_MT8135,
|
||||
.arb_en_all = 0x1ff,
|
||||
.int_en_all = ~(BIT(31) | BIT(1)),
|
||||
.spi_w = PWRAP_MAN_CMD_SPI_WRITE,
|
||||
.wdt_src = PWRAP_WDT_SRC_MASK_ALL,
|
||||
.has_bridge = 1,
|
||||
.init_reg_clock = pwrap_mt8135_init_reg_clock,
|
||||
.init_soc_specific = pwrap_mt8135_init_soc_specific,
|
||||
};
|
||||
|
||||
static struct pmic_wrapper_type pwrap_mt8173 = {
|
||||
.regs = mt8173_regs,
|
||||
.type = PWRAP_MT8173,
|
||||
.arb_en_all = 0x3f,
|
||||
.int_en_all = ~(BIT(31) | BIT(1)),
|
||||
.spi_w = PWRAP_MAN_CMD_SPI_WRITE,
|
||||
.wdt_src = PWRAP_WDT_SRC_MASK_NO_STAUPD,
|
||||
.has_bridge = 0,
|
||||
.init_reg_clock = pwrap_mt8173_init_reg_clock,
|
||||
.init_soc_specific = pwrap_mt8173_init_soc_specific,
|
||||
};
|
||||
|
||||
static struct of_device_id of_pwrap_match_tbl[] = {
|
||||
{
|
||||
.compatible = "mediatek,mt2701-pwrap",
|
||||
.data = &pwrap_mt2701,
|
||||
}, {
|
||||
.compatible = "mediatek,mt8135-pwrap",
|
||||
.data = &pwrap_mt8135,
|
||||
}, {
|
||||
|
@ -831,24 +1109,30 @@ MODULE_DEVICE_TABLE(of, of_pwrap_match_tbl);
|
|||
|
||||
static int pwrap_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret, irq, wdt_src;
|
||||
int ret, irq;
|
||||
struct pmic_wrapper *wrp;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
const struct of_device_id *of_id =
|
||||
of_match_device(of_pwrap_match_tbl, &pdev->dev);
|
||||
const struct pmic_wrapper_type *type;
|
||||
const struct of_device_id *of_slave_id = NULL;
|
||||
struct resource *res;
|
||||
|
||||
if (pdev->dev.of_node->child)
|
||||
of_slave_id = of_match_node(of_slave_match_tbl,
|
||||
pdev->dev.of_node->child);
|
||||
if (!of_slave_id) {
|
||||
dev_dbg(&pdev->dev, "slave pmic should be defined in dts\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
wrp = devm_kzalloc(&pdev->dev, sizeof(*wrp), GFP_KERNEL);
|
||||
if (!wrp)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, wrp);
|
||||
|
||||
type = of_id->data;
|
||||
wrp->regs = type->regs;
|
||||
wrp->type = type->type;
|
||||
wrp->arb_en_all = type->arb_en_all;
|
||||
wrp->master = of_id->data;
|
||||
wrp->slave = of_slave_id->data;
|
||||
wrp->dev = &pdev->dev;
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwrap");
|
||||
|
@ -863,7 +1147,7 @@ static int pwrap_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (pwrap_is_mt8135(wrp)) {
|
||||
if (wrp->master->has_bridge) {
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||
"pwrap-bridge");
|
||||
wrp->bridge_base = devm_ioremap_resource(wrp->dev, res);
|
||||
|
@ -925,11 +1209,9 @@ static int pwrap_probe(struct platform_device *pdev)
|
|||
* Since STAUPD was not used on mt8173 platform,
|
||||
* so STAUPD of WDT_SRC which should be turned off
|
||||
*/
|
||||
wdt_src = pwrap_is_mt8173(wrp) ?
|
||||
PWRAP_WDT_SRC_MASK_NO_STAUPD : PWRAP_WDT_SRC_MASK_ALL;
|
||||
pwrap_writel(wrp, wdt_src, PWRAP_WDT_SRC_EN);
|
||||
pwrap_writel(wrp, wrp->master->wdt_src, PWRAP_WDT_SRC_EN);
|
||||
pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN);
|
||||
pwrap_writel(wrp, ~((1 << 31) | (1 << 1)), PWRAP_INT_EN);
|
||||
pwrap_writel(wrp, wrp->master->int_en_all, PWRAP_INT_EN);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt, IRQF_TRIGGER_HIGH,
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
obj-$(CONFIG_ARCH_R8A7779) += rcar-sysc.o r8a7779-sysc.o
|
||||
obj-$(CONFIG_ARCH_R8A7790) += rcar-sysc.o r8a7790-sysc.o
|
||||
obj-$(CONFIG_ARCH_R8A7791) += rcar-sysc.o r8a7791-sysc.o
|
||||
# R-Car M2-N is identical to R-Car M2-W w.r.t. power domains.
|
||||
obj-$(CONFIG_ARCH_R8A7793) += rcar-sysc.o r8a7791-sysc.o
|
||||
obj-$(CONFIG_ARCH_R8A7794) += rcar-sysc.o r8a7794-sysc.o
|
||||
obj-$(CONFIG_ARCH_R8A7795) += rcar-sysc.o r8a7795-sysc.o
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Renesas R-Car H1 System Controller
|
||||
*
|
||||
* Copyright (C) 2016 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
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*/
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <dt-bindings/power/r8a7779-sysc.h>
|
||||
|
||||
#include "rcar-sysc.h"
|
||||
|
||||
static const struct rcar_sysc_area r8a7779_areas[] __initconst = {
|
||||
{ "always-on", 0, 0, R8A7779_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
|
||||
{ "arm1", 0x40, 1, R8A7779_PD_ARM1, R8A7779_PD_ALWAYS_ON,
|
||||
PD_CPU_CR },
|
||||
{ "arm2", 0x40, 2, R8A7779_PD_ARM2, R8A7779_PD_ALWAYS_ON,
|
||||
PD_CPU_CR },
|
||||
{ "arm3", 0x40, 3, R8A7779_PD_ARM3, R8A7779_PD_ALWAYS_ON,
|
||||
PD_CPU_CR },
|
||||
{ "sgx", 0xc0, 0, R8A7779_PD_SGX, R8A7779_PD_ALWAYS_ON },
|
||||
{ "vdp", 0x100, 0, R8A7779_PD_VDP, R8A7779_PD_ALWAYS_ON },
|
||||
{ "imp", 0x140, 0, R8A7779_PD_IMP, R8A7779_PD_ALWAYS_ON },
|
||||
};
|
||||
|
||||
const struct rcar_sysc_info r8a7779_sysc_info __initconst = {
|
||||
.areas = r8a7779_areas,
|
||||
.num_areas = ARRAY_SIZE(r8a7779_areas),
|
||||
};
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Renesas R-Car H2 System Controller
|
||||
*
|
||||
* Copyright (C) 2016 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
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*/
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <dt-bindings/power/r8a7790-sysc.h>
|
||||
|
||||
#include "rcar-sysc.h"
|
||||
|
||||
static const struct rcar_sysc_area r8a7790_areas[] __initconst = {
|
||||
{ "always-on", 0, 0, R8A7790_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
|
||||
{ "ca15-scu", 0x180, 0, R8A7790_PD_CA15_SCU, R8A7790_PD_ALWAYS_ON,
|
||||
PD_SCU },
|
||||
{ "ca15-cpu0", 0x40, 0, R8A7790_PD_CA15_CPU0, R8A7790_PD_CA15_SCU,
|
||||
PD_CPU_NOCR },
|
||||
{ "ca15-cpu1", 0x40, 1, R8A7790_PD_CA15_CPU1, R8A7790_PD_CA15_SCU,
|
||||
PD_CPU_NOCR },
|
||||
{ "ca15-cpu2", 0x40, 2, R8A7790_PD_CA15_CPU2, R8A7790_PD_CA15_SCU,
|
||||
PD_CPU_NOCR },
|
||||
{ "ca15-cpu3", 0x40, 3, R8A7790_PD_CA15_CPU3, R8A7790_PD_CA15_SCU,
|
||||
PD_CPU_NOCR },
|
||||
{ "ca7-scu", 0x100, 0, R8A7790_PD_CA7_SCU, R8A7790_PD_ALWAYS_ON,
|
||||
PD_SCU },
|
||||
{ "ca7-cpu0", 0x1c0, 0, R8A7790_PD_CA7_CPU0, R8A7790_PD_CA7_SCU,
|
||||
PD_CPU_NOCR },
|
||||
{ "ca7-cpu1", 0x1c0, 1, R8A7790_PD_CA7_CPU1, R8A7790_PD_CA7_SCU,
|
||||
PD_CPU_NOCR },
|
||||
{ "ca7-cpu2", 0x1c0, 2, R8A7790_PD_CA7_CPU2, R8A7790_PD_CA7_SCU,
|
||||
PD_CPU_NOCR },
|
||||
{ "ca7-cpu3", 0x1c0, 3, R8A7790_PD_CA7_CPU3, R8A7790_PD_CA7_SCU,
|
||||
PD_CPU_NOCR },
|
||||
{ "sh-4a", 0x80, 0, R8A7790_PD_SH_4A, R8A7790_PD_ALWAYS_ON },
|
||||
{ "rgx", 0xc0, 0, R8A7790_PD_RGX, R8A7790_PD_ALWAYS_ON },
|
||||
{ "imp", 0x140, 0, R8A7790_PD_IMP, R8A7790_PD_ALWAYS_ON },
|
||||
};
|
||||
|
||||
const struct rcar_sysc_info r8a7790_sysc_info __initconst = {
|
||||
.areas = r8a7790_areas,
|
||||
.num_areas = ARRAY_SIZE(r8a7790_areas),
|
||||
};
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Renesas R-Car M2-W/N System Controller
|
||||
*
|
||||
* Copyright (C) 2016 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
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*/
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <dt-bindings/power/r8a7791-sysc.h>
|
||||
|
||||
#include "rcar-sysc.h"
|
||||
|
||||
static const struct rcar_sysc_area r8a7791_areas[] __initconst = {
|
||||
{ "always-on", 0, 0, R8A7791_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
|
||||
{ "ca15-scu", 0x180, 0, R8A7791_PD_CA15_SCU, R8A7791_PD_ALWAYS_ON,
|
||||
PD_SCU },
|
||||
{ "ca15-cpu0", 0x40, 0, R8A7791_PD_CA15_CPU0, R8A7791_PD_CA15_SCU,
|
||||
PD_CPU_NOCR },
|
||||
{ "ca15-cpu1", 0x40, 1, R8A7791_PD_CA15_CPU1, R8A7791_PD_CA15_SCU,
|
||||
PD_CPU_NOCR },
|
||||
{ "sh-4a", 0x80, 0, R8A7791_PD_SH_4A, R8A7791_PD_ALWAYS_ON },
|
||||
{ "sgx", 0xc0, 0, R8A7791_PD_SGX, R8A7791_PD_ALWAYS_ON },
|
||||
};
|
||||
|
||||
const struct rcar_sysc_info r8a7791_sysc_info __initconst = {
|
||||
.areas = r8a7791_areas,
|
||||
.num_areas = ARRAY_SIZE(r8a7791_areas),
|
||||
};
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Renesas R-Car E2 System Controller
|
||||
*
|
||||
* Copyright (C) 2016 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
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*/
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <dt-bindings/power/r8a7794-sysc.h>
|
||||
|
||||
#include "rcar-sysc.h"
|
||||
|
||||
static const struct rcar_sysc_area r8a7794_areas[] __initconst = {
|
||||
{ "always-on", 0, 0, R8A7794_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
|
||||
{ "ca7-scu", 0x100, 0, R8A7794_PD_CA7_SCU, R8A7794_PD_ALWAYS_ON,
|
||||
PD_SCU },
|
||||
{ "ca7-cpu0", 0x1c0, 0, R8A7794_PD_CA7_CPU0, R8A7794_PD_CA7_SCU,
|
||||
PD_CPU_NOCR },
|
||||
{ "ca7-cpu1", 0x1c0, 1, R8A7794_PD_CA7_CPU1, R8A7794_PD_CA7_SCU,
|
||||
PD_CPU_NOCR },
|
||||
{ "sh-4a", 0x80, 0, R8A7794_PD_SH_4A, R8A7794_PD_ALWAYS_ON },
|
||||
{ "sgx", 0xc0, 0, R8A7794_PD_SGX, R8A7794_PD_ALWAYS_ON },
|
||||
};
|
||||
|
||||
const struct rcar_sysc_info r8a7794_sysc_info __initconst = {
|
||||
.areas = r8a7794_areas,
|
||||
.num_areas = ARRAY_SIZE(r8a7794_areas),
|
||||
};
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Renesas R-Car H3 System Controller
|
||||
*
|
||||
* Copyright (C) 2016 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
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*/
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <dt-bindings/power/r8a7795-sysc.h>
|
||||
|
||||
#include "rcar-sysc.h"
|
||||
|
||||
static const struct rcar_sysc_area r8a7795_areas[] __initconst = {
|
||||
{ "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 },
|
||||
{ "ca57-cpu0", 0x80, 0, R8A7795_PD_CA57_CPU0, R8A7795_PD_CA57_SCU,
|
||||
PD_CPU_NOCR },
|
||||
{ "ca57-cpu1", 0x80, 1, R8A7795_PD_CA57_CPU1, R8A7795_PD_CA57_SCU,
|
||||
PD_CPU_NOCR },
|
||||
{ "ca57-cpu2", 0x80, 2, R8A7795_PD_CA57_CPU2, R8A7795_PD_CA57_SCU,
|
||||
PD_CPU_NOCR },
|
||||
{ "ca57-cpu3", 0x80, 3, R8A7795_PD_CA57_CPU3, R8A7795_PD_CA57_SCU,
|
||||
PD_CPU_NOCR },
|
||||
{ "ca53-scu", 0x140, 0, R8A7795_PD_CA53_SCU, R8A7795_PD_ALWAYS_ON,
|
||||
PD_SCU },
|
||||
{ "ca53-cpu0", 0x200, 0, R8A7795_PD_CA53_CPU0, R8A7795_PD_CA53_SCU,
|
||||
PD_CPU_NOCR },
|
||||
{ "ca53-cpu1", 0x200, 1, R8A7795_PD_CA53_CPU1, R8A7795_PD_CA53_SCU,
|
||||
PD_CPU_NOCR },
|
||||
{ "ca53-cpu2", 0x200, 2, R8A7795_PD_CA53_CPU2, R8A7795_PD_CA53_SCU,
|
||||
PD_CPU_NOCR },
|
||||
{ "ca53-cpu3", 0x200, 3, R8A7795_PD_CA53_CPU3, R8A7795_PD_CA53_SCU,
|
||||
PD_CPU_NOCR },
|
||||
{ "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", 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 },
|
||||
{ "3dg-b", 0x100, 1, R8A7795_PD_3DG_B, R8A7795_PD_3DG_A },
|
||||
{ "3dg-c", 0x100, 2, R8A7795_PD_3DG_C, R8A7795_PD_3DG_B },
|
||||
{ "3dg-d", 0x100, 3, R8A7795_PD_3DG_D, R8A7795_PD_3DG_C },
|
||||
{ "3dg-e", 0x100, 4, R8A7795_PD_3DG_E, R8A7795_PD_3DG_D },
|
||||
{ "a3ir", 0x180, 0, R8A7795_PD_A3IR, R8A7795_PD_ALWAYS_ON },
|
||||
};
|
||||
|
||||
const struct rcar_sysc_info r8a7795_sysc_info __initconst = {
|
||||
.areas = r8a7795_areas,
|
||||
.num_areas = ARRAY_SIZE(r8a7795_areas),
|
||||
};
|
|
@ -0,0 +1,401 @@
|
|||
/*
|
||||
* R-Car SYSC Power management support
|
||||
*
|
||||
* Copyright (C) 2014 Magnus Damm
|
||||
* Copyright (C) 2015-2016 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
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <linux/clk/renesas.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/soc/renesas/rcar-sysc.h>
|
||||
|
||||
#include "rcar-sysc.h"
|
||||
|
||||
/* SYSC Common */
|
||||
#define SYSCSR 0x00 /* SYSC Status Register */
|
||||
#define SYSCISR 0x04 /* Interrupt Status Register */
|
||||
#define SYSCISCR 0x08 /* Interrupt Status Clear Register */
|
||||
#define SYSCIER 0x0c /* Interrupt Enable Register */
|
||||
#define SYSCIMR 0x10 /* Interrupt Mask Register */
|
||||
|
||||
/* SYSC Status Register */
|
||||
#define SYSCSR_PONENB 1 /* Ready for power resume requests */
|
||||
#define SYSCSR_POFFENB 0 /* Ready for power shutoff requests */
|
||||
|
||||
/*
|
||||
* Power Control Register Offsets inside the register block for each domain
|
||||
* Note: The "CR" registers for ARM cores exist on H1 only
|
||||
* Use WFI to power off, CPG/APMU to resume ARM cores on R-Car Gen2
|
||||
* Use PSCI on R-Car Gen3
|
||||
*/
|
||||
#define PWRSR_OFFS 0x00 /* Power Status Register */
|
||||
#define PWROFFCR_OFFS 0x04 /* Power Shutoff Control Register */
|
||||
#define PWROFFSR_OFFS 0x08 /* Power Shutoff Status Register */
|
||||
#define PWRONCR_OFFS 0x0c /* Power Resume Control Register */
|
||||
#define PWRONSR_OFFS 0x10 /* Power Resume Status Register */
|
||||
#define PWRER_OFFS 0x14 /* Power Shutoff/Resume Error */
|
||||
|
||||
|
||||
#define SYSCSR_RETRIES 100
|
||||
#define SYSCSR_DELAY_US 1
|
||||
|
||||
#define PWRER_RETRIES 100
|
||||
#define PWRER_DELAY_US 1
|
||||
|
||||
#define SYSCISR_RETRIES 1000
|
||||
#define SYSCISR_DELAY_US 1
|
||||
|
||||
#define RCAR_PD_ALWAYS_ON 32 /* Always-on power area */
|
||||
|
||||
static void __iomem *rcar_sysc_base;
|
||||
static DEFINE_SPINLOCK(rcar_sysc_lock); /* SMP CPUs + I/O devices */
|
||||
|
||||
static int rcar_sysc_pwr_on_off(const struct rcar_sysc_ch *sysc_ch, bool on)
|
||||
{
|
||||
unsigned int sr_bit, reg_offs;
|
||||
int k;
|
||||
|
||||
if (on) {
|
||||
sr_bit = SYSCSR_PONENB;
|
||||
reg_offs = PWRONCR_OFFS;
|
||||
} else {
|
||||
sr_bit = SYSCSR_POFFENB;
|
||||
reg_offs = PWROFFCR_OFFS;
|
||||
}
|
||||
|
||||
/* Wait until SYSC is ready to accept a power request */
|
||||
for (k = 0; k < SYSCSR_RETRIES; k++) {
|
||||
if (ioread32(rcar_sysc_base + SYSCSR) & BIT(sr_bit))
|
||||
break;
|
||||
udelay(SYSCSR_DELAY_US);
|
||||
}
|
||||
|
||||
if (k == SYSCSR_RETRIES)
|
||||
return -EAGAIN;
|
||||
|
||||
/* Submit power shutoff or power resume request */
|
||||
iowrite32(BIT(sysc_ch->chan_bit),
|
||||
rcar_sysc_base + sysc_ch->chan_offs + reg_offs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on)
|
||||
{
|
||||
unsigned int isr_mask = BIT(sysc_ch->isr_bit);
|
||||
unsigned int chan_mask = BIT(sysc_ch->chan_bit);
|
||||
unsigned int status;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
int k;
|
||||
|
||||
spin_lock_irqsave(&rcar_sysc_lock, flags);
|
||||
|
||||
iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
|
||||
|
||||
/* Submit power shutoff or resume request until it was accepted */
|
||||
for (k = 0; k < PWRER_RETRIES; k++) {
|
||||
ret = rcar_sysc_pwr_on_off(sysc_ch, on);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
status = ioread32(rcar_sysc_base +
|
||||
sysc_ch->chan_offs + PWRER_OFFS);
|
||||
if (!(status & chan_mask))
|
||||
break;
|
||||
|
||||
udelay(PWRER_DELAY_US);
|
||||
}
|
||||
|
||||
if (k == PWRER_RETRIES) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Wait until the power shutoff or resume request has completed * */
|
||||
for (k = 0; k < SYSCISR_RETRIES; k++) {
|
||||
if (ioread32(rcar_sysc_base + SYSCISR) & isr_mask)
|
||||
break;
|
||||
udelay(SYSCISR_DELAY_US);
|
||||
}
|
||||
|
||||
if (k == SYSCISR_RETRIES)
|
||||
ret = -EIO;
|
||||
|
||||
iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&rcar_sysc_lock, flags);
|
||||
|
||||
pr_debug("sysc power %s domain %d: %08x -> %d\n", on ? "on" : "off",
|
||||
sysc_ch->isr_bit, ioread32(rcar_sysc_base + SYSCISR), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch)
|
||||
{
|
||||
return rcar_sysc_power(sysc_ch, false);
|
||||
}
|
||||
|
||||
int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch)
|
||||
{
|
||||
return rcar_sysc_power(sysc_ch, true);
|
||||
}
|
||||
|
||||
static bool rcar_sysc_power_is_off(const struct rcar_sysc_ch *sysc_ch)
|
||||
{
|
||||
unsigned int st;
|
||||
|
||||
st = ioread32(rcar_sysc_base + sysc_ch->chan_offs + PWRSR_OFFS);
|
||||
if (st & BIT(sysc_ch->chan_bit))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void __iomem *rcar_sysc_init(phys_addr_t base)
|
||||
{
|
||||
rcar_sysc_base = ioremap_nocache(base, PAGE_SIZE);
|
||||
if (!rcar_sysc_base)
|
||||
panic("unable to ioremap R-Car SYSC hardware block\n");
|
||||
|
||||
return rcar_sysc_base;
|
||||
}
|
||||
|
||||
struct rcar_sysc_pd {
|
||||
struct generic_pm_domain genpd;
|
||||
struct rcar_sysc_ch ch;
|
||||
unsigned int flags;
|
||||
char name[0];
|
||||
};
|
||||
|
||||
static inline struct rcar_sysc_pd *to_rcar_pd(struct generic_pm_domain *d)
|
||||
{
|
||||
return container_of(d, struct rcar_sysc_pd, genpd);
|
||||
}
|
||||
|
||||
static int rcar_sysc_pd_power_off(struct generic_pm_domain *genpd)
|
||||
{
|
||||
struct rcar_sysc_pd *pd = to_rcar_pd(genpd);
|
||||
|
||||
pr_debug("%s: %s\n", __func__, genpd->name);
|
||||
|
||||
if (pd->flags & PD_NO_CR) {
|
||||
pr_debug("%s: Cannot control %s\n", __func__, genpd->name);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (pd->flags & PD_BUSY) {
|
||||
pr_debug("%s: %s busy\n", __func__, genpd->name);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return rcar_sysc_power_down(&pd->ch);
|
||||
}
|
||||
|
||||
static int rcar_sysc_pd_power_on(struct generic_pm_domain *genpd)
|
||||
{
|
||||
struct rcar_sysc_pd *pd = to_rcar_pd(genpd);
|
||||
|
||||
pr_debug("%s: %s\n", __func__, genpd->name);
|
||||
|
||||
if (pd->flags & PD_NO_CR) {
|
||||
pr_debug("%s: Cannot control %s\n", __func__, genpd->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rcar_sysc_power_up(&pd->ch);
|
||||
}
|
||||
|
||||
static bool has_cpg_mstp;
|
||||
|
||||
static void __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd)
|
||||
{
|
||||
struct generic_pm_domain *genpd = &pd->genpd;
|
||||
const char *name = pd->genpd.name;
|
||||
struct dev_power_governor *gov = &simple_qos_governor;
|
||||
|
||||
if (pd->flags & PD_CPU) {
|
||||
/*
|
||||
* This domain contains a CPU core and therefore it should
|
||||
* only be turned off if the CPU is not in use.
|
||||
*/
|
||||
pr_debug("PM domain %s contains %s\n", name, "CPU");
|
||||
pd->flags |= PD_BUSY;
|
||||
gov = &pm_domain_always_on_gov;
|
||||
} else if (pd->flags & PD_SCU) {
|
||||
/*
|
||||
* This domain contains an SCU and cache-controller, and
|
||||
* therefore it should only be turned off if the CPU cores are
|
||||
* not in use.
|
||||
*/
|
||||
pr_debug("PM domain %s contains %s\n", name, "SCU");
|
||||
pd->flags |= PD_BUSY;
|
||||
gov = &pm_domain_always_on_gov;
|
||||
} else if (pd->flags & PD_NO_CR) {
|
||||
/*
|
||||
* This domain cannot be turned off.
|
||||
*/
|
||||
pd->flags |= PD_BUSY;
|
||||
gov = &pm_domain_always_on_gov;
|
||||
}
|
||||
|
||||
if (!(pd->flags & (PD_CPU | PD_SCU))) {
|
||||
/* Enable Clock Domain for I/O devices */
|
||||
genpd->flags = GENPD_FLAG_PM_CLK;
|
||||
if (has_cpg_mstp) {
|
||||
genpd->attach_dev = cpg_mstp_attach_dev;
|
||||
genpd->detach_dev = cpg_mstp_detach_dev;
|
||||
} else {
|
||||
genpd->attach_dev = cpg_mssr_attach_dev;
|
||||
genpd->detach_dev = cpg_mssr_detach_dev;
|
||||
}
|
||||
}
|
||||
|
||||
genpd->power_off = rcar_sysc_pd_power_off;
|
||||
genpd->power_on = rcar_sysc_pd_power_on;
|
||||
|
||||
if (pd->flags & (PD_CPU | PD_NO_CR)) {
|
||||
/* Skip CPUs (handled by SMP code) and areas without control */
|
||||
pr_debug("%s: Not touching %s\n", __func__, genpd->name);
|
||||
goto finalize;
|
||||
}
|
||||
|
||||
if (!rcar_sysc_power_is_off(&pd->ch)) {
|
||||
pr_debug("%s: %s is already powered\n", __func__, genpd->name);
|
||||
goto finalize;
|
||||
}
|
||||
|
||||
rcar_sysc_power_up(&pd->ch);
|
||||
|
||||
finalize:
|
||||
pm_genpd_init(genpd, gov, false);
|
||||
}
|
||||
|
||||
static const struct of_device_id rcar_sysc_matches[] = {
|
||||
#ifdef CONFIG_ARCH_R8A7779
|
||||
{ .compatible = "renesas,r8a7779-sysc", .data = &r8a7779_sysc_info },
|
||||
#endif
|
||||
#ifdef CONFIG_ARCH_R8A7790
|
||||
{ .compatible = "renesas,r8a7790-sysc", .data = &r8a7790_sysc_info },
|
||||
#endif
|
||||
#ifdef CONFIG_ARCH_R8A7791
|
||||
{ .compatible = "renesas,r8a7791-sysc", .data = &r8a7791_sysc_info },
|
||||
#endif
|
||||
#ifdef CONFIG_ARCH_R8A7793
|
||||
/* R-Car M2-N is identical to R-Car M2-W w.r.t. power domains. */
|
||||
{ .compatible = "renesas,r8a7793-sysc", .data = &r8a7791_sysc_info },
|
||||
#endif
|
||||
#ifdef CONFIG_ARCH_R8A7794
|
||||
{ .compatible = "renesas,r8a7794-sysc", .data = &r8a7794_sysc_info },
|
||||
#endif
|
||||
#ifdef CONFIG_ARCH_R8A7795
|
||||
{ .compatible = "renesas,r8a7795-sysc", .data = &r8a7795_sysc_info },
|
||||
#endif
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
struct rcar_pm_domains {
|
||||
struct genpd_onecell_data onecell_data;
|
||||
struct generic_pm_domain *domains[RCAR_PD_ALWAYS_ON + 1];
|
||||
};
|
||||
|
||||
static int __init rcar_sysc_pd_init(void)
|
||||
{
|
||||
const struct rcar_sysc_info *info;
|
||||
const struct of_device_id *match;
|
||||
struct rcar_pm_domains *domains;
|
||||
struct device_node *np;
|
||||
u32 syscier, syscimr;
|
||||
void __iomem *base;
|
||||
unsigned int i;
|
||||
int error;
|
||||
|
||||
np = of_find_matching_node_and_match(NULL, rcar_sysc_matches, &match);
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
info = match->data;
|
||||
|
||||
has_cpg_mstp = of_find_compatible_node(NULL, NULL,
|
||||
"renesas,cpg-mstp-clocks");
|
||||
|
||||
base = of_iomap(np, 0);
|
||||
if (!base) {
|
||||
pr_warn("%s: Cannot map regs\n", np->full_name);
|
||||
error = -ENOMEM;
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
rcar_sysc_base = base;
|
||||
|
||||
domains = kzalloc(sizeof(*domains), GFP_KERNEL);
|
||||
if (!domains) {
|
||||
error = -ENOMEM;
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
domains->onecell_data.domains = domains->domains;
|
||||
domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains);
|
||||
|
||||
for (i = 0, syscier = 0; i < info->num_areas; i++)
|
||||
syscier |= BIT(info->areas[i].isr_bit);
|
||||
|
||||
/*
|
||||
* Mask all interrupt sources to prevent the CPU from receiving them.
|
||||
* Make sure not to clear reserved bits that were set before.
|
||||
*/
|
||||
syscimr = ioread32(base + SYSCIMR);
|
||||
syscimr |= syscier;
|
||||
pr_debug("%s: syscimr = 0x%08x\n", np->full_name, syscimr);
|
||||
iowrite32(syscimr, base + SYSCIMR);
|
||||
|
||||
/*
|
||||
* SYSC needs all interrupt sources enabled to control power.
|
||||
*/
|
||||
pr_debug("%s: syscier = 0x%08x\n", np->full_name, syscier);
|
||||
iowrite32(syscier, base + SYSCIER);
|
||||
|
||||
for (i = 0; i < info->num_areas; i++) {
|
||||
const struct rcar_sysc_area *area = &info->areas[i];
|
||||
struct rcar_sysc_pd *pd;
|
||||
|
||||
pd = kzalloc(sizeof(*pd) + strlen(area->name) + 1, GFP_KERNEL);
|
||||
if (!pd) {
|
||||
error = -ENOMEM;
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
strcpy(pd->name, area->name);
|
||||
pd->genpd.name = pd->name;
|
||||
pd->ch.chan_offs = area->chan_offs;
|
||||
pd->ch.chan_bit = area->chan_bit;
|
||||
pd->ch.isr_bit = area->isr_bit;
|
||||
pd->flags = area->flags;
|
||||
|
||||
rcar_sysc_pd_setup(pd);
|
||||
if (area->parent >= 0)
|
||||
pm_genpd_add_subdomain(domains->domains[area->parent],
|
||||
&pd->genpd);
|
||||
|
||||
domains->domains[area->isr_bit] = &pd->genpd;
|
||||
}
|
||||
|
||||
of_genpd_add_provider_onecell(np, &domains->onecell_data);
|
||||
|
||||
out_put:
|
||||
of_node_put(np);
|
||||
return error;
|
||||
}
|
||||
early_initcall(rcar_sysc_pd_init);
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Renesas R-Car System Controller
|
||||
*
|
||||
* Copyright (C) 2016 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
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*/
|
||||
#ifndef __SOC_RENESAS_RCAR_SYSC_H__
|
||||
#define __SOC_RENESAS_RCAR_SYSC_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
|
||||
/*
|
||||
* Power Domain flags
|
||||
*/
|
||||
#define PD_CPU BIT(0) /* Area contains main CPU core */
|
||||
#define PD_SCU BIT(1) /* Area contains SCU and L2 cache */
|
||||
#define PD_NO_CR BIT(2) /* Area lacks PWR{ON,OFF}CR registers */
|
||||
|
||||
#define PD_BUSY BIT(3) /* Busy, for internal use only */
|
||||
|
||||
#define PD_CPU_CR PD_CPU /* CPU area has CR (R-Car H1) */
|
||||
#define PD_CPU_NOCR PD_CPU | PD_NO_CR /* CPU area lacks CR (R-Car Gen2/3) */
|
||||
#define PD_ALWAYS_ON PD_NO_CR /* Always-on area */
|
||||
|
||||
|
||||
/*
|
||||
* Description of a Power Area
|
||||
*/
|
||||
|
||||
struct rcar_sysc_area {
|
||||
const char *name;
|
||||
u16 chan_offs; /* Offset of PWRSR register for this area */
|
||||
u8 chan_bit; /* Bit in PWR* (except for PWRUP in PWRSR) */
|
||||
u8 isr_bit; /* Bit in SYSCI*R */
|
||||
int parent; /* -1 if none */
|
||||
unsigned int flags; /* See PD_* */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* SoC-specific Power Area Description
|
||||
*/
|
||||
|
||||
struct rcar_sysc_info {
|
||||
const struct rcar_sysc_area *areas;
|
||||
unsigned int num_areas;
|
||||
};
|
||||
|
||||
extern const struct rcar_sysc_info r8a7779_sysc_info;
|
||||
extern const struct rcar_sysc_info r8a7790_sysc_info;
|
||||
extern const struct rcar_sysc_info r8a7791_sysc_info;
|
||||
extern const struct rcar_sysc_info r8a7794_sysc_info;
|
||||
extern const struct rcar_sysc_info r8a7795_sysc_info;
|
||||
#endif /* __SOC_RENESAS_RCAR_SYSC_H__ */
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/mfd/syscon.h>
|
||||
#include <dt-bindings/power/rk3288-power.h>
|
||||
#include <dt-bindings/power/rk3368-power.h>
|
||||
#include <dt-bindings/power/rk3399-power.h>
|
||||
|
||||
struct rockchip_domain_info {
|
||||
int pwr_mask;
|
||||
|
@ -45,10 +46,20 @@ struct rockchip_pmu_info {
|
|||
const struct rockchip_domain_info *domain_info;
|
||||
};
|
||||
|
||||
#define MAX_QOS_REGS_NUM 5
|
||||
#define QOS_PRIORITY 0x08
|
||||
#define QOS_MODE 0x0c
|
||||
#define QOS_BANDWIDTH 0x10
|
||||
#define QOS_SATURATION 0x14
|
||||
#define QOS_EXTCONTROL 0x18
|
||||
|
||||
struct rockchip_pm_domain {
|
||||
struct generic_pm_domain genpd;
|
||||
const struct rockchip_domain_info *info;
|
||||
struct rockchip_pmu *pmu;
|
||||
int num_qos;
|
||||
struct regmap **qos_regmap;
|
||||
u32 *qos_save_regs[MAX_QOS_REGS_NUM];
|
||||
int num_clks;
|
||||
struct clk *clks[];
|
||||
};
|
||||
|
@ -66,11 +77,11 @@ struct rockchip_pmu {
|
|||
|
||||
#define DOMAIN(pwr, status, req, idle, ack) \
|
||||
{ \
|
||||
.pwr_mask = BIT(pwr), \
|
||||
.status_mask = BIT(status), \
|
||||
.req_mask = BIT(req), \
|
||||
.idle_mask = BIT(idle), \
|
||||
.ack_mask = BIT(ack), \
|
||||
.pwr_mask = (pwr >= 0) ? BIT(pwr) : 0, \
|
||||
.status_mask = (status >= 0) ? BIT(status) : 0, \
|
||||
.req_mask = (req >= 0) ? BIT(req) : 0, \
|
||||
.idle_mask = (idle >= 0) ? BIT(idle) : 0, \
|
||||
.ack_mask = (ack >= 0) ? BIT(ack) : 0, \
|
||||
}
|
||||
|
||||
#define DOMAIN_RK3288(pwr, status, req) \
|
||||
|
@ -79,6 +90,9 @@ struct rockchip_pmu {
|
|||
#define DOMAIN_RK3368(pwr, status, req) \
|
||||
DOMAIN(pwr, status, req, (req) + 16, req)
|
||||
|
||||
#define DOMAIN_RK3399(pwr, status, req) \
|
||||
DOMAIN(pwr, status, req, req, req)
|
||||
|
||||
static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd)
|
||||
{
|
||||
struct rockchip_pmu *pmu = pd->pmu;
|
||||
|
@ -96,6 +110,9 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
|
|||
struct rockchip_pmu *pmu = pd->pmu;
|
||||
unsigned int val;
|
||||
|
||||
if (pd_info->req_mask == 0)
|
||||
return 0;
|
||||
|
||||
regmap_update_bits(pmu->regmap, pmu->info->req_offset,
|
||||
pd_info->req_mask, idle ? -1U : 0);
|
||||
|
||||
|
@ -111,11 +128,64 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_pmu_save_qos(struct rockchip_pm_domain *pd)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pd->num_qos; i++) {
|
||||
regmap_read(pd->qos_regmap[i],
|
||||
QOS_PRIORITY,
|
||||
&pd->qos_save_regs[0][i]);
|
||||
regmap_read(pd->qos_regmap[i],
|
||||
QOS_MODE,
|
||||
&pd->qos_save_regs[1][i]);
|
||||
regmap_read(pd->qos_regmap[i],
|
||||
QOS_BANDWIDTH,
|
||||
&pd->qos_save_regs[2][i]);
|
||||
regmap_read(pd->qos_regmap[i],
|
||||
QOS_SATURATION,
|
||||
&pd->qos_save_regs[3][i]);
|
||||
regmap_read(pd->qos_regmap[i],
|
||||
QOS_EXTCONTROL,
|
||||
&pd->qos_save_regs[4][i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_pmu_restore_qos(struct rockchip_pm_domain *pd)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pd->num_qos; i++) {
|
||||
regmap_write(pd->qos_regmap[i],
|
||||
QOS_PRIORITY,
|
||||
pd->qos_save_regs[0][i]);
|
||||
regmap_write(pd->qos_regmap[i],
|
||||
QOS_MODE,
|
||||
pd->qos_save_regs[1][i]);
|
||||
regmap_write(pd->qos_regmap[i],
|
||||
QOS_BANDWIDTH,
|
||||
pd->qos_save_regs[2][i]);
|
||||
regmap_write(pd->qos_regmap[i],
|
||||
QOS_SATURATION,
|
||||
pd->qos_save_regs[3][i]);
|
||||
regmap_write(pd->qos_regmap[i],
|
||||
QOS_EXTCONTROL,
|
||||
pd->qos_save_regs[4][i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd)
|
||||
{
|
||||
struct rockchip_pmu *pmu = pd->pmu;
|
||||
unsigned int val;
|
||||
|
||||
/* check idle status for idle-only domains */
|
||||
if (pd->info->status_mask == 0)
|
||||
return !rockchip_pmu_domain_is_idle(pd);
|
||||
|
||||
regmap_read(pmu->regmap, pmu->info->status_offset, &val);
|
||||
|
||||
/* 1'b0: power on, 1'b1: power off */
|
||||
|
@ -127,6 +197,9 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
|
|||
{
|
||||
struct rockchip_pmu *pmu = pd->pmu;
|
||||
|
||||
if (pd->info->pwr_mask == 0)
|
||||
return;
|
||||
|
||||
regmap_update_bits(pmu->regmap, pmu->info->pwr_offset,
|
||||
pd->info->pwr_mask, on ? 0 : -1U);
|
||||
|
||||
|
@ -147,7 +220,7 @@ static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
|
|||
clk_enable(pd->clks[i]);
|
||||
|
||||
if (!power_on) {
|
||||
/* FIXME: add code to save AXI_QOS */
|
||||
rockchip_pmu_save_qos(pd);
|
||||
|
||||
/* if powering down, idle request to NIU first */
|
||||
rockchip_pmu_set_idle_request(pd, true);
|
||||
|
@ -159,7 +232,7 @@ static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
|
|||
/* if powering up, leave idle mode */
|
||||
rockchip_pmu_set_idle_request(pd, false);
|
||||
|
||||
/* FIXME: add code to restore AXI_QOS */
|
||||
rockchip_pmu_restore_qos(pd);
|
||||
}
|
||||
|
||||
for (i = pd->num_clks - 1; i >= 0; i--)
|
||||
|
@ -227,9 +300,10 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
|
|||
{
|
||||
const struct rockchip_domain_info *pd_info;
|
||||
struct rockchip_pm_domain *pd;
|
||||
struct device_node *qos_node;
|
||||
struct clk *clk;
|
||||
int clk_cnt;
|
||||
int i;
|
||||
int i, j;
|
||||
u32 id;
|
||||
int error;
|
||||
|
||||
|
@ -289,6 +363,45 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
|
|||
clk, node->name);
|
||||
}
|
||||
|
||||
pd->num_qos = of_count_phandle_with_args(node, "pm_qos",
|
||||
NULL);
|
||||
|
||||
if (pd->num_qos > 0) {
|
||||
pd->qos_regmap = devm_kcalloc(pmu->dev, pd->num_qos,
|
||||
sizeof(*pd->qos_regmap),
|
||||
GFP_KERNEL);
|
||||
if (!pd->qos_regmap) {
|
||||
error = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
for (j = 0; j < MAX_QOS_REGS_NUM; j++) {
|
||||
pd->qos_save_regs[j] = devm_kcalloc(pmu->dev,
|
||||
pd->num_qos,
|
||||
sizeof(u32),
|
||||
GFP_KERNEL);
|
||||
if (!pd->qos_save_regs[j]) {
|
||||
error = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < pd->num_qos; j++) {
|
||||
qos_node = of_parse_phandle(node, "pm_qos", j);
|
||||
if (!qos_node) {
|
||||
error = -ENODEV;
|
||||
goto err_out;
|
||||
}
|
||||
pd->qos_regmap[j] = syscon_node_to_regmap(qos_node);
|
||||
if (IS_ERR(pd->qos_regmap[j])) {
|
||||
error = -ENODEV;
|
||||
of_node_put(qos_node);
|
||||
goto err_out;
|
||||
}
|
||||
of_node_put(qos_node);
|
||||
}
|
||||
}
|
||||
|
||||
error = rockchip_pd_power(pd, true);
|
||||
if (error) {
|
||||
dev_err(pmu->dev,
|
||||
|
@ -360,6 +473,61 @@ static void rockchip_configure_pd_cnt(struct rockchip_pmu *pmu,
|
|||
regmap_write(pmu->regmap, domain_reg_offset + 4, count);
|
||||
}
|
||||
|
||||
static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu,
|
||||
struct device_node *parent)
|
||||
{
|
||||
struct device_node *np;
|
||||
struct generic_pm_domain *child_domain, *parent_domain;
|
||||
int error;
|
||||
|
||||
for_each_child_of_node(parent, np) {
|
||||
u32 idx;
|
||||
|
||||
error = of_property_read_u32(parent, "reg", &idx);
|
||||
if (error) {
|
||||
dev_err(pmu->dev,
|
||||
"%s: failed to retrieve domain id (reg): %d\n",
|
||||
parent->name, error);
|
||||
goto err_out;
|
||||
}
|
||||
parent_domain = pmu->genpd_data.domains[idx];
|
||||
|
||||
error = rockchip_pm_add_one_domain(pmu, np);
|
||||
if (error) {
|
||||
dev_err(pmu->dev, "failed to handle node %s: %d\n",
|
||||
np->name, error);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
error = of_property_read_u32(np, "reg", &idx);
|
||||
if (error) {
|
||||
dev_err(pmu->dev,
|
||||
"%s: failed to retrieve domain id (reg): %d\n",
|
||||
np->name, error);
|
||||
goto err_out;
|
||||
}
|
||||
child_domain = pmu->genpd_data.domains[idx];
|
||||
|
||||
error = pm_genpd_add_subdomain(parent_domain, child_domain);
|
||||
if (error) {
|
||||
dev_err(pmu->dev, "%s failed to add subdomain %s: %d\n",
|
||||
parent_domain->name, child_domain->name, error);
|
||||
goto err_out;
|
||||
} else {
|
||||
dev_dbg(pmu->dev, "%s add subdomain: %s\n",
|
||||
parent_domain->name, child_domain->name);
|
||||
}
|
||||
|
||||
rockchip_pm_add_subdomain(pmu, np);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
of_node_put(np);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int rockchip_pm_domain_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
|
@ -406,6 +574,10 @@ static int rockchip_pm_domain_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
pmu->regmap = syscon_node_to_regmap(parent->of_node);
|
||||
if (IS_ERR(pmu->regmap)) {
|
||||
dev_err(dev, "no regmap available\n");
|
||||
return PTR_ERR(pmu->regmap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure power up and down transition delays for CORE
|
||||
|
@ -426,6 +598,14 @@ static int rockchip_pm_domain_probe(struct platform_device *pdev)
|
|||
of_node_put(node);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
error = rockchip_pm_add_subdomain(pmu, node);
|
||||
if (error < 0) {
|
||||
dev_err(dev, "failed to handle subdomain node %s: %d\n",
|
||||
node->name, error);
|
||||
of_node_put(node);
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
|
@ -457,6 +637,36 @@ static const struct rockchip_domain_info rk3368_pm_domains[] = {
|
|||
[RK3368_PD_GPU_1] = DOMAIN_RK3368(17, 16, 2),
|
||||
};
|
||||
|
||||
static const struct rockchip_domain_info rk3399_pm_domains[] = {
|
||||
[RK3399_PD_TCPD0] = DOMAIN_RK3399(8, 8, -1),
|
||||
[RK3399_PD_TCPD1] = DOMAIN_RK3399(9, 9, -1),
|
||||
[RK3399_PD_CCI] = DOMAIN_RK3399(10, 10, -1),
|
||||
[RK3399_PD_CCI0] = DOMAIN_RK3399(-1, -1, 15),
|
||||
[RK3399_PD_CCI1] = DOMAIN_RK3399(-1, -1, 16),
|
||||
[RK3399_PD_PERILP] = DOMAIN_RK3399(11, 11, 1),
|
||||
[RK3399_PD_PERIHP] = DOMAIN_RK3399(12, 12, 2),
|
||||
[RK3399_PD_CENTER] = DOMAIN_RK3399(13, 13, 14),
|
||||
[RK3399_PD_VIO] = DOMAIN_RK3399(14, 14, 17),
|
||||
[RK3399_PD_GPU] = DOMAIN_RK3399(15, 15, 0),
|
||||
[RK3399_PD_VCODEC] = DOMAIN_RK3399(16, 16, 3),
|
||||
[RK3399_PD_VDU] = DOMAIN_RK3399(17, 17, 4),
|
||||
[RK3399_PD_RGA] = DOMAIN_RK3399(18, 18, 5),
|
||||
[RK3399_PD_IEP] = DOMAIN_RK3399(19, 19, 6),
|
||||
[RK3399_PD_VO] = DOMAIN_RK3399(20, 20, -1),
|
||||
[RK3399_PD_VOPB] = DOMAIN_RK3399(-1, -1, 7),
|
||||
[RK3399_PD_VOPL] = DOMAIN_RK3399(-1, -1, 8),
|
||||
[RK3399_PD_ISP0] = DOMAIN_RK3399(22, 22, 9),
|
||||
[RK3399_PD_ISP1] = DOMAIN_RK3399(23, 23, 10),
|
||||
[RK3399_PD_HDCP] = DOMAIN_RK3399(24, 24, 11),
|
||||
[RK3399_PD_GMAC] = DOMAIN_RK3399(25, 25, 23),
|
||||
[RK3399_PD_EMMC] = DOMAIN_RK3399(26, 26, 24),
|
||||
[RK3399_PD_USB3] = DOMAIN_RK3399(27, 27, 12),
|
||||
[RK3399_PD_EDP] = DOMAIN_RK3399(28, 28, 22),
|
||||
[RK3399_PD_GIC] = DOMAIN_RK3399(29, 29, 27),
|
||||
[RK3399_PD_SD] = DOMAIN_RK3399(30, 30, 28),
|
||||
[RK3399_PD_SDIOAUDIO] = DOMAIN_RK3399(31, 31, 29),
|
||||
};
|
||||
|
||||
static const struct rockchip_pmu_info rk3288_pmu = {
|
||||
.pwr_offset = 0x08,
|
||||
.status_offset = 0x0c,
|
||||
|
@ -491,6 +701,23 @@ static const struct rockchip_pmu_info rk3368_pmu = {
|
|||
.domain_info = rk3368_pm_domains,
|
||||
};
|
||||
|
||||
static const struct rockchip_pmu_info rk3399_pmu = {
|
||||
.pwr_offset = 0x14,
|
||||
.status_offset = 0x18,
|
||||
.req_offset = 0x60,
|
||||
.idle_offset = 0x64,
|
||||
.ack_offset = 0x68,
|
||||
|
||||
.core_pwrcnt_offset = 0x9c,
|
||||
.gpu_pwrcnt_offset = 0xa4,
|
||||
|
||||
.core_power_transition_time = 24,
|
||||
.gpu_power_transition_time = 24,
|
||||
|
||||
.num_domains = ARRAY_SIZE(rk3399_pm_domains),
|
||||
.domain_info = rk3399_pm_domains,
|
||||
};
|
||||
|
||||
static const struct of_device_id rockchip_pm_domain_dt_match[] = {
|
||||
{
|
||||
.compatible = "rockchip,rk3288-power-controller",
|
||||
|
@ -500,6 +727,10 @@ static const struct of_device_id rockchip_pm_domain_dt_match[] = {
|
|||
.compatible = "rockchip,rk3368-power-controller",
|
||||
.data = (void *)&rk3368_pmu,
|
||||
},
|
||||
{
|
||||
.compatible = "rockchip,rk3399-power-controller",
|
||||
.data = (void *)&rk3399_pmu,
|
||||
},
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
|
|
|
@ -28,12 +28,16 @@
|
|||
#include <linux/export.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <soc/tegra/common.h>
|
||||
|
@ -101,6 +105,16 @@
|
|||
|
||||
#define GPU_RG_CNTRL 0x2d4
|
||||
|
||||
struct tegra_powergate {
|
||||
struct generic_pm_domain genpd;
|
||||
struct tegra_pmc *pmc;
|
||||
unsigned int id;
|
||||
struct clk **clks;
|
||||
unsigned int num_clks;
|
||||
struct reset_control **resets;
|
||||
unsigned int num_resets;
|
||||
};
|
||||
|
||||
struct tegra_pmc_soc {
|
||||
unsigned int num_powergates;
|
||||
const char *const *powergates;
|
||||
|
@ -113,8 +127,11 @@ struct tegra_pmc_soc {
|
|||
|
||||
/**
|
||||
* struct tegra_pmc - NVIDIA Tegra PMC
|
||||
* @dev: pointer to PMC device structure
|
||||
* @base: pointer to I/O remapped register region
|
||||
* @clk: pointer to pclk clock
|
||||
* @soc: pointer to SoC data structure
|
||||
* @debugfs: pointer to debugfs entry
|
||||
* @rate: currently configured rate of pclk
|
||||
* @suspend_mode: lowest suspend mode available
|
||||
* @cpu_good_time: CPU power good time (in microseconds)
|
||||
|
@ -128,12 +145,14 @@ struct tegra_pmc_soc {
|
|||
* @cpu_pwr_good_en: CPU power good signal is enabled
|
||||
* @lp0_vec_phys: physical base address of the LP0 warm boot code
|
||||
* @lp0_vec_size: size of the LP0 warm boot code
|
||||
* @powergates_available: Bitmap of available power gates
|
||||
* @powergates_lock: mutex for power gate register access
|
||||
*/
|
||||
struct tegra_pmc {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
struct clk *clk;
|
||||
struct dentry *debugfs;
|
||||
|
||||
const struct tegra_pmc_soc *soc;
|
||||
|
||||
|
@ -151,6 +170,7 @@ struct tegra_pmc {
|
|||
bool cpu_pwr_good_en;
|
||||
u32 lp0_vec_phys;
|
||||
u32 lp0_vec_size;
|
||||
DECLARE_BITMAP(powergates_available, TEGRA_POWERGATE_MAX);
|
||||
|
||||
struct mutex powergates_lock;
|
||||
};
|
||||
|
@ -160,6 +180,12 @@ static struct tegra_pmc *pmc = &(struct tegra_pmc) {
|
|||
.suspend_mode = TEGRA_SUSPEND_NONE,
|
||||
};
|
||||
|
||||
static inline struct tegra_powergate *
|
||||
to_powergate(struct generic_pm_domain *domain)
|
||||
{
|
||||
return container_of(domain, struct tegra_powergate, genpd);
|
||||
}
|
||||
|
||||
static u32 tegra_pmc_readl(unsigned long offset)
|
||||
{
|
||||
return readl(pmc->base + offset);
|
||||
|
@ -170,81 +196,79 @@ static void tegra_pmc_writel(u32 value, unsigned long offset)
|
|||
writel(value, pmc->base + offset);
|
||||
}
|
||||
|
||||
static inline bool tegra_powergate_state(int id)
|
||||
{
|
||||
if (id == TEGRA_POWERGATE_3D && pmc->soc->has_gpu_clamps)
|
||||
return (tegra_pmc_readl(GPU_RG_CNTRL) & 0x1) == 0;
|
||||
else
|
||||
return (tegra_pmc_readl(PWRGATE_STATUS) & BIT(id)) != 0;
|
||||
}
|
||||
|
||||
static inline bool tegra_powergate_is_valid(int id)
|
||||
{
|
||||
return (pmc->soc && pmc->soc->powergates[id]);
|
||||
}
|
||||
|
||||
static inline bool tegra_powergate_is_available(int id)
|
||||
{
|
||||
return test_bit(id, pmc->powergates_available);
|
||||
}
|
||||
|
||||
static int tegra_powergate_lookup(struct tegra_pmc *pmc, const char *name)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!pmc || !pmc->soc || !name)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < pmc->soc->num_powergates; i++) {
|
||||
if (!tegra_powergate_is_valid(i))
|
||||
continue;
|
||||
|
||||
if (!strcmp(name, pmc->soc->powergates[i]))
|
||||
return i;
|
||||
}
|
||||
|
||||
dev_err(pmc->dev, "powergate %s not found\n", name);
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/**
|
||||
* tegra_powergate_set() - set the state of a partition
|
||||
* @id: partition ID
|
||||
* @new_state: new state of the partition
|
||||
*/
|
||||
static int tegra_powergate_set(int id, bool new_state)
|
||||
static int tegra_powergate_set(unsigned int id, bool new_state)
|
||||
{
|
||||
bool status;
|
||||
int err;
|
||||
|
||||
if (id == TEGRA_POWERGATE_3D && pmc->soc->has_gpu_clamps)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&pmc->powergates_lock);
|
||||
|
||||
status = tegra_pmc_readl(PWRGATE_STATUS) & (1 << id);
|
||||
|
||||
if (status == new_state) {
|
||||
if (tegra_powergate_state(id) == new_state) {
|
||||
mutex_unlock(&pmc->powergates_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tegra_pmc_writel(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
|
||||
|
||||
err = readx_poll_timeout(tegra_powergate_state, id, status,
|
||||
status == new_state, 10, 100000);
|
||||
|
||||
mutex_unlock(&pmc->powergates_lock);
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* tegra_powergate_power_on() - power on partition
|
||||
* @id: partition ID
|
||||
*/
|
||||
int tegra_powergate_power_on(int id)
|
||||
{
|
||||
if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates)
|
||||
return -EINVAL;
|
||||
|
||||
return tegra_powergate_set(id, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* tegra_powergate_power_off() - power off partition
|
||||
* @id: partition ID
|
||||
*/
|
||||
int tegra_powergate_power_off(int id)
|
||||
{
|
||||
if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates)
|
||||
return -EINVAL;
|
||||
|
||||
return tegra_powergate_set(id, false);
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_powergate_power_off);
|
||||
|
||||
/**
|
||||
* tegra_powergate_is_powered() - check if partition is powered
|
||||
* @id: partition ID
|
||||
*/
|
||||
int tegra_powergate_is_powered(int id)
|
||||
{
|
||||
u32 status;
|
||||
|
||||
if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates)
|
||||
return -EINVAL;
|
||||
|
||||
status = tegra_pmc_readl(PWRGATE_STATUS) & (1 << id);
|
||||
return !!status;
|
||||
}
|
||||
|
||||
/**
|
||||
* tegra_powergate_remove_clamping() - remove power clamps for partition
|
||||
* @id: partition ID
|
||||
*/
|
||||
int tegra_powergate_remove_clamping(int id)
|
||||
static int __tegra_powergate_remove_clamping(unsigned int id)
|
||||
{
|
||||
u32 mask;
|
||||
|
||||
if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates)
|
||||
return -EINVAL;
|
||||
mutex_lock(&pmc->powergates_lock);
|
||||
|
||||
/*
|
||||
* On Tegra124 and later, the clamps for the GPU are controlled by a
|
||||
|
@ -253,7 +277,7 @@ int tegra_powergate_remove_clamping(int id)
|
|||
if (id == TEGRA_POWERGATE_3D) {
|
||||
if (pmc->soc->has_gpu_clamps) {
|
||||
tegra_pmc_writel(0, GPU_RG_CNTRL);
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -270,8 +294,236 @@ int tegra_powergate_remove_clamping(int id)
|
|||
|
||||
tegra_pmc_writel(mask, REMOVE_CLAMPING);
|
||||
|
||||
out:
|
||||
mutex_unlock(&pmc->powergates_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tegra_powergate_disable_clocks(struct tegra_powergate *pg)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < pg->num_clks; i++)
|
||||
clk_disable_unprepare(pg->clks[i]);
|
||||
}
|
||||
|
||||
static int tegra_powergate_enable_clocks(struct tegra_powergate *pg)
|
||||
{
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
for (i = 0; i < pg->num_clks; i++) {
|
||||
err = clk_prepare_enable(pg->clks[i]);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
while (i--)
|
||||
clk_disable_unprepare(pg->clks[i]);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int tegra_powergate_reset_assert(struct tegra_powergate *pg)
|
||||
{
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
for (i = 0; i < pg->num_resets; i++) {
|
||||
err = reset_control_assert(pg->resets[i]);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_powergate_reset_deassert(struct tegra_powergate *pg)
|
||||
{
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
for (i = 0; i < pg->num_resets; i++) {
|
||||
err = reset_control_deassert(pg->resets[i]);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_powergate_power_up(struct tegra_powergate *pg,
|
||||
bool disable_clocks)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = tegra_powergate_reset_assert(pg);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
usleep_range(10, 20);
|
||||
|
||||
err = tegra_powergate_set(pg->id, true);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
usleep_range(10, 20);
|
||||
|
||||
err = tegra_powergate_enable_clocks(pg);
|
||||
if (err)
|
||||
goto disable_clks;
|
||||
|
||||
usleep_range(10, 20);
|
||||
|
||||
err = __tegra_powergate_remove_clamping(pg->id);
|
||||
if (err)
|
||||
goto disable_clks;
|
||||
|
||||
usleep_range(10, 20);
|
||||
|
||||
err = tegra_powergate_reset_deassert(pg);
|
||||
if (err)
|
||||
goto powergate_off;
|
||||
|
||||
usleep_range(10, 20);
|
||||
|
||||
if (disable_clocks)
|
||||
tegra_powergate_disable_clocks(pg);
|
||||
|
||||
return 0;
|
||||
|
||||
disable_clks:
|
||||
tegra_powergate_disable_clocks(pg);
|
||||
usleep_range(10, 20);
|
||||
powergate_off:
|
||||
tegra_powergate_set(pg->id, false);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int tegra_powergate_power_down(struct tegra_powergate *pg)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = tegra_powergate_enable_clocks(pg);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
usleep_range(10, 20);
|
||||
|
||||
err = tegra_powergate_reset_assert(pg);
|
||||
if (err)
|
||||
goto disable_clks;
|
||||
|
||||
usleep_range(10, 20);
|
||||
|
||||
tegra_powergate_disable_clocks(pg);
|
||||
|
||||
usleep_range(10, 20);
|
||||
|
||||
err = tegra_powergate_set(pg->id, false);
|
||||
if (err)
|
||||
goto assert_resets;
|
||||
|
||||
return 0;
|
||||
|
||||
assert_resets:
|
||||
tegra_powergate_enable_clocks(pg);
|
||||
usleep_range(10, 20);
|
||||
tegra_powergate_reset_deassert(pg);
|
||||
usleep_range(10, 20);
|
||||
disable_clks:
|
||||
tegra_powergate_disable_clocks(pg);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int tegra_genpd_power_on(struct generic_pm_domain *domain)
|
||||
{
|
||||
struct tegra_powergate *pg = to_powergate(domain);
|
||||
struct tegra_pmc *pmc = pg->pmc;
|
||||
int err;
|
||||
|
||||
err = tegra_powergate_power_up(pg, true);
|
||||
if (err)
|
||||
dev_err(pmc->dev, "failed to turn on PM domain %s: %d\n",
|
||||
pg->genpd.name, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int tegra_genpd_power_off(struct generic_pm_domain *domain)
|
||||
{
|
||||
struct tegra_powergate *pg = to_powergate(domain);
|
||||
struct tegra_pmc *pmc = pg->pmc;
|
||||
int err;
|
||||
|
||||
err = tegra_powergate_power_down(pg);
|
||||
if (err)
|
||||
dev_err(pmc->dev, "failed to turn off PM domain %s: %d\n",
|
||||
pg->genpd.name, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* tegra_powergate_power_on() - power on partition
|
||||
* @id: partition ID
|
||||
*/
|
||||
int tegra_powergate_power_on(unsigned int id)
|
||||
{
|
||||
if (!tegra_powergate_is_available(id))
|
||||
return -EINVAL;
|
||||
|
||||
return tegra_powergate_set(id, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* tegra_powergate_power_off() - power off partition
|
||||
* @id: partition ID
|
||||
*/
|
||||
int tegra_powergate_power_off(unsigned int id)
|
||||
{
|
||||
if (!tegra_powergate_is_available(id))
|
||||
return -EINVAL;
|
||||
|
||||
return tegra_powergate_set(id, false);
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_powergate_power_off);
|
||||
|
||||
/**
|
||||
* tegra_powergate_is_powered() - check if partition is powered
|
||||
* @id: partition ID
|
||||
*/
|
||||
int tegra_powergate_is_powered(unsigned int id)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (!tegra_powergate_is_valid(id))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&pmc->powergates_lock);
|
||||
status = tegra_powergate_state(id);
|
||||
mutex_unlock(&pmc->powergates_lock);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* tegra_powergate_remove_clamping() - remove power clamps for partition
|
||||
* @id: partition ID
|
||||
*/
|
||||
int tegra_powergate_remove_clamping(unsigned int id)
|
||||
{
|
||||
if (!tegra_powergate_is_available(id))
|
||||
return -EINVAL;
|
||||
|
||||
return __tegra_powergate_remove_clamping(id);
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_powergate_remove_clamping);
|
||||
|
||||
/**
|
||||
|
@ -282,38 +534,23 @@ EXPORT_SYMBOL(tegra_powergate_remove_clamping);
|
|||
*
|
||||
* Must be called with clk disabled, and returns with clk enabled.
|
||||
*/
|
||||
int tegra_powergate_sequence_power_up(int id, struct clk *clk,
|
||||
int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
|
||||
struct reset_control *rst)
|
||||
{
|
||||
int ret;
|
||||
struct tegra_powergate pg;
|
||||
int err;
|
||||
|
||||
reset_control_assert(rst);
|
||||
pg.id = id;
|
||||
pg.clks = &clk;
|
||||
pg.num_clks = 1;
|
||||
pg.resets = &rst;
|
||||
pg.num_resets = 1;
|
||||
|
||||
ret = tegra_powergate_power_on(id);
|
||||
if (ret)
|
||||
goto err_power;
|
||||
err = tegra_powergate_power_up(&pg, false);
|
||||
if (err)
|
||||
pr_err("failed to turn on partition %d: %d\n", id, err);
|
||||
|
||||
ret = clk_prepare_enable(clk);
|
||||
if (ret)
|
||||
goto err_clk;
|
||||
|
||||
usleep_range(10, 20);
|
||||
|
||||
ret = tegra_powergate_remove_clamping(id);
|
||||
if (ret)
|
||||
goto err_clamp;
|
||||
|
||||
usleep_range(10, 20);
|
||||
reset_control_deassert(rst);
|
||||
|
||||
return 0;
|
||||
|
||||
err_clamp:
|
||||
clk_disable_unprepare(clk);
|
||||
err_clk:
|
||||
tegra_powergate_power_off(id);
|
||||
err_power:
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_powergate_sequence_power_up);
|
||||
|
||||
|
@ -325,9 +562,9 @@ EXPORT_SYMBOL(tegra_powergate_sequence_power_up);
|
|||
* Returns the partition ID corresponding to the CPU partition ID or a
|
||||
* negative error code on failure.
|
||||
*/
|
||||
static int tegra_get_cpu_powergate_id(int cpuid)
|
||||
static int tegra_get_cpu_powergate_id(unsigned int cpuid)
|
||||
{
|
||||
if (pmc->soc && cpuid > 0 && cpuid < pmc->soc->num_cpu_powergates)
|
||||
if (pmc->soc && cpuid < pmc->soc->num_cpu_powergates)
|
||||
return pmc->soc->cpu_powergates[cpuid];
|
||||
|
||||
return -EINVAL;
|
||||
|
@ -337,7 +574,7 @@ static int tegra_get_cpu_powergate_id(int cpuid)
|
|||
* tegra_pmc_cpu_is_powered() - check if CPU partition is powered
|
||||
* @cpuid: CPU partition ID
|
||||
*/
|
||||
bool tegra_pmc_cpu_is_powered(int cpuid)
|
||||
bool tegra_pmc_cpu_is_powered(unsigned int cpuid)
|
||||
{
|
||||
int id;
|
||||
|
||||
|
@ -352,7 +589,7 @@ bool tegra_pmc_cpu_is_powered(int cpuid)
|
|||
* tegra_pmc_cpu_power_on() - power on CPU partition
|
||||
* @cpuid: CPU partition ID
|
||||
*/
|
||||
int tegra_pmc_cpu_power_on(int cpuid)
|
||||
int tegra_pmc_cpu_power_on(unsigned int cpuid)
|
||||
{
|
||||
int id;
|
||||
|
||||
|
@ -367,7 +604,7 @@ int tegra_pmc_cpu_power_on(int cpuid)
|
|||
* tegra_pmc_cpu_remove_clamping() - remove power clamps for CPU partition
|
||||
* @cpuid: CPU partition ID
|
||||
*/
|
||||
int tegra_pmc_cpu_remove_clamping(int cpuid)
|
||||
int tegra_pmc_cpu_remove_clamping(unsigned int cpuid)
|
||||
{
|
||||
int id;
|
||||
|
||||
|
@ -416,16 +653,18 @@ static struct notifier_block tegra_pmc_restart_handler = {
|
|||
static int powergate_show(struct seq_file *s, void *data)
|
||||
{
|
||||
unsigned int i;
|
||||
int status;
|
||||
|
||||
seq_printf(s, " powergate powered\n");
|
||||
seq_printf(s, "------------------\n");
|
||||
|
||||
for (i = 0; i < pmc->soc->num_powergates; i++) {
|
||||
if (!pmc->soc->powergates[i])
|
||||
status = tegra_powergate_is_powered(i);
|
||||
if (status < 0)
|
||||
continue;
|
||||
|
||||
seq_printf(s, " %9s %7s\n", pmc->soc->powergates[i],
|
||||
tegra_powergate_is_powered(i) ? "yes" : "no");
|
||||
status ? "yes" : "no");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -445,17 +684,164 @@ static const struct file_operations powergate_fops = {
|
|||
|
||||
static int tegra_powergate_debugfs_init(void)
|
||||
{
|
||||
struct dentry *d;
|
||||
|
||||
d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
|
||||
pmc->debugfs = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
|
||||
&powergate_fops);
|
||||
if (!d)
|
||||
if (!pmc->debugfs)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_io_rail_prepare(int id, unsigned long *request,
|
||||
static int tegra_powergate_of_get_clks(struct tegra_powergate *pg,
|
||||
struct device_node *np)
|
||||
{
|
||||
struct clk *clk;
|
||||
unsigned int i, count;
|
||||
int err;
|
||||
|
||||
count = of_count_phandle_with_args(np, "clocks", "#clock-cells");
|
||||
if (count == 0)
|
||||
return -ENODEV;
|
||||
|
||||
pg->clks = kcalloc(count, sizeof(clk), GFP_KERNEL);
|
||||
if (!pg->clks)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
pg->clks[i] = of_clk_get(np, i);
|
||||
if (IS_ERR(pg->clks[i])) {
|
||||
err = PTR_ERR(pg->clks[i]);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
pg->num_clks = count;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
while (i--)
|
||||
clk_put(pg->clks[i]);
|
||||
kfree(pg->clks);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int tegra_powergate_of_get_resets(struct tegra_powergate *pg,
|
||||
struct device_node *np)
|
||||
{
|
||||
struct reset_control *rst;
|
||||
unsigned int i, count;
|
||||
int err;
|
||||
|
||||
count = of_count_phandle_with_args(np, "resets", "#reset-cells");
|
||||
if (count == 0)
|
||||
return -ENODEV;
|
||||
|
||||
pg->resets = kcalloc(count, sizeof(rst), GFP_KERNEL);
|
||||
if (!pg->resets)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
pg->resets[i] = of_reset_control_get_by_index(np, i);
|
||||
if (IS_ERR(pg->resets[i])) {
|
||||
err = PTR_ERR(pg->resets[i]);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
pg->num_resets = count;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
while (i--)
|
||||
reset_control_put(pg->resets[i]);
|
||||
kfree(pg->resets);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
|
||||
{
|
||||
struct tegra_powergate *pg;
|
||||
bool off;
|
||||
int id;
|
||||
|
||||
pg = kzalloc(sizeof(*pg), GFP_KERNEL);
|
||||
if (!pg)
|
||||
goto error;
|
||||
|
||||
id = tegra_powergate_lookup(pmc, np->name);
|
||||
if (id < 0)
|
||||
goto free_mem;
|
||||
|
||||
/*
|
||||
* Clear the bit for this powergate so it cannot be managed
|
||||
* directly via the legacy APIs for controlling powergates.
|
||||
*/
|
||||
clear_bit(id, pmc->powergates_available);
|
||||
|
||||
pg->id = id;
|
||||
pg->genpd.name = np->name;
|
||||
pg->genpd.power_off = tegra_genpd_power_off;
|
||||
pg->genpd.power_on = tegra_genpd_power_on;
|
||||
pg->pmc = pmc;
|
||||
|
||||
if (tegra_powergate_of_get_clks(pg, np))
|
||||
goto set_available;
|
||||
|
||||
if (tegra_powergate_of_get_resets(pg, np))
|
||||
goto remove_clks;
|
||||
|
||||
off = !tegra_powergate_is_powered(pg->id);
|
||||
|
||||
pm_genpd_init(&pg->genpd, NULL, off);
|
||||
|
||||
if (of_genpd_add_provider_simple(np, &pg->genpd))
|
||||
goto remove_resets;
|
||||
|
||||
dev_dbg(pmc->dev, "added power domain %s\n", pg->genpd.name);
|
||||
|
||||
return;
|
||||
|
||||
remove_resets:
|
||||
while (pg->num_resets--)
|
||||
reset_control_put(pg->resets[pg->num_resets]);
|
||||
kfree(pg->resets);
|
||||
|
||||
remove_clks:
|
||||
while (pg->num_clks--)
|
||||
clk_put(pg->clks[pg->num_clks]);
|
||||
kfree(pg->clks);
|
||||
|
||||
set_available:
|
||||
set_bit(id, pmc->powergates_available);
|
||||
|
||||
free_mem:
|
||||
kfree(pg);
|
||||
|
||||
error:
|
||||
dev_err(pmc->dev, "failed to create power domain for %s\n", np->name);
|
||||
}
|
||||
|
||||
static void tegra_powergate_init(struct tegra_pmc *pmc)
|
||||
{
|
||||
struct device_node *np, *child;
|
||||
|
||||
np = of_get_child_by_name(pmc->dev->of_node, "powergates");
|
||||
if (!np)
|
||||
return;
|
||||
|
||||
for_each_child_of_node(np, child) {
|
||||
tegra_powergate_add(pmc, child);
|
||||
of_node_put(child);
|
||||
}
|
||||
|
||||
of_node_put(np);
|
||||
}
|
||||
|
||||
static int tegra_io_rail_prepare(unsigned int id, unsigned long *request,
|
||||
unsigned long *status, unsigned int *bit)
|
||||
{
|
||||
unsigned long rate, value;
|
||||
|
@ -512,15 +898,17 @@ static void tegra_io_rail_unprepare(void)
|
|||
tegra_pmc_writel(DPD_SAMPLE_DISABLE, DPD_SAMPLE);
|
||||
}
|
||||
|
||||
int tegra_io_rail_power_on(int id)
|
||||
int tegra_io_rail_power_on(unsigned int id)
|
||||
{
|
||||
unsigned long request, status, value;
|
||||
unsigned int bit, mask;
|
||||
int err;
|
||||
|
||||
mutex_lock(&pmc->powergates_lock);
|
||||
|
||||
err = tegra_io_rail_prepare(id, &request, &status, &bit);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
mask = 1 << bit;
|
||||
|
||||
|
@ -531,27 +919,32 @@ int tegra_io_rail_power_on(int id)
|
|||
tegra_pmc_writel(value, request);
|
||||
|
||||
err = tegra_io_rail_poll(status, mask, 0, 250);
|
||||
if (err < 0) {
|
||||
if (err) {
|
||||
pr_info("tegra_io_rail_poll() failed: %d\n", err);
|
||||
return err;
|
||||
goto error;
|
||||
}
|
||||
|
||||
tegra_io_rail_unprepare();
|
||||
|
||||
return 0;
|
||||
error:
|
||||
mutex_unlock(&pmc->powergates_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_io_rail_power_on);
|
||||
|
||||
int tegra_io_rail_power_off(int id)
|
||||
int tegra_io_rail_power_off(unsigned int id)
|
||||
{
|
||||
unsigned long request, status, value;
|
||||
unsigned int bit, mask;
|
||||
int err;
|
||||
|
||||
mutex_lock(&pmc->powergates_lock);
|
||||
|
||||
err = tegra_io_rail_prepare(id, &request, &status, &bit);
|
||||
if (err < 0) {
|
||||
if (err) {
|
||||
pr_info("tegra_io_rail_prepare() failed: %d\n", err);
|
||||
return err;
|
||||
goto error;
|
||||
}
|
||||
|
||||
mask = 1 << bit;
|
||||
|
@ -563,12 +956,15 @@ int tegra_io_rail_power_off(int id)
|
|||
tegra_pmc_writel(value, request);
|
||||
|
||||
err = tegra_io_rail_poll(status, mask, mask, 250);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
tegra_io_rail_unprepare();
|
||||
|
||||
return 0;
|
||||
error:
|
||||
mutex_unlock(&pmc->powergates_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_io_rail_power_off);
|
||||
|
||||
|
@ -727,7 +1123,7 @@ static void tegra_pmc_init(struct tegra_pmc *pmc)
|
|||
tegra_pmc_writel(value, PMC_CNTRL);
|
||||
}
|
||||
|
||||
void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc)
|
||||
static void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc)
|
||||
{
|
||||
static const char disabled[] = "emergency thermal reset disabled";
|
||||
u32 pmu_addr, ctrl_id, reg_addr, reg_data, pinmux;
|
||||
|
@ -805,7 +1201,7 @@ void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc)
|
|||
|
||||
static int tegra_pmc_probe(struct platform_device *pdev)
|
||||
{
|
||||
void __iomem *base = pmc->base;
|
||||
void __iomem *base;
|
||||
struct resource *res;
|
||||
int err;
|
||||
|
||||
|
@ -815,11 +1211,9 @@ static int tegra_pmc_probe(struct platform_device *pdev)
|
|||
|
||||
/* take over the memory region from the early initialization */
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
pmc->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(pmc->base))
|
||||
return PTR_ERR(pmc->base);
|
||||
|
||||
iounmap(base);
|
||||
base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
pmc->clk = devm_clk_get(&pdev->dev, "pclk");
|
||||
if (IS_ERR(pmc->clk)) {
|
||||
|
@ -842,11 +1236,19 @@ static int tegra_pmc_probe(struct platform_device *pdev)
|
|||
|
||||
err = register_restart_handler(&tegra_pmc_restart_handler);
|
||||
if (err) {
|
||||
debugfs_remove(pmc->debugfs);
|
||||
dev_err(&pdev->dev, "unable to register restart handler, %d\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
|
||||
tegra_powergate_init(pmc);
|
||||
|
||||
mutex_lock(&pmc->powergates_lock);
|
||||
iounmap(pmc->base);
|
||||
pmc->base = base;
|
||||
mutex_unlock(&pmc->powergates_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -964,7 +1366,6 @@ static const char * const tegra124_powergates[] = {
|
|||
[TEGRA_POWERGATE_VENC] = "venc",
|
||||
[TEGRA_POWERGATE_PCIE] = "pcie",
|
||||
[TEGRA_POWERGATE_VDEC] = "vdec",
|
||||
[TEGRA_POWERGATE_L2] = "l2",
|
||||
[TEGRA_POWERGATE_MPE] = "mpe",
|
||||
[TEGRA_POWERGATE_HEG] = "heg",
|
||||
[TEGRA_POWERGATE_SATA] = "sata",
|
||||
|
@ -1006,17 +1407,13 @@ static const char * const tegra210_powergates[] = {
|
|||
[TEGRA_POWERGATE_3D] = "3d",
|
||||
[TEGRA_POWERGATE_VENC] = "venc",
|
||||
[TEGRA_POWERGATE_PCIE] = "pcie",
|
||||
[TEGRA_POWERGATE_L2] = "l2",
|
||||
[TEGRA_POWERGATE_MPE] = "mpe",
|
||||
[TEGRA_POWERGATE_HEG] = "heg",
|
||||
[TEGRA_POWERGATE_SATA] = "sata",
|
||||
[TEGRA_POWERGATE_CPU1] = "cpu1",
|
||||
[TEGRA_POWERGATE_CPU2] = "cpu2",
|
||||
[TEGRA_POWERGATE_CPU3] = "cpu3",
|
||||
[TEGRA_POWERGATE_CELP] = "celp",
|
||||
[TEGRA_POWERGATE_CPU0] = "cpu0",
|
||||
[TEGRA_POWERGATE_C0NC] = "c0nc",
|
||||
[TEGRA_POWERGATE_C1NC] = "c1nc",
|
||||
[TEGRA_POWERGATE_SOR] = "sor",
|
||||
[TEGRA_POWERGATE_DIS] = "dis",
|
||||
[TEGRA_POWERGATE_DISB] = "disb",
|
||||
|
@ -1080,6 +1477,7 @@ static int __init tegra_pmc_early_init(void)
|
|||
const struct of_device_id *match;
|
||||
struct device_node *np;
|
||||
struct resource regs;
|
||||
unsigned int i;
|
||||
bool invert;
|
||||
u32 value;
|
||||
|
||||
|
@ -1129,6 +1527,11 @@ static int __init tegra_pmc_early_init(void)
|
|||
return -ENXIO;
|
||||
}
|
||||
|
||||
/* Create a bit-map of the available and valid partitions */
|
||||
for (i = 0; i < pmc->soc->num_powergates; i++)
|
||||
if (pmc->soc->powergates[i])
|
||||
set_bit(i, pmc->powergates_available);
|
||||
|
||||
mutex_init(&pmc->powergates_lock);
|
||||
|
||||
/*
|
||||
|
|
|
@ -69,6 +69,15 @@ config USB_XHCI_RCAR
|
|||
Say 'Y' to enable the support for the xHCI host controller
|
||||
found in Renesas R-Car ARM SoCs.
|
||||
|
||||
config USB_XHCI_TEGRA
|
||||
tristate "xHCI support for NVIDIA Tegra SoCs"
|
||||
depends on PHY_TEGRA_XUSB
|
||||
depends on RESET_CONTROLLER
|
||||
select FW_LOADER
|
||||
---help---
|
||||
Say 'Y' to enable the support for the xHCI host controller
|
||||
found in NVIDIA Tegra124 and later SoCs.
|
||||
|
||||
endif # USB_XHCI_HCD
|
||||
|
||||
config USB_EHCI_HCD
|
||||
|
|
|
@ -68,6 +68,7 @@ obj-$(CONFIG_USB_XHCI_HCD) += xhci-hcd.o
|
|||
obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o
|
||||
obj-$(CONFIG_USB_XHCI_PLATFORM) += xhci-plat-hcd.o
|
||||
obj-$(CONFIG_USB_XHCI_MTK) += xhci-mtk.o
|
||||
obj-$(CONFIG_USB_XHCI_TEGRA) += xhci-tegra.o
|
||||
obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o
|
||||
obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o
|
||||
obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,53 @@
|
|||
#ifndef __DT_BINDINGS_POWER_RK3399_POWER_H__
|
||||
#define __DT_BINDINGS_POWER_RK3399_POWER_H__
|
||||
|
||||
/* VD_CORE_L */
|
||||
#define RK3399_PD_A53_L0 0
|
||||
#define RK3399_PD_A53_L1 1
|
||||
#define RK3399_PD_A53_L2 2
|
||||
#define RK3399_PD_A53_L3 3
|
||||
#define RK3399_PD_SCU_L 4
|
||||
|
||||
/* VD_CORE_B */
|
||||
#define RK3399_PD_A72_B0 5
|
||||
#define RK3399_PD_A72_B1 6
|
||||
#define RK3399_PD_SCU_B 7
|
||||
|
||||
/* VD_LOGIC */
|
||||
#define RK3399_PD_TCPD0 8
|
||||
#define RK3399_PD_TCPD1 9
|
||||
#define RK3399_PD_CCI 10
|
||||
#define RK3399_PD_CCI0 11
|
||||
#define RK3399_PD_CCI1 12
|
||||
#define RK3399_PD_PERILP 13
|
||||
#define RK3399_PD_PERIHP 14
|
||||
#define RK3399_PD_VIO 15
|
||||
#define RK3399_PD_VO 16
|
||||
#define RK3399_PD_VOPB 17
|
||||
#define RK3399_PD_VOPL 18
|
||||
#define RK3399_PD_ISP0 19
|
||||
#define RK3399_PD_ISP1 20
|
||||
#define RK3399_PD_HDCP 21
|
||||
#define RK3399_PD_GMAC 22
|
||||
#define RK3399_PD_EMMC 23
|
||||
#define RK3399_PD_USB3 24
|
||||
#define RK3399_PD_EDP 25
|
||||
#define RK3399_PD_GIC 26
|
||||
#define RK3399_PD_SD 27
|
||||
#define RK3399_PD_SDIOAUDIO 28
|
||||
#define RK3399_PD_ALIVE 29
|
||||
|
||||
/* VD_CENTER */
|
||||
#define RK3399_PD_CENTER 30
|
||||
#define RK3399_PD_VCODEC 31
|
||||
#define RK3399_PD_VDU 32
|
||||
#define RK3399_PD_RGA 33
|
||||
#define RK3399_PD_IEP 34
|
||||
|
||||
/* VD_GPU */
|
||||
#define RK3399_PD_GPU 35
|
||||
|
||||
/* VD_PMU */
|
||||
#define RK3399_PD_PMU 36
|
||||
|
||||
#endif
|
|
@ -24,12 +24,20 @@ void r8a7778_clocks_init(u32 mode);
|
|||
void r8a7779_clocks_init(u32 mode);
|
||||
void rcar_gen2_clocks_init(u32 mode);
|
||||
|
||||
#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
|
||||
void cpg_mstp_add_clk_domain(struct device_node *np);
|
||||
int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev);
|
||||
void cpg_mstp_detach_dev(struct generic_pm_domain *domain, struct device *dev);
|
||||
#ifdef CONFIG_CLK_RENESAS_CPG_MSTP
|
||||
int cpg_mstp_attach_dev(struct generic_pm_domain *unused, struct device *dev);
|
||||
void cpg_mstp_detach_dev(struct generic_pm_domain *unused, struct device *dev);
|
||||
#else
|
||||
static inline void cpg_mstp_add_clk_domain(struct device_node *np) {}
|
||||
#define cpg_mstp_attach_dev NULL
|
||||
#define cpg_mstp_detach_dev NULL
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CLK_RENESAS_CPG_MSSR
|
||||
int cpg_mssr_attach_dev(struct generic_pm_domain *unused, struct device *dev);
|
||||
void cpg_mssr_detach_dev(struct generic_pm_domain *unused, struct device *dev);
|
||||
#else
|
||||
#define cpg_mssr_attach_dev NULL
|
||||
#define cpg_mssr_detach_dev NULL
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -121,4 +121,9 @@ static inline void tegra_cpu_clock_resume(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
extern void tegra210_xusb_pll_hw_control_enable(void);
|
||||
extern void tegra210_xusb_pll_hw_sequence_start(void);
|
||||
extern void tegra210_sata_pll_hw_control_enable(void);
|
||||
extern void tegra210_sata_pll_hw_sequence_start(void);
|
||||
|
||||
#endif /* __LINUX_CLK_TEGRA_H_ */
|
||||
|
|
|
@ -77,6 +77,7 @@ struct phy {
|
|||
*/
|
||||
struct phy_provider {
|
||||
struct device *dev;
|
||||
struct device_node *children;
|
||||
struct module *owner;
|
||||
struct list_head list;
|
||||
struct phy * (*of_xlate)(struct device *dev,
|
||||
|
@ -93,10 +94,16 @@ struct phy_lookup {
|
|||
#define to_phy(a) (container_of((a), struct phy, dev))
|
||||
|
||||
#define of_phy_provider_register(dev, xlate) \
|
||||
__of_phy_provider_register((dev), THIS_MODULE, (xlate))
|
||||
__of_phy_provider_register((dev), NULL, THIS_MODULE, (xlate))
|
||||
|
||||
#define devm_of_phy_provider_register(dev, xlate) \
|
||||
__devm_of_phy_provider_register((dev), THIS_MODULE, (xlate))
|
||||
__devm_of_phy_provider_register((dev), NULL, THIS_MODULE, (xlate))
|
||||
|
||||
#define of_phy_provider_register_full(dev, children, xlate) \
|
||||
__of_phy_provider_register(dev, children, THIS_MODULE, xlate)
|
||||
|
||||
#define devm_of_phy_provider_register_full(dev, children, xlate) \
|
||||
__devm_of_phy_provider_register(dev, children, THIS_MODULE, xlate)
|
||||
|
||||
static inline void phy_set_drvdata(struct phy *phy, void *data)
|
||||
{
|
||||
|
@ -147,10 +154,12 @@ struct phy *devm_phy_create(struct device *dev, struct device_node *node,
|
|||
void phy_destroy(struct phy *phy);
|
||||
void devm_phy_destroy(struct device *dev, struct phy *phy);
|
||||
struct phy_provider *__of_phy_provider_register(struct device *dev,
|
||||
struct module *owner, struct phy * (*of_xlate)(struct device *dev,
|
||||
struct device_node *children, struct module *owner,
|
||||
struct phy * (*of_xlate)(struct device *dev,
|
||||
struct of_phandle_args *args));
|
||||
struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
|
||||
struct module *owner, struct phy * (*of_xlate)(struct device *dev,
|
||||
struct device_node *children, struct module *owner,
|
||||
struct phy * (*of_xlate)(struct device *dev,
|
||||
struct of_phandle_args *args));
|
||||
void of_phy_provider_unregister(struct phy_provider *phy_provider);
|
||||
void devm_of_phy_provider_unregister(struct device *dev,
|
||||
|
@ -312,14 +321,16 @@ static inline void devm_phy_destroy(struct device *dev, struct phy *phy)
|
|||
}
|
||||
|
||||
static inline struct phy_provider *__of_phy_provider_register(
|
||||
struct device *dev, struct module *owner, struct phy * (*of_xlate)(
|
||||
struct device *dev, struct of_phandle_args *args))
|
||||
struct device *dev, struct device_node *children, struct module *owner,
|
||||
struct phy * (*of_xlate)(struct device *dev,
|
||||
struct of_phandle_args *args))
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline struct phy_provider *__devm_of_phy_provider_register(struct device
|
||||
*dev, struct module *owner, struct phy * (*of_xlate)(struct device *dev,
|
||||
*dev, struct device_node *children, struct module *owner,
|
||||
struct phy * (*of_xlate)(struct device *dev,
|
||||
struct of_phandle_args *args))
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef PHY_TEGRA_XUSB_H
|
||||
#define PHY_TEGRA_XUSB_H
|
||||
|
||||
struct tegra_xusb_padctl;
|
||||
struct device;
|
||||
|
||||
struct tegra_xusb_padctl *tegra_xusb_padctl_get(struct device *dev);
|
||||
void tegra_xusb_padctl_put(struct tegra_xusb_padctl *padctl);
|
||||
|
||||
int tegra_xusb_padctl_usb3_save_context(struct tegra_xusb_padctl *padctl,
|
||||
unsigned int port);
|
||||
int tegra_xusb_padctl_hsic_set_idle(struct tegra_xusb_padctl *padctl,
|
||||
unsigned int port, bool idle);
|
||||
int tegra_xusb_padctl_usb3_set_lfps_detect(struct tegra_xusb_padctl *padctl,
|
||||
unsigned int port, bool enable);
|
||||
|
||||
#endif /* PHY_TEGRA_XUSB_H */
|
|
@ -21,8 +21,6 @@
|
|||
#define PSCI_POWER_STATE_TYPE_POWER_DOWN 1
|
||||
|
||||
bool psci_tos_resident_on(int cpu);
|
||||
bool psci_power_state_loses_context(u32 state);
|
||||
bool psci_power_state_is_valid(u32 state);
|
||||
|
||||
int psci_cpu_init_idle(unsigned int cpu);
|
||||
int psci_cpu_suspend_enter(unsigned long index);
|
||||
|
|
|
@ -31,6 +31,7 @@ struct of_phandle_args;
|
|||
* @ops: a pointer to device specific struct reset_control_ops
|
||||
* @owner: kernel module of the reset controller driver
|
||||
* @list: internal list of reset controller devices
|
||||
* @reset_control_head: head of internal list of requested reset controls
|
||||
* @of_node: corresponding device tree node as phandle target
|
||||
* @of_reset_n_cells: number of cells in reset line specifiers
|
||||
* @of_xlate: translation function to translate from specifier as found in the
|
||||
|
@ -41,6 +42,7 @@ struct reset_controller_dev {
|
|||
const struct reset_control_ops *ops;
|
||||
struct module *owner;
|
||||
struct list_head list;
|
||||
struct list_head reset_control_head;
|
||||
struct device_node *of_node;
|
||||
int of_reset_n_cells;
|
||||
int (*of_xlate)(struct reset_controller_dev *rcdev,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef _LINUX_RESET_H_
|
||||
#define _LINUX_RESET_H_
|
||||
|
||||
struct device;
|
||||
struct device_node;
|
||||
#include <linux/device.h>
|
||||
|
||||
struct reset_control;
|
||||
|
||||
#ifdef CONFIG_RESET_CONTROLLER
|
||||
|
@ -12,9 +12,11 @@ int reset_control_assert(struct reset_control *rstc);
|
|||
int reset_control_deassert(struct reset_control *rstc);
|
||||
int reset_control_status(struct reset_control *rstc);
|
||||
|
||||
struct reset_control *reset_control_get(struct device *dev, const char *id);
|
||||
struct reset_control *__of_reset_control_get(struct device_node *node,
|
||||
const char *id, int index, int shared);
|
||||
void reset_control_put(struct reset_control *rstc);
|
||||
struct reset_control *devm_reset_control_get(struct device *dev, const char *id);
|
||||
struct reset_control *__devm_reset_control_get(struct device *dev,
|
||||
const char *id, int index, int shared);
|
||||
|
||||
int __must_check device_reset(struct device *dev);
|
||||
|
||||
|
@ -23,24 +25,6 @@ static inline int device_reset_optional(struct device *dev)
|
|||
return device_reset(dev);
|
||||
}
|
||||
|
||||
static inline struct reset_control *reset_control_get_optional(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
return reset_control_get(dev, id);
|
||||
}
|
||||
|
||||
static inline struct reset_control *devm_reset_control_get_optional(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
return devm_reset_control_get(dev, id);
|
||||
}
|
||||
|
||||
struct reset_control *of_reset_control_get(struct device_node *node,
|
||||
const char *id);
|
||||
|
||||
struct reset_control *of_reset_control_get_by_index(
|
||||
struct device_node *node, int index);
|
||||
|
||||
#else
|
||||
|
||||
static inline int reset_control_reset(struct reset_control *rstc)
|
||||
|
@ -72,49 +56,191 @@ static inline void reset_control_put(struct reset_control *rstc)
|
|||
WARN_ON(1);
|
||||
}
|
||||
|
||||
static inline int __must_check device_reset(struct device *dev)
|
||||
{
|
||||
WARN_ON(1);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static inline int device_reset_optional(struct device *dev)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static inline struct reset_control *__must_check reset_control_get(
|
||||
struct device *dev, const char *id)
|
||||
static inline struct reset_control *__of_reset_control_get(
|
||||
struct device_node *node,
|
||||
const char *id, int index, int shared)
|
||||
{
|
||||
WARN_ON(1);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static inline struct reset_control *__must_check devm_reset_control_get(
|
||||
static inline struct reset_control *__devm_reset_control_get(
|
||||
struct device *dev,
|
||||
const char *id, int index, int shared)
|
||||
{
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_RESET_CONTROLLER */
|
||||
|
||||
/**
|
||||
* reset_control_get - Lookup and obtain an exclusive reference to a
|
||||
* reset controller.
|
||||
* @dev: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Returns a struct reset_control or IS_ERR() condition containing errno.
|
||||
* If this function is called more then once for the same reset_control it will
|
||||
* return -EBUSY.
|
||||
*
|
||||
* See reset_control_get_shared for details on shared references to
|
||||
* reset-controls.
|
||||
*
|
||||
* Use of id names is optional.
|
||||
*/
|
||||
static inline struct reset_control *__must_check reset_control_get(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
#ifndef CONFIG_RESET_CONTROLLER
|
||||
WARN_ON(1);
|
||||
return ERR_PTR(-EINVAL);
|
||||
#endif
|
||||
return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, 0);
|
||||
}
|
||||
|
||||
static inline struct reset_control *reset_control_get_optional(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* reset_control_get_shared - Lookup and obtain a shared reference to a
|
||||
* reset controller.
|
||||
* @dev: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Returns a struct reset_control or IS_ERR() condition containing errno.
|
||||
* This function is intended for use with reset-controls which are shared
|
||||
* between hardware-blocks.
|
||||
*
|
||||
* When a reset-control is shared, the behavior of reset_control_assert /
|
||||
* deassert is changed, the reset-core will keep track of a deassert_count
|
||||
* and only (re-)assert the reset after reset_control_assert has been called
|
||||
* as many times as reset_control_deassert was called. Also see the remark
|
||||
* about shared reset-controls in the reset_control_assert docs.
|
||||
*
|
||||
* Calling reset_control_assert without first calling reset_control_deassert
|
||||
* is not allowed on a shared reset control. Calling reset_control_reset is
|
||||
* also not allowed on a shared reset control.
|
||||
*
|
||||
* Use of id names is optional.
|
||||
*/
|
||||
static inline struct reset_control *reset_control_get_shared(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* of_reset_control_get - Lookup and obtain an exclusive reference to a
|
||||
* reset controller.
|
||||
* @node: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Returns a struct reset_control or IS_ERR() condition containing errno.
|
||||
*
|
||||
* Use of id names is optional.
|
||||
*/
|
||||
static inline struct reset_control *of_reset_control_get(
|
||||
struct device_node *node, const char *id)
|
||||
{
|
||||
return __of_reset_control_get(node, id, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* of_reset_control_get_by_index - Lookup and obtain an exclusive reference to
|
||||
* a reset controller by index.
|
||||
* @node: device to be reset by the controller
|
||||
* @index: index of the reset controller
|
||||
*
|
||||
* This is to be used to perform a list of resets for a device or power domain
|
||||
* in whatever order. Returns a struct reset_control or IS_ERR() condition
|
||||
* containing errno.
|
||||
*/
|
||||
static inline struct reset_control *of_reset_control_get_by_index(
|
||||
struct device_node *node, int index)
|
||||
{
|
||||
return __of_reset_control_get(node, NULL, index, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_get - resource managed reset_control_get()
|
||||
* @dev: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Managed reset_control_get(). For reset controllers returned from this
|
||||
* function, reset_control_put() is called automatically on driver detach.
|
||||
* See reset_control_get() for more information.
|
||||
*/
|
||||
static inline struct reset_control *__must_check devm_reset_control_get(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
#ifndef CONFIG_RESET_CONTROLLER
|
||||
WARN_ON(1);
|
||||
#endif
|
||||
return __devm_reset_control_get(dev, id, 0, 0);
|
||||
}
|
||||
|
||||
static inline struct reset_control *devm_reset_control_get_optional(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return __devm_reset_control_get(dev, id, 0, 0);
|
||||
}
|
||||
|
||||
static inline struct reset_control *of_reset_control_get(
|
||||
struct device_node *node, const char *id)
|
||||
/**
|
||||
* devm_reset_control_get_by_index - resource managed reset_control_get
|
||||
* @dev: device to be reset by the controller
|
||||
* @index: index of the reset controller
|
||||
*
|
||||
* Managed reset_control_get(). For reset controllers returned from this
|
||||
* function, reset_control_put() is called automatically on driver detach.
|
||||
* See reset_control_get() for more information.
|
||||
*/
|
||||
static inline struct reset_control *devm_reset_control_get_by_index(
|
||||
struct device *dev, int index)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return __devm_reset_control_get(dev, NULL, index, 0);
|
||||
}
|
||||
|
||||
static inline struct reset_control *of_reset_control_get_by_index(
|
||||
struct device_node *node, int index)
|
||||
/**
|
||||
* devm_reset_control_get_shared - resource managed reset_control_get_shared()
|
||||
* @dev: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Managed reset_control_get_shared(). For reset controllers returned from
|
||||
* this function, reset_control_put() is called automatically on driver detach.
|
||||
* See reset_control_get_shared() for more information.
|
||||
*/
|
||||
static inline struct reset_control *devm_reset_control_get_shared(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return __devm_reset_control_get(dev, id, 0, 1);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_RESET_CONTROLLER */
|
||||
/**
|
||||
* devm_reset_control_get_shared_by_index - resource managed
|
||||
* reset_control_get_shared
|
||||
* @dev: device to be reset by the controller
|
||||
* @index: index of the reset controller
|
||||
*
|
||||
* Managed reset_control_get_shared(). For reset controllers returned from
|
||||
* this function, reset_control_put() is called automatically on driver detach.
|
||||
* See reset_control_get_shared() for more information.
|
||||
*/
|
||||
static inline struct reset_control *devm_reset_control_get_shared_by_index(
|
||||
struct device *dev, int index)
|
||||
{
|
||||
return __devm_reset_control_get(dev, NULL, index, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#ifndef PM_RCAR_H
|
||||
#define PM_RCAR_H
|
||||
#ifndef __LINUX_SOC_RENESAS_RCAR_SYSC_H__
|
||||
#define __LINUX_SOC_RENESAS_RCAR_SYSC_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct rcar_sysc_ch {
|
||||
u16 chan_offs;
|
||||
|
@ -9,7 +11,6 @@ struct rcar_sysc_ch {
|
|||
|
||||
int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch);
|
||||
int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch);
|
||||
bool rcar_sysc_power_is_off(const struct rcar_sysc_ch *sysc_ch);
|
||||
void __iomem *rcar_sysc_init(phys_addr_t base);
|
||||
|
||||
#endif /* PM_RCAR_H */
|
||||
#endif /* __LINUX_SOC_RENESAS_RCAR_SYSC_H__ */
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#define TEGRA_FUSE_SKU_CALIB_0 0xf0
|
||||
#define TEGRA30_FUSE_SATA_CALIB 0x124
|
||||
#define TEGRA_FUSE_USB_CALIB_EXT_0 0x250
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
|
|
|
@ -33,9 +33,9 @@ void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode);
|
|||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
bool tegra_pmc_cpu_is_powered(int cpuid);
|
||||
int tegra_pmc_cpu_power_on(int cpuid);
|
||||
int tegra_pmc_cpu_remove_clamping(int cpuid);
|
||||
bool tegra_pmc_cpu_is_powered(unsigned int cpuid);
|
||||
int tegra_pmc_cpu_power_on(unsigned int cpuid);
|
||||
int tegra_pmc_cpu_remove_clamping(unsigned int cpuid);
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
/*
|
||||
|
@ -72,6 +72,7 @@ int tegra_pmc_cpu_remove_clamping(int cpuid);
|
|||
#define TEGRA_POWERGATE_AUD 27
|
||||
#define TEGRA_POWERGATE_DFD 28
|
||||
#define TEGRA_POWERGATE_VE2 29
|
||||
#define TEGRA_POWERGATE_MAX TEGRA_POWERGATE_VE2
|
||||
|
||||
#define TEGRA_POWERGATE_3D0 TEGRA_POWERGATE_3D
|
||||
|
||||
|
@ -108,50 +109,51 @@ int tegra_pmc_cpu_remove_clamping(int cpuid);
|
|||
#define TEGRA_IO_RAIL_SYS_DDC 58
|
||||
|
||||
#ifdef CONFIG_ARCH_TEGRA
|
||||
int tegra_powergate_is_powered(int id);
|
||||
int tegra_powergate_power_on(int id);
|
||||
int tegra_powergate_power_off(int id);
|
||||
int tegra_powergate_remove_clamping(int id);
|
||||
int tegra_powergate_is_powered(unsigned int id);
|
||||
int tegra_powergate_power_on(unsigned int id);
|
||||
int tegra_powergate_power_off(unsigned int id);
|
||||
int tegra_powergate_remove_clamping(unsigned int id);
|
||||
|
||||
/* Must be called with clk disabled, and returns with clk enabled */
|
||||
int tegra_powergate_sequence_power_up(int id, struct clk *clk,
|
||||
int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
|
||||
struct reset_control *rst);
|
||||
|
||||
int tegra_io_rail_power_on(int id);
|
||||
int tegra_io_rail_power_off(int id);
|
||||
int tegra_io_rail_power_on(unsigned int id);
|
||||
int tegra_io_rail_power_off(unsigned int id);
|
||||
#else
|
||||
static inline int tegra_powergate_is_powered(int id)
|
||||
static inline int tegra_powergate_is_powered(unsigned int id)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int tegra_powergate_power_on(int id)
|
||||
static inline int tegra_powergate_power_on(unsigned int id)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int tegra_powergate_power_off(int id)
|
||||
static inline int tegra_powergate_power_off(unsigned int id)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int tegra_powergate_remove_clamping(int id)
|
||||
static inline int tegra_powergate_remove_clamping(unsigned int id)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int tegra_powergate_sequence_power_up(int id, struct clk *clk,
|
||||
static inline int tegra_powergate_sequence_power_up(unsigned int id,
|
||||
struct clk *clk,
|
||||
struct reset_control *rst)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int tegra_io_rail_power_on(int id)
|
||||
static inline int tegra_io_rail_power_on(unsigned int id)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int tegra_io_rail_power_off(int id)
|
||||
static inline int tegra_io_rail_power_off(unsigned int id)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue