mirror of https://gitee.com/openkylin/linux.git
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. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJXdL1gAAoJEME3ZuaGi4PXDgEP/1iPrO92izin4BTql9CxJQ5L LlSHwWeE6JTd/qaMcs8bbRrP1mROLkZozyqkj7QUgxoZxeyXrVpzhjerUp9QSLz4 Pq9Ql57cc4F03mns1uNaZ9Bz9c3vhtoohwkLRHvC4n7yQ4zvjCoyRDXGZ4+osz+K vrlRpm3ZZrkr/MM4QuW9E7O2vL8/1kuPjn10vgCGEyWTSsMHHJe1+m4mpz5p/uPb RB8I1ZIdrvXyBJeNAhgCxWJ27nw2xpotqjAO5h2z/XZ8VSOIktd2iiouu199knso jPrVdJWuY0vv8YBXdJG/3/86T3S8w+HN1ULtaVIcYAbG44TLkzz1YCku3UUWB2yK INZ2J4dreXZ8NvcQPQffcE3B25w+hNx6mDlrAmRaapstLlPIkeNWeiYMI4CaoxTa 1lOGqUuw6gc9JlBrEkJilBS18A9ExzNlquiBJa3EiP/74axe2AriSxbZZCpQ6na0 mOkuW/0xO9iSE56+j1pUuz/GCmoJt4rCMTCRVp17eE6WUM6OW+oUWm0ArVefBCy/ Er5E3WwXNA4nhEuWU6Y1oh/ji2SNzr9eNU3eja254xgOGsHIW1iqaCappUBi4+VC cm6TaXSlzDBv3v/1kQT947LiHkc+5A4/mldizDSaujF9vjIyQvHzG+yGpHEbyWAT qf37rI3BB2GJgs13U5Jf =sS8p -----END PGP SIGNATURE----- Merge tag 'samsung-drivers-exynos-mfc-4.8-2' of git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux into next/dt 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>
This commit is contained in:
commit
8fe9c8b750
|
@ -21,15 +21,18 @@ Required properties:
|
||||||
- clock-names : from common clock binding: must contain "mfc",
|
- clock-names : from common clock binding: must contain "mfc",
|
||||||
corresponding to entry in the clocks property.
|
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:
|
Optional properties:
|
||||||
- power-domains : power-domain property defined with a phandle
|
- power-domains : power-domain property defined with a phandle
|
||||||
to respective power domain.
|
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:
|
Example:
|
||||||
SoC specific DT entry:
|
SoC specific DT entry:
|
||||||
|
@ -43,9 +46,29 @@ mfc: codec@13400000 {
|
||||||
clock-names = "mfc";
|
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:
|
Board specific DT entry:
|
||||||
|
|
||||||
codec@13400000 {
|
codec@13400000 {
|
||||||
samsung,mfc-r = <0x43000000 0x800000>;
|
memory-region = <&mfc_left>, <&mfc_right>;
|
||||||
samsung,mfc-l = <0x51000000 0x800000>;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* 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_mfc_left {
|
||||||
|
compatible = "shared-dma-pool";
|
||||||
|
no-map;
|
||||||
|
size = <0x1000000>;
|
||||||
|
alignment = <0x100000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
mfc_right: region_mfc_right {
|
||||||
|
compatible = "shared-dma-pool";
|
||||||
|
no-map;
|
||||||
|
size = <0x800000>;
|
||||||
|
alignment = <0x100000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&mfc {
|
||||||
|
memory-region = <&mfc_left>, <&mfc_right>;
|
||||||
|
};
|
|
@ -632,10 +632,6 @@ &i2s2 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
||||||
&mfc {
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&jpeg {
|
&jpeg {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
|
@ -431,7 +431,6 @@ mfc: codec@13400000 {
|
||||||
clocks = <&cmu CLK_MFC>, <&cmu CLK_SCLK_MFC>;
|
clocks = <&cmu CLK_MFC>, <&cmu CLK_SCLK_MFC>;
|
||||||
power-domains = <&pd_mfc>;
|
power-domains = <&pd_mfc>;
|
||||||
iommus = <&sysmmu_mfc>;
|
iommus = <&sysmmu_mfc>;
|
||||||
status = "disabled";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
sysmmu_mfc: sysmmu@13620000 {
|
sysmmu_mfc: sysmmu@13620000 {
|
||||||
|
|
|
@ -428,7 +428,6 @@ mfc: codec@13400000 {
|
||||||
clock-names = "mfc", "sclk_mfc";
|
clock-names = "mfc", "sclk_mfc";
|
||||||
iommus = <&sysmmu_mfc_l>, <&sysmmu_mfc_r>;
|
iommus = <&sysmmu_mfc_l>, <&sysmmu_mfc_r>;
|
||||||
iommu-names = "left", "right";
|
iommu-names = "left", "right";
|
||||||
status = "disabled";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
serial_0: serial@13800000 {
|
serial_0: serial@13800000 {
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "exynos4210.dtsi"
|
#include "exynos4210.dtsi"
|
||||||
#include <dt-bindings/gpio/gpio.h>
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
#include <dt-bindings/input/input.h>
|
#include <dt-bindings/input/input.h>
|
||||||
|
#include "exynos-mfc-reserved-memory.dtsi"
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
model = "Insignal Origen evaluation board based on Exynos4210";
|
model = "Insignal Origen evaluation board based on Exynos4210";
|
||||||
|
@ -287,12 +288,6 @@ buck7_reg: BUCK7 {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
&mfc {
|
|
||||||
samsung,mfc-r = <0x43000000 0x800000>;
|
|
||||||
samsung,mfc-l = <0x51000000 0x800000>;
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&sdhci_0 {
|
&sdhci_0 {
|
||||||
bus-width = <4>;
|
bus-width = <4>;
|
||||||
pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_cd>;
|
pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_cd>;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
/dts-v1/;
|
/dts-v1/;
|
||||||
#include "exynos4210.dtsi"
|
#include "exynos4210.dtsi"
|
||||||
#include <dt-bindings/gpio/gpio.h>
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
#include "exynos-mfc-reserved-memory.dtsi"
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
model = "Samsung smdkv310 evaluation board based on Exynos4210";
|
model = "Samsung smdkv310 evaluation board based on Exynos4210";
|
||||||
|
@ -132,12 +133,6 @@ key_e {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
&mfc {
|
|
||||||
samsung,mfc-r = <0x43000000 0x800000>;
|
|
||||||
samsung,mfc-l = <0x51000000 0x800000>;
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&pinctrl_1 {
|
&pinctrl_1 {
|
||||||
keypad_rows: keypad-rows {
|
keypad_rows: keypad-rows {
|
||||||
samsung,pins = "gpx2-0", "gpx2-1";
|
samsung,pins = "gpx2-0", "gpx2-1";
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "exynos4412.dtsi"
|
#include "exynos4412.dtsi"
|
||||||
#include "exynos4412-ppmu-common.dtsi"
|
#include "exynos4412-ppmu-common.dtsi"
|
||||||
#include <dt-bindings/gpio/gpio.h>
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
#include "exynos-mfc-reserved-memory.dtsi"
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
chosen {
|
chosen {
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "exynos4412.dtsi"
|
#include "exynos4412.dtsi"
|
||||||
#include <dt-bindings/gpio/gpio.h>
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
#include <dt-bindings/input/input.h>
|
#include <dt-bindings/input/input.h>
|
||||||
|
#include "exynos-mfc-reserved-memory.dtsi"
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
model = "Insignal Origen evaluation board based on Exynos4412";
|
model = "Insignal Origen evaluation board based on Exynos4412";
|
||||||
|
@ -481,12 +482,6 @@ key_enter {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
&mfc {
|
|
||||||
samsung,mfc-r = <0x43000000 0x800000>;
|
|
||||||
samsung,mfc-l = <0x51000000 0x800000>;
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&mshc_0 {
|
&mshc_0 {
|
||||||
pinctrl-0 = <&sd4_clk &sd4_cmd &sd4_bus4 &sd4_bus8>;
|
pinctrl-0 = <&sd4_clk &sd4_cmd &sd4_bus4 &sd4_bus8>;
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
/dts-v1/;
|
/dts-v1/;
|
||||||
#include "exynos4412.dtsi"
|
#include "exynos4412.dtsi"
|
||||||
|
#include "exynos-mfc-reserved-memory.dtsi"
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
model = "Samsung SMDK evaluation board based on Exynos4412";
|
model = "Samsung SMDK evaluation board based on Exynos4412";
|
||||||
|
@ -111,12 +112,6 @@ key_E {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
&mfc {
|
|
||||||
samsung,mfc-r = <0x43000000 0x800000>;
|
|
||||||
samsung,mfc-l = <0x51000000 0x800000>;
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&pinctrl_1 {
|
&pinctrl_1 {
|
||||||
keypad_rows: keypad-rows {
|
keypad_rows: keypad-rows {
|
||||||
samsung,pins = "gpx2-0", "gpx2-1", "gpx2-2";
|
samsung,pins = "gpx2-0", "gpx2-1", "gpx2-2";
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <dt-bindings/interrupt-controller/irq.h>
|
#include <dt-bindings/interrupt-controller/irq.h>
|
||||||
#include <dt-bindings/input/input.h>
|
#include <dt-bindings/input/input.h>
|
||||||
#include "exynos5250.dtsi"
|
#include "exynos5250.dtsi"
|
||||||
|
#include "exynos-mfc-reserved-memory.dtsi"
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
model = "Insignal Arndale evaluation board based on EXYNOS5250";
|
model = "Insignal Arndale evaluation board based on EXYNOS5250";
|
||||||
|
@ -515,11 +516,6 @@ &i2s0 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
||||||
&mfc {
|
|
||||||
samsung,mfc-r = <0x43000000 0x800000>;
|
|
||||||
samsung,mfc-l = <0x51000000 0x800000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
&mmc_0 {
|
&mmc_0 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
num-slots = <1>;
|
num-slots = <1>;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <dt-bindings/gpio/gpio.h>
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
#include <dt-bindings/interrupt-controller/irq.h>
|
#include <dt-bindings/interrupt-controller/irq.h>
|
||||||
#include "exynos5250.dtsi"
|
#include "exynos5250.dtsi"
|
||||||
|
#include "exynos-mfc-reserved-memory.dtsi"
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
model = "SAMSUNG SMDK5250 board based on EXYNOS5250";
|
model = "SAMSUNG SMDK5250 board based on EXYNOS5250";
|
||||||
|
@ -343,11 +344,6 @@ &i2s0 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
||||||
&mfc {
|
|
||||||
samsung,mfc-r = <0x43000000 0x800000>;
|
|
||||||
samsung,mfc-l = <0x51000000 0x800000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
&mmc_0 {
|
&mmc_0 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
num-slots = <1>;
|
num-slots = <1>;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <dt-bindings/interrupt-controller/irq.h>
|
#include <dt-bindings/interrupt-controller/irq.h>
|
||||||
#include <dt-bindings/input/input.h>
|
#include <dt-bindings/input/input.h>
|
||||||
#include "exynos5250.dtsi"
|
#include "exynos5250.dtsi"
|
||||||
|
#include "exynos-mfc-reserved-memory.dtsi"
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
model = "Google Spring";
|
model = "Google Spring";
|
||||||
|
@ -424,11 +425,6 @@ &i2s0 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
||||||
&mfc {
|
|
||||||
samsung,mfc-r = <0x43000000 0x800000>;
|
|
||||||
samsung,mfc-l = <0x51000000 0x800000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
&mmc_0 {
|
&mmc_0 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
num-slots = <1>;
|
num-slots = <1>;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <dt-bindings/interrupt-controller/irq.h>
|
#include <dt-bindings/interrupt-controller/irq.h>
|
||||||
#include <dt-bindings/input/input.h>
|
#include <dt-bindings/input/input.h>
|
||||||
#include <dt-bindings/clock/samsung,s2mps11.h>
|
#include <dt-bindings/clock/samsung,s2mps11.h>
|
||||||
|
#include "exynos-mfc-reserved-memory.dtsi"
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
model = "Insignal Arndale Octa evaluation board based on EXYNOS5420";
|
model = "Insignal Arndale Octa evaluation board based on EXYNOS5420";
|
||||||
|
@ -346,11 +347,6 @@ buck10_reg: BUCK10 {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
&mfc {
|
|
||||||
samsung,mfc-r = <0x43000000 0x800000>;
|
|
||||||
samsung,mfc-l = <0x51000000 0x800000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
&mmc_0 {
|
&mmc_0 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
broken-cd;
|
broken-cd;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <dt-bindings/regulator/maxim,max77802.h>
|
#include <dt-bindings/regulator/maxim,max77802.h>
|
||||||
#include "exynos5420.dtsi"
|
#include "exynos5420.dtsi"
|
||||||
#include "exynos5420-cpus.dtsi"
|
#include "exynos5420-cpus.dtsi"
|
||||||
|
#include "exynos-mfc-reserved-memory.dtsi"
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
model = "Google Peach Pit Rev 6+";
|
model = "Google Peach Pit Rev 6+";
|
||||||
|
@ -688,11 +689,6 @@ &i2s0 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
||||||
&mfc {
|
|
||||||
samsung,mfc-r = <0x43000000 0x800000>;
|
|
||||||
samsung,mfc-l = <0x51000000 0x800000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
&mmc_0 {
|
&mmc_0 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
num-slots = <1>;
|
num-slots = <1>;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "exynos5420.dtsi"
|
#include "exynos5420.dtsi"
|
||||||
#include "exynos5420-cpus.dtsi"
|
#include "exynos5420-cpus.dtsi"
|
||||||
#include <dt-bindings/gpio/gpio.h>
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
#include "exynos-mfc-reserved-memory.dtsi"
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
model = "Samsung SMDK5420 board based on EXYNOS5420";
|
model = "Samsung SMDK5420 board based on EXYNOS5420";
|
||||||
|
@ -354,11 +355,6 @@ hdmiddc@50 {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
&mfc {
|
|
||||||
samsung,mfc-r = <0x43000000 0x800000>;
|
|
||||||
samsung,mfc-l = <0x51000000 0x800000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
&mmc_0 {
|
&mmc_0 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
broken-cd;
|
broken-cd;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <dt-bindings/sound/samsung-i2s.h>
|
#include <dt-bindings/sound/samsung-i2s.h>
|
||||||
#include "exynos5800.dtsi"
|
#include "exynos5800.dtsi"
|
||||||
#include "exynos5422-cpus.dtsi"
|
#include "exynos5422-cpus.dtsi"
|
||||||
|
#include "exynos-mfc-reserved-memory.dtsi"
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
memory {
|
memory {
|
||||||
|
@ -494,11 +495,6 @@ hdmiddc@50 {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
&mfc {
|
|
||||||
samsung,mfc-r = <0x43000000 0x800000>;
|
|
||||||
samsung,mfc-l = <0x51000000 0x800000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
&mmc_0 {
|
&mmc_0 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
mmc-pwrseq = <&emmc_pwrseq>;
|
mmc-pwrseq = <&emmc_pwrseq>;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <dt-bindings/regulator/maxim,max77802.h>
|
#include <dt-bindings/regulator/maxim,max77802.h>
|
||||||
#include "exynos5800.dtsi"
|
#include "exynos5800.dtsi"
|
||||||
#include "exynos5420-cpus.dtsi"
|
#include "exynos5420-cpus.dtsi"
|
||||||
|
#include "exynos-mfc-reserved-memory.dtsi"
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
model = "Google Peach Pi Rev 10+";
|
model = "Google Peach Pi Rev 10+";
|
||||||
|
@ -663,11 +664,6 @@ &i2s0 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
||||||
&mfc {
|
|
||||||
samsung,mfc-r = <0x43000000 0x800000>;
|
|
||||||
samsung,mfc-l = <0x51000000 0x800000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
&mmc_0 {
|
&mmc_0 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
num-slots = <1>;
|
num-slots = <1>;
|
||||||
|
|
|
@ -23,5 +23,3 @@ AFLAGS_sleep.o :=-Wa,-march=armv7-a$(plus_sec)
|
||||||
|
|
||||||
obj-$(CONFIG_EXYNOS5420_MCPM) += mcpm-exynos.o
|
obj-$(CONFIG_EXYNOS5420_MCPM) += mcpm-exynos.o
|
||||||
CFLAGS_mcpm-exynos.o += -march=armv7-a
|
CFLAGS_mcpm-exynos.o += -march=armv7-a
|
||||||
|
|
||||||
obj-$(CONFIG_S5P_DEV_MFC) += s5p-dev-mfc.o
|
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
#include <mach/map.h>
|
#include <mach/map.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "mfc.h"
|
|
||||||
|
|
||||||
static struct map_desc exynos4_iodesc[] __initdata = {
|
static struct map_desc exynos4_iodesc[] __initdata = {
|
||||||
{
|
{
|
||||||
|
@ -237,23 +236,6 @@ static char const *const exynos_dt_compat[] __initconst = {
|
||||||
NULL
|
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)
|
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_machine = exynos_dt_machine_init,
|
||||||
.init_late = exynos_init_late,
|
.init_late = exynos_init_late,
|
||||||
.dt_compat = exynos_dt_compat,
|
.dt_compat = exynos_dt_compat,
|
||||||
.reserve = exynos_reserve,
|
|
||||||
.dt_fixup = exynos_dt_fixup,
|
.dt_fixup = exynos_dt_fixup,
|
||||||
MACHINE_END
|
MACHINE_END
|
||||||
|
|
|
@ -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 */
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -1124,6 +1124,7 @@ static int gsc_probe(struct platform_device *pdev)
|
||||||
goto err_m2m;
|
goto err_m2m;
|
||||||
|
|
||||||
/* Initialize continious memory allocator */
|
/* 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);
|
gsc->alloc_ctx = vb2_dma_contig_init_ctx(dev);
|
||||||
if (IS_ERR(gsc->alloc_ctx)) {
|
if (IS_ERR(gsc->alloc_ctx)) {
|
||||||
ret = PTR_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);
|
v4l2_device_unregister(&gsc->v4l2_dev);
|
||||||
|
|
||||||
vb2_dma_contig_cleanup_ctx(gsc->alloc_ctx);
|
vb2_dma_contig_cleanup_ctx(gsc->alloc_ctx);
|
||||||
|
vb2_dma_contig_clear_max_seg_size(&pdev->dev);
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
gsc_clk_put(gsc);
|
gsc_clk_put(gsc);
|
||||||
|
|
||||||
|
|
|
@ -1019,6 +1019,7 @@ static int fimc_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize contiguous memory allocator */
|
/* 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);
|
fimc->alloc_ctx = vb2_dma_contig_init_ctx(dev);
|
||||||
if (IS_ERR(fimc->alloc_ctx)) {
|
if (IS_ERR(fimc->alloc_ctx)) {
|
||||||
ret = PTR_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);
|
fimc_unregister_capture_subdev(fimc);
|
||||||
vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx);
|
vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx);
|
||||||
|
vb2_dma_contig_clear_max_seg_size(&pdev->dev);
|
||||||
|
|
||||||
clk_disable(fimc->clock[CLK_BUS]);
|
clk_disable(fimc->clock[CLK_BUS]);
|
||||||
fimc_clk_put(fimc);
|
fimc_clk_put(fimc);
|
||||||
|
|
|
@ -847,6 +847,7 @@ static int fimc_is_probe(struct platform_device *pdev)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err_pm;
|
goto err_pm;
|
||||||
|
|
||||||
|
vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32));
|
||||||
is->alloc_ctx = vb2_dma_contig_init_ctx(dev);
|
is->alloc_ctx = vb2_dma_contig_init_ctx(dev);
|
||||||
if (IS_ERR(is->alloc_ctx)) {
|
if (IS_ERR(is->alloc_ctx)) {
|
||||||
ret = PTR_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);
|
free_irq(is->irq, is);
|
||||||
fimc_is_unregister_subdevs(is);
|
fimc_is_unregister_subdevs(is);
|
||||||
vb2_dma_contig_cleanup_ctx(is->alloc_ctx);
|
vb2_dma_contig_cleanup_ctx(is->alloc_ctx);
|
||||||
|
vb2_dma_contig_clear_max_seg_size(dev);
|
||||||
fimc_is_put_clocks(is);
|
fimc_is_put_clocks(is);
|
||||||
fimc_is_debugfs_remove(is);
|
fimc_is_debugfs_remove(is);
|
||||||
release_firmware(is->fw.f_w);
|
release_firmware(is->fw.f_w);
|
||||||
|
|
|
@ -1551,6 +1551,7 @@ static int fimc_lite_probe(struct platform_device *pdev)
|
||||||
goto err_sd;
|
goto err_sd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32));
|
||||||
fimc->alloc_ctx = vb2_dma_contig_init_ctx(dev);
|
fimc->alloc_ctx = vb2_dma_contig_init_ctx(dev);
|
||||||
if (IS_ERR(fimc->alloc_ctx)) {
|
if (IS_ERR(fimc->alloc_ctx)) {
|
||||||
ret = PTR_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);
|
pm_runtime_set_suspended(dev);
|
||||||
fimc_lite_unregister_capture_subdev(fimc);
|
fimc_lite_unregister_capture_subdev(fimc);
|
||||||
vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx);
|
vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx);
|
||||||
|
vb2_dma_contig_clear_max_seg_size(dev);
|
||||||
fimc_lite_clk_put(fimc);
|
fimc_lite_clk_put(fimc);
|
||||||
|
|
||||||
dev_info(dev, "Driver unloaded\n");
|
dev_info(dev, "Driver unloaded\n");
|
||||||
|
|
|
@ -681,6 +681,7 @@ static int g2d_probe(struct platform_device *pdev)
|
||||||
goto put_clk_gate;
|
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);
|
dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
|
||||||
if (IS_ERR(dev->alloc_ctx)) {
|
if (IS_ERR(dev->alloc_ctx)) {
|
||||||
ret = PTR_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);
|
video_unregister_device(dev->vfd);
|
||||||
v4l2_device_unregister(&dev->v4l2_dev);
|
v4l2_device_unregister(&dev->v4l2_dev);
|
||||||
vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
|
vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
|
||||||
|
vb2_dma_contig_clear_max_seg_size(&pdev->dev);
|
||||||
clk_unprepare(dev->gate);
|
clk_unprepare(dev->gate);
|
||||||
clk_put(dev->gate);
|
clk_put(dev->gate);
|
||||||
clk_unprepare(dev->clk);
|
clk_unprepare(dev->clk);
|
||||||
|
|
|
@ -2843,6 +2843,7 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
|
||||||
goto device_register_rollback;
|
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);
|
jpeg->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
|
||||||
if (IS_ERR(jpeg->alloc_ctx)) {
|
if (IS_ERR(jpeg->alloc_ctx)) {
|
||||||
v4l2_err(&jpeg->v4l2_dev, "Failed to init memory allocator\n");
|
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_decoder);
|
||||||
video_unregister_device(jpeg->vfd_encoder);
|
video_unregister_device(jpeg->vfd_encoder);
|
||||||
vb2_dma_contig_cleanup_ctx(jpeg->alloc_ctx);
|
vb2_dma_contig_cleanup_ctx(jpeg->alloc_ctx);
|
||||||
|
vb2_dma_contig_clear_max_seg_size(&pdev->dev);
|
||||||
v4l2_m2m_release(jpeg->m2m_dev);
|
v4l2_m2m_release(jpeg->m2m_dev);
|
||||||
v4l2_device_unregister(&jpeg->v4l2_dev);
|
v4l2_device_unregister(&jpeg->v4l2_dev);
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <media/v4l2-event.h>
|
#include <media/v4l2-event.h>
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_reserved_mem.h>
|
||||||
#include <media/videobuf2-v4l2.h>
|
#include <media/videobuf2-v4l2.h>
|
||||||
#include "s5p_mfc_common.h"
|
#include "s5p_mfc_common.h"
|
||||||
#include "s5p_mfc_ctrl.h"
|
#include "s5p_mfc_ctrl.h"
|
||||||
|
@ -29,6 +30,7 @@
|
||||||
#include "s5p_mfc_dec.h"
|
#include "s5p_mfc_dec.h"
|
||||||
#include "s5p_mfc_enc.h"
|
#include "s5p_mfc_enc.h"
|
||||||
#include "s5p_mfc_intr.h"
|
#include "s5p_mfc_intr.h"
|
||||||
|
#include "s5p_mfc_iommu.h"
|
||||||
#include "s5p_mfc_opr.h"
|
#include "s5p_mfc_opr.h"
|
||||||
#include "s5p_mfc_cmd.h"
|
#include "s5p_mfc_cmd.h"
|
||||||
#include "s5p_mfc_pm.h"
|
#include "s5p_mfc_pm.h"
|
||||||
|
@ -1043,55 +1045,94 @@ static const struct v4l2_file_operations s5p_mfc_fops = {
|
||||||
.mmap = s5p_mfc_mmap,
|
.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))
|
of_reserved_mem_device_release(dev);
|
||||||
return 0;
|
}
|
||||||
return !strcmp(dev_name(dev), (char *)data);
|
|
||||||
|
static struct device *s5p_mfc_alloc_memdev(struct device *dev,
|
||||||
|
const char *name, unsigned int idx)
|
||||||
|
{
|
||||||
|
struct device *child;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
static void *mfc_get_drv_data(struct platform_device *pdev);
|
||||||
|
|
||||||
static int s5p_mfc_alloc_memdevs(struct s5p_mfc_dev *dev)
|
|
||||||
{
|
|
||||||
unsigned int mem_info[2] = { };
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* MFC probe function */
|
/* MFC probe function */
|
||||||
static int s5p_mfc_probe(struct platform_device *pdev)
|
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);
|
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);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
|
||||||
dev->regs_base = devm_ioremap_resource(&pdev->dev, res);
|
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;
|
goto err_res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pdev->dev.of_node) {
|
ret = s5p_mfc_configure_dma_memory(dev);
|
||||||
ret = s5p_mfc_alloc_memdevs(dev);
|
if (ret < 0) {
|
||||||
if (ret < 0)
|
dev_err(&pdev->dev, "failed to configure DMA memory\n");
|
||||||
goto err_res;
|
return ret;
|
||||||
} 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_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);
|
dev->alloc_ctx[0] = vb2_dma_contig_init_ctx(dev->mem_dev_l);
|
||||||
if (IS_ERR(dev->alloc_ctx[0])) {
|
if (IS_ERR(dev->alloc_ctx[0])) {
|
||||||
ret = PTR_ERR(dev->alloc_ctx[0]);
|
ret = PTR_ERR(dev->alloc_ctx[0]);
|
||||||
goto err_res;
|
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);
|
dev->alloc_ctx[1] = vb2_dma_contig_init_ctx(dev->mem_dev_r);
|
||||||
if (IS_ERR(dev->alloc_ctx[1])) {
|
if (IS_ERR(dev->alloc_ctx[1])) {
|
||||||
ret = PTR_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;
|
vfd->vfl_dir = VFL_DIR_M2M;
|
||||||
snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_DEC_NAME);
|
snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_DEC_NAME);
|
||||||
dev->vfd_dec = vfd;
|
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);
|
video_set_drvdata(vfd, dev);
|
||||||
|
|
||||||
/* encoder */
|
/* encoder */
|
||||||
|
@ -1226,14 +1246,6 @@ static int s5p_mfc_probe(struct platform_device *pdev)
|
||||||
vfd->vfl_dir = VFL_DIR_M2M;
|
vfd->vfl_dir = VFL_DIR_M2M;
|
||||||
snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_ENC_NAME);
|
snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_ENC_NAME);
|
||||||
dev->vfd_enc = vfd;
|
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);
|
video_set_drvdata(vfd, dev);
|
||||||
platform_set_drvdata(pdev, 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_hw_cmds(dev);
|
||||||
s5p_mfc_init_regs(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__);
|
pr_debug("%s--\n", __func__);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Deinit MFC if probe had failed */
|
/* Deinit MFC if probe had failed */
|
||||||
err_enc_reg:
|
err_enc_reg:
|
||||||
video_device_release(dev->vfd_enc);
|
|
||||||
err_enc_alloc:
|
|
||||||
video_unregister_device(dev->vfd_dec);
|
video_unregister_device(dev->vfd_dec);
|
||||||
err_dec_reg:
|
err_dec_reg:
|
||||||
|
video_device_release(dev->vfd_enc);
|
||||||
|
err_enc_alloc:
|
||||||
video_device_release(dev->vfd_dec);
|
video_device_release(dev->vfd_dec);
|
||||||
err_dec_alloc:
|
err_dec_alloc:
|
||||||
v4l2_device_unregister(&dev->v4l2_dev);
|
v4l2_device_unregister(&dev->v4l2_dev);
|
||||||
|
@ -1293,10 +1324,9 @@ static int s5p_mfc_remove(struct platform_device *pdev)
|
||||||
s5p_mfc_release_firmware(dev);
|
s5p_mfc_release_firmware(dev);
|
||||||
vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]);
|
vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]);
|
||||||
vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]);
|
vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]);
|
||||||
if (pdev->dev.of_node) {
|
s5p_mfc_unconfigure_dma_memory(dev);
|
||||||
put_device(dev->mem_dev_l);
|
vb2_dma_contig_clear_max_seg_size(dev->mem_dev_l);
|
||||||
put_device(dev->mem_dev_r);
|
vb2_dma_contig_clear_max_seg_size(dev->mem_dev_r);
|
||||||
}
|
|
||||||
|
|
||||||
s5p_mfc_final_pm(dev);
|
s5p_mfc_final_pm(dev);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -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_ */
|
|
@ -80,6 +80,7 @@ int mxr_acquire_video(struct mxr_device *mdev,
|
||||||
goto fail;
|
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);
|
mdev->alloc_ctx = vb2_dma_contig_init_ctx(mdev->dev);
|
||||||
if (IS_ERR(mdev->alloc_ctx)) {
|
if (IS_ERR(mdev->alloc_ctx)) {
|
||||||
mxr_err(mdev, "could not acquire vb2 allocator\n");
|
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]);
|
kfree(mdev->output[i]);
|
||||||
|
|
||||||
vb2_dma_contig_cleanup_ctx(mdev->alloc_ctx);
|
vb2_dma_contig_cleanup_ctx(mdev->alloc_ctx);
|
||||||
|
vb2_dma_contig_clear_max_seg_size(mdev->dev);
|
||||||
v4l2_device_unregister(&mdev->v4l2_dev);
|
v4l2_device_unregister(&mdev->v4l2_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -753,6 +753,59 @@ void vb2_dma_contig_cleanup_ctx(void *alloc_ctx)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(vb2_dma_contig_cleanup_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_DESCRIPTION("DMA-contig memory handling routines for videobuf2");
|
||||||
MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>");
|
MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <linux/sizes.h>
|
#include <linux/sizes.h>
|
||||||
#include <linux/of_reserved_mem.h>
|
#include <linux/of_reserved_mem.h>
|
||||||
#include <linux/sort.h>
|
#include <linux/sort.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
#define MAX_RESERVED_REGIONS 16
|
#define MAX_RESERVED_REGIONS 16
|
||||||
static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS];
|
static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS];
|
||||||
|
@ -296,53 +297,95 @@ static inline struct reserved_mem *__find_rmem(struct device_node *node)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
struct rmem_assigned_device {
|
||||||
* of_reserved_mem_device_init() - assign reserved memory region to given device
|
struct device *dev;
|
||||||
*
|
struct reserved_mem *rmem;
|
||||||
* This function assign memory region pointed by "memory-region" device tree
|
struct list_head list;
|
||||||
* property to the given device.
|
};
|
||||||
*/
|
|
||||||
int of_reserved_mem_device_init(struct device *dev)
|
static LIST_HEAD(of_rmem_assigned_device_list);
|
||||||
{
|
static DEFINE_MUTEX(of_rmem_assigned_device_mutex);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 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_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 reserved_mem *rmem;
|
||||||
struct device_node *np;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
np = of_parse_phandle(dev->of_node, "memory-region", 0);
|
if (!np || !dev)
|
||||||
if (!np)
|
return -EINVAL;
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
rmem = __find_rmem(np);
|
target = of_parse_phandle(np, "memory-region", idx);
|
||||||
of_node_put(np);
|
if (!target)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
rmem = __find_rmem(target);
|
||||||
|
of_node_put(target);
|
||||||
|
|
||||||
if (!rmem || !rmem->ops || !rmem->ops->device_init)
|
if (!rmem || !rmem->ops || !rmem->ops->device_init)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
rd = kmalloc(sizeof(struct rmem_assigned_device), GFP_KERNEL);
|
||||||
|
if (!rd)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
ret = rmem->ops->device_init(rmem, dev);
|
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);
|
dev_info(dev, "assigned reserved memory node %s\n", rmem->name);
|
||||||
|
} else {
|
||||||
|
kfree(rd);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
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
|
* 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
|
* This function releases structures allocated for memory region handling for
|
||||||
* the given device.
|
* the given device.
|
||||||
*/
|
*/
|
||||||
void of_reserved_mem_device_release(struct device *dev)
|
void of_reserved_mem_device_release(struct device *dev)
|
||||||
{
|
{
|
||||||
struct reserved_mem *rmem;
|
struct rmem_assigned_device *rd;
|
||||||
struct device_node *np;
|
struct reserved_mem *rmem = NULL;
|
||||||
|
|
||||||
np = of_parse_phandle(dev->of_node, "memory-region", 0);
|
mutex_lock(&of_rmem_assigned_device_mutex);
|
||||||
if (!np)
|
list_for_each_entry(rd, &of_rmem_assigned_device_list, list) {
|
||||||
return;
|
if (rd->dev == dev) {
|
||||||
|
rmem = rd->rmem;
|
||||||
rmem = __find_rmem(np);
|
list_del(&rd->list);
|
||||||
of_node_put(np);
|
kfree(rd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mutex_unlock(&of_rmem_assigned_device_mutex);
|
||||||
|
|
||||||
if (!rmem || !rmem->ops || !rmem->ops->device_release)
|
if (!rmem || !rmem->ops || !rmem->ops->device_release)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#ifndef __OF_RESERVED_MEM_H
|
#ifndef __OF_RESERVED_MEM_H
|
||||||
#define __OF_RESERVED_MEM_H
|
#define __OF_RESERVED_MEM_H
|
||||||
|
|
||||||
struct device;
|
#include <linux/device.h>
|
||||||
|
|
||||||
struct of_phandle_args;
|
struct of_phandle_args;
|
||||||
struct reserved_mem_ops;
|
struct reserved_mem_ops;
|
||||||
|
|
||||||
|
@ -28,7 +29,9 @@ typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem);
|
||||||
_OF_DECLARE(reservedmem, name, compat, init, reservedmem_of_init_fn)
|
_OF_DECLARE(reservedmem, name, compat, init, reservedmem_of_init_fn)
|
||||||
|
|
||||||
#ifdef CONFIG_OF_RESERVED_MEM
|
#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 of_reserved_mem_device_release(struct device *dev);
|
||||||
|
|
||||||
int early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
|
int early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
|
||||||
|
@ -42,7 +45,8 @@ void fdt_init_reserved_mem(void);
|
||||||
void fdt_reserved_mem_save_node(unsigned long node, const char *uname,
|
void fdt_reserved_mem_save_node(unsigned long node, const char *uname,
|
||||||
phys_addr_t base, phys_addr_t size);
|
phys_addr_t base, phys_addr_t size);
|
||||||
#else
|
#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;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
@ -53,4 +57,19 @@ static inline void fdt_reserved_mem_save_node(unsigned long node,
|
||||||
const char *uname, phys_addr_t base, phys_addr_t size) { }
|
const char *uname, phys_addr_t base, phys_addr_t size) { }
|
||||||
#endif
|
#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 */
|
#endif /* __OF_RESERVED_MEM_H */
|
||||||
|
|
|
@ -35,6 +35,8 @@ static inline void *vb2_dma_contig_init_ctx(struct device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
void vb2_dma_contig_cleanup_ctx(void *alloc_ctx);
|
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;
|
extern const struct vb2_mem_ops vb2_dma_contig_memops;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue