Merge tag 'samsung-drivers-exynos-mfc-4.8-2' of git://git.kernel.org/pub/scm/linux...
authorOlof Johansson <olof@lixom.net>
Wed, 6 Jul 2016 05:46:39 +0000 (22:46 -0700)
committerOlof Johansson <olof@lixom.net>
Wed, 6 Jul 2016 05:46:39 +0000 (22:46 -0700)
Topic branch for Exynos MFC changes for v4.8, part 2:

Replace hardcoded reserved memory ranges with auto-allocated ones
and enable MFC for all boards.

* tag 'samsung-drivers-exynos-mfc-4.8-2' of git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux:
  ARM: dts: exynos: enable MFC device for all boards
  ARM: dts: exynos: move MFC reserved memory regions from boards to .dtsi
  ARM: dts: exynos: replace hardcoded reserved memory ranges with auto-allocated ones
  ARM: dts: exynos: Enable MFC device on Exynos4412 Odroid boards
  ARM: dts: exynos: Convert MFC device to generic reserved memory bindings
  ARM: EXYNOS: Remove code for MFC custom reserved memory handling
  media: s5p-mfc: add iommu support
  media: s5p-mfc: replace custom reserved memory handling code with generic one
  media: s5p-mfc: use generic reserved memory bindings
  of: reserved_mem: add support for using more than one region for given device
  media: set proper max seg size for devices on Exynos SoCs
  media: vb2-dma-contig: add helper for setting dma max seg size
  s5p-mfc: Fix race between s5p_mfc_probe() and s5p_mfc_open()
  s5p-mfc: Add release callback for memory region devs
  s5p-mfc: Set device name for reserved memory region devs

Signed-off-by: Olof Johansson <olof@lixom.net>
1  2 
arch/arm/boot/dts/exynos4412-odroid-common.dtsi
arch/arm/boot/dts/exynos4412-origen.dts
arch/arm/boot/dts/exynos5420-peach-pit.dts
arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
arch/arm/boot/dts/exynos5800-peach-pi.dts
drivers/of/of_reserved_mem.c
include/linux/of_reserved_mem.h

@@@ -13,6 -13,7 +13,7 @@@
  #include "exynos4412.dtsi"
  #include "exynos4412-ppmu-common.dtsi"
  #include <dt-bindings/gpio/gpio.h>
+ #include "exynos-mfc-reserved-memory.dtsi"
  
  / {
        chosen {
                                regulator-name = "VDDQ_MMC2_2.8V";
                                regulator-min-microvolt = <2800000>;
                                regulator-max-microvolt = <2800000>;
 -                              regulator-always-on;
                                regulator-boot-on;
                        };
  
                        };
  
                        ldo21_reg: LDO21 {
 -                              regulator-name = "LDO21_3.3V";
 -                              regulator-min-microvolt = <3300000>;
 -                              regulator-max-microvolt = <3300000>;
 -                              regulator-always-on;
 +                              regulator-name = "TFLASH_2.8V";
 +                              regulator-min-microvolt = <2800000>;
 +                              regulator-max-microvolt = <2800000>;
 +                              regulator-boot-on;
 +                      };
 +
 +                      ldo22_reg: LDO22 {
 +                              /*
 +                               * Only U3 uses it, so let it define the
 +                               * constraints
 +                               */
 +                              regulator-name = "LDO22";
                                regulator-boot-on;
                        };
  
                        };
  
                        buck8_reg: BUCK8 {
 +                              /*
 +                               * Constraints set by specific board: X,
 +                               * X2 and U3.
 +                               */
                                regulator-name = "BUCK8_2.8V";
 -                              regulator-min-microvolt = <2800000>;
 -                              regulator-max-microvolt = <2800000>;
                        };
                };
        };
  &mshc_0 {
        pinctrl-0 = <&sd4_clk &sd4_cmd &sd4_bus4 &sd4_bus8>;
        pinctrl-names = "default";
 -      vmmc-supply = <&ldo20_reg &buck8_reg>;
 +      vmmc-supply = <&ldo20_reg>;
        mmc-pwrseq = <&emmc_pwrseq>;
        status = "okay";
  
        bus-width = <4>;
        pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
        pinctrl-names = "default";
 -      vmmc-supply = <&ldo4_reg &ldo21_reg>;
 +      vmmc-supply = <&ldo21_reg>;
 +      vqmmc-supply = <&ldo4_reg>;
        cd-gpios = <&gpk2 2 GPIO_ACTIVE_HIGH>;
        cd-inverted;
        status = "okay";
@@@ -16,6 -16,7 +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";
        cpu0-supply = <&buck2_reg>;
  };
  
 +&exynos_usbphy {
 +      status = "okay";
 +};
 +
 +&ehci {
 +      samsung,vbus-gpio = <&gpx3 5 1>;
 +      status = "okay";
 +
 +      port@1{
 +              status = "okay";
 +      };
 +      port@2 {
 +              status = "okay";
 +      };
 +};
 +
  &fimd {
        pinctrl-0 = <&lcd_clk &lcd_data24 &pwm1_out>;
        pinctrl-names = "default";
        };
  };
  
- &mfc {
-       samsung,mfc-r = <0x43000000 0x800000>;
-       samsung,mfc-l = <0x51000000 0x800000>;
-       status = "okay";
- };
  &mshc_0 {
        pinctrl-0 = <&sd4_clk &sd4_cmd &sd4_bus4 &sd4_bus8>;
        pinctrl-names = "default";
@@@ -16,6 -16,7 +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+";
                                regulator-name = "vdd_1v2";
                                regulator-min-microvolt = <1200000>;
                                regulator-max-microvolt = <1200000>;
 -                              regulator-always-on;
                                regulator-boot-on;
                                regulator-state-mem {
                                        regulator-off-in-suspend;
                                regulator-name = "vdd_1v35";
                                regulator-min-microvolt = <1350000>;
                                regulator-max-microvolt = <1350000>;
 -                              regulator-always-on;
                                regulator-boot-on;
                                regulator-state-mem {
                                        regulator-on-in-suspend;
                                regulator-name = "vdd_2v";
                                regulator-min-microvolt = <2000000>;
                                regulator-max-microvolt = <2000000>;
 -                              regulator-always-on;
                                regulator-boot-on;
                                regulator-state-mem {
                                        regulator-on-in-suspend;
                                regulator-name = "vdd_1v8";
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <1800000>;
 -                              regulator-always-on;
                                regulator-boot-on;
                                regulator-state-mem {
                                        regulator-on-in-suspend;
                                regulator-name = "vdd_ldo9";
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <1800000>;
 -                              regulator-always-on;
                                regulator-state-mem {
                                        regulator-on-in-suspend;
                                        regulator-mode = <MAX77802_OPMODE_LP>;
                                regulator-name = "vdd_ldo10";
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <1800000>;
 -                              regulator-always-on;
                                regulator-state-mem {
                                        regulator-off-in-suspend;
                                };
        status = "okay";
  };
  
- &mfc {
-       samsung,mfc-r = <0x43000000 0x800000>;
-       samsung,mfc-l = <0x51000000 0x800000>;
- };
  &mmc_0 {
        status = "okay";
        num-slots = <1>;
        status = "okay";
  };
  
 +&tmu_cpu0 {
 +      vtmu-supply = <&ldo10_reg>;
 +};
 +
 +&tmu_cpu1 {
 +      vtmu-supply = <&ldo10_reg>;
 +};
 +
 +&tmu_cpu2 {
 +      vtmu-supply = <&ldo10_reg>;
 +};
 +
 +&tmu_cpu3 {
 +      vtmu-supply = <&ldo10_reg>;
 +};
 +
 +&tmu_gpu {
 +      vtmu-supply = <&ldo10_reg>;
 +};
 +
  &usbdrd_dwc3_0 {
        dr_mode = "host";
  };
@@@ -1,11 -1,9 +1,11 @@@
  /*
   * Hardkernel Odroid XU3 board device tree source
   *
 - * Copyright (c) 2014 Collabora Ltd.
   * Copyright (c) 2013 Samsung Electronics Co., Ltd.
   *            http://www.samsung.com
 + * Copyright (c) 2014 Collabora Ltd.
 + * Copyright (c) 2015 Lukasz Majewski <l.majewski@samsung.com>
 + *                    Anand Moon <linux.amoon@gmail.com>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
@@@ -18,6 -16,8 +18,7 @@@
  #include <dt-bindings/sound/samsung-i2s.h>
  #include "exynos5800.dtsi"
  #include "exynos5422-cpus.dtsi"
 -#include "exynos5422-cpu-thermal.dtsi"
+ #include "exynos-mfc-reserved-memory.dtsi"
  
  / {
        memory {
                #cooling-cells = <2>;
                cooling-levels = <0 130 170 230>;
        };
 +
 +      thermal-zones {
 +              cpu0_thermal: cpu0-thermal {
 +                      thermal-sensors = <&tmu_cpu0 0>;
 +                      polling-delay-passive = <250>;
 +                      polling-delay = <0>;
 +                      trips {
 +                              cpu_alert0: cpu-alert-0 {
 +                                      temperature = <50000>; /* millicelsius */
 +                                      hysteresis = <5000>; /* millicelsius */
 +                                      type = "active";
 +                              };
 +                              cpu_alert1: cpu-alert-1 {
 +                                      temperature = <60000>; /* millicelsius */
 +                                      hysteresis = <5000>; /* millicelsius */
 +                                      type = "active";
 +                              };
 +                              cpu_alert2: cpu-alert-2 {
 +                                      temperature = <70000>; /* millicelsius */
 +                                      hysteresis = <5000>; /* millicelsius */
 +                                      type = "active";
 +                              };
 +                              cpu_crit0: cpu-crit-0 {
 +                                      temperature = <120000>; /* millicelsius */
 +                                      hysteresis = <0>; /* millicelsius */
 +                                      type = "critical";
 +                              };
 +                              /*
 +                               * Exynos542x supports only 4 trip-points
 +                               * so for these polling mode is required.
 +                               * Start polling at temperature level of last
 +                               * interrupt-driven trip: cpu_alert2
 +                               */
 +                              cpu_alert3: cpu-alert-3 {
 +                                      temperature = <70000>; /* millicelsius */
 +                                      hysteresis = <10000>; /* millicelsius */
 +                                      type = "passive";
 +                              };
 +                              cpu_alert4: cpu-alert-4 {
 +                                      temperature = <85000>; /* millicelsius */
 +                                      hysteresis = <10000>; /* millicelsius */
 +                                      type = "passive";
 +                              };
 +
 +                      };
 +                      cooling-maps {
 +                              map0 {
 +                                      trip = <&cpu_alert0>;
 +                                      cooling-device = <&fan0 0 1>;
 +                              };
 +                              map1 {
 +                                      trip = <&cpu_alert1>;
 +                                      cooling-device = <&fan0 1 2>;
 +                              };
 +                              map2 {
 +                                      trip = <&cpu_alert2>;
 +                                      cooling-device = <&fan0 2 3>;
 +                              };
 +                              /*
 +                               * When reaching cpu_alert3, reduce CPU
 +                               * by 2 steps. On Exynos5422/5800 that would
 +                               * be: 1600 MHz and 1100 MHz.
 +                               */
 +                              map3 {
 +                                      trip = <&cpu_alert3>;
 +                                      cooling-device = <&cpu0 0 2>;
 +                              };
 +                              map4 {
 +                                      trip = <&cpu_alert3>;
 +                                      cooling-device = <&cpu4 0 2>;
 +                              };
 +
 +                              /*
 +                               * When reaching cpu_alert4, reduce CPU
 +                               * further, down to 600 MHz (11 steps for big,
 +                               * 7 steps for LITTLE).
 +                               */
 +                              map5 {
 +                                      trip = <&cpu_alert4>;
 +                                      cooling-device = <&cpu0 3 7>;
 +                              };
 +                              map6 {
 +                                      trip = <&cpu_alert4>;
 +                                      cooling-device = <&cpu4 3 11>;
 +                              };
 +                      };
 +              };
 +      };
  };
  
  &bus_wcore {
        };
  };
  
- &mfc {
-       samsung,mfc-r = <0x43000000 0x800000>;
-       samsung,mfc-l = <0x51000000 0x800000>;
- };
  &mmc_0 {
        status = "okay";
        mmc-pwrseq = <&emmc_pwrseq>;
  
  &tmu_cpu0 {
        vtmu-supply = <&ldo7_reg>;
 -      status = "okay";
  };
  
  &tmu_cpu1 {
        vtmu-supply = <&ldo7_reg>;
 -      status = "okay";
  };
  
  &tmu_cpu2 {
        vtmu-supply = <&ldo7_reg>;
 -      status = "okay";
  };
  
  &tmu_cpu3 {
        vtmu-supply = <&ldo7_reg>;
 -      status = "okay";
  };
  
  &tmu_gpu {
        vtmu-supply = <&ldo7_reg>;
 -      status = "okay";
  };
  
  &rtc {
@@@ -16,6 -16,7 +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+";
                                regulator-name = "vdd_1v2";
                                regulator-min-microvolt = <1200000>;
                                regulator-max-microvolt = <1200000>;
 -                              regulator-always-on;
                                regulator-boot-on;
                                regulator-state-mem {
                                        regulator-off-in-suspend;
                                regulator-name = "vdd_1v35";
                                regulator-min-microvolt = <1350000>;
                                regulator-max-microvolt = <1350000>;
 -                              regulator-always-on;
                                regulator-boot-on;
                                regulator-state-mem {
                                        regulator-on-in-suspend;
                                regulator-name = "vdd_2v";
                                regulator-min-microvolt = <2000000>;
                                regulator-max-microvolt = <2000000>;
 -                              regulator-always-on;
                                regulator-boot-on;
                                regulator-state-mem {
                                        regulator-on-in-suspend;
                                regulator-name = "vdd_1v8";
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <1800000>;
 -                              regulator-always-on;
                                regulator-boot-on;
                                regulator-state-mem {
                                        regulator-on-in-suspend;
                                regulator-name = "vdd_ldo9";
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <1800000>;
 -                              regulator-always-on;
                                regulator-state-mem {
                                        regulator-on-in-suspend;
                                        regulator-mode = <MAX77802_OPMODE_LP>;
                                regulator-name = "vdd_ldo10";
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <1800000>;
 -                              regulator-always-on;
                                regulator-state-mem {
                                        regulator-off-in-suspend;
                                };
        status = "okay";
  };
  
- &mfc {
-       samsung,mfc-r = <0x43000000 0x800000>;
-       samsung,mfc-l = <0x51000000 0x800000>;
- };
  &mmc_0 {
        status = "okay";
        num-slots = <1>;
        status = "okay";
  };
  
 +&tmu_cpu0 {
 +      vtmu-supply = <&ldo10_reg>;
 +};
 +
 +&tmu_cpu1 {
 +      vtmu-supply = <&ldo10_reg>;
 +};
 +
 +&tmu_cpu2 {
 +      vtmu-supply = <&ldo10_reg>;
 +};
 +
 +&tmu_cpu3 {
 +      vtmu-supply = <&ldo10_reg>;
 +};
 +
 +&tmu_gpu {
 +      vtmu-supply = <&ldo10_reg>;
 +};
 +
  &usbdrd_dwc3_0 {
        dr_mode = "host";
  };
@@@ -21,6 -21,7 +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];
@@@ -127,15 -128,8 +128,15 @@@ static int __init __reserved_mem_alloc_
        }
  
        /* Need adjust the alignment to satisfy the CMA requirement */
 -      if (IS_ENABLED(CONFIG_CMA) && of_flat_dt_is_compatible(node, "shared-dma-pool"))
 -              align = max(align, (phys_addr_t)PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order));
 +      if (IS_ENABLED(CONFIG_CMA)
 +          && of_flat_dt_is_compatible(node, "shared-dma-pool")
 +          && of_get_flat_dt_prop(node, "reusable", NULL)
 +          && !of_get_flat_dt_prop(node, "no-map", NULL)) {
 +              unsigned long order =
 +                      max_t(unsigned long, MAX_ORDER - 1, pageblock_order);
 +
 +              align = max(align, (phys_addr_t)PAGE_SIZE << order);
 +      }
  
        prop = of_get_flat_dt_prop(node, "alloc-ranges", &len);
        if (prop) {
@@@ -296,53 -290,95 +297,95 @@@ static inline struct reserved_mem *__fi
        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;
@@@ -1,7 -1,8 +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,21 -29,17 +29,24 @@@ typedef int (*reservedmem_of_init_fn)(s
        _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);
  
 +int early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
 +                                           phys_addr_t align,
 +                                           phys_addr_t start,
 +                                           phys_addr_t end,
 +                                           bool nomap,
 +                                           phys_addr_t *res_base);
 +
  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;
  }
@@@ -53,4 -50,19 +57,19 @@@ static inline void fdt_reserved_mem_sav
                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 */