Commit b2e3c431 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.

  A handful of driver changes this time around. The larger changes are:

   - Reset drivers for hi3660 and zx2967

   - AHCI driver for Davinci, acked by Tejun and brought in here due to
     platform dependencies

   - Cleanups of atmel-ebi (External Bus Interface)

   - Tweaks for Rockchip GRF (General Register File) usage (kitchensink
     misc register range on the SoCs)

   - PM domains changes for support of two new ZTE SoCs (zx296718 and
     zx2967)"

* tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (53 commits)
  soc: samsung: pmu: Add register defines for pad retention control
  reset: make zx2967 explicitly non-modular
  reset: core: fix reset_control_put
  soc: samsung: pm_domains: Read domain name from the new label property
  soc: samsung: pm_domains: Remove message about failed memory allocation
  soc: samsung: pm_domains: Remove unused name field
  soc: samsung: pm_domains: Use full names in subdomains registration log
  sata: ahci-da850: un-hardcode the MPY bits
  sata: ahci-da850: add a workaround for controller instability
  sata: ahci: export ahci_do_hardreset() locally
  sata: ahci-da850: implement a workaround for the softreset quirk
  sata: ahci-da850: add device tree match table
  sata: ahci-da850: get the sata clock using a connection id
  soc: samsung: pmu: Remove duplicated define for ARM_L2_OPTION register
  memory: atmel-ebi: Enable the SMC clock if specified
  soc: samsung: pmu: Remove unused and duplicated defines
  memory: atmel-ebi: Properly handle multiple reference to the same CS
  memory: atmel-ebi: Fix the test to enable generic SMC logic
  soc: samsung: pm_domains: Add new Exynos5433 compatible
  soc: samsung: pmu: Add dummy support for Exynos5433 SoC
  ...
parents c61c15e0 db27dd05
...@@ -6,12 +6,15 @@ to gate power to one or more peripherals on the processor. ...@@ -6,12 +6,15 @@ to gate power to one or more peripherals on the processor.
Required Properties: Required Properties:
- compatible: should be one of the following. - compatible: should be one of the following.
* samsung,exynos4210-pd - for exynos4210 type power domain. * samsung,exynos4210-pd - for exynos4210 type power domain.
* samsung,exynos5433-pd - for exynos5433 type power domain.
- reg: physical base address of the controller and length of memory mapped - reg: physical base address of the controller and length of memory mapped
region. region.
- #power-domain-cells: number of cells in power domain specifier; - #power-domain-cells: number of cells in power domain specifier;
must be 0. must be 0.
Optional Properties: Optional Properties:
- label: Human readable string with domain name. Will be visible in userspace
to let user to distinguish between multiple domains in SoC.
- clocks: List of clock handles. The parent clocks of the input clocks to the - clocks: List of clock handles. The parent clocks of the input clocks to the
devices in this power domain are set to oscclk before power gating devices in this power domain are set to oscclk before power gating
and restored back after powering on a domain. This is required for and restored back after powering on a domain. This is required for
...@@ -38,6 +41,7 @@ Example: ...@@ -38,6 +41,7 @@ Example:
compatible = "samsung,exynos4210-pd"; compatible = "samsung,exynos4210-pd";
reg = <0x10023C00 0x10>; reg = <0x10023C00 0x10>;
#power-domain-cells = <0>; #power-domain-cells = <0>;
label = "LCD0";
}; };
mfc_pd: power-domain@10044060 { mfc_pd: power-domain@10044060 {
...@@ -46,6 +50,7 @@ Example: ...@@ -46,6 +50,7 @@ Example:
clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MOUT_USER_ACLK333>; clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MOUT_USER_ACLK333>;
clock-names = "oscclk", "clk0"; clock-names = "oscclk", "clk0";
#power-domain-cells = <0>; #power-domain-cells = <0>;
label = "MFC";
}; };
See Documentation/devicetree/bindings/power/power_domain.txt for description See Documentation/devicetree/bindings/power/power_domain.txt for description
......
Hisilicon System Reset Controller
======================================
Please also refer to reset.txt in this directory for common reset
controller binding usage.
The reset controller registers are part of the system-ctl block on
hi3660 SoC.
Required properties:
- compatible: should be
"hisilicon,hi3660-reset"
- hisi,rst-syscon: phandle of the reset's syscon.
- #reset-cells : Specifies the number of cells needed to encode a
reset source. The type shall be a <u32> and the value shall be 2.
Cell #1 : offset of the reset assert control
register from the syscon register base
offset + 4: deassert control register
offset + 8: status control register
Cell #2 : bit position of the reset in the reset control register
Example:
iomcu: iomcu@ffd7e000 {
compatible = "hisilicon,hi3660-iomcu", "syscon";
reg = <0x0 0xffd7e000 0x0 0x1000>;
};
iomcu_rst: iomcu_rst_controller {
compatible = "hisilicon,hi3660-reset";
hisi,rst-syscon = <&iomcu>;
#reset-cells = <2>;
};
Specifying reset lines connected to IP modules
==============================================
example:
i2c0: i2c@..... {
...
resets = <&iomcu_rst 0x20 3>; /* offset: 0x20; bit: 3 */
...
};
...@@ -63,7 +63,7 @@ Example: ...@@ -63,7 +63,7 @@ Example:
-------- --------
The following example demonstrates a syscon node, the reset controller node The following example demonstrates a syscon node, the reset controller node
using the syscon node, and a consumer (a DSP device) on the TI Keystone 2 using the syscon node, and a consumer (a DSP device) on the TI Keystone 2
Edison SoC. 66AK2E SoC.
/ { / {
soc { soc {
...@@ -71,13 +71,13 @@ Edison SoC. ...@@ -71,13 +71,13 @@ Edison SoC.
compatible = "syscon", "simple-mfd"; compatible = "syscon", "simple-mfd";
reg = <0x02350000 0x1000>; reg = <0x02350000 0x1000>;
pscrst: psc-reset { pscrst: reset-controller {
compatible = "ti,k2e-pscrst", "ti,syscon-reset"; compatible = "ti,k2e-pscrst", "ti,syscon-reset";
#reset-cells = <1>; #reset-cells = <1>;
ti,reset-bits = < ti,reset-bits = <
0xa3c 8 0xa3c 8 0x83c 8 (ASSERT_SET|DEASSERT_CLEAR|STATUS_SET) /* 0: pcrst-dsp0 */ 0xa3c 8 0xa3c 8 0x83c 8 (ASSERT_CLEAR | DEASSERT_SET | STATUS_CLEAR) /* 0: dsp0 */
0xa40 5 0xa44 3 0 0 (ASSERT_SET|DEASSERT_CLEAR|STATUS_NONE) /* 1: pcrst-example */ 0xa40 5 0xa44 3 0 0 (ASSERT_SET | DEASSERT_CLEAR | STATUS_NONE) /* 1: example */
>; >;
}; };
}; };
......
...@@ -6,14 +6,14 @@ System reset ...@@ -6,14 +6,14 @@ System reset
Required properties: Required properties:
- compatible: should be one of the following: - compatible: should be one of the following:
"socionext,uniphier-sld3-reset" - for sLD3 SoC. "socionext,uniphier-sld3-reset" - for sLD3 SoC
"socionext,uniphier-ld4-reset" - for LD4 SoC. "socionext,uniphier-ld4-reset" - for LD4 SoC
"socionext,uniphier-pro4-reset" - for Pro4 SoC. "socionext,uniphier-pro4-reset" - for Pro4 SoC
"socionext,uniphier-sld8-reset" - for sLD8 SoC. "socionext,uniphier-sld8-reset" - for sLD8 SoC
"socionext,uniphier-pro5-reset" - for Pro5 SoC. "socionext,uniphier-pro5-reset" - for Pro5 SoC
"socionext,uniphier-pxs2-reset" - for PXs2/LD6b SoC. "socionext,uniphier-pxs2-reset" - for PXs2/LD6b SoC
"socionext,uniphier-ld11-reset" - for LD11 SoC. "socionext,uniphier-ld11-reset" - for LD11 SoC
"socionext,uniphier-ld20-reset" - for LD20 SoC. "socionext,uniphier-ld20-reset" - for LD20 SoC
- #reset-cells: should be 1. - #reset-cells: should be 1.
Example: Example:
...@@ -37,14 +37,15 @@ Media I/O (MIO) reset, SD reset ...@@ -37,14 +37,15 @@ Media I/O (MIO) reset, SD reset
Required properties: Required properties:
- compatible: should be one of the following: - compatible: should be one of the following:
"socionext,uniphier-sld3-mio-reset" - for sLD3 SoC. "socionext,uniphier-sld3-mio-reset" - for sLD3 SoC
"socionext,uniphier-ld4-mio-reset" - for LD4 SoC. "socionext,uniphier-ld4-mio-reset" - for LD4 SoC
"socionext,uniphier-pro4-mio-reset" - for Pro4 SoC. "socionext,uniphier-pro4-mio-reset" - for Pro4 SoC
"socionext,uniphier-sld8-mio-reset" - for sLD8 SoC. "socionext,uniphier-sld8-mio-reset" - for sLD8 SoC
"socionext,uniphier-pro5-sd-reset" - for Pro5 SoC. "socionext,uniphier-pro5-sd-reset" - for Pro5 SoC
"socionext,uniphier-pxs2-sd-reset" - for PXs2/LD6b SoC. "socionext,uniphier-pxs2-sd-reset" - for PXs2/LD6b SoC
"socionext,uniphier-ld11-mio-reset" - for LD11 SoC. "socionext,uniphier-ld11-mio-reset" - for LD11 SoC (MIO)
"socionext,uniphier-ld20-sd-reset" - for LD20 SoC. "socionext,uniphier-ld11-sd-reset" - for LD11 SoC (SD)
"socionext,uniphier-ld20-sd-reset" - for LD20 SoC
- #reset-cells: should be 1. - #reset-cells: should be 1.
Example: Example:
...@@ -68,13 +69,13 @@ Peripheral reset ...@@ -68,13 +69,13 @@ Peripheral reset
Required properties: Required properties:
- compatible: should be one of the following: - compatible: should be one of the following:
"socionext,uniphier-ld4-peri-reset" - for LD4 SoC. "socionext,uniphier-ld4-peri-reset" - for LD4 SoC
"socionext,uniphier-pro4-peri-reset" - for Pro4 SoC. "socionext,uniphier-pro4-peri-reset" - for Pro4 SoC
"socionext,uniphier-sld8-peri-reset" - for sLD8 SoC. "socionext,uniphier-sld8-peri-reset" - for sLD8 SoC
"socionext,uniphier-pro5-peri-reset" - for Pro5 SoC. "socionext,uniphier-pro5-peri-reset" - for Pro5 SoC
"socionext,uniphier-pxs2-peri-reset" - for PXs2/LD6b SoC. "socionext,uniphier-pxs2-peri-reset" - for PXs2/LD6b SoC
"socionext,uniphier-ld11-peri-reset" - for LD11 SoC. "socionext,uniphier-ld11-peri-reset" - for LD11 SoC
"socionext,uniphier-ld20-peri-reset" - for LD20 SoC. "socionext,uniphier-ld20-peri-reset" - for LD20 SoC
- #reset-cells: should be 1. - #reset-cells: should be 1.
Example: Example:
......
ZTE zx2967 SoCs Reset Controller
=======================================
Please also refer to reset.txt in this directory for common reset
controller binding usage.
Required properties:
- compatible: should be one of the following.
* zte,zx296718-reset
- reg: physical base address of the controller and length of memory mapped
region.
- #reset-cells: must be 1.
example:
reset: reset-controller@1461060 {
compatible = "zte,zx296718-reset";
reg = <0x01461060 0x8>;
#reset-cells = <1>;
};
...@@ -5,11 +5,13 @@ is composed of many registers for system control. ...@@ -5,11 +5,13 @@ is composed of many registers for system control.
From RK3368 SoCs, the GRF is divided into two sections, From RK3368 SoCs, the GRF is divided into two sections,
- GRF, used for general non-secure system, - GRF, used for general non-secure system,
- SGRF, used for general secure system,
- PMUGRF, used for always on system - PMUGRF, used for always on system
Required Properties: Required Properties:
- compatible: GRF should be one of the followings - compatible: GRF should be one of the followings
- "rockchip,rk3036-grf", "syscon": for rk3036
- "rockchip,rk3066-grf", "syscon": for rk3066 - "rockchip,rk3066-grf", "syscon": for rk3066
- "rockchip,rk3188-grf", "syscon": for rk3188 - "rockchip,rk3188-grf", "syscon": for rk3188
- "rockchip,rk3228-grf", "syscon": for rk3228 - "rockchip,rk3228-grf", "syscon": for rk3228
...@@ -19,6 +21,8 @@ Required Properties: ...@@ -19,6 +21,8 @@ Required Properties:
- compatible: PMUGRF should be one of the followings - compatible: PMUGRF should be one of the followings
- "rockchip,rk3368-pmugrf", "syscon": for rk3368 - "rockchip,rk3368-pmugrf", "syscon": for rk3368
- "rockchip,rk3399-pmugrf", "syscon": for rk3399 - "rockchip,rk3399-pmugrf", "syscon": for rk3399
- compatible: SGRF should be one of the following
- "rockchip,rk3288-sgrf", "syscon": for rk3288
- reg: physical base address of the controller and length of memory mapped - reg: physical base address of the controller and length of memory mapped
region. region.
......
...@@ -6,6 +6,7 @@ powered up/down by software based on different application scenes to save power. ...@@ -6,6 +6,7 @@ powered up/down by software based on different application scenes to save power.
Required properties for power domain controller: 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,rk3328-power-controller" - for RK3328 SoCs.
"rockchip,rk3368-power-controller" - for RK3368 SoCs. "rockchip,rk3368-power-controller" - for RK3368 SoCs.
"rockchip,rk3399-power-controller" - for RK3399 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.
...@@ -16,6 +17,7 @@ Required properties for power domain controller: ...@@ -16,6 +17,7 @@ Required properties for power domain controller:
Required properties for power domain sub nodes: 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/rk3328-power.h" - for RK3328 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. "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
...@@ -90,6 +92,7 @@ containing a phandle to the power device node and an index specifying which ...@@ -90,6 +92,7 @@ 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/rk3328-power.h" - for rk3328 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. "include/dt-bindings/power/rk3399-power.h" - for rk3399 type power domain.
......
* ZTE zx2967 family Power Domains
zx2967 family includes support for multiple power domains which are used
to gate power to one or more peripherals on the processor.
Required Properties:
- compatible: should be one of the following.
* zte,zx296718-pcu - for zx296718 power domain.
- reg: physical base address of the controller and length of memory mapped
region.
- #power-domain-cells: Must be 1.
Example:
pcu_domain: pcu@117000 {
compatible = "zte,zx296718-pcu";
reg = <0x00117000 0x1000>;
#power-domain-cells = <1>;
};
...@@ -1633,6 +1633,7 @@ F: arch/arm64/boot/dts/qcom/* ...@@ -1633,6 +1633,7 @@ F: arch/arm64/boot/dts/qcom/*
F: drivers/i2c/busses/i2c-qup.c F: drivers/i2c/busses/i2c-qup.c
F: drivers/clk/qcom/ F: drivers/clk/qcom/
F: drivers/pinctrl/qcom/ F: drivers/pinctrl/qcom/
F: drivers/dma/qcom/
F: drivers/soc/qcom/ F: drivers/soc/qcom/
F: drivers/spi/spi-qup.c F: drivers/spi/spi-qup.c
F: drivers/tty/serial/msm_serial.h F: drivers/tty/serial/msm_serial.h
...@@ -1987,12 +1988,18 @@ F: arch/arm/mach-pxa/include/mach/z2.h ...@@ -1987,12 +1988,18 @@ F: arch/arm/mach-pxa/include/mach/z2.h
ARM/ZTE ARCHITECTURE ARM/ZTE ARCHITECTURE
M: Jun Nie <jun.nie@linaro.org> M: Jun Nie <jun.nie@linaro.org>
M: Baoyou Xie <baoyou.xie@linaro.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained S: Maintained
F: arch/arm/mach-zx/ F: arch/arm/mach-zx/
F: drivers/clk/zte/ F: drivers/clk/zte/
F: drivers/reset/reset-zx2967.c
F: drivers/soc/zte/
F: Documentation/devicetree/bindings/arm/zte.txt F: Documentation/devicetree/bindings/arm/zte.txt
F: Documentation/devicetree/bindings/clock/zx296702-clk.txt F: Documentation/devicetree/bindings/clock/zx296702-clk.txt
F: Documentation/devicetree/bindings/reset/zte,zx2967-reset.txt
F: Documentation/devicetree/bindings/soc/zte/
F: include/dt-bindings/soc/zx*.h
ARM/ZYNQ ARCHITECTURE ARM/ZYNQ ARCHITECTURE
M: Michal Simek <michal.simek@xilinx.com> M: Michal Simek <michal.simek@xilinx.com>
......
...@@ -345,9 +345,9 @@ static void exynos5420_pm_prepare(void) ...@@ -345,9 +345,9 @@ static void exynos5420_pm_prepare(void)
if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM)) if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM))
pmu_raw_writel(virt_to_phys(mcpm_entry_point), S5P_INFORM0); pmu_raw_writel(virt_to_phys(mcpm_entry_point), S5P_INFORM0);
tmp = pmu_raw_readl(EXYNOS5_ARM_L2_OPTION); tmp = pmu_raw_readl(EXYNOS_L2_OPTION(0));
tmp &= ~EXYNOS5_USE_RETENTION; tmp &= ~EXYNOS_L2_USE_RETENTION;
pmu_raw_writel(tmp, EXYNOS5_ARM_L2_OPTION); pmu_raw_writel(tmp, EXYNOS_L2_OPTION(0));
tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1); tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1);
tmp |= EXYNOS5420_UFS; tmp |= EXYNOS5420_UFS;
......
...@@ -29,13 +29,11 @@ ...@@ -29,13 +29,11 @@
#include "core.h" #include "core.h"
#include "pm.h" #include "pm.h"
#define RK3288_GRF_SOC_CON0 0x244
#define RK3288_TIMER6_7_PHYS 0xff810000 #define RK3288_TIMER6_7_PHYS 0xff810000
static void __init rockchip_timer_init(void) static void __init rockchip_timer_init(void)
{ {
if (of_machine_is_compatible("rockchip,rk3288")) { if (of_machine_is_compatible("rockchip,rk3288")) {
struct regmap *grf;
void __iomem *reg_base; void __iomem *reg_base;
/* /*
...@@ -54,16 +52,6 @@ static void __init rockchip_timer_init(void) ...@@ -54,16 +52,6 @@ static void __init rockchip_timer_init(void)
} else { } else {
pr_err("rockchip: could not map timer7 registers\n"); pr_err("rockchip: could not map timer7 registers\n");
} }
/*
* Disable auto jtag/sdmmc switching that causes issues
* with the mmc controllers making them unreliable
*/
grf = syscon_regmap_lookup_by_compatible("rockchip,rk3288-grf");
if (!IS_ERR(grf))
regmap_write(grf, RK3288_GRF_SOC_CON0, 0x10000000);
else
pr_err("rockchip: could not get grf syscon\n");
} }
of_clk_init(NULL); of_clk_init(NULL);
......
...@@ -398,6 +398,9 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class, ...@@ -398,6 +398,9 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
int pmp, unsigned long deadline, int pmp, unsigned long deadline,
int (*check_ready)(struct ata_link *link)); int (*check_ready)(struct ata_link *link));
int ahci_do_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline, bool *online);
unsigned int ahci_qc_issue(struct ata_queued_cmd *qc); unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
int ahci_stop_engine(struct ata_port *ap); int ahci_stop_engine(struct ata_port *ap);
void ahci_start_fis_rx(struct ata_port *ap); void ahci_start_fis_rx(struct ata_port *ap);
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "ahci.h" #include "ahci.h"
#define DRV_NAME "ahci_da850" #define DRV_NAME "ahci_da850"
#define HARDRESET_RETRIES 5
/* SATA PHY Control Register offset from AHCI base */ /* SATA PHY Control Register offset from AHCI base */
#define SATA_P0PHYCR_REG 0x178 #define SATA_P0PHYCR_REG 0x178
...@@ -28,17 +29,8 @@ ...@@ -28,17 +29,8 @@
#define SATA_PHY_TXSWING(x) ((x) << 19) #define SATA_PHY_TXSWING(x) ((x) << 19)
#define SATA_PHY_ENPLL(x) ((x) << 31) #define SATA_PHY_ENPLL(x) ((x) << 31)
/*
* The multiplier needed for 1.5GHz PLL output.
*
* NOTE: This is currently hardcoded to be suitable for 100MHz crystal
* frequency (which is used by DA850 EVM board) and may need to be changed
* if you would like to use this driver on some other board.
*/
#define DA850_SATA_CLK_MULTIPLIER 7
static void da850_sata_init(struct device *dev, void __iomem *pwrdn_reg, static void da850_sata_init(struct device *dev, void __iomem *pwrdn_reg,
void __iomem *ahci_base) void __iomem *ahci_base, u32 mpy)
{ {
unsigned int val; unsigned int val;
...@@ -47,18 +39,122 @@ static void da850_sata_init(struct device *dev, void __iomem *pwrdn_reg, ...@@ -47,18 +39,122 @@ static void da850_sata_init(struct device *dev, void __iomem *pwrdn_reg,
val &= ~BIT(0); val &= ~BIT(0);
writel(val, pwrdn_reg); writel(val, pwrdn_reg);
val = SATA_PHY_MPY(DA850_SATA_CLK_MULTIPLIER + 1) | SATA_PHY_LOS(1) | val = SATA_PHY_MPY(mpy) | SATA_PHY_LOS(1) | SATA_PHY_RXCDR(4) |
SATA_PHY_RXCDR(4) | SATA_PHY_RXEQ(1) | SATA_PHY_TXSWING(3) | SATA_PHY_RXEQ(1) | SATA_PHY_TXSWING(3) | SATA_PHY_ENPLL(1);
SATA_PHY_ENPLL(1);
writel(val, ahci_base + SATA_P0PHYCR_REG); writel(val, ahci_base + SATA_P0PHYCR_REG);
} }
static u32 ahci_da850_calculate_mpy(unsigned long refclk_rate)
{
u32 pll_output = 1500000000, needed;
/*
* We need to determine the value of the multiplier (MPY) bits.
* In order to include the 12.5 multiplier we need to first divide
* the refclk rate by ten.
*
* __div64_32() turned out to be unreliable, sometimes returning
* false results.
*/
WARN((refclk_rate % 10) != 0, "refclk must be divisible by 10");
needed = pll_output / (refclk_rate / 10);
/*
* What we have now is (multiplier * 10).
*
* Let's determine the actual register value we need to write.
*/
switch (needed) {
case 50:
return 0x1;
case 60:
return 0x2;
case 80:
return 0x4;
case 100:
return 0x5;
case 120:
return 0x6;
case 125:
return 0x7;
case 150:
return 0x8;
case 200:
return 0x9;
case 250:
return 0xa;
default:
/*
* We should have divided evenly - if not, return an invalid
* value.
*/
return 0;
}
}
static int ahci_da850_softreset(struct ata_link *link,
unsigned int *class, unsigned long deadline)
{
int pmp, ret;
pmp = sata_srst_pmp(link);
/*
* There's an issue with the SATA controller on da850 SoCs: if we
* enable Port Multiplier support, but the drive is connected directly
* to the board, it can't be detected. As a workaround: if PMP is
* enabled, we first call ahci_do_softreset() and pass it the result of
* sata_srst_pmp(). If this call fails, we retry with pmp = 0.
*/
ret = ahci_do_softreset(link, class, pmp, deadline, ahci_check_ready);
if (pmp && ret == -EBUSY)
return ahci_do_softreset(link, class, 0,
deadline, ahci_check_ready);
return ret;
}
static int ahci_da850_hardreset(struct ata_link *link,
unsigned int *class, unsigned long deadline)
{
int ret, retry = HARDRESET_RETRIES;
bool online;
/*
* In order to correctly service the LCD controller of the da850 SoC,
* we increased the PLL0 frequency to 456MHz from the default 300MHz.
*
* This made the SATA controller unstable and the hardreset operation
* does not always succeed the first time. Before really giving up to
* bring up the link, retry the reset a couple times.
*/
do {
ret = ahci_do_hardreset(link, class, deadline, &online);
if (online)
return ret;
} while (retry--);
return ret;
}
static struct ata_port_operations ahci_da850_port_ops = {
.inherits = &ahci_platform_ops,
.softreset = ahci_da850_softreset,
/*
* No need to override .pmp_softreset - it's only used for actual
* PMP-enabled ports.
*/
.hardreset = ahci_da850_hardreset,
.pmp_hardreset = ahci_da850_hardreset,
};
static const struct ata_port_info ahci_da850_port_info = { static const struct ata_port_info ahci_da850_port_info = {
.flags = AHCI_FLAG_COMMON, .flags = AHCI_FLAG_COMMON,
.pio_mask = ATA_PIO4, .pio_mask = ATA_PIO4,
.udma_mask = ATA_UDMA6, .udma_mask = ATA_UDMA6,
.port_ops = &ahci_platform_ops, .port_ops = &ahci_da850_port_ops,
}; };
static struct scsi_host_template ahci_platform_sht = { static struct scsi_host_template ahci_platform_sht = {
...@@ -69,14 +165,52 @@ static int ahci_da850_probe(struct platform_device *pdev) ...@@ -69,14 +165,52 @@ static int ahci_da850_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct ahci_host_priv *hpriv; struct ahci_host_priv *hpriv;
struct resource *res;
void __iomem *pwrdn_reg; void __iomem *pwrdn_reg;
struct resource *res;
struct clk *clk;
u32 mpy;
int rc; int rc;
hpriv = ahci_platform_get_resources(pdev); hpriv = ahci_platform_get_resources(pdev);
if (IS_ERR(hpriv)) if (IS_ERR(hpriv))
return PTR_ERR(hpriv); return PTR_ERR(hpriv);
/*
* Internally ahci_platform_get_resources() calls clk_get(dev, NULL)
* when trying to obtain the functional clock. This SATA controller
* uses two clocks for which we specify two connection ids. If we don't
* have the functional clock at this point - call clk_get() again with
* con_id = "fck".
*/
if (!hpriv->clks[0]) {
clk = clk_get(dev, "fck");
if (IS_ERR(clk))
return PTR_ERR(clk);
hpriv->clks[0] = clk;
}
/*
* The second clock used by ahci-da850 is the external REFCLK. If we
* didn't get it from ahci_platform_get_resources(), let's try to
* specify the con_id in clk_get().
*/
if (!hpriv->clks[1]) {
clk = clk_get(dev, "refclk");
if (IS_ERR(clk)) {
dev_err(dev, "unable to obtain the reference clock");
return -ENODEV;
}
hpriv->clks[1] = clk;
}
mpy = ahci_da850_calculate_mpy(clk_get_rate(hpriv->clks[1]));
if (mpy == 0) {
dev_err(dev, "invalid REFCLK multiplier value: 0x%x", mpy);
return -EINVAL;
}
rc = ahci_platform_enable_resources(hpriv); rc = ahci_platform_enable_resources(hpriv);
if (rc) if (rc)
return rc; return rc;
...@@ -89,7 +223,7 @@ static int ahci_da850_probe(struct platform_device *pdev) ...@@ -89,7 +223,7 @@ static int ahci_da850_probe(struct platform_device *pdev)
if (!pwrdn_reg) if (!pwrdn_reg)
goto disable_resources; goto disable_resources;
da850_sata_init(dev, pwrdn_reg, hpriv->mmio); da850_sata_init(dev, pwrdn_reg, hpriv->mmio, mpy);
rc = ahci_platform_init_host(pdev, hpriv, &ahci_da850_port_info, rc = ahci_platform_init_host(pdev, hpriv, &ahci_da850_port_info,
&ahci_platform_sht); &ahci_platform_sht);
...@@ -105,11 +239,18 @@ static int ahci_da850_probe(struct platform_device *pdev) ...@@ -105,11 +239,18 @@ static int ahci_da850_probe(struct platform_device *pdev)
static SIMPLE_DEV_PM_OPS(ahci_da850_pm_ops, ahci_platform_suspend, static SIMPLE_DEV_PM_OPS(ahci_da850_pm_ops, ahci_platform_suspend,
ahci_platform_resume); ahci_platform_resume);
static const struct of_device_id ahci_da850_of_match[] = {
{ .compatible = "ti,da850-ahci", },
{ },
};
MODULE_DEVICE_TABLE(of, ahci_da850_of_match);
static struct platform_driver ahci_da850_driver = { static struct platform_driver ahci_da850_driver = {
.probe = ahci_da850_probe, .probe = ahci_da850_probe,
.remove = ata_platform_remove_one, .remove = ata_platform_remove_one,
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.of_match_table = ahci_da850_of_match,
.pm = &ahci_da850_pm_ops, .pm = &ahci_da850_pm_ops,
}, },
}; };
......
...@@ -1519,8 +1519,8 @@ static int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class, ...@@ -1519,8 +1519,8 @@ static int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class,
return rc; return rc;
} }
static int ahci_hardreset(struct ata_link *link, unsigned int *class, int ahci_do_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline) unsigned long deadline, bool *online)
{ {
const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
struct ata_port *ap = link->ap; struct ata_port *ap = link->ap;
...@@ -1528,7 +1528,6 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class, ...@@ -1528,7 +1528,6 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class,
struct ahci_host_priv *hpriv = ap->host->private_data; struct ahci_host_priv *hpriv = ap->host->private_data;
u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
struct ata_taskfile tf; struct ata_taskfile tf;
bool online;
int rc; int rc;
DPRINTK("ENTER\n"); DPRINTK("ENTER\n");
...@@ -1540,17 +1539,26 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class, ...@@ -1540,17 +1539,26 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class,
tf.command = ATA_BUSY; tf.command = ATA_BUSY;
ata_tf_to_fis(&tf, 0, 0, d2h_fis); ata_tf_to_fis(&tf, 0, 0, d2h_fis);
rc = sata_link_hardreset(link, timing, deadline, &online, rc = sata_link_hardreset(link, timing, deadline, online,
ahci_check_ready); ahci_check_ready);
hpriv->start_engine(ap); hpriv->start_engine(ap);
if (online) if (*online)
*class = ahci_dev_classify(ap); *class = ahci_dev_classify(ap);
DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(ahci_do_hardreset);
static int ahci_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline)
{
bool online;
return ahci_do_hardreset(link, class, deadline, &online);
}
static void ahci_postreset(struct ata_link *link, unsigned int *class) static void ahci_postreset(struct ata_link *link, unsigned int *class)
{ {
......
...@@ -112,6 +112,7 @@ config QCOM_EBI2 ...@@ -112,6 +112,7 @@ config QCOM_EBI2
bool "Qualcomm External Bus Interface 2 (EBI2)" bool "Qualcomm External Bus Interface 2 (EBI2)"
depends on HAS_IOMEM depends on HAS_IOMEM
depends on ARCH_QCOM || COMPILE_TEST depends on ARCH_QCOM || COMPILE_TEST
default ARCH_QCOM
help help
Say y here to enable support for the Qualcomm External Bus Say y here to enable support for the Qualcomm External Bus
Interface 2, which can be used to connect things like NAND Flash, Interface 2, which can be used to connect things like NAND Flash,
......
...@@ -560,3 +560,21 @@ int __qcom_scm_pas_mss_reset(struct device *dev, bool reset) ...@@ -560,3 +560,21 @@ int __qcom_scm_pas_mss_reset(struct device *dev, bool reset)
return ret ? : le32_to_cpu(out); return ret ? : le32_to_cpu(out);
} }
int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id)
{
struct {
__le32 state;
__le32 id;
} req;
__le32 scm_ret = 0;
int ret;
req.state = cpu_to_le32(state);
req.id = cpu_to_le32(id);
ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_SET_REMOTE_STATE,
&req, sizeof(req), &scm_ret, sizeof(scm_ret));
return ret ? : le32_to_cpu(scm_ret);
}
...@@ -365,3 +365,19 @@ int __qcom_scm_pas_mss_reset(struct device *dev, bool reset) ...@@ -365,3 +365,19 @@ int __qcom_scm_pas_mss_reset(struct device *dev, bool reset)
return ret ? : res.a1; return ret ? : res.a1;
} }
int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id)
{
struct qcom_scm_desc desc = {0};
struct arm_smccc_res res;
int ret;
desc.args[0] = state;
desc.args[1] = id;
desc.arginfo = QCOM_SCM_ARGS(2);
ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_SET_REMOTE_STATE,
&desc, &res);
return ret ? : res.a1;
}
...@@ -324,6 +324,12 @@ bool qcom_scm_is_available(void) ...@@ -324,6 +324,12 @@ bool qcom_scm_is_available(void)
} }
EXPORT_SYMBOL(qcom_scm_is_available); EXPORT_SYMBOL(qcom_scm_is_available);
int qcom_scm_set_remote_state(u32 state, u32 id)
{
return __qcom_scm_set_remote_state(__scm->dev, state, id);
}
EXPORT_SYMBOL(qcom_scm_set_remote_state);
static int qcom_scm_probe(struct platform_device *pdev) static int qcom_scm_probe(struct platform_device *pdev)
{ {
struct qcom_scm *scm; struct qcom_scm *scm;
...@@ -387,7 +393,7 @@ static int qcom_scm_probe(struct platform_device *pdev) ...@@ -387,7 +393,7 @@ static int qcom_scm_probe(struct platform_device *pdev)
static const struct of_device_id qcom_scm_dt_match[] = { static const struct of_device_id qcom_scm_dt_match[] = {
{ .compatible = "qcom,scm-apq8064", { .compatible = "qcom,scm-apq8064",
.data = (void *) SCM_HAS_CORE_CLK, /* FIXME: This should have .data = (void *) SCM_HAS_CORE_CLK */
}, },
{ .compatible = "qcom,scm-msm8660", { .compatible = "qcom,scm-msm8660",
.data = (void *) SCM_HAS_CORE_CLK, .data = (void *) SCM_HAS_CORE_CLK,
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#define QCOM_SCM_SVC_BOOT 0x1 #define QCOM_SCM_SVC_BOOT 0x1
#define QCOM_SCM_BOOT_ADDR 0x1 #define QCOM_SCM_BOOT_ADDR 0x1
#define QCOM_SCM_BOOT_ADDR_MC 0x11 #define QCOM_SCM_BOOT_ADDR_MC 0x11
#define QCOM_SCM_SET_REMOTE_STATE 0xa
extern int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id);
#define QCOM_SCM_FLAG_HLOS 0x01 #define QCOM_SCM_FLAG_HLOS 0x01
#define QCOM_SCM_FLAG_COLDBOOT_MC 0x02 #define QCOM_SCM_FLAG_COLDBOOT_MC 0x02
......
...@@ -76,9 +76,11 @@ struct at91_ebi_caps { ...@@ -76,9 +76,11 @@ struct at91_ebi_caps {
struct at91_ebi { struct at91_ebi {
struct clk *clk; struct clk *clk;
struct regmap *smc;
struct regmap *matrix; struct regmap *matrix;
struct {
struct regmap *regmap;
struct clk *clk;
} smc;
struct regmap_field *ebi_csa; struct regmap_field *ebi_csa;
struct device *dev; struct device *dev;
...@@ -93,7 +95,7 @@ static void at91sam9_ebi_get_config(struct at91_ebi_dev *ebid, ...@@ -93,7 +95,7 @@ static void at91sam9_ebi_get_config(struct at91_ebi_dev *ebid,
struct at91_ebi_dev_config *conf) struct at91_ebi_dev_config *conf)
{ {
struct at91sam9_smc_generic_fields *fields = &ebid->ebi->sam9; struct at91sam9_smc_generic_fields *fields = &ebid->ebi->sam9;
unsigned int clk_rate = clk_get_rate(ebid->ebi->clk); unsigned int clk_period = NSEC_PER_SEC / clk_get_rate(ebid->ebi->clk);
struct at91sam9_ebi_dev_config *config = &conf->sam9; struct at91sam9_ebi_dev_config *config = &conf->sam9;
struct at91sam9_smc_timings *timings = &config->timings; struct at91sam9_smc_timings *timings = &config->timings;
unsigned int val; unsigned int val;
...@@ -102,43 +104,43 @@ static void at91sam9_ebi_get_config(struct at91_ebi_dev *ebid, ...@@ -102,43 +104,43 @@ static void at91sam9_ebi_get_config(struct at91_ebi_dev *ebid,
config->mode = val & ~AT91_SMC_TDF; config->mode = val & ~AT91_SMC_TDF;
val = (val & AT91_SMC_TDF) >> 16; val = (val & AT91_SMC_TDF) >> 16;
timings->tdf_ns = clk_rate * val; timings->tdf_ns = clk_period * val;
regmap_fields_read(fields->setup, conf->cs, &val); regmap_fields_read(fields->setup, conf->cs, &val);
timings->ncs_rd_setup_ns = (val >> 24) & 0x1f; timings->ncs_rd_setup_ns = (val >> 24) & 0x1f;
timings->ncs_rd_setup_ns += ((val >> 29) & 0x1) * 128; timings->ncs_rd_setup_ns += ((val >> 29) & 0x1) * 128;
timings->ncs_rd_setup_ns *= clk_rate; timings->ncs_rd_setup_ns *= clk_period;
timings->nrd_setup_ns = (val >> 16) & 0x1f; timings->nrd_setup_ns = (val >> 16) & 0x1f;
timings->nrd_setup_ns += ((val >> 21) & 0x1) * 128; timings->nrd_setup_ns += ((val >> 21) & 0x1) * 128;
timings->nrd_setup_ns *= clk_rate; timings->nrd_setup_ns *= clk_period;
timings->ncs_wr_setup_ns = (val >> 8) & 0x1f; timings->ncs_wr_setup_ns = (val >> 8) & 0x1f;
timings->ncs_wr_setup_ns += ((val >> 13) & 0x1) * 128; timings->ncs_wr_setup_ns += ((val >> 13) & 0x1) * 128;
timings->ncs_wr_setup_ns *= clk_rate; timings->ncs_wr_setup_ns *= clk_period;
timings->nwe_setup_ns = val & 0x1f; timings->nwe_setup_ns = val & 0x1f;
timings->nwe_setup_ns += ((val >> 5) & 0x1) * 128; timings->nwe_setup_ns += ((val >> 5) & 0x1) * 128;
timings->nwe_setup_ns *= clk_rate; timings->nwe_setup_ns *= clk_period;
regmap_fields_read(fields->pulse, conf->cs, &val); regmap_fields_read(fields->pulse, conf->cs, &val);
timings->ncs_rd_pulse_ns = (val >> 24) & 0x3f; timings->ncs_rd_pulse_ns = (val >> 24) & 0x3f;
timings->ncs_rd_pulse_ns += ((val >> 30) & 0x1) * 256; timings->ncs_rd_pulse_ns += ((val >> 30) & 0x1) * 256;
timings->ncs_rd_pulse_ns *= clk_rate; timings->ncs_rd_pulse_ns *= clk_period;
timings->nrd_pulse_ns = (val >> 16) & 0x3f; timings->nrd_pulse_ns = (val >> 16) & 0x3f;
timings->nrd_pulse_ns += ((val >> 22) & 0x1) * 256; timings->nrd_pulse_ns += ((val >> 22) & 0x1) * 256;
timings->nrd_pulse_ns *= clk_rate; timings->nrd_pulse_ns *= clk_period;
timings->ncs_wr_pulse_ns = (val >> 8) & 0x3f; timings->ncs_wr_pulse_ns = (val >> 8) & 0x3f;
timings->ncs_wr_pulse_ns += ((val >> 14) & 0x1) * 256; timings->ncs_wr_pulse_ns += ((val >> 14) & 0x1) * 256;
timings->ncs_wr_pulse_ns *= clk_rate; timings->ncs_wr_pulse_ns *= clk_period;
timings->nwe_pulse_ns = val & 0x3f; timings->nwe_pulse_ns = val & 0x3f;
timings->nwe_pulse_ns += ((val >> 6) & 0x1) * 256; timings->nwe_pulse_ns += ((val >> 6) & 0x1) * 256;
timings->nwe_pulse_ns *= clk_rate; timings->nwe_pulse_ns *= clk_period;
regmap_fields_read(fields->cycle, conf->cs, &val); regmap_fields_read(fields->cycle, conf->cs, &val);
timings->nrd_cycle_ns = (val >> 16) & 0x7f; timings->nrd_cycle_ns = (val >> 16) & 0x7f;
timings->nrd_cycle_ns += ((val >> 23) & 0x3) * 256; timings->nrd_cycle_ns += ((val >> 23) & 0x3) * 256;
timings->nrd_cycle_ns *= clk_rate; timings->nrd_cycle_ns *= clk_period;
timings->nwe_cycle_ns = val & 0x7f; timings->nwe_cycle_ns = val & 0x7f;
timings->nwe_cycle_ns += ((val >> 7) & 0x3) * 256; timings->nwe_cycle_ns += ((val >> 7) & 0x3) * 256;
timings->nwe_cycle_ns *= clk_rate; timings->nwe_cycle_ns *= clk_period;
} }
static int at91_xlate_timing(struct device_node *np, const char *prop, static int at91_xlate_timing(struct device_node *np, const char *prop,
...@@ -334,6 +336,7 @@ static int at91sam9_ebi_apply_config(struct at91_ebi_dev *ebid, ...@@ -334,6 +336,7 @@ static int at91sam9_ebi_apply_config(struct at91_ebi_dev *ebid,
struct at91_ebi_dev_config *conf) struct at91_ebi_dev_config *conf)
{ {
unsigned int clk_rate = clk_get_rate(ebid->ebi->clk); unsigned int clk_rate = clk_get_rate(ebid->ebi->clk);
unsigned int clk_period = NSEC_PER_SEC / clk_rate;
struct at91sam9_ebi_dev_config *config = &conf->sam9; struct at91sam9_ebi_dev_config *config = &conf->sam9;
struct at91sam9_smc_timings *timings = &config->timings; struct at91sam9_smc_timings *timings = &config->timings;
struct at91sam9_smc_generic_fields *fields = &ebid->ebi->sam9; struct at91sam9_smc_generic_fields *fields = &ebid->ebi->sam9;
...@@ -376,7 +379,7 @@ static int at91sam9_ebi_apply_config(struct at91_ebi_dev *ebid, ...@@ -376,7 +379,7 @@ static int at91sam9_ebi_apply_config(struct at91_ebi_dev *ebid,
val |= AT91SAM9_SMC_NWECYCLE(coded_val); val |= AT91SAM9_SMC_NWECYCLE(coded_val);
regmap_fields_write(fields->cycle, conf->cs, val); regmap_fields_write(fields->cycle, conf->cs, val);
val = DIV_ROUND_UP(timings->tdf_ns, clk_rate); val = DIV_ROUND_UP(timings->tdf_ns, clk_period);
if (val > AT91_SMC_TDF_MAX) if (val > AT91_SMC_TDF_MAX)
val = AT91_SMC_TDF_MAX; val = AT91_SMC_TDF_MAX;
regmap_fields_write(fields->mode, conf->cs, regmap_fields_write(fields->mode, conf->cs,
...@@ -394,22 +397,26 @@ static int at91sam9_ebi_init(struct at91_ebi *ebi) ...@@ -394,22 +397,26 @@ static int at91sam9_ebi_init(struct at91_ebi *ebi)
field.id_offset = AT91SAM9_SMC_GENERIC_BLK_SZ; field.id_offset = AT91SAM9_SMC_GENERIC_BLK_SZ;
field.reg = AT91SAM9_SMC_SETUP(AT91SAM9_SMC_GENERIC); field.reg = AT91SAM9_SMC_SETUP(AT91SAM9_SMC_GENERIC);
fields->setup = devm_regmap_field_alloc(ebi->dev, ebi->smc, field); fields->setup = devm_regmap_field_alloc(ebi->dev, ebi->smc.regmap,
field);
if (IS_ERR(fields->setup)) if (IS_ERR(fields->setup))
return PTR_ERR(fields->setup); return PTR_ERR(fields->setup);
field.reg = AT91SAM9_SMC_PULSE(AT91SAM9_SMC_GENERIC); field.reg = AT91SAM9_SMC_PULSE(AT91SAM9_SMC_GENERIC);
fields->pulse = devm_regmap_field_alloc(ebi->dev, ebi->smc, field); fields->pulse = devm_regmap_field_alloc(ebi->dev, ebi->smc.regmap,
field);
if (IS_ERR(fields->pulse)) if (IS_ERR(fields->pulse))
return PTR_ERR(fields->pulse); return PTR_ERR(fields->pulse);
field.reg = AT91SAM9_SMC_CYCLE(AT91SAM9_SMC_GENERIC); field.reg = AT91SAM9_SMC_CYCLE(AT91SAM9_SMC_GENERIC);
fields->cycle = devm_regmap_field_alloc(ebi->dev, ebi->smc, field); fields->cycle = devm_regmap_field_alloc(ebi->dev, ebi->smc.regmap,
field);
if (IS_ERR(fields->cycle)) if (IS_ERR(fields->cycle))
return PTR_ERR(fields->cycle); return PTR_ERR(fields->cycle);
field.reg = AT91SAM9_SMC_MODE(AT91SAM9_SMC_GENERIC); field.reg = AT91SAM9_SMC_MODE(AT91SAM9_SMC_GENERIC);
fields->mode = devm_regmap_field_alloc(ebi->dev, ebi->smc, field); fields->mode = devm_regmap_field_alloc(ebi->dev, ebi->smc.regmap,
field);
return PTR_ERR_OR_ZERO(fields->mode); return PTR_ERR_OR_ZERO(fields->mode);
} }
...@@ -422,22 +429,26 @@ static int sama5d3_ebi_init(struct at91_ebi *ebi) ...@@ -422,22 +429,26 @@ static int sama5d3_ebi_init(struct at91_ebi *ebi)
field.id_offset = SAMA5_SMC_GENERIC_BLK_SZ; field.id_offset = SAMA5_SMC_GENERIC_BLK_SZ;
field.reg = AT91SAM9_SMC_SETUP(SAMA5_SMC_GENERIC); field.reg = AT91SAM9_SMC_SETUP(SAMA5_SMC_GENERIC);
fields->setup = devm_regmap_field_alloc(ebi->dev, ebi->smc, field); fields->setup = devm_regmap_field_alloc(ebi->dev, ebi->smc.regmap,
field);
if (IS_ERR(fields->setup)) if (IS_ERR(fields->setup))
return PTR_ERR(fields->setup); return PTR_ERR(fields->setup);
field.reg = AT91SAM9_SMC_PULSE(SAMA5_SMC_GENERIC); field.reg = AT91SAM9_SMC_PULSE(SAMA5_SMC_GENERIC);
fields->pulse = devm_regmap_field_alloc(ebi->dev, ebi->smc, field); fields->pulse = devm_regmap_field_alloc(ebi->dev, ebi->smc.regmap,
field);
if (IS_ERR(fields->pulse)) if (IS_ERR(fields->pulse))
return PTR_ERR(fields->pulse); return PTR_ERR(fields->pulse);
field.reg = AT91SAM9_SMC_CYCLE(SAMA5_SMC_GENERIC); field.reg = AT91SAM9_SMC_CYCLE(SAMA5_SMC_GENERIC);
fields->cycle = devm_regmap_field_alloc(ebi->dev, ebi->smc, field); fields->cycle = devm_regmap_field_alloc(ebi->dev, ebi->smc.regmap,
field);
if (IS_ERR(fields->cycle)) if (IS_ERR(fields->cycle))
return PTR_ERR(fields->cycle); return PTR_ERR(fields->cycle);
field.reg = SAMA5_SMC_MODE(SAMA5_SMC_GENERIC); field.reg = SAMA5_SMC_MODE(SAMA5_SMC_GENERIC);
fields->mode = devm_regmap_field_alloc(ebi->dev, ebi->smc, field); fields->mode = devm_regmap_field_alloc(ebi->dev, ebi->smc.regmap,
field);
return PTR_ERR_OR_ZERO(fields->mode); return PTR_ERR_OR_ZERO(fields->mode);
} }
...@@ -448,12 +459,31 @@ static int at91_ebi_dev_setup(struct at91_ebi *ebi, struct device_node *np, ...@@ -448,12 +459,31 @@ static int at91_ebi_dev_setup(struct at91_ebi *ebi, struct device_node *np,
struct at91_ebi_dev_config conf = { }; struct at91_ebi_dev_config conf = { };
struct device *dev = ebi->dev; struct device *dev = ebi->dev;
struct at91_ebi_dev *ebid; struct at91_ebi_dev *ebid;
int ret, numcs = 0, i; unsigned long cslines = 0;
int ret, numcs = 0, nentries, i;
bool apply = false; bool apply = false;
u32 cs;
numcs = of_property_count_elems_of_size(np, "reg", nentries = of_property_count_elems_of_size(np, "reg",
reg_cells * sizeof(u32)); reg_cells * sizeof(u32));
if (numcs <= 0) { for (i = 0; i < nentries; i++) {
ret = of_property_read_u32_index(np, "reg", i * reg_cells,
&cs);
if (ret)
return ret;
if (cs >= AT91_MATRIX_EBI_NUM_CS ||
!(ebi->caps->available_cs & BIT(cs))) {
dev_err(dev, "invalid reg property in %s\n",
np->full_name);
return -EINVAL;
}
if (!test_and_set_bit(cs, &cslines))
numcs++;
}
if (!numcs) {
dev_err(dev, "invalid reg property in %s\n", np->full_name); dev_err(dev, "invalid reg property in %s\n", np->full_name);
return -EINVAL; return -EINVAL;
} }
...@@ -472,21 +502,8 @@ static int at91_ebi_dev_setup(struct at91_ebi *ebi, struct device_node *np, ...@@ -472,21 +502,8 @@ static int at91_ebi_dev_setup(struct at91_ebi *ebi, struct device_node *np,
else if (ret) else if (ret)
apply = true; apply = true;
for (i = 0; i < numcs; i++) { i = 0;
u32 cs; for_each_set_bit(cs, &cslines, AT91_MATRIX_EBI_NUM_CS) {
ret = of_property_read_u32_index(np, "reg", i * reg_cells,
&cs);
if (ret)
return ret;
if (cs > AT91_MATRIX_EBI_NUM_CS ||
!(ebi->caps->available_cs & BIT(cs))) {
dev_err(dev, "invalid reg property in %s\n",
np->full_name);
return -EINVAL;
}
ebid->configs[i].cs = cs; ebid->configs[i].cs = cs;
if (apply) { if (apply) {
...@@ -502,9 +519,11 @@ static int at91_ebi_dev_setup(struct at91_ebi *ebi, struct device_node *np, ...@@ -502,9 +519,11 @@ static int at91_ebi_dev_setup(struct at91_ebi *ebi, struct device_node *np,
* Attach the EBI device to the generic SMC logic if at least * Attach the EBI device to the generic SMC logic if at least
* one "atmel,smc-" property is present. * one "atmel,smc-" property is present.
*/ */
if (ebi->ebi_csa && ret) if (ebi->ebi_csa && apply)
regmap_field_update_bits(ebi->ebi_csa, regmap_field_update_bits(ebi->ebi_csa,
BIT(cs), 0); BIT(cs), 0);
i++;
} }
list_add_tail(&ebid->node, &ebi->devs); list_add_tail(&ebid->node, &ebi->devs);
...@@ -668,7 +687,7 @@ static int at91_ebi_dev_disable(struct at91_ebi *ebi, struct device_node *np) ...@@ -668,7 +687,7 @@ static int at91_ebi_dev_disable(struct at91_ebi *ebi, struct device_node *np)
static int at91_ebi_probe(struct platform_device *pdev) static int at91_ebi_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *child, *np = dev->of_node; struct device_node *child, *np = dev->of_node, *smc_np;
const struct of_device_id *match; const struct of_device_id *match;
struct at91_ebi *ebi; struct at91_ebi *ebi;
int ret, reg_cells; int ret, reg_cells;
...@@ -693,9 +712,22 @@ static int at91_ebi_probe(struct platform_device *pdev) ...@@ -693,9 +712,22 @@ static int at91_ebi_probe(struct platform_device *pdev)
ebi->clk = clk; ebi->clk = clk;
ebi->smc = syscon_regmap_lookup_by_phandle(np, "atmel,smc"); smc_np = of_parse_phandle(dev->of_node, "atmel,smc", 0);
if (IS_ERR(ebi->smc))
return PTR_ERR(ebi->smc); ebi->smc.regmap = syscon_node_to_regmap(smc_np);
if (IS_ERR(ebi->smc.regmap))
return PTR_ERR(ebi->smc.regmap);
ebi->smc.clk = of_clk_get(smc_np, 0);
if (IS_ERR(ebi->smc.clk)) {
if (PTR_ERR(ebi->smc.clk) != -ENOENT)
return PTR_ERR(ebi->smc.clk);
ebi->smc.clk = NULL;
}
ret = clk_prepare_enable(ebi->smc.clk);
if (ret)
return ret;
/* /*
* The sama5d3 does not provide an EBICSA register and thus does need * The sama5d3 does not provide an EBICSA register and thus does need
......
...@@ -1115,11 +1115,10 @@ static int tegra_emc_probe(struct platform_device *pdev) ...@@ -1115,11 +1115,10 @@ static int tegra_emc_probe(struct platform_device *pdev)
} }
mc = of_find_device_by_node(np); mc = of_find_device_by_node(np);
of_node_put(np);
if (!mc) if (!mc)
return -ENOENT; return -ENOENT;
of_node_put(np);
emc->mc = platform_get_drvdata(mc); emc->mc = platform_get_drvdata(mc);
if (!emc->mc) if (!emc->mc)
return -EPROBE_DEFER; return -EPROBE_DEFER;
...@@ -1135,9 +1134,7 @@ static int tegra_emc_probe(struct platform_device *pdev) ...@@ -1135,9 +1134,7 @@ static int tegra_emc_probe(struct platform_device *pdev)
} }
err = tegra_emc_load_timings_from_dt(emc, np); err = tegra_emc_load_timings_from_dt(emc, np);
of_node_put(np); of_node_put(np);
if (err) if (err)
return err; return err;
......
...@@ -86,6 +86,12 @@ config RESET_UNIPHIER ...@@ -86,6 +86,12 @@ config RESET_UNIPHIER
Say Y if you want to control reset signals provided by System Control Say Y if you want to control reset signals provided by System Control
block, Media I/O block, Peripheral Block. block, Media I/O block, Peripheral Block.
config RESET_ZX2967
bool "ZTE ZX2967 Reset Driver"
depends on ARCH_ZX || COMPILE_TEST
help
This enables the reset controller driver for ZTE's zx2967 family.
config RESET_ZYNQ config RESET_ZYNQ
bool "ZYNQ Reset Driver" if COMPILE_TEST bool "ZYNQ Reset Driver" if COMPILE_TEST
default ARCH_ZYNQ default ARCH_ZYNQ
......
...@@ -13,4 +13,5 @@ obj-$(CONFIG_RESET_STM32) += reset-stm32.o ...@@ -13,4 +13,5 @@ obj-$(CONFIG_RESET_STM32) += reset-stm32.o
obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
obj-$(CONFIG_TI_SYSCON_RESET) += reset-ti-syscon.o obj-$(CONFIG_TI_SYSCON_RESET) += reset-ti-syscon.o
obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
obj-$(CONFIG_RESET_ZX2967) += reset-zx2967.o
obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
...@@ -41,7 +41,7 @@ struct reset_control { ...@@ -41,7 +41,7 @@ struct reset_control {
struct list_head list; struct list_head list;
unsigned int id; unsigned int id;
unsigned int refcnt; unsigned int refcnt;
int shared; bool shared;
atomic_t deassert_count; atomic_t deassert_count;
atomic_t triggered_count; atomic_t triggered_count;
}; };
...@@ -143,12 +143,18 @@ EXPORT_SYMBOL_GPL(devm_reset_controller_register); ...@@ -143,12 +143,18 @@ EXPORT_SYMBOL_GPL(devm_reset_controller_register);
* a no-op. * a no-op.
* Consumers must not use reset_control_(de)assert on shared reset lines when * Consumers must not use reset_control_(de)assert on shared reset lines when
* reset_control_reset has been used. * reset_control_reset has been used.
*
* If rstc is NULL it is an optional reset and the function will just
* return 0.
*/ */
int reset_control_reset(struct reset_control *rstc) int reset_control_reset(struct reset_control *rstc)
{ {
int ret; int ret;
if (WARN_ON(IS_ERR_OR_NULL(rstc))) if (!rstc)
return 0;
if (WARN_ON(IS_ERR(rstc)))
return -EINVAL; return -EINVAL;
if (!rstc->rcdev->ops->reset) if (!rstc->rcdev->ops->reset)
...@@ -182,10 +188,17 @@ EXPORT_SYMBOL_GPL(reset_control_reset); ...@@ -182,10 +188,17 @@ EXPORT_SYMBOL_GPL(reset_control_reset);
* internal state to be reset, but must be prepared for this to happen. * internal state to be reset, but must be prepared for this to happen.
* Consumers must not use reset_control_reset on shared reset lines when * Consumers must not use reset_control_reset on shared reset lines when
* reset_control_(de)assert has been used. * reset_control_(de)assert has been used.
* return 0.
*
* If rstc is NULL it is an optional reset and the function will just
* return 0.
*/ */
int reset_control_assert(struct reset_control *rstc) int reset_control_assert(struct reset_control *rstc)
{ {
if (WARN_ON(IS_ERR_OR_NULL(rstc))) if (!rstc)
return 0;
if (WARN_ON(IS_ERR(rstc)))
return -EINVAL; return -EINVAL;
if (!rstc->rcdev->ops->assert) if (!rstc->rcdev->ops->assert)
...@@ -213,10 +226,17 @@ EXPORT_SYMBOL_GPL(reset_control_assert); ...@@ -213,10 +226,17 @@ EXPORT_SYMBOL_GPL(reset_control_assert);
* After calling this function, the reset is guaranteed to be deasserted. * After calling this function, the reset is guaranteed to be deasserted.
* Consumers must not use reset_control_reset on shared reset lines when * Consumers must not use reset_control_reset on shared reset lines when
* reset_control_(de)assert has been used. * reset_control_(de)assert has been used.
* return 0.
*
* If rstc is NULL it is an optional reset and the function will just
* return 0.
*/ */
int reset_control_deassert(struct reset_control *rstc) int reset_control_deassert(struct reset_control *rstc)
{ {
if (WARN_ON(IS_ERR_OR_NULL(rstc))) if (!rstc)
return 0;
if (WARN_ON(IS_ERR(rstc)))
return -EINVAL; return -EINVAL;
if (!rstc->rcdev->ops->deassert) if (!rstc->rcdev->ops->deassert)
...@@ -237,12 +257,15 @@ EXPORT_SYMBOL_GPL(reset_control_deassert); ...@@ -237,12 +257,15 @@ EXPORT_SYMBOL_GPL(reset_control_deassert);
/** /**
* reset_control_status - returns a negative errno if not supported, a * reset_control_status - returns a negative errno if not supported, a
* positive value if the reset line is asserted, or zero if the reset * positive value if the reset line is asserted, or zero if the reset
* line is not asserted. * line is not asserted or if the desc is NULL (optional reset).
* @rstc: reset controller * @rstc: reset controller
*/ */
int reset_control_status(struct reset_control *rstc) int reset_control_status(struct reset_control *rstc)
{ {
if (WARN_ON(IS_ERR_OR_NULL(rstc))) if (!rstc)
return 0;
if (WARN_ON(IS_ERR(rstc)))
return -EINVAL; return -EINVAL;
if (rstc->rcdev->ops->status) if (rstc->rcdev->ops->status)
...@@ -254,7 +277,7 @@ EXPORT_SYMBOL_GPL(reset_control_status); ...@@ -254,7 +277,7 @@ EXPORT_SYMBOL_GPL(reset_control_status);
static struct reset_control *__reset_control_get( static struct reset_control *__reset_control_get(
struct reset_controller_dev *rcdev, struct reset_controller_dev *rcdev,
unsigned int index, int shared) unsigned int index, bool shared)
{ {
struct reset_control *rstc; struct reset_control *rstc;
...@@ -299,7 +322,8 @@ static void __reset_control_put(struct reset_control *rstc) ...@@ -299,7 +322,8 @@ static void __reset_control_put(struct reset_control *rstc)
} }
struct reset_control *__of_reset_control_get(struct device_node *node, struct reset_control *__of_reset_control_get(struct device_node *node,
const char *id, int index, int shared) const char *id, int index, bool shared,
bool optional)
{ {
struct reset_control *rstc; struct reset_control *rstc;
struct reset_controller_dev *r, *rcdev; struct reset_controller_dev *r, *rcdev;
...@@ -313,14 +337,18 @@ struct reset_control *__of_reset_control_get(struct device_node *node, ...@@ -313,14 +337,18 @@ struct reset_control *__of_reset_control_get(struct device_node *node,
if (id) { if (id) {
index = of_property_match_string(node, index = of_property_match_string(node,
"reset-names", id); "reset-names", id);
if (index == -EILSEQ)
return ERR_PTR(index);
if (index < 0) if (index < 0)
return ERR_PTR(-ENOENT); return optional ? NULL : 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 == -EINVAL)
return ERR_PTR(ret); return ERR_PTR(ret);
if (ret)
return optional ? NULL : ERR_PTR(ret);
mutex_lock(&reset_list_mutex); mutex_lock(&reset_list_mutex);
rcdev = NULL; rcdev = NULL;
...@@ -364,7 +392,7 @@ EXPORT_SYMBOL_GPL(__of_reset_control_get); ...@@ -364,7 +392,7 @@ EXPORT_SYMBOL_GPL(__of_reset_control_get);
void reset_control_put(struct reset_control *rstc) void reset_control_put(struct reset_control *rstc)
{ {
if (IS_ERR(rstc)) if (IS_ERR_OR_NULL(rstc))
return; return;
mutex_lock(&reset_list_mutex); mutex_lock(&reset_list_mutex);
...@@ -379,7 +407,8 @@ static void devm_reset_control_release(struct device *dev, void *res) ...@@ -379,7 +407,8 @@ static void devm_reset_control_release(struct device *dev, void *res)
} }
struct reset_control *__devm_reset_control_get(struct device *dev, struct reset_control *__devm_reset_control_get(struct device *dev,
const char *id, int index, int shared) const char *id, int index, bool shared,
bool optional)
{ {
struct reset_control **ptr, *rstc; struct reset_control **ptr, *rstc;
...@@ -389,7 +418,7 @@ struct reset_control *__devm_reset_control_get(struct device *dev, ...@@ -389,7 +418,7 @@ struct reset_control *__devm_reset_control_get(struct device *dev,
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
rstc = __of_reset_control_get(dev ? dev->of_node : NULL, rstc = __of_reset_control_get(dev ? dev->of_node : NULL,
id, index, shared); id, index, shared, optional);
if (!IS_ERR(rstc)) { if (!IS_ERR(rstc)) {
*ptr = rstc; *ptr = rstc;
devres_add(dev, ptr); devres_add(dev, ptr);
......
config COMMON_RESET_HI3660
tristate "Hi3660 Reset Driver"
depends on ARCH_HISI || COMPILE_TEST
default ARCH_HISI
help
Build the Hisilicon Hi3660 reset driver.
config COMMON_RESET_HI6220 config COMMON_RESET_HI6220
tristate "Hi6220 Reset Driver" tristate "Hi6220 Reset Driver"
depends on ARCH_HISI || COMPILE_TEST depends on ARCH_HISI || COMPILE_TEST
......
obj-$(CONFIG_COMMON_RESET_HI6220) += hi6220_reset.o obj-$(CONFIG_COMMON_RESET_HI6220) += hi6220_reset.o
obj-$(CONFIG_COMMON_RESET_HI3660) += reset-hi3660.o
/*
* Copyright (c) 2016-2017 Linaro Ltd.
* Copyright (c) 2016-2017 HiSilicon Technologies Co., Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset-controller.h>
struct hi3660_reset_controller {
struct reset_controller_dev rst;
struct regmap *map;
};
#define to_hi3660_reset_controller(_rst) \
container_of(_rst, struct hi3660_reset_controller, rst)
static int hi3660_reset_program_hw(struct reset_controller_dev *rcdev,
unsigned long idx, bool assert)
{
struct hi3660_reset_controller *rc = to_hi3660_reset_controller(rcdev);
unsigned int offset = idx >> 8;
unsigned int mask = BIT(idx & 0x1f);
if (assert)
return regmap_write(rc->map, offset, mask);
else
return regmap_write(rc->map, offset + 4, mask);
}
static int hi3660_reset_assert(struct reset_controller_dev *rcdev,
unsigned long idx)
{
return hi3660_reset_program_hw(rcdev, idx, true);
}
static int hi3660_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long idx)
{
return hi3660_reset_program_hw(rcdev, idx, false);
}
static int hi3660_reset_dev(struct reset_controller_dev *rcdev,
unsigned long idx)
{
int err;
err = hi3660_reset_assert(rcdev, idx);
if (err)
return err;
return hi3660_reset_deassert(rcdev, idx);
}
static struct reset_control_ops hi3660_reset_ops = {
.reset = hi3660_reset_dev,
.assert = hi3660_reset_assert,
.deassert = hi3660_reset_deassert,
};
static int hi3660_reset_xlate(struct reset_controller_dev *rcdev,
const struct of_phandle_args *reset_spec)
{
unsigned int offset, bit;
offset = reset_spec->args[0];
bit = reset_spec->args[1];
return (offset << 8) | bit;
}
static int hi3660_reset_probe(struct platform_device *pdev)
{
struct hi3660_reset_controller *rc;
struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev;
rc = devm_kzalloc(dev, sizeof(*rc), GFP_KERNEL);
if (!rc)
return -ENOMEM;
rc->map = syscon_regmap_lookup_by_phandle(np, "hisi,rst-syscon");
if (IS_ERR(rc->map)) {
dev_err(dev, "failed to get hi3660,rst-syscon\n");
return PTR_ERR(rc->map);
}
rc->rst.ops = &hi3660_reset_ops,
rc->rst.of_node = np;
rc->rst.of_reset_n_cells = 2;
rc->rst.of_xlate = hi3660_reset_xlate;
return reset_controller_register(&rc->rst);
}
static const struct of_device_id hi3660_reset_match[] = {
{ .compatible = "hisilicon,hi3660-reset", },
{},
};
MODULE_DEVICE_TABLE(of, hi3660_reset_match);
static struct platform_driver hi3660_reset_driver = {
.probe = hi3660_reset_probe,
.driver = {
.name = "hi3660-reset",
.of_match_table = hi3660_reset_match,
},
};
static int __init hi3660_reset_init(void)
{
return platform_driver_register(&hi3660_reset_driver);
}
arch_initcall(hi3660_reset_init);
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:hi3660-reset");
MODULE_DESCRIPTION("HiSilicon Hi3660 Reset Driver");
...@@ -154,11 +154,11 @@ static int ti_syscon_reset_status(struct reset_controller_dev *rcdev, ...@@ -154,11 +154,11 @@ static int ti_syscon_reset_status(struct reset_controller_dev *rcdev,
if (ret) if (ret)
return ret; return ret;
return (reset_state & BIT(control->status_bit)) && return !(reset_state & BIT(control->status_bit)) ==
(control->flags & STATUS_SET); !(control->flags & STATUS_SET);
} }
static struct reset_control_ops ti_syscon_reset_ops = { static const struct reset_control_ops ti_syscon_reset_ops = {
.assert = ti_syscon_reset_assert, .assert = ti_syscon_reset_assert,
.deassert = ti_syscon_reset_deassert, .deassert = ti_syscon_reset_deassert,
.status = ti_syscon_reset_status, .status = ti_syscon_reset_status,
......
...@@ -389,6 +389,10 @@ static const struct of_device_id uniphier_reset_match[] = { ...@@ -389,6 +389,10 @@ static const struct of_device_id uniphier_reset_match[] = {
.compatible = "socionext,uniphier-ld11-mio-reset", .compatible = "socionext,uniphier-ld11-mio-reset",
.data = uniphier_sld3_mio_reset_data, .data = uniphier_sld3_mio_reset_data,
}, },
{
.compatible = "socionext,uniphier-ld11-sd-reset",
.data = uniphier_pro5_sd_reset_data,
},
{ {
.compatible = "socionext,uniphier-ld20-sd-reset", .compatible = "socionext,uniphier-ld20-sd-reset",
.data = uniphier_pro5_sd_reset_data, .data = uniphier_pro5_sd_reset_data,
......
/*
* ZTE's zx2967 family reset controller driver
*
* Copyright (C) 2017 ZTE Ltd.
*
* Author: Baoyou Xie <baoyou.xie@linaro.org>
*
* License terms: GNU General Public License (GPL) version 2
*/
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
struct zx2967_reset {
void __iomem *reg_base;
spinlock_t lock;
struct reset_controller_dev rcdev;
};
static int zx2967_reset_act(struct reset_controller_dev *rcdev,
unsigned long id, bool assert)
{
struct zx2967_reset *reset = NULL;
int bank = id / 32;
int offset = id % 32;
u32 reg;
unsigned long flags;
reset = container_of(rcdev, struct zx2967_reset, rcdev);
spin_lock_irqsave(&reset->lock, flags);
reg = readl_relaxed(reset->reg_base + (bank * 4));
if (assert)
reg &= ~BIT(offset);
else
reg |= BIT(offset);
writel_relaxed(reg, reset->reg_base + (bank * 4));
spin_unlock_irqrestore(&reset->lock, flags);
return 0;
}
static int zx2967_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return zx2967_reset_act(rcdev, id, true);
}
static int zx2967_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return zx2967_reset_act(rcdev, id, false);
}
static struct reset_control_ops zx2967_reset_ops = {
.assert = zx2967_reset_assert,
.deassert = zx2967_reset_deassert,
};
static int zx2967_reset_probe(struct platform_device *pdev)
{
struct zx2967_reset *reset;
struct resource *res;
reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
if (!reset)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
reset->reg_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(reset->reg_base))
return PTR_ERR(reset->reg_base);
spin_lock_init(&reset->lock);
reset->rcdev.owner = THIS_MODULE;
reset->rcdev.nr_resets = resource_size(res) * 8;
reset->rcdev.ops = &zx2967_reset_ops;
reset->rcdev.of_node = pdev->dev.of_node;
return devm_reset_controller_register(&pdev->dev, &reset->rcdev);
}
static const struct of_device_id zx2967_reset_dt_ids[] = {
{ .compatible = "zte,zx296718-reset", },
{},
};
static struct platform_driver zx2967_reset_driver = {
.probe = zx2967_reset_probe,
.driver = {
.name = "zx2967-reset",
.of_match_table = zx2967_reset_dt_ids,
},
};
builtin_platform_driver(zx2967_reset_driver);
...@@ -11,5 +11,6 @@ source "drivers/soc/tegra/Kconfig" ...@@ -11,5 +11,6 @@ source "drivers/soc/tegra/Kconfig"
source "drivers/soc/ti/Kconfig" source "drivers/soc/ti/Kconfig"
source "drivers/soc/ux500/Kconfig" source "drivers/soc/ux500/Kconfig"
source "drivers/soc/versatile/Kconfig" source "drivers/soc/versatile/Kconfig"
source "drivers/soc/zte/Kconfig"
endmenu endmenu
...@@ -16,3 +16,4 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/ ...@@ -16,3 +16,4 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-$(CONFIG_SOC_TI) += ti/ obj-$(CONFIG_SOC_TI) += ti/
obj-$(CONFIG_ARCH_U8500) += ux500/ obj-$(CONFIG_ARCH_U8500) += ux500/
obj-$(CONFIG_PLAT_VERSATILE) += versatile/ obj-$(CONFIG_PLAT_VERSATILE) += versatile/
obj-$(CONFIG_ARCH_ZX) += zte/
...@@ -3,6 +3,16 @@ if ARCH_ROCKCHIP || COMPILE_TEST ...@@ -3,6 +3,16 @@ if ARCH_ROCKCHIP || COMPILE_TEST
# #
# Rockchip Soc drivers # Rockchip Soc drivers
# #
config ROCKCHIP_GRF
bool
default y
help
The General Register Files are a central component providing
special additional settings registers for a lot of soc-components.
In a lot of cases there also need to be default settings initialized
to make some of them conform to expectations of the kernel.
config ROCKCHIP_PM_DOMAINS config ROCKCHIP_PM_DOMAINS
bool "Rockchip generic power domain" bool "Rockchip generic power domain"
depends on PM depends on PM
......
# #
# Rockchip Soc drivers # Rockchip Soc drivers
# #
obj-$(CONFIG_ROCKCHIP_GRF) += grf.o
obj-$(CONFIG_ROCKCHIP_PM_DOMAINS) += pm_domains.o obj-$(CONFIG_ROCKCHIP_PM_DOMAINS) += pm_domains.o
/*
* Rockchip Generic Register Files setup
*
* Copyright (c) 2016 Heiko Stuebner <heiko@sntech.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/err.h>
#include <linux/mfd/syscon.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#define HIWORD_UPDATE(val, mask, shift) \
((val) << (shift) | (mask) << ((shift) + 16))
struct rockchip_grf_value {
const char *desc;
u32 reg;
u32 val;
};
struct rockchip_grf_info {
const struct rockchip_grf_value *values;
int num_values;
};
#define RK3036_GRF_SOC_CON0 0x140
static const struct rockchip_grf_value rk3036_defaults[] __initconst = {
/*
* Disable auto jtag/sdmmc switching that causes issues with the
* clock-framework and the mmc controllers making them unreliable.
*/
{ "jtag switching", RK3036_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 11) },
};
static const struct rockchip_grf_info rk3036_grf __initconst = {
.values = rk3036_defaults,
.num_values = ARRAY_SIZE(rk3036_defaults),
};
#define RK3288_GRF_SOC_CON0 0x244
static const struct rockchip_grf_value rk3288_defaults[] __initconst = {
{ "jtag switching", RK3288_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 12) },
};
static const struct rockchip_grf_info rk3288_grf __initconst = {
.values = rk3288_defaults,
.num_values = ARRAY_SIZE(rk3288_defaults),
};
#define RK3368_GRF_SOC_CON15 0x43c
static const struct rockchip_grf_value rk3368_defaults[] __initconst = {
{ "jtag switching", RK3368_GRF_SOC_CON15, HIWORD_UPDATE(0, 1, 13) },
};
static const struct rockchip_grf_info rk3368_grf __initconst = {
.values = rk3368_defaults,
.num_values = ARRAY_SIZE(rk3368_defaults),
};
#define RK3399_GRF_SOC_CON7 0xe21c
static const struct rockchip_grf_value rk3399_defaults[] __initconst = {
{ "jtag switching", RK3399_GRF_SOC_CON7, HIWORD_UPDATE(0, 1, 12) },
};
static const struct rockchip_grf_info rk3399_grf __initconst = {
.values = rk3399_defaults,
.num_values = ARRAY_SIZE(rk3399_defaults),
};
static const struct of_device_id rockchip_grf_dt_match[] __initconst = {
{
.compatible = "rockchip,rk3036-grf",
.data = (void *)&rk3036_grf,
}, {
.compatible = "rockchip,rk3288-grf",
.data = (void *)&rk3288_grf,
}, {
.compatible = "rockchip,rk3368-grf",
.data = (void *)&rk3368_grf,
}, {
.compatible = "rockchip,rk3399-grf",
.data = (void *)&rk3399_grf,
},
{ /* sentinel */ },
};
static int __init rockchip_grf_init(void)
{
const struct rockchip_grf_info *grf_info;
const struct of_device_id *match;
struct device_node *np;
struct regmap *grf;
int ret, i;
np = of_find_matching_node_and_match(NULL, rockchip_grf_dt_match,
&match);
if (!np)
return -ENODEV;
if (!match || !match->data) {
pr_err("%s: missing grf data\n", __func__);
return -EINVAL;
}
grf_info = match->data;
grf = syscon_node_to_regmap(np);
if (IS_ERR(grf)) {
pr_err("%s: could not get grf syscon\n", __func__);
return PTR_ERR(grf);
}
for (i = 0; i < grf_info->num_values; i++) {
const struct rockchip_grf_value *val = &grf_info->values[i];
pr_debug("%s: adjusting %s in %#6x to %#10x\n", __func__,
val->desc, val->reg, val->val);
ret = regmap_write(grf, val->reg, val->val);
if (ret < 0)
pr_err("%s: write to %#6x failed with %d\n",
__func__, val->reg, ret);
}
return 0;
}
postcore_initcall(rockchip_grf_init);
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
#include <dt-bindings/power/rk3288-power.h> #include <dt-bindings/power/rk3288-power.h>
#include <dt-bindings/power/rk3328-power.h>
#include <dt-bindings/power/rk3368-power.h> #include <dt-bindings/power/rk3368-power.h>
#include <dt-bindings/power/rk3399-power.h> #include <dt-bindings/power/rk3399-power.h>
...@@ -29,6 +30,8 @@ struct rockchip_domain_info { ...@@ -29,6 +30,8 @@ struct rockchip_domain_info {
int idle_mask; int idle_mask;
int ack_mask; int ack_mask;
bool active_wakeup; bool active_wakeup;
int pwr_w_mask;
int req_w_mask;
}; };
struct rockchip_pmu_info { struct rockchip_pmu_info {
...@@ -87,9 +90,24 @@ struct rockchip_pmu { ...@@ -87,9 +90,24 @@ struct rockchip_pmu {
.active_wakeup = wakeup, \ .active_wakeup = wakeup, \
} }
#define DOMAIN_M(pwr, status, req, idle, ack, wakeup) \
{ \
.pwr_w_mask = (pwr >= 0) ? BIT(pwr + 16) : 0, \
.pwr_mask = (pwr >= 0) ? BIT(pwr) : 0, \
.status_mask = (status >= 0) ? BIT(status) : 0, \
.req_w_mask = (req >= 0) ? BIT(req + 16) : 0, \
.req_mask = (req >= 0) ? BIT(req) : 0, \
.idle_mask = (idle >= 0) ? BIT(idle) : 0, \
.ack_mask = (ack >= 0) ? BIT(ack) : 0, \
.active_wakeup = wakeup, \
}
#define DOMAIN_RK3288(pwr, status, req, wakeup) \ #define DOMAIN_RK3288(pwr, status, req, wakeup) \
DOMAIN(pwr, status, req, req, (req) + 16, wakeup) DOMAIN(pwr, status, req, req, (req) + 16, wakeup)
#define DOMAIN_RK3328(pwr, status, req, wakeup) \
DOMAIN_M(pwr, pwr, req, (req) + 10, req, wakeup)
#define DOMAIN_RK3368(pwr, status, req, wakeup) \ #define DOMAIN_RK3368(pwr, status, req, wakeup) \
DOMAIN(pwr, status, req, (req) + 16, req, wakeup) DOMAIN(pwr, status, req, (req) + 16, req, wakeup)
...@@ -127,7 +145,11 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd, ...@@ -127,7 +145,11 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
if (pd_info->req_mask == 0) if (pd_info->req_mask == 0)
return 0; return 0;
else if (pd_info->req_w_mask)
regmap_write(pmu->regmap, pmu->info->req_offset,
idle ? (pd_info->req_mask | pd_info->req_w_mask) :
pd_info->req_w_mask);
else
regmap_update_bits(pmu->regmap, pmu->info->req_offset, regmap_update_bits(pmu->regmap, pmu->info->req_offset,
pd_info->req_mask, idle ? -1U : 0); pd_info->req_mask, idle ? -1U : 0);
...@@ -230,7 +252,11 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd, ...@@ -230,7 +252,11 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
if (pd->info->pwr_mask == 0) if (pd->info->pwr_mask == 0)
return; return;
else if (pd->info->pwr_w_mask)
regmap_write(pmu->regmap, pmu->info->pwr_offset,
on ? pd->info->pwr_mask :
(pd->info->pwr_mask | pd->info->pwr_w_mask));
else
regmap_update_bits(pmu->regmap, pmu->info->pwr_offset, regmap_update_bits(pmu->regmap, pmu->info->pwr_offset,
pd->info->pwr_mask, on ? 0 : -1U); pd->info->pwr_mask, on ? 0 : -1U);
...@@ -692,6 +718,18 @@ static const struct rockchip_domain_info rk3288_pm_domains[] = { ...@@ -692,6 +718,18 @@ static const struct rockchip_domain_info rk3288_pm_domains[] = {
[RK3288_PD_GPU] = DOMAIN_RK3288(9, 9, 2, false), [RK3288_PD_GPU] = DOMAIN_RK3288(9, 9, 2, false),
}; };
static const struct rockchip_domain_info rk3328_pm_domains[] = {
[RK3328_PD_CORE] = DOMAIN_RK3328(-1, 0, 0, false),
[RK3328_PD_GPU] = DOMAIN_RK3328(-1, 1, 1, false),
[RK3328_PD_BUS] = DOMAIN_RK3328(-1, 2, 2, true),
[RK3328_PD_MSCH] = DOMAIN_RK3328(-1, 3, 3, true),
[RK3328_PD_PERI] = DOMAIN_RK3328(-1, 4, 4, true),
[RK3328_PD_VIDEO] = DOMAIN_RK3328(-1, 5, 5, false),
[RK3328_PD_HEVC] = DOMAIN_RK3328(-1, 6, 6, false),
[RK3328_PD_VIO] = DOMAIN_RK3328(-1, 8, 8, false),
[RK3328_PD_VPU] = DOMAIN_RK3328(-1, 9, 9, false),
};
static const struct rockchip_domain_info rk3368_pm_domains[] = { static const struct rockchip_domain_info rk3368_pm_domains[] = {
[RK3368_PD_PERI] = DOMAIN_RK3368(13, 12, 6, true), [RK3368_PD_PERI] = DOMAIN_RK3368(13, 12, 6, true),
[RK3368_PD_VIO] = DOMAIN_RK3368(15, 14, 8, false), [RK3368_PD_VIO] = DOMAIN_RK3368(15, 14, 8, false),
...@@ -747,6 +785,15 @@ static const struct rockchip_pmu_info rk3288_pmu = { ...@@ -747,6 +785,15 @@ static const struct rockchip_pmu_info rk3288_pmu = {
.domain_info = rk3288_pm_domains, .domain_info = rk3288_pm_domains,
}; };
static const struct rockchip_pmu_info rk3328_pmu = {
.req_offset = 0x414,
.idle_offset = 0x484,
.ack_offset = 0x484,
.num_domains = ARRAY_SIZE(rk3328_pm_domains),
.domain_info = rk3328_pm_domains,
};
static const struct rockchip_pmu_info rk3368_pmu = { static const struct rockchip_pmu_info rk3368_pmu = {
.pwr_offset = 0x0c, .pwr_offset = 0x0c,
.status_offset = 0x10, .status_offset = 0x10,
...@@ -782,6 +829,10 @@ static const struct of_device_id rockchip_pm_domain_dt_match[] = { ...@@ -782,6 +829,10 @@ static const struct of_device_id rockchip_pm_domain_dt_match[] = {
.compatible = "rockchip,rk3288-power-controller", .compatible = "rockchip,rk3288-power-controller",
.data = (void *)&rk3288_pmu, .data = (void *)&rk3288_pmu,
}, },
{
.compatible = "rockchip,rk3328-power-controller",
.data = (void *)&rk3328_pmu,
},
{ {
.compatible = "rockchip,rk3368-power-controller", .compatible = "rockchip,rk3368-power-controller",
.data = (void *)&rk3368_pmu, .data = (void *)&rk3368_pmu,
......
...@@ -44,7 +44,7 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode) ...@@ -44,7 +44,7 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode)
unsigned int i; unsigned int i;
const struct exynos_pmu_data *pmu_data; const struct exynos_pmu_data *pmu_data;
if (!pmu_context) if (!pmu_context || !pmu_context->pmu_data)
return; return;
pmu_data = pmu_context->pmu_data; pmu_data = pmu_context->pmu_data;
...@@ -90,6 +90,8 @@ static const struct of_device_id exynos_pmu_of_device_ids[] = { ...@@ -90,6 +90,8 @@ static const struct of_device_id exynos_pmu_of_device_ids[] = {
}, { }, {
.compatible = "samsung,exynos5420-pmu", .compatible = "samsung,exynos5420-pmu",
.data = &exynos5420_pmu_data, .data = &exynos5420_pmu_data,
}, {
.compatible = "samsung,exynos5433-pmu",
}, },
{ /*sentinel*/ }, { /*sentinel*/ },
}; };
...@@ -122,7 +124,7 @@ static int exynos_pmu_probe(struct platform_device *pdev) ...@@ -122,7 +124,7 @@ static int exynos_pmu_probe(struct platform_device *pdev)
pmu_context->dev = dev; pmu_context->dev = dev;
pmu_context->pmu_data = of_device_get_match_data(dev); pmu_context->pmu_data = of_device_get_match_data(dev);
if (pmu_context->pmu_data->pmu_init) if (pmu_context->pmu_data && pmu_context->pmu_data->pmu_init)
pmu_context->pmu_data->pmu_init(); pmu_context->pmu_data->pmu_init();
platform_set_drvdata(pdev, pmu_context); platform_set_drvdata(pdev, pmu_context);
......
...@@ -29,7 +29,7 @@ static const struct exynos_pmu_conf exynos5250_pmu_config[] = { ...@@ -29,7 +29,7 @@ static const struct exynos_pmu_conf exynos5250_pmu_config[] = {
{ EXYNOS5_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} }, { EXYNOS5_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5_ARM_COMMON_SYS_PWR_REG, { 0x0, 0x0, 0x2} }, { EXYNOS5_ARM_COMMON_SYS_PWR_REG, { 0x0, 0x0, 0x2} },
{ EXYNOS5_ARM_L2_SYS_PWR_REG, { 0x3, 0x3, 0x3} }, { EXYNOS5_ARM_L2_SYS_PWR_REG, { 0x3, 0x3, 0x3} },
{ EXYNOS5_ARM_L2_OPTION, { 0x10, 0x10, 0x0 } }, { EXYNOS_L2_OPTION(0), { 0x10, 0x10, 0x0 } },
{ EXYNOS5_CMU_ACLKSTOP_SYS_PWR_REG, { 0x1, 0x0, 0x1} }, { EXYNOS5_CMU_ACLKSTOP_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
{ EXYNOS5_CMU_SCLKSTOP_SYS_PWR_REG, { 0x1, 0x0, 0x1} }, { EXYNOS5_CMU_SCLKSTOP_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
{ EXYNOS5_CMU_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, { EXYNOS5_CMU_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
......
...@@ -230,11 +230,11 @@ static void exynos5420_pmu_init(void) ...@@ -230,11 +230,11 @@ static void exynos5420_pmu_init(void)
pmu_raw_writel(EXYNOS5420_USE_STANDBY_WFI_ALL, S5P_CENTRAL_SEQ_OPTION); pmu_raw_writel(EXYNOS5420_USE_STANDBY_WFI_ALL, S5P_CENTRAL_SEQ_OPTION);
value = pmu_raw_readl(EXYNOS_L2_OPTION(0)); value = pmu_raw_readl(EXYNOS_L2_OPTION(0));
value &= ~EXYNOS5_USE_RETENTION; value &= ~EXYNOS_L2_USE_RETENTION;
pmu_raw_writel(value, EXYNOS_L2_OPTION(0)); pmu_raw_writel(value, EXYNOS_L2_OPTION(0));
value = pmu_raw_readl(EXYNOS_L2_OPTION(1)); value = pmu_raw_readl(EXYNOS_L2_OPTION(1));
value &= ~EXYNOS5_USE_RETENTION; value &= ~EXYNOS_L2_USE_RETENTION;
pmu_raw_writel(value, EXYNOS_L2_OPTION(1)); pmu_raw_writel(value, EXYNOS_L2_OPTION(1));
/* /*
......
...@@ -35,7 +35,6 @@ struct exynos_pm_domain_config { ...@@ -35,7 +35,6 @@ struct exynos_pm_domain_config {
*/ */
struct exynos_pm_domain { struct exynos_pm_domain {
void __iomem *base; void __iomem *base;
char const *name;
bool is_off; bool is_off;
struct generic_pm_domain pd; struct generic_pm_domain pd;
struct clk *oscclk; struct clk *oscclk;
...@@ -70,7 +69,7 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on) ...@@ -70,7 +69,7 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
pd->pclk[i] = clk_get_parent(pd->clk[i]); pd->pclk[i] = clk_get_parent(pd->clk[i]);
if (clk_set_parent(pd->clk[i], pd->oscclk)) if (clk_set_parent(pd->clk[i], pd->oscclk))
pr_err("%s: error setting oscclk as parent to clock %d\n", pr_err("%s: error setting oscclk as parent to clock %d\n",
pd->name, i); domain->name, i);
} }
} }
...@@ -101,7 +100,7 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on) ...@@ -101,7 +100,7 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
continue; /* Skip on first power up */ continue; /* Skip on first power up */
if (clk_set_parent(pd->clk[i], pd->pclk[i])) if (clk_set_parent(pd->clk[i], pd->pclk[i]))
pr_err("%s: error setting parent to clock%d\n", pr_err("%s: error setting parent to clock%d\n",
pd->name, i); domain->name, i);
} }
} }
...@@ -128,14 +127,30 @@ static const struct exynos_pm_domain_config exynos4210_cfg __initconst = { ...@@ -128,14 +127,30 @@ static const struct exynos_pm_domain_config exynos4210_cfg __initconst = {
.local_pwr_cfg = 0x7, .local_pwr_cfg = 0x7,
}; };
static const struct exynos_pm_domain_config exynos5433_cfg __initconst = {
.local_pwr_cfg = 0xf,
};
static const struct of_device_id exynos_pm_domain_of_match[] __initconst = { static const struct of_device_id exynos_pm_domain_of_match[] __initconst = {
{ {
.compatible = "samsung,exynos4210-pd", .compatible = "samsung,exynos4210-pd",
.data = &exynos4210_cfg, .data = &exynos4210_cfg,
}, {
.compatible = "samsung,exynos5433-pd",
.data = &exynos5433_cfg,
}, },
{ }, { },
}; };
static __init const char *exynos_get_domain_name(struct device_node *node)
{
const char *name;
if (of_property_read_string(node, "label", &name) < 0)
name = strrchr(node->full_name, '/') + 1;
return kstrdup_const(name, GFP_KERNEL);
}
static __init int exynos4_pm_init_power_domain(void) static __init int exynos4_pm_init_power_domain(void)
{ {
struct device_node *np; struct device_node *np;
...@@ -150,20 +165,16 @@ static __init int exynos4_pm_init_power_domain(void) ...@@ -150,20 +165,16 @@ static __init int exynos4_pm_init_power_domain(void)
pd = kzalloc(sizeof(*pd), GFP_KERNEL); pd = kzalloc(sizeof(*pd), GFP_KERNEL);
if (!pd) { if (!pd) {
pr_err("%s: failed to allocate memory for domain\n",
__func__);
of_node_put(np); of_node_put(np);
return -ENOMEM; return -ENOMEM;
} }
pd->pd.name = kstrdup_const(strrchr(np->full_name, '/') + 1, pd->pd.name = exynos_get_domain_name(np);
GFP_KERNEL);
if (!pd->pd.name) { if (!pd->pd.name) {
kfree(pd); kfree(pd);
of_node_put(np); of_node_put(np);
return -ENOMEM; return -ENOMEM;
} }
pd->name = pd->pd.name;
pd->base = of_iomap(np, 0); pd->base = of_iomap(np, 0);
if (!pd->base) { if (!pd->base) {
pr_warn("%s: failed to map memory\n", __func__); pr_warn("%s: failed to map memory\n", __func__);
...@@ -227,10 +238,10 @@ static __init int exynos4_pm_init_power_domain(void) ...@@ -227,10 +238,10 @@ static __init int exynos4_pm_init_power_domain(void)
if (of_genpd_add_subdomain(&parent, &child)) if (of_genpd_add_subdomain(&parent, &child))
pr_warn("%s failed to add subdomain: %s\n", pr_warn("%s failed to add subdomain: %s\n",
parent.np->name, child.np->name); parent.np->full_name, child.np->full_name);
else else
pr_info("%s has as child subdomain: %s.\n", pr_info("%s has as child subdomain: %s.\n",
parent.np->name, child.np->name); parent.np->full_name, child.np->full_name);
} }
return 0; return 0;
......
...@@ -395,7 +395,7 @@ static int of_channel_match_helper(struct device_node *np, const char *name, ...@@ -395,7 +395,7 @@ static int of_channel_match_helper(struct device_node *np, const char *name,
if (of_parse_phandle_with_fixed_args(np, "ti,navigator-dmas", if (of_parse_phandle_with_fixed_args(np, "ti,navigator-dmas",
1, index, &args)) { 1, index, &args)) {
dev_err(kdev->dev, "Missing the pahndle args name %s\n", name); dev_err(kdev->dev, "Missing the phandle args name %s\n", name);
return -ENODEV; return -ENODEV;
} }
......
...@@ -16,21 +16,12 @@ ...@@ -16,21 +16,12 @@
* General Public License for more details. * General Public License for more details.
*/ */
#include <linux/kernel.h> #include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/bitops.h> #include <linux/module.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/soc/ti/knav_qmss.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/firmware.h> #include <linux/soc/ti/knav_qmss.h>
#include "knav_qmss.h" #include "knav_qmss.h"
......
...@@ -16,26 +16,17 @@ ...@@ -16,26 +16,17 @@
* General Public License for more details. * General Public License for more details.
*/ */
#include <linux/kernel.h> #include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/bitops.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/of.h> #include <linux/firmware.h>
#include <linux/of_irq.h> #include <linux/interrupt.h>
#include <linux/of_device.h> #include <linux/io.h>
#include <linux/module.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/firmware.h> #include <linux/slab.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/string.h>
#include <linux/soc/ti/knav_qmss.h> #include <linux/soc/ti/knav_qmss.h>
#include "knav_qmss.h" #include "knav_qmss.h"
......
...@@ -370,8 +370,6 @@ static void wkup_m3_rproc_boot_thread(struct wkup_m3_ipc *m3_ipc) ...@@ -370,8 +370,6 @@ static void wkup_m3_rproc_boot_thread(struct wkup_m3_ipc *m3_ipc)
struct device *dev = m3_ipc->dev; struct device *dev = m3_ipc->dev;
int ret; int ret;
wait_for_completion(&m3_ipc->rproc->firmware_loading_complete);
init_completion(&m3_ipc->sync_complete); init_completion(&m3_ipc->sync_complete);
ret = rproc_boot(m3_ipc->rproc); ret = rproc_boot(m3_ipc->rproc);
......
#
# ZTE SoC drivers
#
menuconfig SOC_ZTE
bool "ZTE SoC driver support"
if SOC_ZTE
config ZX2967_PM_DOMAINS
bool "ZX2967 PM domains"
depends on PM_GENERIC_DOMAINS
endif
#
# ZTE SOC drivers
#
obj-$(CONFIG_ZX2967_PM_DOMAINS) += zx2967_pm_domains.o
obj-$(CONFIG_ZX2967_PM_DOMAINS) += zx296718_pm_domains.o
/*
* Copyright (C) 2017 ZTE Ltd.
*
* Author: Baoyou Xie <baoyou.xie@linaro.org>
* License terms: GNU General Public License (GPL) version 2
*/
#include <dt-bindings/soc/zte,pm_domains.h>
#include "zx2967_pm_domains.h"
static u16 zx296718_offsets[REG_ARRAY_SIZE] = {
[REG_CLKEN] = 0x18,
[REG_ISOEN] = 0x1c,
[REG_RSTEN] = 0x20,
[REG_PWREN] = 0x24,
[REG_ACK_SYNC] = 0x28,
};
enum {
PCU_DM_VOU = 0,
PCU_DM_SAPPU,
PCU_DM_VDE,
PCU_DM_VCE,
PCU_DM_HDE,
PCU_DM_VIU,
PCU_DM_USB20,
PCU_DM_USB21,
PCU_DM_USB30,
PCU_DM_HSIC,
PCU_DM_GMAC,
PCU_DM_TS,
};
static struct zx2967_pm_domain vou_domain = {
.dm = {
.name = "vou_domain",
},
.bit = PCU_DM_VOU,
.polarity = PWREN,
.reg_offset = zx296718_offsets,
};
static struct zx2967_pm_domain sappu_domain = {
.dm = {
.name = "sappu_domain",
},
.bit = PCU_DM_SAPPU,
.polarity = PWREN,
.reg_offset = zx296718_offsets,
};
static struct zx2967_pm_domain vde_domain = {
.dm = {
.name = "vde_domain",
},
.bit = PCU_DM_VDE,
.polarity = PWREN,
.reg_offset = zx296718_offsets,
};
static struct zx2967_pm_domain vce_domain = {
.dm = {
.name = "vce_domain",
},
.bit = PCU_DM_VCE,
.polarity = PWREN,
.reg_offset = zx296718_offsets,
};
static struct zx2967_pm_domain hde_domain = {
.dm = {
.name = "hde_domain",
},
.bit = PCU_DM_HDE,
.polarity = PWREN,
.reg_offset = zx296718_offsets,
};
static struct zx2967_pm_domain viu_domain = {
.dm = {
.name = "viu_domain",
},
.bit = PCU_DM_VIU,
.polarity = PWREN,
.reg_offset = zx296718_offsets,
};
static struct zx2967_pm_domain usb20_domain = {
.dm = {
.name = "usb20_domain",
},
.bit = PCU_DM_USB20,
.polarity = PWREN,
.reg_offset = zx296718_offsets,
};
static struct zx2967_pm_domain usb21_domain = {
.dm = {
.name = "usb21_domain",
},
.bit = PCU_DM_USB21,
.polarity = PWREN,
.reg_offset = zx296718_offsets,
};
static struct zx2967_pm_domain usb30_domain = {
.dm = {
.name = "usb30_domain",
},
.bit = PCU_DM_USB30,
.polarity = PWREN,
.reg_offset = zx296718_offsets,
};
static struct zx2967_pm_domain hsic_domain = {
.dm = {
.name = "hsic_domain",
},
.bit = PCU_DM_HSIC,
.polarity = PWREN,
.reg_offset = zx296718_offsets,
};
static struct zx2967_pm_domain gmac_domain = {
.dm = {
.name = "gmac_domain",
},
.bit = PCU_DM_GMAC,
.polarity = PWREN,
.reg_offset = zx296718_offsets,
};
static struct zx2967_pm_domain ts_domain = {
.dm = {
.name = "ts_domain",
},
.bit = PCU_DM_TS,
.polarity = PWREN,
.reg_offset = zx296718_offsets,
};
static struct generic_pm_domain *zx296718_pm_domains[] = {
[DM_ZX296718_VOU] = &vou_domain.dm,
[DM_ZX296718_SAPPU] = &sappu_domain.dm,
[DM_ZX296718_VDE] = &vde_domain.dm,
[DM_ZX296718_VCE] = &vce_domain.dm,
[DM_ZX296718_HDE] = &hde_domain.dm,
[DM_ZX296718_VIU] = &viu_domain.dm,
[DM_ZX296718_USB20] = &usb20_domain.dm,
[DM_ZX296718_USB21] = &usb21_domain.dm,
[DM_ZX296718_USB30] = &usb30_domain.dm,
[DM_ZX296718_HSIC] = &hsic_domain.dm,
[DM_ZX296718_GMAC] = &gmac_domain.dm,
[DM_ZX296718_TS] = &ts_domain.dm,
};
static int zx296718_pd_probe(struct platform_device *pdev)
{
return zx2967_pd_probe(pdev,
zx296718_pm_domains,
ARRAY_SIZE(zx296718_pm_domains));
}
static const struct of_device_id zx296718_pm_domain_matches[] = {
{ .compatible = "zte,zx296718-pcu", },
{ },
};
static struct platform_driver zx296718_pd_driver = {
.driver = {
.name = "zx296718-powerdomain",
.owner = THIS_MODULE,
.of_match_table = zx296718_pm_domain_matches,
},
.probe = zx296718_pd_probe,
};
static int __init zx296718_pd_init(void)
{
return platform_driver_register(&zx296718_pd_driver);
}
subsys_initcall(zx296718_pd_init);
/*
* Copyright (C) 2017 ZTE Ltd.
*
* Author: Baoyou Xie <baoyou.xie@linaro.org>
* License terms: GNU General Public License (GPL) version 2
*/
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/of.h>
#include "zx2967_pm_domains.h"
#define PCU_DM_CLKEN(zpd) ((zpd)->reg_offset[REG_CLKEN])
#define PCU_DM_ISOEN(zpd) ((zpd)->reg_offset[REG_ISOEN])
#define PCU_DM_RSTEN(zpd) ((zpd)->reg_offset[REG_RSTEN])
#define PCU_DM_PWREN(zpd) ((zpd)->reg_offset[REG_PWREN])
#define PCU_DM_ACK_SYNC(zpd) ((zpd)->reg_offset[REG_ACK_SYNC])
static void __iomem *pcubase;
static int zx2967_power_on(struct generic_pm_domain *domain)
{
struct zx2967_pm_domain *zpd = (struct zx2967_pm_domain *)domain;
unsigned long loop = 1000;
u32 val;
val = readl_relaxed(pcubase + PCU_DM_PWREN(zpd));
if (zpd->polarity == PWREN)
val |= BIT(zpd->bit);
else
val &= ~BIT(zpd->bit);
writel_relaxed(val, pcubase + PCU_DM_PWREN(zpd));
do {
udelay(1);
val = readl_relaxed(pcubase + PCU_DM_ACK_SYNC(zpd))
& BIT(zpd->bit);
} while (--loop && !val);
if (!loop) {
pr_err("Error: %s %s fail\n", __func__, domain->name);
return -EIO;
}
val = readl_relaxed(pcubase + PCU_DM_RSTEN(zpd));
val |= BIT(zpd->bit);
writel_relaxed(val, pcubase + PCU_DM_RSTEN(zpd));
udelay(5);
val = readl_relaxed(pcubase + PCU_DM_ISOEN(zpd));
val &= ~BIT(zpd->bit);
writel_relaxed(val, pcubase + PCU_DM_ISOEN(zpd));
udelay(5);
val = readl_relaxed(pcubase + PCU_DM_CLKEN(zpd));
val |= BIT(zpd->bit);
writel_relaxed(val, pcubase + PCU_DM_CLKEN(zpd));
udelay(5);
pr_debug("poweron %s\n", domain->name);
return 0;
}
static int zx2967_power_off(struct generic_pm_domain *domain)
{
struct zx2967_pm_domain *zpd = (struct zx2967_pm_domain *)domain;
unsigned long loop = 1000;
u32 val;
val = readl_relaxed(pcubase + PCU_DM_CLKEN(zpd));
val &= ~BIT(zpd->bit);
writel_relaxed(val, pcubase + PCU_DM_CLKEN(zpd));
udelay(5);
val = readl_relaxed(pcubase + PCU_DM_ISOEN(zpd));
val |= BIT(zpd->bit);
writel_relaxed(val, pcubase + PCU_DM_ISOEN(zpd));
udelay(5);
val = readl_relaxed(pcubase + PCU_DM_RSTEN(zpd));
val &= ~BIT(zpd->bit);
writel_relaxed(val, pcubase + PCU_DM_RSTEN(zpd));
udelay(5);
val = readl_relaxed(pcubase + PCU_DM_PWREN(zpd));
if (zpd->polarity == PWREN)
val &= ~BIT(zpd->bit);
else
val |= BIT(zpd->bit);
writel_relaxed(val, pcubase + PCU_DM_PWREN(zpd));
do {
udelay(1);
val = readl_relaxed(pcubase + PCU_DM_ACK_SYNC(zpd))
& BIT(zpd->bit);
} while (--loop && val);
if (!loop) {
pr_err("Error: %s %s fail\n", __func__, domain->name);
return -EIO;
}
pr_debug("poweroff %s\n", domain->name);
return 0;
}
int zx2967_pd_probe(struct platform_device *pdev,
struct generic_pm_domain **zx_pm_domains,
int domain_num)
{
struct genpd_onecell_data *genpd_data;
struct resource *res;
int i;
genpd_data = devm_kzalloc(&pdev->dev, sizeof(*genpd_data), GFP_KERNEL);
if (!genpd_data)
return -ENOMEM;
genpd_data->domains = zx_pm_domains;
genpd_data->num_domains = domain_num;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pcubase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(pcubase)) {
dev_err(&pdev->dev, "ioremap fail.\n");
return PTR_ERR(pcubase);
}
for (i = 0; i < domain_num; ++i) {
zx_pm_domains[i]->power_on = zx2967_power_on;
zx_pm_domains[i]->power_off = zx2967_power_off;
pm_genpd_init(zx_pm_domains[i], NULL, false);
}
of_genpd_add_provider_onecell(pdev->dev.of_node, genpd_data);
dev_info(&pdev->dev, "powerdomain init ok\n");
return 0;
}
/*
* Header for ZTE's Power Domain Driver support
*
* Copyright (C) 2017 ZTE Ltd.
*
* Author: Baoyou Xie <baoyou.xie@linaro.org>
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef __ZTE_ZX2967_PM_DOMAIN_H
#define __ZTE_ZX2967_PM_DOMAIN_H
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
enum {
REG_CLKEN,
REG_ISOEN,
REG_RSTEN,
REG_PWREN,
REG_PWRDN,
REG_ACK_SYNC,
/* The size of the array - must be last */
REG_ARRAY_SIZE,
};
enum zx2967_power_polarity {
PWREN,
PWRDN,
};
struct zx2967_pm_domain {
struct generic_pm_domain dm;
const u16 bit;
const enum zx2967_power_polarity polarity;
const u16 *reg_offset;
};
int zx2967_pd_probe(struct platform_device *pdev,
struct generic_pm_domain **zx_pm_domains,
int domain_num);
#endif /* __ZTE_ZX2967_PM_DOMAIN_H */
#ifndef __DT_BINDINGS_POWER_RK3328_POWER_H__
#define __DT_BINDINGS_POWER_RK3328_POWER_H__
/**
* RK3328 idle id Summary.
*/
#define RK3328_PD_CORE 0
#define RK3328_PD_GPU 1
#define RK3328_PD_BUS 2
#define RK3328_PD_MSCH 3
#define RK3328_PD_PERI 4
#define RK3328_PD_VIDEO 5
#define RK3328_PD_HEVC 6
#define RK3328_PD_SYS 7
#define RK3328_PD_VPU 8
#define RK3328_PD_VIO 9
#endif
/*
* Copyright (C) 2017 Linaro Ltd.
*
* Author: Baoyou Xie <baoyou.xie@linaro.org>
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef _DT_BINDINGS_SOC_ZTE_PM_DOMAINS_H
#define _DT_BINDINGS_SOC_ZTE_PM_DOMAINS_H
#define DM_ZX296718_SAPPU 0
#define DM_ZX296718_VDE 1 /* g1v6 */
#define DM_ZX296718_VCE 2 /* h1v6 */
#define DM_ZX296718_HDE 3 /* g2v2 */
#define DM_ZX296718_VIU 4
#define DM_ZX296718_USB20 5
#define DM_ZX296718_USB21 6
#define DM_ZX296718_USB30 7
#define DM_ZX296718_HSIC 8
#define DM_ZX296718_GMAC 9
#define DM_ZX296718_TS 10
#define DM_ZX296718_VOU 11
#endif /* _DT_BINDINGS_SOC_ZTE_PM_DOMAINS_H */
...@@ -13,9 +13,9 @@ ...@@ -13,9 +13,9 @@
#ifndef __QCOM_SCM_H #ifndef __QCOM_SCM_H
#define __QCOM_SCM_H #define __QCOM_SCM_H
extern int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus); #define QCOM_SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
extern int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus); #define QCOM_SCM_CPU_PWR_DOWN_L2_ON 0x0
#define QCOM_SCM_CPU_PWR_DOWN_L2_OFF 0x1
#define QCOM_SCM_HDCP_MAX_REQ_CNT 5 #define QCOM_SCM_HDCP_MAX_REQ_CNT 5
struct qcom_scm_hdcp_req { struct qcom_scm_hdcp_req {
...@@ -23,12 +23,13 @@ struct qcom_scm_hdcp_req { ...@@ -23,12 +23,13 @@ struct qcom_scm_hdcp_req {
u32 val; u32 val;
}; };
#if IS_ENABLED(CONFIG_QCOM_SCM)
extern int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus);
extern int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus);
extern bool qcom_scm_is_available(void); extern bool qcom_scm_is_available(void);
extern bool qcom_scm_hdcp_available(void); extern bool qcom_scm_hdcp_available(void);
extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt,
u32 *resp); u32 *resp);
extern bool qcom_scm_pas_supported(u32 peripheral); extern bool qcom_scm_pas_supported(u32 peripheral);
extern int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, extern int qcom_scm_pas_init_image(u32 peripheral, const void *metadata,
size_t size); size_t size);
...@@ -36,14 +37,35 @@ extern int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, ...@@ -36,14 +37,35 @@ extern int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr,
phys_addr_t size); phys_addr_t size);
extern int qcom_scm_pas_auth_and_reset(u32 peripheral); extern int qcom_scm_pas_auth_and_reset(u32 peripheral);
extern int qcom_scm_pas_shutdown(u32 peripheral); extern int qcom_scm_pas_shutdown(u32 peripheral);
#define QCOM_SCM_CPU_PWR_DOWN_L2_ON 0x0
#define QCOM_SCM_CPU_PWR_DOWN_L2_OFF 0x1
extern void qcom_scm_cpu_power_down(u32 flags); extern void qcom_scm_cpu_power_down(u32 flags);
#define QCOM_SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
extern u32 qcom_scm_get_version(void); extern u32 qcom_scm_get_version(void);
extern int qcom_scm_set_remote_state(u32 state, u32 id);
#else
static inline
int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
{
return -ENODEV;
}
static inline
int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
{
return -ENODEV;
}
static inline bool qcom_scm_is_available(void) { return false; }
static inline bool qcom_scm_hdcp_available(void) { return false; }
static inline int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt,
u32 *resp) { return -ENODEV; }
static inline bool qcom_scm_pas_supported(u32 peripheral) { return false; }
static inline int qcom_scm_pas_init_image(u32 peripheral, const void *metadata,
size_t size) { return -ENODEV; }
static inline int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr,
phys_addr_t size) { return -ENODEV; }
static inline int
qcom_scm_pas_auth_and_reset(u32 peripheral) { return -ENODEV; }
static inline int qcom_scm_pas_shutdown(u32 peripheral) { return -ENODEV; }
static inline void qcom_scm_cpu_power_down(u32 flags) {}
static inline u32 qcom_scm_get_version(void) { return 0; }
static inline u32
qcom_scm_set_remote_state(u32 state,u32 id) { return -ENODEV; }
#endif
#endif #endif
...@@ -13,10 +13,12 @@ int reset_control_deassert(struct reset_control *rstc); ...@@ -13,10 +13,12 @@ int reset_control_deassert(struct reset_control *rstc);
int reset_control_status(struct reset_control *rstc); int reset_control_status(struct reset_control *rstc);
struct reset_control *__of_reset_control_get(struct device_node *node, struct reset_control *__of_reset_control_get(struct device_node *node,
const char *id, int index, int shared); const char *id, int index, bool shared,
bool optional);
void reset_control_put(struct reset_control *rstc); void reset_control_put(struct reset_control *rstc);
struct reset_control *__devm_reset_control_get(struct device *dev, struct reset_control *__devm_reset_control_get(struct device *dev,
const char *id, int index, int shared); const char *id, int index, bool shared,
bool optional);
int __must_check device_reset(struct device *dev); int __must_check device_reset(struct device *dev);
...@@ -69,14 +71,15 @@ static inline int device_reset_optional(struct device *dev) ...@@ -69,14 +71,15 @@ static inline int device_reset_optional(struct device *dev)
static inline struct reset_control *__of_reset_control_get( static inline struct reset_control *__of_reset_control_get(
struct device_node *node, struct device_node *node,
const char *id, int index, int shared) const char *id, int index, bool shared,
bool optional)
{ {
return ERR_PTR(-ENOTSUPP); return ERR_PTR(-ENOTSUPP);
} }
static inline struct reset_control *__devm_reset_control_get( static inline struct reset_control *__devm_reset_control_get(
struct device *dev, struct device *dev, const char *id,
const char *id, int index, int shared) int index, bool shared, bool optional)
{ {
return ERR_PTR(-ENOTSUPP); return ERR_PTR(-ENOTSUPP);
} }
...@@ -104,7 +107,8 @@ __must_check reset_control_get_exclusive(struct device *dev, const char *id) ...@@ -104,7 +107,8 @@ __must_check reset_control_get_exclusive(struct device *dev, const char *id)
#ifndef CONFIG_RESET_CONTROLLER #ifndef CONFIG_RESET_CONTROLLER
WARN_ON(1); WARN_ON(1);
#endif #endif
return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, 0); return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, false,
false);
} }
/** /**
...@@ -132,19 +136,22 @@ __must_check reset_control_get_exclusive(struct device *dev, const char *id) ...@@ -132,19 +136,22 @@ __must_check reset_control_get_exclusive(struct device *dev, const char *id)
static inline struct reset_control *reset_control_get_shared( static inline struct reset_control *reset_control_get_shared(
struct device *dev, const char *id) struct device *dev, const char *id)
{ {
return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, 1); return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, true,
false);
} }
static inline struct reset_control *reset_control_get_optional_exclusive( static inline struct reset_control *reset_control_get_optional_exclusive(
struct device *dev, const char *id) struct device *dev, const char *id)
{ {
return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, 0); return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, false,
true);
} }
static inline struct reset_control *reset_control_get_optional_shared( static inline struct reset_control *reset_control_get_optional_shared(
struct device *dev, const char *id) struct device *dev, const char *id)
{ {
return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, 1); return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, true,
true);
} }
/** /**
...@@ -160,7 +167,7 @@ static inline struct reset_control *reset_control_get_optional_shared( ...@@ -160,7 +167,7 @@ static inline struct reset_control *reset_control_get_optional_shared(
static inline struct reset_control *of_reset_control_get_exclusive( static inline struct reset_control *of_reset_control_get_exclusive(
struct device_node *node, const char *id) struct device_node *node, const char *id)
{ {
return __of_reset_control_get(node, id, 0, 0); return __of_reset_control_get(node, id, 0, false, false);
} }
/** /**
...@@ -185,7 +192,7 @@ static inline struct reset_control *of_reset_control_get_exclusive( ...@@ -185,7 +192,7 @@ static inline struct reset_control *of_reset_control_get_exclusive(
static inline struct reset_control *of_reset_control_get_shared( static inline struct reset_control *of_reset_control_get_shared(
struct device_node *node, const char *id) struct device_node *node, const char *id)
{ {
return __of_reset_control_get(node, id, 0, 1); return __of_reset_control_get(node, id, 0, true, false);
} }
/** /**
...@@ -202,7 +209,7 @@ static inline struct reset_control *of_reset_control_get_shared( ...@@ -202,7 +209,7 @@ static inline struct reset_control *of_reset_control_get_shared(
static inline struct reset_control *of_reset_control_get_exclusive_by_index( static inline struct reset_control *of_reset_control_get_exclusive_by_index(
struct device_node *node, int index) struct device_node *node, int index)
{ {
return __of_reset_control_get(node, NULL, index, 0); return __of_reset_control_get(node, NULL, index, false, false);
} }
/** /**
...@@ -230,7 +237,7 @@ static inline struct reset_control *of_reset_control_get_exclusive_by_index( ...@@ -230,7 +237,7 @@ static inline struct reset_control *of_reset_control_get_exclusive_by_index(
static inline struct reset_control *of_reset_control_get_shared_by_index( static inline struct reset_control *of_reset_control_get_shared_by_index(
struct device_node *node, int index) struct device_node *node, int index)
{ {
return __of_reset_control_get(node, NULL, index, 1); return __of_reset_control_get(node, NULL, index, true, false);
} }
/** /**
...@@ -252,7 +259,7 @@ __must_check devm_reset_control_get_exclusive(struct device *dev, ...@@ -252,7 +259,7 @@ __must_check devm_reset_control_get_exclusive(struct device *dev,
#ifndef CONFIG_RESET_CONTROLLER #ifndef CONFIG_RESET_CONTROLLER
WARN_ON(1); WARN_ON(1);
#endif #endif
return __devm_reset_control_get(dev, id, 0, 0); return __devm_reset_control_get(dev, id, 0, false, false);
} }
/** /**
...@@ -267,19 +274,19 @@ __must_check devm_reset_control_get_exclusive(struct device *dev, ...@@ -267,19 +274,19 @@ __must_check devm_reset_control_get_exclusive(struct device *dev,
static inline struct reset_control *devm_reset_control_get_shared( static inline struct reset_control *devm_reset_control_get_shared(
struct device *dev, const char *id) struct device *dev, const char *id)
{ {
return __devm_reset_control_get(dev, id, 0, 1); return __devm_reset_control_get(dev, id, 0, true, false);
} }
static inline struct reset_control *devm_reset_control_get_optional_exclusive( static inline struct reset_control *devm_reset_control_get_optional_exclusive(
struct device *dev, const char *id) struct device *dev, const char *id)
{ {
return __devm_reset_control_get(dev, id, 0, 0); return __devm_reset_control_get(dev, id, 0, false, true);
} }
static inline struct reset_control *devm_reset_control_get_optional_shared( static inline struct reset_control *devm_reset_control_get_optional_shared(
struct device *dev, const char *id) struct device *dev, const char *id)
{ {
return __devm_reset_control_get(dev, id, 0, 1); return __devm_reset_control_get(dev, id, 0, true, true);
} }
/** /**
...@@ -297,7 +304,7 @@ static inline struct reset_control *devm_reset_control_get_optional_shared( ...@@ -297,7 +304,7 @@ static inline struct reset_control *devm_reset_control_get_optional_shared(
static inline struct reset_control * static inline struct reset_control *
devm_reset_control_get_exclusive_by_index(struct device *dev, int index) devm_reset_control_get_exclusive_by_index(struct device *dev, int index)
{ {
return __devm_reset_control_get(dev, NULL, index, 0); return __devm_reset_control_get(dev, NULL, index, false, false);
} }
/** /**
...@@ -313,7 +320,7 @@ devm_reset_control_get_exclusive_by_index(struct device *dev, int index) ...@@ -313,7 +320,7 @@ devm_reset_control_get_exclusive_by_index(struct device *dev, int index)
static inline struct reset_control * static inline struct reset_control *
devm_reset_control_get_shared_by_index(struct device *dev, int index) devm_reset_control_get_shared_by_index(struct device *dev, int index)
{ {
return __devm_reset_control_get(dev, NULL, index, 1); return __devm_reset_control_get(dev, NULL, index, true, false);
} }
/* /*
......
...@@ -7,7 +7,13 @@ ...@@ -7,7 +7,13 @@
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ *
*
* Notice:
* This is not a list of all Exynos Power Management Unit SFRs.
* There are too many of them, not mentioning subtle differences
* between SoCs. For now, put here only the used registers.
*/
#ifndef __LINUX_SOC_EXYNOS_REGS_PMU_H #ifndef __LINUX_SOC_EXYNOS_REGS_PMU_H
#define __LINUX_SOC_EXYNOS_REGS_PMU_H __FILE__ #define __LINUX_SOC_EXYNOS_REGS_PMU_H __FILE__
...@@ -38,7 +44,6 @@ ...@@ -38,7 +44,6 @@
#define EXYNOS_CORE_PO_RESET(n) ((1 << 4) << n) #define EXYNOS_CORE_PO_RESET(n) ((1 << 4) << n)
#define EXYNOS_WAKEUP_FROM_LOWPWR (1 << 28) #define EXYNOS_WAKEUP_FROM_LOWPWR (1 << 28)
#define EXYNOS_SWRESET 0x0400 #define EXYNOS_SWRESET 0x0400
#define EXYNOS5440_SWRESET 0x00C4
#define S5P_WAKEUP_STAT 0x0600 #define S5P_WAKEUP_STAT 0x0600
#define S5P_EINT_WAKEUP_MASK 0x0604 #define S5P_EINT_WAKEUP_MASK 0x0604
...@@ -136,12 +141,6 @@ ...@@ -136,12 +141,6 @@
#define EXYNOS_COMMON_OPTION(_nr) \ #define EXYNOS_COMMON_OPTION(_nr) \
(EXYNOS_COMMON_CONFIGURATION(_nr) + 0x8) (EXYNOS_COMMON_CONFIGURATION(_nr) + 0x8)
#define EXYNOS_CORE_LOCAL_PWR_EN 0x3
#define EXYNOS_ARM_COMMON_STATUS 0x2504
#define EXYNOS_COMMON_OPTION(_nr) \
(EXYNOS_COMMON_CONFIGURATION(_nr) + 0x8)
#define EXYNOS_ARM_L2_CONFIGURATION 0x2600 #define EXYNOS_ARM_L2_CONFIGURATION 0x2600
#define EXYNOS_L2_CONFIGURATION(_nr) \ #define EXYNOS_L2_CONFIGURATION(_nr) \
(EXYNOS_ARM_L2_CONFIGURATION + ((_nr) * 0x80)) (EXYNOS_ARM_L2_CONFIGURATION + ((_nr) * 0x80))
...@@ -149,17 +148,8 @@ ...@@ -149,17 +148,8 @@
(EXYNOS_L2_CONFIGURATION(_nr) + 0x4) (EXYNOS_L2_CONFIGURATION(_nr) + 0x4)
#define EXYNOS_L2_OPTION(_nr) \ #define EXYNOS_L2_OPTION(_nr) \
(EXYNOS_L2_CONFIGURATION(_nr) + 0x8) (EXYNOS_L2_CONFIGURATION(_nr) + 0x8)
#define EXYNOS_L2_COMMON_PWR_EN 0x3
#define EXYNOS_ARM_CORE_X_STATUS_OFFSET 0x4
#define EXYNOS5_APLL_SYSCLK_CONFIGURATION 0x2A00 #define EXYNOS_L2_USE_RETENTION BIT(4)
#define EXYNOS5_APLL_SYSCLK_STATUS 0x2A04
#define EXYNOS5_ARM_L2_OPTION 0x2608
#define EXYNOS5_USE_RETENTION BIT(4)
#define EXYNOS5_L2RSTDISABLE_VALUE BIT(3)
#define S5P_PAD_RET_MAUDIO_OPTION 0x3028 #define S5P_PAD_RET_MAUDIO_OPTION 0x3028
#define S5P_PAD_RET_MMC2_OPTION 0x30c8 #define S5P_PAD_RET_MMC2_OPTION 0x30c8
...@@ -411,7 +401,6 @@ ...@@ -411,7 +401,6 @@
#define EXYNOS5_SATA_MEM_SYS_PWR_REG 0x11FC #define EXYNOS5_SATA_MEM_SYS_PWR_REG 0x11FC
#define EXYNOS5_PAD_RETENTION_DRAM_SYS_PWR_REG 0x1200 #define EXYNOS5_PAD_RETENTION_DRAM_SYS_PWR_REG 0x1200
#define EXYNOS5_PAD_RETENTION_MAU_SYS_PWR_REG 0x1204 #define EXYNOS5_PAD_RETENTION_MAU_SYS_PWR_REG 0x1204
#define EXYNOS5_PAD_RETENTION_EFNAND_SYS_PWR_REG 0x1208
#define EXYNOS5_PAD_RETENTION_GPIO_SYS_PWR_REG 0x1220 #define EXYNOS5_PAD_RETENTION_GPIO_SYS_PWR_REG 0x1220
#define EXYNOS5_PAD_RETENTION_UART_SYS_PWR_REG 0x1224 #define EXYNOS5_PAD_RETENTION_UART_SYS_PWR_REG 0x1224
#define EXYNOS5_PAD_RETENTION_MMCA_SYS_PWR_REG 0x1228 #define EXYNOS5_PAD_RETENTION_MMCA_SYS_PWR_REG 0x1228
...@@ -485,7 +474,6 @@ ...@@ -485,7 +474,6 @@
#define EXYNOS5420_SWRESET_KFC_SEL 0x3 #define EXYNOS5420_SWRESET_KFC_SEL 0x3
/* Only for EXYNOS5420 */ /* Only for EXYNOS5420 */
#define EXYNOS5420_ISP_ARM_OPTION 0x2488
#define EXYNOS5420_L2RSTDISABLE_VALUE BIT(3) #define EXYNOS5420_L2RSTDISABLE_VALUE BIT(3)
#define EXYNOS5420_LPI_MASK 0x0004 #define EXYNOS5420_LPI_MASK 0x0004
...@@ -494,9 +482,6 @@ ...@@ -494,9 +482,6 @@
#define EXYNOS5420_ATB_KFC BIT(13) #define EXYNOS5420_ATB_KFC BIT(13)
#define EXYNOS5420_ATB_ISP_ARM BIT(19) #define EXYNOS5420_ATB_ISP_ARM BIT(19)
#define EXYNOS5420_EMULATION BIT(31) #define EXYNOS5420_EMULATION BIT(31)
#define ATB_ISP_ARM BIT(12)
#define ATB_KFC BIT(13)
#define ATB_NOC BIT(14)
#define EXYNOS5420_ARM_INTR_SPREAD_ENABLE 0x0100 #define EXYNOS5420_ARM_INTR_SPREAD_ENABLE 0x0100
#define EXYNOS5420_ARM_INTR_SPREAD_USE_STANDBYWFI 0x0104 #define EXYNOS5420_ARM_INTR_SPREAD_USE_STANDBYWFI 0x0104
...@@ -510,11 +495,6 @@ ...@@ -510,11 +495,6 @@
#define EXYNOS5420_KFC_CORE_RESET(_nr) \ #define EXYNOS5420_KFC_CORE_RESET(_nr) \
((EXYNOS5420_KFC_CORE_RESET0 | EXYNOS5420_KFC_ETM_RESET0) << (_nr)) ((EXYNOS5420_KFC_CORE_RESET0 | EXYNOS5420_KFC_ETM_RESET0) << (_nr))
#define EXYNOS5420_BB_CON1 0x0784
#define EXYNOS5420_BB_SEL_EN BIT(31)
#define EXYNOS5420_BB_PMOS_EN BIT(7)
#define EXYNOS5420_BB_1300X 0XF
#define EXYNOS5420_ARM_CORE2_SYS_PWR_REG 0x1020 #define EXYNOS5420_ARM_CORE2_SYS_PWR_REG 0x1020
#define EXYNOS5420_DIS_IRQ_ARM_CORE2_LOCAL_SYS_PWR_REG 0x1024 #define EXYNOS5420_DIS_IRQ_ARM_CORE2_LOCAL_SYS_PWR_REG 0x1024
#define EXYNOS5420_DIS_IRQ_ARM_CORE2_CENTRAL_SYS_PWR_REG 0x1028 #define EXYNOS5420_DIS_IRQ_ARM_CORE2_CENTRAL_SYS_PWR_REG 0x1028
...@@ -546,15 +526,6 @@ ...@@ -546,15 +526,6 @@
#define EXYNOS5420_SPLL_SYSCLK_SYS_PWR_REG 0x1178 #define EXYNOS5420_SPLL_SYSCLK_SYS_PWR_REG 0x1178
#define EXYNOS5420_INTRAM_MEM_SYS_PWR_REG 0x11B8 #define EXYNOS5420_INTRAM_MEM_SYS_PWR_REG 0x11B8
#define EXYNOS5420_INTROM_MEM_SYS_PWR_REG 0x11BC #define EXYNOS5420_INTROM_MEM_SYS_PWR_REG 0x11BC
#define EXYNOS5420_ONENANDXL_MEM_SYS_PWR 0x11C0
#define EXYNOS5420_USBDEV_MEM_SYS_PWR 0x11CC
#define EXYNOS5420_USBDEV1_MEM_SYS_PWR 0x11D0
#define EXYNOS5420_SDMMC_MEM_SYS_PWR 0x11D4
#define EXYNOS5420_CSSYS_MEM_SYS_PWR 0x11D8
#define EXYNOS5420_SECSS_MEM_SYS_PWR 0x11DC
#define EXYNOS5420_ROTATOR_MEM_SYS_PWR 0x11E0
#define EXYNOS5420_INTRAM_MEM_SYS_PWR 0x11E4
#define EXYNOS5420_INTROM_MEM_SYS_PWR 0x11E8
#define EXYNOS5420_PAD_RETENTION_JTAG_SYS_PWR_REG 0x1208 #define EXYNOS5420_PAD_RETENTION_JTAG_SYS_PWR_REG 0x1208
#define EXYNOS5420_PAD_RETENTION_DRAM_SYS_PWR_REG 0x1210 #define EXYNOS5420_PAD_RETENTION_DRAM_SYS_PWR_REG 0x1210
#define EXYNOS5420_PAD_RETENTION_UART_SYS_PWR_REG 0x1214 #define EXYNOS5420_PAD_RETENTION_UART_SYS_PWR_REG 0x1214
...@@ -605,13 +576,7 @@ ...@@ -605,13 +576,7 @@
#define EXYNOS5420_CMU_RESET_MSC_SYS_PWR_REG 0x159C #define EXYNOS5420_CMU_RESET_MSC_SYS_PWR_REG 0x159C
#define EXYNOS5420_CMU_RESET_FSYS_SYS_PWR_REG 0x15A0 #define EXYNOS5420_CMU_RESET_FSYS_SYS_PWR_REG 0x15A0
#define EXYNOS5420_SFR_AXI_CGDIS1 0x15E4 #define EXYNOS5420_SFR_AXI_CGDIS1 0x15E4
#define EXYNOS_ARM_CORE2_CONFIGURATION 0x2100
#define EXYNOS5420_ARM_CORE2_OPTION 0x2108
#define EXYNOS_ARM_CORE3_CONFIGURATION 0x2180
#define EXYNOS5420_ARM_CORE3_OPTION 0x2188
#define EXYNOS5420_ARM_COMMON_STATUS 0x2504
#define EXYNOS5420_ARM_COMMON_OPTION 0x2508 #define EXYNOS5420_ARM_COMMON_OPTION 0x2508
#define EXYNOS5420_KFC_COMMON_STATUS 0x2584
#define EXYNOS5420_KFC_COMMON_OPTION 0x2588 #define EXYNOS5420_KFC_COMMON_OPTION 0x2588
#define EXYNOS5420_LOGIC_RESET_DURATION3 0x2D1C #define EXYNOS5420_LOGIC_RESET_DURATION3 0x2D1C
...@@ -626,33 +591,9 @@ ...@@ -626,33 +591,9 @@
#define EXYNOS_PAD_RET_DRAM_OPTION 0x3008 #define EXYNOS_PAD_RET_DRAM_OPTION 0x3008
#define EXYNOS_PAD_RET_MAUDIO_OPTION 0x3028 #define EXYNOS_PAD_RET_MAUDIO_OPTION 0x3028
#define EXYNOS_PAD_RET_JTAG_OPTION 0x3048 #define EXYNOS_PAD_RET_JTAG_OPTION 0x3048
#define EXYNOS_PAD_RET_GPIO_OPTION 0x3108
#define EXYNOS_PAD_RET_UART_OPTION 0x3128
#define EXYNOS_PAD_RET_MMCA_OPTION 0x3148
#define EXYNOS_PAD_RET_MMCB_OPTION 0x3168
#define EXYNOS_PAD_RET_EBIA_OPTION 0x3188 #define EXYNOS_PAD_RET_EBIA_OPTION 0x3188
#define EXYNOS_PAD_RET_EBIB_OPTION 0x31A8 #define EXYNOS_PAD_RET_EBIB_OPTION 0x31A8
#define EXYNOS_PS_HOLD_CONTROL 0x330C
/* For SYS_PWR_REG */
#define EXYNOS_SYS_PWR_CFG BIT(0)
#define EXYNOS5420_MFC_CONFIGURATION 0x4060
#define EXYNOS5420_MFC_STATUS 0x4064
#define EXYNOS5420_MFC_OPTION 0x4068
#define EXYNOS5420_G3D_CONFIGURATION 0x4080
#define EXYNOS5420_G3D_STATUS 0x4084
#define EXYNOS5420_G3D_OPTION 0x4088
#define EXYNOS5420_DISP0_CONFIGURATION 0x40A0
#define EXYNOS5420_DISP0_STATUS 0x40A4
#define EXYNOS5420_DISP0_OPTION 0x40A8
#define EXYNOS5420_DISP1_CONFIGURATION 0x40C0
#define EXYNOS5420_DISP1_STATUS 0x40C4
#define EXYNOS5420_DISP1_OPTION 0x40C8
#define EXYNOS5420_MAU_CONFIGURATION 0x40E0
#define EXYNOS5420_MAU_STATUS 0x40E4
#define EXYNOS5420_MAU_OPTION 0x40E8
#define EXYNOS5420_FSYS2_OPTION 0x4168 #define EXYNOS5420_FSYS2_OPTION 0x4168
#define EXYNOS5420_PSGEN_OPTION 0x4188 #define EXYNOS5420_PSGEN_OPTION 0x4188
...@@ -690,4 +631,20 @@ ...@@ -690,4 +631,20 @@
| EXYNOS5420_KFC_USE_STANDBY_WFI2 \ | EXYNOS5420_KFC_USE_STANDBY_WFI2 \
| EXYNOS5420_KFC_USE_STANDBY_WFI3) | EXYNOS5420_KFC_USE_STANDBY_WFI3)
/* For EXYNOS5433 */
#define EXYNOS5433_PAD_RETENTION_AUD_OPTION (0x3028)
#define EXYNOS5433_PAD_RETENTION_MMC2_OPTION (0x30C8)
#define EXYNOS5433_PAD_RETENTION_TOP_OPTION (0x3108)
#define EXYNOS5433_PAD_RETENTION_UART_OPTION (0x3128)
#define EXYNOS5433_PAD_RETENTION_MMC0_OPTION (0x3148)
#define EXYNOS5433_PAD_RETENTION_MMC1_OPTION (0x3168)
#define EXYNOS5433_PAD_RETENTION_EBIA_OPTION (0x3188)
#define EXYNOS5433_PAD_RETENTION_EBIB_OPTION (0x31A8)
#define EXYNOS5433_PAD_RETENTION_SPI_OPTION (0x31C8)
#define EXYNOS5433_PAD_RETENTION_MIF_OPTION (0x31E8)
#define EXYNOS5433_PAD_RETENTION_USBXTI_OPTION (0x3228)
#define EXYNOS5433_PAD_RETENTION_BOOTLDO_OPTION (0x3248)
#define EXYNOS5433_PAD_RETENTION_UFS_OPTION (0x3268)
#define EXYNOS5433_PAD_RETENTION_FSYSGENIO_OPTION (0x32A8)
#endif /* __LINUX_SOC_EXYNOS_REGS_PMU_H */ #endif /* __LINUX_SOC_EXYNOS_REGS_PMU_H */
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