Commit 4a5219ed authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents 9797f6b0 5420f9fd
NVIDIA Tegra Power Management Controller (PMC) NVIDIA Tegra Power Management Controller (PMC)
== Power Management Controller Node ==
The PMC block interacts with an external Power Management Unit. The PMC The PMC block interacts with an external Power Management Unit. The PMC
mostly controls the entry and exit of the system from different sleep mostly controls the entry and exit of the system from different sleep
modes. It provides power-gating controllers for SoC and CPU power-islands. modes. It provides power-gating controllers for SoC and CPU power-islands.
Required properties: Required properties:
- name : Should be pmc - name : Should be pmc
- compatible : For Tegra20, must contain "nvidia,tegra20-pmc". For Tegra30, - compatible : Should contain one of the following:
must contain "nvidia,tegra30-pmc". For Tegra114, must contain For Tegra20 must contain "nvidia,tegra20-pmc".
"nvidia,tegra114-pmc". For Tegra124, must contain "nvidia,tegra124-pmc". For Tegra30 must contain "nvidia,tegra30-pmc".
Otherwise, must contain "nvidia,<chip>-pmc", plus at least one of the For Tegra114 must contain "nvidia,tegra114-pmc"
above, where <chip> is tegra132. 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 - reg : Offset and length of the register set for the device
- clocks : Must contain an entry for each entry in clock-names. - clocks : Must contain an entry for each entry in clock-names.
See ../clocks/clock-bindings.txt for details. See ../clocks/clock-bindings.txt for details.
...@@ -68,6 +72,11 @@ Optional properties for hardware-triggered thermal reset (inside 'i2c-thermtrip' ...@@ -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 Defaults to 0. Valid values are described in section 12.5.2
"Pinmux Support" of the Tegra4 Technical Reference Manual. "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: Example:
/ SoC dts including file / SoC dts including file
...@@ -113,3 +122,76 @@ pmc@7000f400 { ...@@ -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>;
...
};
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>;
};
};
Flash device on ARM Versatile board 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: 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. - 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 The device tree may optionally contain sub-nodes describing partitions of the
address space. See partition.txt for more detail. 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: ...@@ -60,11 +60,14 @@ Required properties:
- afi - afi
- pcie_x - 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. - phys: Must contain an entry for each entry in phy-names.
- phy-names: Must include the following entries: - phy-names: Must include the following entries:
- pcie - pcie
These properties are deprecated in favour of per-lane PHYs define in each of
the root ports (see below).
Power supplies for Tegra20: Power supplies for Tegra20:
- avdd-pex-supply: Power supply for analog PCIe logic. Must supply 1.05 V. - 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. - vdd-pex-supply: Power supply for digital PCIe I/O. Must supply 1.05 V.
...@@ -122,11 +125,22 @@ Required properties: ...@@ -122,11 +125,22 @@ Required properties:
- Root port 0 uses 4 lanes, root port 1 is unused. - Root port 0 uses 4 lanes, root port 1 is unused.
- Both root ports use 2 lanes. - 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: SoC DTSI:
pcie-controller { pcie-controller@80003000 {
compatible = "nvidia,tegra20-pcie"; compatible = "nvidia,tegra20-pcie";
device_type = "pci"; device_type = "pci";
reg = <0x80003000 0x00000800 /* PADS registers */ reg = <0x80003000 0x00000800 /* PADS registers */
...@@ -186,10 +200,9 @@ SoC DTSI: ...@@ -186,10 +200,9 @@ SoC DTSI:
}; };
}; };
Board DTS: Board DTS:
pcie-controller { pcie-controller@80003000 {
status = "okay"; status = "okay";
vdd-supply = <&pci_vdd_reg>; 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, ...@@ -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 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 instantiated at the proper location in the operating system's device tree (as
illustrated by the optional nodes in the example above). 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";
};
};
Device tree binding for NVIDIA Tegra XUSB pad controller 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 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 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. associated PHY that must be powered up before the pad can be used.
......
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: ...@@ -7,6 +7,7 @@ Required properties for power domain controller:
- compatible: Should be one of the following. - compatible: Should be one of the following.
"rockchip,rk3288-power-controller" - for RK3288 SoCs. "rockchip,rk3288-power-controller" - for RK3288 SoCs.
"rockchip,rk3368-power-controller" - for RK3368 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. - #power-domain-cells: Number of cells in a power-domain specifier.
Should be 1 for multiple PM domains. Should be 1 for multiple PM domains.
- #address-cells: Should be 1. - #address-cells: Should be 1.
...@@ -16,8 +17,18 @@ Required properties for power domain sub nodes: ...@@ -16,8 +17,18 @@ Required properties for power domain sub nodes:
- reg: index of the power domain, should use macros in: - 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/rk3288-power.h" - for RK3288 type power domain.
"include/dt-bindings/power/rk3368-power.h" - for RK3368 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 - clocks (optional): phandles to clocks which need to be enabled while power domain
switches state. 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: Example:
...@@ -30,6 +41,7 @@ Example: ...@@ -30,6 +41,7 @@ Example:
pd_gpu { pd_gpu {
reg = <RK3288_PD_GPU>; reg = <RK3288_PD_GPU>;
clocks = <&cru ACLK_GPU>; clocks = <&cru ACLK_GPU>;
pm_qos = <&qos_gpu>;
}; };
}; };
...@@ -45,12 +57,41 @@ Example: ...@@ -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, 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 containing a phandle to the power device node and an index specifying which
power domain to use. power domain to use.
The index should use macros in: The index should use macros in:
"include/dt-bindings/power/rk3288-power.h" - for rk3288 type power domain. "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/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: Example of the node using power domain:
...@@ -65,3 +106,9 @@ 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>; power-domains = <&power RK3368_PD_GPU_1>;
/* ... */ /* ... */
}; };
node {
/* ... */
power-domains = <&power RK3399_PD_VOPB>;
/* ... */
};
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 ...@@ -31,16 +31,28 @@ should provide its own implementation of of_xlate. of_xlate is used only for
dt boot case. dt boot case.
#define of_phy_provider_register(dev, xlate) \ #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) \ #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 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 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 arguments. For the dt boot case, all PHY providers should use one of the above
2 macros to register the PHY provider. 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, void devm_of_phy_provider_unregister(struct device *dev,
struct phy_provider *phy_provider); struct phy_provider *phy_provider);
void of_phy_provider_unregister(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/ ...@@ -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 T: git git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git next
S: Supported S: Supported
F: arch/arm64/boot/dts/renesas/ F: arch/arm64/boot/dts/renesas/
F: drivers/soc/renesas/
F: include/linux/soc/renesas/
ARM/RISCPC ARCHITECTURE ARM/RISCPC ARCHITECTURE
M: Russell King <linux@armlinux.org.uk> M: Russell King <linux@armlinux.org.uk>
...@@ -1584,6 +1586,7 @@ F: arch/arm/mach-s5p*/ ...@@ -1584,6 +1586,7 @@ F: arch/arm/mach-s5p*/
F: arch/arm/mach-exynos*/ F: arch/arm/mach-exynos*/
F: drivers/*/*s3c2410* F: drivers/*/*s3c2410*
F: drivers/*/*/*s3c2410* F: drivers/*/*/*s3c2410*
F: drivers/memory/samsung/*
F: drivers/soc/samsung/* F: drivers/soc/samsung/*
F: drivers/spi/spi-s3c* F: drivers/spi/spi-s3c*
F: sound/soc/samsung/* F: sound/soc/samsung/*
...@@ -1648,6 +1651,8 @@ F: arch/arm/configs/shmobile_defconfig ...@@ -1648,6 +1651,8 @@ F: arch/arm/configs/shmobile_defconfig
F: arch/arm/include/debug/renesas-scif.S F: arch/arm/include/debug/renesas-scif.S
F: arch/arm/mach-shmobile/ F: arch/arm/mach-shmobile/
F: drivers/sh/ F: drivers/sh/
F: drivers/soc/renesas/
F: include/linux/soc/renesas/
ARM/SOCFPGA ARCHITECTURE ARM/SOCFPGA ARCHITECTURE
M: Dinh Nguyen <dinguyen@opensource.altera.com> M: Dinh Nguyen <dinguyen@opensource.altera.com>
......
...@@ -52,8 +52,9 @@ pic@14000000 { ...@@ -52,8 +52,9 @@ pic@14000000 {
}; };
flash@24000000 { flash@24000000 {
compatible = "cfi-flash"; compatible = "arm,versatile-flash", "cfi-flash";
reg = <0x24000000 0x02000000>; reg = <0x24000000 0x02000000>;
bank-width = <4>;
}; };
fpga { fpga {
......
...@@ -119,8 +119,9 @@ pclk: pclk@24M { ...@@ -119,8 +119,9 @@ pclk: pclk@24M {
}; };
flash@34000000 { flash@34000000 {
compatible = "arm,versatile-flash"; /* 64 MiB NOR flash in non-interleaved chips */
reg = <0x34000000 0x4000000>; compatible = "arm,versatile-flash", "cfi-flash";
reg = <0x34000000 0x04000000>;
bank-width = <4>; bank-width = <4>;
}; };
......
...@@ -173,12 +173,12 @@ config ARCH_BRCMSTB ...@@ -173,12 +173,12 @@ config ARCH_BRCMSTB
select ARM_GIC select ARM_GIC
select ARM_ERRATA_798181 if SMP select ARM_ERRATA_798181 if SMP
select HAVE_ARM_ARCH_TIMER select HAVE_ARM_ARCH_TIMER
select BRCMSTB_GISB_ARB
select BRCMSTB_L2_IRQ select BRCMSTB_L2_IRQ
select BCM7120_L2_IRQ select BCM7120_L2_IRQ
select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
select ARCH_WANT_OPTIONAL_GPIOLIB select ARCH_WANT_OPTIONAL_GPIOLIB
select SOC_BRCMSTB select SOC_BRCMSTB
select SOC_BUS
help help
Say Y if you intend to run the kernel on a Broadcom ARM-based STB Say Y if you intend to run the kernel on a Broadcom ARM-based STB
chipset. chipset.
......
...@@ -18,6 +18,7 @@ menuconfig ARCH_EXYNOS ...@@ -18,6 +18,7 @@ menuconfig ARCH_EXYNOS
select COMMON_CLK_SAMSUNG select COMMON_CLK_SAMSUNG
select EXYNOS_THERMAL select EXYNOS_THERMAL
select EXYNOS_PMU select EXYNOS_PMU
select EXYNOS_SROM
select HAVE_ARM_SCU if SMP select HAVE_ARM_SCU if SMP
select HAVE_S3C2410_I2C if I2C select HAVE_S3C2410_I2C if I2C
select HAVE_S3C2410_WATCHDOG if WATCHDOG select HAVE_S3C2410_WATCHDOG if WATCHDOG
...@@ -26,11 +27,13 @@ menuconfig ARCH_EXYNOS ...@@ -26,11 +27,13 @@ menuconfig ARCH_EXYNOS
select PINCTRL_EXYNOS select PINCTRL_EXYNOS
select PM_GENERIC_DOMAINS if PM select PM_GENERIC_DOMAINS if PM
select S5P_DEV_MFC select S5P_DEV_MFC
select SAMSUNG_MC
select SOC_SAMSUNG select SOC_SAMSUNG
select SRAM select SRAM
select THERMAL select THERMAL
select THERMAL_OF select THERMAL_OF
select MFD_SYSCON select MFD_SYSCON
select MEMORY
select CLKSRC_EXYNOS_MCT select CLKSRC_EXYNOS_MCT
select POWER_RESET select POWER_RESET
select POWER_RESET_SYSCON select POWER_RESET_SYSCON
......
...@@ -31,11 +31,6 @@ ...@@ -31,11 +31,6 @@
static struct map_desc exynos4_iodesc[] __initdata = { 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, .virtual = (unsigned long)S5P_VA_CMU,
.pfn = __phys_to_pfn(EXYNOS4_PA_CMU), .pfn = __phys_to_pfn(EXYNOS4_PA_CMU),
.length = SZ_128K, .length = SZ_128K,
...@@ -58,15 +53,6 @@ static struct map_desc exynos4_iodesc[] __initdata = { ...@@ -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 = { static struct platform_device exynos_cpuidle = {
.name = "exynos_cpuidle", .name = "exynos_cpuidle",
#ifdef CONFIG_ARM_EXYNOS_CPUIDLE #ifdef CONFIG_ARM_EXYNOS_CPUIDLE
...@@ -138,9 +124,6 @@ static void __init exynos_map_io(void) ...@@ -138,9 +124,6 @@ static void __init exynos_map_io(void)
{ {
if (soc_is_exynos4()) if (soc_is_exynos4())
iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc)); 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) static void __init exynos_init_io(void)
......
...@@ -25,7 +25,4 @@ ...@@ -25,7 +25,4 @@
#define EXYNOS4_PA_COREPERI 0x10500000 #define EXYNOS4_PA_COREPERI 0x10500000
#define EXYNOS4_PA_SROMC 0x12570000
#define EXYNOS5_PA_SROMC 0x12250000
#endif /* __ASM_ARCH_MAP_H */ #endif /* __ASM_ARCH_MAP_H */
/*
* 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 @@ ...@@ -34,10 +34,11 @@
#include <asm/smp_scu.h> #include <asm/smp_scu.h>
#include <asm/suspend.h> #include <asm/suspend.h>
#include <mach/map.h>
#include <plat/pm-common.h> #include <plat/pm-common.h>
#include "common.h" #include "common.h"
#include "regs-srom.h"
#define REG_TABLE_END (-1U) #define REG_TABLE_END (-1U)
...@@ -53,15 +54,6 @@ struct exynos_wkup_irq { ...@@ -53,15 +54,6 @@ struct exynos_wkup_irq {
u32 mask; 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 { struct exynos_pm_data {
const struct exynos_wkup_irq *wkup_irq; const struct exynos_wkup_irq *wkup_irq;
unsigned int wake_disable_mask; unsigned int wake_disable_mask;
...@@ -343,8 +335,6 @@ static void exynos_pm_prepare(void) ...@@ -343,8 +335,6 @@ static void exynos_pm_prepare(void)
/* Set wake-up mask registers */ /* Set wake-up mask registers */
exynos_pm_set_wakeup_mask(); exynos_pm_set_wakeup_mask();
s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
exynos_pm_enter_sleep_mode(); exynos_pm_enter_sleep_mode();
/* ensure at least INFORM0 has the resume address */ /* ensure at least INFORM0 has the resume address */
...@@ -375,8 +365,6 @@ static void exynos5420_pm_prepare(void) ...@@ -375,8 +365,6 @@ static void exynos5420_pm_prepare(void)
/* Set wake-up mask registers */ /* Set wake-up mask registers */
exynos_pm_set_wakeup_mask(); 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); exynos_pmu_spare3 = pmu_raw_readl(S5P_PMU_SPARE3);
/* /*
* The cpu state needs to be saved and restored so that the * The cpu state needs to be saved and restored so that the
...@@ -467,8 +455,6 @@ static void exynos_pm_resume(void) ...@@ -467,8 +455,6 @@ static void exynos_pm_resume(void)
/* For release retention */ /* For release retention */
exynos_pm_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) if (cpuid == ARM_CPU_PART_CORTEX_A9)
scu_enable(S5P_VA_SCU); scu_enable(S5P_VA_SCU);
...@@ -535,8 +521,6 @@ static void exynos5420_pm_resume(void) ...@@ -535,8 +521,6 @@ static void exynos5420_pm_resume(void)
pmu_raw_writel(exynos_pmu_spare3, S5P_PMU_SPARE3); pmu_raw_writel(exynos_pmu_spare3, S5P_PMU_SPARE3);
s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
early_wakeup: early_wakeup:
tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1); tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1);
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include <linux/amba/kmi.h> #include <linux/amba/kmi.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/irqchip.h> #include <linux/irqchip.h>
#include <linux/mtd/physmap.h>
#include <linux/platform_data/clk-integrator.h> #include <linux/platform_data/clk-integrator.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/of_address.h> #include <linux/of_address.h>
...@@ -146,65 +145,6 @@ static int __init irq_syscore_init(void) ...@@ -146,65 +145,6 @@ static int __init irq_syscore_init(void)
device_initcall(irq_syscore_init); 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 * For the PL010 found in the Integrator/AP some of the UART control is
* implemented in the system controller and accessed using a callback * implemented in the system controller and accessed using a callback
...@@ -266,8 +206,6 @@ static struct of_dev_auxdata ap_auxdata_lookup[] __initdata = { ...@@ -266,8 +206,6 @@ static struct of_dev_auxdata ap_auxdata_lookup[] __initdata = {
"kmi0", NULL), "kmi0", NULL),
OF_DEV_AUXDATA("arm,primecell", KMI1_BASE, OF_DEV_AUXDATA("arm,primecell", KMI1_BASE,
"kmi1", NULL), "kmi1", NULL),
OF_DEV_AUXDATA("cfi-flash", INTEGRATOR_FLASH_BASE,
"physmap-flash", &ap_flash_data),
{ /* sentinel */ }, { /* sentinel */ },
}; };
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/irqchip.h> #include <linux/irqchip.h>
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/mtd/physmap.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
...@@ -43,14 +42,8 @@ ...@@ -43,14 +42,8 @@
/* Base address to the CP controller */ /* Base address to the CP controller */
static void __iomem *intcp_con_base; static void __iomem *intcp_con_base;
#define INTCP_PA_FLASH_BASE 0x24000000
#define INTCP_PA_CLCD_BASE 0xc0000000 #define INTCP_PA_CLCD_BASE 0xc0000000
#define INTCP_FLASHPROG 0x04
#define CINTEGRATOR_FLASHPROG_FLVPPEN (1 << 0)
#define CINTEGRATOR_FLASHPROG_FLWREN (1 << 1)
/* /*
* Logical Physical * Logical Physical
* f1000000 10000000 Core module registers * f1000000 10000000 Core module registers
...@@ -107,48 +100,6 @@ static void __init intcp_map_io(void) ...@@ -107,48 +100,6 @@ static void __init intcp_map_io(void)
iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc)); 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 * It seems that the card insertion interrupt remains active after
* we've acknowledged it. We therefore ignore the interrupt, and * we've acknowledged it. We therefore ignore the interrupt, and
...@@ -260,8 +211,6 @@ static struct of_dev_auxdata intcp_auxdata_lookup[] __initdata = { ...@@ -260,8 +211,6 @@ static struct of_dev_auxdata intcp_auxdata_lookup[] __initdata = {
"aaci", &mmc_data), "aaci", &mmc_data),
OF_DEV_AUXDATA("arm,primecell", INTCP_PA_CLCD_BASE, OF_DEV_AUXDATA("arm,primecell", INTCP_PA_CLCD_BASE,
"clcd", &clcd_data), "clcd", &clcd_data),
OF_DEV_AUXDATA("cfi-flash", INTCP_PA_FLASH_BASE,
"physmap-flash", &intcp_flash_data),
{ /* sentinel */ }, { /* sentinel */ },
}; };
......
...@@ -29,6 +29,7 @@ static void __init mediatek_timer_init(void) ...@@ -29,6 +29,7 @@ static void __init mediatek_timer_init(void)
void __iomem *gpt_base; void __iomem *gpt_base;
if (of_machine_is_compatible("mediatek,mt6589") || if (of_machine_is_compatible("mediatek,mt6589") ||
of_machine_is_compatible("mediatek,mt7623") ||
of_machine_is_compatible("mediatek,mt8135") || of_machine_is_compatible("mediatek,mt8135") ||
of_machine_is_compatible("mediatek,mt8127")) { of_machine_is_compatible("mediatek,mt8127")) {
/* turn on GPT6 which ungates arch timer clocks */ /* turn on GPT6 which ungates arch timer clocks */
......
...@@ -4,11 +4,6 @@ config ARCH_SHMOBILE ...@@ -4,11 +4,6 @@ config ARCH_SHMOBILE
config ARCH_SHMOBILE_MULTI config ARCH_SHMOBILE_MULTI
bool bool
config PM_RCAR
bool
select PM
select PM_GENERIC_DOMAINS
config PM_RMOBILE config PM_RMOBILE
bool bool
select PM select PM
...@@ -16,13 +11,15 @@ config PM_RMOBILE ...@@ -16,13 +11,15 @@ config PM_RMOBILE
config ARCH_RCAR_GEN1 config ARCH_RCAR_GEN1
bool bool
select PM_RCAR select PM
select PM_GENERIC_DOMAINS
select RENESAS_INTC_IRQPIN select RENESAS_INTC_IRQPIN
select SYS_SUPPORTS_SH_TMU select SYS_SUPPORTS_SH_TMU
config ARCH_RCAR_GEN2 config ARCH_RCAR_GEN2
bool bool
select PM_RCAR select PM
select PM_GENERIC_DOMAINS
select RENESAS_IRQC select RENESAS_IRQC
select SYS_SUPPORTS_SH_CMT select SYS_SUPPORTS_SH_CMT
select PCI_DOMAINS if PCI select PCI_DOMAINS if PCI
......
...@@ -38,7 +38,6 @@ smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o headsmp-scu.o platsmp-scu.o ...@@ -38,7 +38,6 @@ smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o headsmp-scu.o platsmp-scu.o
# PM objects # PM objects
obj-$(CONFIG_SUSPEND) += suspend.o obj-$(CONFIG_SUSPEND) += suspend.o
obj-$(CONFIG_PM_RCAR) += pm-rcar.o
obj-$(CONFIG_PM_RMOBILE) += pm-rmobile.o obj-$(CONFIG_PM_RMOBILE) += pm-rmobile.o
obj-$(CONFIG_ARCH_RCAR_GEN2) += pm-rcar-gen2.o obj-$(CONFIG_ARCH_RCAR_GEN2) += pm-rcar-gen2.o
......
...@@ -9,9 +9,10 @@ ...@@ -9,9 +9,10 @@
* for more details. * for more details.
*/ */
#include <linux/soc/renesas/rcar-sysc.h>
#include <asm/io.h> #include <asm/io.h>
#include "pm-rcar.h"
#include "r8a7779.h" #include "r8a7779.h"
/* SYSC */ /* SYSC */
......
...@@ -13,9 +13,9 @@ ...@@ -13,9 +13,9 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/soc/renesas/rcar-sysc.h>
#include <asm/io.h> #include <asm/io.h>
#include "common.h" #include "common.h"
#include "pm-rcar.h"
#include "rcar-gen2.h" #include "rcar-gen2.h"
/* RST */ /* RST */
......
...@@ -19,13 +19,13 @@ ...@@ -19,13 +19,13 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/soc/renesas/rcar-sysc.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/smp_plat.h> #include <asm/smp_plat.h>
#include <asm/smp_scu.h> #include <asm/smp_scu.h>
#include "common.h" #include "common.h"
#include "pm-rcar.h"
#include "r8a7779.h" #include "r8a7779.h"
#define AVECR IOMEM(0xfe700040) #define AVECR IOMEM(0xfe700040)
......
...@@ -17,12 +17,12 @@ ...@@ -17,12 +17,12 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/soc/renesas/rcar-sysc.h>
#include <asm/smp_plat.h> #include <asm/smp_plat.h>
#include "common.h" #include "common.h"
#include "platsmp-apmu.h" #include "platsmp-apmu.h"
#include "pm-rcar.h"
#include "rcar-gen2.h" #include "rcar-gen2.h"
#include "r8a7790.h" #include "r8a7790.h"
......
...@@ -108,19 +108,9 @@ static int tegra30_boot_secondary(unsigned int cpu, struct task_struct *idle) ...@@ -108,19 +108,9 @@ static int tegra30_boot_secondary(unsigned int cpu, struct task_struct *idle)
* be un-gated by un-toggling the power gate register * be un-gated by un-toggling the power gate register
* manually. * manually.
*/ */
if (!tegra_pmc_cpu_is_powered(cpu)) { ret = tegra_pmc_cpu_power_on(cpu);
ret = tegra_pmc_cpu_power_on(cpu); if (ret)
if (ret) return 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: remove_clamps:
/* CPU partition is powered. Enable the CPU clock. */ /* CPU partition is powered. Enable the CPU clock. */
......
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
#include <linux/amba/clcd.h> #include <linux/amba/clcd.h>
#include <linux/platform_data/video-clcd-versatile.h> #include <linux/platform_data/video-clcd-versatile.h>
#include <linux/amba/mmci.h> #include <linux/amba/mmci.h>
#include <linux/mtd/physmap.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
...@@ -41,12 +40,6 @@ ...@@ -41,12 +40,6 @@
#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) #define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
#define __io_address(n) ((void __iomem __force *)IO_ADDRESS(n)) #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 * Versatile Registers
...@@ -54,14 +47,8 @@ ...@@ -54,14 +47,8 @@
*/ */
#define VERSATILE_SYS_PCICTL_OFFSET 0x44 #define VERSATILE_SYS_PCICTL_OFFSET 0x44
#define VERSATILE_SYS_MCI_OFFSET 0x48 #define VERSATILE_SYS_MCI_OFFSET 0x48
#define VERSATILE_SYS_FLASH_OFFSET 0x4C
#define VERSATILE_SYS_CLCD_OFFSET 0x50 #define VERSATILE_SYS_CLCD_OFFSET 0x50
/*
* VERSATILE_SYS_FLASH
*/
#define VERSATILE_FLASHPROG_FLVPPEN (1 << 0) /* Enable writing to flash */
/* /*
* VERSATILE peripheral addresses * VERSATILE peripheral addresses
*/ */
...@@ -86,39 +73,6 @@ ...@@ -86,39 +73,6 @@
static void __iomem *versatile_sys_base; static void __iomem *versatile_sys_base;
static void __iomem *versatile_ib2_ctrl; 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) unsigned int mmc_status(struct device *dev)
{ {
struct amba_device *adev = container_of(dev, struct amba_device, dev); struct amba_device *adev = container_of(dev, struct amba_device, dev);
...@@ -390,7 +344,6 @@ static void __init versatile_dt_init(void) ...@@ -390,7 +344,6 @@ static void __init versatile_dt_init(void)
versatile_dt_pci_init(); versatile_dt_pci_init();
platform_device_register(&versatile_flash_device);
of_platform_populate(NULL, of_default_bus_match_table, of_platform_populate(NULL, of_default_bus_match_table,
versatile_auxdata_lookup, NULL); versatile_auxdata_lookup, NULL);
} }
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#define S5P_VA_DMC0 S3C_ADDR(0x02440000) #define S5P_VA_DMC0 S3C_ADDR(0x02440000)
#define S5P_VA_DMC1 S3C_ADDR(0x02480000) #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_BASE S3C_ADDR(0x02800000)
#define S5P_VA_COREPERI(x) (S5P_VA_COREPERI_BASE + (x)) #define S5P_VA_COREPERI(x) (S5P_VA_COREPERI_BASE + (x))
......
...@@ -48,7 +48,7 @@ config ARM_CCI5xx_PMU ...@@ -48,7 +48,7 @@ config ARM_CCI5xx_PMU
If unsure, say Y If unsure, say Y
config ARM_CCN config ARM_CCN
bool "ARM CCN driver support" tristate "ARM CCN driver support"
depends on ARM || ARM64 depends on ARM || ARM64
depends on PERF_EVENTS depends on PERF_EVENTS
help help
...@@ -58,6 +58,7 @@ config ARM_CCN ...@@ -58,6 +58,7 @@ config ARM_CCN
config BRCMSTB_GISB_ARB config BRCMSTB_GISB_ARB
bool "Broadcom STB GISB bus arbiter" bool "Broadcom STB GISB bus arbiter"
depends on ARM || MIPS depends on ARM || MIPS
default ARCH_BRCMSTB || BMIPS_GENERIC
help help
Driver for the Broadcom Set Top Box System-on-a-chip internal bus Driver for the Broadcom Set Top Box System-on-a-chip internal bus
arbiter. This driver provides timeout and target abort error handling arbiter. This driver provides timeout and target abort error handling
...@@ -110,7 +111,7 @@ config OMAP_OCP2SCP ...@@ -110,7 +111,7 @@ config OMAP_OCP2SCP
config SIMPLE_PM_BUS config SIMPLE_PM_BUS
bool "Simple Power-Managed Bus Driver" bool "Simple Power-Managed Bus Driver"
depends on OF && PM depends on OF && PM
depends on ARCH_SHMOBILE || COMPILE_TEST depends on ARCH_RENESAS || COMPILE_TEST
help help
Driver for transparent busses that don't need a real driver, but 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 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, ...@@ -1189,7 +1189,7 @@ static int arm_ccn_pmu_cpu_notifier(struct notifier_block *nb,
perf_pmu_migrate_context(&dt->pmu, cpu, target); perf_pmu_migrate_context(&dt->pmu, cpu, target);
cpumask_set_cpu(target, &dt->cpu); cpumask_set_cpu(target, &dt->cpu);
if (ccn->irq) 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: default:
break; break;
} }
...@@ -1278,7 +1278,7 @@ static int arm_ccn_pmu_init(struct arm_ccn *ccn) ...@@ -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 */ /* Also make sure that the overflow interrupt is handled by this CPU */
if (ccn->irq) { if (ccn->irq) {
err = irq_set_affinity(ccn->irq, &ccn->dt.cpu); err = irq_set_affinity_hint(ccn->irq, &ccn->dt.cpu);
if (err) { if (err) {
dev_err(ccn->dev, "Failed to set interrupt affinity!\n"); dev_err(ccn->dev, "Failed to set interrupt affinity!\n");
goto error_set_affinity; goto error_set_affinity;
...@@ -1306,7 +1306,8 @@ static void arm_ccn_pmu_cleanup(struct arm_ccn *ccn) ...@@ -1306,7 +1306,8 @@ static void arm_ccn_pmu_cleanup(struct arm_ccn *ccn)
{ {
int i; 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); unregister_cpu_notifier(&ccn->dt.cpu_nb);
for (i = 0; i < ccn->num_xps; i++) for (i = 0; i < ccn->num_xps; i++)
writel(0, ccn->xp[i].base + CCN_XP_DT_CONTROL); writel(0, ccn->xp[i].base + CCN_XP_DT_CONTROL);
......
...@@ -201,6 +201,7 @@ source "drivers/clk/bcm/Kconfig" ...@@ -201,6 +201,7 @@ source "drivers/clk/bcm/Kconfig"
source "drivers/clk/hisilicon/Kconfig" source "drivers/clk/hisilicon/Kconfig"
source "drivers/clk/mvebu/Kconfig" source "drivers/clk/mvebu/Kconfig"
source "drivers/clk/qcom/Kconfig" source "drivers/clk/qcom/Kconfig"
source "drivers/clk/renesas/Kconfig"
source "drivers/clk/samsung/Kconfig" source "drivers/clk/samsung/Kconfig"
source "drivers/clk/tegra/Kconfig" source "drivers/clk/tegra/Kconfig"
source "drivers/clk/ti/Kconfig" source "drivers/clk/ti/Kconfig"
......
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
obj-$(CONFIG_ARCH_EMEV2) += clk-emev2.o obj-$(CONFIG_ARCH_EMEV2) += clk-emev2.o
obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o clk-mstp.o obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o
obj-$(CONFIG_ARCH_R8A73A4) += clk-r8a73a4.o clk-mstp.o clk-div6.o obj-$(CONFIG_ARCH_R8A73A4) += clk-r8a73a4.o clk-div6.o
obj-$(CONFIG_ARCH_R8A7740) += clk-r8a7740.o clk-mstp.o clk-div6.o obj-$(CONFIG_ARCH_R8A7740) += clk-r8a7740.o clk-div6.o
obj-$(CONFIG_ARCH_R8A7778) += clk-r8a7778.o clk-mstp.o obj-$(CONFIG_ARCH_R8A7778) += clk-r8a7778.o
obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o clk-mstp.o obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o
obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o clk-mstp.o clk-div6.o obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o clk-div6.o
obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o clk-mstp.o clk-div6.o obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o clk-div6.o
obj-$(CONFIG_ARCH_R8A7793) += clk-rcar-gen2.o clk-mstp.o clk-div6.o obj-$(CONFIG_ARCH_R8A7793) += clk-rcar-gen2.o clk-div6.o
obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o clk-mstp.o clk-div6.o obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o clk-div6.o
obj-$(CONFIG_ARCH_R8A7795) += renesas-cpg-mssr.o \ obj-$(CONFIG_ARCH_R8A7795) += r8a7795-cpg-mssr.o
r8a7795-cpg-mssr.o clk-div6.o obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o clk-div6.o
obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o clk-mstp.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) ...@@ -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); CLK_OF_DECLARE(cpg_mstp_clks, "renesas,cpg-mstp-clocks", cpg_mstp_clocks_init);
int cpg_mstp_attach_dev(struct generic_pm_domain *unused, struct device *dev)
#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev)
{ {
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct of_phandle_args clkspec; struct of_phandle_args clkspec;
...@@ -297,7 +295,7 @@ int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev) ...@@ -297,7 +295,7 @@ int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev)
return error; 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)) if (!list_empty(&dev->power.subsys_data->clock_list))
pm_clk_destroy(dev); pm_clk_destroy(dev);
...@@ -326,4 +324,3 @@ void __init cpg_mstp_add_clk_domain(struct device_node *np) ...@@ -326,4 +324,3 @@ void __init cpg_mstp_add_clk_domain(struct device_node *np)
of_genpd_add_provider_simple(np, pd); of_genpd_add_provider_simple(np, pd);
} }
#endif /* !CONFIG_PM_GENERIC_DOMAINS_OF */
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
*/ */
#include <linux/bug.h> #include <linux/bug.h>
#include <linux/clk.h>
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/err.h> #include <linux/err.h>
...@@ -26,6 +27,7 @@ ...@@ -26,6 +27,7 @@
#include "renesas-cpg-mssr.h" #include "renesas-cpg-mssr.h"
#define CPG_RCKCR 0x240
enum clk_ids { enum clk_ids {
/* Core Clock Outputs exported to DT */ /* Core Clock Outputs exported to DT */
...@@ -50,6 +52,7 @@ enum clk_ids { ...@@ -50,6 +52,7 @@ enum clk_ids {
CLK_S3, CLK_S3,
CLK_SDSRC, CLK_SDSRC,
CLK_SSPSRC, CLK_SSPSRC,
CLK_RINT,
/* Module Clocks */ /* Module Clocks */
MOD_CLK_BASE MOD_CLK_BASE
...@@ -63,8 +66,12 @@ enum r8a7795_clk_types { ...@@ -63,8 +66,12 @@ enum r8a7795_clk_types {
CLK_TYPE_GEN3_PLL3, CLK_TYPE_GEN3_PLL3,
CLK_TYPE_GEN3_PLL4, CLK_TYPE_GEN3_PLL4,
CLK_TYPE_GEN3_SD, 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 = { static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
/* External Clock Inputs */ /* External Clock Inputs */
DEF_INPUT("extal", CLK_EXTAL), DEF_INPUT("extal", CLK_EXTAL),
...@@ -102,10 +109,10 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = { ...@@ -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("s3d2", R8A7795_CLK_S3D2, CLK_S3, 2, 1),
DEF_FIXED("s3d4", R8A7795_CLK_S3D4, CLK_S3, 4, 1), DEF_FIXED("s3d4", R8A7795_CLK_S3D4, CLK_S3, 4, 1),
DEF_SD("sd0", R8A7795_CLK_SD0, CLK_PLL1_DIV2, 0x0074), DEF_GEN3_SD("sd0", R8A7795_CLK_SD0, CLK_PLL1_DIV2, 0x0074),
DEF_SD("sd1", R8A7795_CLK_SD1, CLK_PLL1_DIV2, 0x0078), DEF_GEN3_SD("sd1", R8A7795_CLK_SD1, CLK_PLL1_DIV2, 0x0078),
DEF_SD("sd2", R8A7795_CLK_SD2, CLK_PLL1_DIV2, 0x0268), DEF_GEN3_SD("sd2", R8A7795_CLK_SD2, CLK_PLL1_DIV2, 0x0268),
DEF_SD("sd3", R8A7795_CLK_SD3, CLK_PLL1_DIV2, 0x026c), DEF_GEN3_SD("sd3", R8A7795_CLK_SD3, CLK_PLL1_DIV2, 0x026c),
DEF_FIXED("cl", R8A7795_CLK_CL, CLK_PLL1_DIV2, 48, 1), DEF_FIXED("cl", R8A7795_CLK_CL, CLK_PLL1_DIV2, 48, 1),
DEF_FIXED("cp", R8A7795_CLK_CP, CLK_EXTAL, 2, 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 = { ...@@ -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("mso", R8A7795_CLK_MSO, CLK_PLL1_DIV4, 0x014),
DEF_DIV6P1("hdmi", R8A7795_CLK_HDMI, CLK_PLL1_DIV2, 0x250), DEF_DIV6P1("hdmi", R8A7795_CLK_HDMI, CLK_PLL1_DIV2, 0x250),
DEF_DIV6P1("canfd", R8A7795_CLK_CANFD, CLK_PLL1_DIV4, 0x244), 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 = { static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
...@@ -139,6 +151,7 @@ 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("usb3-if0", 328, R8A7795_CLK_S3D1),
DEF_MOD("usb-dmac0", 330, R8A7795_CLK_S3D1), DEF_MOD("usb-dmac0", 330, R8A7795_CLK_S3D1),
DEF_MOD("usb-dmac1", 331, 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-ex", 407, R8A7795_CLK_CP),
DEF_MOD("intc-ap", 408, R8A7795_CLK_S3D1), DEF_MOD("intc-ap", 408, R8A7795_CLK_S3D1),
DEF_MOD("audmac0", 502, R8A7795_CLK_S3D4), DEF_MOD("audmac0", 502, R8A7795_CLK_S3D4),
...@@ -148,6 +161,7 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { ...@@ -148,6 +161,7 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
DEF_MOD("hscif2", 518, R8A7795_CLK_S3D1), DEF_MOD("hscif2", 518, R8A7795_CLK_S3D1),
DEF_MOD("hscif1", 519, R8A7795_CLK_S3D1), DEF_MOD("hscif1", 519, R8A7795_CLK_S3D1),
DEF_MOD("hscif0", 520, 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("fcpvd3", 600, R8A7795_CLK_S2D1),
DEF_MOD("fcpvd2", 601, R8A7795_CLK_S2D1), DEF_MOD("fcpvd2", 601, R8A7795_CLK_S2D1),
DEF_MOD("fcpvd1", 602, R8A7795_CLK_S2D1), DEF_MOD("fcpvd1", 602, R8A7795_CLK_S2D1),
...@@ -578,6 +592,18 @@ struct clk * __init r8a7795_cpg_clk_register(struct device *dev, ...@@ -578,6 +592,18 @@ struct clk * __init r8a7795_cpg_clk_register(struct device *dev,
case CLK_TYPE_GEN3_SD: case CLK_TYPE_GEN3_SD:
return cpg_sd_clk_register(core, base, __clk_get_name(parent)); 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: default:
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/clk/renesas.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
...@@ -253,7 +254,7 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core, ...@@ -253,7 +254,7 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
{ {
struct clk *clk = NULL, *parent; struct clk *clk = NULL, *parent;
struct device *dev = priv->dev; struct device *dev = priv->dev;
unsigned int id = core->id; unsigned int id = core->id, div = core->div;
const char *parent_name; const char *parent_name;
WARN_DEBUG(id >= priv->num_core_clks); 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, ...@@ -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_FF:
case CLK_TYPE_DIV6P1: case CLK_TYPE_DIV6P1:
case CLK_TYPE_DIV6_RO:
WARN_DEBUG(core->parent >= priv->num_core_clks); WARN_DEBUG(core->parent >= priv->num_core_clks);
parent = priv->clks[core->parent]; parent = priv->clks[core->parent];
if (IS_ERR(parent)) { if (IS_ERR(parent)) {
...@@ -274,13 +276,18 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core, ...@@ -274,13 +276,18 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
} }
parent_name = __clk_get_name(parent); parent_name = __clk_get_name(parent);
if (core->type == CLK_TYPE_FF) {
clk = clk_register_fixed_factor(NULL, core->name, if (core->type == CLK_TYPE_DIV6_RO)
parent_name, 0, /* Multiply with the DIV6 register value */
core->mult, core->div); div *= (readl(priv->base + core->offset) & 0x3f) + 1;
} else {
if (core->type == CLK_TYPE_DIV6P1) {
clk = cpg_div6_register(core->name, 1, &parent_name, clk = cpg_div6_register(core->name, 1, &parent_name,
priv->base + core->offset); priv->base + core->offset);
} else {
clk = clk_register_fixed_factor(NULL, core->name,
parent_name, 0,
core->mult, div);
} }
break; break;
...@@ -375,8 +382,6 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod, ...@@ -375,8 +382,6 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod,
kfree(clock); kfree(clock);
} }
#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
struct cpg_mssr_clk_domain { struct cpg_mssr_clk_domain {
struct generic_pm_domain genpd; struct generic_pm_domain genpd;
struct device_node *np; struct device_node *np;
...@@ -384,6 +389,8 @@ struct cpg_mssr_clk_domain { ...@@ -384,6 +389,8 @@ struct cpg_mssr_clk_domain {
unsigned int core_pm_clks[0]; 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, static bool cpg_mssr_is_pm_clk(const struct of_phandle_args *clkspec,
struct cpg_mssr_clk_domain *pd) struct cpg_mssr_clk_domain *pd)
{ {
...@@ -407,17 +414,20 @@ static bool cpg_mssr_is_pm_clk(const struct of_phandle_args *clkspec, ...@@ -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, int cpg_mssr_attach_dev(struct generic_pm_domain *unused, struct device *dev)
struct device *dev)
{ {
struct cpg_mssr_clk_domain *pd = struct cpg_mssr_clk_domain *pd = cpg_mssr_clk_domain;
container_of(genpd, struct cpg_mssr_clk_domain, genpd);
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct of_phandle_args clkspec; struct of_phandle_args clkspec;
struct clk *clk; struct clk *clk;
int i = 0; int i = 0;
int error; 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, while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i,
&clkspec)) { &clkspec)) {
if (cpg_mssr_is_pm_clk(&clkspec, pd)) if (cpg_mssr_is_pm_clk(&clkspec, pd))
...@@ -457,8 +467,7 @@ static int cpg_mssr_attach_dev(struct generic_pm_domain *genpd, ...@@ -457,8 +467,7 @@ static int cpg_mssr_attach_dev(struct generic_pm_domain *genpd,
return error; return error;
} }
static void cpg_mssr_detach_dev(struct generic_pm_domain *genpd, void cpg_mssr_detach_dev(struct generic_pm_domain *unused, struct device *dev)
struct device *dev)
{ {
if (!list_empty(&dev->power.subsys_data->clock_list)) if (!list_empty(&dev->power.subsys_data->clock_list))
pm_clk_destroy(dev); pm_clk_destroy(dev);
...@@ -487,19 +496,11 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev, ...@@ -487,19 +496,11 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev,
pm_genpd_init(genpd, &simple_qos_governor, false); pm_genpd_init(genpd, &simple_qos_governor, false);
genpd->attach_dev = cpg_mssr_attach_dev; genpd->attach_dev = cpg_mssr_attach_dev;
genpd->detach_dev = cpg_mssr_detach_dev; genpd->detach_dev = cpg_mssr_detach_dev;
cpg_mssr_clk_domain = pd;
of_genpd_add_provider_simple(np, genpd); of_genpd_add_provider_simple(np, genpd);
return 0; 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[] = { static const struct of_device_id cpg_mssr_match[] = {
#ifdef CONFIG_ARCH_R8A7795 #ifdef CONFIG_ARCH_R8A7795
......
...@@ -37,6 +37,7 @@ enum clk_types { ...@@ -37,6 +37,7 @@ enum clk_types {
CLK_TYPE_IN, /* External Clock Input */ CLK_TYPE_IN, /* External Clock Input */
CLK_TYPE_FF, /* Fixed Factor Clock */ CLK_TYPE_FF, /* Fixed Factor Clock */
CLK_TYPE_DIV6P1, /* DIV6 Clock with 1 parent 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 */ /* Custom definitions start here */
CLK_TYPE_CUSTOM, CLK_TYPE_CUSTOM,
...@@ -53,9 +54,8 @@ enum clk_types { ...@@ -53,9 +54,8 @@ enum clk_types {
DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult) DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult)
#define DEF_DIV6P1(_name, _id, _parent, _offset) \ #define DEF_DIV6P1(_name, _id, _parent, _offset) \
DEF_BASE(_name, _id, CLK_TYPE_DIV6P1, _parent, .offset = _offset) DEF_BASE(_name, _id, CLK_TYPE_DIV6P1, _parent, .offset = _offset)
#define DEF_SD(_name, _id, _parent, _offset) \ #define DEF_DIV6_RO(_name, _id, _parent, _offset, _div) \
DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset) DEF_BASE(_name, _id, CLK_TYPE_DIV6_RO, _parent, .offset = _offset, .div = _div, .mult = 1)
/* /*
* Definitions of Module Clocks * Definitions of Module Clocks
......
...@@ -175,6 +175,19 @@ ...@@ -175,6 +175,19 @@
#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14) #define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14)
#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12) #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 0x52c
#define UTMIPLL_HW_PWRDN_CFG0_UTMIPLL_LOCK BIT(31) #define UTMIPLL_HW_PWRDN_CFG0_UTMIPLL_LOCK BIT(31)
#define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE BIT(25) #define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE BIT(25)
...@@ -416,6 +429,51 @@ static const char *mux_pllmcp_clkm[] = { ...@@ -416,6 +429,51 @@ static const char *mux_pllmcp_clkm[] = {
#define PLLU_MISC0_WRITE_MASK 0xbfffffff #define PLLU_MISC0_WRITE_MASK 0xbfffffff
#define PLLU_MISC1_WRITE_MASK 0x00000007 #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, static inline void _pll_misc_chk_default(void __iomem *base,
struct tegra_clk_pll_params *params, struct tegra_clk_pll_params *params,
u8 misc_num, u32 default_val, u32 mask) u8 misc_num, u32 default_val, u32 mask)
......
...@@ -91,7 +91,7 @@ static inline bool psci_has_ext_power_state(void) ...@@ -91,7 +91,7 @@ static inline bool psci_has_ext_power_state(void)
PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK; 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() ? const u32 mask = psci_has_ext_power_state() ?
PSCI_1_0_EXT_POWER_STATE_TYPE_MASK : PSCI_1_0_EXT_POWER_STATE_TYPE_MASK :
...@@ -100,7 +100,7 @@ bool psci_power_state_loses_context(u32 state) ...@@ -100,7 +100,7 @@ bool psci_power_state_loses_context(u32 state)
return state & mask; 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() ? const u32 valid_mask = psci_has_ext_power_state() ?
PSCI_1_0_EXT_POWER_STATE_MASK : PSCI_1_0_EXT_POWER_STATE_MASK :
...@@ -563,7 +563,7 @@ static int __init psci_0_1_init(struct device_node *np) ...@@ -563,7 +563,7 @@ static int __init psci_0_1_init(struct device_node *np)
return err; 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", .data = psci_0_1_init},
{ .compatible = "arm,psci-0.2", .data = psci_0_2_init}, { .compatible = "arm,psci-0.2", .data = psci_0_2_init},
{ .compatible = "arm,psci-1.0", .data = psci_0_2_init}, { .compatible = "arm,psci-1.0", .data = psci_0_2_init},
......
...@@ -121,7 +121,7 @@ struct tegra_dc { ...@@ -121,7 +121,7 @@ struct tegra_dc {
spinlock_t lock; spinlock_t lock;
struct drm_crtc base; struct drm_crtc base;
int powergate; unsigned int powergate;
int pipe; int pipe;
struct clk *clk; struct clk *clk;
......
...@@ -122,6 +122,7 @@ config MTK_SMI ...@@ -122,6 +122,7 @@ config MTK_SMI
mainly help enable/disable iommu and control the power domain and mainly help enable/disable iommu and control the power domain and
clocks for each local arbiter. clocks for each local arbiter.
source "drivers/memory/samsung/Kconfig"
source "drivers/memory/tegra/Kconfig" source "drivers/memory/tegra/Kconfig"
endif endif
...@@ -17,4 +17,5 @@ obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o ...@@ -17,4 +17,5 @@ obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o
obj-$(CONFIG_JZ4780_NEMC) += jz4780-nemc.o obj-$(CONFIG_JZ4780_NEMC) += jz4780-nemc.o
obj-$(CONFIG_MTK_SMI) += mtk-smi.o obj-$(CONFIG_MTK_SMI) += mtk-smi.o
obj-$(CONFIG_SAMSUNG_MC) += samsung/
obj-$(CONFIG_TEGRA_MC) += tegra/ obj-$(CONFIG_TEGRA_MC) += tegra/
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
obj-$(CONFIG_EXYNOS_SROM) += exynos-srom.o
/*
* 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");
/*
* 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 ...@@ -74,6 +74,16 @@ config MTD_PHYSMAP_OF
physically into the CPU's memory. The mapping description here is physically into the CPU's memory. The mapping description here is
taken from OF device tree. 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 config MTD_PMC_MSP_EVM
tristate "CFI Flash device mapped on PMC-Sierra MSP" tristate "CFI Flash device mapped on PMC-Sierra MSP"
depends on PMC_MSP && MTD_CFI depends on PMC_MSP && MTD_CFI
......
...@@ -18,6 +18,9 @@ obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o ...@@ -18,6 +18,9 @@ obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o
obj-$(CONFIG_MTD_PXA2XX) += pxa2xx-flash.o obj-$(CONFIG_MTD_PXA2XX) += pxa2xx-flash.o
obj-$(CONFIG_MTD_PHYSMAP) += physmap.o obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of.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_PISMO) += pismo.o
obj-$(CONFIG_MTD_PMC_MSP_EVM) += pmcmsp-flash.o obj-$(CONFIG_MTD_PMC_MSP_EVM) += pmcmsp-flash.o
obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "physmap_of_versatile.h"
struct of_flash_list { struct of_flash_list {
struct mtd_info *mtd; struct mtd_info *mtd;
...@@ -240,6 +241,11 @@ static int of_flash_probe(struct platform_device *dev) ...@@ -240,6 +241,11 @@ static int of_flash_probe(struct platform_device *dev)
info->list[i].map.size = res_size; info->list[i].map.size = res_size;
info->list[i].map.bankwidth = be32_to_cpup(width); info->list[i].map.bankwidth = be32_to_cpup(width);
info->list[i].map.device_node = dp; 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; err = -ENOMEM;
info->list[i].map.virt = ioremap(info->list[i].map.phys, info->list[i].map.virt = ioremap(info->list[i].map.phys,
......
/*
* 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);
#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 { ...@@ -295,6 +295,7 @@ struct tegra_pcie {
struct reset_control *afi_rst; struct reset_control *afi_rst;
struct reset_control *pcie_xrst; struct reset_control *pcie_xrst;
bool legacy_phy;
struct phy *phy; struct phy *phy;
struct tegra_msi msi; struct tegra_msi msi;
...@@ -311,11 +312,14 @@ struct tegra_pcie { ...@@ -311,11 +312,14 @@ struct tegra_pcie {
struct tegra_pcie_port { struct tegra_pcie_port {
struct tegra_pcie *pcie; struct tegra_pcie *pcie;
struct device_node *np;
struct list_head list; struct list_head list;
struct resource regs; struct resource regs;
void __iomem *base; void __iomem *base;
unsigned int index; unsigned int index;
unsigned int lanes; unsigned int lanes;
struct phy **phys;
}; };
struct tegra_pcie_bus { struct tegra_pcie_bus {
...@@ -860,6 +864,128 @@ static int tegra_pcie_phy_enable(struct tegra_pcie *pcie) ...@@ -860,6 +864,128 @@ static int tegra_pcie_phy_enable(struct tegra_pcie *pcie)
return 0; 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) static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
{ {
const struct tegra_pcie_soc_data *soc = pcie->soc_data; const struct tegra_pcie_soc_data *soc = pcie->soc_data;
...@@ -899,13 +1025,9 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie) ...@@ -899,13 +1025,9 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
afi_writel(pcie, value, AFI_FUSE); afi_writel(pcie, value, AFI_FUSE);
} }
if (!pcie->phy) err = tegra_pcie_phy_power_on(pcie);
err = tegra_pcie_phy_enable(pcie);
else
err = phy_power_on(pcie->phy);
if (err < 0) { 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; return err;
} }
...@@ -942,9 +1064,9 @@ static void tegra_pcie_power_off(struct tegra_pcie *pcie) ...@@ -942,9 +1064,9 @@ static void tegra_pcie_power_off(struct tegra_pcie *pcie)
/* TODO: disable and unprepare clocks? */ /* TODO: disable and unprepare clocks? */
err = phy_power_off(pcie->phy); err = tegra_pcie_phy_power_off(pcie);
if (err < 0) 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->pcie_xrst);
reset_control_assert(pcie->afi_rst); reset_control_assert(pcie->afi_rst);
...@@ -1049,6 +1171,100 @@ static int tegra_pcie_resets_get(struct tegra_pcie *pcie) ...@@ -1049,6 +1171,100 @@ static int tegra_pcie_resets_get(struct tegra_pcie *pcie)
return 0; 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) static int tegra_pcie_get_resources(struct tegra_pcie *pcie)
{ {
struct platform_device *pdev = to_platform_device(pcie->dev); struct platform_device *pdev = to_platform_device(pcie->dev);
...@@ -1067,16 +1283,9 @@ static int tegra_pcie_get_resources(struct tegra_pcie *pcie) ...@@ -1067,16 +1283,9 @@ static int tegra_pcie_get_resources(struct tegra_pcie *pcie)
return err; return err;
} }
pcie->phy = devm_phy_optional_get(pcie->dev, "pcie"); err = tegra_pcie_phys_get(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);
if (err < 0) { 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; return err;
} }
...@@ -1752,6 +1961,7 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie) ...@@ -1752,6 +1961,7 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
rp->index = index; rp->index = index;
rp->lanes = value; rp->lanes = value;
rp->pcie = pcie; rp->pcie = pcie;
rp->np = port;
rp->base = devm_ioremap_resource(pcie->dev, &rp->regs); rp->base = devm_ioremap_resource(pcie->dev, &rp->regs);
if (IS_ERR(rp->base)) if (IS_ERR(rp->base))
......
...@@ -421,4 +421,6 @@ config PHY_CYGNUS_PCIE ...@@ -421,4 +421,6 @@ config PHY_CYGNUS_PCIE
Enable this to support the Broadcom Cygnus PCIe PHY. Enable this to support the Broadcom Cygnus PCIe PHY.
If unsure, say N. If unsure, say N.
source "drivers/phy/tegra/Kconfig"
endmenu endmenu
...@@ -52,3 +52,5 @@ obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o ...@@ -52,3 +52,5 @@ obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o
obj-$(CONFIG_PHY_BRCMSTB_SATA) += phy-brcmstb-sata.o obj-$(CONFIG_PHY_BRCMSTB_SATA) += phy-brcmstb-sata.o
obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.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) ...@@ -141,7 +141,7 @@ static struct phy_provider *of_phy_provider_lookup(struct device_node *node)
if (phy_provider->dev->of_node == node) if (phy_provider->dev->of_node == node)
return phy_provider; 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) if (child == node)
return phy_provider; return phy_provider;
} }
...@@ -811,24 +811,59 @@ EXPORT_SYMBOL_GPL(devm_phy_destroy); ...@@ -811,24 +811,59 @@ EXPORT_SYMBOL_GPL(devm_phy_destroy);
/** /**
* __of_phy_provider_register() - create/register phy provider with the framework * __of_phy_provider_register() - create/register phy provider with the framework
* @dev: struct device of the phy provider * @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 * @owner: the module owner containing of_xlate
* @of_xlate: function pointer to obtain phy instance from phy provider * @of_xlate: function pointer to obtain phy instance from phy provider
* *
* Creates struct phy_provider from dev and of_xlate function pointer. * 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 * This is used in the case of dt boot for finding the phy instance from
* phy provider. * 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 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 of_phandle_args *args)) struct phy * (*of_xlate)(struct device *dev,
struct of_phandle_args *args))
{ {
struct phy_provider *phy_provider; 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); phy_provider = kzalloc(sizeof(*phy_provider), GFP_KERNEL);
if (!phy_provider) if (!phy_provider)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
phy_provider->dev = dev; phy_provider->dev = dev;
phy_provider->children = of_node_get(children);
phy_provider->owner = owner; phy_provider->owner = owner;
phy_provider->of_xlate = of_xlate; phy_provider->of_xlate = of_xlate;
...@@ -854,8 +889,9 @@ EXPORT_SYMBOL_GPL(__of_phy_provider_register); ...@@ -854,8 +889,9 @@ EXPORT_SYMBOL_GPL(__of_phy_provider_register);
* on the devres data, then, devres data is freed. * on the devres data, then, devres data is freed.
*/ */
struct phy_provider *__devm_of_phy_provider_register(struct device *dev, 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 of_phandle_args *args)) struct phy * (*of_xlate)(struct device *dev,
struct of_phandle_args *args))
{ {
struct phy_provider **ptr, *phy_provider; struct phy_provider **ptr, *phy_provider;
...@@ -863,7 +899,8 @@ struct phy_provider *__devm_of_phy_provider_register(struct device *dev, ...@@ -863,7 +899,8 @@ struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
if (!ptr) if (!ptr)
return ERR_PTR(-ENOMEM); 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)) { if (!IS_ERR(phy_provider)) {
*ptr = phy_provider; *ptr = phy_provider;
devres_add(dev, ptr); devres_add(dev, ptr);
...@@ -888,6 +925,7 @@ void of_phy_provider_unregister(struct phy_provider *phy_provider) ...@@ -888,6 +925,7 @@ void of_phy_provider_unregister(struct phy_provider *phy_provider)
mutex_lock(&phy_provider_mutex); mutex_lock(&phy_provider_mutex);
list_del(&phy_provider->list); list_del(&phy_provider->list);
of_node_put(phy_provider->children);
kfree(phy_provider); kfree(phy_provider);
mutex_unlock(&phy_provider_mutex); mutex_unlock(&phy_provider_mutex);
} }
......
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.
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
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -873,7 +873,7 @@ static const struct of_device_id tegra_xusb_padctl_of_match[] = { ...@@ -873,7 +873,7 @@ static const struct of_device_id tegra_xusb_padctl_of_match[] = {
}; };
MODULE_DEVICE_TABLE(of, 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; struct tegra_xusb_padctl *padctl;
const struct of_device_id *match; const struct of_device_id *match;
...@@ -955,8 +955,9 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev) ...@@ -955,8 +955,9 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev)
reset_control_assert(padctl->rst); reset_control_assert(padctl->rst);
return err; 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); struct tegra_xusb_padctl *padctl = platform_get_drvdata(pdev);
int err; int err;
...@@ -969,17 +970,4 @@ static int tegra_xusb_padctl_remove(struct platform_device *pdev) ...@@ -969,17 +970,4 @@ static int tegra_xusb_padctl_remove(struct platform_device *pdev)
return err; return err;
} }
EXPORT_SYMBOL_GPL(tegra_xusb_padctl_legacy_remove);
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");
...@@ -12,5 +12,8 @@ menuconfig RESET_CONTROLLER ...@@ -12,5 +12,8 @@ menuconfig RESET_CONTROLLER
If unsure, say no. If unsure, say no.
config RESET_OXNAS
bool
source "drivers/reset/sti/Kconfig" source "drivers/reset/sti/Kconfig"
source "drivers/reset/hisilicon/Kconfig" source "drivers/reset/hisilicon/Kconfig"
...@@ -8,3 +8,4 @@ obj-$(CONFIG_ARCH_STI) += sti/ ...@@ -8,3 +8,4 @@ obj-$(CONFIG_ARCH_STI) += sti/
obj-$(CONFIG_ARCH_HISI) += hisilicon/ obj-$(CONFIG_ARCH_HISI) += hisilicon/
obj-$(CONFIG_ARCH_ZYNQ) += reset-zynq.o obj-$(CONFIG_ARCH_ZYNQ) += reset-zynq.o
obj-$(CONFIG_ATH79) += reset-ath79.o obj-$(CONFIG_ATH79) += reset-ath79.o
obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
*/ */
#include <linux/atomic.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/export.h> #include <linux/export.h>
...@@ -18,19 +19,27 @@ ...@@ -18,19 +19,27 @@
#include <linux/reset-controller.h> #include <linux/reset-controller.h>
#include <linux/slab.h> #include <linux/slab.h>
static DEFINE_MUTEX(reset_controller_list_mutex); static DEFINE_MUTEX(reset_list_mutex);
static LIST_HEAD(reset_controller_list); static LIST_HEAD(reset_controller_list);
/** /**
* struct reset_control - a reset control * struct reset_control - a reset control
* @rcdev: a pointer to the reset controller device * @rcdev: a pointer to the reset controller device
* this reset control belongs to * this reset control belongs to
* @list: list entry for the rcdev's reset controller list
* @id: ID of the reset controller in the reset * @id: ID of the reset controller in the reset
* controller device * 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_control {
struct reset_controller_dev *rcdev; struct reset_controller_dev *rcdev;
struct list_head list;
unsigned int id; 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) ...@@ -62,9 +71,11 @@ int reset_controller_register(struct reset_controller_dev *rcdev)
rcdev->of_xlate = of_reset_simple_xlate; 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); list_add(&rcdev->list, &reset_controller_list);
mutex_unlock(&reset_controller_list_mutex); mutex_unlock(&reset_list_mutex);
return 0; return 0;
} }
...@@ -76,18 +87,23 @@ EXPORT_SYMBOL_GPL(reset_controller_register); ...@@ -76,18 +87,23 @@ EXPORT_SYMBOL_GPL(reset_controller_register);
*/ */
void reset_controller_unregister(struct reset_controller_dev *rcdev) void reset_controller_unregister(struct reset_controller_dev *rcdev)
{ {
mutex_lock(&reset_controller_list_mutex); mutex_lock(&reset_list_mutex);
list_del(&rcdev->list); list_del(&rcdev->list);
mutex_unlock(&reset_controller_list_mutex); mutex_unlock(&reset_list_mutex);
} }
EXPORT_SYMBOL_GPL(reset_controller_unregister); EXPORT_SYMBOL_GPL(reset_controller_unregister);
/** /**
* reset_control_reset - reset the controlled device * reset_control_reset - reset the controlled device
* @rstc: reset controller * @rstc: reset controller
*
* Calling this on a shared reset controller is an error.
*/ */
int reset_control_reset(struct reset_control *rstc) int reset_control_reset(struct reset_control *rstc)
{ {
if (WARN_ON(rstc->shared))
return -EINVAL;
if (rstc->rcdev->ops->reset) if (rstc->rcdev->ops->reset)
return rstc->rcdev->ops->reset(rstc->rcdev, rstc->id); return rstc->rcdev->ops->reset(rstc->rcdev, rstc->id);
...@@ -98,26 +114,48 @@ EXPORT_SYMBOL_GPL(reset_control_reset); ...@@ -98,26 +114,48 @@ EXPORT_SYMBOL_GPL(reset_control_reset);
/** /**
* reset_control_assert - asserts the reset line * reset_control_assert - asserts the reset line
* @rstc: reset controller * @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) int reset_control_assert(struct reset_control *rstc)
{ {
if (rstc->rcdev->ops->assert) if (!rstc->rcdev->ops->assert)
return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id); return -ENOTSUPP;
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); EXPORT_SYMBOL_GPL(reset_control_assert);
/** /**
* reset_control_deassert - deasserts the reset line * reset_control_deassert - deasserts the reset line
* @rstc: reset controller * @rstc: reset controller
*
* After calling this function, the reset is guaranteed to be deasserted.
*/ */
int reset_control_deassert(struct reset_control *rstc) int reset_control_deassert(struct reset_control *rstc)
{ {
if (rstc->rcdev->ops->deassert) if (!rstc->rcdev->ops->deassert)
return rstc->rcdev->ops->deassert(rstc->rcdev, rstc->id); return -ENOTSUPP;
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); EXPORT_SYMBOL_GPL(reset_control_deassert);
...@@ -136,18 +174,54 @@ int reset_control_status(struct reset_control *rstc) ...@@ -136,18 +174,54 @@ int reset_control_status(struct reset_control *rstc)
} }
EXPORT_SYMBOL_GPL(reset_control_status); EXPORT_SYMBOL_GPL(reset_control_status);
/** static struct reset_control *__reset_control_get(
* of_reset_control_get_by_index - Lookup and obtain a reference to a reset struct reset_controller_dev *rcdev,
* controller by index. unsigned int index, int shared)
* @node: device to be reset by the controller {
* @index: index of the reset controller struct reset_control *rstc;
*
* This is to be used to perform a list of resets for a device or power domain lockdep_assert_held(&reset_list_mutex);
* in whatever order. Returns a struct reset_control or IS_ERR() condition
* containing errno. list_for_each_entry(rstc, &rcdev->reset_control_head, list) {
*/ if (rstc->id == index) {
struct reset_control *of_reset_control_get_by_index(struct device_node *node, if (WARN_ON(!rstc->shared || !shared))
int index) 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_control *rstc;
struct reset_controller_dev *r, *rcdev; struct reset_controller_dev *r, *rcdev;
...@@ -155,12 +229,22 @@ struct reset_control *of_reset_control_get_by_index(struct device_node *node, ...@@ -155,12 +229,22 @@ struct reset_control *of_reset_control_get_by_index(struct device_node *node,
int rstc_id; int rstc_id;
int ret; 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", ret = of_parse_phandle_with_args(node, "resets", "#reset-cells",
index, &args); index, &args);
if (ret) if (ret)
return ERR_PTR(ret); return ERR_PTR(ret);
mutex_lock(&reset_controller_list_mutex); mutex_lock(&reset_list_mutex);
rcdev = NULL; rcdev = NULL;
list_for_each_entry(r, &reset_controller_list, list) { list_for_each_entry(r, &reset_controller_list, list) {
if (args.np == r->of_node) { if (args.np == r->of_node) {
...@@ -171,78 +255,29 @@ struct reset_control *of_reset_control_get_by_index(struct device_node *node, ...@@ -171,78 +255,29 @@ struct reset_control *of_reset_control_get_by_index(struct device_node *node,
of_node_put(args.np); of_node_put(args.np);
if (!rcdev) { if (!rcdev) {
mutex_unlock(&reset_controller_list_mutex); mutex_unlock(&reset_list_mutex);
return ERR_PTR(-EPROBE_DEFER); return ERR_PTR(-EPROBE_DEFER);
} }
if (WARN_ON(args.args_count != rcdev->of_reset_n_cells)) { 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); return ERR_PTR(-EINVAL);
} }
rstc_id = rcdev->of_xlate(rcdev, &args); rstc_id = rcdev->of_xlate(rcdev, &args);
if (rstc_id < 0) { if (rstc_id < 0) {
mutex_unlock(&reset_controller_list_mutex); mutex_unlock(&reset_list_mutex);
return ERR_PTR(rstc_id); return ERR_PTR(rstc_id);
} }
try_module_get(rcdev->owner); /* reset_list_mutex also protects the rcdev's reset_control list */
mutex_unlock(&reset_controller_list_mutex); 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; mutex_unlock(&reset_list_mutex);
rstc->id = rstc_id;
return rstc; return rstc;
} }
EXPORT_SYMBOL_GPL(of_reset_control_get_by_index); EXPORT_SYMBOL_GPL(__of_reset_control_get);
/**
* 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);
/** /**
* reset_control_put - free the reset controller * reset_control_put - free the reset controller
...@@ -254,8 +289,9 @@ void reset_control_put(struct reset_control *rstc) ...@@ -254,8 +289,9 @@ void reset_control_put(struct reset_control *rstc)
if (IS_ERR(rstc)) if (IS_ERR(rstc))
return; return;
module_put(rstc->rcdev->owner); mutex_lock(&reset_list_mutex);
kfree(rstc); __reset_control_put(rstc);
mutex_unlock(&reset_list_mutex);
} }
EXPORT_SYMBOL_GPL(reset_control_put); EXPORT_SYMBOL_GPL(reset_control_put);
...@@ -264,16 +300,8 @@ static void devm_reset_control_release(struct device *dev, void *res) ...@@ -264,16 +300,8 @@ static void devm_reset_control_release(struct device *dev, void *res)
reset_control_put(*(struct reset_control **)res); reset_control_put(*(struct reset_control **)res);
} }
/** struct reset_control *__devm_reset_control_get(struct device *dev,
* devm_reset_control_get - resource managed reset_control_get() const char *id, int index, int shared)
* @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 **ptr, *rstc; struct reset_control **ptr, *rstc;
...@@ -282,7 +310,8 @@ struct reset_control *devm_reset_control_get(struct device *dev, const char *id) ...@@ -282,7 +310,8 @@ struct reset_control *devm_reset_control_get(struct device *dev, const char *id)
if (!ptr) if (!ptr)
return ERR_PTR(-ENOMEM); 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)) { if (!IS_ERR(rstc)) {
*ptr = rstc; *ptr = rstc;
devres_add(dev, ptr); devres_add(dev, ptr);
...@@ -292,7 +321,7 @@ struct reset_control *devm_reset_control_get(struct device *dev, const char *id) ...@@ -292,7 +321,7 @@ struct reset_control *devm_reset_control_get(struct device *dev, const char *id)
return rstc; 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 * device_reset - find reset controller associated with the device
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment