Merge tag 'scpi-updates-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep...
authorOlof Johansson <olof@lixom.net>
Tue, 5 Jul 2016 04:32:07 +0000 (21:32 -0700)
committerOlof Johansson <olof@lixom.net>
Tue, 5 Jul 2016 04:32:07 +0000 (21:32 -0700)
SCPI updates and fixes for v4.8

1. Adds support for device power state management using generic power
   domains and runtime PM

2. Other minor/miscellaneous fixes to the driver

* tag 'scpi-updates-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux:
  firmware: scpi: add device power domain support using genpd
  Documentation: add DT bindings for ARM SCPI power domains
  firmware: arm_scpi: add support for device power state management
  firmware: arm_scpi: make it depend on MAILBOX instead of ARM_MHU
  firmware: arm_scpi: mark scpi_get_sensor_value as static
  firmware: arm_scpi: remove dvfs_get packed structure

Signed-off-by: Olof Johansson <olof@lixom.net>
80 files changed:
Documentation/devicetree/bindings/media/s5p-mfc.txt
Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt [new file with mode: 0644]
Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt
Documentation/devicetree/bindings/reset/amlogic,meson-reset.txt [new file with mode: 0644]
Documentation/driver-model/devres.txt
MAINTAINERS
arch/arm/boot/dts/exynos-mfc-reserved-memory.dtsi [new file with mode: 0644]
arch/arm/boot/dts/exynos4210-origen.dts
arch/arm/boot/dts/exynos4210-smdkv310.dts
arch/arm/boot/dts/exynos4412-odroid-common.dtsi
arch/arm/boot/dts/exynos4412-origen.dts
arch/arm/boot/dts/exynos4412-smdk4412.dts
arch/arm/boot/dts/exynos5250-arndale.dts
arch/arm/boot/dts/exynos5250-smdk5250.dts
arch/arm/boot/dts/exynos5250-spring.dts
arch/arm/boot/dts/exynos5420-arndale-octa.dts
arch/arm/boot/dts/exynos5420-peach-pit.dts
arch/arm/boot/dts/exynos5420-smdk5420.dts
arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
arch/arm/boot/dts/exynos5800-peach-pi.dts
arch/arm/mach-exynos/Kconfig
arch/arm/mach-exynos/Makefile
arch/arm/mach-exynos/exynos.c
arch/arm/mach-exynos/mfc.h [deleted file]
arch/arm/mach-exynos/pm_domains.c [deleted file]
arch/arm/mach-exynos/s5p-dev-mfc.c [deleted file]
drivers/media/platform/exynos-gsc/gsc-core.c
drivers/media/platform/exynos4-is/fimc-core.c
drivers/media/platform/exynos4-is/fimc-is.c
drivers/media/platform/exynos4-is/fimc-lite.c
drivers/media/platform/s5p-g2d/g2d.c
drivers/media/platform/s5p-jpeg/jpeg-core.c
drivers/media/platform/s5p-mfc/s5p_mfc.c
drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h [new file with mode: 0644]
drivers/media/platform/s5p-tv/mixer_video.c
drivers/media/v4l2-core/videobuf2-dma-contig.c
drivers/memory/Kconfig
drivers/memory/Makefile
drivers/memory/atmel-ebi.c [new file with mode: 0644]
drivers/memory/atmel-sdramc.c
drivers/of/of_reserved_mem.c
drivers/power/reset/Kconfig
drivers/power/reset/Makefile
drivers/power/reset/brcm-kona-reset.c [new file with mode: 0644]
drivers/reset/Kconfig
drivers/reset/Makefile
drivers/reset/core.c
drivers/reset/reset-ath79.c
drivers/reset/reset-meson.c [new file with mode: 0644]
drivers/reset/reset-oxnas.c
drivers/reset/reset-pistachio.c
drivers/reset/reset-socfpga.c
drivers/reset/reset-sunxi.c
drivers/reset/reset-zynq.c
drivers/reset/sti/Kconfig
drivers/soc/Kconfig
drivers/soc/Makefile
drivers/soc/bcm/Kconfig
drivers/soc/bcm/Makefile
drivers/soc/bcm/brcmstb/Makefile [new file with mode: 0644]
drivers/soc/bcm/brcmstb/biuctrl.c [new file with mode: 0644]
drivers/soc/bcm/brcmstb/common.c [new file with mode: 0644]
drivers/soc/brcmstb/Kconfig [deleted file]
drivers/soc/brcmstb/Makefile [deleted file]
drivers/soc/brcmstb/biuctrl.c [deleted file]
drivers/soc/brcmstb/common.c [deleted file]
drivers/soc/renesas/Makefile
drivers/soc/renesas/r8a7796-sysc.c [new file with mode: 0644]
drivers/soc/renesas/rcar-sysc.c
drivers/soc/renesas/rcar-sysc.h
drivers/soc/samsung/Kconfig
drivers/soc/samsung/Makefile
drivers/soc/samsung/pm_domains.c [new file with mode: 0644]
include/dt-bindings/power/r8a7796-sysc.h [new file with mode: 0644]
include/dt-bindings/reset/amlogic,meson-gxbb-reset.h [new file with mode: 0644]
include/dt-bindings/reset/amlogic,meson8b-reset.h [new file with mode: 0644]
include/linux/of_reserved_mem.h
include/linux/reset-controller.h
include/linux/reset.h
include/media/videobuf2-dma-contig.h

index 2d5787e..92c94f5 100644 (file)
@@ -21,15 +21,18 @@ Required properties:
   - clock-names : from common clock binding: must contain "mfc",
                  corresponding to entry in the clocks property.
 
-  - samsung,mfc-r : Base address of the first memory bank used by MFC
-                   for DMA contiguous memory allocation and its size.
-
-  - samsung,mfc-l : Base address of the second memory bank used by MFC
-                   for DMA contiguous memory allocation and its size.
-
 Optional properties:
   - power-domains : power-domain property defined with a phandle
                           to respective power domain.
+  - memory-region : from reserved memory binding: phandles to two reserved
+       memory regions, first is for "left" mfc memory bus interfaces,
+       second if for the "right" mfc memory bus, used when no SYSMMU
+       support is available
+
+Obsolete properties:
+  - samsung,mfc-r, samsung,mfc-l : support removed, please use memory-region
+       property instead
+
 
 Example:
 SoC specific DT entry:
@@ -43,9 +46,29 @@ mfc: codec@13400000 {
        clock-names = "mfc";
 };
 
+Reserved memory specific DT entry for given board (see reserved memory binding
+for more information):
+
+reserved-memory {
+       #address-cells = <1>;
+       #size-cells = <1>;
+       ranges;
+
+       mfc_left: region@51000000 {
+               compatible = "shared-dma-pool";
+               no-map;
+               reg = <0x51000000 0x800000>;
+       };
+
+       mfc_right: region@43000000 {
+               compatible = "shared-dma-pool";
+               no-map;
+               reg = <0x43000000 0x800000>;
+       };
+};
+
 Board specific DT entry:
 
 codec@13400000 {
-       samsung,mfc-r = <0x43000000 0x800000>;
-       samsung,mfc-l = <0x51000000 0x800000>;
+       memory-region = <&mfc_left>, <&mfc_right>;
 };
diff --git a/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt b/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
new file mode 100644 (file)
index 0000000..9bb5f57
--- /dev/null
@@ -0,0 +1,136 @@
+* Device tree bindings for Atmel EBI
+
+The External Bus Interface (EBI) controller is a bus where you can connect
+asynchronous (NAND, NOR, SRAM, ....) and synchronous memories (SDR/DDR SDRAMs).
+The EBI provides a glue-less interface to asynchronous memories through the SMC
+(Static Memory Controller).
+
+Required properties:
+
+- compatible:          "atmel,at91sam9260-ebi"
+                       "atmel,at91sam9261-ebi"
+                       "atmel,at91sam9263-ebi0"
+                       "atmel,at91sam9263-ebi1"
+                       "atmel,at91sam9rl-ebi"
+                       "atmel,at91sam9g45-ebi"
+                       "atmel,at91sam9x5-ebi"
+                       "atmel,sama5d3-ebi"
+
+- reg:                 Contains offset/length value for EBI memory mapping.
+                       This property might contain several entries if the EBI
+                       memory range is not contiguous
+
+- #address-cells:      Must be 2.
+                       The first cell encodes the CS.
+                       The second cell encode the offset into the CS memory
+                       range.
+
+- #size-cells:         Must be set to 1.
+
+- ranges:              Encodes CS to memory region association.
+
+- clocks:              Clock feeding the EBI controller.
+                       See clock-bindings.txt
+
+Children device nodes are representing device connected to the EBI bus.
+
+Required device node properties:
+
+- reg:                 Contains the chip-select id, the offset and the length
+                       of the memory region requested by the device.
+
+EBI bus configuration will be defined directly in the device subnode.
+
+Optional EBI/SMC properties:
+
+- atmel,smc-bus-width:         width of the asynchronous device's data bus
+                               8, 16 or 32.
+                               Default to 8 when undefined.
+
+- atmel,smc-byte-access-type   "write" or "select" (see Atmel datasheet).
+                               Default to "select" when undefined.
+
+- atmel,smc-read-mode          "nrd" or "ncs".
+                               Default to "ncs" when undefined.
+
+- atmel,smc-write-mode         "nwe" or "ncs".
+                               Default to "ncs" when undefined.
+
+- atmel,smc-exnw-mode          "disabled", "frozen" or "ready".
+                               Default to "disabled" when undefined.
+
+- atmel,smc-page-mode          enable page mode if present. The provided value
+                               defines the page size (supported values: 4, 8,
+                               16 and 32).
+
+- atmel,smc-tdf-mode:          "normal" or "optimized". When set to
+                               "optimized" the data float time is optimized
+                               depending on the next device being accessed
+                               (next device setup time is subtracted to the
+                               current device data float time).
+                               Default to "normal" when undefined.
+
+If at least one atmel,smc- property is defined the following SMC timing
+properties become mandatory. In the other hand, if none of the atmel,smc-
+properties are specified, we assume that the EBI bus configuration will be
+handled by the sub-device driver, and none of those properties should be
+defined.
+
+All the timings are expressed in nanoseconds (see Atmel datasheet for a full
+description).
+
+- atmel,smc-ncs-rd-setup-ns
+- atmel,smc-nrd-setup-ns
+- atmel,smc-ncs-wr-setup-ns
+- atmel,smc-nwe-setup-ns
+- atmel,smc-ncs-rd-pulse-ns
+- atmel,smc-nrd-pulse-ns
+- atmel,smc-ncs-wr-pulse-ns
+- atmel,smc-nwe-pulse-ns
+- atmel,smc-nwe-cycle-ns
+- atmel,smc-nrd-cycle-ns
+- atmel,smc-tdf-ns
+
+Example:
+
+       ebi: ebi@10000000 {
+               compatible = "atmel,sama5d3-ebi";
+               #address-cells = <2>;
+               #size-cells = <1>;
+               atmel,smc = <&hsmc>;
+               atmel,matrix = <&matrix>;
+               reg = <0x10000000 0x10000000
+                      0x40000000 0x30000000>;
+               ranges = <0x0 0x0 0x10000000 0x10000000
+                         0x1 0x0 0x40000000 0x10000000
+                         0x2 0x0 0x50000000 0x10000000
+                         0x3 0x0 0x60000000 0x10000000>;
+               clocks = <&mck>;
+
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_ebi_addr>;
+
+               nor: flash@0,0 {
+                       compatible = "cfi-flash";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0x0 0x0 0x1000000>;
+                       bank-width = <2>;
+
+                       atmel,smc-read-mode = "nrd";
+                       atmel,smc-write-mode = "nwe";
+                       atmel,smc-bus-width = <16>;
+                       atmel,smc-ncs-rd-setup-ns = <0>;
+                       atmel,smc-ncs-wr-setup-ns = <0>;
+                       atmel,smc-nwe-setup-ns = <8>;
+                       atmel,smc-nrd-setup-ns = <16>;
+                       atmel,smc-ncs-rd-pulse-ns = <84>;
+                       atmel,smc-ncs-wr-pulse-ns = <84>;
+                       atmel,smc-nrd-pulse-ns = <76>;
+                       atmel,smc-nwe-pulse-ns = <76>;
+                       atmel,smc-nrd-cycle-ns = <107>;
+                       atmel,smc-nwe-cycle-ns = <84>;
+                       atmel,smc-tdf-ns = <16>;
+               };
+       };
+
index b74e4d4..0725fb3 100644 (file)
@@ -14,6 +14,7 @@ Required properties:
       - "renesas,r8a7793-sysc" (R-Car M2-N)
       - "renesas,r8a7794-sysc" (R-Car E2)
       - "renesas,r8a7795-sysc" (R-Car H3)
+      - "renesas,r8a7796-sysc" (R-Car M3-W)
   - reg: Address start and address range for the device.
   - #power-domain-cells: Must be 1.
 
diff --git a/Documentation/devicetree/bindings/reset/amlogic,meson-reset.txt b/Documentation/devicetree/bindings/reset/amlogic,meson-reset.txt
new file mode 100644 (file)
index 0000000..e746b63
--- /dev/null
@@ -0,0 +1,18 @@
+Amlogic Meson SoC Reset Controller
+=======================================
+
+Please also refer to reset.txt in this directory for common reset
+controller binding usage.
+
+Required properties:
+- compatible: Should be "amlogic,meson8b-reset" or "amlogic,meson-gxbb-reset"
+- reg: should contain the register address base
+- #reset-cells: 1, see below
+
+example:
+
+reset: reset-controller {
+       compatible = "amlogic,meson-gxbb-reset";
+       reg = <0x0 0x04404 0x0 0x20>;
+       #reset-cells = <1>;
+};
index c63eea0..f5e5223 100644 (file)
@@ -352,6 +352,10 @@ REGULATOR
   devm_regulator_put()
   devm_regulator_register()
 
+RESET
+  devm_reset_control_get()
+  devm_reset_controller_register()
+
 SLAVE DMA ENGINE
   devm_acpi_dma_controller_register()
 
index 7304d2e..2e0187d 100644 (file)
@@ -2489,6 +2489,7 @@ F:        arch/arm64/boot/dts/broadcom/
 F:     arch/arm/configs/bcm_defconfig
 F:     drivers/mmc/host/sdhci-bcm-kona.c
 F:     drivers/clocksource/bcm_kona_timer.c
+F:     drivers/power/reset/brcm-kona-reset.c
 
 BROADCOM BCM2835 ARM ARCHITECTURE
 M:     Stephen Warren <swarren@wwwdotorg.org>
diff --git a/arch/arm/boot/dts/exynos-mfc-reserved-memory.dtsi b/arch/arm/boot/dts/exynos-mfc-reserved-memory.dtsi
new file mode 100644 (file)
index 0000000..c4d063a
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Samsung's Exynos SoC MFC (Video Codec) reserved memory common definition.
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+/ {
+       reserved-memory {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               mfc_left: region@51000000 {
+                       compatible = "shared-dma-pool";
+                       no-map;
+                       reg = <0x51000000 0x800000>;
+               };
+
+               mfc_right: region@43000000 {
+                       compatible = "shared-dma-pool";
+                       no-map;
+                       reg = <0x43000000 0x800000>;
+               };
+       };
+};
index ad7394c..f5e4eb2 100644 (file)
@@ -18,6 +18,7 @@
 #include "exynos4210.dtsi"
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
+#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
        model = "Insignal Origen evaluation board based on Exynos4210";
 };
 
 &mfc {
-       samsung,mfc-r = <0x43000000 0x800000>;
-       samsung,mfc-l = <0x51000000 0x800000>;
+       memory-region = <&mfc_left>, <&mfc_right>;
        status = "okay";
 };
 
index 94ca7d3..de917f0 100644 (file)
@@ -17,6 +17,7 @@
 /dts-v1/;
 #include "exynos4210.dtsi"
 #include <dt-bindings/gpio/gpio.h>
+#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
        model = "Samsung smdkv310 evaluation board based on Exynos4210";
 };
 
 &mfc {
-       samsung,mfc-r = <0x43000000 0x800000>;
-       samsung,mfc-l = <0x51000000 0x800000>;
+       memory-region = <&mfc_left>, <&mfc_right>;
        status = "okay";
 };
 
index ec7619a..276ac9a 100644 (file)
@@ -13,6 +13,7 @@
 #include "exynos4412.dtsi"
 #include "exynos4412-ppmu-common.dtsi"
 #include <dt-bindings/gpio/gpio.h>
+#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
        chosen {
        clock-names = "iis", "i2s_opclk0", "i2s_opclk1";
 };
 
+&mfc {
+       memory-region = <&mfc_left>, <&mfc_right>;
+       status = "okay";
+};
+
 &mixer {
        status = "okay";
 };
index 8bca699..cd363d7 100644 (file)
@@ -16,6 +16,7 @@
 #include "exynos4412.dtsi"
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
+#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
        model = "Insignal Origen evaluation board based on Exynos4412";
 };
 
 &mfc {
-       samsung,mfc-r = <0x43000000 0x800000>;
-       samsung,mfc-l = <0x51000000 0x800000>;
+       memory-region = <&mfc_left>, <&mfc_right>;
        status = "okay";
 };
 
index a51069f..9b6d561 100644 (file)
@@ -14,6 +14,7 @@
 
 /dts-v1/;
 #include "exynos4412.dtsi"
+#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
        model = "Samsung SMDK evaluation board based on Exynos4412";
 };
 
 &mfc {
-       samsung,mfc-r = <0x43000000 0x800000>;
-       samsung,mfc-l = <0x51000000 0x800000>;
+       memory-region = <&mfc_left>, <&mfc_right>;
        status = "okay";
 };
 
index 85dad29..39940f4 100644 (file)
@@ -14,6 +14,7 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/input/input.h>
 #include "exynos5250.dtsi"
+#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
        model = "Insignal Arndale evaluation board based on EXYNOS5250";
 };
 
 &mfc {
-       samsung,mfc-r = <0x43000000 0x800000>;
-       samsung,mfc-l = <0x51000000 0x800000>;
+       memory-region = <&mfc_left>, <&mfc_right>;
 };
 
 &mmc_0 {
index b7992b1..9fac874 100644 (file)
@@ -13,6 +13,7 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include "exynos5250.dtsi"
+#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
        model = "SAMSUNG SMDK5250 board based on EXYNOS5250";
 };
 
 &mfc {
-       samsung,mfc-r = <0x43000000 0x800000>;
-       samsung,mfc-l = <0x51000000 0x800000>;
+       memory-region = <&mfc_left>, <&mfc_right>;
 };
 
 &mmc_0 {
index ac291f5..784130b 100644 (file)
@@ -14,6 +14,7 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/input/input.h>
 #include "exynos5250.dtsi"
+#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
        model = "Google Spring";
 };
 
 &mfc {
-       samsung,mfc-r = <0x43000000 0x800000>;
-       samsung,mfc-l = <0x51000000 0x800000>;
+       memory-region = <&mfc_left>, <&mfc_right>;
 };
 
 &mmc_0 {
index 60bc861..b8b5f3a 100644 (file)
@@ -16,6 +16,7 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/clock/samsung,s2mps11.h>
+#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
        model = "Insignal Arndale Octa evaluation board based on EXYNOS5420";
 };
 
 &mfc {
-       samsung,mfc-r = <0x43000000 0x800000>;
-       samsung,mfc-l = <0x51000000 0x800000>;
+       memory-region = <&mfc_left>, <&mfc_right>;
 };
 
 &mmc_0 {
index f9d2e4f..d530b4f 100644 (file)
@@ -16,6 +16,7 @@
 #include <dt-bindings/regulator/maxim,max77802.h>
 #include "exynos5420.dtsi"
 #include "exynos5420-cpus.dtsi"
+#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
        model = "Google Peach Pit Rev 6+";
 };
 
 &mfc {
-       samsung,mfc-r = <0x43000000 0x800000>;
-       samsung,mfc-l = <0x51000000 0x800000>;
+       memory-region = <&mfc_left>, <&mfc_right>;
 };
 
 &mmc_0 {
index 2e748d1..5206f41 100644 (file)
@@ -13,6 +13,7 @@
 #include "exynos5420.dtsi"
 #include "exynos5420-cpus.dtsi"
 #include <dt-bindings/gpio/gpio.h>
+#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
        model = "Samsung SMDK5420 board based on EXYNOS5420";
 };
 
 &mfc {
-       samsung,mfc-r = <0x43000000 0x800000>;
-       samsung,mfc-l = <0x51000000 0x800000>;
+       memory-region = <&mfc_left>, <&mfc_right>;
 };
 
 &mmc_0 {
index 2a4e10b..7c2335f 100644 (file)
@@ -17,6 +17,7 @@
 #include "exynos5800.dtsi"
 #include "exynos5422-cpus.dtsi"
 #include "exynos5422-cpu-thermal.dtsi"
+#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
        memory {
 };
 
 &mfc {
-       samsung,mfc-r = <0x43000000 0x800000>;
-       samsung,mfc-l = <0x51000000 0x800000>;
+       memory-region = <&mfc_left>, <&mfc_right>;
 };
 
 &mmc_0 {
index 62ceb89..1f73596 100644 (file)
@@ -16,6 +16,7 @@
 #include <dt-bindings/regulator/maxim,max77802.h>
 #include "exynos5800.dtsi"
 #include "exynos5420-cpus.dtsi"
+#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
        model = "Google Peach Pi Rev 10+";
 };
 
 &mfc {
-       samsung,mfc-r = <0x43000000 0x800000>;
-       samsung,mfc-l = <0x51000000 0x800000>;
+       memory-region = <&mfc_left>, <&mfc_right>;
 };
 
 &mmc_0 {
index e65aa7d..58b334f 100644 (file)
@@ -19,6 +19,7 @@ menuconfig ARCH_EXYNOS
        select EXYNOS_THERMAL
        select EXYNOS_PMU
        select EXYNOS_SROM
+       select EXYNOS_PM_DOMAINS if PM_GENERIC_DOMAINS
        select HAVE_ARM_SCU if SMP
        select HAVE_S3C2410_I2C if I2C
        select HAVE_S3C2410_WATCHDOG if WATCHDOG
index 34d29df..9ea6c54 100644 (file)
@@ -13,7 +13,6 @@ obj-$(CONFIG_ARCH_EXYNOS)     += exynos.o exynos-smc.o firmware.o
 
 obj-$(CONFIG_EXYNOS_CPU_SUSPEND) += pm.o sleep.o
 obj-$(CONFIG_PM_SLEEP)         += suspend.o
-obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
 
 obj-$(CONFIG_SMP)              += platsmp.o headsmp.o
 
@@ -23,5 +22,3 @@ AFLAGS_sleep.o                        :=-Wa,-march=armv7-a$(plus_sec)
 
 obj-$(CONFIG_EXYNOS5420_MCPM)  += mcpm-exynos.o
 CFLAGS_mcpm-exynos.o           += -march=armv7-a
-
-obj-$(CONFIG_S5P_DEV_MFC)      += s5p-dev-mfc.o
index 52ccf24..a8620c6 100644 (file)
@@ -27,7 +27,6 @@
 #include <mach/map.h>
 
 #include "common.h"
-#include "mfc.h"
 
 static struct map_desc exynos4_iodesc[] __initdata = {
        {
@@ -237,23 +236,6 @@ static char const *const exynos_dt_compat[] __initconst = {
        NULL
 };
 
-static void __init exynos_reserve(void)
-{
-#ifdef CONFIG_S5P_DEV_MFC
-       int i;
-       char *mfc_mem[] = {
-               "samsung,mfc-v5",
-               "samsung,mfc-v6",
-               "samsung,mfc-v7",
-               "samsung,mfc-v8",
-       };
-
-       for (i = 0; i < ARRAY_SIZE(mfc_mem); i++)
-               if (of_scan_flat_dt(s5p_fdt_alloc_mfc_mem, mfc_mem[i]))
-                       break;
-#endif
-}
-
 static void __init exynos_dt_fixup(void)
 {
        /*
@@ -275,6 +257,5 @@ DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)")
        .init_machine   = exynos_dt_machine_init,
        .init_late      = exynos_init_late,
        .dt_compat      = exynos_dt_compat,
-       .reserve        = exynos_reserve,
        .dt_fixup       = exynos_dt_fixup,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mfc.h b/arch/arm/mach-exynos/mfc.h
deleted file mode 100644 (file)
index dec93cd..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) 2013 Samsung Electronics 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.
- */
-
-#ifndef __MACH_EXYNOS_MFC_H
-#define __MACH_EXYNOS_MFC_H __FILE__
-
-int __init s5p_fdt_alloc_mfc_mem(unsigned long node, const char *uname,
-                               int depth, void *data);
-
-#endif /* __MACH_EXYNOS_MFC_H */
diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c
deleted file mode 100644 (file)
index 875a2ba..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Exynos Generic power domain support.
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Implementation of Exynos specific power domain control which is used in
- * conjunction with runtime-pm. Support for both device-tree and non-device-tree
- * based power domain support is included.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/io.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/pm_domain.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/sched.h>
-
-#define INT_LOCAL_PWR_EN       0x7
-#define MAX_CLK_PER_DOMAIN     4
-
-/*
- * Exynos specific wrapper around the generic power domain
- */
-struct exynos_pm_domain {
-       void __iomem *base;
-       char const *name;
-       bool is_off;
-       struct generic_pm_domain pd;
-       struct clk *oscclk;
-       struct clk *clk[MAX_CLK_PER_DOMAIN];
-       struct clk *pclk[MAX_CLK_PER_DOMAIN];
-       struct clk *asb_clk[MAX_CLK_PER_DOMAIN];
-};
-
-static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
-{
-       struct exynos_pm_domain *pd;
-       void __iomem *base;
-       u32 timeout, pwr;
-       char *op;
-       int i;
-
-       pd = container_of(domain, struct exynos_pm_domain, pd);
-       base = pd->base;
-
-       for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
-               if (IS_ERR(pd->asb_clk[i]))
-                       break;
-               clk_prepare_enable(pd->asb_clk[i]);
-       }
-
-       /* Set oscclk before powering off a domain*/
-       if (!power_on) {
-               for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
-                       if (IS_ERR(pd->clk[i]))
-                               break;
-                       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);
-               }
-       }
-
-       pwr = power_on ? INT_LOCAL_PWR_EN : 0;
-       __raw_writel(pwr, base);
-
-       /* Wait max 1ms */
-       timeout = 10;
-
-       while ((__raw_readl(base + 0x4) & INT_LOCAL_PWR_EN) != pwr) {
-               if (!timeout) {
-                       op = (power_on) ? "enable" : "disable";
-                       pr_err("Power domain %s %s failed\n", domain->name, op);
-                       return -ETIMEDOUT;
-               }
-               timeout--;
-               cpu_relax();
-               usleep_range(80, 100);
-       }
-
-       /* Restore clocks after powering on a domain*/
-       if (power_on) {
-               for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
-                       if (IS_ERR(pd->clk[i]))
-                               break;
-
-                       if (IS_ERR(pd->pclk[i]))
-                               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);
-               }
-       }
-
-       for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
-               if (IS_ERR(pd->asb_clk[i]))
-                       break;
-               clk_disable_unprepare(pd->asb_clk[i]);
-       }
-
-       return 0;
-}
-
-static int exynos_pd_power_on(struct generic_pm_domain *domain)
-{
-       return exynos_pd_power(domain, true);
-}
-
-static int exynos_pd_power_off(struct generic_pm_domain *domain)
-{
-       return exynos_pd_power(domain, false);
-}
-
-static __init int exynos4_pm_init_power_domain(void)
-{
-       struct device_node *np;
-
-       for_each_compatible_node(np, NULL, "samsung,exynos4210-pd") {
-               struct exynos_pm_domain *pd;
-               int on, i;
-
-               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);
-               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__);
-                       kfree_const(pd->pd.name);
-                       kfree(pd);
-                       continue;
-               }
-
-               pd->pd.power_off = exynos_pd_power_off;
-               pd->pd.power_on = exynos_pd_power_on;
-
-               for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
-                       char clk_name[8];
-
-                       snprintf(clk_name, sizeof(clk_name), "asb%d", i);
-                       pd->asb_clk[i] = of_clk_get_by_name(np, clk_name);
-                       if (IS_ERR(pd->asb_clk[i]))
-                               break;
-               }
-
-               pd->oscclk = of_clk_get_by_name(np, "oscclk");
-               if (IS_ERR(pd->oscclk))
-                       goto no_clk;
-
-               for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
-                       char clk_name[8];
-
-                       snprintf(clk_name, sizeof(clk_name), "clk%d", i);
-                       pd->clk[i] = of_clk_get_by_name(np, clk_name);
-                       if (IS_ERR(pd->clk[i]))
-                               break;
-                       /*
-                        * Skip setting parent on first power up.
-                        * The parent at this time may not be useful at all.
-                        */
-                       pd->pclk[i] = ERR_PTR(-EINVAL);
-               }
-
-               if (IS_ERR(pd->clk[0]))
-                       clk_put(pd->oscclk);
-
-no_clk:
-               on = __raw_readl(pd->base + 0x4) & INT_LOCAL_PWR_EN;
-
-               pm_genpd_init(&pd->pd, NULL, !on);
-               of_genpd_add_provider_simple(np, &pd->pd);
-       }
-
-       /* Assign the child power domains to their parents */
-       for_each_compatible_node(np, NULL, "samsung,exynos4210-pd") {
-               struct generic_pm_domain *child_domain, *parent_domain;
-               struct of_phandle_args args;
-
-               args.np = np;
-               args.args_count = 0;
-               child_domain = of_genpd_get_from_provider(&args);
-               if (IS_ERR(child_domain))
-                       continue;
-
-               if (of_parse_phandle_with_args(np, "power-domains",
-                                        "#power-domain-cells", 0, &args) != 0)
-                       continue;
-
-               parent_domain = of_genpd_get_from_provider(&args);
-               if (IS_ERR(parent_domain))
-                       continue;
-
-               if (pm_genpd_add_subdomain(parent_domain, child_domain))
-                       pr_warn("%s failed to add subdomain: %s\n",
-                               parent_domain->name, child_domain->name);
-               else
-                       pr_info("%s has as child subdomain: %s.\n",
-                               parent_domain->name, child_domain->name);
-       }
-
-       return 0;
-}
-core_initcall(exynos4_pm_init_power_domain);
diff --git a/arch/arm/mach-exynos/s5p-dev-mfc.c b/arch/arm/mach-exynos/s5p-dev-mfc.c
deleted file mode 100644 (file)
index 8ef1f3e..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2010-2011 Samsung Electronics Co.Ltd
- *
- * Base S5P MFC resource and device definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/memblock.h>
-#include <linux/ioport.h>
-#include <linux/of_fdt.h>
-#include <linux/of.h>
-
-static struct platform_device s5p_device_mfc_l;
-static struct platform_device s5p_device_mfc_r;
-
-struct s5p_mfc_dt_meminfo {
-       unsigned long   loff;
-       unsigned long   lsize;
-       unsigned long   roff;
-       unsigned long   rsize;
-       char            *compatible;
-};
-
-struct s5p_mfc_reserved_mem {
-       phys_addr_t     base;
-       unsigned long   size;
-       struct device   *dev;
-};
-
-static struct s5p_mfc_reserved_mem s5p_mfc_mem[2] __initdata;
-
-
-static void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
-                               phys_addr_t lbase, unsigned int lsize)
-{
-       int i;
-
-       s5p_mfc_mem[0].dev = &s5p_device_mfc_r.dev;
-       s5p_mfc_mem[0].base = rbase;
-       s5p_mfc_mem[0].size = rsize;
-
-       s5p_mfc_mem[1].dev = &s5p_device_mfc_l.dev;
-       s5p_mfc_mem[1].base = lbase;
-       s5p_mfc_mem[1].size = lsize;
-
-       for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) {
-               struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i];
-               if (memblock_remove(area->base, area->size)) {
-                       printk(KERN_ERR "Failed to reserve memory for MFC device (%ld bytes at 0x%08lx)\n",
-                              area->size, (unsigned long) area->base);
-                       area->base = 0;
-               }
-       }
-}
-
-int __init s5p_fdt_alloc_mfc_mem(unsigned long node, const char *uname,
-                               int depth, void *data)
-{
-       const __be32 *prop;
-       int len;
-       struct s5p_mfc_dt_meminfo mfc_mem;
-
-       if (!data)
-               return 0;
-
-       if (!of_flat_dt_is_compatible(node, data))
-               return 0;
-
-       prop = of_get_flat_dt_prop(node, "samsung,mfc-l", &len);
-       if (!prop || (len != 2 * sizeof(unsigned long)))
-               return 0;
-
-       mfc_mem.loff = be32_to_cpu(prop[0]);
-       mfc_mem.lsize = be32_to_cpu(prop[1]);
-
-       prop = of_get_flat_dt_prop(node, "samsung,mfc-r", &len);
-       if (!prop || (len != 2 * sizeof(unsigned long)))
-               return 0;
-
-       mfc_mem.roff = be32_to_cpu(prop[0]);
-       mfc_mem.rsize = be32_to_cpu(prop[1]);
-
-       s5p_mfc_reserve_mem(mfc_mem.roff, mfc_mem.rsize,
-                       mfc_mem.loff, mfc_mem.lsize);
-
-       return 1;
-}
index c049736..c9d2009 100644 (file)
@@ -1124,6 +1124,7 @@ static int gsc_probe(struct platform_device *pdev)
                goto err_m2m;
 
        /* Initialize continious memory allocator */
+       vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32));
        gsc->alloc_ctx = vb2_dma_contig_init_ctx(dev);
        if (IS_ERR(gsc->alloc_ctx)) {
                ret = PTR_ERR(gsc->alloc_ctx);
@@ -1153,6 +1154,7 @@ static int gsc_remove(struct platform_device *pdev)
        v4l2_device_unregister(&gsc->v4l2_dev);
 
        vb2_dma_contig_cleanup_ctx(gsc->alloc_ctx);
+       vb2_dma_contig_clear_max_seg_size(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
        gsc_clk_put(gsc);
 
index b1c1cea..368f44f 100644 (file)
@@ -1019,6 +1019,7 @@ static int fimc_probe(struct platform_device *pdev)
        }
 
        /* Initialize contiguous memory allocator */
+       vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32));
        fimc->alloc_ctx = vb2_dma_contig_init_ctx(dev);
        if (IS_ERR(fimc->alloc_ctx)) {
                ret = PTR_ERR(fimc->alloc_ctx);
@@ -1124,6 +1125,7 @@ static int fimc_remove(struct platform_device *pdev)
 
        fimc_unregister_capture_subdev(fimc);
        vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx);
+       vb2_dma_contig_clear_max_seg_size(&pdev->dev);
 
        clk_disable(fimc->clock[CLK_BUS]);
        fimc_clk_put(fimc);
index 979c388..bd98b56 100644 (file)
@@ -847,6 +847,7 @@ static int fimc_is_probe(struct platform_device *pdev)
        if (ret < 0)
                goto err_pm;
 
+       vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32));
        is->alloc_ctx = vb2_dma_contig_init_ctx(dev);
        if (IS_ERR(is->alloc_ctx)) {
                ret = PTR_ERR(is->alloc_ctx);
@@ -940,6 +941,7 @@ static int fimc_is_remove(struct platform_device *pdev)
        free_irq(is->irq, is);
        fimc_is_unregister_subdevs(is);
        vb2_dma_contig_cleanup_ctx(is->alloc_ctx);
+       vb2_dma_contig_clear_max_seg_size(dev);
        fimc_is_put_clocks(is);
        fimc_is_debugfs_remove(is);
        release_firmware(is->fw.f_w);
index dc1b929..27cb620 100644 (file)
@@ -1551,6 +1551,7 @@ static int fimc_lite_probe(struct platform_device *pdev)
                        goto err_sd;
        }
 
+       vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32));
        fimc->alloc_ctx = vb2_dma_contig_init_ctx(dev);
        if (IS_ERR(fimc->alloc_ctx)) {
                ret = PTR_ERR(fimc->alloc_ctx);
@@ -1652,6 +1653,7 @@ static int fimc_lite_remove(struct platform_device *pdev)
        pm_runtime_set_suspended(dev);
        fimc_lite_unregister_capture_subdev(fimc);
        vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx);
+       vb2_dma_contig_clear_max_seg_size(dev);
        fimc_lite_clk_put(fimc);
 
        dev_info(dev, "Driver unloaded\n");
index 612d1ea..d3e3469 100644 (file)
@@ -681,6 +681,7 @@ static int g2d_probe(struct platform_device *pdev)
                goto put_clk_gate;
        }
 
+       vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
        dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
        if (IS_ERR(dev->alloc_ctx)) {
                ret = PTR_ERR(dev->alloc_ctx);
@@ -757,6 +758,7 @@ static int g2d_remove(struct platform_device *pdev)
        video_unregister_device(dev->vfd);
        v4l2_device_unregister(&dev->v4l2_dev);
        vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
+       vb2_dma_contig_clear_max_seg_size(&pdev->dev);
        clk_unprepare(dev->gate);
        clk_put(dev->gate);
        clk_unprepare(dev->clk);
index caa19b4..17bc940 100644 (file)
@@ -2843,6 +2843,7 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
                goto device_register_rollback;
        }
 
+       vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
        jpeg->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
        if (IS_ERR(jpeg->alloc_ctx)) {
                v4l2_err(&jpeg->v4l2_dev, "Failed to init memory allocator\n");
@@ -2942,6 +2943,7 @@ static int s5p_jpeg_remove(struct platform_device *pdev)
        video_unregister_device(jpeg->vfd_decoder);
        video_unregister_device(jpeg->vfd_encoder);
        vb2_dma_contig_cleanup_ctx(jpeg->alloc_ctx);
+       vb2_dma_contig_clear_max_seg_size(&pdev->dev);
        v4l2_m2m_release(jpeg->m2m_dev);
        v4l2_device_unregister(&jpeg->v4l2_dev);
 
index b16466f..6ee620e 100644 (file)
@@ -22,6 +22,7 @@
 #include <media/v4l2-event.h>
 #include <linux/workqueue.h>
 #include <linux/of.h>
+#include <linux/of_reserved_mem.h>
 #include <media/videobuf2-v4l2.h>
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_ctrl.h"
@@ -29,6 +30,7 @@
 #include "s5p_mfc_dec.h"
 #include "s5p_mfc_enc.h"
 #include "s5p_mfc_intr.h"
+#include "s5p_mfc_iommu.h"
 #include "s5p_mfc_opr.h"
 #include "s5p_mfc_cmd.h"
 #include "s5p_mfc_pm.h"
@@ -1043,55 +1045,94 @@ static const struct v4l2_file_operations s5p_mfc_fops = {
        .mmap = s5p_mfc_mmap,
 };
 
-static int match_child(struct device *dev, void *data)
+/* DMA memory related helper functions */
+static void s5p_mfc_memdev_release(struct device *dev)
 {
-       if (!dev_name(dev))
-               return 0;
-       return !strcmp(dev_name(dev), (char *)data);
+       of_reserved_mem_device_release(dev);
 }
 
-static void *mfc_get_drv_data(struct platform_device *pdev);
-
-static int s5p_mfc_alloc_memdevs(struct s5p_mfc_dev *dev)
+static struct device *s5p_mfc_alloc_memdev(struct device *dev,
+                                          const char *name, unsigned int idx)
 {
-       unsigned int mem_info[2] = { };
+       struct device *child;
+       int ret;
 
-       dev->mem_dev_l = devm_kzalloc(&dev->plat_dev->dev,
-                       sizeof(struct device), GFP_KERNEL);
-       if (!dev->mem_dev_l) {
-               mfc_err("Not enough memory\n");
-               return -ENOMEM;
-       }
-       device_initialize(dev->mem_dev_l);
-       of_property_read_u32_array(dev->plat_dev->dev.of_node,
-                       "samsung,mfc-l", mem_info, 2);
-       if (dma_declare_coherent_memory(dev->mem_dev_l, mem_info[0],
-                               mem_info[0], mem_info[1],
-                               DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0) {
-               mfc_err("Failed to declare coherent memory for\n"
-               "MFC device\n");
-               return -ENOMEM;
+       child = devm_kzalloc(dev, sizeof(struct device), GFP_KERNEL);
+       if (!child)
+               return NULL;
+
+       device_initialize(child);
+       dev_set_name(child, "%s:%s", dev_name(dev), name);
+       child->parent = dev;
+       child->bus = dev->bus;
+       child->coherent_dma_mask = dev->coherent_dma_mask;
+       child->dma_mask = dev->dma_mask;
+       child->release = s5p_mfc_memdev_release;
+
+       if (device_add(child) == 0) {
+               ret = of_reserved_mem_device_init_by_idx(child, dev->of_node,
+                                                        idx);
+               if (ret == 0)
+                       return child;
        }
 
-       dev->mem_dev_r = devm_kzalloc(&dev->plat_dev->dev,
-                       sizeof(struct device), GFP_KERNEL);
-       if (!dev->mem_dev_r) {
-               mfc_err("Not enough memory\n");
-               return -ENOMEM;
+       put_device(child);
+       return NULL;
+}
+
+static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev)
+{
+       struct device *dev = &mfc_dev->plat_dev->dev;
+
+       /*
+        * When IOMMU is available, we cannot use the default configuration,
+        * because of MFC firmware requirements: address space limited to
+        * 256M and non-zero default start address.
+        * This is still simplified, not optimal configuration, but for now
+        * IOMMU core doesn't allow to configure device's IOMMUs channel
+        * separately.
+        */
+       if (exynos_is_iommu_available(dev)) {
+               int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE,
+                                                S5P_MFC_IOMMU_DMA_SIZE);
+               if (ret == 0)
+                       mfc_dev->mem_dev_l = mfc_dev->mem_dev_r = dev;
+               return ret;
        }
-       device_initialize(dev->mem_dev_r);
-       of_property_read_u32_array(dev->plat_dev->dev.of_node,
-                       "samsung,mfc-r", mem_info, 2);
-       if (dma_declare_coherent_memory(dev->mem_dev_r, mem_info[0],
-                               mem_info[0], mem_info[1],
-                               DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0) {
-               pr_err("Failed to declare coherent memory for\n"
-               "MFC device\n");
-               return -ENOMEM;
+
+       /*
+        * Create and initialize virtual devices for accessing
+        * reserved memory regions.
+        */
+       mfc_dev->mem_dev_l = s5p_mfc_alloc_memdev(dev, "left",
+                                                 MFC_BANK1_ALLOC_CTX);
+       if (!mfc_dev->mem_dev_l)
+               return -ENODEV;
+       mfc_dev->mem_dev_r = s5p_mfc_alloc_memdev(dev, "right",
+                                                 MFC_BANK2_ALLOC_CTX);
+       if (!mfc_dev->mem_dev_r) {
+               device_unregister(mfc_dev->mem_dev_l);
+               return -ENODEV;
        }
+
        return 0;
 }
 
+static void s5p_mfc_unconfigure_dma_memory(struct s5p_mfc_dev *mfc_dev)
+{
+       struct device *dev = &mfc_dev->plat_dev->dev;
+
+       if (exynos_is_iommu_available(dev)) {
+               exynos_unconfigure_iommu(dev);
+               return;
+       }
+
+       device_unregister(mfc_dev->mem_dev_l);
+       device_unregister(mfc_dev->mem_dev_r);
+}
+
+static void *mfc_get_drv_data(struct platform_device *pdev);
+
 /* MFC probe function */
 static int s5p_mfc_probe(struct platform_device *pdev)
 {
@@ -1117,12 +1158,6 @@ static int s5p_mfc_probe(struct platform_device *pdev)
 
        dev->variant = mfc_get_drv_data(pdev);
 
-       ret = s5p_mfc_init_pm(dev);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "failed to get mfc clock source\n");
-               return ret;
-       }
-
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
        dev->regs_base = devm_ioremap_resource(&pdev->dev, res);
@@ -1143,32 +1178,25 @@ static int s5p_mfc_probe(struct platform_device *pdev)
                goto err_res;
        }
 
-       if (pdev->dev.of_node) {
-               ret = s5p_mfc_alloc_memdevs(dev);
-               if (ret < 0)
-                       goto err_res;
-       } else {
-               dev->mem_dev_l = device_find_child(&dev->plat_dev->dev,
-                               "s5p-mfc-l", match_child);
-               if (!dev->mem_dev_l) {
-                       mfc_err("Mem child (L) device get failed\n");
-                       ret = -ENODEV;
-                       goto err_res;
-               }
-               dev->mem_dev_r = device_find_child(&dev->plat_dev->dev,
-                               "s5p-mfc-r", match_child);
-               if (!dev->mem_dev_r) {
-                       mfc_err("Mem child (R) device get failed\n");
-                       ret = -ENODEV;
-                       goto err_res;
-               }
+       ret = s5p_mfc_configure_dma_memory(dev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to configure DMA memory\n");
+               return ret;
        }
 
+       ret = s5p_mfc_init_pm(dev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to get mfc clock source\n");
+               return ret;
+       }
+
+       vb2_dma_contig_set_max_seg_size(dev->mem_dev_l, DMA_BIT_MASK(32));
        dev->alloc_ctx[0] = vb2_dma_contig_init_ctx(dev->mem_dev_l);
        if (IS_ERR(dev->alloc_ctx[0])) {
                ret = PTR_ERR(dev->alloc_ctx[0]);
                goto err_res;
        }
+       vb2_dma_contig_set_max_seg_size(dev->mem_dev_r, DMA_BIT_MASK(32));
        dev->alloc_ctx[1] = vb2_dma_contig_init_ctx(dev->mem_dev_r);
        if (IS_ERR(dev->alloc_ctx[1])) {
                ret = PTR_ERR(dev->alloc_ctx[1]);
@@ -1201,14 +1229,6 @@ static int s5p_mfc_probe(struct platform_device *pdev)
        vfd->vfl_dir    = VFL_DIR_M2M;
        snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_DEC_NAME);
        dev->vfd_dec    = vfd;
-       ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
-       if (ret) {
-               v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
-               video_device_release(vfd);
-               goto err_dec_reg;
-       }
-       v4l2_info(&dev->v4l2_dev,
-                 "decoder registered as /dev/video%d\n", vfd->num);
        video_set_drvdata(vfd, dev);
 
        /* encoder */
@@ -1226,14 +1246,6 @@ static int s5p_mfc_probe(struct platform_device *pdev)
        vfd->vfl_dir    = VFL_DIR_M2M;
        snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_ENC_NAME);
        dev->vfd_enc    = vfd;
-       ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
-       if (ret) {
-               v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
-               video_device_release(vfd);
-               goto err_enc_reg;
-       }
-       v4l2_info(&dev->v4l2_dev,
-                 "encoder registered as /dev/video%d\n", vfd->num);
        video_set_drvdata(vfd, dev);
        platform_set_drvdata(pdev, dev);
 
@@ -1250,15 +1262,34 @@ static int s5p_mfc_probe(struct platform_device *pdev)
        s5p_mfc_init_hw_cmds(dev);
        s5p_mfc_init_regs(dev);
 
+       /* Register decoder and encoder */
+       ret = video_register_device(dev->vfd_dec, VFL_TYPE_GRABBER, 0);
+       if (ret) {
+               v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
+               video_device_release(dev->vfd_dec);
+               goto err_dec_reg;
+       }
+       v4l2_info(&dev->v4l2_dev,
+                 "decoder registered as /dev/video%d\n", dev->vfd_dec->num);
+
+       ret = video_register_device(dev->vfd_enc, VFL_TYPE_GRABBER, 0);
+       if (ret) {
+               v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
+               video_device_release(dev->vfd_enc);
+               goto err_enc_reg;
+       }
+       v4l2_info(&dev->v4l2_dev,
+                 "encoder registered as /dev/video%d\n", dev->vfd_enc->num);
+
        pr_debug("%s--\n", __func__);
        return 0;
 
 /* Deinit MFC if probe had failed */
 err_enc_reg:
-       video_device_release(dev->vfd_enc);
-err_enc_alloc:
        video_unregister_device(dev->vfd_dec);
 err_dec_reg:
+       video_device_release(dev->vfd_enc);
+err_enc_alloc:
        video_device_release(dev->vfd_dec);
 err_dec_alloc:
        v4l2_device_unregister(&dev->v4l2_dev);
@@ -1293,10 +1324,9 @@ static int s5p_mfc_remove(struct platform_device *pdev)
        s5p_mfc_release_firmware(dev);
        vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]);
        vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]);
-       if (pdev->dev.of_node) {
-               put_device(dev->mem_dev_l);
-               put_device(dev->mem_dev_r);
-       }
+       s5p_mfc_unconfigure_dma_memory(dev);
+       vb2_dma_contig_clear_max_seg_size(dev->mem_dev_l);
+       vb2_dma_contig_clear_max_seg_size(dev->mem_dev_r);
 
        s5p_mfc_final_pm(dev);
        return 0;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h b/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h
new file mode 100644 (file)
index 0000000..5d1d1c2
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co.Ltd
+ * Authors: Marek Szyprowski <m.szyprowski@samsung.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef S5P_MFC_IOMMU_H_
+#define S5P_MFC_IOMMU_H_
+
+#define S5P_MFC_IOMMU_DMA_BASE 0x20000000lu
+#define S5P_MFC_IOMMU_DMA_SIZE SZ_256M
+
+#ifdef CONFIG_EXYNOS_IOMMU
+
+#include <asm/dma-iommu.h>
+
+static inline bool exynos_is_iommu_available(struct device *dev)
+{
+       return dev->archdata.iommu != NULL;
+}
+
+static inline void exynos_unconfigure_iommu(struct device *dev)
+{
+       struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+
+       arm_iommu_detach_device(dev);
+       arm_iommu_release_mapping(mapping);
+}
+
+static inline int exynos_configure_iommu(struct device *dev,
+                                        unsigned int base, unsigned int size)
+{
+       struct dma_iommu_mapping *mapping = NULL;
+       int ret;
+
+       /* Disable the default mapping created by device core */
+       if (to_dma_iommu_mapping(dev))
+               exynos_unconfigure_iommu(dev);
+
+       mapping = arm_iommu_create_mapping(dev->bus, base, size);
+       if (IS_ERR(mapping)) {
+               pr_warn("Failed to create IOMMU mapping for device %s\n",
+                       dev_name(dev));
+               return PTR_ERR(mapping);
+       }
+
+       ret = arm_iommu_attach_device(dev, mapping);
+       if (ret) {
+               pr_warn("Failed to attached device %s to IOMMU_mapping\n",
+                               dev_name(dev));
+               arm_iommu_release_mapping(mapping);
+               return ret;
+       }
+
+       return 0;
+}
+
+#else
+
+static inline bool exynos_is_iommu_available(struct device *dev)
+{
+       return false;
+}
+
+static inline int exynos_configure_iommu(struct device *dev,
+                                        unsigned int base, unsigned int size)
+{
+       return -ENOSYS;
+}
+
+static inline void exynos_unconfigure_iommu(struct device *dev) { }
+
+#endif
+
+#endif /* S5P_MFC_IOMMU_H_ */
index 7ab5578..123d271 100644 (file)
@@ -80,6 +80,7 @@ int mxr_acquire_video(struct mxr_device *mdev,
                goto fail;
        }
 
+       vb2_dma_contig_set_max_seg_size(mdev->dev, DMA_BIT_MASK(32));
        mdev->alloc_ctx = vb2_dma_contig_init_ctx(mdev->dev);
        if (IS_ERR(mdev->alloc_ctx)) {
                mxr_err(mdev, "could not acquire vb2 allocator\n");
@@ -152,6 +153,7 @@ void mxr_release_video(struct mxr_device *mdev)
                kfree(mdev->output[i]);
 
        vb2_dma_contig_cleanup_ctx(mdev->alloc_ctx);
+       vb2_dma_contig_clear_max_seg_size(mdev->dev);
        v4l2_device_unregister(&mdev->v4l2_dev);
 }
 
index 5361197..e3e47ac 100644 (file)
@@ -753,6 +753,59 @@ void vb2_dma_contig_cleanup_ctx(void *alloc_ctx)
 }
 EXPORT_SYMBOL_GPL(vb2_dma_contig_cleanup_ctx);
 
+/**
+ * vb2_dma_contig_set_max_seg_size() - configure DMA max segment size
+ * @dev:       device for configuring DMA parameters
+ * @size:      size of DMA max segment size to set
+ *
+ * To allow mapping the scatter-list into a single chunk in the DMA
+ * address space, the device is required to have the DMA max segment
+ * size parameter set to a value larger than the buffer size. Otherwise,
+ * the DMA-mapping subsystem will split the mapping into max segment
+ * size chunks. This function sets the DMA max segment size
+ * parameter to let DMA-mapping map a buffer as a single chunk in DMA
+ * address space.
+ * This code assumes that the DMA-mapping subsystem will merge all
+ * scatterlist segments if this is really possible (for example when
+ * an IOMMU is available and enabled).
+ * Ideally, this parameter should be set by the generic bus code, but it
+ * is left with the default 64KiB value due to historical litmiations in
+ * other subsystems (like limited USB host drivers) and there no good
+ * place to set it to the proper value.
+ * This function should be called from the drivers, which are known to
+ * operate on platforms with IOMMU and provide access to shared buffers
+ * (either USERPTR or DMABUF). This should be done before initializing
+ * videobuf2 queue.
+ */
+int vb2_dma_contig_set_max_seg_size(struct device *dev, unsigned int size)
+{
+       if (!dev->dma_parms) {
+               dev->dma_parms = kzalloc(sizeof(dev->dma_parms), GFP_KERNEL);
+               if (!dev->dma_parms)
+                       return -ENOMEM;
+       }
+       if (dma_get_max_seg_size(dev) < size)
+               return dma_set_max_seg_size(dev, size);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_dma_contig_set_max_seg_size);
+
+/*
+ * vb2_dma_contig_clear_max_seg_size() - release resources for DMA parameters
+ * @dev:       device for configuring DMA parameters
+ *
+ * This function releases resources allocated to configure DMA parameters
+ * (see vb2_dma_contig_set_max_seg_size() function). It should be called from
+ * device drivers on driver remove.
+ */
+void vb2_dma_contig_clear_max_seg_size(struct device *dev)
+{
+       kfree(dev->dma_parms);
+       dev->dma_parms = NULL;
+}
+EXPORT_SYMBOL_GPL(vb2_dma_contig_clear_max_seg_size);
+
 MODULE_DESCRIPTION("DMA-contig memory handling routines for videobuf2");
 MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>");
 MODULE_LICENSE("GPL");
index 81ddb17..1337123 100644 (file)
@@ -25,6 +25,17 @@ config ATMEL_SDRAMC
          Starting with the at91sam9g45, this controller supports SDR, DDR and
          LP-DDR memories.
 
+config ATMEL_EBI
+       bool "Atmel EBI driver"
+       default y
+       depends on ARCH_AT91 && OF
+       select MFD_SYSCON
+       help
+         Driver for Atmel EBI controller.
+         Used to configure the EBI (external bus interface) when the device-
+         tree is used. This bus supports NANDs, external ethernet controller,
+         SRAMs, ATA devices, etc.
+
 config TI_AEMIF
        tristate "Texas Instruments AEMIF driver"
        depends on (ARCH_DAVINCI || ARCH_KEYSTONE) && OF
index cb0b7a1..b20ae38 100644 (file)
@@ -7,6 +7,7 @@ obj-$(CONFIG_OF)                += of_memory.o
 endif
 obj-$(CONFIG_ARM_PL172_MPMC)   += pl172.o
 obj-$(CONFIG_ATMEL_SDRAMC)     += atmel-sdramc.o
+obj-$(CONFIG_ATMEL_EBI)                += atmel-ebi.o
 obj-$(CONFIG_TI_AEMIF)         += ti-aemif.o
 obj-$(CONFIG_TI_EMIF)          += emif.o
 obj-$(CONFIG_OMAP_GPMC)                += omap-gpmc.o
diff --git a/drivers/memory/atmel-ebi.c b/drivers/memory/atmel-ebi.c
new file mode 100644 (file)
index 0000000..f87ad6f
--- /dev/null
@@ -0,0 +1,766 @@
+/*
+ * EBI driver for Atmel chips
+ * inspired by the fsl weim bus driver
+ *
+ * Copyright (C) 2013 Jean-Jacques Hiblot <jjhiblot@traphandler.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/atmel-matrix.h>
+#include <linux/mfd/syscon/atmel-smc.h>
+#include <linux/init.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+
+struct at91sam9_smc_timings {
+       u32 ncs_rd_setup_ns;
+       u32 nrd_setup_ns;
+       u32 ncs_wr_setup_ns;
+       u32 nwe_setup_ns;
+       u32 ncs_rd_pulse_ns;
+       u32 nrd_pulse_ns;
+       u32 ncs_wr_pulse_ns;
+       u32 nwe_pulse_ns;
+       u32 nrd_cycle_ns;
+       u32 nwe_cycle_ns;
+       u32 tdf_ns;
+};
+
+struct at91sam9_smc_generic_fields {
+       struct regmap_field *setup;
+       struct regmap_field *pulse;
+       struct regmap_field *cycle;
+       struct regmap_field *mode;
+};
+
+struct at91sam9_ebi_dev_config {
+       struct at91sam9_smc_timings timings;
+       u32 mode;
+};
+
+struct at91_ebi_dev_config {
+       int cs;
+       union {
+               struct at91sam9_ebi_dev_config sam9;
+       };
+};
+
+struct at91_ebi;
+
+struct at91_ebi_dev {
+       struct list_head node;
+       struct at91_ebi *ebi;
+       u32 mode;
+       int numcs;
+       struct at91_ebi_dev_config configs[];
+};
+
+struct at91_ebi_caps {
+       unsigned int available_cs;
+       const struct reg_field *ebi_csa;
+       void (*get_config)(struct at91_ebi_dev *ebid,
+                          struct at91_ebi_dev_config *conf);
+       int (*xlate_config)(struct at91_ebi_dev *ebid,
+                           struct device_node *configs_np,
+                           struct at91_ebi_dev_config *conf);
+       int (*apply_config)(struct at91_ebi_dev *ebid,
+                           struct at91_ebi_dev_config *conf);
+       int (*init)(struct at91_ebi *ebi);
+};
+
+struct at91_ebi {
+       struct clk *clk;
+       struct regmap *smc;
+       struct regmap *matrix;
+
+       struct regmap_field *ebi_csa;
+
+       struct device *dev;
+       const struct at91_ebi_caps *caps;
+       struct list_head devs;
+       union {
+               struct at91sam9_smc_generic_fields sam9;
+       };
+};
+
+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);
+       struct at91sam9_ebi_dev_config *config = &conf->sam9;
+       struct at91sam9_smc_timings *timings = &config->timings;
+       unsigned int val;
+
+       regmap_fields_read(fields->mode, conf->cs, &val);
+       config->mode = val & ~AT91_SMC_TDF;
+
+       val = (val & AT91_SMC_TDF) >> 16;
+       timings->tdf_ns = clk_rate * 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->nrd_setup_ns = (val >> 16) & 0x1f;
+       timings->nrd_setup_ns += ((val >> 21) & 0x1) * 128;
+       timings->nrd_setup_ns *= clk_rate;
+       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->nwe_setup_ns = val & 0x1f;
+       timings->nwe_setup_ns += ((val >> 5) & 0x1) * 128;
+       timings->nwe_setup_ns *= clk_rate;
+
+       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->nrd_pulse_ns = (val >> 16) & 0x3f;
+       timings->nrd_pulse_ns += ((val >> 22) & 0x1) * 256;
+       timings->nrd_pulse_ns *= clk_rate;
+       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->nwe_pulse_ns = val & 0x3f;
+       timings->nwe_pulse_ns += ((val >> 6) & 0x1) * 256;
+       timings->nwe_pulse_ns *= clk_rate;
+
+       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->nwe_cycle_ns = val & 0x7f;
+       timings->nwe_cycle_ns += ((val >> 7) & 0x3) * 256;
+       timings->nwe_cycle_ns *= clk_rate;
+}
+
+static int at91_xlate_timing(struct device_node *np, const char *prop,
+                            u32 *val, bool *required)
+{
+       if (!of_property_read_u32(np, prop, val)) {
+               *required = true;
+               return 0;
+       }
+
+       if (*required)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int at91sam9_smc_xslate_timings(struct at91_ebi_dev *ebid,
+                                      struct device_node *np,
+                                      struct at91sam9_smc_timings *timings,
+                                      bool *required)
+{
+       int ret;
+
+       ret = at91_xlate_timing(np, "atmel,smc-ncs-rd-setup-ns",
+                               &timings->ncs_rd_setup_ns, required);
+       if (ret)
+               goto out;
+
+       ret = at91_xlate_timing(np, "atmel,smc-nrd-setup-ns",
+                               &timings->nrd_setup_ns, required);
+       if (ret)
+               goto out;
+
+       ret = at91_xlate_timing(np, "atmel,smc-ncs-wr-setup-ns",
+                               &timings->ncs_wr_setup_ns, required);
+       if (ret)
+               goto out;
+
+       ret = at91_xlate_timing(np, "atmel,smc-nwe-setup-ns",
+                               &timings->nwe_setup_ns, required);
+       if (ret)
+               goto out;
+
+       ret = at91_xlate_timing(np, "atmel,smc-ncs-rd-pulse-ns",
+                               &timings->ncs_rd_pulse_ns, required);
+       if (ret)
+               goto out;
+
+       ret = at91_xlate_timing(np, "atmel,smc-nrd-pulse-ns",
+                               &timings->nrd_pulse_ns, required);
+       if (ret)
+               goto out;
+
+       ret = at91_xlate_timing(np, "atmel,smc-ncs-wr-pulse-ns",
+                               &timings->ncs_wr_pulse_ns, required);
+       if (ret)
+               goto out;
+
+       ret = at91_xlate_timing(np, "atmel,smc-nwe-pulse-ns",
+                               &timings->nwe_pulse_ns, required);
+       if (ret)
+               goto out;
+
+       ret = at91_xlate_timing(np, "atmel,smc-nwe-cycle-ns",
+                               &timings->nwe_cycle_ns, required);
+       if (ret)
+               goto out;
+
+       ret = at91_xlate_timing(np, "atmel,smc-nrd-cycle-ns",
+                               &timings->nrd_cycle_ns, required);
+       if (ret)
+               goto out;
+
+       ret = at91_xlate_timing(np, "atmel,smc-tdf-ns",
+                               &timings->tdf_ns, required);
+
+out:
+       if (ret)
+               dev_err(ebid->ebi->dev,
+                       "missing or invalid timings definition in %s",
+                       np->full_name);
+
+       return ret;
+}
+
+static int at91sam9_ebi_xslate_config(struct at91_ebi_dev *ebid,
+                                     struct device_node *np,
+                                     struct at91_ebi_dev_config *conf)
+{
+       struct at91sam9_ebi_dev_config *config = &conf->sam9;
+       bool required = false;
+       const char *tmp_str;
+       u32 tmp;
+       int ret;
+
+       ret = of_property_read_u32(np, "atmel,smc-bus-width", &tmp);
+       if (!ret) {
+               switch (tmp) {
+               case 8:
+                       config->mode |= AT91_SMC_DBW_8;
+                       break;
+
+               case 16:
+                       config->mode |= AT91_SMC_DBW_16;
+                       break;
+
+               case 32:
+                       config->mode |= AT91_SMC_DBW_32;
+                       break;
+
+               default:
+                       return -EINVAL;
+               }
+
+               required = true;
+       }
+
+       if (of_property_read_bool(np, "atmel,smc-tdf-optimized")) {
+               config->mode |= AT91_SMC_TDFMODE_OPTIMIZED;
+               required = true;
+       }
+
+       tmp_str = NULL;
+       of_property_read_string(np, "atmel,smc-byte-access-type", &tmp_str);
+       if (tmp_str && !strcmp(tmp_str, "write")) {
+               config->mode |= AT91_SMC_BAT_WRITE;
+               required = true;
+       }
+
+       tmp_str = NULL;
+       of_property_read_string(np, "atmel,smc-read-mode", &tmp_str);
+       if (tmp_str && !strcmp(tmp_str, "nrd")) {
+               config->mode |= AT91_SMC_READMODE_NRD;
+               required = true;
+       }
+
+       tmp_str = NULL;
+       of_property_read_string(np, "atmel,smc-write-mode", &tmp_str);
+       if (tmp_str && !strcmp(tmp_str, "nwe")) {
+               config->mode |= AT91_SMC_WRITEMODE_NWE;
+               required = true;
+       }
+
+       tmp_str = NULL;
+       of_property_read_string(np, "atmel,smc-exnw-mode", &tmp_str);
+       if (tmp_str) {
+               if (!strcmp(tmp_str, "frozen"))
+                       config->mode |= AT91_SMC_EXNWMODE_FROZEN;
+               else if (!strcmp(tmp_str, "ready"))
+                       config->mode |= AT91_SMC_EXNWMODE_READY;
+               else if (strcmp(tmp_str, "disabled"))
+                       return -EINVAL;
+
+               required = true;
+       }
+
+       ret = of_property_read_u32(np, "atmel,smc-page-mode", &tmp);
+       if (!ret) {
+               switch (tmp) {
+               case 4:
+                       config->mode |= AT91_SMC_PS_4;
+                       break;
+
+               case 8:
+                       config->mode |= AT91_SMC_PS_8;
+                       break;
+
+               case 16:
+                       config->mode |= AT91_SMC_PS_16;
+                       break;
+
+               case 32:
+                       config->mode |= AT91_SMC_PS_32;
+                       break;
+
+               default:
+                       return -EINVAL;
+               }
+
+               config->mode |= AT91_SMC_PMEN;
+               required = true;
+       }
+
+       ret = at91sam9_smc_xslate_timings(ebid, np, &config->timings,
+                                         &required);
+       if (ret)
+               return ret;
+
+       return required;
+}
+
+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);
+       struct at91sam9_ebi_dev_config *config = &conf->sam9;
+       struct at91sam9_smc_timings *timings = &config->timings;
+       struct at91sam9_smc_generic_fields *fields = &ebid->ebi->sam9;
+       u32 coded_val;
+       u32 val;
+
+       coded_val = at91sam9_smc_setup_ns_to_cycles(clk_rate,
+                                                   timings->ncs_rd_setup_ns);
+       val = AT91SAM9_SMC_NCS_NRDSETUP(coded_val);
+       coded_val = at91sam9_smc_setup_ns_to_cycles(clk_rate,
+                                                   timings->nrd_setup_ns);
+       val |= AT91SAM9_SMC_NRDSETUP(coded_val);
+       coded_val = at91sam9_smc_setup_ns_to_cycles(clk_rate,
+                                                   timings->ncs_wr_setup_ns);
+       val |= AT91SAM9_SMC_NCS_WRSETUP(coded_val);
+       coded_val = at91sam9_smc_setup_ns_to_cycles(clk_rate,
+                                                   timings->nwe_setup_ns);
+       val |= AT91SAM9_SMC_NWESETUP(coded_val);
+       regmap_fields_write(fields->setup, conf->cs, val);
+
+       coded_val = at91sam9_smc_pulse_ns_to_cycles(clk_rate,
+                                                   timings->ncs_rd_pulse_ns);
+       val = AT91SAM9_SMC_NCS_NRDPULSE(coded_val);
+       coded_val = at91sam9_smc_pulse_ns_to_cycles(clk_rate,
+                                                   timings->nrd_pulse_ns);
+       val |= AT91SAM9_SMC_NRDPULSE(coded_val);
+       coded_val = at91sam9_smc_pulse_ns_to_cycles(clk_rate,
+                                                   timings->ncs_wr_pulse_ns);
+       val |= AT91SAM9_SMC_NCS_WRPULSE(coded_val);
+       coded_val = at91sam9_smc_pulse_ns_to_cycles(clk_rate,
+                                                   timings->nwe_pulse_ns);
+       val |= AT91SAM9_SMC_NWEPULSE(coded_val);
+       regmap_fields_write(fields->pulse, conf->cs, val);
+
+       coded_val = at91sam9_smc_cycle_ns_to_cycles(clk_rate,
+                                                   timings->nrd_cycle_ns);
+       val = AT91SAM9_SMC_NRDCYCLE(coded_val);
+       coded_val = at91sam9_smc_cycle_ns_to_cycles(clk_rate,
+                                                   timings->nwe_cycle_ns);
+       val |= AT91SAM9_SMC_NWECYCLE(coded_val);
+       regmap_fields_write(fields->cycle, conf->cs, val);
+
+       val = DIV_ROUND_UP(timings->tdf_ns, clk_rate);
+       if (val > AT91_SMC_TDF_MAX)
+               val = AT91_SMC_TDF_MAX;
+       regmap_fields_write(fields->mode, conf->cs,
+                           config->mode | AT91_SMC_TDF_(val));
+
+       return 0;
+}
+
+static int at91sam9_ebi_init(struct at91_ebi *ebi)
+{
+       struct at91sam9_smc_generic_fields *fields = &ebi->sam9;
+       struct reg_field field = REG_FIELD(0, 0, 31);
+
+       field.id_size = fls(ebi->caps->available_cs);
+       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);
+       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);
+       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);
+       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);
+       if (IS_ERR(fields->mode))
+               return PTR_ERR(fields->mode);
+
+       return 0;
+}
+
+static int sama5d3_ebi_init(struct at91_ebi *ebi)
+{
+       struct at91sam9_smc_generic_fields *fields = &ebi->sam9;
+       struct reg_field field = REG_FIELD(0, 0, 31);
+
+       field.id_size = fls(ebi->caps->available_cs);
+       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);
+       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);
+       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);
+       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);
+       if (IS_ERR(fields->mode))
+               return PTR_ERR(fields->mode);
+
+       return 0;
+}
+
+static int at91_ebi_dev_setup(struct at91_ebi *ebi, struct device_node *np,
+                             int reg_cells)
+{
+       const struct at91_ebi_caps *caps = ebi->caps;
+       struct at91_ebi_dev_config conf = { };
+       struct device *dev = ebi->dev;
+       struct at91_ebi_dev *ebid;
+       int ret, numcs = 0, i;
+       bool apply = false;
+
+       numcs = of_property_count_elems_of_size(np, "reg",
+                                               reg_cells * sizeof(u32));
+       if (numcs <= 0) {
+               dev_err(dev, "invalid reg property in %s\n", np->full_name);
+               return -EINVAL;
+       }
+
+       ebid = devm_kzalloc(ebi->dev,
+                           sizeof(*ebid) + (numcs * sizeof(*ebid->configs)),
+                           GFP_KERNEL);
+       if (!ebid)
+               return -ENOMEM;
+
+       ebid->ebi = ebi;
+
+       ret = caps->xlate_config(ebid, np, &conf);
+       if (ret < 0)
+               return ret;
+       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;
+               }
+
+               ebid->configs[i].cs = cs;
+
+               if (apply) {
+                       conf.cs = cs;
+                       ret = caps->apply_config(ebid, &conf);
+                       if (ret)
+                               return ret;
+               }
+
+               caps->get_config(ebid, &ebid->configs[i]);
+
+               /*
+                * Attach the EBI device to the generic SMC logic if at least
+                * one "atmel,smc-" property is present.
+                */
+               if (ebi->ebi_csa && ret)
+                       regmap_field_update_bits(ebi->ebi_csa,
+                                                BIT(cs), 0);
+       }
+
+       list_add_tail(&ebid->node, &ebi->devs);
+
+       return 0;
+}
+
+static const struct reg_field at91sam9260_ebi_csa =
+                               REG_FIELD(AT91SAM9260_MATRIX_EBICSA, 0,
+                                         AT91_MATRIX_EBI_NUM_CS - 1);
+
+static const struct at91_ebi_caps at91sam9260_ebi_caps = {
+       .available_cs = 0xff,
+       .ebi_csa = &at91sam9260_ebi_csa,
+       .get_config = at91sam9_ebi_get_config,
+       .xlate_config = at91sam9_ebi_xslate_config,
+       .apply_config = at91sam9_ebi_apply_config,
+       .init = at91sam9_ebi_init,
+};
+
+static const struct reg_field at91sam9261_ebi_csa =
+                               REG_FIELD(AT91SAM9261_MATRIX_EBICSA, 0,
+                                         AT91_MATRIX_EBI_NUM_CS - 1);
+
+static const struct at91_ebi_caps at91sam9261_ebi_caps = {
+       .available_cs = 0xff,
+       .ebi_csa = &at91sam9261_ebi_csa,
+       .get_config = at91sam9_ebi_get_config,
+       .xlate_config = at91sam9_ebi_xslate_config,
+       .apply_config = at91sam9_ebi_apply_config,
+       .init = at91sam9_ebi_init,
+};
+
+static const struct reg_field at91sam9263_ebi0_csa =
+                               REG_FIELD(AT91SAM9263_MATRIX_EBI0CSA, 0,
+                                         AT91_MATRIX_EBI_NUM_CS - 1);
+
+static const struct at91_ebi_caps at91sam9263_ebi0_caps = {
+       .available_cs = 0x3f,
+       .ebi_csa = &at91sam9263_ebi0_csa,
+       .get_config = at91sam9_ebi_get_config,
+       .xlate_config = at91sam9_ebi_xslate_config,
+       .apply_config = at91sam9_ebi_apply_config,
+       .init = at91sam9_ebi_init,
+};
+
+static const struct reg_field at91sam9263_ebi1_csa =
+                               REG_FIELD(AT91SAM9263_MATRIX_EBI1CSA, 0,
+                                         AT91_MATRIX_EBI_NUM_CS - 1);
+
+static const struct at91_ebi_caps at91sam9263_ebi1_caps = {
+       .available_cs = 0x7,
+       .ebi_csa = &at91sam9263_ebi1_csa,
+       .get_config = at91sam9_ebi_get_config,
+       .xlate_config = at91sam9_ebi_xslate_config,
+       .apply_config = at91sam9_ebi_apply_config,
+       .init = at91sam9_ebi_init,
+};
+
+static const struct reg_field at91sam9rl_ebi_csa =
+                               REG_FIELD(AT91SAM9RL_MATRIX_EBICSA, 0,
+                                         AT91_MATRIX_EBI_NUM_CS - 1);
+
+static const struct at91_ebi_caps at91sam9rl_ebi_caps = {
+       .available_cs = 0x3f,
+       .ebi_csa = &at91sam9rl_ebi_csa,
+       .get_config = at91sam9_ebi_get_config,
+       .xlate_config = at91sam9_ebi_xslate_config,
+       .apply_config = at91sam9_ebi_apply_config,
+       .init = at91sam9_ebi_init,
+};
+
+static const struct reg_field at91sam9g45_ebi_csa =
+                               REG_FIELD(AT91SAM9G45_MATRIX_EBICSA, 0,
+                                         AT91_MATRIX_EBI_NUM_CS - 1);
+
+static const struct at91_ebi_caps at91sam9g45_ebi_caps = {
+       .available_cs = 0x3f,
+       .ebi_csa = &at91sam9g45_ebi_csa,
+       .get_config = at91sam9_ebi_get_config,
+       .xlate_config = at91sam9_ebi_xslate_config,
+       .apply_config = at91sam9_ebi_apply_config,
+       .init = at91sam9_ebi_init,
+};
+
+static const struct at91_ebi_caps at91sam9x5_ebi_caps = {
+       .available_cs = 0x3f,
+       .ebi_csa = &at91sam9263_ebi0_csa,
+       .get_config = at91sam9_ebi_get_config,
+       .xlate_config = at91sam9_ebi_xslate_config,
+       .apply_config = at91sam9_ebi_apply_config,
+       .init = at91sam9_ebi_init,
+};
+
+static const struct at91_ebi_caps sama5d3_ebi_caps = {
+       .available_cs = 0xf,
+       .get_config = at91sam9_ebi_get_config,
+       .xlate_config = at91sam9_ebi_xslate_config,
+       .apply_config = at91sam9_ebi_apply_config,
+       .init = sama5d3_ebi_init,
+};
+
+static const struct of_device_id at91_ebi_id_table[] = {
+       {
+               .compatible = "atmel,at91sam9260-ebi",
+               .data = &at91sam9260_ebi_caps,
+       },
+       {
+               .compatible = "atmel,at91sam9261-ebi",
+               .data = &at91sam9261_ebi_caps,
+       },
+       {
+               .compatible = "atmel,at91sam9263-ebi0",
+               .data = &at91sam9263_ebi0_caps,
+       },
+       {
+               .compatible = "atmel,at91sam9263-ebi1",
+               .data = &at91sam9263_ebi1_caps,
+       },
+       {
+               .compatible = "atmel,at91sam9rl-ebi",
+               .data = &at91sam9rl_ebi_caps,
+       },
+       {
+               .compatible = "atmel,at91sam9g45-ebi",
+               .data = &at91sam9g45_ebi_caps,
+       },
+       {
+               .compatible = "atmel,at91sam9x5-ebi",
+               .data = &at91sam9x5_ebi_caps,
+       },
+       {
+               .compatible = "atmel,sama5d3-ebi",
+               .data = &sama5d3_ebi_caps,
+       },
+       { /* sentinel */ }
+};
+
+static int at91_ebi_dev_disable(struct at91_ebi *ebi, struct device_node *np)
+{
+       struct device *dev = ebi->dev;
+       struct property *newprop;
+
+       newprop = devm_kzalloc(dev, sizeof(*newprop), GFP_KERNEL);
+       if (!newprop)
+               return -ENOMEM;
+
+       newprop->name = devm_kstrdup(dev, "status", GFP_KERNEL);
+       if (!newprop->name)
+               return -ENOMEM;
+
+       newprop->value = devm_kstrdup(dev, "disabled", GFP_KERNEL);
+       if (!newprop->name)
+               return -ENOMEM;
+
+       newprop->length = sizeof("disabled");
+
+       return of_update_property(np, newprop);
+}
+
+static int at91_ebi_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *child, *np = dev->of_node;
+       const struct of_device_id *match;
+       struct at91_ebi *ebi;
+       int ret, reg_cells;
+       struct clk *clk;
+       u32 val;
+
+       match = of_match_device(at91_ebi_id_table, dev);
+       if (!match || !match->data)
+               return -EINVAL;
+
+       ebi = devm_kzalloc(dev, sizeof(*ebi), GFP_KERNEL);
+       if (!ebi)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&ebi->devs);
+       ebi->caps = match->data;
+       ebi->dev = dev;
+
+       clk = devm_clk_get(dev, NULL);
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       ebi->clk = clk;
+
+       ebi->smc = syscon_regmap_lookup_by_phandle(np, "atmel,smc");
+       if (IS_ERR(ebi->smc))
+               return PTR_ERR(ebi->smc);
+
+       /*
+        * The sama5d3 does not provide an EBICSA register and thus does need
+        * to access the matrix registers.
+        */
+       if (ebi->caps->ebi_csa) {
+               ebi->matrix =
+                       syscon_regmap_lookup_by_phandle(np, "atmel,matrix");
+               if (IS_ERR(ebi->matrix))
+                       return PTR_ERR(ebi->matrix);
+
+               ebi->ebi_csa = regmap_field_alloc(ebi->matrix,
+                                                 *ebi->caps->ebi_csa);
+               if (IS_ERR(ebi->ebi_csa))
+                       return PTR_ERR(ebi->ebi_csa);
+       }
+
+       ret = ebi->caps->init(ebi);
+       if (ret)
+               return ret;
+
+       ret = of_property_read_u32(np, "#address-cells", &val);
+       if (ret) {
+               dev_err(dev, "missing #address-cells property\n");
+               return ret;
+       }
+
+       reg_cells = val;
+
+       ret = of_property_read_u32(np, "#size-cells", &val);
+       if (ret) {
+               dev_err(dev, "missing #address-cells property\n");
+               return ret;
+       }
+
+       reg_cells += val;
+
+       for_each_available_child_of_node(np, child) {
+               if (!of_find_property(child, "reg", NULL))
+                       continue;
+
+               ret = at91_ebi_dev_setup(ebi, child, reg_cells);
+               if (ret) {
+                       dev_err(dev, "failed to configure EBI bus for %s, disabling the device",
+                               child->full_name);
+
+                       ret = at91_ebi_dev_disable(ebi, child);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       return of_platform_populate(np, NULL, NULL, dev);
+}
+
+static struct platform_driver at91_ebi_driver = {
+       .driver = {
+               .name = "atmel-ebi",
+               .of_match_table = at91_ebi_id_table,
+       },
+};
+builtin_platform_driver_probe(at91_ebi_driver, at91_ebi_probe);
index a3ebc8a..53a341f 100644 (file)
@@ -1,6 +1,8 @@
 /*
  * Atmel (Multi-port DDR-)SDRAM Controller driver
  *
+ * Author: Alexandre Belloni <alexandre.belloni@free-electrons.com>
+ *
  * Copyright (C) 2014 Atmel
  *
  * This program is free software: you can redistribute it and/or modify
@@ -20,7 +22,7 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 
@@ -48,7 +50,6 @@ static const struct of_device_id atmel_ramc_of_match[] = {
        { .compatible = "atmel,sama5d3-ddramc", .data = &sama5d3_caps, },
        {},
 };
-MODULE_DEVICE_TABLE(of, atmel_ramc_of_match);
 
 static int atmel_ramc_probe(struct platform_device *pdev)
 {
@@ -90,8 +91,4 @@ static int __init atmel_ramc_init(void)
 {
        return platform_driver_register(&atmel_ramc_driver);
 }
-module_init(atmel_ramc_init);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@free-electrons.com>");
-MODULE_DESCRIPTION("Atmel (Multi-port DDR-)SDRAM Controller");
+device_initcall(atmel_ramc_init);
index ed01c01..04e4fe5 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/sizes.h>
 #include <linux/of_reserved_mem.h>
 #include <linux/sort.h>
+#include <linux/slab.h>
 
 #define MAX_RESERVED_REGIONS   16
 static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS];
@@ -289,53 +290,95 @@ static inline struct reserved_mem *__find_rmem(struct device_node *node)
        return NULL;
 }
 
+struct rmem_assigned_device {
+       struct device *dev;
+       struct reserved_mem *rmem;
+       struct list_head list;
+};
+
+static LIST_HEAD(of_rmem_assigned_device_list);
+static DEFINE_MUTEX(of_rmem_assigned_device_mutex);
+
 /**
- * of_reserved_mem_device_init() - assign reserved memory region to given device
+ * of_reserved_mem_device_init_by_idx() - assign reserved memory region to
+ *                                       given device
+ * @dev:       Pointer to the device to configure
+ * @np:                Pointer to the device_node with 'reserved-memory' property
+ * @idx:       Index of selected region
  *
- * This function assign memory region pointed by "memory-region" device tree
- * property to the given device.
+ * This function assigns respective DMA-mapping operations based on reserved
+ * memory region specified by 'memory-region' property in @np node to the @dev
+ * device. When driver needs to use more than one reserved memory region, it
+ * should allocate child devices and initialize regions by name for each of
+ * child device.
+ *
+ * Returns error code or zero on success.
  */
-int of_reserved_mem_device_init(struct device *dev)
+int of_reserved_mem_device_init_by_idx(struct device *dev,
+                                      struct device_node *np, int idx)
 {
+       struct rmem_assigned_device *rd;
+       struct device_node *target;
        struct reserved_mem *rmem;
-       struct device_node *np;
        int ret;
 
-       np = of_parse_phandle(dev->of_node, "memory-region", 0);
-       if (!np)
-               return -ENODEV;
+       if (!np || !dev)
+               return -EINVAL;
+
+       target = of_parse_phandle(np, "memory-region", idx);
+       if (!target)
+               return -EINVAL;
 
-       rmem = __find_rmem(np);
-       of_node_put(np);
+       rmem = __find_rmem(target);
+       of_node_put(target);
 
        if (!rmem || !rmem->ops || !rmem->ops->device_init)
                return -EINVAL;
 
+       rd = kmalloc(sizeof(struct rmem_assigned_device), GFP_KERNEL);
+       if (!rd)
+               return -ENOMEM;
+
        ret = rmem->ops->device_init(rmem, dev);
-       if (ret == 0)
+       if (ret == 0) {
+               rd->dev = dev;
+               rd->rmem = rmem;
+
+               mutex_lock(&of_rmem_assigned_device_mutex);
+               list_add(&rd->list, &of_rmem_assigned_device_list);
+               mutex_unlock(&of_rmem_assigned_device_mutex);
+
                dev_info(dev, "assigned reserved memory node %s\n", rmem->name);
+       } else {
+               kfree(rd);
+       }
 
        return ret;
 }
-EXPORT_SYMBOL_GPL(of_reserved_mem_device_init);
+EXPORT_SYMBOL_GPL(of_reserved_mem_device_init_by_idx);
 
 /**
  * of_reserved_mem_device_release() - release reserved memory device structures
+ * @dev:       Pointer to the device to deconfigure
  *
  * This function releases structures allocated for memory region handling for
  * the given device.
  */
 void of_reserved_mem_device_release(struct device *dev)
 {
-       struct reserved_mem *rmem;
-       struct device_node *np;
-
-       np = of_parse_phandle(dev->of_node, "memory-region", 0);
-       if (!np)
-               return;
-
-       rmem = __find_rmem(np);
-       of_node_put(np);
+       struct rmem_assigned_device *rd;
+       struct reserved_mem *rmem = NULL;
+
+       mutex_lock(&of_rmem_assigned_device_mutex);
+       list_for_each_entry(rd, &of_rmem_assigned_device_list, list) {
+               if (rd->dev == dev) {
+                       rmem = rd->rmem;
+                       list_del(&rd->list);
+                       kfree(rd);
+                       break;
+               }
+       }
+       mutex_unlock(&of_rmem_assigned_device_mutex);
 
        if (!rmem || !rmem->ops || !rmem->ops->device_release)
                return;
index 9bb2622..f38ac90 100644 (file)
@@ -46,6 +46,16 @@ config POWER_RESET_AXXIA
 
          Say Y if you have an Axxia family SoC.
 
+config POWER_RESET_BRCMKONA
+       bool "Broadcom Kona reset driver"
+       depends on ARM || COMPILE_TEST
+       default ARCH_BCM_MOBILE
+       help
+         This driver provides restart support for Broadcom Kona chips.
+
+         Say Y here if you have a Broadcom Kona-based board and you wish
+         to have restart support.
+
 config POWER_RESET_BRCMSTB
        bool "Broadcom STB reset driver"
        depends on ARM || MIPS || COMPILE_TEST
index ab7aa86..6b6eeb3 100644 (file)
@@ -3,6 +3,7 @@ obj-$(CONFIG_POWER_RESET_AT91_POWEROFF) += at91-poweroff.o
 obj-$(CONFIG_POWER_RESET_AT91_RESET) += at91-reset.o
 obj-$(CONFIG_POWER_RESET_AT91_SAMA5D2_SHDWC) += at91-sama5d2_shdwc.o
 obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
+obj-$(CONFIG_POWER_RESET_BRCMKONA) += brcm-kona-reset.o
 obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o
 obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
 obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o
diff --git a/drivers/power/reset/brcm-kona-reset.c b/drivers/power/reset/brcm-kona-reset.c
new file mode 100644 (file)
index 0000000..8eaa959
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/reboot.h>
+
+#define RSTMGR_REG_WR_ACCESS_OFFSET    0
+#define RSTMGR_REG_CHIP_SOFT_RST_OFFSET        4
+
+#define RSTMGR_WR_PASSWORD             0xa5a5
+#define RSTMGR_WR_PASSWORD_SHIFT       8
+#define RSTMGR_WR_ACCESS_ENABLE                1
+
+static void __iomem *kona_reset_base;
+
+static int kona_reset_handler(struct notifier_block *this,
+                               unsigned long mode, void *cmd)
+{
+       /*
+        * A soft reset is triggered by writing a 0 to bit 0 of the soft reset
+        * register. To write to that register we must first write the password
+        * and the enable bit in the write access enable register.
+        */
+       writel((RSTMGR_WR_PASSWORD << RSTMGR_WR_PASSWORD_SHIFT) |
+               RSTMGR_WR_ACCESS_ENABLE,
+               kona_reset_base + RSTMGR_REG_WR_ACCESS_OFFSET);
+       writel(0, kona_reset_base + RSTMGR_REG_CHIP_SOFT_RST_OFFSET);
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block kona_reset_nb = {
+       .notifier_call = kona_reset_handler,
+       .priority = 128,
+};
+
+static int kona_reset_probe(struct platform_device *pdev)
+{
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       kona_reset_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(kona_reset_base))
+               return PTR_ERR(kona_reset_base);
+
+       return register_restart_handler(&kona_reset_nb);
+}
+
+static const struct of_device_id of_match[] = {
+       { .compatible = "brcm,bcm21664-resetmgr" },
+       {},
+};
+
+static struct platform_driver bcm_kona_reset_driver = {
+       .probe = kona_reset_probe,
+       .driver = {
+               .name = "brcm-kona-reset",
+               .of_match_table = of_match,
+       },
+};
+
+builtin_platform_driver(bcm_kona_reset_driver);
index 0b2733d..ab37f4d 100644 (file)
@@ -12,8 +12,12 @@ menuconfig RESET_CONTROLLER
 
          If unsure, say no.
 
+if RESET_CONTROLLER
+
 config RESET_OXNAS
        bool
 
 source "drivers/reset/sti/Kconfig"
 source "drivers/reset/hisilicon/Kconfig"
+
+endif
index f173fc3..03dc1bb 100644 (file)
@@ -3,6 +3,7 @@ obj-$(CONFIG_ARCH_LPC18XX) += reset-lpc18xx.o
 obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
 obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
 obj-$(CONFIG_MACH_PISTACHIO) += reset-pistachio.o
+obj-$(CONFIG_ARCH_MESON) += reset-meson.o
 obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
 obj-$(CONFIG_ARCH_STI) += sti/
 obj-$(CONFIG_ARCH_HISI) += hisilicon/
index 72b32bd..395dc9c 100644 (file)
@@ -93,6 +93,43 @@ void reset_controller_unregister(struct reset_controller_dev *rcdev)
 }
 EXPORT_SYMBOL_GPL(reset_controller_unregister);
 
+static void devm_reset_controller_release(struct device *dev, void *res)
+{
+       reset_controller_unregister(*(struct reset_controller_dev **)res);
+}
+
+/**
+ * devm_reset_controller_register - resource managed reset_controller_register()
+ * @dev: device that is registering this reset controller
+ * @rcdev: a pointer to the initialized reset controller device
+ *
+ * Managed reset_controller_register(). For reset controllers registered by
+ * this function, reset_controller_unregister() is automatically called on
+ * driver detach. See reset_controller_register() for more information.
+ */
+int devm_reset_controller_register(struct device *dev,
+                                  struct reset_controller_dev *rcdev)
+{
+       struct reset_controller_dev **rcdevp;
+       int ret;
+
+       rcdevp = devres_alloc(devm_reset_controller_release, sizeof(*rcdevp),
+                             GFP_KERNEL);
+       if (!rcdevp)
+               return -ENOMEM;
+
+       ret = reset_controller_register(rcdev);
+       if (!ret) {
+               *rcdevp = rcdev;
+               devres_add(dev, rcdevp);
+       } else {
+               devres_free(rcdevp);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(devm_reset_controller_register);
+
 /**
  * reset_control_reset - reset the controlled device
  * @rstc: reset controller
index ccb940a..16d410c 100644 (file)
@@ -112,7 +112,7 @@ static int ath79_reset_probe(struct platform_device *pdev)
        ath79_reset->rcdev.of_reset_n_cells = 1;
        ath79_reset->rcdev.nr_resets = 32;
 
-       err = reset_controller_register(&ath79_reset->rcdev);
+       err = devm_reset_controller_register(&pdev->dev, &ath79_reset->rcdev);
        if (err)
                return err;
 
@@ -131,7 +131,6 @@ static int ath79_reset_remove(struct platform_device *pdev)
        struct ath79_reset *ath79_reset = platform_get_drvdata(pdev);
 
        unregister_restart_handler(&ath79_reset->restart_nb);
-       reset_controller_unregister(&ath79_reset->rcdev);
 
        return 0;
 }
diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c
new file mode 100644 (file)
index 0000000..c32f11a
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#define REG_COUNT      8
+#define BITS_PER_REG   32
+
+struct meson_reset {
+       void __iomem *reg_base;
+       struct reset_controller_dev rcdev;
+};
+
+static int meson_reset_reset(struct reset_controller_dev *rcdev,
+                             unsigned long id)
+{
+       struct meson_reset *data =
+               container_of(rcdev, struct meson_reset, rcdev);
+       unsigned int bank = id / BITS_PER_REG;
+       unsigned int offset = id % BITS_PER_REG;
+       void __iomem *reg_addr = data->reg_base + (bank << 2);
+
+       if (bank >= REG_COUNT)
+               return -EINVAL;
+
+       writel(BIT(offset), reg_addr);
+
+       return 0;
+}
+
+static const struct reset_control_ops meson_reset_ops = {
+       .reset          = meson_reset_reset,
+};
+
+static const struct of_device_id meson_reset_dt_ids[] = {
+        { .compatible = "amlogic,meson8b-reset", },
+        { .compatible = "amlogic,meson-gxbb-reset", },
+        { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, meson_reset_dt_ids);
+
+static int meson_reset_probe(struct platform_device *pdev)
+{
+       struct meson_reset *data;
+       struct resource *res;
+
+       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       data->reg_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(data->reg_base))
+               return PTR_ERR(data->reg_base);
+
+       platform_set_drvdata(pdev, data);
+
+       data->rcdev.owner = THIS_MODULE;
+       data->rcdev.nr_resets = REG_COUNT * BITS_PER_REG;
+       data->rcdev.ops = &meson_reset_ops;
+       data->rcdev.of_node = pdev->dev.of_node;
+
+       return devm_reset_controller_register(&pdev->dev, &data->rcdev);
+}
+
+static struct platform_driver meson_reset_driver = {
+       .probe  = meson_reset_probe,
+       .driver = {
+               .name           = "meson_reset",
+               .of_match_table = meson_reset_dt_ids,
+       },
+};
+
+module_platform_driver(meson_reset_driver);
+
+MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
+MODULE_DESCRIPTION("Amlogic Meson Reset Controller driver");
+MODULE_LICENSE("Dual BSD/GPL");
index c60fb2d..9449805 100644 (file)
@@ -112,21 +112,11 @@ static int oxnas_reset_probe(struct platform_device *pdev)
        data->rcdev.ops = &oxnas_reset_ops;
        data->rcdev.of_node = pdev->dev.of_node;
 
-       return reset_controller_register(&data->rcdev);
-}
-
-static int oxnas_reset_remove(struct platform_device *pdev)
-{
-       struct oxnas_reset *data = platform_get_drvdata(pdev);
-
-       reset_controller_unregister(&data->rcdev);
-
-       return 0;
+       return devm_reset_controller_register(&pdev->dev, &data->rcdev);
 }
 
 static struct platform_driver oxnas_reset_driver = {
        .probe  = oxnas_reset_probe,
-       .remove = oxnas_reset_remove,
        .driver = {
                .name           = "oxnas-reset",
                .of_match_table = oxnas_reset_dt_ids,
index 72a97a1..bbc4c06 100644 (file)
@@ -121,16 +121,7 @@ static int pistachio_reset_probe(struct platform_device *pdev)
        rd->rcdev.ops = &pistachio_reset_ops;
        rd->rcdev.of_node = np;
 
-       return reset_controller_register(&rd->rcdev);
-}
-
-static int pistachio_reset_remove(struct platform_device *pdev)
-{
-       struct pistachio_reset_data *data = platform_get_drvdata(pdev);
-
-       reset_controller_unregister(&data->rcdev);
-
-       return 0;
+       return devm_reset_controller_register(dev, &rd->rcdev);
 }
 
 static const struct of_device_id pistachio_reset_dt_ids[] = {
@@ -141,7 +132,6 @@ MODULE_DEVICE_TABLE(of, pistachio_reset_dt_ids);
 
 static struct platform_driver pistachio_reset_driver = {
        .probe  = pistachio_reset_probe,
-       .remove = pistachio_reset_remove,
        .driver = {
                .name           = "pistachio-reset",
                .of_match_table = pistachio_reset_dt_ids,
index cd05a70..12add9b 100644 (file)
@@ -134,16 +134,7 @@ static int socfpga_reset_probe(struct platform_device *pdev)
        data->rcdev.ops = &socfpga_reset_ops;
        data->rcdev.of_node = pdev->dev.of_node;
 
-       return reset_controller_register(&data->rcdev);
-}
-
-static int socfpga_reset_remove(struct platform_device *pdev)
-{
-       struct socfpga_reset_data *data = platform_get_drvdata(pdev);
-
-       reset_controller_unregister(&data->rcdev);
-
-       return 0;
+       return devm_reset_controller_register(dev, &data->rcdev);
 }
 
 static const struct of_device_id socfpga_reset_dt_ids[] = {
@@ -153,7 +144,6 @@ static const struct of_device_id socfpga_reset_dt_ids[] = {
 
 static struct platform_driver socfpga_reset_driver = {
        .probe  = socfpga_reset_probe,
-       .remove = socfpga_reset_remove,
        .driver = {
                .name           = "socfpga-reset",
                .of_match_table = socfpga_reset_dt_ids,
index 677f865..3080190 100644 (file)
@@ -165,21 +165,11 @@ static int sunxi_reset_probe(struct platform_device *pdev)
        data->rcdev.ops = &sunxi_reset_ops;
        data->rcdev.of_node = pdev->dev.of_node;
 
-       return reset_controller_register(&data->rcdev);
-}
-
-static int sunxi_reset_remove(struct platform_device *pdev)
-{
-       struct sunxi_reset_data *data = platform_get_drvdata(pdev);
-
-       reset_controller_unregister(&data->rcdev);
-
-       return 0;
+       return devm_reset_controller_register(&pdev->dev, &data->rcdev);
 }
 
 static struct platform_driver sunxi_reset_driver = {
        .probe  = sunxi_reset_probe,
-       .remove = sunxi_reset_remove,
        .driver = {
                .name           = "sunxi-reset",
                .of_match_table = sunxi_reset_dt_ids,
index a7e87bc..138f2f2 100644 (file)
@@ -122,16 +122,7 @@ static int zynq_reset_probe(struct platform_device *pdev)
        priv->rcdev.ops = &zynq_reset_ops;
        priv->rcdev.of_node = pdev->dev.of_node;
 
-       return reset_controller_register(&priv->rcdev);
-}
-
-static int zynq_reset_remove(struct platform_device *pdev)
-{
-       struct zynq_reset_data *priv = platform_get_drvdata(pdev);
-
-       reset_controller_unregister(&priv->rcdev);
-
-       return 0;
+       return devm_reset_controller_register(&pdev->dev, &priv->rcdev);
 }
 
 static const struct of_device_id zynq_reset_dt_ids[] = {
@@ -141,7 +132,6 @@ static const struct of_device_id zynq_reset_dt_ids[] = {
 
 static struct platform_driver zynq_reset_driver = {
        .probe  = zynq_reset_probe,
-       .remove = zynq_reset_remove,
        .driver = {
                .name           = KBUILD_MODNAME,
                .of_match_table = zynq_reset_dt_ids,
index f8c15a3..6131785 100644 (file)
@@ -2,7 +2,6 @@ if ARCH_STI
 
 config STI_RESET_SYSCFG
        bool
-       select RESET_CONTROLLER
 
 config STIH415_RESET
        bool
index cb58ef0..91d5c05 100644 (file)
@@ -1,7 +1,6 @@
 menu "SOC (System On Chip) specific Drivers"
 
 source "drivers/soc/bcm/Kconfig"
-source "drivers/soc/brcmstb/Kconfig"
 source "drivers/soc/fsl/qe/Kconfig"
 source "drivers/soc/mediatek/Kconfig"
 source "drivers/soc/qcom/Kconfig"
index 380230f..b75e3bd 100644 (file)
@@ -3,7 +3,6 @@
 #
 
 obj-y                          += bcm/
-obj-$(CONFIG_SOC_BRCMSTB)      += brcmstb/
 obj-$(CONFIG_ARCH_DOVE)                += dove/
 obj-$(CONFIG_MACH_DOVE)                += dove/
 obj-y                          += fsl/
index 3066ede..97156ae 100644 (file)
@@ -1,3 +1,5 @@
+menu "Broadcom SoC drivers"
+
 config RASPBERRYPI_POWER
        bool "Raspberry Pi power domain driver"
        depends on ARCH_BCM2835 || COMPILE_TEST
@@ -7,3 +9,16 @@ config RASPBERRYPI_POWER
        help
          This enables support for the RPi power domains which can be enabled
          or disabled via the RPi firmware.
+
+config SOC_BRCMSTB
+       bool "Broadcom STB SoC drivers"
+       depends on ARM
+       select SOC_BUS
+       help
+         Enables drivers for the Broadcom Set-Top Box (STB) series of chips.
+         This option alone enables only some support code, while the drivers
+         can be enabled individually within this menu.
+
+         If unsure, say N.
+
+endmenu
index 63aa3eb..dc4fced 100644 (file)
@@ -1 +1,2 @@
 obj-$(CONFIG_RASPBERRYPI_POWER)        += raspberrypi-power.o
+obj-$(CONFIG_SOC_BRCMSTB)      += brcmstb/
diff --git a/drivers/soc/bcm/brcmstb/Makefile b/drivers/soc/bcm/brcmstb/Makefile
new file mode 100644 (file)
index 0000000..9120b27
--- /dev/null
@@ -0,0 +1 @@
+obj-y                          += common.o biuctrl.o
diff --git a/drivers/soc/bcm/brcmstb/biuctrl.c b/drivers/soc/bcm/brcmstb/biuctrl.c
new file mode 100644 (file)
index 0000000..3c39415
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Broadcom STB SoCs Bus Unit Interface controls
+ *
+ * Copyright (C) 2015, Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt)    "brcmstb: " KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+#include <linux/soc/brcmstb/brcmstb.h>
+
+#define CPU_CREDIT_REG_OFFSET                  0x184
+#define  CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK        0x70000000
+
+static void __iomem *cpubiuctrl_base;
+static bool mcp_wr_pairing_en;
+
+static int __init mcp_write_pairing_set(void)
+{
+       u32 creds = 0;
+
+       if (!cpubiuctrl_base)
+               return -1;
+
+       creds = readl_relaxed(cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
+       if (mcp_wr_pairing_en) {
+               pr_info("MCP: Enabling write pairing\n");
+               writel_relaxed(creds | CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK,
+                            cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
+       } else if (creds & CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK) {
+               pr_info("MCP: Disabling write pairing\n");
+               writel_relaxed(creds & ~CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK,
+                               cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
+       } else {
+               pr_info("MCP: Write pairing already disabled\n");
+       }
+
+       return 0;
+}
+
+static int __init setup_hifcpubiuctrl_regs(void)
+{
+       struct device_node *np;
+       int ret = 0;
+
+       np = of_find_compatible_node(NULL, NULL, "brcm,brcmstb-cpu-biu-ctrl");
+       if (!np) {
+               pr_err("missing BIU control node\n");
+               return -ENODEV;
+       }
+
+       cpubiuctrl_base = of_iomap(np, 0);
+       if (!cpubiuctrl_base) {
+               pr_err("failed to remap BIU control base\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       mcp_wr_pairing_en = of_property_read_bool(np, "brcm,write-pairing");
+out:
+       of_node_put(np);
+       return ret;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static u32 cpu_credit_reg_dump;  /* for save/restore */
+
+static int brcmstb_cpu_credit_reg_suspend(void)
+{
+       if (cpubiuctrl_base)
+               cpu_credit_reg_dump =
+                       readl_relaxed(cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
+       return 0;
+}
+
+static void brcmstb_cpu_credit_reg_resume(void)
+{
+       if (cpubiuctrl_base)
+               writel_relaxed(cpu_credit_reg_dump,
+                               cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
+}
+
+static struct syscore_ops brcmstb_cpu_credit_syscore_ops = {
+       .suspend = brcmstb_cpu_credit_reg_suspend,
+       .resume = brcmstb_cpu_credit_reg_resume,
+};
+#endif
+
+
+void __init brcmstb_biuctrl_init(void)
+{
+       int ret;
+
+       setup_hifcpubiuctrl_regs();
+
+       ret = mcp_write_pairing_set();
+       if (ret) {
+               pr_err("MCP: Unable to disable write pairing!\n");
+               return;
+       }
+
+#ifdef CONFIG_PM_SLEEP
+       register_syscore_ops(&brcmstb_cpu_credit_syscore_ops);
+#endif
+}
diff --git a/drivers/soc/bcm/brcmstb/common.c b/drivers/soc/bcm/brcmstb/common.c
new file mode 100644 (file)
index 0000000..94e7335
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright Â© 2014 NVIDIA Corporation
+ * Copyright Â© 2015 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/soc/brcmstb/brcmstb.h>
+#include <linux/sys_soc.h>
+
+#include <soc/brcmstb/common.h>
+
+static u32 family_id;
+static u32 product_id;
+
+static const struct of_device_id brcmstb_machine_match[] = {
+       { .compatible = "brcm,brcmstb", },
+       { }
+};
+
+bool soc_is_brcmstb(void)
+{
+       struct device_node *root;
+
+       root = of_find_node_by_path("/");
+       if (!root)
+               return false;
+
+       return of_match_node(brcmstb_machine_match, root) != NULL;
+}
+
+static const struct of_device_id sun_top_ctrl_match[] = {
+       { .compatible = "brcm,brcmstb-sun-top-ctrl", },
+       { }
+};
+
+static int __init brcmstb_soc_device_init(void)
+{
+       struct soc_device_attribute *soc_dev_attr;
+       struct soc_device *soc_dev;
+       struct device_node *sun_top_ctrl;
+       void __iomem *sun_top_ctrl_base;
+       int ret = 0;
+
+       sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match);
+       if (!sun_top_ctrl)
+               return -ENODEV;
+
+       sun_top_ctrl_base = of_iomap(sun_top_ctrl, 0);
+       if (!sun_top_ctrl_base)
+               return -ENODEV;
+
+       family_id = readl(sun_top_ctrl_base);
+       product_id = readl(sun_top_ctrl_base + 0x4);
+
+       soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+       if (!soc_dev_attr) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       soc_dev_attr->family = kasprintf(GFP_KERNEL, "%x",
+                                        family_id >> 28 ?
+                                        family_id >> 16 : family_id >> 8);
+       soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%x",
+                                        product_id >> 28 ?
+                                        product_id >> 16 : product_id >> 8);
+       soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c%d",
+                                        ((product_id & 0xf0) >> 4) + 'A',
+                                          product_id & 0xf);
+
+       soc_dev = soc_device_register(soc_dev_attr);
+       if (IS_ERR(soc_dev)) {
+               kfree(soc_dev_attr->family);
+               kfree(soc_dev_attr->soc_id);
+               kfree(soc_dev_attr->revision);
+               kfree(soc_dev_attr);
+               ret = -ENODEV;
+               goto out;
+       }
+
+       return 0;
+
+out:
+       iounmap(sun_top_ctrl_base);
+       return ret;
+}
+arch_initcall(brcmstb_soc_device_init);
diff --git a/drivers/soc/brcmstb/Kconfig b/drivers/soc/brcmstb/Kconfig
deleted file mode 100644 (file)
index 7fec3b4..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-menuconfig SOC_BRCMSTB
-       bool "Broadcom STB SoC drivers"
-       depends on ARM
-       select SOC_BUS
-       help
-         Enables drivers for the Broadcom Set-Top Box (STB) series of chips.
-         This option alone enables only some support code, while the drivers
-         can be enabled individually within this menu.
-
-         If unsure, say N.
diff --git a/drivers/soc/brcmstb/Makefile b/drivers/soc/brcmstb/Makefile
deleted file mode 100644 (file)
index 9120b27..0000000
+++ /dev/null
@@ -1 +0,0 @@
-obj-y                          += common.o biuctrl.o
diff --git a/drivers/soc/brcmstb/biuctrl.c b/drivers/soc/brcmstb/biuctrl.c
deleted file mode 100644 (file)
index 9049c07..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Broadcom STB SoCs Bus Unit Interface controls
- *
- * Copyright (C) 2015, Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#define pr_fmt(fmt)    "brcmstb: " KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/of_address.h>
-#include <linux/syscore_ops.h>
-
-#define CPU_CREDIT_REG_OFFSET                  0x184
-#define  CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK        0x70000000
-
-static void __iomem *cpubiuctrl_base;
-static bool mcp_wr_pairing_en;
-
-static int __init mcp_write_pairing_set(void)
-{
-       u32 creds = 0;
-
-       if (!cpubiuctrl_base)
-               return -1;
-
-       creds = readl_relaxed(cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
-       if (mcp_wr_pairing_en) {
-               pr_info("MCP: Enabling write pairing\n");
-               writel_relaxed(creds | CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK,
-                            cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
-       } else if (creds & CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK) {
-               pr_info("MCP: Disabling write pairing\n");
-               writel_relaxed(creds & ~CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK,
-                               cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
-       } else {
-               pr_info("MCP: Write pairing already disabled\n");
-       }
-
-       return 0;
-}
-
-static int __init setup_hifcpubiuctrl_regs(void)
-{
-       struct device_node *np;
-       int ret = 0;
-
-       np = of_find_compatible_node(NULL, NULL, "brcm,brcmstb-cpu-biu-ctrl");
-       if (!np) {
-               pr_err("missing BIU control node\n");
-               return -ENODEV;
-       }
-
-       cpubiuctrl_base = of_iomap(np, 0);
-       if (!cpubiuctrl_base) {
-               pr_err("failed to remap BIU control base\n");
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       mcp_wr_pairing_en = of_property_read_bool(np, "brcm,write-pairing");
-out:
-       of_node_put(np);
-       return ret;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static u32 cpu_credit_reg_dump;  /* for save/restore */
-
-static int brcmstb_cpu_credit_reg_suspend(void)
-{
-       if (cpubiuctrl_base)
-               cpu_credit_reg_dump =
-                       readl_relaxed(cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
-       return 0;
-}
-
-static void brcmstb_cpu_credit_reg_resume(void)
-{
-       if (cpubiuctrl_base)
-               writel_relaxed(cpu_credit_reg_dump,
-                               cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
-}
-
-static struct syscore_ops brcmstb_cpu_credit_syscore_ops = {
-       .suspend = brcmstb_cpu_credit_reg_suspend,
-       .resume = brcmstb_cpu_credit_reg_resume,
-};
-#endif
-
-
-void __init brcmstb_biuctrl_init(void)
-{
-       int ret;
-
-       setup_hifcpubiuctrl_regs();
-
-       ret = mcp_write_pairing_set();
-       if (ret) {
-               pr_err("MCP: Unable to disable write pairing!\n");
-               return;
-       }
-
-#ifdef CONFIG_PM_SLEEP
-       register_syscore_ops(&brcmstb_cpu_credit_syscore_ops);
-#endif
-}
diff --git a/drivers/soc/brcmstb/common.c b/drivers/soc/brcmstb/common.c
deleted file mode 100644 (file)
index 94e7335..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright Â© 2014 NVIDIA Corporation
- * Copyright Â© 2015 Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/slab.h>
-#include <linux/soc/brcmstb/brcmstb.h>
-#include <linux/sys_soc.h>
-
-#include <soc/brcmstb/common.h>
-
-static u32 family_id;
-static u32 product_id;
-
-static const struct of_device_id brcmstb_machine_match[] = {
-       { .compatible = "brcm,brcmstb", },
-       { }
-};
-
-bool soc_is_brcmstb(void)
-{
-       struct device_node *root;
-
-       root = of_find_node_by_path("/");
-       if (!root)
-               return false;
-
-       return of_match_node(brcmstb_machine_match, root) != NULL;
-}
-
-static const struct of_device_id sun_top_ctrl_match[] = {
-       { .compatible = "brcm,brcmstb-sun-top-ctrl", },
-       { }
-};
-
-static int __init brcmstb_soc_device_init(void)
-{
-       struct soc_device_attribute *soc_dev_attr;
-       struct soc_device *soc_dev;
-       struct device_node *sun_top_ctrl;
-       void __iomem *sun_top_ctrl_base;
-       int ret = 0;
-
-       sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match);
-       if (!sun_top_ctrl)
-               return -ENODEV;
-
-       sun_top_ctrl_base = of_iomap(sun_top_ctrl, 0);
-       if (!sun_top_ctrl_base)
-               return -ENODEV;
-
-       family_id = readl(sun_top_ctrl_base);
-       product_id = readl(sun_top_ctrl_base + 0x4);
-
-       soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
-       if (!soc_dev_attr) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       soc_dev_attr->family = kasprintf(GFP_KERNEL, "%x",
-                                        family_id >> 28 ?
-                                        family_id >> 16 : family_id >> 8);
-       soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%x",
-                                        product_id >> 28 ?
-                                        product_id >> 16 : product_id >> 8);
-       soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c%d",
-                                        ((product_id & 0xf0) >> 4) + 'A',
-                                          product_id & 0xf);
-
-       soc_dev = soc_device_register(soc_dev_attr);
-       if (IS_ERR(soc_dev)) {
-               kfree(soc_dev_attr->family);
-               kfree(soc_dev_attr->soc_id);
-               kfree(soc_dev_attr->revision);
-               kfree(soc_dev_attr);
-               ret = -ENODEV;
-               goto out;
-       }
-
-       return 0;
-
-out:
-       iounmap(sun_top_ctrl_base);
-       return ret;
-}
-arch_initcall(brcmstb_soc_device_init);
index 151fcd3..cd85cd5 100644 (file)
@@ -5,3 +5,4 @@ obj-$(CONFIG_ARCH_R8A7791)      += rcar-sysc.o r8a7791-sysc.o
 obj-$(CONFIG_ARCH_R8A7793)     += rcar-sysc.o r8a7791-sysc.o
 obj-$(CONFIG_ARCH_R8A7794)     += rcar-sysc.o r8a7794-sysc.o
 obj-$(CONFIG_ARCH_R8A7795)     += rcar-sysc.o r8a7795-sysc.o
+obj-$(CONFIG_ARCH_R8A7796)     += rcar-sysc.o r8a7796-sysc.o
diff --git a/drivers/soc/renesas/r8a7796-sysc.c b/drivers/soc/renesas/r8a7796-sysc.c
new file mode 100644 (file)
index 0000000..f700c84
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Renesas R-Car M3-W System Controller
+ *
+ * Copyright (C) 2016 Glider bvba
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/bug.h>
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a7796-sysc.h>
+
+#include "rcar-sysc.h"
+
+static const struct rcar_sysc_area r8a7796_areas[] __initconst = {
+       { "always-on",      0, 0, R8A7796_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "ca57-scu",   0x1c0, 0, R8A7796_PD_CA57_SCU,  R8A7796_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca57-cpu0",   0x80, 0, R8A7796_PD_CA57_CPU0, R8A7796_PD_CA57_SCU,
+         PD_CPU_NOCR },
+       { "ca57-cpu1",   0x80, 1, R8A7796_PD_CA57_CPU1, R8A7796_PD_CA57_SCU,
+         PD_CPU_NOCR },
+       { "ca53-scu",   0x140, 0, R8A7796_PD_CA53_SCU,  R8A7796_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca53-cpu0",  0x200, 0, R8A7796_PD_CA53_CPU0, R8A7796_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "ca53-cpu1",  0x200, 1, R8A7796_PD_CA53_CPU1, R8A7796_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "ca53-cpu2",  0x200, 2, R8A7796_PD_CA53_CPU2, R8A7796_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "ca53-cpu3",  0x200, 3, R8A7796_PD_CA53_CPU3, R8A7796_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "cr7",        0x240, 0, R8A7796_PD_CR7,       R8A7796_PD_ALWAYS_ON },
+       { "a3vc",       0x380, 0, R8A7796_PD_A3VC,      R8A7796_PD_ALWAYS_ON },
+       { "a2vc0",      0x3c0, 0, R8A7796_PD_A2VC0,     R8A7796_PD_A3VC },
+       { "a2vc1",      0x3c0, 1, R8A7796_PD_A2VC1,     R8A7796_PD_A3VC },
+       { "3dg-a",      0x100, 0, R8A7796_PD_3DG_A,     R8A7796_PD_ALWAYS_ON },
+       { "3dg-b",      0x100, 1, R8A7796_PD_3DG_B,     R8A7796_PD_3DG_A },
+       { "a3ir",       0x180, 0, R8A7796_PD_A3IR,      R8A7796_PD_ALWAYS_ON },
+};
+
+const struct rcar_sysc_info r8a7796_sysc_info __initconst = {
+       .areas = r8a7796_areas,
+       .num_areas = ARRAY_SIZE(r8a7796_areas),
+};
index 79dbc77..fc997d4 100644 (file)
@@ -302,6 +302,9 @@ static const struct of_device_id rcar_sysc_matches[] = {
 #endif
 #ifdef CONFIG_ARCH_R8A7795
        { .compatible = "renesas,r8a7795-sysc", .data = &r8a7795_sysc_info },
+#endif
+#ifdef CONFIG_ARCH_R8A7796
+       { .compatible = "renesas,r8a7796-sysc", .data = &r8a7796_sysc_info },
 #endif
        { /* sentinel */ }
 };
index 5e76617..4ac3d7b 100644 (file)
@@ -55,4 +55,5 @@ extern const struct rcar_sysc_info r8a7790_sysc_info;
 extern const struct rcar_sysc_info r8a7791_sysc_info;
 extern const struct rcar_sysc_info r8a7794_sysc_info;
 extern const struct rcar_sysc_info r8a7795_sysc_info;
+extern const struct rcar_sysc_info r8a7796_sysc_info;
 #endif /* __SOC_RENESAS_RCAR_SYSC_H__ */
index d7fc123..2455339 100644 (file)
@@ -10,4 +10,8 @@ config EXYNOS_PMU
        bool "Exynos PMU controller driver" if COMPILE_TEST
        depends on (ARM && ARCH_EXYNOS) || ((ARM || ARM64) && COMPILE_TEST)
 
+config EXYNOS_PM_DOMAINS
+       bool "Exynos PM domains" if COMPILE_TEST
+       depends on PM_GENERIC_DOMAINS || COMPILE_TEST
+
 endif
index f64ac4d..3619f2e 100644 (file)
@@ -1,2 +1,3 @@
 obj-$(CONFIG_EXYNOS_PMU)       += exynos-pmu.o exynos3250-pmu.o exynos4-pmu.o \
                                        exynos5250-pmu.o exynos5420-pmu.o
+obj-$(CONFIG_EXYNOS_PM_DOMAINS) += pm_domains.o
diff --git a/drivers/soc/samsung/pm_domains.c b/drivers/soc/samsung/pm_domains.c
new file mode 100644 (file)
index 0000000..f60515e
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Exynos Generic power domain support.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Implementation of Exynos specific power domain control which is used in
+ * conjunction with runtime-pm. Support for both device-tree and non-device-tree
+ * based power domain support is included.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/pm_domain.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/sched.h>
+
+#define MAX_CLK_PER_DOMAIN     4
+
+struct exynos_pm_domain_config {
+       /* Value for LOCAL_PWR_CFG and STATUS fields for each domain */
+       u32 local_pwr_cfg;
+};
+
+/*
+ * Exynos specific wrapper around the generic power domain
+ */
+struct exynos_pm_domain {
+       void __iomem *base;
+       char const *name;
+       bool is_off;
+       struct generic_pm_domain pd;
+       struct clk *oscclk;
+       struct clk *clk[MAX_CLK_PER_DOMAIN];
+       struct clk *pclk[MAX_CLK_PER_DOMAIN];
+       struct clk *asb_clk[MAX_CLK_PER_DOMAIN];
+       u32 local_pwr_cfg;
+};
+
+static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
+{
+       struct exynos_pm_domain *pd;
+       void __iomem *base;
+       u32 timeout, pwr;
+       char *op;
+       int i;
+
+       pd = container_of(domain, struct exynos_pm_domain, pd);
+       base = pd->base;
+
+       for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
+               if (IS_ERR(pd->asb_clk[i]))
+                       break;
+               clk_prepare_enable(pd->asb_clk[i]);
+       }
+
+       /* Set oscclk before powering off a domain*/
+       if (!power_on) {
+               for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
+                       if (IS_ERR(pd->clk[i]))
+                               break;
+                       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);
+               }
+       }
+
+       pwr = power_on ? pd->local_pwr_cfg : 0;
+       __raw_writel(pwr, base);
+
+       /* Wait max 1ms */
+       timeout = 10;
+
+       while ((__raw_readl(base + 0x4) & pd->local_pwr_cfg) != pwr) {
+               if (!timeout) {
+                       op = (power_on) ? "enable" : "disable";
+                       pr_err("Power domain %s %s failed\n", domain->name, op);
+                       return -ETIMEDOUT;
+               }
+               timeout--;
+               cpu_relax();
+               usleep_range(80, 100);
+       }
+
+       /* Restore clocks after powering on a domain*/
+       if (power_on) {
+               for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
+                       if (IS_ERR(pd->clk[i]))
+                               break;
+
+                       if (IS_ERR(pd->pclk[i]))
+                               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);
+               }
+       }
+
+       for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
+               if (IS_ERR(pd->asb_clk[i]))
+                       break;
+               clk_disable_unprepare(pd->asb_clk[i]);
+       }
+
+       return 0;
+}
+
+static int exynos_pd_power_on(struct generic_pm_domain *domain)
+{
+       return exynos_pd_power(domain, true);
+}
+
+static int exynos_pd_power_off(struct generic_pm_domain *domain)
+{
+       return exynos_pd_power(domain, false);
+}
+
+static const struct exynos_pm_domain_config exynos4210_cfg __initconst = {
+       .local_pwr_cfg          = 0x7,
+};
+
+static const struct of_device_id exynos_pm_domain_of_match[] __initconst = {
+       {
+               .compatible = "samsung,exynos4210-pd",
+               .data = &exynos4210_cfg,
+       },
+       { },
+};
+
+static __init int exynos4_pm_init_power_domain(void)
+{
+       struct device_node *np;
+       const struct of_device_id *match;
+
+       for_each_matching_node_and_match(np, exynos_pm_domain_of_match, &match) {
+               const struct exynos_pm_domain_config *pm_domain_cfg;
+               struct exynos_pm_domain *pd;
+               int on, i;
+
+               pm_domain_cfg = match->data;
+
+               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);
+               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__);
+                       kfree_const(pd->pd.name);
+                       kfree(pd);
+                       continue;
+               }
+
+               pd->pd.power_off = exynos_pd_power_off;
+               pd->pd.power_on = exynos_pd_power_on;
+               pd->local_pwr_cfg = pm_domain_cfg->local_pwr_cfg;
+
+               for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
+                       char clk_name[8];
+
+                       snprintf(clk_name, sizeof(clk_name), "asb%d", i);
+                       pd->asb_clk[i] = of_clk_get_by_name(np, clk_name);
+                       if (IS_ERR(pd->asb_clk[i]))
+                               break;
+               }
+
+               pd->oscclk = of_clk_get_by_name(np, "oscclk");
+               if (IS_ERR(pd->oscclk))
+                       goto no_clk;
+
+               for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
+                       char clk_name[8];
+
+                       snprintf(clk_name, sizeof(clk_name), "clk%d", i);
+                       pd->clk[i] = of_clk_get_by_name(np, clk_name);
+                       if (IS_ERR(pd->clk[i]))
+                               break;
+                       /*
+                        * Skip setting parent on first power up.
+                        * The parent at this time may not be useful at all.
+                        */
+                       pd->pclk[i] = ERR_PTR(-EINVAL);
+               }
+
+               if (IS_ERR(pd->clk[0]))
+                       clk_put(pd->oscclk);
+
+no_clk:
+               on = __raw_readl(pd->base + 0x4) & pd->local_pwr_cfg;
+
+               pm_genpd_init(&pd->pd, NULL, !on);
+               of_genpd_add_provider_simple(np, &pd->pd);
+       }
+
+       /* Assign the child power domains to their parents */
+       for_each_matching_node(np, exynos_pm_domain_of_match) {
+               struct generic_pm_domain *child_domain, *parent_domain;
+               struct of_phandle_args args;
+
+               args.np = np;
+               args.args_count = 0;
+               child_domain = of_genpd_get_from_provider(&args);
+               if (IS_ERR(child_domain))
+                       continue;
+
+               if (of_parse_phandle_with_args(np, "power-domains",
+                                        "#power-domain-cells", 0, &args) != 0)
+                       continue;
+
+               parent_domain = of_genpd_get_from_provider(&args);
+               if (IS_ERR(parent_domain))
+                       continue;
+
+               if (pm_genpd_add_subdomain(parent_domain, child_domain))
+                       pr_warn("%s failed to add subdomain: %s\n",
+                               parent_domain->name, child_domain->name);
+               else
+                       pr_info("%s has as child subdomain: %s.\n",
+                               parent_domain->name, child_domain->name);
+       }
+
+       return 0;
+}
+core_initcall(exynos4_pm_init_power_domain);
diff --git a/include/dt-bindings/power/r8a7796-sysc.h b/include/dt-bindings/power/r8a7796-sysc.h
new file mode 100644 (file)
index 0000000..5b4daab
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 Glider bvba
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+#ifndef __DT_BINDINGS_POWER_R8A7796_SYSC_H__
+#define __DT_BINDINGS_POWER_R8A7796_SYSC_H__
+
+/*
+ * These power domain indices match the numbers of the interrupt bits
+ * representing the power areas in the various Interrupt Registers
+ * (e.g. SYSCISR, Interrupt Status Register)
+ */
+
+#define R8A7796_PD_CA57_CPU0            0
+#define R8A7796_PD_CA57_CPU1            1
+#define R8A7796_PD_CA53_CPU0            5
+#define R8A7796_PD_CA53_CPU1            6
+#define R8A7796_PD_CA53_CPU2            7
+#define R8A7796_PD_CA53_CPU3            8
+#define R8A7796_PD_CA57_SCU            12
+#define R8A7796_PD_CR7                 13
+#define R8A7796_PD_A3VC                        14
+#define R8A7796_PD_3DG_A               17
+#define R8A7796_PD_3DG_B               18
+#define R8A7796_PD_CA53_SCU            21
+#define R8A7796_PD_A3IR                        24
+#define R8A7796_PD_A2VC0               25
+#define R8A7796_PD_A2VC1               26
+
+/* Always-on power area */
+#define R8A7796_PD_ALWAYS_ON           32
+
+#endif /* __DT_BINDINGS_POWER_R8A7796_SYSC_H__ */
diff --git a/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h b/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h
new file mode 100644 (file)
index 0000000..524d607
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _DT_BINDINGS_AMLOGIC_MESON_GXBB_RESET_H
+#define _DT_BINDINGS_AMLOGIC_MESON_GXBB_RESET_H
+
+/*     RESET0                                  */
+#define RESET_HIU                      0
+/*                                     1       */
+#define RESET_DOS_RESET                        2
+#define RESET_DDR_TOP                  3
+#define RESET_DCU_RESET                        4
+#define RESET_VIU                      5
+#define RESET_AIU                      6
+#define RESET_VID_PLL_DIV              7
+/*                                     8       */
+#define RESET_PMUX                     9
+#define RESET_VENC                     10
+#define RESET_ASSIST                   11
+#define RESET_AFIFO2                   12
+#define RESET_VCBUS                    13
+/*                                     14      */
+/*                                     15      */
+#define RESET_GIC                      16
+#define RESET_CAPB3_DECODE             17
+#define RESET_NAND_CAPB3               18
+#define RESET_HDMITX_CAPB3             19
+#define RESET_MALI_CAPB3               20
+#define RESET_DOS_CAPB3                        21
+#define RESET_SYS_CPU_CAPB3            22
+#define RESET_CBUS_CAPB3               23
+#define RESET_AHB_CNTL                 24
+#define RESET_AHB_DATA                 25
+#define RESET_VCBUS_CLK81              26
+#define RESET_MMC                      27
+#define RESET_MIPI_0                   28
+#define RESET_MIPI_1                   29
+#define RESET_MIPI_2                   30
+#define RESET_MIPI_3                   31
+/*     RESET1                                  */
+#define RESET_CPPM                     32
+#define RESET_DEMUX                    33
+#define RESET_USB_OTG                  34
+#define RESET_DDR                      35
+#define RESET_AO_RESET                 36
+#define RESET_BT656                    37
+#define RESET_AHB_SRAM                 38
+/*                                     39      */
+#define RESET_PARSER                   40
+#define RESET_BLKMV                    41
+#define RESET_ISA                      42
+#define RESET_ETHERNET                 43
+#define RESET_SD_EMMC_A                        44
+#define RESET_SD_EMMC_B                        45
+#define RESET_SD_EMMC_C                        46
+#define RESET_ROM_BOOT                 47
+#define RESET_SYS_CPU_0                        48
+#define RESET_SYS_CPU_1                        49
+#define RESET_SYS_CPU_2                        50
+#define RESET_SYS_CPU_3                        51
+#define RESET_SYS_CPU_CORE_0           52
+#define RESET_SYS_CPU_CORE_1           53
+#define RESET_SYS_CPU_CORE_2           54
+#define RESET_SYS_CPU_CORE_3           55
+#define RESET_SYS_PLL_DIV              56
+#define RESET_SYS_CPU_AXI              57
+#define RESET_SYS_CPU_L2               58
+#define RESET_SYS_CPU_P                        59
+#define RESET_SYS_CPU_MBIST            60
+/*                                     61      */
+/*                                     62      */
+/*                                     63      */
+/*     RESET2                                  */
+#define RESET_VD_RMEM                  64
+#define RESET_AUDIN                    65
+#define RESET_HDMI_TX                  66
+/*                                     67      */
+/*                                     68      */
+/*                                     69      */
+#define RESET_GE2D                     70
+#define RESET_PARSER_REG               71
+#define RESET_PARSER_FETCH             72
+#define RESET_PARSER_CTL               73
+#define RESET_PARSER_TOP               74
+/*                                     75      */
+/*                                     76      */
+#define RESET_AO_CPU_RESET             77
+#define RESET_MALI                     78
+#define RESET_HDMI_SYSTEM_RESET                79
+/*                                     80-95   */
+/*     RESET3                                  */
+#define RESET_RING_OSCILLATOR          96
+#define RESET_SYS_CPU                  97
+#define RESET_EFUSE                    98
+#define RESET_SYS_CPU_BVCI             99
+#define RESET_AIFIFO                   100
+#define RESET_TVFE                     101
+#define RESET_AHB_BRIDGE_CNTL          102
+/*                                     103     */
+#define RESET_AUDIO_DAC                        104
+#define RESET_DEMUX_TOP                        105
+#define RESET_DEMUX_DES                        106
+#define RESET_DEMUX_S2P_0              107
+#define RESET_DEMUX_S2P_1              108
+#define RESET_DEMUX_RESET_0            109
+#define RESET_DEMUX_RESET_1            110
+#define RESET_DEMUX_RESET_2            111
+/*                                     112-127 */
+/*     RESET4                                  */
+/*                                     128     */
+/*                                     129     */
+/*                                     130     */
+/*                                     131     */
+#define RESET_DVIN_RESET               132
+#define RESET_RDMA                     133
+#define RESET_VENCI                    134
+#define RESET_VENCP                    135
+/*                                     136     */
+#define RESET_VDAC                     137
+#define RESET_RTC                      138
+/*                                     139     */
+#define RESET_VDI6                     140
+#define RESET_VENCL                    141
+#define RESET_I2C_MASTER_2             142
+#define RESET_I2C_MASTER_1             143
+/*                                     144-159 */
+/*     RESET5                                  */
+/*                                     160-191 */
+/*     RESET6                                  */
+#define RESET_PERIPHS_GENERAL          192
+#define RESET_PERIPHS_SPICC            193
+#define RESET_PERIPHS_SMART_CARD       194
+#define RESET_PERIPHS_SAR_ADC          195
+#define RESET_PERIPHS_I2C_MASTER_0     196
+#define RESET_SANA                     197
+/*                                     198     */
+#define RESET_PERIPHS_STREAM_INTERFACE 199
+#define RESET_PERIPHS_SDIO             200
+#define RESET_PERIPHS_UART_0           201
+#define RESET_PERIPHS_UART_1_2         202
+#define RESET_PERIPHS_ASYNC_0          203
+#define RESET_PERIPHS_ASYNC_1          204
+#define RESET_PERIPHS_SPI_0            205
+#define RESET_PERIPHS_SDHC             206
+#define RESET_UART_SLIP                        207
+/*                                     208-223 */
+/*     RESET7                                  */
+#define RESET_USB_DDR_0                        224
+#define RESET_USB_DDR_1                        225
+#define RESET_USB_DDR_2                        226
+#define RESET_USB_DDR_3                        227
+/*                                     228     */
+#define RESET_DEVICE_MMC_ARB           229
+/*                                     230     */
+#define RESET_VID_LOCK                 231
+#define RESET_A9_DMC_PIPEL             232
+/*                                     233-255 */
+
+#endif
diff --git a/include/dt-bindings/reset/amlogic,meson8b-reset.h b/include/dt-bindings/reset/amlogic,meson8b-reset.h
new file mode 100644 (file)
index 0000000..614aff2
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _DT_BINDINGS_AMLOGIC_MESON8B_RESET_H
+#define _DT_BINDINGS_AMLOGIC_MESON8B_RESET_H
+
+/*     RESET0                                  */
+#define RESET_HIU                      0
+#define RESET_VLD                      1
+#define RESET_IQIDCT                   2
+#define RESET_MC                       3
+/*                                     8       */
+#define RESET_VIU                      5
+#define RESET_AIU                      6
+#define RESET_MCPU                     7
+#define RESET_CCPU                     8
+#define RESET_PMUX                     9
+#define RESET_VENC                     10
+#define RESET_ASSIST                   11
+#define RESET_AFIFO2                   12
+#define RESET_MDEC                     13
+#define RESET_VLD_PART                 14
+#define RESET_VIFIFO                   15
+/*                                     16-31   */
+/*     RESET1                                  */
+/*                                     32      */
+#define RESET_DEMUX                    33
+#define RESET_USB_OTG                  34
+#define RESET_DDR                      35
+#define RESET_VDAC_1                   36
+#define RESET_BT656                    37
+#define RESET_AHB_SRAM                 38
+#define RESET_AHB_BRIDGE               39
+#define RESET_PARSER                   40
+#define RESET_BLKMV                    41
+#define RESET_ISA                      42
+#define RESET_ETHERNET                 43
+#define RESET_ABUF                     44
+#define RESET_AHB_DATA                 45
+#define RESET_AHB_CNTL                 46
+#define RESET_ROM_BOOT                 47
+/*                                     48-63   */
+/*     RESET2                                  */
+#define RESET_VD_RMEM                  64
+#define RESET_AUDIN                    65
+#define RESET_DBLK                     66
+#define RESET_PIC_DC                   66
+#define RESET_PSC                      66
+#define RESET_NAND                     66
+#define RESET_GE2D                     70
+#define RESET_PARSER_REG               71
+#define RESET_PARSER_FETCH             72
+#define RESET_PARSER_CTL               73
+#define RESET_PARSER_TOP               74
+#define RESET_HDMI_APB                 75
+#define RESET_AUDIO_APB                        76
+#define RESET_MEDIA_CPU                        77
+#define RESET_MALI                     78
+#define RESET_HDMI_SYSTEM_RESET                79
+/*                                     80-95   */
+/*     RESET3                                  */
+#define RESET_RING_OSCILLATOR          96
+#define RESET_SYS_CPU_0                        97
+#define RESET_EFUSE                    98
+#define RESET_SYS_CPU_BVCI             99
+#define RESET_AIFIFO                   100
+#define RESET_AUDIO_PLL_MODULATOR      101
+#define RESET_AHB_BRIDGE_CNTL          102
+#define RESET_SYS_CPU_1                        103
+#define RESET_AUDIO_DAC                        104
+#define RESET_DEMUX_TOP                        105
+#define RESET_DEMUX_DES                        106
+#define RESET_DEMUX_S2P_0              107
+#define RESET_DEMUX_S2P_1              108
+#define RESET_DEMUX_RESET_0            109
+#define RESET_DEMUX_RESET_1            110
+#define RESET_DEMUX_RESET_2            111
+/*                                     112-127 */
+/*     RESET4                                  */
+#define RESET_PL310                    128
+#define RESET_A5_APB                   129
+#define RESET_A5_AXI                   130
+#define RESET_A5                       131
+#define RESET_DVIN                     132
+#define RESET_RDMA                     133
+#define RESET_VENCI                    134
+#define RESET_VENCP                    135
+#define RESET_VENCT                    136
+#define RESET_VDAC_4                   137
+#define RESET_RTC                      138
+#define RESET_A5_DEBUG                 139
+#define RESET_VDI6                     140
+#define RESET_VENCL                    141
+/*                                     142-159 */
+/*     RESET5                                  */
+#define RESET_DDR_PLL                  160
+#define RESET_MISC_PLL                 161
+#define RESET_SYS_PLL                  162
+#define RESET_HPLL_PLL                 163
+#define RESET_AUDIO_PLL                        164
+#define RESET_VID2_PLL                 165
+/*                                     166-191 */
+/*     RESET6                                  */
+#define RESET_PERIPHS_GENERAL          192
+#define RESET_PERIPHS_IR_REMOTE                193
+#define RESET_PERIPHS_SMART_CARD       194
+#define RESET_PERIPHS_SAR_ADC          195
+#define RESET_PERIPHS_I2C_MASTER_0     196
+#define RESET_PERIPHS_I2C_MASTER_1     197
+#define RESET_PERIPHS_I2C_SLAVE                198
+#define RESET_PERIPHS_STREAM_INTERFACE 199
+#define RESET_PERIPHS_SDIO             200
+#define RESET_PERIPHS_UART_0           201
+#define RESET_PERIPHS_UART_1           202
+#define RESET_PERIPHS_ASYNC_0          203
+#define RESET_PERIPHS_ASYNC_1          204
+#define RESET_PERIPHS_SPI_0            205
+#define RESET_PERIPHS_SPI_1            206
+#define RESET_PERIPHS_LED_PWM          207
+/*                                     208-223 */
+/*     RESET7                                  */
+/*                                     224-255 */
+
+#endif
index ad2f670..1779cda 100644 (file)
@@ -1,7 +1,8 @@
 #ifndef __OF_RESERVED_MEM_H
 #define __OF_RESERVED_MEM_H
 
-struct device;
+#include <linux/device.h>
+
 struct of_phandle_args;
 struct reserved_mem_ops;
 
@@ -28,14 +29,17 @@ typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem);
        _OF_DECLARE(reservedmem, name, compat, init, reservedmem_of_init_fn)
 
 #ifdef CONFIG_OF_RESERVED_MEM
-int of_reserved_mem_device_init(struct device *dev);
+
+int of_reserved_mem_device_init_by_idx(struct device *dev,
+                                      struct device_node *np, int idx);
 void of_reserved_mem_device_release(struct device *dev);
 
 void fdt_init_reserved_mem(void);
 void fdt_reserved_mem_save_node(unsigned long node, const char *uname,
                               phys_addr_t base, phys_addr_t size);
 #else
-static inline int of_reserved_mem_device_init(struct device *dev)
+static inline int of_reserved_mem_device_init_by_idx(struct device *dev,
+                                       struct device_node *np, int idx)
 {
        return -ENOSYS;
 }
@@ -46,4 +50,19 @@ static inline void fdt_reserved_mem_save_node(unsigned long node,
                const char *uname, phys_addr_t base, phys_addr_t size) { }
 #endif
 
+/**
+ * of_reserved_mem_device_init() - assign reserved memory region to given device
+ * @dev:       Pointer to the device to configure
+ *
+ * This function assigns respective DMA-mapping operations based on the first
+ * reserved memory region specified by 'memory-region' property in device tree
+ * node of the given device.
+ *
+ * Returns error code or zero on success.
+ */
+static inline int of_reserved_mem_device_init(struct device *dev)
+{
+       return of_reserved_mem_device_init_by_idx(dev, dev->of_node, 0);
+}
+
 #endif /* __OF_RESERVED_MEM_H */
index b91ba93..db1fe67 100644 (file)
@@ -53,4 +53,8 @@ struct reset_controller_dev {
 int reset_controller_register(struct reset_controller_dev *rcdev);
 void reset_controller_unregister(struct reset_controller_dev *rcdev);
 
+struct device;
+int devm_reset_controller_register(struct device *dev,
+                                  struct reset_controller_dev *rcdev);
+
 #endif
index ec0306c..067db57 100644 (file)
@@ -71,14 +71,14 @@ static inline struct reset_control *__of_reset_control_get(
                                        struct device_node *node,
                                        const char *id, int index, int shared)
 {
-       return ERR_PTR(-EINVAL);
+       return ERR_PTR(-ENOTSUPP);
 }
 
 static inline struct reset_control *__devm_reset_control_get(
                                        struct device *dev,
                                        const char *id, int index, int shared)
 {
-       return ERR_PTR(-EINVAL);
+       return ERR_PTR(-ENOTSUPP);
 }
 
 #endif /* CONFIG_RESET_CONTROLLER */
index 2087c9a..f7dc840 100644 (file)
@@ -35,6 +35,8 @@ static inline void *vb2_dma_contig_init_ctx(struct device *dev)
 }
 
 void vb2_dma_contig_cleanup_ctx(void *alloc_ctx);
+int vb2_dma_contig_set_max_seg_size(struct device *dev, unsigned int size);
+void vb2_dma_contig_clear_max_seg_size(struct device *dev);
 
 extern const struct vb2_mem_ops vb2_dma_contig_memops;