mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
ARM: SoC driver updates
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) -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJYrM7/AAoJEIwa5zzehBx3qisP/18NwvbYvC3rMza7k+TEU66n vuEF9KW5GhUpQPbNIsTer5qHhC7ZgL7RoR/H7mpZcCxfhYiNXuUaOv8TMGK+WTLQ HH6QTs4mARLh1IrRcog1hoElzzqMVxaQgODeaaG1DcPvTqHWsQurbXsf17tCQOri nWKyxFpLNlu0kktkGb5JWrM4XBjU9KsW7LME9H86wG8HmB6+mcT5ddeYwW5nD8cG txXgmMjdTEKcpbeTg3cAzL4504auhIl4R9uK+8dc1sw+e9T0nXNDS9IkmLPwWtSR u8q6zQ3zReoDw4jGUgPP0ILHudfQsiMdWS+P2hw/krpbtLlQ+irHDVa1VA3NLiUT 9aG9cNTYRMo3ct22YEeWsnAC04XOxpCsqHTR+UWuZaBmf3eoMIXnsafTuwLzqKlQ Ent/4eFPInMAzDH8Kaf1Hh0918qkgF2bNlshem11TccQKvHP+qCoHk6mKGxwEj5k E1UEG4S6k6zNqjLwmTBBbk8sLMl/WVo6RMSMz+JflatgPmVZco4EX2O73iKGAJVU 5GfHIUG9Yl4+aTIUORu59cWxOCApK0kqERrFKe412BMurXlLfqVcr/H2tiiuWnn1 cEJ9d+uBd8IxTIQX0iEYGUAkX97mhxGUYdqGQuGJSV+MOfWX1zNP1sI4EscLGKQj sDDZScCaguM4xE20Jum1 =od7u -----END PGP SIGNATURE----- Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc Pull ARM SoC driver updates from Arnd Bergmann: "Driver updates for ARM SoCs. 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 ...
This commit is contained in:
commit
b2e3c4319d
@ -6,12 +6,15 @@ to gate power to one or more peripherals on the processor.
|
||||
Required Properties:
|
||||
- compatible: should be one of the following.
|
||||
* 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
|
||||
region.
|
||||
- #power-domain-cells: number of cells in power domain specifier;
|
||||
must be 0.
|
||||
|
||||
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
|
||||
devices in this power domain are set to oscclk before power gating
|
||||
and restored back after powering on a domain. This is required for
|
||||
@ -38,6 +41,7 @@ Example:
|
||||
compatible = "samsung,exynos4210-pd";
|
||||
reg = <0x10023C00 0x10>;
|
||||
#power-domain-cells = <0>;
|
||||
label = "LCD0";
|
||||
};
|
||||
|
||||
mfc_pd: power-domain@10044060 {
|
||||
@ -46,6 +50,7 @@ Example:
|
||||
clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MOUT_USER_ACLK333>;
|
||||
clock-names = "oscclk", "clk0";
|
||||
#power-domain-cells = <0>;
|
||||
label = "MFC";
|
||||
};
|
||||
|
||||
See Documentation/devicetree/bindings/power/power_domain.txt for description
|
||||
|
@ -0,0 +1,43 @@
|
||||
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:
|
||||
--------
|
||||
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
|
||||
Edison SoC.
|
||||
66AK2E SoC.
|
||||
|
||||
/ {
|
||||
soc {
|
||||
@ -71,13 +71,13 @@ Edison SoC.
|
||||
compatible = "syscon", "simple-mfd";
|
||||
reg = <0x02350000 0x1000>;
|
||||
|
||||
pscrst: psc-reset {
|
||||
pscrst: reset-controller {
|
||||
compatible = "ti,k2e-pscrst", "ti,syscon-reset";
|
||||
#reset-cells = <1>;
|
||||
|
||||
ti,reset-bits = <
|
||||
0xa3c 8 0xa3c 8 0x83c 8 (ASSERT_SET|DEASSERT_CLEAR|STATUS_SET) /* 0: pcrst-dsp0 */
|
||||
0xa40 5 0xa44 3 0 0 (ASSERT_SET|DEASSERT_CLEAR|STATUS_NONE) /* 1: pcrst-example */
|
||||
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: example */
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
@ -6,14 +6,14 @@ System reset
|
||||
|
||||
Required properties:
|
||||
- compatible: should be one of the following:
|
||||
"socionext,uniphier-sld3-reset" - for sLD3 SoC.
|
||||
"socionext,uniphier-ld4-reset" - for LD4 SoC.
|
||||
"socionext,uniphier-pro4-reset" - for Pro4 SoC.
|
||||
"socionext,uniphier-sld8-reset" - for sLD8 SoC.
|
||||
"socionext,uniphier-pro5-reset" - for Pro5 SoC.
|
||||
"socionext,uniphier-pxs2-reset" - for PXs2/LD6b SoC.
|
||||
"socionext,uniphier-ld11-reset" - for LD11 SoC.
|
||||
"socionext,uniphier-ld20-reset" - for LD20 SoC.
|
||||
"socionext,uniphier-sld3-reset" - for sLD3 SoC
|
||||
"socionext,uniphier-ld4-reset" - for LD4 SoC
|
||||
"socionext,uniphier-pro4-reset" - for Pro4 SoC
|
||||
"socionext,uniphier-sld8-reset" - for sLD8 SoC
|
||||
"socionext,uniphier-pro5-reset" - for Pro5 SoC
|
||||
"socionext,uniphier-pxs2-reset" - for PXs2/LD6b SoC
|
||||
"socionext,uniphier-ld11-reset" - for LD11 SoC
|
||||
"socionext,uniphier-ld20-reset" - for LD20 SoC
|
||||
- #reset-cells: should be 1.
|
||||
|
||||
Example:
|
||||
@ -37,14 +37,15 @@ Media I/O (MIO) reset, SD reset
|
||||
|
||||
Required properties:
|
||||
- compatible: should be one of the following:
|
||||
"socionext,uniphier-sld3-mio-reset" - for sLD3 SoC.
|
||||
"socionext,uniphier-ld4-mio-reset" - for LD4 SoC.
|
||||
"socionext,uniphier-pro4-mio-reset" - for Pro4 SoC.
|
||||
"socionext,uniphier-sld8-mio-reset" - for sLD8 SoC.
|
||||
"socionext,uniphier-pro5-sd-reset" - for Pro5 SoC.
|
||||
"socionext,uniphier-pxs2-sd-reset" - for PXs2/LD6b SoC.
|
||||
"socionext,uniphier-ld11-mio-reset" - for LD11 SoC.
|
||||
"socionext,uniphier-ld20-sd-reset" - for LD20 SoC.
|
||||
"socionext,uniphier-sld3-mio-reset" - for sLD3 SoC
|
||||
"socionext,uniphier-ld4-mio-reset" - for LD4 SoC
|
||||
"socionext,uniphier-pro4-mio-reset" - for Pro4 SoC
|
||||
"socionext,uniphier-sld8-mio-reset" - for sLD8 SoC
|
||||
"socionext,uniphier-pro5-sd-reset" - for Pro5 SoC
|
||||
"socionext,uniphier-pxs2-sd-reset" - for PXs2/LD6b SoC
|
||||
"socionext,uniphier-ld11-mio-reset" - for LD11 SoC (MIO)
|
||||
"socionext,uniphier-ld11-sd-reset" - for LD11 SoC (SD)
|
||||
"socionext,uniphier-ld20-sd-reset" - for LD20 SoC
|
||||
- #reset-cells: should be 1.
|
||||
|
||||
Example:
|
||||
@ -68,13 +69,13 @@ Peripheral reset
|
||||
|
||||
Required properties:
|
||||
- compatible: should be one of the following:
|
||||
"socionext,uniphier-ld4-peri-reset" - for LD4 SoC.
|
||||
"socionext,uniphier-pro4-peri-reset" - for Pro4 SoC.
|
||||
"socionext,uniphier-sld8-peri-reset" - for sLD8 SoC.
|
||||
"socionext,uniphier-pro5-peri-reset" - for Pro5 SoC.
|
||||
"socionext,uniphier-pxs2-peri-reset" - for PXs2/LD6b SoC.
|
||||
"socionext,uniphier-ld11-peri-reset" - for LD11 SoC.
|
||||
"socionext,uniphier-ld20-peri-reset" - for LD20 SoC.
|
||||
"socionext,uniphier-ld4-peri-reset" - for LD4 SoC
|
||||
"socionext,uniphier-pro4-peri-reset" - for Pro4 SoC
|
||||
"socionext,uniphier-sld8-peri-reset" - for sLD8 SoC
|
||||
"socionext,uniphier-pro5-peri-reset" - for Pro5 SoC
|
||||
"socionext,uniphier-pxs2-peri-reset" - for PXs2/LD6b SoC
|
||||
"socionext,uniphier-ld11-peri-reset" - for LD11 SoC
|
||||
"socionext,uniphier-ld20-peri-reset" - for LD20 SoC
|
||||
- #reset-cells: should be 1.
|
||||
|
||||
Example:
|
||||
|
20
Documentation/devicetree/bindings/reset/zte,zx2967-reset.txt
Normal file
20
Documentation/devicetree/bindings/reset/zte,zx2967-reset.txt
Normal file
@ -0,0 +1,20 @@
|
||||
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.
|
||||
|
||||
From RK3368 SoCs, the GRF is divided into two sections,
|
||||
- GRF, used for general non-secure system,
|
||||
- SGRF, used for general secure system,
|
||||
- PMUGRF, used for always on system
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible: GRF should be one of the followings
|
||||
- "rockchip,rk3036-grf", "syscon": for rk3036
|
||||
- "rockchip,rk3066-grf", "syscon": for rk3066
|
||||
- "rockchip,rk3188-grf", "syscon": for rk3188
|
||||
- "rockchip,rk3228-grf", "syscon": for rk3228
|
||||
@ -19,6 +21,8 @@ Required Properties:
|
||||
- compatible: PMUGRF should be one of the followings
|
||||
- "rockchip,rk3368-pmugrf", "syscon": for rk3368
|
||||
- "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
|
||||
region.
|
||||
|
||||
|
@ -6,6 +6,7 @@ powered up/down by software based on different application scenes to save power.
|
||||
Required properties for power domain controller:
|
||||
- compatible: Should be one of the following.
|
||||
"rockchip,rk3288-power-controller" - for RK3288 SoCs.
|
||||
"rockchip,rk3328-power-controller" - for RK3328 SoCs.
|
||||
"rockchip,rk3368-power-controller" - for RK3368 SoCs.
|
||||
"rockchip,rk3399-power-controller" - for RK3399 SoCs.
|
||||
- #power-domain-cells: Number of cells in a power-domain specifier.
|
||||
@ -16,6 +17,7 @@ Required properties for power domain controller:
|
||||
Required properties for power domain sub nodes:
|
||||
- reg: index of the power domain, should use macros in:
|
||||
"include/dt-bindings/power/rk3288-power.h" - for RK3288 type power domain.
|
||||
"include/dt-bindings/power/rk3328-power.h" - for RK3328 type power domain.
|
||||
"include/dt-bindings/power/rk3368-power.h" - for RK3368 type power domain.
|
||||
"include/dt-bindings/power/rk3399-power.h" - for RK3399 type power domain.
|
||||
- clocks (optional): phandles to clocks which need to be enabled while power domain
|
||||
@ -90,6 +92,7 @@ containing a phandle to the power device node and an index specifying which
|
||||
power domain to use.
|
||||
The index should use macros in:
|
||||
"include/dt-bindings/power/rk3288-power.h" - for rk3288 type power domain.
|
||||
"include/dt-bindings/power/rk3328-power.h" - for rk3328 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.
|
||||
|
||||
|
19
Documentation/devicetree/bindings/soc/zte/pd-2967xx.txt
Normal file
19
Documentation/devicetree/bindings/soc/zte/pd-2967xx.txt
Normal file
@ -0,0 +1,19 @@
|
||||
* 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/*
|
||||
F: drivers/i2c/busses/i2c-qup.c
|
||||
F: drivers/clk/qcom/
|
||||
F: drivers/pinctrl/qcom/
|
||||
F: drivers/dma/qcom/
|
||||
F: drivers/soc/qcom/
|
||||
F: drivers/spi/spi-qup.c
|
||||
F: drivers/tty/serial/msm_serial.h
|
||||
@ -1987,12 +1988,18 @@ F: arch/arm/mach-pxa/include/mach/z2.h
|
||||
|
||||
ARM/ZTE ARCHITECTURE
|
||||
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)
|
||||
S: Maintained
|
||||
F: arch/arm/mach-zx/
|
||||
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/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
|
||||
M: Michal Simek <michal.simek@xilinx.com>
|
||||
|
@ -345,9 +345,9 @@ static void exynos5420_pm_prepare(void)
|
||||
if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM))
|
||||
pmu_raw_writel(virt_to_phys(mcpm_entry_point), S5P_INFORM0);
|
||||
|
||||
tmp = pmu_raw_readl(EXYNOS5_ARM_L2_OPTION);
|
||||
tmp &= ~EXYNOS5_USE_RETENTION;
|
||||
pmu_raw_writel(tmp, EXYNOS5_ARM_L2_OPTION);
|
||||
tmp = pmu_raw_readl(EXYNOS_L2_OPTION(0));
|
||||
tmp &= ~EXYNOS_L2_USE_RETENTION;
|
||||
pmu_raw_writel(tmp, EXYNOS_L2_OPTION(0));
|
||||
|
||||
tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1);
|
||||
tmp |= EXYNOS5420_UFS;
|
||||
|
@ -29,13 +29,11 @@
|
||||
#include "core.h"
|
||||
#include "pm.h"
|
||||
|
||||
#define RK3288_GRF_SOC_CON0 0x244
|
||||
#define RK3288_TIMER6_7_PHYS 0xff810000
|
||||
|
||||
static void __init rockchip_timer_init(void)
|
||||
{
|
||||
if (of_machine_is_compatible("rockchip,rk3288")) {
|
||||
struct regmap *grf;
|
||||
void __iomem *reg_base;
|
||||
|
||||
/*
|
||||
@ -54,16 +52,6 @@ static void __init rockchip_timer_init(void)
|
||||
} else {
|
||||
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);
|
||||
|
@ -398,6 +398,9 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
|
||||
int pmp, unsigned long deadline,
|
||||
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);
|
||||
int ahci_stop_engine(struct ata_port *ap);
|
||||
void ahci_start_fis_rx(struct ata_port *ap);
|
||||
|
@ -16,7 +16,8 @@
|
||||
#include <linux/ahci_platform.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 */
|
||||
#define SATA_P0PHYCR_REG 0x178
|
||||
@ -28,17 +29,8 @@
|
||||
#define SATA_PHY_TXSWING(x) ((x) << 19)
|
||||
#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,
|
||||
void __iomem *ahci_base)
|
||||
void __iomem *ahci_base, u32 mpy)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
@ -47,18 +39,122 @@ static void da850_sata_init(struct device *dev, void __iomem *pwrdn_reg,
|
||||
val &= ~BIT(0);
|
||||
writel(val, pwrdn_reg);
|
||||
|
||||
val = SATA_PHY_MPY(DA850_SATA_CLK_MULTIPLIER + 1) | SATA_PHY_LOS(1) |
|
||||
SATA_PHY_RXCDR(4) | SATA_PHY_RXEQ(1) | SATA_PHY_TXSWING(3) |
|
||||
SATA_PHY_ENPLL(1);
|
||||
val = SATA_PHY_MPY(mpy) | SATA_PHY_LOS(1) | SATA_PHY_RXCDR(4) |
|
||||
SATA_PHY_RXEQ(1) | SATA_PHY_TXSWING(3) | SATA_PHY_ENPLL(1);
|
||||
|
||||
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 = {
|
||||
.flags = AHCI_FLAG_COMMON,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.udma_mask = ATA_UDMA6,
|
||||
.port_ops = &ahci_platform_ops,
|
||||
.port_ops = &ahci_da850_port_ops,
|
||||
};
|
||||
|
||||
static struct scsi_host_template ahci_platform_sht = {
|
||||
@ -69,14 +165,52 @@ static int ahci_da850_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct ahci_host_priv *hpriv;
|
||||
struct resource *res;
|
||||
void __iomem *pwrdn_reg;
|
||||
struct resource *res;
|
||||
struct clk *clk;
|
||||
u32 mpy;
|
||||
int rc;
|
||||
|
||||
hpriv = ahci_platform_get_resources(pdev);
|
||||
if (IS_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);
|
||||
if (rc)
|
||||
return rc;
|
||||
@ -89,7 +223,7 @@ static int ahci_da850_probe(struct platform_device *pdev)
|
||||
if (!pwrdn_reg)
|
||||
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,
|
||||
&ahci_platform_sht);
|
||||
@ -105,11 +239,18 @@ disable_resources:
|
||||
static SIMPLE_DEV_PM_OPS(ahci_da850_pm_ops, ahci_platform_suspend,
|
||||
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 = {
|
||||
.probe = ahci_da850_probe,
|
||||
.remove = ata_platform_remove_one,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = ahci_da850_of_match,
|
||||
.pm = &ahci_da850_pm_ops,
|
||||
},
|
||||
};
|
||||
|
@ -1519,8 +1519,8 @@ static int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ahci_hardreset(struct ata_link *link, unsigned int *class,
|
||||
unsigned long deadline)
|
||||
int ahci_do_hardreset(struct ata_link *link, unsigned int *class,
|
||||
unsigned long deadline, bool *online)
|
||||
{
|
||||
const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
|
||||
struct ata_port *ap = link->ap;
|
||||
@ -1528,7 +1528,6 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class,
|
||||
struct ahci_host_priv *hpriv = ap->host->private_data;
|
||||
u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
|
||||
struct ata_taskfile tf;
|
||||
bool online;
|
||||
int rc;
|
||||
|
||||
DPRINTK("ENTER\n");
|
||||
@ -1540,17 +1539,26 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class,
|
||||
tf.command = ATA_BUSY;
|
||||
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);
|
||||
|
||||
hpriv->start_engine(ap);
|
||||
|
||||
if (online)
|
||||
if (*online)
|
||||
*class = ahci_dev_classify(ap);
|
||||
|
||||
DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
|
||||
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)
|
||||
{
|
||||
|
@ -112,6 +112,7 @@ config QCOM_EBI2
|
||||
bool "Qualcomm External Bus Interface 2 (EBI2)"
|
||||
depends on HAS_IOMEM
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
default ARCH_QCOM
|
||||
help
|
||||
Say y here to enable support for the Qualcomm External Bus
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
}
|
||||
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)
|
||||
{
|
||||
struct qcom_scm *scm;
|
||||
@ -387,7 +393,7 @@ static int qcom_scm_probe(struct platform_device *pdev)
|
||||
|
||||
static const struct of_device_id qcom_scm_dt_match[] = {
|
||||
{ .compatible = "qcom,scm-apq8064",
|
||||
.data = (void *) SCM_HAS_CORE_CLK,
|
||||
/* FIXME: This should have .data = (void *) SCM_HAS_CORE_CLK */
|
||||
},
|
||||
{ .compatible = "qcom,scm-msm8660",
|
||||
.data = (void *) SCM_HAS_CORE_CLK,
|
||||
|
@ -15,6 +15,8 @@
|
||||
#define QCOM_SCM_SVC_BOOT 0x1
|
||||
#define QCOM_SCM_BOOT_ADDR 0x1
|
||||
#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_COLDBOOT_MC 0x02
|
||||
|
@ -76,9 +76,11 @@ struct at91_ebi_caps {
|
||||
|
||||
struct at91_ebi {
|
||||
struct clk *clk;
|
||||
struct regmap *smc;
|
||||
struct regmap *matrix;
|
||||
|
||||
struct {
|
||||
struct regmap *regmap;
|
||||
struct clk *clk;
|
||||
} smc;
|
||||
struct regmap_field *ebi_csa;
|
||||
|
||||
struct device *dev;
|
||||
@ -93,7 +95,7 @@ static void at91sam9_ebi_get_config(struct at91_ebi_dev *ebid,
|
||||
struct at91_ebi_dev_config *conf)
|
||||
{
|
||||
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_smc_timings *timings = &config->timings;
|
||||
unsigned int val;
|
||||
@ -102,43 +104,43 @@ static void at91sam9_ebi_get_config(struct at91_ebi_dev *ebid,
|
||||
config->mode = val & ~AT91_SMC_TDF;
|
||||
|
||||
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);
|
||||
timings->ncs_rd_setup_ns = (val >> 24) & 0x1f;
|
||||
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 >> 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 >> 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 >> 5) & 0x1) * 128;
|
||||
timings->nwe_setup_ns *= clk_rate;
|
||||
timings->nwe_setup_ns *= clk_period;
|
||||
|
||||
regmap_fields_read(fields->pulse, conf->cs, &val);
|
||||
timings->ncs_rd_pulse_ns = (val >> 24) & 0x3f;
|
||||
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 >> 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 >> 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 >> 6) & 0x1) * 256;
|
||||
timings->nwe_pulse_ns *= clk_rate;
|
||||
timings->nwe_pulse_ns *= clk_period;
|
||||
|
||||
regmap_fields_read(fields->cycle, conf->cs, &val);
|
||||
timings->nrd_cycle_ns = (val >> 16) & 0x7f;
|
||||
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 >> 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,
|
||||
@ -334,6 +336,7 @@ static int at91sam9_ebi_apply_config(struct at91_ebi_dev *ebid,
|
||||
struct at91_ebi_dev_config *conf)
|
||||
{
|
||||
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_smc_timings *timings = &config->timings;
|
||||
struct at91sam9_smc_generic_fields *fields = &ebid->ebi->sam9;
|
||||
@ -376,7 +379,7 @@ static int at91sam9_ebi_apply_config(struct at91_ebi_dev *ebid,
|
||||
val |= AT91SAM9_SMC_NWECYCLE(coded_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)
|
||||
val = AT91_SMC_TDF_MAX;
|
||||
regmap_fields_write(fields->mode, conf->cs,
|
||||
@ -394,22 +397,26 @@ static int at91sam9_ebi_init(struct at91_ebi *ebi)
|
||||
field.id_offset = AT91SAM9_SMC_GENERIC_BLK_SZ;
|
||||
|
||||
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))
|
||||
return PTR_ERR(fields->setup);
|
||||
|
||||
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))
|
||||
return PTR_ERR(fields->pulse);
|
||||
|
||||
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))
|
||||
return PTR_ERR(fields->cycle);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -422,22 +429,26 @@ static int sama5d3_ebi_init(struct at91_ebi *ebi)
|
||||
field.id_offset = SAMA5_SMC_GENERIC_BLK_SZ;
|
||||
|
||||
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))
|
||||
return PTR_ERR(fields->setup);
|
||||
|
||||
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))
|
||||
return PTR_ERR(fields->pulse);
|
||||
|
||||
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))
|
||||
return PTR_ERR(fields->cycle);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -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 device *dev = ebi->dev;
|
||||
struct at91_ebi_dev *ebid;
|
||||
int ret, numcs = 0, i;
|
||||
unsigned long cslines = 0;
|
||||
int ret, numcs = 0, nentries, i;
|
||||
bool apply = false;
|
||||
u32 cs;
|
||||
|
||||
numcs = of_property_count_elems_of_size(np, "reg",
|
||||
reg_cells * sizeof(u32));
|
||||
if (numcs <= 0) {
|
||||
nentries = of_property_count_elems_of_size(np, "reg",
|
||||
reg_cells * sizeof(u32));
|
||||
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);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -472,21 +502,8 @@ static int at91_ebi_dev_setup(struct at91_ebi *ebi, struct device_node *np,
|
||||
else if (ret)
|
||||
apply = true;
|
||||
|
||||
for (i = 0; i < numcs; i++) {
|
||||
u32 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;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for_each_set_bit(cs, &cslines, AT91_MATRIX_EBI_NUM_CS) {
|
||||
ebid->configs[i].cs = cs;
|
||||
|
||||
if (apply) {
|
||||
@ -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
|
||||
* one "atmel,smc-" property is present.
|
||||
*/
|
||||
if (ebi->ebi_csa && ret)
|
||||
if (ebi->ebi_csa && apply)
|
||||
regmap_field_update_bits(ebi->ebi_csa,
|
||||
BIT(cs), 0);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
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)
|
||||
static int at91_ebi_probe(struct platform_device *pdev)
|
||||
{
|
||||
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;
|
||||
struct at91_ebi *ebi;
|
||||
int ret, reg_cells;
|
||||
@ -693,9 +712,22 @@ static int at91_ebi_probe(struct platform_device *pdev)
|
||||
|
||||
ebi->clk = clk;
|
||||
|
||||
ebi->smc = syscon_regmap_lookup_by_phandle(np, "atmel,smc");
|
||||
if (IS_ERR(ebi->smc))
|
||||
return PTR_ERR(ebi->smc);
|
||||
smc_np = of_parse_phandle(dev->of_node, "atmel,smc", 0);
|
||||
|
||||
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
|
||||
|
@ -1115,11 +1115,10 @@ static int tegra_emc_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
mc = of_find_device_by_node(np);
|
||||
of_node_put(np);
|
||||
if (!mc)
|
||||
return -ENOENT;
|
||||
|
||||
of_node_put(np);
|
||||
|
||||
emc->mc = platform_get_drvdata(mc);
|
||||
if (!emc->mc)
|
||||
return -EPROBE_DEFER;
|
||||
@ -1135,9 +1134,7 @@ static int tegra_emc_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
err = tegra_emc_load_timings_from_dt(emc, np);
|
||||
|
||||
of_node_put(np);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -86,6 +86,12 @@ config RESET_UNIPHIER
|
||||
Say Y if you want to control reset signals provided by System Control
|
||||
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
|
||||
bool "ZYNQ Reset Driver" if COMPILE_TEST
|
||||
default ARCH_ZYNQ
|
||||
|
@ -13,4 +13,5 @@ obj-$(CONFIG_RESET_STM32) += reset-stm32.o
|
||||
obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
|
||||
obj-$(CONFIG_TI_SYSCON_RESET) += reset-ti-syscon.o
|
||||
obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
|
||||
obj-$(CONFIG_RESET_ZX2967) += reset-zx2967.o
|
||||
obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
|
||||
|
@ -41,7 +41,7 @@ struct reset_control {
|
||||
struct list_head list;
|
||||
unsigned int id;
|
||||
unsigned int refcnt;
|
||||
int shared;
|
||||
bool shared;
|
||||
atomic_t deassert_count;
|
||||
atomic_t triggered_count;
|
||||
};
|
||||
@ -143,12 +143,18 @@ EXPORT_SYMBOL_GPL(devm_reset_controller_register);
|
||||
* a no-op.
|
||||
* Consumers must not use reset_control_(de)assert on shared reset lines when
|
||||
* 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 ret;
|
||||
|
||||
if (WARN_ON(IS_ERR_OR_NULL(rstc)))
|
||||
if (!rstc)
|
||||
return 0;
|
||||
|
||||
if (WARN_ON(IS_ERR(rstc)))
|
||||
return -EINVAL;
|
||||
|
||||
if (!rstc->rcdev->ops->reset)
|
||||
@ -182,10 +188,17 @@ EXPORT_SYMBOL_GPL(reset_control_reset);
|
||||
* 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
|
||||
* 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)
|
||||
{
|
||||
if (WARN_ON(IS_ERR_OR_NULL(rstc)))
|
||||
if (!rstc)
|
||||
return 0;
|
||||
|
||||
if (WARN_ON(IS_ERR(rstc)))
|
||||
return -EINVAL;
|
||||
|
||||
if (!rstc->rcdev->ops->assert)
|
||||
@ -213,10 +226,17 @@ EXPORT_SYMBOL_GPL(reset_control_assert);
|
||||
* After calling this function, the reset is guaranteed to be deasserted.
|
||||
* Consumers must not use reset_control_reset on shared reset lines when
|
||||
* 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)
|
||||
{
|
||||
if (WARN_ON(IS_ERR_OR_NULL(rstc)))
|
||||
if (!rstc)
|
||||
return 0;
|
||||
|
||||
if (WARN_ON(IS_ERR(rstc)))
|
||||
return -EINVAL;
|
||||
|
||||
if (!rstc->rcdev->ops->deassert)
|
||||
@ -237,12 +257,15 @@ EXPORT_SYMBOL_GPL(reset_control_deassert);
|
||||
/**
|
||||
* reset_control_status - returns a negative errno if not supported, a
|
||||
* 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
|
||||
*/
|
||||
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;
|
||||
|
||||
if (rstc->rcdev->ops->status)
|
||||
@ -254,7 +277,7 @@ EXPORT_SYMBOL_GPL(reset_control_status);
|
||||
|
||||
static struct reset_control *__reset_control_get(
|
||||
struct reset_controller_dev *rcdev,
|
||||
unsigned int index, int shared)
|
||||
unsigned int index, bool shared)
|
||||
{
|
||||
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,
|
||||
const char *id, int index, int shared)
|
||||
const char *id, int index, bool shared,
|
||||
bool optional)
|
||||
{
|
||||
struct reset_control *rstc;
|
||||
struct reset_controller_dev *r, *rcdev;
|
||||
@ -313,14 +337,18 @@ struct reset_control *__of_reset_control_get(struct device_node *node,
|
||||
if (id) {
|
||||
index = of_property_match_string(node,
|
||||
"reset-names", id);
|
||||
if (index == -EILSEQ)
|
||||
return ERR_PTR(index);
|
||||
if (index < 0)
|
||||
return ERR_PTR(-ENOENT);
|
||||
return optional ? NULL : ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
||||
ret = of_parse_phandle_with_args(node, "resets", "#reset-cells",
|
||||
index, &args);
|
||||
if (ret)
|
||||
if (ret == -EINVAL)
|
||||
return ERR_PTR(ret);
|
||||
if (ret)
|
||||
return optional ? NULL : ERR_PTR(ret);
|
||||
|
||||
mutex_lock(&reset_list_mutex);
|
||||
rcdev = NULL;
|
||||
@ -364,7 +392,7 @@ EXPORT_SYMBOL_GPL(__of_reset_control_get);
|
||||
|
||||
void reset_control_put(struct reset_control *rstc)
|
||||
{
|
||||
if (IS_ERR(rstc))
|
||||
if (IS_ERR_OR_NULL(rstc))
|
||||
return;
|
||||
|
||||
mutex_lock(&reset_list_mutex);
|
||||
@ -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,
|
||||
const char *id, int index, int shared)
|
||||
const char *id, int index, bool shared,
|
||||
bool optional)
|
||||
{
|
||||
struct reset_control **ptr, *rstc;
|
||||
|
||||
@ -389,7 +418,7 @@ struct reset_control *__devm_reset_control_get(struct device *dev,
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
rstc = __of_reset_control_get(dev ? dev->of_node : NULL,
|
||||
id, index, shared);
|
||||
id, index, shared, optional);
|
||||
if (!IS_ERR(rstc)) {
|
||||
*ptr = rstc;
|
||||
devres_add(dev, ptr);
|
||||
|
@ -1,3 +1,10 @@
|
||||
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
|
||||
tristate "Hi6220 Reset Driver"
|
||||
depends on ARCH_HISI || COMPILE_TEST
|
||||
|
@ -1 +1,2 @@
|
||||
obj-$(CONFIG_COMMON_RESET_HI6220) += hi6220_reset.o
|
||||
obj-$(CONFIG_COMMON_RESET_HI3660) += reset-hi3660.o
|
||||
|
126
drivers/reset/hisilicon/reset-hi3660.c
Normal file
126
drivers/reset/hisilicon/reset-hi3660.c
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return (reset_state & BIT(control->status_bit)) &&
|
||||
(control->flags & STATUS_SET);
|
||||
return !(reset_state & BIT(control->status_bit)) ==
|
||||
!(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,
|
||||
.deassert = ti_syscon_reset_deassert,
|
||||
.status = ti_syscon_reset_status,
|
||||
|
@ -389,6 +389,10 @@ static const struct of_device_id uniphier_reset_match[] = {
|
||||
.compatible = "socionext,uniphier-ld11-mio-reset",
|
||||
.data = uniphier_sld3_mio_reset_data,
|
||||
},
|
||||
{
|
||||
.compatible = "socionext,uniphier-ld11-sd-reset",
|
||||
.data = uniphier_pro5_sd_reset_data,
|
||||
},
|
||||
{
|
||||
.compatible = "socionext,uniphier-ld20-sd-reset",
|
||||
.data = uniphier_pro5_sd_reset_data,
|
||||
|
99
drivers/reset/reset-zx2967.c
Normal file
99
drivers/reset/reset-zx2967.c
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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"
|
||||
source "drivers/soc/ti/Kconfig"
|
||||
source "drivers/soc/ux500/Kconfig"
|
||||
source "drivers/soc/versatile/Kconfig"
|
||||
source "drivers/soc/zte/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
@ -16,3 +16,4 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/
|
||||
obj-$(CONFIG_SOC_TI) += ti/
|
||||
obj-$(CONFIG_ARCH_U8500) += ux500/
|
||||
obj-$(CONFIG_PLAT_VERSATILE) += versatile/
|
||||
obj-$(CONFIG_ARCH_ZX) += zte/
|
||||
|
@ -3,6 +3,16 @@ if ARCH_ROCKCHIP || COMPILE_TEST
|
||||
#
|
||||
# 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
|
||||
bool "Rockchip generic power domain"
|
||||
depends on PM
|
||||
|
@ -1,4 +1,5 @@
|
||||
#
|
||||
# Rockchip Soc drivers
|
||||
#
|
||||
obj-$(CONFIG_ROCKCHIP_GRF) += grf.o
|
||||
obj-$(CONFIG_ROCKCHIP_PM_DOMAINS) += pm_domains.o
|
||||
|
134
drivers/soc/rockchip/grf.c
Normal file
134
drivers/soc/rockchip/grf.c
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* 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 @@
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/mfd/syscon.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/rk3399-power.h>
|
||||
|
||||
@ -29,6 +30,8 @@ struct rockchip_domain_info {
|
||||
int idle_mask;
|
||||
int ack_mask;
|
||||
bool active_wakeup;
|
||||
int pwr_w_mask;
|
||||
int req_w_mask;
|
||||
};
|
||||
|
||||
struct rockchip_pmu_info {
|
||||
@ -87,9 +90,24 @@ struct rockchip_pmu {
|
||||
.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) \
|
||||
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) \
|
||||
DOMAIN(pwr, status, req, (req) + 16, req, wakeup)
|
||||
|
||||
@ -127,9 +145,13 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
|
||||
|
||||
if (pd_info->req_mask == 0)
|
||||
return 0;
|
||||
|
||||
regmap_update_bits(pmu->regmap, pmu->info->req_offset,
|
||||
pd_info->req_mask, idle ? -1U : 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,
|
||||
pd_info->req_mask, idle ? -1U : 0);
|
||||
|
||||
dsb(sy);
|
||||
|
||||
@ -230,9 +252,13 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
|
||||
|
||||
if (pd->info->pwr_mask == 0)
|
||||
return;
|
||||
|
||||
regmap_update_bits(pmu->regmap, pmu->info->pwr_offset,
|
||||
pd->info->pwr_mask, on ? 0 : -1U);
|
||||
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,
|
||||
pd->info->pwr_mask, on ? 0 : -1U);
|
||||
|
||||
dsb(sy);
|
||||
|
||||
@ -692,6 +718,18 @@ static const struct rockchip_domain_info rk3288_pm_domains[] = {
|
||||
[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[] = {
|
||||
[RK3368_PD_PERI] = DOMAIN_RK3368(13, 12, 6, true),
|
||||
[RK3368_PD_VIO] = DOMAIN_RK3368(15, 14, 8, false),
|
||||
@ -747,6 +785,15 @@ static const struct rockchip_pmu_info rk3288_pmu = {
|
||||
.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 = {
|
||||
.pwr_offset = 0x0c,
|
||||
.status_offset = 0x10,
|
||||
@ -782,6 +829,10 @@ static const struct of_device_id rockchip_pm_domain_dt_match[] = {
|
||||
.compatible = "rockchip,rk3288-power-controller",
|
||||
.data = (void *)&rk3288_pmu,
|
||||
},
|
||||
{
|
||||
.compatible = "rockchip,rk3328-power-controller",
|
||||
.data = (void *)&rk3328_pmu,
|
||||
},
|
||||
{
|
||||
.compatible = "rockchip,rk3368-power-controller",
|
||||
.data = (void *)&rk3368_pmu,
|
||||
|
@ -44,7 +44,7 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode)
|
||||
unsigned int i;
|
||||
const struct exynos_pmu_data *pmu_data;
|
||||
|
||||
if (!pmu_context)
|
||||
if (!pmu_context || !pmu_context->pmu_data)
|
||||
return;
|
||||
|
||||
pmu_data = pmu_context->pmu_data;
|
||||
@ -90,6 +90,8 @@ static const struct of_device_id exynos_pmu_of_device_ids[] = {
|
||||
}, {
|
||||
.compatible = "samsung,exynos5420-pmu",
|
||||
.data = &exynos5420_pmu_data,
|
||||
}, {
|
||||
.compatible = "samsung,exynos5433-pmu",
|
||||
},
|
||||
{ /*sentinel*/ },
|
||||
};
|
||||
@ -122,7 +124,7 @@ static int exynos_pmu_probe(struct platform_device *pdev)
|
||||
pmu_context->dev = 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();
|
||||
|
||||
platform_set_drvdata(pdev, pmu_context);
|
||||
|
@ -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_ARM_COMMON_SYS_PWR_REG, { 0x0, 0x0, 0x2} },
|
||||
{ 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_SCLKSTOP_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
|
||||
{ EXYNOS5_CMU_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
|
||||
|
@ -230,11 +230,11 @@ static void exynos5420_pmu_init(void)
|
||||
pmu_raw_writel(EXYNOS5420_USE_STANDBY_WFI_ALL, S5P_CENTRAL_SEQ_OPTION);
|
||||
|
||||
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));
|
||||
|
||||
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));
|
||||
|
||||
/*
|
||||
|
@ -35,7 +35,6 @@ struct exynos_pm_domain_config {
|
||||
*/
|
||||
struct exynos_pm_domain {
|
||||
void __iomem *base;
|
||||
char const *name;
|
||||
bool is_off;
|
||||
struct generic_pm_domain pd;
|
||||
struct clk *oscclk;
|
||||
@ -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]);
|
||||
if (clk_set_parent(pd->clk[i], pd->oscclk))
|
||||
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)
|
||||
continue; /* Skip on first power up */
|
||||
if (clk_set_parent(pd->clk[i], pd->pclk[i]))
|
||||
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 = {
|
||||
.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 = {
|
||||
{
|
||||
.compatible = "samsung,exynos4210-pd",
|
||||
.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)
|
||||
{
|
||||
struct device_node *np;
|
||||
@ -150,20 +165,16 @@ static __init int exynos4_pm_init_power_domain(void)
|
||||
|
||||
pd = kzalloc(sizeof(*pd), GFP_KERNEL);
|
||||
if (!pd) {
|
||||
pr_err("%s: failed to allocate memory for domain\n",
|
||||
__func__);
|
||||
of_node_put(np);
|
||||
return -ENOMEM;
|
||||
}
|
||||
pd->pd.name = kstrdup_const(strrchr(np->full_name, '/') + 1,
|
||||
GFP_KERNEL);
|
||||
pd->pd.name = exynos_get_domain_name(np);
|
||||
if (!pd->pd.name) {
|
||||
kfree(pd);
|
||||
of_node_put(np);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pd->name = pd->pd.name;
|
||||
pd->base = of_iomap(np, 0);
|
||||
if (!pd->base) {
|
||||
pr_warn("%s: failed to map memory\n", __func__);
|
||||
@ -227,10 +238,10 @@ no_clk:
|
||||
|
||||
if (of_genpd_add_subdomain(&parent, &child))
|
||||
pr_warn("%s failed to add subdomain: %s\n",
|
||||
parent.np->name, child.np->name);
|
||||
parent.np->full_name, child.np->full_name);
|
||||
else
|
||||
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;
|
||||
|
@ -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",
|
||||
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;
|
||||
}
|
||||
|
||||
@ -436,7 +436,7 @@ void *knav_dma_open_channel(struct device *dev, const char *name,
|
||||
}
|
||||
|
||||
dev_dbg(kdev->dev, "initializing %s channel %d from DMA %s\n",
|
||||
config->direction == DMA_MEM_TO_DEV ? "transmit" :
|
||||
config->direction == DMA_MEM_TO_DEV ? "transmit" :
|
||||
config->direction == DMA_DEV_TO_MEM ? "receive" :
|
||||
"unknown", chan_num, instance);
|
||||
|
||||
|
@ -16,21 +16,12 @@
|
||||
* General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/bitops.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/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/soc/ti/knav_qmss.h>
|
||||
|
||||
#include "knav_qmss.h"
|
||||
|
||||
|
@ -16,26 +16,17 @@
|
||||
* General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.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/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/soc/ti/knav_qmss.h>
|
||||
|
||||
#include "knav_qmss.h"
|
||||
|
@ -370,8 +370,6 @@ static void wkup_m3_rproc_boot_thread(struct wkup_m3_ipc *m3_ipc)
|
||||
struct device *dev = m3_ipc->dev;
|
||||
int ret;
|
||||
|
||||
wait_for_completion(&m3_ipc->rproc->firmware_loading_complete);
|
||||
|
||||
init_completion(&m3_ipc->sync_complete);
|
||||
|
||||
ret = rproc_boot(m3_ipc->rproc);
|
||||
|
13
drivers/soc/zte/Kconfig
Normal file
13
drivers/soc/zte/Kconfig
Normal file
@ -0,0 +1,13 @@
|
||||
#
|
||||
# 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
|
5
drivers/soc/zte/Makefile
Normal file
5
drivers/soc/zte/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
#
|
||||
# ZTE SOC drivers
|
||||
#
|
||||
obj-$(CONFIG_ZX2967_PM_DOMAINS) += zx2967_pm_domains.o
|
||||
obj-$(CONFIG_ZX2967_PM_DOMAINS) += zx296718_pm_domains.o
|
182
drivers/soc/zte/zx296718_pm_domains.c
Normal file
182
drivers/soc/zte/zx296718_pm_domains.c
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* 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);
|
143
drivers/soc/zte/zx2967_pm_domains.c
Normal file
143
drivers/soc/zte/zx2967_pm_domains.c
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
44
drivers/soc/zte/zx2967_pm_domains.h
Normal file
44
drivers/soc/zte/zx2967_pm_domains.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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 */
|
18
include/dt-bindings/power/rk3328-power.h
Normal file
18
include/dt-bindings/power/rk3328-power.h
Normal file
@ -0,0 +1,18 @@
|
||||
#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
|
24
include/dt-bindings/soc/zte,pm_domains.h
Normal file
24
include/dt-bindings/soc/zte,pm_domains.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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 @@
|
||||
#ifndef __QCOM_SCM_H
|
||||
#define __QCOM_SCM_H
|
||||
|
||||
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);
|
||||
|
||||
#define QCOM_SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
|
||||
#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
|
||||
|
||||
struct qcom_scm_hdcp_req {
|
||||
@ -23,27 +23,49 @@ struct qcom_scm_hdcp_req {
|
||||
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_hdcp_available(void);
|
||||
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 int qcom_scm_pas_init_image(u32 peripheral, const void *metadata,
|
||||
size_t size);
|
||||
size_t size);
|
||||
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_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);
|
||||
|
||||
#define QCOM_SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
|
||||
|
||||
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
|
||||
|
@ -13,10 +13,12 @@ int reset_control_deassert(struct reset_control *rstc);
|
||||
int reset_control_status(struct reset_control *rstc);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
@ -69,14 +71,15 @@ static inline int device_reset_optional(struct device *dev)
|
||||
|
||||
static inline 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)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
}
|
||||
|
||||
static inline struct reset_control *__devm_reset_control_get(
|
||||
struct device *dev,
|
||||
const char *id, int index, int shared)
|
||||
struct device *dev, const char *id,
|
||||
int index, bool shared, bool optional)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
}
|
||||
@ -104,7 +107,8 @@ __must_check reset_control_get_exclusive(struct device *dev, const char *id)
|
||||
#ifndef CONFIG_RESET_CONTROLLER
|
||||
WARN_ON(1);
|
||||
#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)
|
||||
static inline struct reset_control *reset_control_get_shared(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, 1);
|
||||
return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, true,
|
||||
false);
|
||||
}
|
||||
|
||||
static inline struct reset_control *reset_control_get_optional_exclusive(
|
||||
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(
|
||||
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(
|
||||
static inline struct reset_control *of_reset_control_get_exclusive(
|
||||
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(
|
||||
static inline struct reset_control *of_reset_control_get_shared(
|
||||
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(
|
||||
static inline struct reset_control *of_reset_control_get_exclusive_by_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(
|
||||
static inline struct reset_control *of_reset_control_get_shared_by_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,
|
||||
#ifndef CONFIG_RESET_CONTROLLER
|
||||
WARN_ON(1);
|
||||
#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,
|
||||
static inline struct reset_control *devm_reset_control_get_shared(
|
||||
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(
|
||||
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(
|
||||
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(
|
||||
static inline struct reset_control *
|
||||
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)
|
||||
static inline struct reset_control *
|
||||
devm_reset_control_get_shared_by_index(struct device *dev, int index)
|
||||
{
|
||||
return __devm_reset_control_get(dev, NULL, index, 1);
|
||||
return __devm_reset_control_get(dev, NULL, index, true, false);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -7,7 +7,13 @@
|
||||
* 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.
|
||||
*/
|
||||
*
|
||||
*
|
||||
* 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
|
||||
#define __LINUX_SOC_EXYNOS_REGS_PMU_H __FILE__
|
||||
@ -38,7 +44,6 @@
|
||||
#define EXYNOS_CORE_PO_RESET(n) ((1 << 4) << n)
|
||||
#define EXYNOS_WAKEUP_FROM_LOWPWR (1 << 28)
|
||||
#define EXYNOS_SWRESET 0x0400
|
||||
#define EXYNOS5440_SWRESET 0x00C4
|
||||
|
||||
#define S5P_WAKEUP_STAT 0x0600
|
||||
#define S5P_EINT_WAKEUP_MASK 0x0604
|
||||
@ -136,12 +141,6 @@
|
||||
#define EXYNOS_COMMON_OPTION(_nr) \
|
||||
(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_L2_CONFIGURATION(_nr) \
|
||||
(EXYNOS_ARM_L2_CONFIGURATION + ((_nr) * 0x80))
|
||||
@ -149,17 +148,8 @@
|
||||
(EXYNOS_L2_CONFIGURATION(_nr) + 0x4)
|
||||
#define EXYNOS_L2_OPTION(_nr) \
|
||||
(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 EXYNOS5_APLL_SYSCLK_STATUS 0x2A04
|
||||
|
||||
#define EXYNOS5_ARM_L2_OPTION 0x2608
|
||||
#define EXYNOS5_USE_RETENTION BIT(4)
|
||||
|
||||
#define EXYNOS5_L2RSTDISABLE_VALUE BIT(3)
|
||||
#define EXYNOS_L2_USE_RETENTION BIT(4)
|
||||
|
||||
#define S5P_PAD_RET_MAUDIO_OPTION 0x3028
|
||||
#define S5P_PAD_RET_MMC2_OPTION 0x30c8
|
||||
@ -411,7 +401,6 @@
|
||||
#define EXYNOS5_SATA_MEM_SYS_PWR_REG 0x11FC
|
||||
#define EXYNOS5_PAD_RETENTION_DRAM_SYS_PWR_REG 0x1200
|
||||
#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_UART_SYS_PWR_REG 0x1224
|
||||
#define EXYNOS5_PAD_RETENTION_MMCA_SYS_PWR_REG 0x1228
|
||||
@ -485,7 +474,6 @@
|
||||
#define EXYNOS5420_SWRESET_KFC_SEL 0x3
|
||||
|
||||
/* Only for EXYNOS5420 */
|
||||
#define EXYNOS5420_ISP_ARM_OPTION 0x2488
|
||||
#define EXYNOS5420_L2RSTDISABLE_VALUE BIT(3)
|
||||
|
||||
#define EXYNOS5420_LPI_MASK 0x0004
|
||||
@ -494,9 +482,6 @@
|
||||
#define EXYNOS5420_ATB_KFC BIT(13)
|
||||
#define EXYNOS5420_ATB_ISP_ARM BIT(19)
|
||||
#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_USE_STANDBYWFI 0x0104
|
||||
@ -510,11 +495,6 @@
|
||||
#define EXYNOS5420_KFC_CORE_RESET(_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_DIS_IRQ_ARM_CORE2_LOCAL_SYS_PWR_REG 0x1024
|
||||
#define EXYNOS5420_DIS_IRQ_ARM_CORE2_CENTRAL_SYS_PWR_REG 0x1028
|
||||
@ -546,15 +526,6 @@
|
||||
#define EXYNOS5420_SPLL_SYSCLK_SYS_PWR_REG 0x1178
|
||||
#define EXYNOS5420_INTRAM_MEM_SYS_PWR_REG 0x11B8
|
||||
#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_DRAM_SYS_PWR_REG 0x1210
|
||||
#define EXYNOS5420_PAD_RETENTION_UART_SYS_PWR_REG 0x1214
|
||||
@ -605,13 +576,7 @@
|
||||
#define EXYNOS5420_CMU_RESET_MSC_SYS_PWR_REG 0x159C
|
||||
#define EXYNOS5420_CMU_RESET_FSYS_SYS_PWR_REG 0x15A0
|
||||
#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_KFC_COMMON_STATUS 0x2584
|
||||
#define EXYNOS5420_KFC_COMMON_OPTION 0x2588
|
||||
#define EXYNOS5420_LOGIC_RESET_DURATION3 0x2D1C
|
||||
|
||||
@ -626,33 +591,9 @@
|
||||
#define EXYNOS_PAD_RET_DRAM_OPTION 0x3008
|
||||
#define EXYNOS_PAD_RET_MAUDIO_OPTION 0x3028
|
||||
#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_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_PSGEN_OPTION 0x4188
|
||||
|
||||
@ -690,4 +631,20 @@
|
||||
| EXYNOS5420_KFC_USE_STANDBY_WFI2 \
|
||||
| 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 */
|
||||
|
Loading…
Reference in New Issue
Block a user