diff options
author | MyungJoo Ham <myungjoo.ham@samsung.com> | 2014-03-20 15:29:15 +0900 |
---|---|---|
committer | MyungJoo Ham <myungjoo.ham@samsung.com> | 2014-03-20 15:29:15 +0900 |
commit | b3a6e2c5448b7d340ff6bea9e99f79989453b1f7 (patch) | |
tree | 03f7e2c45fa76d6f65f46ba1de2b2541ebe3dc7b | |
parent | 9157e421d4c229d2b45e00b4e36ede3606033ad3 (diff) | |
download | linux-3.10-devel/v3.10-ltsi.tar.gz linux-3.10-devel/v3.10-ltsi.tar.bz2 linux-3.10-devel/v3.10-ltsi.zip |
add Tizen ARM reference patchesdevel/v3.10-ltsi
- Imported 20140319.065243:
author Jonghwa Lee <jonghwa3.lee@samsung.com>
Wed, 19 Mar 2014 00:55:10 +0900 (00:55 +0900)
committer Jonghwa Lee <jonghwa3.lee@samsung.com>
Wed, 19 Mar 2014 01:13:40 +0900 (01:13 +0900)
commit 7464f7e4fed02c10aa619746890bdd96b1b43fc3
Based on Linux 3.10.19 LTS.
Change-Id: I17572de4952319a6815c18379bdbe35b1db0a88c
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
1302 files changed, 385483 insertions, 0 deletions
diff --git a/patches.tizen/0001-ARM-EXYNOS-Fail-l2x0-cache-initialization-if-DT-base.patch b/patches.tizen/0001-ARM-EXYNOS-Fail-l2x0-cache-initialization-if-DT-base.patch new file mode 100644 index 00000000000..c1e705bcedc --- /dev/null +++ b/patches.tizen/0001-ARM-EXYNOS-Fail-l2x0-cache-initialization-if-DT-base.patch @@ -0,0 +1,38 @@ +From cf01114c6e953bcbcf1fc2a9474eedb71e4f3a9b Mon Sep 17 00:00:00 2001 +From: Tomasz Figa <t.figa@samsung.com> +Date: Wed, 12 Sep 2012 15:30:32 +0200 +Subject: [PATCH 0001/1302] ARM: EXYNOS: Fail l2x0 cache initialization if + DT-based init fails + +On DT-based boards, DT decides whether to enable l2x0 cache controller +or not. + +This patch modifies Exynos l2x0 cache initialization code to fail if +l2x0_of_init fails. + +Signed-off-by: Tomasz Figa <t.figa@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/mach-exynos/common.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c +index f7e504b..5bb6b26 100644 +--- a/arch/arm/mach-exynos/common.c ++++ b/arch/arm/mach-exynos/common.c +@@ -560,8 +560,10 @@ static int __init exynos4_l2x0_cache_init(void) + if (soc_is_exynos5250() || soc_is_exynos5440()) + return 0; + +- ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK); +- if (!ret) { ++ if (of_have_populated_dt()) { ++ ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK); ++ if (ret) ++ return ret; + l2x0_regs_phys = virt_to_phys(&l2x0_saved_regs); + clean_dcache_area(&l2x0_regs_phys, sizeof(unsigned long)); + return 0; +-- +1.8.3.2 + diff --git a/patches.tizen/0002-ARM-EXYNOS-Add-secure-firmware-support-to-l2x0-initi.patch b/patches.tizen/0002-ARM-EXYNOS-Add-secure-firmware-support-to-l2x0-initi.patch new file mode 100644 index 00000000000..05d199a2539 --- /dev/null +++ b/patches.tizen/0002-ARM-EXYNOS-Add-secure-firmware-support-to-l2x0-initi.patch @@ -0,0 +1,60 @@ +From 156f9542badc0700e9759ec0a8c1660aead1092d Mon Sep 17 00:00:00 2001 +From: Tomasz Figa <t.figa@samsung.com> +Date: Wed, 12 Sep 2012 15:35:58 +0200 +Subject: [PATCH 0002/1302] ARM: EXYNOS: Add secure firmware support to l2x0 + initialization + +Signed-off-by: Tomasz Figa <t.figa@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/mach-exynos/common.c | 3 +++ + arch/arm/mach-exynos/firmware.c | 8 ++++++++ + 2 files changed, 11 insertions(+) + +diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c +index 5bb6b26..02fb4a1 100644 +--- a/arch/arm/mach-exynos/common.c ++++ b/arch/arm/mach-exynos/common.c +@@ -33,6 +33,7 @@ + + #include <asm/proc-fns.h> + #include <asm/exception.h> ++#include <asm/firmware.h> + #include <asm/hardware/cache-l2x0.h> + #include <asm/mach/map.h> + #include <asm/mach/irq.h> +@@ -560,6 +561,8 @@ static int __init exynos4_l2x0_cache_init(void) + if (soc_is_exynos5250() || soc_is_exynos5440()) + return 0; + ++ call_firmware_op(l2x0_init); ++ + if (of_have_populated_dt()) { + ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK); + if (ret) +diff --git a/arch/arm/mach-exynos/firmware.c b/arch/arm/mach-exynos/firmware.c +index ed11f10..da5fb26 100644 +--- a/arch/arm/mach-exynos/firmware.c ++++ b/arch/arm/mach-exynos/firmware.c +@@ -40,10 +40,18 @@ static int exynos_set_cpu_boot_addr(int cpu, unsigned long boot_addr) + return 0; + } + ++static int exynos_l2x0_init(void) ++{ ++ exynos_smc(SMC_CMD_L2X0INVALL, 0, 0, 0); ++ exynos_smc(SMC_CMD_L2X0CTRL, 1, 0, 0); ++ return 0; ++} ++ + static const struct firmware_ops exynos_firmware_ops = { + .do_idle = exynos_do_idle, + .set_cpu_boot_addr = exynos_set_cpu_boot_addr, + .cpu_boot = exynos_cpu_boot, ++ .l2x0_init = exynos_l2x0_init, + }; + + void __init exynos_firmware_init(void) +-- +1.8.3.2 + diff --git a/patches.tizen/0003-ARM-dts-exynos4-Add-DT-nodes-for-L2-cache-controller.patch b/patches.tizen/0003-ARM-dts-exynos4-Add-DT-nodes-for-L2-cache-controller.patch new file mode 100644 index 00000000000..249b51e09fb --- /dev/null +++ b/patches.tizen/0003-ARM-dts-exynos4-Add-DT-nodes-for-L2-cache-controller.patch @@ -0,0 +1,64 @@ +From fd0079387c13066ea0ef1f9d6f7f863fd16cc69f Mon Sep 17 00:00:00 2001 +From: Tomasz Figa <t.figa@samsung.com> +Date: Wed, 12 Sep 2012 15:36:39 +0200 +Subject: [PATCH 0003/1302] ARM: dts: exynos4: Add DT nodes for L2 cache + controller + +Signed-off-by: Tomasz Figa <t.figa@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4.dtsi | 6 ++++++ + arch/arm/boot/dts/exynos4210.dtsi | 4 ++++ + arch/arm/boot/dts/exynos4x12.dtsi | 4 ++++ + 3 files changed, 14 insertions(+) + +diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi +index 359694c..b90bab3 100644 +--- a/arch/arm/boot/dts/exynos4.dtsi ++++ b/arch/arm/boot/dts/exynos4.dtsi +@@ -92,6 +92,12 @@ + reg = <0x10010000 0x400>; + }; + ++ cache-controller@0x10502000 { ++ compatible = "arm,pl310-cache"; ++ reg = <0x10502000 0x1000>; ++ arm,tag-latency = <1 1 0>; ++ }; ++ + watchdog@10060000 { + compatible = "samsung,s3c2410-wdt"; + reg = <0x10060000 0x100>; +diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi +index 54710de..ef707bd 100644 +--- a/arch/arm/boot/dts/exynos4210.dtsi ++++ b/arch/arm/boot/dts/exynos4210.dtsi +@@ -48,6 +48,10 @@ + <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>; + }; + ++ cache-controller@0x10502000 { ++ arm,data-latency = <1 1 0>; ++ }; ++ + mct@10050000 { + compatible = "samsung,exynos4210-mct"; + reg = <0x10050000 0x800>; +diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi +index e3380a7..4afda47 100644 +--- a/arch/arm/boot/dts/exynos4x12.dtsi ++++ b/arch/arm/boot/dts/exynos4x12.dtsi +@@ -36,6 +36,10 @@ + <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>; + }; + ++ cache-controller@0x10502000 { ++ arm,data-latency = <1 2 0>; ++ }; ++ + clock: clock-controller@0x10030000 { + compatible = "samsung,exynos4412-clock"; + reg = <0x10030000 0x20000>; +-- +1.8.3.2 + diff --git a/patches.tizen/0004-fs-jbd2-force-commit-to-free-jbd2-s-cma-isolated-pag.patch b/patches.tizen/0004-fs-jbd2-force-commit-to-free-jbd2-s-cma-isolated-pag.patch new file mode 100644 index 00000000000..0d968b19741 --- /dev/null +++ b/patches.tizen/0004-fs-jbd2-force-commit-to-free-jbd2-s-cma-isolated-pag.patch @@ -0,0 +1,42 @@ +From 429ab036e5b0de2292a4b2c207acde3bd436092a Mon Sep 17 00:00:00 2001 +From: Marek Szyprowski <m.szyprowski@samsung.com> +Date: Tue, 4 Sep 2012 10:44:49 +0200 +Subject: [PATCH 0004/1302] fs: jbd2: force commit to free jbd2's cma/isolated + page + +Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + fs/jbd2/transaction.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c +index e0c0bc2..ca188f5 100644 +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -1776,8 +1776,22 @@ int jbd2_journal_try_to_free_buffers(journal_t *journal, + __journal_try_to_free_buffer(journal, bh); + jbd2_journal_put_journal_head(jh); + jbd_unlock_bh_state(bh); ++ ++#ifndef CONFIG_CMA + if (buffer_jbd(bh)) + goto busy; ++#else ++ if (buffer_jbd(bh)) { ++ unsigned mt = get_pageblock_migratetype(page); ++ /* ++ * Workaround: In case of CMA page, just commit journal. ++ */ ++ if (mt == MIGRATE_ISOLATE || mt == MIGRATE_CMA) ++ jbd2_journal_force_commit(journal); ++ else ++ goto busy; ++ } ++#endif + } while ((bh = bh->b_this_page) != head); + + ret = try_to_free_buffers(page); +-- +1.8.3.2 + diff --git a/patches.tizen/0005-fs-buffer.c-Revoke-LRU-when-trying-to-drop-buffers.patch b/patches.tizen/0005-fs-buffer.c-Revoke-LRU-when-trying-to-drop-buffers.patch new file mode 100644 index 00000000000..41a0caf2c18 --- /dev/null +++ b/patches.tizen/0005-fs-buffer.c-Revoke-LRU-when-trying-to-drop-buffers.patch @@ -0,0 +1,95 @@ +From e2154558e6cea6a813e53e8b1c1f346d9b050d5b Mon Sep 17 00:00:00 2001 +From: Laura Abbott <lauraa@codeaurora.org> +Date: Wed, 12 Sep 2012 09:36:16 +0200 +Subject: [PATCH 0005/1302] fs/buffer.c: Revoke LRU when trying to drop buffers + +When a buffer is added to the LRU list, a reference is taken which is +not dropped until the buffer is evicted from the LRU list. This is the +correct behavior, however this LRU reference will prevent the buffer +from being dropped. This means that the buffer can't actually be dropped +until it is selected for eviction. There's no bound on the time spent +on the LRU list, which means that the buffer may be undroppable for +very long periods of time. Given that migration involves dropping +buffers, the associated page is now unmigratible for long periods of +time as well. CMA relies on being able to migrate a specific range +of pages, so these these types of failures make CMA significantly +less reliable, especially under high filesystem usage. + +Rather than waiting for the LRU algorithm to eventually kick out +the buffer, explicitly remove the buffer from the LRU list when trying +to drop it. There is still the possibility that the buffer +could be added back on the list, but that indicates the buffer is +still in use and would probably have other 'in use' indicates to +prevent dropping. + +Signed-off-by: Laura Abbott <lauraa@codeaurora.org> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + fs/buffer.c | 38 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +diff --git a/fs/buffer.c b/fs/buffer.c +index d2a4d1b..087816b 100644 +--- a/fs/buffer.c ++++ b/fs/buffer.c +@@ -1413,12 +1413,49 @@ static bool has_bh_in_lru(int cpu, void *dummy) + return 0; + } + ++static void __evict_bh_lru(void *arg) ++{ ++ struct bh_lru *b = &get_cpu_var(bh_lrus); ++ struct buffer_head *bh = arg; ++ int i; ++ ++ for (i = 0; i < BH_LRU_SIZE; i++) { ++ if (b->bhs[i] == bh) { ++ brelse(b->bhs[i]); ++ b->bhs[i] = NULL; ++ goto out; ++ } ++ } ++out: ++ put_cpu_var(bh_lrus); ++} ++ ++static bool bh_exists_in_lru(int cpu, void *arg) ++{ ++ struct bh_lru *b = per_cpu_ptr(&bh_lrus, cpu); ++ struct buffer_head *bh = arg; ++ int i; ++ ++ for (i = 0; i < BH_LRU_SIZE; i++) { ++ if (b->bhs[i] == bh) ++ return 1; ++ } ++ ++ return 0; ++ ++} + void invalidate_bh_lrus(void) + { + on_each_cpu_cond(has_bh_in_lru, invalidate_bh_lru, NULL, 1, GFP_KERNEL); + } + EXPORT_SYMBOL_GPL(invalidate_bh_lrus); + ++void evict_bh_lrus(struct buffer_head *bh) ++{ ++ on_each_cpu_cond(bh_exists_in_lru, __evict_bh_lru, bh, 1, GFP_ATOMIC); ++} ++EXPORT_SYMBOL_GPL(evict_bh_lrus); ++ + void set_bh_page(struct buffer_head *bh, + struct page *page, unsigned long offset) + { +@@ -3140,6 +3177,7 @@ drop_buffers(struct page *page, struct buffer_head **buffers_to_free) + + bh = head; + do { ++ evict_bh_lrus(bh); + if (buffer_write_io_error(bh) && page->mapping) + set_bit(AS_EIO, &page->mapping->flags); + if (buffer_busy(bh)) +-- +1.8.3.2 + diff --git a/patches.tizen/0006-mm-cma-allocate-pages-from-CMA-if-NR_FREE_PAGES-appr.patch b/patches.tizen/0006-mm-cma-allocate-pages-from-CMA-if-NR_FREE_PAGES-appr.patch new file mode 100644 index 00000000000..baa43d8f27e --- /dev/null +++ b/patches.tizen/0006-mm-cma-allocate-pages-from-CMA-if-NR_FREE_PAGES-appr.patch @@ -0,0 +1,46 @@ +From 2aeb96c2467ab83034cc2344db35be7c042343ee Mon Sep 17 00:00:00 2001 +From: Marek Szyprowski <m.szyprowski@samsung.com> +Date: Fri, 9 Nov 2012 16:04:23 +0100 +Subject: [PATCH 0006/1302] mm: cma: allocate pages from CMA if NR_FREE_PAGES + approaches low water mark + +It has been observed that system tends to keep a lot of CMA free pages +even in very high memory pressure use cases. The CMA fallback for movable +pages is used very rarely, only when system is completely pruned from +MOVABLE pages, what usually means that the out-of-memory even will be +triggered very soon. To avoid such situation and make better use of CMA +pages, a heuristics is introduced which turns on CMA fallback for movable +pages when the real number of free pages (excluding CMA free pages) +approaches low water mark. + +Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> +Reviewed-by: Kyungmin Park <kyungmin.park@samsung.com> +CC: Michal Nazarewicz <mina86@mina86.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + mm/page_alloc.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index 2ee0fd3..bb92575 100644 +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -1099,6 +1099,15 @@ static struct page *__rmqueue(struct zone *zone, unsigned int order, + { + struct page *page; + ++#ifdef CONFIG_CMA ++ unsigned long nr_free = zone_page_state(zone, NR_FREE_PAGES); ++ unsigned long nr_cma_free = zone_page_state(zone, NR_FREE_CMA_PAGES); ++ ++ if (migratetype == MIGRATE_MOVABLE && nr_cma_free && ++ nr_free - nr_cma_free < 2 * low_wmark_pages(zone)) ++ migratetype = MIGRATE_CMA; ++#endif /* CONFIG_CMA */ ++ + retry_reserve: + page = __rmqueue_smallest(zone, order, migratetype); + +-- +1.8.3.2 + diff --git a/patches.tizen/0007-usb-gadget-s3c-hsotg-Add-device-tree-based-instantia.patch b/patches.tizen/0007-usb-gadget-s3c-hsotg-Add-device-tree-based-instantia.patch new file mode 100644 index 00000000000..3181921075f --- /dev/null +++ b/patches.tizen/0007-usb-gadget-s3c-hsotg-Add-device-tree-based-instantia.patch @@ -0,0 +1,44 @@ +From d2cff49885392b7551d7866fa9708c25b81bf215 Mon Sep 17 00:00:00 2001 +From: Tomasz Figa <t.figa@samsung.com> +Date: Tue, 11 Sep 2012 13:36:51 +0200 +Subject: [PATCH 0007/1302] usb: gadget: s3c-hsotg: Add device tree-based + instantiation + +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + drivers/usb/gadget/s3c-hsotg.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c +index af22f24..8fd9681 100644 +--- a/drivers/usb/gadget/s3c-hsotg.c ++++ b/drivers/usb/gadget/s3c-hsotg.c +@@ -29,6 +29,7 @@ + #include <linux/slab.h> + #include <linux/clk.h> + #include <linux/regulator/consumer.h> ++#include <linux/of_platform.h> + + #include <linux/usb/ch9.h> + #include <linux/usb/gadget.h> +@@ -3648,10 +3649,17 @@ static int s3c_hsotg_remove(struct platform_device *pdev) + #define s3c_hsotg_resume NULL + #endif + ++static const struct of_device_id s3c_hsotg_of_ids[] = { ++ { .compatible = "samsung,s3c-hsotg", }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, s3c_hsotg_of_ids); ++ + static struct platform_driver s3c_hsotg_driver = { + .driver = { + .name = "s3c-hsotg", + .owner = THIS_MODULE, ++ .of_match_table = s3c_hsotg_of_ids, + }, + .probe = s3c_hsotg_probe, + .remove = s3c_hsotg_remove, +-- +1.8.3.2 + diff --git a/patches.tizen/0008-usb-phy-samsung-Select-common-driver-part-implicitly.patch b/patches.tizen/0008-usb-phy-samsung-Select-common-driver-part-implicitly.patch new file mode 100644 index 00000000000..f62d5e0260d --- /dev/null +++ b/patches.tizen/0008-usb-phy-samsung-Select-common-driver-part-implicitly.patch @@ -0,0 +1,36 @@ +From 8457ce3c61cea74b7f69262e398ba235242edadd Mon Sep 17 00:00:00 2001 +From: Tomasz Figa <t.figa@samsung.com> +Date: Mon, 25 Mar 2013 15:48:47 +0100 +Subject: [PATCH 0008/1302] usb: phy: samsung: Select common driver part + implicitly + +Since phy-samsung-usb library can be used only by phy-samsung-usb2 and +phy-samsung-usb3 drivers, there is no need to give explicit control over +its Kconfig symbol. + +This patch makes CONFIG_SAMSUNG_USBPHY symbol hidden and selected +implicitly by CONFIG_SAMSUNG_USB2PHY and CONFIG_SAMSUNG_USB3PHY. + +Signed-off-by: Tomasz Figa <t.figa@samsung.com> +Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + drivers/usb/phy/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig +index 2311b1e..a5a9552 100644 +--- a/drivers/usb/phy/Kconfig ++++ b/drivers/usb/phy/Kconfig +@@ -92,7 +92,7 @@ config OMAP_USB3 + on/off the PHY. + + config SAMSUNG_USBPHY +- tristate "Samsung USB PHY Driver" ++ tristate + help + Enable this to support Samsung USB phy helper driver for Samsung SoCs. + This driver provides common interface to interact, for Samsung USB 2.0 PHY +-- +1.8.3.2 + diff --git a/patches.tizen/0009-usb-phy-samsung-Use-clk_get-to-get-reference-clock.patch b/patches.tizen/0009-usb-phy-samsung-Use-clk_get-to-get-reference-clock.patch new file mode 100644 index 00000000000..7a1a5ed41e1 --- /dev/null +++ b/patches.tizen/0009-usb-phy-samsung-Use-clk_get-to-get-reference-clock.patch @@ -0,0 +1,38 @@ +From 75e1b6b4a47930f988adba7072dd929b22c37d67 Mon Sep 17 00:00:00 2001 +From: Tomasz Figa <t.figa@samsung.com> +Date: Mon, 25 Mar 2013 19:36:22 +0100 +Subject: [PATCH 0009/1302] usb: phy: samsung: Use clk_get to get reference + clock + +There is no need to use devm_clk_get to get a clock that is being put +at the end of the function. + +This patch changes the code getting reference clock to use clk_get +instead of useless in this case devm_clk_get. + +Signed-off-by: Tomasz Figa <t.figa@samsung.com> +Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + drivers/usb/phy/phy-samsung-usb.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/phy/phy-samsung-usb.c b/drivers/usb/phy/phy-samsung-usb.c +index 7b118ee5..62cdb7e 100644 +--- a/drivers/usb/phy/phy-samsung-usb.c ++++ b/drivers/usb/phy/phy-samsung-usb.c +@@ -175,9 +175,9 @@ int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy) + * external crystal clock XXTI + */ + if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) +- ref_clk = devm_clk_get(sphy->dev, "ext_xtal"); ++ ref_clk = clk_get(sphy->dev, "ext_xtal"); + else +- ref_clk = devm_clk_get(sphy->dev, "xusbxti"); ++ ref_clk = clk_get(sphy->dev, "xusbxti"); + if (IS_ERR(ref_clk)) { + dev_err(sphy->dev, "Failed to get reference clock\n"); + return PTR_ERR(ref_clk); +-- +1.8.3.2 + diff --git a/patches.tizen/0010-usb-phy-samsung-Consolidate-reference-clock-rate-han.patch b/patches.tizen/0010-usb-phy-samsung-Consolidate-reference-clock-rate-han.patch new file mode 100644 index 00000000000..e0e22d7cb17 --- /dev/null +++ b/patches.tizen/0010-usb-phy-samsung-Consolidate-reference-clock-rate-han.patch @@ -0,0 +1,252 @@ +From 3abf3521ded9d23d57d5ee8e0a8520363de5fc9a Mon Sep 17 00:00:00 2001 +From: Tomasz Figa <t.figa@samsung.com> +Date: Mon, 25 Mar 2013 16:15:55 +0100 +Subject: [PATCH 0010/1302] usb: phy: samsung: Consolidate reference clock rate + handling + +This patch cleans up handling of reference clock rate in Samsung USB PHY +drivers. It is mostly a cosmetic change but improves error handling in +case of failing to get reference clock or invalid clock rate. + +Signed-off-by: Tomasz Figa <t.figa@samsung.com> +Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + drivers/usb/phy/phy-samsung-usb.c | 114 ++++++++++++++++++++++--------------- + drivers/usb/phy/phy-samsung-usb.h | 7 +++ + drivers/usb/phy/phy-samsung-usb2.c | 8 ++- + drivers/usb/phy/phy-samsung-usb3.c | 6 +- + 4 files changed, 86 insertions(+), 49 deletions(-) + +diff --git a/drivers/usb/phy/phy-samsung-usb.c b/drivers/usb/phy/phy-samsung-usb.c +index 62cdb7e..c40ea32 100644 +--- a/drivers/usb/phy/phy-samsung-usb.c ++++ b/drivers/usb/phy/phy-samsung-usb.c +@@ -162,13 +162,76 @@ int samsung_usbphy_set_type(struct usb_phy *phy, + } + EXPORT_SYMBOL_GPL(samsung_usbphy_set_type); + ++int samsung_usbphy_rate_to_clksel_64xx(struct samsung_usbphy *sphy, ++ unsigned long rate) ++{ ++ unsigned int clksel; ++ ++ switch (rate) { ++ case 12 * MHZ: ++ clksel = PHYCLK_CLKSEL_12M; ++ break; ++ case 24 * MHZ: ++ clksel = PHYCLK_CLKSEL_24M; ++ break; ++ case 48 * MHZ: ++ clksel = PHYCLK_CLKSEL_48M; ++ break; ++ default: ++ dev_err(sphy->dev, ++ "Invalid reference clock frequency: %lu\n", rate); ++ return -EINVAL; ++ } ++ ++ return clksel; ++} ++EXPORT_SYMBOL_GPL(samsung_usbphy_rate_to_clksel_64xx); ++ ++int samsung_usbphy_rate_to_clksel_4x12(struct samsung_usbphy *sphy, ++ unsigned long rate) ++{ ++ unsigned int clksel; ++ ++ switch (rate) { ++ case 9600 * KHZ: ++ clksel = FSEL_CLKSEL_9600K; ++ break; ++ case 10 * MHZ: ++ clksel = FSEL_CLKSEL_10M; ++ break; ++ case 12 * MHZ: ++ clksel = FSEL_CLKSEL_12M; ++ break; ++ case 19200 * KHZ: ++ clksel = FSEL_CLKSEL_19200K; ++ break; ++ case 20 * MHZ: ++ clksel = FSEL_CLKSEL_20M; ++ break; ++ case 24 * MHZ: ++ clksel = FSEL_CLKSEL_24M; ++ break; ++ case 50 * MHZ: ++ clksel = FSEL_CLKSEL_50M; ++ break; ++ default: ++ dev_err(sphy->dev, ++ "Invalid reference clock frequency: %lu\n", rate); ++ return -EINVAL; ++ } ++ ++ return clksel; ++} ++EXPORT_SYMBOL_GPL(samsung_usbphy_rate_to_clksel_4x12); ++ + /* + * Returns reference clock frequency selection value + */ + int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy) + { + struct clk *ref_clk; +- int refclk_freq = 0; ++ unsigned long rate; ++ int refclk_freq; + + /* + * In exynos5250 USB host and device PHY use +@@ -183,52 +246,9 @@ int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy) + return PTR_ERR(ref_clk); + } + +- if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) { +- /* set clock frequency for PLL */ +- switch (clk_get_rate(ref_clk)) { +- case 9600 * KHZ: +- refclk_freq = FSEL_CLKSEL_9600K; +- break; +- case 10 * MHZ: +- refclk_freq = FSEL_CLKSEL_10M; +- break; +- case 12 * MHZ: +- refclk_freq = FSEL_CLKSEL_12M; +- break; +- case 19200 * KHZ: +- refclk_freq = FSEL_CLKSEL_19200K; +- break; +- case 20 * MHZ: +- refclk_freq = FSEL_CLKSEL_20M; +- break; +- case 50 * MHZ: +- refclk_freq = FSEL_CLKSEL_50M; +- break; +- case 24 * MHZ: +- default: +- /* default reference clock */ +- refclk_freq = FSEL_CLKSEL_24M; +- break; +- } +- } else { +- switch (clk_get_rate(ref_clk)) { +- case 12 * MHZ: +- refclk_freq = PHYCLK_CLKSEL_12M; +- break; +- case 24 * MHZ: +- refclk_freq = PHYCLK_CLKSEL_24M; +- break; +- case 48 * MHZ: +- refclk_freq = PHYCLK_CLKSEL_48M; +- break; +- default: +- if (sphy->drv_data->cpu_type == TYPE_S3C64XX) +- refclk_freq = PHYCLK_CLKSEL_48M; +- else +- refclk_freq = PHYCLK_CLKSEL_24M; +- break; +- } +- } ++ rate = clk_get_rate(ref_clk); ++ refclk_freq = sphy->drv_data->rate_to_clksel(sphy, rate); ++ + clk_put(ref_clk); + + return refclk_freq; +diff --git a/drivers/usb/phy/phy-samsung-usb.h b/drivers/usb/phy/phy-samsung-usb.h +index 70a9cae..0336f6b 100644 +--- a/drivers/usb/phy/phy-samsung-usb.h ++++ b/drivers/usb/phy/phy-samsung-usb.h +@@ -244,6 +244,8 @@ enum samsung_cpu_type { + TYPE_EXYNOS5250, + }; + ++struct samsung_usbphy; ++ + /* + * struct samsung_usbphy_drvdata - driver data for various SoC variants + * @cpu_type: machine identifier +@@ -268,6 +270,7 @@ struct samsung_usbphy_drvdata { + int hostphy_en_mask; + u32 devphy_reg_offset; + u32 hostphy_reg_offset; ++ int (*rate_to_clksel)(struct samsung_usbphy *, unsigned long); + }; + + /* +@@ -325,3 +328,7 @@ extern void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy); + extern int samsung_usbphy_set_type(struct usb_phy *phy, + enum samsung_usb_phy_type phy_type); + extern int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy); ++extern int samsung_usbphy_rate_to_clksel_64xx(struct samsung_usbphy *sphy, ++ unsigned long rate); ++extern int samsung_usbphy_rate_to_clksel_4x12(struct samsung_usbphy *sphy, ++ unsigned long rate); +diff --git a/drivers/usb/phy/phy-samsung-usb2.c b/drivers/usb/phy/phy-samsung-usb2.c +index 9d5e273..be6031d 100644 +--- a/drivers/usb/phy/phy-samsung-usb2.c ++++ b/drivers/usb/phy/phy-samsung-usb2.c +@@ -408,7 +408,10 @@ static int samsung_usb2phy_probe(struct platform_device *pdev) + sphy->phy.label = "samsung-usb2phy"; + sphy->phy.init = samsung_usb2phy_init; + sphy->phy.shutdown = samsung_usb2phy_shutdown; +- sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy); ++ ++ sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy); ++ if (sphy->ref_clk_freq < 0) ++ return -EINVAL; + + sphy->phy.otg = otg; + sphy->phy.otg->phy = &sphy->phy; +@@ -438,18 +441,21 @@ static int samsung_usb2phy_remove(struct platform_device *pdev) + static const struct samsung_usbphy_drvdata usb2phy_s3c64xx = { + .cpu_type = TYPE_S3C64XX, + .devphy_en_mask = S3C64XX_USBPHY_ENABLE, ++ .rate_to_clksel = samsung_usbphy_rate_to_clksel_64xx, + }; + + static const struct samsung_usbphy_drvdata usb2phy_exynos4 = { + .cpu_type = TYPE_EXYNOS4210, + .devphy_en_mask = EXYNOS_USBPHY_ENABLE, + .hostphy_en_mask = EXYNOS_USBPHY_ENABLE, ++ .rate_to_clksel = samsung_usbphy_rate_to_clksel_64xx, + }; + + static struct samsung_usbphy_drvdata usb2phy_exynos5 = { + .cpu_type = TYPE_EXYNOS5250, + .hostphy_en_mask = EXYNOS_USBPHY_ENABLE, + .hostphy_reg_offset = EXYNOS_USBHOST_PHY_CTRL_OFFSET, ++ .rate_to_clksel = samsung_usbphy_rate_to_clksel_4x12, + }; + + #ifdef CONFIG_OF +diff --git a/drivers/usb/phy/phy-samsung-usb3.c b/drivers/usb/phy/phy-samsung-usb3.c +index 5a9efcb..ec44b35 100644 +--- a/drivers/usb/phy/phy-samsung-usb3.c ++++ b/drivers/usb/phy/phy-samsung-usb3.c +@@ -274,7 +274,10 @@ static int samsung_usb3phy_probe(struct platform_device *pdev) + sphy->phy.init = samsung_usb3phy_init; + sphy->phy.shutdown = samsung_usb3phy_shutdown; + sphy->drv_data = samsung_usbphy_get_driver_data(pdev); +- sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy); ++ ++ sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy); ++ if (sphy->ref_clk_freq < 0) ++ return -EINVAL; + + spin_lock_init(&sphy->lock); + +@@ -300,6 +303,7 @@ static int samsung_usb3phy_remove(struct platform_device *pdev) + static struct samsung_usbphy_drvdata usb3phy_exynos5 = { + .cpu_type = TYPE_EXYNOS5250, + .devphy_en_mask = EXYNOS_USBPHY_ENABLE, ++ .rate_to_clksel = samsung_usbphy_rate_to_clksel_4x12, + }; + + #ifdef CONFIG_OF +-- +1.8.3.2 + diff --git a/patches.tizen/0011-usb-phy-samsung-Pass-set_isolation-callback-through-.patch b/patches.tizen/0011-usb-phy-samsung-Pass-set_isolation-callback-through-.patch new file mode 100644 index 00000000000..a717f632712 --- /dev/null +++ b/patches.tizen/0011-usb-phy-samsung-Pass-set_isolation-callback-through-.patch @@ -0,0 +1,188 @@ +From 1fd2b2ad555a88707683d0241d2ae71874b553a6 Mon Sep 17 00:00:00 2001 +From: Tomasz Figa <t.figa@samsung.com> +Date: Mon, 25 Mar 2013 16:40:52 +0100 +Subject: [PATCH 0011/1302] usb: phy: samsung: Pass set_isolation callback + through driver data + +This patch extends driver data structure with set_isolation callback, +which allows to remove the need for checking for SoC type in a switch +statement. + +Signed-off-by: Tomasz Figa <t.figa@samsung.com> +Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + drivers/usb/phy/phy-samsung-usb.c | 36 ++++++++---------------------------- + drivers/usb/phy/phy-samsung-usb.h | 4 +++- + drivers/usb/phy/phy-samsung-usb2.c | 11 +++++++---- + drivers/usb/phy/phy-samsung-usb3.c | 7 +++++-- + 4 files changed, 23 insertions(+), 35 deletions(-) + +diff --git a/drivers/usb/phy/phy-samsung-usb.c b/drivers/usb/phy/phy-samsung-usb.c +index c40ea32..7a1ed90 100644 +--- a/drivers/usb/phy/phy-samsung-usb.c ++++ b/drivers/usb/phy/phy-samsung-usb.c +@@ -73,7 +73,7 @@ EXPORT_SYMBOL_GPL(samsung_usbphy_parse_dt); + * Here 'on = true' would mean USB PHY block is isolated, hence + * de-activated and vice-versa. + */ +-void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on) ++void samsung_usbphy_set_isolation_4210(struct samsung_usbphy *sphy, bool on) + { + void __iomem *reg = NULL; + u32 reg_val; +@@ -84,32 +84,12 @@ void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on) + return; + } + +- switch (sphy->drv_data->cpu_type) { +- case TYPE_S3C64XX: +- /* +- * Do nothing: We will add here once S3C64xx goes for DT support +- */ +- break; +- case TYPE_EXYNOS4210: +- /* +- * Fall through since exynos4210 and exynos5250 have similar +- * register architecture: two separate registers for host and +- * device phy control with enable bit at position 0. +- */ +- case TYPE_EXYNOS5250: +- if (sphy->phy_type == USB_PHY_TYPE_DEVICE) { +- reg = sphy->pmuregs + +- sphy->drv_data->devphy_reg_offset; +- en_mask = sphy->drv_data->devphy_en_mask; +- } else if (sphy->phy_type == USB_PHY_TYPE_HOST) { +- reg = sphy->pmuregs + +- sphy->drv_data->hostphy_reg_offset; +- en_mask = sphy->drv_data->hostphy_en_mask; +- } +- break; +- default: +- dev_err(sphy->dev, "Invalid SoC type\n"); +- return; ++ if (sphy->phy_type == USB_PHY_TYPE_DEVICE) { ++ reg = sphy->pmuregs + sphy->drv_data->devphy_reg_offset; ++ en_mask = sphy->drv_data->devphy_en_mask; ++ } else if (sphy->phy_type == USB_PHY_TYPE_HOST) { ++ reg = sphy->pmuregs + sphy->drv_data->hostphy_reg_offset; ++ en_mask = sphy->drv_data->hostphy_en_mask; + } + + reg_val = readl(reg); +@@ -121,7 +101,7 @@ void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on) + + writel(reg_val, reg); + } +-EXPORT_SYMBOL_GPL(samsung_usbphy_set_isolation); ++EXPORT_SYMBOL_GPL(samsung_usbphy_set_isolation_4210); + + /* + * Configure the mode of working of usb-phy here: HOST/DEVICE. +diff --git a/drivers/usb/phy/phy-samsung-usb.h b/drivers/usb/phy/phy-samsung-usb.h +index 0336f6b..5203784 100644 +--- a/drivers/usb/phy/phy-samsung-usb.h ++++ b/drivers/usb/phy/phy-samsung-usb.h +@@ -271,6 +271,7 @@ struct samsung_usbphy_drvdata { + u32 devphy_reg_offset; + u32 hostphy_reg_offset; + int (*rate_to_clksel)(struct samsung_usbphy *, unsigned long); ++ void (*set_isolation)(struct samsung_usbphy *, bool); + }; + + /* +@@ -323,7 +324,8 @@ static inline const struct samsung_usbphy_drvdata + } + + extern int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy); +-extern void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on); ++extern void samsung_usbphy_set_isolation_4210(struct samsung_usbphy *sphy, ++ bool on); + extern void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy); + extern int samsung_usbphy_set_type(struct usb_phy *phy, + enum samsung_usb_phy_type phy_type); +diff --git a/drivers/usb/phy/phy-samsung-usb2.c b/drivers/usb/phy/phy-samsung-usb2.c +index be6031d..a01247e 100644 +--- a/drivers/usb/phy/phy-samsung-usb2.c ++++ b/drivers/usb/phy/phy-samsung-usb2.c +@@ -284,8 +284,8 @@ static int samsung_usb2phy_init(struct usb_phy *phy) + /* Disable phy isolation */ + if (sphy->plat && sphy->plat->pmu_isolation) + sphy->plat->pmu_isolation(false); +- else +- samsung_usbphy_set_isolation(sphy, false); ++ else if (sphy->drv_data->set_isolation) ++ sphy->drv_data->set_isolation(sphy, false); + + /* Selecting Host/OTG mode; After reset USB2.0PHY_CFG: HOST */ + samsung_usbphy_cfg_sel(sphy); +@@ -342,8 +342,8 @@ static void samsung_usb2phy_shutdown(struct usb_phy *phy) + /* Enable phy isolation */ + if (sphy->plat && sphy->plat->pmu_isolation) + sphy->plat->pmu_isolation(true); +- else +- samsung_usbphy_set_isolation(sphy, true); ++ else if (sphy->drv_data->set_isolation) ++ sphy->drv_data->set_isolation(sphy, true); + + spin_unlock_irqrestore(&sphy->lock, flags); + +@@ -442,6 +442,7 @@ static const struct samsung_usbphy_drvdata usb2phy_s3c64xx = { + .cpu_type = TYPE_S3C64XX, + .devphy_en_mask = S3C64XX_USBPHY_ENABLE, + .rate_to_clksel = samsung_usbphy_rate_to_clksel_64xx, ++ .set_isolation = NULL, /* TODO */ + }; + + static const struct samsung_usbphy_drvdata usb2phy_exynos4 = { +@@ -449,6 +450,7 @@ static const struct samsung_usbphy_drvdata usb2phy_exynos4 = { + .devphy_en_mask = EXYNOS_USBPHY_ENABLE, + .hostphy_en_mask = EXYNOS_USBPHY_ENABLE, + .rate_to_clksel = samsung_usbphy_rate_to_clksel_64xx, ++ .set_isolation = samsung_usbphy_set_isolation_4210, + }; + + static struct samsung_usbphy_drvdata usb2phy_exynos5 = { +@@ -456,6 +458,7 @@ static struct samsung_usbphy_drvdata usb2phy_exynos5 = { + .hostphy_en_mask = EXYNOS_USBPHY_ENABLE, + .hostphy_reg_offset = EXYNOS_USBHOST_PHY_CTRL_OFFSET, + .rate_to_clksel = samsung_usbphy_rate_to_clksel_4x12, ++ .set_isolation = samsung_usbphy_set_isolation_4210, + }; + + #ifdef CONFIG_OF +diff --git a/drivers/usb/phy/phy-samsung-usb3.c b/drivers/usb/phy/phy-samsung-usb3.c +index ec44b35..3a30a5e 100644 +--- a/drivers/usb/phy/phy-samsung-usb3.c ++++ b/drivers/usb/phy/phy-samsung-usb3.c +@@ -184,7 +184,8 @@ static int samsung_usb3phy_init(struct usb_phy *phy) + samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); + + /* Disable phy isolation */ +- samsung_usbphy_set_isolation(sphy, false); ++ if (sphy->drv_data->set_isolation) ++ sphy->drv_data->set_isolation(sphy, false); + + /* Initialize usb phy registers */ + samsung_exynos5_usb3phy_enable(sphy); +@@ -221,7 +222,8 @@ static void samsung_usb3phy_shutdown(struct usb_phy *phy) + samsung_exynos5_usb3phy_disable(sphy); + + /* Enable phy isolation */ +- samsung_usbphy_set_isolation(sphy, true); ++ if (sphy->drv_data->set_isolation) ++ sphy->drv_data->set_isolation(sphy, true); + + spin_unlock_irqrestore(&sphy->lock, flags); + +@@ -304,6 +306,7 @@ static struct samsung_usbphy_drvdata usb3phy_exynos5 = { + .cpu_type = TYPE_EXYNOS5250, + .devphy_en_mask = EXYNOS_USBPHY_ENABLE, + .rate_to_clksel = samsung_usbphy_rate_to_clksel_4x12, ++ .set_isolation = samsung_usbphy_set_isolation_4210, + }; + + #ifdef CONFIG_OF +-- +1.8.3.2 + diff --git a/patches.tizen/0012-usb-phy-samsung-Pass-enable-disable-callbacks-throug.patch b/patches.tizen/0012-usb-phy-samsung-Pass-enable-disable-callbacks-throug.patch new file mode 100644 index 00000000000..00a0c7aff9d --- /dev/null +++ b/patches.tizen/0012-usb-phy-samsung-Pass-enable-disable-callbacks-throug.patch @@ -0,0 +1,139 @@ +From 0b1ad1c2d3320a3e31f3f66e4a1c29d6763006cb Mon Sep 17 00:00:00 2001 +From: Tomasz Figa <t.figa@samsung.com> +Date: Mon, 25 Mar 2013 16:57:32 +0100 +Subject: [PATCH 0012/1302] usb: phy: samsung: Pass enable/disable callbacks + through driver data + +To remove unnecessary if statements, this patch introduces phy_enable +and phy_disable callbacks in driver data structure that implement +SoC-specific PHY initialization and deinitialization. + +Signed-off-by: Tomasz Figa <t.figa@samsung.com> +Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + drivers/usb/phy/phy-samsung-usb.h | 2 ++ + drivers/usb/phy/phy-samsung-usb2.c | 16 ++++++++-------- + drivers/usb/phy/phy-samsung-usb3.c | 10 +++++----- + 3 files changed, 15 insertions(+), 13 deletions(-) + +diff --git a/drivers/usb/phy/phy-samsung-usb.h b/drivers/usb/phy/phy-samsung-usb.h +index 5203784..31e2ec3 100644 +--- a/drivers/usb/phy/phy-samsung-usb.h ++++ b/drivers/usb/phy/phy-samsung-usb.h +@@ -272,6 +272,8 @@ struct samsung_usbphy_drvdata { + u32 hostphy_reg_offset; + int (*rate_to_clksel)(struct samsung_usbphy *, unsigned long); + void (*set_isolation)(struct samsung_usbphy *, bool); ++ void (*phy_enable)(struct samsung_usbphy *); ++ void (*phy_disable)(struct samsung_usbphy *); + }; + + /* +diff --git a/drivers/usb/phy/phy-samsung-usb2.c b/drivers/usb/phy/phy-samsung-usb2.c +index a01247e..1c3abd4 100644 +--- a/drivers/usb/phy/phy-samsung-usb2.c ++++ b/drivers/usb/phy/phy-samsung-usb2.c +@@ -291,10 +291,7 @@ static int samsung_usb2phy_init(struct usb_phy *phy) + samsung_usbphy_cfg_sel(sphy); + + /* Initialize usb phy registers */ +- if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) +- samsung_exynos5_usb2phy_enable(sphy); +- else +- samsung_usb2phy_enable(sphy); ++ sphy->drv_data->phy_enable(sphy); + + spin_unlock_irqrestore(&sphy->lock, flags); + +@@ -334,10 +331,7 @@ static void samsung_usb2phy_shutdown(struct usb_phy *phy) + } + + /* De-initialize usb phy registers */ +- if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) +- samsung_exynos5_usb2phy_disable(sphy); +- else +- samsung_usb2phy_disable(sphy); ++ sphy->drv_data->phy_disable(sphy); + + /* Enable phy isolation */ + if (sphy->plat && sphy->plat->pmu_isolation) +@@ -443,6 +437,8 @@ static const struct samsung_usbphy_drvdata usb2phy_s3c64xx = { + .devphy_en_mask = S3C64XX_USBPHY_ENABLE, + .rate_to_clksel = samsung_usbphy_rate_to_clksel_64xx, + .set_isolation = NULL, /* TODO */ ++ .phy_enable = samsung_usb2phy_enable, ++ .phy_disable = samsung_usb2phy_disable, + }; + + static const struct samsung_usbphy_drvdata usb2phy_exynos4 = { +@@ -451,6 +447,8 @@ static const struct samsung_usbphy_drvdata usb2phy_exynos4 = { + .hostphy_en_mask = EXYNOS_USBPHY_ENABLE, + .rate_to_clksel = samsung_usbphy_rate_to_clksel_64xx, + .set_isolation = samsung_usbphy_set_isolation_4210, ++ .phy_enable = samsung_usb2phy_enable, ++ .phy_disable = samsung_usb2phy_disable, + }; + + static struct samsung_usbphy_drvdata usb2phy_exynos5 = { +@@ -459,6 +457,8 @@ static struct samsung_usbphy_drvdata usb2phy_exynos5 = { + .hostphy_reg_offset = EXYNOS_USBHOST_PHY_CTRL_OFFSET, + .rate_to_clksel = samsung_usbphy_rate_to_clksel_4x12, + .set_isolation = samsung_usbphy_set_isolation_4210, ++ .phy_enable = samsung_exynos5_usb2phy_enable, ++ .phy_disable = samsung_exynos5_usb2phy_disable, + }; + + #ifdef CONFIG_OF +diff --git a/drivers/usb/phy/phy-samsung-usb3.c b/drivers/usb/phy/phy-samsung-usb3.c +index 3a30a5e..300e0cf 100644 +--- a/drivers/usb/phy/phy-samsung-usb3.c ++++ b/drivers/usb/phy/phy-samsung-usb3.c +@@ -65,7 +65,7 @@ static u32 samsung_usb3phy_set_refclk(struct samsung_usbphy *sphy) + return reg; + } + +-static int samsung_exynos5_usb3phy_enable(struct samsung_usbphy *sphy) ++static void samsung_exynos5_usb3phy_enable(struct samsung_usbphy *sphy) + { + void __iomem *regs = sphy->regs; + u32 phyparam0; +@@ -133,8 +133,6 @@ static int samsung_exynos5_usb3phy_enable(struct samsung_usbphy *sphy) + + phyclkrst &= ~(PHYCLKRST_PORTRESET); + writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST); +- +- return 0; + } + + static void samsung_exynos5_usb3phy_disable(struct samsung_usbphy *sphy) +@@ -188,7 +186,7 @@ static int samsung_usb3phy_init(struct usb_phy *phy) + sphy->drv_data->set_isolation(sphy, false); + + /* Initialize usb phy registers */ +- samsung_exynos5_usb3phy_enable(sphy); ++ sphy->drv_data->phy_enable(sphy); + + spin_unlock_irqrestore(&sphy->lock, flags); + +@@ -219,7 +217,7 @@ static void samsung_usb3phy_shutdown(struct usb_phy *phy) + samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); + + /* De-initialize usb phy registers */ +- samsung_exynos5_usb3phy_disable(sphy); ++ sphy->drv_data->phy_disable(sphy); + + /* Enable phy isolation */ + if (sphy->drv_data->set_isolation) +@@ -307,6 +305,8 @@ static struct samsung_usbphy_drvdata usb3phy_exynos5 = { + .devphy_en_mask = EXYNOS_USBPHY_ENABLE, + .rate_to_clksel = samsung_usbphy_rate_to_clksel_4x12, + .set_isolation = samsung_usbphy_set_isolation_4210, ++ .phy_enable = samsung_exynos5_usb3phy_enable, ++ .phy_disable = samsung_exynos5_usb3phy_disable, + }; + + #ifdef CONFIG_OF +-- +1.8.3.2 + diff --git a/patches.tizen/0013-usb-phy-samsung-Add-support-for-USB-2.0-PHY-on-Exyno.patch b/patches.tizen/0013-usb-phy-samsung-Add-support-for-USB-2.0-PHY-on-Exyno.patch new file mode 100644 index 00000000000..30c889192de --- /dev/null +++ b/patches.tizen/0013-usb-phy-samsung-Add-support-for-USB-2.0-PHY-on-Exyno.patch @@ -0,0 +1,88 @@ +From b02d45e230000601faad72811548bb3d93203152 Mon Sep 17 00:00:00 2001 +From: Tomasz Figa <t.figa@samsung.com> +Date: Mon, 25 Mar 2013 17:39:07 +0100 +Subject: [PATCH 0013/1302] usb: phy: samsung: Add support for USB 2.0 PHY on + Exynos 4x12 + +This patch adds driver data for Exynos 4x12 USB 2.0 PHY. + +Signed-off-by: Tomasz Figa <t.figa@samsung.com> +Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + drivers/usb/phy/phy-samsung-usb.h | 1 + + drivers/usb/phy/phy-samsung-usb2.c | 18 ++++++++++++++++++ + 2 files changed, 19 insertions(+) + +diff --git a/drivers/usb/phy/phy-samsung-usb.h b/drivers/usb/phy/phy-samsung-usb.h +index 31e2ec3..585d12f 100644 +--- a/drivers/usb/phy/phy-samsung-usb.h ++++ b/drivers/usb/phy/phy-samsung-usb.h +@@ -241,6 +241,7 @@ + enum samsung_cpu_type { + TYPE_S3C64XX, + TYPE_EXYNOS4210, ++ TYPE_EXYNOS4X12, + TYPE_EXYNOS5250, + }; + +diff --git a/drivers/usb/phy/phy-samsung-usb2.c b/drivers/usb/phy/phy-samsung-usb2.c +index 1c3abd4..03180c0 100644 +--- a/drivers/usb/phy/phy-samsung-usb2.c ++++ b/drivers/usb/phy/phy-samsung-usb2.c +@@ -177,6 +177,7 @@ static void samsung_usb2phy_enable(struct samsung_usbphy *sphy) + rstcon |= RSTCON_SWRST; + break; + case TYPE_EXYNOS4210: ++ case TYPE_EXYNOS4X12: + phypwr &= ~PHYPWR_NORMAL_MASK_PHY0; + rstcon |= RSTCON_SWRST; + default: +@@ -240,6 +241,7 @@ static void samsung_usb2phy_disable(struct samsung_usbphy *sphy) + phypwr |= PHYPWR_NORMAL_MASK; + break; + case TYPE_EXYNOS4210: ++ case TYPE_EXYNOS4X12: + phypwr |= PHYPWR_NORMAL_MASK_PHY0; + default: + break; +@@ -451,6 +453,16 @@ static const struct samsung_usbphy_drvdata usb2phy_exynos4 = { + .phy_disable = samsung_usb2phy_disable, + }; + ++static const struct samsung_usbphy_drvdata usb2phy_exynos4x12 = { ++ .cpu_type = TYPE_EXYNOS4X12, ++ .devphy_en_mask = EXYNOS_USBPHY_ENABLE, ++ .hostphy_en_mask = EXYNOS_USBPHY_ENABLE, ++ .rate_to_clksel = samsung_usbphy_rate_to_clksel_4x12, ++ .set_isolation = samsung_usbphy_set_isolation_4210, ++ .phy_enable = samsung_usb2phy_enable, ++ .phy_disable = samsung_usb2phy_disable, ++}; ++ + static struct samsung_usbphy_drvdata usb2phy_exynos5 = { + .cpu_type = TYPE_EXYNOS5250, + .hostphy_en_mask = EXYNOS_USBPHY_ENABLE, +@@ -470,6 +482,9 @@ static const struct of_device_id samsung_usbphy_dt_match[] = { + .compatible = "samsung,exynos4210-usb2phy", + .data = &usb2phy_exynos4, + }, { ++ .compatible = "samsung,exynos4x12-usb2phy", ++ .data = &usb2phy_exynos4x12, ++ }, { + .compatible = "samsung,exynos5250-usb2phy", + .data = &usb2phy_exynos5 + }, +@@ -486,6 +501,9 @@ static struct platform_device_id samsung_usbphy_driver_ids[] = { + .name = "exynos4210-usb2phy", + .driver_data = (unsigned long)&usb2phy_exynos4, + }, { ++ .name = "exynos4x12-usb2phy", ++ .driver_data = (unsigned long)&usb2phy_exynos4x12, ++ }, { + .name = "exynos5250-usb2phy", + .driver_data = (unsigned long)&usb2phy_exynos5, + }, +-- +1.8.3.2 + diff --git a/patches.tizen/0014-ARM-dts-exynos4-Add-node-for-hsotg.patch b/patches.tizen/0014-ARM-dts-exynos4-Add-node-for-hsotg.patch new file mode 100644 index 00000000000..92425a892a3 --- /dev/null +++ b/patches.tizen/0014-ARM-dts-exynos4-Add-node-for-hsotg.patch @@ -0,0 +1,32 @@ +From 23b3d46f3bfbd2f3f1a53b5210a986667300e25b Mon Sep 17 00:00:00 2001 +From: Tomasz Figa <t.figa@samsung.com> +Date: Tue, 11 Sep 2012 13:37:40 +0200 +Subject: [PATCH 0014/1302] ARM: dts: exynos4: Add node for hsotg + +Signed-off-by: Tomasz Figa <t.figa@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4.dtsi | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi +index b90bab3..5f57f59 100644 +--- a/arch/arm/boot/dts/exynos4.dtsi ++++ b/arch/arm/boot/dts/exynos4.dtsi +@@ -350,6 +350,13 @@ + status = "disabled"; + }; + ++ hsotg@12480000 { ++ compatible = "samsung,s3c-hsotg"; ++ reg = <0x12480000 0x20000>; ++ interrupts = <0 71 0>; ++ status = "disabled"; ++ }; ++ + amba { + #address-cells = <1>; + #size-cells = <1>; +-- +1.8.3.2 + diff --git a/patches.tizen/0015-iommu-exynos-do-not-include-removed-header.patch b/patches.tizen/0015-iommu-exynos-do-not-include-removed-header.patch new file mode 100644 index 00000000000..f24970217db --- /dev/null +++ b/patches.tizen/0015-iommu-exynos-do-not-include-removed-header.patch @@ -0,0 +1,37 @@ +From cbffb3bc2d93c6b044332fc24fce091cedef80ff Mon Sep 17 00:00:00 2001 +From: Cho KyongHo <pullip.cho@samsung.com> +Date: Fri, 26 Jul 2013 20:26:10 +0900 +Subject: [PATCH 0015/1302] iommu/exynos: do not include removed header + +This commit remove <mach/sysmmu.h> which is removed. + +Signed-off-by: Cho KyongHo <pullip.cho@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + drivers/iommu/exynos-iommu.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c +index 3f32d64..233f382 100644 +--- a/drivers/iommu/exynos-iommu.c ++++ b/drivers/iommu/exynos-iommu.c +@@ -12,6 +12,7 @@ + #define DEBUG + #endif + ++#include <linux/kernel.h> + #include <linux/io.h> + #include <linux/interrupt.h> + #include <linux/platform_device.h> +@@ -29,8 +30,6 @@ + #include <asm/cacheflush.h> + #include <asm/pgtable.h> + +-#include <mach/sysmmu.h> +- + /* We does not consider super section mapping (16MB) */ + #define SECT_ORDER 20 + #define LPAGE_ORDER 16 +-- +1.8.3.2 + diff --git a/patches.tizen/0016-iommu-exynos-add-missing-cache-flush-for-removed-pag.patch b/patches.tizen/0016-iommu-exynos-add-missing-cache-flush-for-removed-pag.patch new file mode 100644 index 00000000000..118a322c5f3 --- /dev/null +++ b/patches.tizen/0016-iommu-exynos-add-missing-cache-flush-for-removed-pag.patch @@ -0,0 +1,40 @@ +From bc5501f6b0afe076af0f30845221dbb4834c6ed4 Mon Sep 17 00:00:00 2001 +From: Cho KyongHo <pullip.cho@samsung.com> +Date: Fri, 26 Jul 2013 20:26:28 +0900 +Subject: [PATCH 0016/1302] iommu/exynos: add missing cache flush for removed + page table entries + +This commit adds cache flush for removed small and large page entries +in exynos_iommu_unmap(). Missing cache flush of removed page table +entries can cause missing page fault interrupt when a master IP +accesses an unmapped area. + +Signed-off-by: Cho KyongHo <pullip.cho@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + drivers/iommu/exynos-iommu.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c +index 233f382..e3be3e5 100644 +--- a/drivers/iommu/exynos-iommu.c ++++ b/drivers/iommu/exynos-iommu.c +@@ -1002,6 +1002,7 @@ static size_t exynos_iommu_unmap(struct iommu_domain *domain, + if (lv2ent_small(ent)) { + *ent = 0; + size = SPAGE_SIZE; ++ pgtable_flush(ent, ent +1); + priv->lv2entcnt[lv1ent_offset(iova)] += 1; + goto done; + } +@@ -1010,6 +1011,7 @@ static size_t exynos_iommu_unmap(struct iommu_domain *domain, + BUG_ON(size < LPAGE_SIZE); + + memset(ent, 0, sizeof(*ent) * SPAGES_PER_LPAGE); ++ pgtable_flush(ent, ent + SPAGES_PER_LPAGE); + + size = LPAGE_SIZE; + priv->lv2entcnt[lv1ent_offset(iova)] += SPAGES_PER_LPAGE; +-- +1.8.3.2 + diff --git a/patches.tizen/0017-iommu-exynos-fix-page-table-maintenance.patch b/patches.tizen/0017-iommu-exynos-fix-page-table-maintenance.patch new file mode 100644 index 00000000000..481b43c3452 --- /dev/null +++ b/patches.tizen/0017-iommu-exynos-fix-page-table-maintenance.patch @@ -0,0 +1,151 @@ +From e16855c6f3919791b9ffc0d7471843df045e43ca Mon Sep 17 00:00:00 2001 +From: Cho KyongHo <pullip.cho@samsung.com> +Date: Fri, 26 Jul 2013 20:27:11 +0900 +Subject: [PATCH 0017/1302] iommu/exynos: fix page table maintenance + +This prevents allocating lv2 page table for the lv1 page table entry +that already has 1MB page mapping. In addition some BUG_ON() is +changed to WARN_ON(). + +Signed-off-by: Cho KyongHo <pullip.cho@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + drivers/iommu/exynos-iommu.c | 52 +++++++++++++++++++++++++++++++------------- + 1 file changed, 37 insertions(+), 15 deletions(-) + +diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c +index e3be3e5..6c4ecce 100644 +--- a/drivers/iommu/exynos-iommu.c ++++ b/drivers/iommu/exynos-iommu.c +@@ -52,11 +52,11 @@ + #define lv2ent_large(pent) ((*(pent) & 3) == 1) + + #define section_phys(sent) (*(sent) & SECT_MASK) +-#define section_offs(iova) ((iova) & 0xFFFFF) ++#define section_offs(iova) ((iova) & ~SECT_MASK) + #define lpage_phys(pent) (*(pent) & LPAGE_MASK) +-#define lpage_offs(iova) ((iova) & 0xFFFF) ++#define lpage_offs(iova) ((iova) & ~LPAGE_MASK) + #define spage_phys(pent) (*(pent) & SPAGE_MASK) +-#define spage_offs(iova) ((iova) & 0xFFF) ++#define spage_offs(iova) ((iova) & ~SPAGE_MASK) + + #define lv1ent_offset(iova) ((iova) >> SECT_ORDER) + #define lv2ent_offset(iova) (((iova) & 0xFF000) >> SPAGE_ORDER) +@@ -862,12 +862,14 @@ static unsigned long *alloc_lv2entry(unsigned long *sent, unsigned long iova, + pent = kzalloc(LV2TABLE_SIZE, GFP_ATOMIC); + BUG_ON((unsigned long)pent & (LV2TABLE_SIZE - 1)); + if (!pent) +- return NULL; ++ return ERR_PTR(-ENOMEM); + + *sent = mk_lv1ent_page(__pa(pent)); + *pgcounter = NUM_LV2ENTRIES; + pgtable_flush(pent, pent + NUM_LV2ENTRIES); + pgtable_flush(sent, sent + 1); ++ } else if (lv1ent_section(sent)) { ++ return ERR_PTR(-EADDRINUSE); + } + + return page_entry(sent, iova); +@@ -894,6 +896,12 @@ static int lv1set_section(unsigned long *sent, phys_addr_t paddr, short *pgcnt) + return 0; + } + ++static void clear_page_table(unsigned long *ent, int n) ++{ ++ if (n > 0) ++ memset(ent, 0, sizeof(*ent) * n); ++} ++ + static int lv2set_page(unsigned long *pent, phys_addr_t paddr, size_t size, + short *pgcnt) + { +@@ -908,7 +916,7 @@ static int lv2set_page(unsigned long *pent, phys_addr_t paddr, size_t size, + int i; + for (i = 0; i < SPAGES_PER_LPAGE; i++, pent++) { + if (!lv2ent_fault(pent)) { +- memset(pent, 0, sizeof(*pent) * i); ++ clear_page_table(pent - i, i); + return -EADDRINUSE; + } + +@@ -944,17 +952,16 @@ static int exynos_iommu_map(struct iommu_domain *domain, unsigned long iova, + pent = alloc_lv2entry(entry, iova, + &priv->lv2entcnt[lv1ent_offset(iova)]); + +- if (!pent) +- ret = -ENOMEM; ++ if (IS_ERR(pent)) ++ ret = PTR_ERR(pent); + else + ret = lv2set_page(pent, paddr, size, + &priv->lv2entcnt[lv1ent_offset(iova)]); + } + +- if (ret) { +- pr_debug("%s: Failed to map iova 0x%lx/0x%x bytes\n", +- __func__, iova, size); +- } ++ if (ret) ++ pr_err("%s: Failed(%d) to map 0x%#x bytes @ %#lx\n", ++ __func__, ret, size, iova); + + spin_unlock_irqrestore(&priv->pgtablelock, flags); + +@@ -968,6 +975,7 @@ static size_t exynos_iommu_unmap(struct iommu_domain *domain, + struct sysmmu_drvdata *data; + unsigned long flags; + unsigned long *ent; ++ size_t err_pgsize; + + BUG_ON(priv->pgtable == NULL); + +@@ -976,7 +984,10 @@ static size_t exynos_iommu_unmap(struct iommu_domain *domain, + ent = section_entry(priv->pgtable, iova); + + if (lv1ent_section(ent)) { +- BUG_ON(size < SECT_SIZE); ++ if (WARN_ON(size < SECT_SIZE)) { ++ err_pgsize = SECT_SIZE; ++ goto err; ++ } + + *ent = 0; + pgtable_flush(ent, ent + 1); +@@ -1008,9 +1019,12 @@ static size_t exynos_iommu_unmap(struct iommu_domain *domain, + } + + /* lv1ent_large(ent) == true here */ +- BUG_ON(size < LPAGE_SIZE); ++ if (WARN_ON(size < LPAGE_SIZE)) { ++ err_pgsize = LPAGE_SIZE; ++ goto err; ++ } + +- memset(ent, 0, sizeof(*ent) * SPAGES_PER_LPAGE); ++ clear_page_table(ent, SPAGES_PER_LPAGE); + pgtable_flush(ent, ent + SPAGES_PER_LPAGE); + + size = LPAGE_SIZE; +@@ -1023,8 +1037,16 @@ done: + sysmmu_tlb_invalidate_entry(data->dev, iova); + spin_unlock_irqrestore(&priv->lock, flags); + +- + return size; ++err: ++ spin_unlock_irqrestore(&priv->pgtablelock, flags); ++ ++ pr_err("%s: Failed due to size(%#x) @ %#lx is"\ ++ " smaller than page size %#x\n", ++ __func__, size, iova, err_pgsize); ++ ++ return 0; ++ + } + + static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *domain, +-- +1.8.3.2 + diff --git a/patches.tizen/0018-iommu-exynos-allocate-lv2-page-table-from-own-slab.patch b/patches.tizen/0018-iommu-exynos-allocate-lv2-page-table-from-own-slab.patch new file mode 100644 index 00000000000..bb5a914a409 --- /dev/null +++ b/patches.tizen/0018-iommu-exynos-allocate-lv2-page-table-from-own-slab.patch @@ -0,0 +1,84 @@ +From 429942a268e534b39ddbe819cbd8c5641c7bbf38 Mon Sep 17 00:00:00 2001 +From: Cho KyongHo <pullip.cho@samsung.com> +Date: Fri, 26 Jul 2013 20:27:29 +0900 +Subject: [PATCH 0018/1302] iommu/exynos: allocate lv2 page table from own slab + +Since kmalloc() does not guarantee that the allignment of 1KiB when it +allocates 1KiB, it is required to allocate lv2 page table from own +slab that guarantees alignment of 1KiB + +Signed-off-by: Cho KyongHo <pullip.cho@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + drivers/iommu/exynos-iommu.c | 24 ++++++++++++++++++++---- + 1 file changed, 20 insertions(+), 4 deletions(-) + +diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c +index 6c4ecce..093eea5 100644 +--- a/drivers/iommu/exynos-iommu.c ++++ b/drivers/iommu/exynos-iommu.c +@@ -100,6 +100,8 @@ + #define REG_PB1_SADDR 0x054 + #define REG_PB1_EADDR 0x058 + ++static struct kmem_cache *lv2table_kmem_cache; ++ + static unsigned long *section_entry(unsigned long *pgtable, unsigned long iova) + { + return pgtable + lv1ent_offset(iova); +@@ -765,7 +767,8 @@ static void exynos_iommu_domain_destroy(struct iommu_domain *domain) + + for (i = 0; i < NUM_LV1ENTRIES; i++) + if (lv1ent_page(priv->pgtable + i)) +- kfree(__va(lv2table_base(priv->pgtable + i))); ++ kmem_cache_free(lv2table_kmem_cache, ++ __va(lv2table_base(priv->pgtable + i))); + + free_pages((unsigned long)priv->pgtable, 2); + free_pages((unsigned long)priv->lv2entcnt, 1); +@@ -859,7 +862,7 @@ static unsigned long *alloc_lv2entry(unsigned long *sent, unsigned long iova, + if (lv1ent_fault(sent)) { + unsigned long *pent; + +- pent = kzalloc(LV2TABLE_SIZE, GFP_ATOMIC); ++ pent = kmem_cache_zalloc(lv2table_kmem_cache, GFP_ATOMIC); + BUG_ON((unsigned long)pent & (LV2TABLE_SIZE - 1)); + if (!pent) + return ERR_PTR(-ENOMEM); +@@ -884,7 +887,7 @@ static int lv1set_section(unsigned long *sent, phys_addr_t paddr, short *pgcnt) + if (*pgcnt != NUM_LV2ENTRIES) + return -EADDRINUSE; + +- kfree(page_entry(sent, 0)); ++ kmem_cache_free(lv2table_kmem_cache, page_entry(sent, 0)); + + *pgcnt = 0; + } +@@ -1092,10 +1095,23 @@ static int __init exynos_iommu_init(void) + { + int ret; + ++ lv2table_kmem_cache = kmem_cache_create("exynos-iommu-lv2table", ++ LV2TABLE_SIZE, LV2TABLE_SIZE, 0, NULL); ++ if (!lv2table_kmem_cache) { ++ pr_err("%s: Failed to create kmem cache\n", __func__); ++ return -ENOMEM; ++ } ++ + ret = platform_driver_register(&exynos_sysmmu_driver); + + if (ret == 0) +- bus_set_iommu(&platform_bus_type, &exynos_iommu_ops); ++ ret = bus_set_iommu(&platform_bus_type, &exynos_iommu_ops); ++ ++ if (ret) { ++ pr_err("%s: Failed to register exynos-iommu driver.\n", ++ __func__); ++ kmem_cache_destroy(lv2table_kmem_cache); ++ } + + return ret; + } +-- +1.8.3.2 + diff --git a/patches.tizen/0019-clk-exynos5250-add-gate-clock-descriptions-of-System.patch b/patches.tizen/0019-clk-exynos5250-add-gate-clock-descriptions-of-System.patch new file mode 100644 index 00000000000..e68990e7632 --- /dev/null +++ b/patches.tizen/0019-clk-exynos5250-add-gate-clock-descriptions-of-System.patch @@ -0,0 +1,157 @@ +From c25040eec6251a3cd2f82d7dc7133c29fd019a6e Mon Sep 17 00:00:00 2001 +From: Cho KyongHo <pullip.cho@samsung.com> +Date: Fri, 26 Jul 2013 20:27:54 +0900 +Subject: [PATCH 0019/1302] clk: exynos5250: add gate clock descriptions of + System MMU + +This adds gate clocks of all System MMUs and their master IPs +that are not apeared in clk-exynos5250.c + +Signed-off-by: Cho KyongHo <pullip.cho@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + .../devicetree/bindings/clock/exynos5250-clock.txt | 28 ++++++++++- + drivers/clk/samsung/clk-exynos5250.c | 57 ++++++++++++++++++---- + 2 files changed, 75 insertions(+), 10 deletions(-) + +diff --git a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt +index 781a627..df49694 100644 +--- a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt ++++ b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt +@@ -154,7 +154,33 @@ clock which they consume. + dsim0 341 + dp 342 + mixer 343 +- hdmi 345 ++ hdmi 344 ++ camif_top 345 ++ smmu_fimc_lite0 346 ++ smmu_fimc_lite1 347 ++ smmu_fimc_lite2 348 ++ smmu_tv 349 ++ smmu_fimd1 350 ++ smmu_2d 351 ++ fimc_isp 352 ++ fimc_drc 353 ++ fimc_fd 354 ++ fimc_scc 355 ++ fimc_scp 356 ++ fimc_mcuctl 357 ++ fimc_odc 358 ++ fimc_dis 359 ++ fimc_3dnr 360 ++ smmu_fimc_isp 361 ++ smmu_fimc_drc 362 ++ smmu_fimc_fd 363 ++ smmu_fimc_scc 364 ++ smmu_fimc_scp 365 ++ smmu_fimc_mcuctl 366 ++ smmu_fimc_odc 367 ++ smmu_fimc_dis0 368 ++ smmu_fimc_dis1 369 ++ smmu_fimc_3dnr 370 + + Example 1: An example of a clock controller node is listed below. + +diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c +index 22d7699..e242bde 100644 +--- a/drivers/clk/samsung/clk-exynos5250.c ++++ b/drivers/clk/samsung/clk-exynos5250.c +@@ -53,12 +53,15 @@ + #define DIV_PERIC3 0x10564 + #define DIV_PERIC4 0x10568 + #define DIV_PERIC5 0x1056c ++#define GATE_IP_ISP0 0x0C800 ++#define GATE_IP_ISP1 0x0C800 + #define GATE_IP_GSCL 0x10920 + #define GATE_IP_MFC 0x1092c + #define GATE_IP_GEN 0x10934 + #define GATE_IP_FSYS 0x10944 + #define GATE_IP_PERIC 0x10950 + #define GATE_IP_PERIS 0x10960 ++#define GATE_IP_ACP 0x18800 + #define SRC_CDREX 0x20200 + #define PLL_DIV2_SEL 0x20a24 + #define GATE_IP_DISP1 0x10928 +@@ -100,6 +103,14 @@ enum exynos5250_clks { + tzpc2, tzpc3, tzpc4, tzpc5, tzpc6, tzpc7, tzpc8, tzpc9, hdmi_cec, mct, + wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi, + ++ camif_top, smmu_fimc_lite0, smmu_fimc_lite1, smmu_fimc_lite2, ++ smmu_tv, smmu_fimd1, smmu_2d, ++ fimc_isp, fimc_drc, fimc_fd, fimc_scc, fimc_scp, fimc_mcuctl, fimc_odc, ++ fimc_dis, fimc_3dnr, ++ smmu_fimc_isp, smmu_fimc_drc, smmu_fimc_fd, smmu_fimc_scc, ++ smmu_fimc_scp, smmu_fimc_mcuctl, smmu_fimc_odc, smmu_fimc_dis0, ++ smmu_fimc_dis1, smmu_fimc_3dnr, ++ + nr_clks, + }; + +@@ -320,19 +331,26 @@ struct samsung_gate_clock exynos5250_gate_clks[] __initdata = { + GATE(gscl3, "gscl3", "aclk266", GATE_IP_GSCL, 3, 0, 0), + GATE(gscl_wa, "gscl_wa", "div_gscl_wa", GATE_IP_GSCL, 5, 0, 0), + GATE(gscl_wb, "gscl_wb", "div_gscl_wb", GATE_IP_GSCL, 6, 0, 0), +- GATE(smmu_gscl0, "smmu_gscl0", "aclk266", GATE_IP_GSCL, 7, 0, 0), +- GATE(smmu_gscl1, "smmu_gscl1", "aclk266", GATE_IP_GSCL, 8, 0, 0), +- GATE(smmu_gscl2, "smmu_gscl2", "aclk266", GATE_IP_GSCL, 9, 0, 0), +- GATE(smmu_gscl3, "smmu_gscl3", "aclk266", GATE_IP_GSCL, 10, 0, 0), ++ GATE(smmu_gscl0, "smmu_gscl0", "none", GATE_IP_GSCL, 7, 0, 0), ++ GATE(smmu_gscl1, "smmu_gscl1", "none", GATE_IP_GSCL, 8, 0, 0), ++ GATE(smmu_gscl2, "smmu_gscl2", "none", GATE_IP_GSCL, 9, 0, 0), ++ GATE(smmu_gscl3, "smmu_gscl3", "none", GATE_IP_GSCL, 10, 0, 0), ++ GATE(camif_top, "camif_top", "aclk266", GATE_IP_GSCL, 4, 0, 0), ++ GATE(smmu_fimc_lite0, "smmu_fimc_lite0", "none", ++ GATE_IP_GSCL, 12, 0, 0), ++ GATE(smmu_fimc_lite1, "smmu_fimc_lite1", "none", ++ GATE_IP_GSCL, 13, 0, 0), ++ GATE(smmu_fimc_lite2, "smmu_fimc_lite2", "none", ++ GATE_IP_GSCL, 14, 0, 0), + GATE(mfc, "mfc", "aclk333", GATE_IP_MFC, 0, 0, 0), +- GATE(smmu_mfcl, "smmu_mfcl", "aclk333", GATE_IP_MFC, 1, 0, 0), +- GATE(smmu_mfcr, "smmu_mfcr", "aclk333", GATE_IP_MFC, 2, 0, 0), ++ GATE(smmu_mfcr, "smmu_mfcr", "none", GATE_IP_MFC, 1, 0, 0), ++ GATE(smmu_mfcl, "smmu_mfcl", "none", GATE_IP_MFC, 2, 0, 0), + GATE(rotator, "rotator", "aclk266", GATE_IP_GEN, 1, 0, 0), + GATE(jpeg, "jpeg", "aclk166", GATE_IP_GEN, 2, 0, 0), + GATE(mdma1, "mdma1", "aclk266", GATE_IP_GEN, 4, 0, 0), +- GATE(smmu_rotator, "smmu_rotator", "aclk266", GATE_IP_GEN, 6, 0, 0), +- GATE(smmu_jpeg, "smmu_jpeg", "aclk166", GATE_IP_GEN, 7, 0, 0), +- GATE(smmu_mdma1, "smmu_mdma1", "aclk266", GATE_IP_GEN, 9, 0, 0), ++ GATE(smmu_rotator, "smmu_rotator", "none", GATE_IP_GEN, 6, 0, 0), ++ GATE(smmu_jpeg, "smmu_jpeg", "none", GATE_IP_GEN, 7, 0, 0), ++ GATE(smmu_mdma1, "smmu_mdma1", "none", GATE_IP_GEN, 9, 0, 0), + GATE(pdma0, "pdma0", "aclk200", GATE_IP_FSYS, 1, 0, 0), + GATE(pdma1, "pdma1", "aclk200", GATE_IP_FSYS, 2, 0, 0), + GATE(sata, "sata", "aclk200", GATE_IP_FSYS, 6, 0, 0), +@@ -462,6 +480,27 @@ struct samsung_gate_clock exynos5250_gate_clks[] __initdata = { + GATE(dp, "dp", "aclk200", GATE_IP_DISP1, 4, 0, 0), + GATE(mixer, "mixer", "aclk200", GATE_IP_DISP1, 5, 0, 0), + GATE(hdmi, "hdmi", "aclk200", GATE_IP_DISP1, 6, 0, 0), ++ GATE(smmu_tv, "smmu_tv", "none", GATE_IP_DISP1, 2, 0, 0), ++ GATE(smmu_fimd1, "smmu_fimd1", "none", GATE_IP_DISP1, 8, 0, 0), ++ ++ GATE(smmu_fimc_isp, "smmu_fimc_isp", "none", GATE_IP_ISP0, 8, 0, 0), ++ GATE(smmu_fimc_drc, "smmu_fimc_drc", "none", GATE_IP_ISP0, 9, 0, 0), ++ GATE(smmu_fimc_fd, "smmu_fimc_fd", "none", GATE_IP_ISP0, 10, 0, 0), ++ GATE(smmu_fimc_scc, "smmu_fimc_scc", "none", ++ GATE_IP_ISP0, 11, 0, 0), ++ GATE(smmu_fimc_scp, "smmu_fimc_scp", "none", ++ GATE_IP_ISP0, 12, 0, 0), ++ GATE(smmu_fimc_mcuctl, "smmu_fimc_mcuctl", "none", ++ GATE_IP_ISP0, 13, 0, 0), ++ GATE(smmu_fimc_odc, "smmu_fimc_odc", "none", GATE_IP_ISP1, 4, 0, 0), ++ GATE(smmu_fimc_dis0, "smmu_fimc_dis0", "none", ++ GATE_IP_ISP1, 5, 0, 0), ++ GATE(smmu_fimc_dis1, "smmu_fimc_dis1", "none", ++ GATE_IP_ISP1, 6, 0, 0), ++ GATE(smmu_fimc_3dnr, "smmu_fimc_3dnr", "none", ++ GATE_IP_ISP1, 7, 0, 0), ++ ++ GATE(smmu_2d, "smmu_2d", "none", GATE_IP_ACP, 7, 0, 0), + }; + + static __initdata struct of_device_id ext_clk_match[] = { +-- +1.8.3.2 + diff --git a/patches.tizen/0020-ARM-dts-Add-description-of-System-MMU-of-Exynos-SoCs.patch b/patches.tizen/0020-ARM-dts-Add-description-of-System-MMU-of-Exynos-SoCs.patch new file mode 100644 index 00000000000..968f3e8c517 --- /dev/null +++ b/patches.tizen/0020-ARM-dts-Add-description-of-System-MMU-of-Exynos-SoCs.patch @@ -0,0 +1,738 @@ +From aedbf55d2d2ee9fc3f1b87608f4410882f89e456 Mon Sep 17 00:00:00 2001 +From: Cho KyongHo <pullip.cho@samsung.com> +Date: Fri, 26 Jul 2013 20:28:19 +0900 +Subject: [PATCH 0020/1302] ARM: dts: Add description of System MMU of Exynos + SoCs + +Signed-off-by: Cho KyongHo <pullip.cho@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + .../bindings/iommu/samsung,exynos4210-sysmmu.txt | 103 ++++++++ + arch/arm/boot/dts/exynos4.dtsi | 122 +++++++++ + arch/arm/boot/dts/exynos4210.dtsi | 25 ++ + arch/arm/boot/dts/exynos4x12.dtsi | 76 ++++++ + arch/arm/boot/dts/exynos5250.dtsi | 291 +++++++++++++++++++++ + 5 files changed, 617 insertions(+) + create mode 100644 Documentation/devicetree/bindings/iommu/samsung,exynos4210-sysmmu.txt + +diff --git a/Documentation/devicetree/bindings/iommu/samsung,exynos4210-sysmmu.txt b/Documentation/devicetree/bindings/iommu/samsung,exynos4210-sysmmu.txt +new file mode 100644 +index 0000000..92f0a33 +--- /dev/null ++++ b/Documentation/devicetree/bindings/iommu/samsung,exynos4210-sysmmu.txt +@@ -0,0 +1,103 @@ ++Samsung Exynos4210 IOMMU H/W, System MMU (System Memory Management Unit) ++ ++Samsung's Exynos architecture contains System MMU that enables scattered ++physical memory chunks visible as a contiguous region to DMA-capable peripheral ++devices like MFC, FIMC, FIMD, GScaler, FIMC-IS and so forth. ++ ++System MMU is a sort of IOMMU and support identical translation table format to ++ARMv7 translation tables with minimum set of page properties including access ++permissions, shareability and security protection. In addition, System MMU has ++another capabilities like L2 TLB or block-fetch buffers to minimize translation ++latency. ++ ++A System MMU is dedicated to a single master peripheral device. Thus, it is ++important to specify the correct System MMU in the device node of its master ++device. Whereas a System MMU is dedicated to a master device, the master device ++may have more than one System MMU. ++ ++Required properties: ++- compatible: Should be "samsung,exynos4210-sysmmu" ++- reg: A tuple of base address and size of System MMU registers. ++- interrupt-parent: The phandle of the interrupt controller of System MMU ++- interrupts: A tuple of numbers that indicates the interrupt source. ++- clock-names: Should be "sysmmu" if the System MMU is needed to gate its clock. ++ Please refer to the following documents: ++ Documentation/devicetree/bindings/clock/clock-bindings.txt ++ Documentation/devicetree/bindings/clock/exynos4-clock.txt ++ Documentation/devicetree/bindings/clock/exynos5250-clock.txt ++ Optional "master" if the clock to the System MMU is gated by ++ another gate clock other than "sysmmu". The System MMU driver ++ sets "master" the parent of "sysmmu". ++ Exynos4 SoCs, there needs no "master" clocks. ++ Exynos5 SoCs, some System MMUs must have "master" clocks. ++- clocks: Required if the System MMU is needed to gate its clock. ++ Please refer to the documents listed above. ++- samsung,power-domain: Required if the System MMU is needed to gate its power. ++ Please refer to the following document: ++ Documentation/devicetree/bindings/arm/exynos/power_domain.txt ++ ++Required properties for the master peripheral devices: ++- iommu: phandles to the System MMUs of the device ++ ++Examples: ++A System MMU is dedicated to a single master device. ++ gsc_0: gsc@0x13e00000 { ++ compatible = "samsung,exynos5-gsc"; ++ reg = <0x13e00000 0x1000>; ++ interrupts = <0 85 0>; ++ samsung,power-domain = <&pd_gsc>; ++ clocks = <&clock 256>; ++ clock-names = "gscl"; ++ iommu = <&sysmmu_gsc1>; ++ }; ++ ++ sysmmu_gsc0: sysmmu@13E80000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x13E80000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-gsc0"; ++ interrupts = <2 0>; ++ clock-names = "sysmmu", "master"; ++ clocks = <&clock 262>, <&clock 256>; ++ samsung,power-domain = <&pd_gsc>; ++ status = "ok"; ++ }; ++ ++MFC has 2 System MMUs for each port that MFC is attached. Thus it seems natural ++to define 2 System MMUs for each port of the MFC: ++ ++ mfc: codec@13400000 { ++ compatible = "samsung,mfc-v5"; ++ reg = <0x13400000 0x10000>; ++ interrupts = <0 94 0>; ++ samsung,power-domain = <&pd_mfc>; ++ clocks = <&clock 170>, <&clock 273>; ++ clock-names = "sclk_mfc", "mfc"; ++ status = "ok"; ++ iommu = <&sysmmu_mfc_l>, <&sysmmu_mfc_r>; ++ }; ++ ++ sysmmu_mfc_l: sysmmu@13620000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x13620000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-mfc-l"; ++ interrupts = <5 5>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 274>; ++ samsung,power-domain = <&pd_mfc>; ++ status = "ok"; ++ }; ++ ++ sysmmu_mfc_r: sysmmu@13630000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x13630000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-mfc-r"; ++ interrupts = <5 6>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 275>; ++ samsung,power-domain = <&pd_mfc>; ++ status = "ok"; ++ }; ++ +diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi +index 5f57f59..77ac4af 100644 +--- a/arch/arm/boot/dts/exynos4.dtsi ++++ b/arch/arm/boot/dts/exynos4.dtsi +@@ -167,6 +167,7 @@ + interrupts = <0 94 0>; + samsung,power-domain = <&pd_mfc>; + status = "disabled"; ++ iommu = <&sysmmu_mfc_l>, <&sysmmu_mfc_r>; + }; + + serial@13800000 { +@@ -408,5 +409,126 @@ + clock-names = "sclk_fimd", "fimd"; + samsung,power-domain = <&pd_lcd0>; + status = "disabled"; ++ iommu = <&sysmmu_fimd0>; ++ }; ++ ++ sysmmu_mfc_l: sysmmu@13620000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x13620000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-mfc-l"; ++ interrupts = <5 5>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 274>; ++ samsung,power-domain = <&pd_mfc>; ++ status = "ok"; ++ }; ++ ++ sysmmu_mfc_r: sysmmu@13630000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x13630000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-mfc-r"; ++ interrupts = <5 6>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 275>; ++ samsung,power-domain = <&pd_mfc>; ++ status = "ok"; ++ }; ++ ++ sysmmu_tv: sysmmu@13E20000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x13E20000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-tv"; ++ interrupts = <5 4>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 272>; ++ samsung,power-domain = <&pd_tv>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc0: sysmmu@11A20000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x11A20000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimc0"; ++ interrupts = <4 2>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 263>; ++ samsung,power-domain = <&pd_cam>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc1: sysmmu@11A30000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x11A30000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimc1"; ++ interrupts = <4 3>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 264>; ++ samsung,power-domain = <&pd_cam>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc2: sysmmu@11A40000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x11A40000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimc2"; ++ interrupts = <4 4>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 265>; ++ samsung,power-domain = <&pd_cam>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc3: sysmmu@11A50000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x11A50000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimc3"; ++ interrupts = <4 5>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 266>; ++ samsung,power-domain = <&pd_cam>; ++ status = "ok"; ++ }; ++ ++ sysmmu_jpeg: sysmmu@11A60000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x11A60000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-jpeg"; ++ interrupts = <4 6>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 267>; ++ samsung,power-domain = <&pd_cam>; ++ status = "ok"; ++ }; ++ ++ sysmmu_rotator: sysmmu@12A30000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x12A30000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-rotator"; ++ interrupts = <5 0>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 281>; ++ samsung,power-domain = <&pd_lcd0>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimd0: sysmmu@11E20000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x11E20000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimd0"; ++ interrupts = <5 2>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 287>; ++ samsung,power-domain = <&pd_lcd0>; ++ status = "ok"; + }; + }; +diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi +index ef707bd..7ab619e 100644 +--- a/arch/arm/boot/dts/exynos4210.dtsi ++++ b/arch/arm/boot/dts/exynos4210.dtsi +@@ -123,5 +123,30 @@ + reg = <0x12800000 0x1000>; + interrupts = <0 89 0>; + status = "disabled"; ++ iommu = <&sysmmu_g2d>; ++ }; ++ ++ sysmmu_g2d: sysmmu@12A20000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x12A20000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-g2d"; ++ interrupts = <4 7>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 280>; ++ samsung,power-domain = <&pd_lcd0>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimd1: sysmmu@12220000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimd1"; ++ reg = <0x12220000 0x1000>; ++ interrupts = <5 3>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 291>; ++ samsung,power-domain = <&pd_lcd1>; ++ status = "ok"; + }; + }; +diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi +index 4afda47..3bf2d09 100644 +--- a/arch/arm/boot/dts/exynos4x12.dtsi ++++ b/arch/arm/boot/dts/exynos4x12.dtsi +@@ -83,4 +83,80 @@ + interrupts = <0 89 0>; + status = "disabled"; + }; ++ ++ sysmmu_g2d: sysmmu@10A40000{ ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x10A40000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-g2d"; ++ interrupts = <4 7>; ++ clock-names = "sysmmu"; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc_isp: sysmmu@12260000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x12260000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimc_isp"; ++ interrupts = <16 2>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 362>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc_drc: sysmmu@12270000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x12270000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimc_drc"; ++ interrupts = <16 3>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 363>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc_fd: sysmmu@122A0000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x122A0000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimc_fd"; ++ interrupts = <16 4>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 364>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc_mcuctl: sysmmu@122B0000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x122B0000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimc_mcuctl"; ++ interrupts = <16 5>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 376>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc_lite0: sysmmu@123B0000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x123B0000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimc_lite0"; ++ interrupts = <16 0>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 366>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc_lite1: sysmmu@123C0000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x123C0000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimc_lite1"; ++ interrupts = <16 1>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 365>; ++ status = "ok"; ++ }; + }; +diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi +index fc9fb3d..130d23d 100644 +--- a/arch/arm/boot/dts/exynos5250.dtsi ++++ b/arch/arm/boot/dts/exynos5250.dtsi +@@ -66,6 +66,16 @@ + reg = <0x10044040 0x20>; + }; + ++ pd_isp: mfc-power-domain@0x10044020 { ++ compatible = "samsung,exynos4210-pd"; ++ reg = <0x10044020 0x20>; ++ }; ++ ++ pd_disp1: mfc-power-domain@0x100440A0 { ++ compatible = "samsung,exynos4210-pd"; ++ reg = <0x100440A0 0x20>; ++ }; ++ + clock: clock-controller@0x10010000 { + compatible = "samsung,exynos5250-clock"; + reg = <0x10010000 0x30000>; +@@ -180,6 +190,7 @@ + reg = <0x11000000 0x10000>; + interrupts = <0 96 0>; + samsung,power-domain = <&pd_mfc>; ++ iommu = <&sysmmu_mfc_l &sysmmu_mfc_l>; + }; + + rtc { +@@ -571,6 +582,7 @@ + samsung,power-domain = <&pd_gsc>; + clocks = <&clock 256>; + clock-names = "gscl"; ++ iommu = <&sysmmu_gsc1>; + }; + + gsc_1: gsc@0x13e10000 { +@@ -580,6 +592,7 @@ + samsung,power-domain = <&pd_gsc>; + clocks = <&clock 257>; + clock-names = "gscl"; ++ iommu = <&sysmmu_gsc1>; + }; + + gsc_2: gsc@0x13e20000 { +@@ -589,6 +602,7 @@ + samsung,power-domain = <&pd_gsc>; + clocks = <&clock 258>; + clock-names = "gscl"; ++ iommu = <&sysmmu_gsc2>; + }; + + gsc_3: gsc@0x13e30000 { +@@ -598,6 +612,7 @@ + samsung,power-domain = <&pd_gsc>; + clocks = <&clock 259>; + clock-names = "gscl"; ++ iommu = <&sysmmu_gsc3>; + }; + + hdmi { +@@ -614,6 +629,7 @@ + compatible = "samsung,exynos5-mixer"; + reg = <0x14450000 0x10000>; + interrupts = <0 94 0>; ++ iommu = <&sysmmu_tv>; + }; + + dp-controller { +@@ -638,5 +654,280 @@ + interrupts = <18 4>, <18 5>, <18 6>; + clocks = <&clock 133>, <&clock 339>; + clock-names = "sclk_fimd", "fimd"; ++ iommu = <&sysmmu_fimd1>; ++ }; ++ ++ sysmmu_mfc_l: sysmmu@11210000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x11210000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-mfc_l"; ++ interrupts = <8 5>; ++ clock-names = "sysmmu", "master"; ++ clocks = <&clock 267>, <&clock 266>; ++ samsung,power-domain = <&pd_mfc>; ++ status = "ok"; ++ }; ++ ++ sysmmu_mfc_r: sysmmu@11200000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x11200000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-mfc_r"; ++ interrupts = <6 2>; ++ clock-names = "sysmmu", "master"; ++ clocks = <&clock 268>, <&clock 266>; ++ samsung,power-domain = <&pd_mfc>; ++ status = "ok"; ++ }; ++ ++ sysmmu_tv: sysmmu@14650000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x14650000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-tv"; ++ interrupts = <7 4>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 349>; ++ samsung,power-domain = <&pd_disp1>; ++ status = "ok"; ++ }; ++ ++ sysmmu_gsc0: sysmmu@13E80000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x13E80000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-gsc0"; ++ interrupts = <2 0>; ++ clock-names = "sysmmu", "master"; ++ clocks = <&clock 262>, <&clock 256>; ++ samsung,power-domain = <&pd_gsc>; ++ status = "ok"; ++ }; ++ ++ sysmmu_gsc1: sysmmu@13E90000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x13E90000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-gsc1"; ++ interrupts = <2 2>; ++ clock-names = "sysmmu", "master"; ++ clocks = <&clock 263>, <&clock 257>; ++ samsung,power-domain = <&pd_gsc>; ++ status = "ok"; ++ }; ++ ++ sysmmu_gsc2: sysmmu@13EA0000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x13EA0000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-gsc2"; ++ interrupts = <2 4>; ++ clock-names = "sysmmu", "master"; ++ clocks = <&clock 264>, <&clock 258>; ++ samsung,power-domain = <&pd_gsc>; ++ status = "ok"; ++ }; ++ ++ sysmmu_gsc3: sysmmu@13EB0000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x13EB0000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-gsc3"; ++ interrupts = <2 6>; ++ clock-names = "sysmmu", "master"; ++ clocks = <&clock 265>, <&clock 259>; ++ samsung,power-domain = <&pd_gsc>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimd1: sysmmu@14640000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x14640000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimd1"; ++ interrupts = <3 2>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 350>; ++ samsung,power-domain = <&pd_disp1>; ++ status = "ok"; ++ }; ++ ++ sysmmu_rotator: sysmmu@11D40000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x11D40000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-rotator"; ++ interrupts = <4 0>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 272>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc_isp: sysmmu@13260000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x13260000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimc_isp"; ++ interrupts = <10 6>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 361>; ++ samsung,power-domain = <&pd_isp>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc_drc: sysmmu@13270000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x13270000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimc_drc"; ++ interrupts = <11 6>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 362>; ++ samsung,power-domain = <&pd_isp>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc_fd: sysmmu@132A0000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x132A0000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimc_fd"; ++ interrupts = <5 0>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 363>; ++ samsung,power-domain = <&pd_isp>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc_scc: sysmmu@13280000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x13280000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimc_scalerc"; ++ interrupts = <5 2>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 364>; ++ samsung,power-domain = <&pd_isp>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc_scp: sysmmu@13290000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x13290000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimc_scalerp"; ++ interrupts = <3 6>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 365>; ++ samsung,power-domain = <&pd_isp>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc_mcuctl: sysmmu@132B0000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x132B0000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimc_mcuctl"; ++ interrupts = <5 4>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 366>; ++ samsung,power-domain = <&pd_isp>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc_odc: sysmmu@132C0000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x132C0000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimc_odc"; ++ interrupts = <11 0>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 367>; ++ samsung,power-domain = <&pd_isp>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc_dis0: sysmmu@132D0000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x132D0000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimc_dis0"; ++ interrupts = <10 4>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 368>; ++ samsung,power-domain = <&pd_isp>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc_dis1: sysmmu@132E0000{ ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x132E0000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimc_dis1"; ++ interrupts = <9 4>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 369>; ++ samsung,power-domain = <&pd_isp>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc_3dnr: sysmmu@132F0000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x132F0000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimc_3dnr"; ++ interrupts = <5 6>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 370>; ++ samsung,power-domain = <&pd_isp>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc_lite0: sysmmu@13C40000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x13C40000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimc_lite0"; ++ interrupts = <3 4>; ++ clock-names = "sysmmu", "master"; ++ clocks = <&clock 346>, <&clock 345>; ++ samsung,power-domain = <&pd_gsc>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc_lite1: sysmmu@13C50000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x13C50000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-fimc_lite1"; ++ interrupts = <24 1>; ++ clock-names = "sysmmu", "master"; ++ clocks = <&clock 347>, <&clock 345>; ++ samsung,power-domain = <&pd_gsc>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc_jpeg: sysmmu@11F20000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x11F20000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-jpeg"; ++ interrupts = <4 2>; ++ clock-names = "sysmmu", "master"; ++ clocks = <&clock 273>, <&clock 270>; ++ samsung,power-domain = <&pd_gsc>; ++ status = "ok"; ++ }; ++ ++ sysmmu_fimc_2d: sysmmu@10A60000 { ++ compatible = "samsung,exynos4210-sysmmu"; ++ reg = <0x10A60000 0x1000>; ++ interrupt-parent = <&combiner>; ++ interrupt-names = "sysmmu-2d"; ++ interrupts = <24 5>; ++ clock-names = "sysmmu"; ++ clocks = <&clock 361>; ++ status = "ok"; + }; + }; +-- +1.8.3.2 + diff --git a/patches.tizen/0021-iommu-exynos-support-for-device-tree.patch b/patches.tizen/0021-iommu-exynos-support-for-device-tree.patch new file mode 100644 index 00000000000..bccd0ca27ca --- /dev/null +++ b/patches.tizen/0021-iommu-exynos-support-for-device-tree.patch @@ -0,0 +1,371 @@ +From 04b137b2e5937b599851436409535c65971d0538 Mon Sep 17 00:00:00 2001 +From: Cho KyongHo <pullip.cho@samsung.com> +Date: Fri, 26 Jul 2013 20:28:36 +0900 +Subject: [PATCH 0021/1302] iommu/exynos: support for device tree + +This commit adds device tree support for System MMU. +This also include the following changes and enhancements: + +* use managed device helper functions. +Simplyfies System MMU device driver. + +* use only a single clock descriptor. +System MMU device descriptor is seperate if it is imposible to make +a single clock descriptor to make a device descriptor for a group of +System MMUs. + +* removed dbgname member from sysmmu_drvdata structure. +debugging kernel message for a System MMU is distinguisheable with the +name of device descroptors. + +Signed-off-by: Cho KyongHo <pullip.cho@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + drivers/iommu/Kconfig | 5 +- + drivers/iommu/exynos-iommu.c | 182 ++++++++++++++++--------------------------- + 2 files changed, 70 insertions(+), 117 deletions(-) + +diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig +index c332fb9..d45f3c9 100644 +--- a/drivers/iommu/Kconfig ++++ b/drivers/iommu/Kconfig +@@ -168,16 +168,15 @@ config TEGRA_IOMMU_SMMU + + config EXYNOS_IOMMU + bool "Exynos IOMMU Support" +- depends on ARCH_EXYNOS && EXYNOS_DEV_SYSMMU ++ depends on ARCH_EXYNOS + select IOMMU_API ++ default n + help + Support for the IOMMU(System MMU) of Samsung Exynos application + processor family. This enables H/W multimedia accellerators to see + non-linear physical memory chunks as a linear memory in their + address spaces + +- If unsure, say N here. +- + config EXYNOS_IOMMU_DEBUG + bool "Debugging log for Exynos IOMMU" + depends on EXYNOS_IOMMU +diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c +index 093eea5..cfc02ed 100644 +--- a/drivers/iommu/exynos-iommu.c ++++ b/drivers/iommu/exynos-iommu.c +@@ -26,6 +26,7 @@ + #include <linux/list.h> + #include <linux/memblock.h> + #include <linux/export.h> ++#include <linux/of.h> + + #include <asm/cacheflush.h> + #include <asm/pgtable.h> +@@ -170,15 +171,14 @@ struct sysmmu_drvdata { + struct list_head node; /* entry of exynos_iommu_domain.clients */ + struct device *sysmmu; /* System MMU's device descriptor */ + struct device *dev; /* Owner of system MMU */ +- char *dbgname; + int nsfrs; +- void __iomem **sfrbases; +- struct clk *clk[2]; ++ struct clk *clk; + int activations; + rwlock_t lock; + struct iommu_domain *domain; + sysmmu_fault_handler_t fault_handler; + unsigned long pgtable; ++ void __iomem *sfrbases[0]; + }; + + static bool set_sysmmu_active(struct sysmmu_drvdata *data) +@@ -385,8 +385,8 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) + if (!ret && (itype != SYSMMU_FAULT_UNKNOWN)) + __raw_writel(1 << itype, data->sfrbases[i] + REG_INT_CLEAR); + else +- dev_dbg(data->sysmmu, "(%s) %s is not handled.\n", +- data->dbgname, sysmmu_fault_name[itype]); ++ dev_dbg(data->sysmmu, "%s is not handled.\n", ++ sysmmu_fault_name[itype]); + + if (itype != SYSMMU_FAULT_UNKNOWN) + sysmmu_unblock(data->sfrbases[i]); +@@ -410,10 +410,8 @@ static bool __exynos_sysmmu_disable(struct sysmmu_drvdata *data) + for (i = 0; i < data->nsfrs; i++) + __raw_writel(CTRL_DISABLE, data->sfrbases[i] + REG_MMU_CTRL); + +- if (data->clk[1]) +- clk_disable(data->clk[1]); +- if (data->clk[0]) +- clk_disable(data->clk[0]); ++ if (data->clk) ++ clk_disable(data->clk); + + disabled = true; + data->pgtable = 0; +@@ -422,10 +420,10 @@ finish: + write_unlock_irqrestore(&data->lock, flags); + + if (disabled) +- dev_dbg(data->sysmmu, "(%s) Disabled\n", data->dbgname); ++ dev_dbg(data->sysmmu, "Disabled\n"); + else +- dev_dbg(data->sysmmu, "(%s) %d times left to be disabled\n", +- data->dbgname, data->activations); ++ dev_dbg(data->sysmmu, "%d times left to be disabled\n", ++ data->activations); + + return disabled; + } +@@ -452,14 +450,12 @@ static int __exynos_sysmmu_enable(struct sysmmu_drvdata *data, + ret = 1; + } + +- dev_dbg(data->sysmmu, "(%s) Already enabled\n", data->dbgname); ++ dev_dbg(data->sysmmu, "Already enabled\n"); + goto finish; + } + +- if (data->clk[0]) +- clk_enable(data->clk[0]); +- if (data->clk[1]) +- clk_enable(data->clk[1]); ++ if (data->clk) ++ clk_enable(data->clk); + + data->pgtable = pgtable; + +@@ -479,7 +475,7 @@ static int __exynos_sysmmu_enable(struct sysmmu_drvdata *data, + + data->domain = domain; + +- dev_dbg(data->sysmmu, "(%s) Enabled\n", data->dbgname); ++ dev_dbg(data->sysmmu, "Enabled\n"); + finish: + write_unlock_irqrestore(&data->lock, flags); + +@@ -495,7 +491,7 @@ int exynos_sysmmu_enable(struct device *dev, unsigned long pgtable) + + ret = pm_runtime_get_sync(data->sysmmu); + if (ret < 0) { +- dev_dbg(data->sysmmu, "(%s) Failed to enable\n", data->dbgname); ++ dev_dbg(data->sysmmu, "Failed to enable\n"); + return ret; + } + +@@ -503,8 +499,8 @@ int exynos_sysmmu_enable(struct device *dev, unsigned long pgtable) + if (WARN_ON(ret < 0)) { + pm_runtime_put(data->sysmmu); + dev_err(data->sysmmu, +- "(%s) Already enabled with page table %#lx\n", +- data->dbgname, data->pgtable); ++ "Already enabled with page table %#lx\n", ++ data->pgtable); + } else { + data->dev = dev; + } +@@ -540,9 +536,7 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, unsigned long iova) + } + } + } else { +- dev_dbg(data->sysmmu, +- "(%s) Disabled. Skipping invalidating TLB.\n", +- data->dbgname); ++ dev_dbg(data->sysmmu, "Disabled. Skipping invalidating TLB.\n"); + } + + read_unlock_irqrestore(&data->lock, flags); +@@ -564,141 +558,101 @@ void exynos_sysmmu_tlb_invalidate(struct device *dev) + } + } + } else { +- dev_dbg(data->sysmmu, +- "(%s) Disabled. Skipping invalidating TLB.\n", +- data->dbgname); ++ dev_dbg(data->sysmmu, "Disabled. Skipping invalidating TLB.\n"); + } + + read_unlock_irqrestore(&data->lock, flags); + } + +-static int exynos_sysmmu_probe(struct platform_device *pdev) ++static int __init exynos_sysmmu_probe(struct platform_device *pdev) + { + int i, ret; +- struct device *dev; ++ struct device *dev = &pdev->dev; + struct sysmmu_drvdata *data; + +- dev = &pdev->dev; +- +- data = kzalloc(sizeof(*data), GFP_KERNEL); +- if (!data) { +- dev_dbg(dev, "Not enough memory\n"); +- ret = -ENOMEM; +- goto err_alloc; ++ if (pdev->num_resources == 0) { ++ dev_err(dev, "No System MMU resource defined\n"); ++ return -ENODEV; + } + +- ret = dev_set_drvdata(dev, data); +- if (ret) { +- dev_dbg(dev, "Unabled to initialize driver data\n"); +- goto err_init; ++ data = devm_kzalloc(dev, ++ sizeof(*data) + ++ sizeof(*data->sfrbases) * (pdev->num_resources / 2), ++ GFP_KERNEL); ++ if (!data) { ++ dev_err(dev, "Not enough memory for initialization\n"); ++ return -ENOMEM; + } + + data->nsfrs = pdev->num_resources / 2; +- data->sfrbases = kmalloc(sizeof(*data->sfrbases) * data->nsfrs, +- GFP_KERNEL); +- if (data->sfrbases == NULL) { +- dev_dbg(dev, "Not enough memory\n"); +- ret = -ENOMEM; +- goto err_init; +- } + + for (i = 0; i < data->nsfrs; i++) { + struct resource *res; ++ + res = platform_get_resource(pdev, IORESOURCE_MEM, i); + if (!res) { +- dev_dbg(dev, "Unable to find IOMEM region\n"); +- ret = -ENOENT; +- goto err_res; ++ dev_err(dev, "Unable to find IOMEM region\n"); ++ return -ENOENT; + } + +- data->sfrbases[i] = ioremap(res->start, resource_size(res)); ++ data->sfrbases[i] = devm_request_and_ioremap(dev, res); + if (!data->sfrbases[i]) { +- dev_dbg(dev, "Unable to map IOMEM @ PA:%#x\n", +- res->start); +- ret = -ENOENT; +- goto err_res; ++ dev_err(dev, "Unable to map IOMEM @ %#x\n", res->start); ++ return -EBUSY; + } + } + + for (i = 0; i < data->nsfrs; i++) { +- ret = platform_get_irq(pdev, i); +- if (ret <= 0) { +- dev_dbg(dev, "Unable to find IRQ resource\n"); +- goto err_irq; ++ int irq; ++ ++ irq = platform_get_irq(pdev, i); ++ if (irq <= 0) { ++ dev_err(dev, "Unable to find IRQ resource\n"); ++ return -ENOENT; + } + +- ret = request_irq(ret, exynos_sysmmu_irq, 0, +- dev_name(dev), data); ++ ret = devm_request_irq(dev, irq, exynos_sysmmu_irq, ++ 0, dev_name(dev), data); + if (ret) { +- dev_dbg(dev, "Unabled to register interrupt handler\n"); +- goto err_irq; ++ dev_err(dev, "Unable to register handler to irq %d\n", ++ irq); ++ return ret; + } + } + +- if (dev_get_platdata(dev)) { +- char *deli, *beg; +- struct sysmmu_platform_data *platdata = dev_get_platdata(dev); +- +- beg = platdata->clockname; +- +- for (deli = beg; (*deli != '\0') && (*deli != ','); deli++) +- /* NOTHING */; +- +- if (*deli == '\0') +- deli = NULL; +- else +- *deli = '\0'; +- +- data->clk[0] = clk_get(dev, beg); +- if (IS_ERR(data->clk[0])) { +- data->clk[0] = NULL; +- dev_dbg(dev, "No clock descriptor registered\n"); +- } ++ pm_runtime_enable(dev); + +- if (data->clk[0] && deli) { +- *deli = ','; +- data->clk[1] = clk_get(dev, deli + 1); +- if (IS_ERR(data->clk[1])) +- data->clk[1] = NULL; +- } ++ __set_fault_handler(data, &default_fault_handler); + +- data->dbgname = platdata->dbgname; ++ data->sysmmu = dev; ++ data->clk = devm_clk_get(dev, "sysmmu"); ++ if (IS_ERR(data->clk)) { ++ dev_info(dev, "No gate clock found!\n"); ++ data->clk = NULL; + } + +- data->sysmmu = dev; + rwlock_init(&data->lock); + INIT_LIST_HEAD(&data->node); + +- __set_fault_handler(data, &default_fault_handler); +- +- if (dev->parent) +- pm_runtime_enable(dev); ++ platform_set_drvdata(pdev, data); ++ dev_dbg(dev, "Probed and initialized\n"); + +- dev_dbg(dev, "(%s) Initialized\n", data->dbgname); +- return 0; +-err_irq: +- while (i-- > 0) { +- int irq; +- +- irq = platform_get_irq(pdev, i); +- free_irq(irq, data); +- } +-err_res: +- while (data->nsfrs-- > 0) +- iounmap(data->sfrbases[data->nsfrs]); +- kfree(data->sfrbases); +-err_init: +- kfree(data); +-err_alloc: +- dev_err(dev, "Failed to initialize\n"); + return ret; + } + +-static struct platform_driver exynos_sysmmu_driver = { +- .probe = exynos_sysmmu_probe, +- .driver = { ++#ifdef CONFIG_OF ++static struct of_device_id sysmmu_of_match[] __initconst = { ++ { .compatible = "samsung,exynos4210-sysmmu", }, ++ { }, ++}; ++#endif ++ ++static struct platform_driver exynos_sysmmu_driver __refdata = { ++ .probe = exynos_sysmmu_probe, ++ .driver = { + .owner = THIS_MODULE, + .name = "exynos-sysmmu", ++ .of_match_table = of_match_ptr(sysmmu_of_match), + } + }; + +-- +1.8.3.2 + diff --git a/patches.tizen/0022-iommu-exynos-remove-prefetch-buffer-setting-when-ena.patch b/patches.tizen/0022-iommu-exynos-remove-prefetch-buffer-setting-when-ena.patch new file mode 100644 index 00000000000..f2a6b1a64d8 --- /dev/null +++ b/patches.tizen/0022-iommu-exynos-remove-prefetch-buffer-setting-when-ena.patch @@ -0,0 +1,88 @@ +From 502cdfe01e48640471d866215e432f0a7f67544e Mon Sep 17 00:00:00 2001 +From: Cho KyongHo <pullip.cho@samsung.com> +Date: Fri, 26 Jul 2013 20:28:49 +0900 +Subject: [PATCH 0022/1302] iommu/exynos: remove prefetch buffer setting when + enabling System MMU + +Prefetch buffer must be handled accurately, exact range of a buffer, +frame by frame manually. Otherwise, it may causes page fault or +deadlock in System MMU. +Thus this patch removes prefetch buffer setting when System MMU is +initialized(enabled). + +Signed-off-by: Cho KyongHo <pullip.cho@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + drivers/iommu/exynos-iommu.c | 32 +++++++++++++++++++++++++++----- + 1 file changed, 27 insertions(+), 5 deletions(-) + +diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c +index cfc02ed..87f6bb7 100644 +--- a/drivers/iommu/exynos-iommu.c ++++ b/drivers/iommu/exynos-iommu.c +@@ -80,6 +80,8 @@ + #define CTRL_BLOCK 0x7 + #define CTRL_DISABLE 0x0 + ++#define CFG_FLPDCACHE (1 << 20) /* System MMU 3.2+ only */ ++ + #define REG_MMU_CTRL 0x000 + #define REG_MMU_CFG 0x004 + #define REG_MMU_STATUS 0x008 +@@ -96,6 +98,9 @@ + + #define REG_MMU_VERSION 0x034 + ++#define MMU_MAJ_VER(reg) (reg >> 28) ++#define MMU_MIN_VER(reg) ((reg >> 21) & 0x7F) ++ + #define REG_PB0_SADDR 0x04C + #define REG_PB0_EADDR 0x050 + #define REG_PB1_SADDR 0x054 +@@ -200,6 +205,22 @@ static bool is_sysmmu_active(struct sysmmu_drvdata *data) + return data->activations > 0; + } + ++static unsigned int __sysmmu_version(struct sysmmu_drvdata *data, ++ int idx, unsigned int *minor) ++{ ++ unsigned long major; ++ ++ major = readl(data->sfrbases[idx] + REG_MMU_VERSION); ++ ++ if (minor) ++ *minor = MMU_MIN_VER(major); ++ ++ if (MMU_MAJ_VER(major) > 3) ++ return 1; ++ ++ return MMU_MAJ_VER(major); ++} ++ + static void sysmmu_unblock(void __iomem *sfrbase) + { + __raw_writel(CTRL_ENABLE, sfrbase + REG_MMU_CTRL); +@@ -460,14 +481,15 @@ static int __exynos_sysmmu_enable(struct sysmmu_drvdata *data, + data->pgtable = pgtable; + + for (i = 0; i < data->nsfrs; i++) { ++ unsigned int min; ++ + __sysmmu_set_ptbase(data->sfrbases[i], pgtable); + +- if ((readl(data->sfrbases[i] + REG_MMU_VERSION) >> 28) == 3) { +- /* System MMU version is 3.x */ +- __raw_writel((1 << 12) | (2 << 28), ++ if ((__sysmmu_version(data, i, &min) == 3) && (min > 1)) { ++ unsigned long cfg; ++ cfg = __raw_readl(data->sfrbases[i] + REG_MMU_CFG); ++ __raw_writel(cfg | CFG_FLPDCACHE, + data->sfrbases[i] + REG_MMU_CFG); +- __sysmmu_set_prefbuf(data->sfrbases[i], 0, -1, 0); +- __sysmmu_set_prefbuf(data->sfrbases[i], 0, -1, 1); + } + + __raw_writel(CTRL_ENABLE, data->sfrbases[i] + REG_MMU_CTRL); +-- +1.8.3.2 + diff --git a/patches.tizen/0023-iommu-exynos-remove-custom-fault-handler.patch b/patches.tizen/0023-iommu-exynos-remove-custom-fault-handler.patch new file mode 100644 index 00000000000..cd90d3eccd1 --- /dev/null +++ b/patches.tizen/0023-iommu-exynos-remove-custom-fault-handler.patch @@ -0,0 +1,160 @@ +From 4cd7a209da2bf86ed038833232f757990828c0f7 Mon Sep 17 00:00:00 2001 +From: Cho KyongHo <pullip.cho@samsung.com> +Date: Fri, 26 Jul 2013 20:29:06 +0900 +Subject: [PATCH 0023/1302] iommu/exynos: remove custom fault handler + +This commit removes custom fault handler. The device drivers that +need to register fault handler can register +with iommu_set_fault_handler(). + +Signed-off-by: Cho KyongHo <pullip.cho@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + drivers/iommu/exynos-iommu.c | 71 +++++++++++--------------------------------- + 1 file changed, 17 insertions(+), 54 deletions(-) + +diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c +index 87f6bb7..f9853fe 100644 +--- a/drivers/iommu/exynos-iommu.c ++++ b/drivers/iommu/exynos-iommu.c +@@ -131,16 +131,6 @@ enum exynos_sysmmu_inttype { + SYSMMU_FAULTS_NUM + }; + +-/* +- * @itype: type of fault. +- * @pgtable_base: the physical address of page table base. This is 0 if @itype +- * is SYSMMU_BUSERROR. +- * @fault_addr: the device (virtual) address that the System MMU tried to +- * translated. This is 0 if @itype is SYSMMU_BUSERROR. +- */ +-typedef int (*sysmmu_fault_handler_t)(enum exynos_sysmmu_inttype itype, +- unsigned long pgtable_base, unsigned long fault_addr); +- + static unsigned short fault_reg_offset[SYSMMU_FAULTS_NUM] = { + REG_PAGE_FAULT_ADDR, + REG_AR_FAULT_ADDR, +@@ -181,7 +171,6 @@ struct sysmmu_drvdata { + int activations; + rwlock_t lock; + struct iommu_domain *domain; +- sysmmu_fault_handler_t fault_handler; + unsigned long pgtable; + void __iomem *sfrbases[0]; + }; +@@ -313,34 +302,17 @@ finish: + read_unlock_irqrestore(&data->lock, flags); + } + +-static void __set_fault_handler(struct sysmmu_drvdata *data, +- sysmmu_fault_handler_t handler) +-{ +- unsigned long flags; +- +- write_lock_irqsave(&data->lock, flags); +- data->fault_handler = handler; +- write_unlock_irqrestore(&data->lock, flags); +-} +- +-void exynos_sysmmu_set_fault_handler(struct device *dev, +- sysmmu_fault_handler_t handler) +-{ +- struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); +- +- __set_fault_handler(data, handler); +-} +- +-static int default_fault_handler(enum exynos_sysmmu_inttype itype, +- unsigned long pgtable_base, unsigned long fault_addr) ++static void show_fault_information(const char *name, ++ enum exynos_sysmmu_inttype itype, ++ unsigned long pgtable_base, unsigned long fault_addr) + { + unsigned long *ent; + + if ((itype >= SYSMMU_FAULTS_NUM) || (itype < SYSMMU_PAGEFAULT)) + itype = SYSMMU_FAULT_UNKNOWN; + +- pr_err("%s occurred at 0x%lx(Page table base: 0x%lx)\n", +- sysmmu_fault_name[itype], fault_addr, pgtable_base); ++ pr_err("%s occurred at 0x%lx by %s(Page table base: 0x%lx)\n", ++ sysmmu_fault_name[itype], fault_addr, name, pgtable_base); + + ent = section_entry(__va(pgtable_base), fault_addr); + pr_err("\tLv1 entry: 0x%lx\n", *ent); +@@ -353,16 +325,12 @@ static int default_fault_handler(enum exynos_sysmmu_inttype itype, + pr_err("Generating Kernel OOPS... because it is unrecoverable.\n"); + + BUG(); +- +- return 0; + } + + static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) + { + /* SYSMMU is in blocked when interrupt occurred. */ + struct sysmmu_drvdata *data = dev_id; +- struct resource *irqres; +- struct platform_device *pdev; + enum exynos_sysmmu_inttype itype; + unsigned long addr = -1; + +@@ -372,14 +340,15 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) + + WARN_ON(!is_sysmmu_active(data)); + +- pdev = to_platform_device(data->sysmmu); +- for (i = 0; i < (pdev->num_resources / 2); i++) { +- irqres = platform_get_resource(pdev, IORESOURCE_IRQ, i); ++ for (i = 0; i < data->nsfrs; i++) { ++ struct resource *irqres; ++ irqres = platform_get_resource(to_platform_device(data->sysmmu), ++ IORESOURCE_IRQ, i); + if (irqres && ((int)irqres->start == irq)) + break; + } + +- if (i == pdev->num_resources) { ++ if (i == data->nsfrs) { + itype = SYSMMU_FAULT_UNKNOWN; + } else { + itype = (enum exynos_sysmmu_inttype) +@@ -395,19 +364,15 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) + ret = report_iommu_fault(data->domain, data->dev, + addr, itype); + +- if ((ret == -ENOSYS) && data->fault_handler) { +- unsigned long base = data->pgtable; +- if (itype != SYSMMU_FAULT_UNKNOWN) +- base = __raw_readl( +- data->sfrbases[i] + REG_PT_BASE_ADDR); +- ret = data->fault_handler(itype, base, addr); +- } +- + if (!ret && (itype != SYSMMU_FAULT_UNKNOWN)) + __raw_writel(1 << itype, data->sfrbases[i] + REG_INT_CLEAR); +- else +- dev_dbg(data->sysmmu, "%s is not handled.\n", +- sysmmu_fault_name[itype]); ++ else { ++ unsigned long ba = data->pgtable; ++ if (itype != SYSMMU_FAULT_UNKNOWN) ++ ba = __raw_readl(data->sfrbases[i] + REG_PT_BASE_ADDR); ++ show_fault_information(dev_name(data->sysmmu), ++ itype, ba, addr); ++ } + + if (itype != SYSMMU_FAULT_UNKNOWN) + sysmmu_unblock(data->sfrbases[i]); +@@ -644,8 +609,6 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev) + + pm_runtime_enable(dev); + +- __set_fault_handler(data, &default_fault_handler); +- + data->sysmmu = dev; + data->clk = devm_clk_get(dev, "sysmmu"); + if (IS_ERR(data->clk)) { +-- +1.8.3.2 + diff --git a/patches.tizen/0024-iommu-exynos-add-bus-notifier-for-registering-System.patch b/patches.tizen/0024-iommu-exynos-add-bus-notifier-for-registering-System.patch new file mode 100644 index 00000000000..e4335de9074 --- /dev/null +++ b/patches.tizen/0024-iommu-exynos-add-bus-notifier-for-registering-System.patch @@ -0,0 +1,987 @@ +From 9f3387f3b3b2acc4042eb81e7f86123c4a308280 Mon Sep 17 00:00:00 2001 +From: Cho KyongHo <pullip.cho@samsung.com> +Date: Fri, 26 Jul 2013 20:30:17 +0900 +Subject: [PATCH 0024/1302] iommu/exynos: add bus notifier for registering + System MMU + +When a device driver is registered, all constructs to handle System MMU +is prepared by bus notifier call. + +Signed-off-by: Cho KyongHo <pullip.cho@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + drivers/iommu/exynos-iommu.c | 708 +++++++++++++++++++++++++++++++++---------- + 1 file changed, 552 insertions(+), 156 deletions(-) + +diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c +index f9853fe..c62c244 100644 +--- a/drivers/iommu/exynos-iommu.c ++++ b/drivers/iommu/exynos-iommu.c +@@ -27,6 +27,9 @@ + #include <linux/memblock.h> + #include <linux/export.h> + #include <linux/of.h> ++#include <linux/of_platform.h> ++#include <linux/pm_domain.h> ++#include <linux/notifier.h> + + #include <asm/cacheflush.h> + #include <asm/pgtable.h> +@@ -80,7 +83,13 @@ + #define CTRL_BLOCK 0x7 + #define CTRL_DISABLE 0x0 + ++#define CFG_LRU 0x1 ++#define CFG_QOS(n) ((n & 0xF) << 7) ++#define CFG_MASK 0x0150FFFF /* Selecting bit 0-15, 20, 22 and 24 */ ++#define CFG_ACGEN (1 << 24) /* System MMU 3.3 only */ ++#define CFG_SYSSEL (1 << 22) /* System MMU 3.2 only */ + #define CFG_FLPDCACHE (1 << 20) /* System MMU 3.2+ only */ ++#define CFG_SHAREABLE (1 << 12) /* System MMU 3.x only */ + + #define REG_MMU_CTRL 0x000 + #define REG_MMU_CFG 0x004 +@@ -154,6 +163,14 @@ static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = { + "UNKNOWN FAULT" + }; + ++struct exynos_iommu_client { ++ struct list_head node; /* entry of exynos_iommu_domain.clients */ ++ struct device *dev; ++ spinlock_t lock; ++ int num_sysmmu; ++ struct device *sysmmu[0]; ++}; ++ + struct exynos_iommu_domain { + struct list_head clients; /* list of sysmmu_drvdata.node */ + unsigned long *pgtable; /* lv1 page table, 16KB */ +@@ -165,12 +182,14 @@ struct exynos_iommu_domain { + struct sysmmu_drvdata { + struct list_head node; /* entry of exynos_iommu_domain.clients */ + struct device *sysmmu; /* System MMU's device descriptor */ +- struct device *dev; /* Owner of system MMU */ ++ struct device *master; /* Owner of system MMU */ + int nsfrs; + struct clk *clk; ++ struct clk *clk_master; + int activations; + rwlock_t lock; + struct iommu_domain *domain; ++ bool runtime_active; + unsigned long pgtable; + void __iomem *sfrbases[0]; + }; +@@ -245,7 +264,6 @@ static void __sysmmu_tlb_invalidate_entry(void __iomem *sfrbase, + static void __sysmmu_set_ptbase(void __iomem *sfrbase, + unsigned long pgd) + { +- __raw_writel(0x1, sfrbase + REG_MMU_CFG); /* 16KB LV1, LRU */ + __raw_writel(pgd, sfrbase + REG_PT_BASE_ADDR); + + __sysmmu_tlb_invalidate(sfrbase); +@@ -273,6 +291,7 @@ void exynos_sysmmu_set_prefbuf(struct device *dev, + if (!is_sysmmu_active(data)) + goto finish; + ++ clk_enable(data->clk_master); + for (i = 0; i < data->nsfrs; i++) { + if ((readl(data->sfrbases[i] + REG_MMU_VERSION) >> 28) == 3) { + if (!sysmmu_block(data->sfrbases[i])) +@@ -298,6 +317,7 @@ void exynos_sysmmu_set_prefbuf(struct device *dev, + sysmmu_unblock(data->sfrbases[i]); + } + } ++ clk_disable(data->clk_master); + finish: + read_unlock_irqrestore(&data->lock, flags); + } +@@ -331,12 +351,13 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) + { + /* SYSMMU is in blocked when interrupt occurred. */ + struct sysmmu_drvdata *data = dev_id; ++ struct exynos_iommu_client *client = NULL; + enum exynos_sysmmu_inttype itype; + unsigned long addr = -1; +- + int i, ret = -ENOSYS; + +- read_lock(&data->lock); ++ if (data->master) ++ client = data->master->archdata.iommu; + + WARN_ON(!is_sysmmu_active(data)); + +@@ -348,6 +369,10 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) + break; + } + ++ if (client) ++ spin_lock(&client->lock); ++ read_lock(&data->lock); ++ + if (i == data->nsfrs) { + itype = SYSMMU_FAULT_UNKNOWN; + } else { +@@ -361,7 +386,7 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) + } + + if (data->domain) +- ret = report_iommu_fault(data->domain, data->dev, ++ ret = report_iommu_fault(data->domain, data->master, + addr, itype); + + if (!ret && (itype != SYSMMU_FAULT_UNKNOWN)) +@@ -378,177 +403,251 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) + sysmmu_unblock(data->sfrbases[i]); + + read_unlock(&data->lock); ++ if (client) ++ spin_unlock(&client->lock); + + return IRQ_HANDLED; + } + +-static bool __exynos_sysmmu_disable(struct sysmmu_drvdata *data) ++static void __sysmmu_disable_nocount(struct sysmmu_drvdata *data) + { +- unsigned long flags; +- bool disabled = false; + int i; + +- write_lock_irqsave(&data->lock, flags); ++ clk_enable(data->clk_master); ++ for (i = 0; i < data->nsfrs; i++) { ++ __raw_writel(CTRL_DISABLE, ++ data->sfrbases[i] + REG_MMU_CTRL); ++ __raw_writel(0, data->sfrbases[i] + REG_MMU_CFG); ++ } + +- if (!set_sysmmu_inactive(data)) +- goto finish; ++ clk_disable(data->clk); ++ clk_disable(data->clk_master); ++} + +- for (i = 0; i < data->nsfrs; i++) +- __raw_writel(CTRL_DISABLE, data->sfrbases[i] + REG_MMU_CTRL); ++static bool __sysmmu_disable(struct sysmmu_drvdata *data) ++{ ++ bool disabled; ++ unsigned long flags; + +- if (data->clk) +- clk_disable(data->clk); ++ write_lock_irqsave(&data->lock, flags); + +- disabled = true; +- data->pgtable = 0; +- data->domain = NULL; +-finish: +- write_unlock_irqrestore(&data->lock, flags); ++ disabled = set_sysmmu_inactive(data); ++ ++ if (disabled) { ++ data->pgtable = 0; ++ data->domain = NULL; ++ ++ if (data->runtime_active) ++ __sysmmu_disable_nocount(data); + +- if (disabled) + dev_dbg(data->sysmmu, "Disabled\n"); +- else +- dev_dbg(data->sysmmu, "%d times left to be disabled\n", ++ } else { ++ dev_dbg(data->sysmmu, "%d times left to disable\n", + data->activations); ++ } ++ ++ write_unlock_irqrestore(&data->lock, flags); + + return disabled; + } + +-/* __exynos_sysmmu_enable: Enables System MMU +- * +- * returns -error if an error occurred and System MMU is not enabled, +- * 0 if the System MMU has been just enabled and 1 if System MMU was already +- * enabled before. +- */ +-static int __exynos_sysmmu_enable(struct sysmmu_drvdata *data, ++ ++static void __sysmmu_init_config(struct sysmmu_drvdata *data, int idx) ++{ ++ unsigned long cfg = CFG_LRU | CFG_QOS(15); ++ int maj, min = 0; ++ ++ maj = __sysmmu_version(data, idx, &min); ++ if (maj == 3) { ++ if (min > 1) { ++ cfg |= CFG_FLPDCACHE; ++ cfg |= (min == 2) ? CFG_SYSSEL : CFG_ACGEN; ++ } ++ } ++ ++ __raw_writel(cfg, data->sfrbases[idx] + REG_MMU_CFG); ++} ++ ++static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data) ++{ ++ int i; ++ ++ clk_enable(data->clk_master); ++ clk_enable(data->clk); ++ ++ for (i = 0; i < data->nsfrs; i++) { ++ __raw_writel(CTRL_BLOCK, data->sfrbases[i] + REG_MMU_CTRL); ++ ++ __sysmmu_init_config(data, i); ++ ++ __sysmmu_set_ptbase(data->sfrbases[i], data->pgtable); ++ ++ __raw_writel(CTRL_ENABLE, data->sfrbases[i] + REG_MMU_CTRL); ++ } ++ clk_disable(data->clk_master); ++} ++ ++static int __sysmmu_enable(struct sysmmu_drvdata *data, + unsigned long pgtable, struct iommu_domain *domain) + { +- int i, ret = 0; ++ int ret = 0; + unsigned long flags; + + write_lock_irqsave(&data->lock, flags); ++ if (set_sysmmu_active(data)) { ++ data->pgtable = pgtable; ++ data->domain = domain; + +- if (!set_sysmmu_active(data)) { +- if (WARN_ON(pgtable != data->pgtable)) { +- ret = -EBUSY; +- set_sysmmu_inactive(data); +- } else { +- ret = 1; +- } ++ if (data->runtime_active) ++ __sysmmu_enable_nocount(data); + +- dev_dbg(data->sysmmu, "Already enabled\n"); +- goto finish; ++ dev_dbg(data->sysmmu, "Enabled\n"); ++ } else { ++ ret = (pgtable == data->pgtable) ? 1 : -EBUSY; ++ ++ dev_dbg(data->sysmmu, "already enabled\n"); + } + +- if (data->clk) +- clk_enable(data->clk); ++ if (WARN_ON(ret < 0)) ++ set_sysmmu_inactive(data); /* decrement count */ + +- data->pgtable = pgtable; ++ write_unlock_irqrestore(&data->lock, flags); + +- for (i = 0; i < data->nsfrs; i++) { +- unsigned int min; ++ return ret; ++} + +- __sysmmu_set_ptbase(data->sfrbases[i], pgtable); ++/* __exynos_sysmmu_enable: Enables System MMU ++ * ++ * returns -error if an error occurred and System MMU is not enabled, ++ * 0 if the System MMU has been just enabled and 1 if System MMU was already ++ * enabled before. ++ */ ++static int __exynos_sysmmu_enable(struct device *dev, unsigned long pgtable, ++ struct iommu_domain *domain) ++{ ++ int ret = 0; ++ unsigned long flags; ++ struct exynos_iommu_client *client = dev->archdata.iommu; ++ int i; + +- if ((__sysmmu_version(data, i, &min) == 3) && (min > 1)) { +- unsigned long cfg; +- cfg = __raw_readl(data->sfrbases[i] + REG_MMU_CFG); +- __raw_writel(cfg | CFG_FLPDCACHE, +- data->sfrbases[i] + REG_MMU_CFG); +- } ++ if (WARN_ON(!client)) ++ return -ENODEV; + +- __raw_writel(CTRL_ENABLE, data->sfrbases[i] + REG_MMU_CTRL); +- } ++ spin_lock_irqsave(&client->lock, flags); + +- data->domain = domain; ++ for (i = 0; i < client->num_sysmmu; i++) { ++ struct sysmmu_drvdata *data = ++ dev_get_drvdata(client->sysmmu[i]); ++ ret = __sysmmu_enable(data, pgtable, domain); ++ if (ret < 0) { ++ int j; ++ for (j = 0; j < i; j++) ++ __sysmmu_disable(data); ++ break; ++ } else { ++ data->master = dev; ++ } ++ } + +- dev_dbg(data->sysmmu, "Enabled\n"); +-finish: +- write_unlock_irqrestore(&data->lock, flags); ++ spin_unlock_irqrestore(&client->lock, flags); + + return ret; + } + + int exynos_sysmmu_enable(struct device *dev, unsigned long pgtable) + { +- struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); + int ret; + + BUG_ON(!memblock_is_memory(pgtable)); + +- ret = pm_runtime_get_sync(data->sysmmu); +- if (ret < 0) { +- dev_dbg(data->sysmmu, "Failed to enable\n"); +- return ret; +- } +- +- ret = __exynos_sysmmu_enable(data, pgtable, NULL); +- if (WARN_ON(ret < 0)) { +- pm_runtime_put(data->sysmmu); +- dev_err(data->sysmmu, +- "Already enabled with page table %#lx\n", +- data->pgtable); +- } else { +- data->dev = dev; +- } ++ ret = __exynos_sysmmu_enable(dev, pgtable, NULL); + + return ret; + } + + static bool exynos_sysmmu_disable(struct device *dev) + { +- struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); +- bool disabled; ++ unsigned long flags; ++ bool disabled = true; ++ struct exynos_iommu_client *client = dev->archdata.iommu; ++ int i; + +- disabled = __exynos_sysmmu_disable(data); +- pm_runtime_put(data->sysmmu); ++ if (WARN_ON(!client)) ++ return true; ++ ++ spin_lock_irqsave(&client->lock, flags); ++ ++ /* Every call to __sysmmu_disable() must return same result */ ++ for (i = 0; i < client->num_sysmmu; i++) { ++ struct sysmmu_drvdata *data = ++ dev_get_drvdata(client->sysmmu[i]); ++ disabled = __sysmmu_disable(data); ++ if (disabled) ++ data->master = NULL; ++ } ++ ++ spin_unlock_irqrestore(&client->lock, flags); + + return disabled; + } + + static void sysmmu_tlb_invalidate_entry(struct device *dev, unsigned long iova) + { +- unsigned long flags; +- struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); ++ struct exynos_iommu_client *client = dev->archdata.iommu; ++ int i; + +- read_lock_irqsave(&data->lock, flags); ++ for (i = 0; i < client->num_sysmmu; i++) { ++ unsigned long flags; ++ struct sysmmu_drvdata *data; + +- if (is_sysmmu_active(data)) { +- int i; +- for (i = 0; i < data->nsfrs; i++) { +- if (sysmmu_block(data->sfrbases[i])) { ++ data = dev_get_drvdata(client->sysmmu[i]); ++ ++ read_lock_irqsave(&data->lock, flags); ++ if (is_sysmmu_active(data) && data->runtime_active) { ++ int i; ++ clk_enable(data->clk_master); ++ for (i = 0; i < data->nsfrs; i++) + __sysmmu_tlb_invalidate_entry( + data->sfrbases[i], iova); +- sysmmu_unblock(data->sfrbases[i]); +- } ++ clk_disable(data->clk_master); ++ } else { ++ dev_dbg(dev, ++ "disabled. Skipping TLB invalidation @ %#lx\n", ++ iova); + } +- } else { +- dev_dbg(data->sysmmu, "Disabled. Skipping invalidating TLB.\n"); ++ read_unlock_irqrestore(&data->lock, flags); + } +- +- read_unlock_irqrestore(&data->lock, flags); + } + + void exynos_sysmmu_tlb_invalidate(struct device *dev) + { +- unsigned long flags; +- struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); +- +- read_lock_irqsave(&data->lock, flags); ++ struct exynos_iommu_client *client = dev->archdata.iommu; ++ int i; + +- if (is_sysmmu_active(data)) { +- int i; +- for (i = 0; i < data->nsfrs; i++) { +- if (sysmmu_block(data->sfrbases[i])) { +- __sysmmu_tlb_invalidate(data->sfrbases[i]); +- sysmmu_unblock(data->sfrbases[i]); ++ for (i = 0; i < client->num_sysmmu; i++) { ++ unsigned long flags; ++ struct sysmmu_drvdata *data; ++ ++ data = dev_get_drvdata(client->sysmmu[i]); ++ ++ read_lock_irqsave(&data->lock, flags); ++ if (is_sysmmu_active(data) && ++ data->runtime_active) { ++ int i; ++ for (i = 0; i < data->nsfrs; i++) { ++ clk_enable(data->clk_master); ++ if (sysmmu_block(data->sfrbases[i])) { ++ __sysmmu_tlb_invalidate( ++ data->sfrbases[i]); ++ sysmmu_unblock(data->sfrbases[i]); ++ } ++ clk_disable(data->clk_master); + } ++ } else { ++ dev_dbg(dev, "disabled. Skipping TLB invalidation\n"); + } +- } else { +- dev_dbg(data->sysmmu, "Disabled. Skipping invalidating TLB.\n"); ++ read_unlock_irqrestore(&data->lock, flags); + } +- +- read_unlock_irqrestore(&data->lock, flags); + } + + static int __init exynos_sysmmu_probe(struct platform_device *pdev) +@@ -610,12 +709,32 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev) + pm_runtime_enable(dev); + + data->sysmmu = dev; ++ + data->clk = devm_clk_get(dev, "sysmmu"); + if (IS_ERR(data->clk)) { + dev_info(dev, "No gate clock found!\n"); + data->clk = NULL; + } + ++ ret = clk_prepare(data->clk); ++ if (ret) { ++ dev_err(dev, "Failed to prepare clk\n"); ++ return ret; ++ } ++ ++ data->clk_master = devm_clk_get(dev, "master"); ++ if (IS_ERR(data->clk_master)) ++ data->clk_master = NULL; ++ ++ ret = clk_prepare(data->clk_master); ++ if (ret) { ++ clk_unprepare(data->clk); ++ dev_err(dev, "Failed to prepare master's clk\n"); ++ return ret; ++ } ++ ++ data->runtime_active = !pm_runtime_enabled(dev); ++ + rwlock_init(&data->lock); + INIT_LIST_HEAD(&data->node); + +@@ -625,6 +744,34 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev) + return ret; + } + ++#ifdef CONFIG_PM_SLEEP ++static int sysmmu_suspend(struct device *dev) ++{ ++ struct sysmmu_drvdata *data = dev_get_drvdata(dev); ++ unsigned long flags; ++ read_lock_irqsave(&data->lock, flags); ++ if (is_sysmmu_active(data) && ++ (!pm_runtime_enabled(dev) || data->runtime_active)) ++ __sysmmu_disable_nocount(data); ++ read_unlock_irqrestore(&data->lock, flags); ++ return 0; ++} ++ ++static int sysmmu_resume(struct device *dev) ++{ ++ struct sysmmu_drvdata *data = dev_get_drvdata(dev); ++ unsigned long flags; ++ read_lock_irqsave(&data->lock, flags); ++ if (is_sysmmu_active(data) && ++ (!pm_runtime_enabled(dev) || data->runtime_active)) ++ __sysmmu_enable_nocount(data); ++ read_unlock_irqrestore(&data->lock, flags); ++ return 0; ++} ++#endif ++ ++static SIMPLE_DEV_PM_OPS(sysmmu_pm_ops, sysmmu_suspend, sysmmu_resume); ++ + #ifdef CONFIG_OF + static struct of_device_id sysmmu_of_match[] __initconst = { + { .compatible = "samsung,exynos4210-sysmmu", }, +@@ -637,6 +784,7 @@ static struct platform_driver exynos_sysmmu_driver __refdata = { + .driver = { + .owner = THIS_MODULE, + .name = "exynos-sysmmu", ++ .pm = &sysmmu_pm_ops, + .of_match_table = of_match_ptr(sysmmu_of_match), + } + }; +@@ -689,7 +837,7 @@ err_pgtable: + static void exynos_iommu_domain_destroy(struct iommu_domain *domain) + { + struct exynos_iommu_domain *priv = domain->priv; +- struct sysmmu_drvdata *data; ++ struct exynos_iommu_client *client; + unsigned long flags; + int i; + +@@ -697,11 +845,14 @@ static void exynos_iommu_domain_destroy(struct iommu_domain *domain) + + spin_lock_irqsave(&priv->lock, flags); + +- list_for_each_entry(data, &priv->clients, node) { +- while (!exynos_sysmmu_disable(data->dev)) ++ list_for_each_entry(client, &priv->clients, node) { ++ while (!exynos_sysmmu_disable(client->dev)) + ; /* until System MMU is actually disabled */ + } + ++ while (!list_empty(&priv->clients)) ++ list_del_init(priv->clients.next); ++ + spin_unlock_irqrestore(&priv->lock, flags); + + for (i = 0; i < NUM_LV1ENTRIES; i++) +@@ -718,41 +869,26 @@ static void exynos_iommu_domain_destroy(struct iommu_domain *domain) + static int exynos_iommu_attach_device(struct iommu_domain *domain, + struct device *dev) + { +- struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); ++ struct exynos_iommu_client *client = dev->archdata.iommu; + struct exynos_iommu_domain *priv = domain->priv; + unsigned long flags; + int ret; + +- ret = pm_runtime_get_sync(data->sysmmu); +- if (ret < 0) +- return ret; +- +- ret = 0; +- + spin_lock_irqsave(&priv->lock, flags); + +- ret = __exynos_sysmmu_enable(data, __pa(priv->pgtable), domain); +- +- if (ret == 0) { +- /* 'data->node' must not be appeared in priv->clients */ +- BUG_ON(!list_empty(&data->node)); +- data->dev = dev; +- list_add_tail(&data->node, &priv->clients); +- } ++ ret = __exynos_sysmmu_enable(dev, __pa(priv->pgtable), domain); ++ if (ret == 0) ++ list_add_tail(&client->node, &priv->clients); + + spin_unlock_irqrestore(&priv->lock, flags); + +- if (ret < 0) { ++ if (ret < 0) + dev_err(dev, "%s: Failed to attach IOMMU with pgtable %#lx\n", + __func__, __pa(priv->pgtable)); +- pm_runtime_put(data->sysmmu); +- } else if (ret > 0) { +- dev_dbg(dev, "%s: IOMMU with pgtable 0x%lx already attached\n", +- __func__, __pa(priv->pgtable)); +- } else { +- dev_dbg(dev, "%s: Attached new IOMMU with pgtable 0x%lx\n", +- __func__, __pa(priv->pgtable)); +- } ++ else ++ dev_dbg(dev, "%s: Attached IOMMU with pgtable 0x%lx%s\n", ++ __func__, __pa(priv->pgtable), ++ (ret == 0) ? "" : ", again"); + + return ret; + } +@@ -760,39 +896,27 @@ static int exynos_iommu_attach_device(struct iommu_domain *domain, + static void exynos_iommu_detach_device(struct iommu_domain *domain, + struct device *dev) + { +- struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); ++ struct exynos_iommu_client *client = NULL; + struct exynos_iommu_domain *priv = domain->priv; +- struct list_head *pos; + unsigned long flags; +- bool found = false; + + spin_lock_irqsave(&priv->lock, flags); + +- list_for_each(pos, &priv->clients) { +- if (list_entry(pos, struct sysmmu_drvdata, node) == data) { +- found = true; ++ list_for_each_entry(client, &priv->clients, node) { ++ if (client == dev->archdata.iommu) { ++ if (exynos_sysmmu_disable(dev)) ++ list_del_init(&client->node); + break; + } + } + +- if (!found) +- goto finish; ++ spin_unlock_irqrestore(&priv->lock, flags); + +- if (__exynos_sysmmu_disable(data)) { ++ if (client == dev->archdata.iommu) + dev_dbg(dev, "%s: Detached IOMMU with pgtable %#lx\n", + __func__, __pa(priv->pgtable)); +- list_del_init(&data->node); +- +- } else { +- dev_dbg(dev, "%s: Detaching IOMMU with pgtable %#lx delayed", +- __func__, __pa(priv->pgtable)); +- } +- +-finish: +- spin_unlock_irqrestore(&priv->lock, flags); +- +- if (found) +- pm_runtime_put(data->sysmmu); ++ else ++ dev_dbg(dev, "%s: No IOMMU is attached\n", __func__); + } + + static unsigned long *alloc_lv2entry(unsigned long *sent, unsigned long iova, +@@ -914,7 +1038,7 @@ static size_t exynos_iommu_unmap(struct iommu_domain *domain, + unsigned long iova, size_t size) + { + struct exynos_iommu_domain *priv = domain->priv; +- struct sysmmu_drvdata *data; ++ struct exynos_iommu_client *client; + unsigned long flags; + unsigned long *ent; + size_t err_pgsize; +@@ -975,8 +1099,8 @@ done: + spin_unlock_irqrestore(&priv->pgtablelock, flags); + + spin_lock_irqsave(&priv->lock, flags); +- list_for_each_entry(data, &priv->clients, node) +- sysmmu_tlb_invalidate_entry(data->dev, iova); ++ list_for_each_entry(client, &priv->clients, node) ++ sysmmu_tlb_invalidate_entry(client->dev, iova); + spin_unlock_irqrestore(&priv->lock, flags); + + return size; +@@ -1055,3 +1179,275 @@ static int __init exynos_iommu_init(void) + return ret; + } + subsys_initcall(exynos_iommu_init); ++ ++#ifdef CONFIG_PM_SLEEP ++static int sysmmu_pm_genpd_suspend(struct device *dev) ++{ ++ struct exynos_iommu_client *client = dev->archdata.iommu; ++ int ret = 0; ++ int i; ++ ++ for (i = 0; i < client->num_sysmmu; i++) { ++ ret = pm_generic_suspend(client->sysmmu[i]); ++ if (ret) ++ break; ++ } ++ ++ if (!ret) ++ ret = pm_generic_suspend(dev); ++ ++ if (ret) { ++ int j; ++ ++ for (j = 0; j < i; j++) ++ pm_generic_resume(client->sysmmu[j]); ++ } ++ ++ return ret; ++} ++ ++static int sysmmu_pm_genpd_resume(struct device *dev) ++{ ++ struct exynos_iommu_client *client = dev->archdata.iommu; ++ int ret = 0; ++ int i; ++ ++ for (i = 0; i < client->num_sysmmu; i++) { ++ ret = pm_generic_resume(client->sysmmu[i]); ++ if (ret) ++ break; ++ } ++ ++ if (!ret) ++ ret = pm_generic_resume(dev); ++ ++ if (ret) { ++ int j; ++ ++ for (j = 0; j < i; j++) ++ pm_generic_suspend(client->sysmmu[j]); ++ } ++ ++ return ret; ++} ++#endif ++ ++#ifdef CONFIG_PM_RUNTIME ++static void sysmmu_restore_state(struct device *sysmmu) ++{ ++ struct sysmmu_drvdata *data = dev_get_drvdata(sysmmu); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&data->lock, flags); ++ data->runtime_active = true; ++ if (is_sysmmu_active(data)) ++ __sysmmu_enable_nocount(data); ++ spin_unlock_irqrestore(&data->lock, flags); ++} ++ ++static void sysmmu_save_state(struct device *sysmmu) ++{ ++ struct sysmmu_drvdata *data = dev_get_drvdata(sysmmu); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&data->lock, flags); ++ if (is_sysmmu_active(data)) ++ __sysmmu_disable_nocount(data); ++ data->runtime_active = false; ++ spin_unlock_irqrestore(&data->lock, flags); ++} ++ ++static int sysmmu_pm_genpd_save_state(struct device *dev) ++{ ++ struct exynos_iommu_client *client = dev->archdata.iommu; ++ int (*cb)(struct device *__dev); ++ int i; ++ ++ if (dev->type && dev->type->pm) ++ cb = dev->type->pm->runtime_suspend; ++ else if (dev->class && dev->class->pm) ++ cb = dev->class->pm->runtime_suspend; ++ else if (dev->bus && dev->bus->pm) ++ cb = dev->bus->pm->runtime_suspend; ++ else ++ cb = NULL; ++ ++ if (!cb && dev->driver && dev->driver->pm) ++ cb = dev->driver->pm->runtime_suspend; ++ ++ if (cb) { ++ int ret; ++ ++ ret = cb(dev); ++ if (ret) ++ return ret; ++ } ++ ++ for (i = 0; i < client->num_sysmmu; i++) ++ sysmmu_save_state(client->sysmmu[i]); ++ ++ return 0; ++} ++ ++static int sysmmu_pm_genpd_restore_state(struct device *dev) ++{ ++ struct exynos_iommu_client *client = dev->archdata.iommu; ++ int (*cb)(struct device *__dev); ++ int i; ++ ++ if (dev->type && dev->type->pm) ++ cb = dev->type->pm->runtime_resume; ++ else if (dev->class && dev->class->pm) ++ cb = dev->class->pm->runtime_resume; ++ else if (dev->bus && dev->bus->pm) ++ cb = dev->bus->pm->runtime_resume; ++ else ++ cb = NULL; ++ ++ if (!cb && dev->driver && dev->driver->pm) ++ cb = dev->driver->pm->runtime_resume; ++ ++ for (i = 0; i < client->num_sysmmu; i++) ++ sysmmu_restore_state(client->sysmmu[i]); ++ ++ if (cb) { ++ int ret; ++ ret = cb(dev); ++ if (ret) { ++ for (i = 0; i < client->num_sysmmu; i++) ++ sysmmu_save_state(client->sysmmu[i]); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++#endif ++ ++#ifdef CONFIG_PM_GENERIC_DOMAINS ++struct gpd_dev_ops sysmmu_devpm_ops = { ++#ifdef CONFIG_PM_RUNTIME ++ .save_state = &sysmmu_pm_genpd_save_state, ++ .restore_state = &sysmmu_pm_genpd_restore_state, ++#endif ++#ifdef CONFIG_PM_SLEEP ++ .suspend = &sysmmu_pm_genpd_suspend, ++ .resume = &sysmmu_pm_genpd_resume, ++#endif ++}; ++#endif /* CONFIG_PM_GENERIC_DOMAINS */ ++ ++static int sysmmu_hook_driver_register(struct notifier_block *nb, ++ unsigned long val, ++ void *p) ++{ ++ struct device *dev = p; ++ ++ switch (val) { ++ case BUS_NOTIFY_BIND_DRIVER: ++ { ++ int i = 0; ++ int size = 0; ++ const __be32 *phandle; ++ struct exynos_iommu_client *client; ++ ++ phandle = of_get_property(dev->of_node, "iommu", &size); ++ if (!phandle) ++ break; ++ ++ size = size / sizeof(*phandle); /* number of elements */ ++ ++ client = devm_kzalloc(dev, sizeof(*client) * size, GFP_KERNEL); ++ if (!client) { ++ dev_err(dev, "No Memory for exynos_iommu_client\n"); ++ return -ENOMEM; ++ } ++ ++ client->num_sysmmu = size; ++ client->dev = dev; ++ INIT_LIST_HEAD(&client->node); ++ spin_lock_init(&client->lock); ++ ++ for (i = 0; i < size; i++) { ++ struct device_node *np; ++ struct platform_device *sysmmu; ++ ++ /* this always success: see above of_find_property() */ ++ np = of_parse_phandle(dev->of_node, "iommu", i); ++ ++ sysmmu = of_find_device_by_node(np); ++ if (!sysmmu) { ++ dev_err(dev, ++ "sysmmu node '%s' is not found\n", ++ np->name); ++ break; ++ } ++ ++ client->sysmmu[i] = &sysmmu->dev; ++ } ++ ++ if (i < size) { ++ while (--i >= 0) ++ of_node_put(client->sysmmu[i]->of_node); ++ devm_kfree(dev, client); ++ return -ENODEV; ++ } ++ ++ i = pm_genpd_add_callbacks(dev, &sysmmu_devpm_ops, NULL); ++ if (i && (i != -ENOSYS)) { ++ dev_err(dev, ++ "Failed to register 'dev_pm_ops' for iommu\n"); ++ devm_kfree(dev, client); ++ return i; ++ } ++ ++ dev->archdata.iommu = client; ++ break; ++ } ++ case BUS_NOTIFY_BOUND_DRIVER: ++ { ++ struct exynos_iommu_client *client = dev->archdata.iommu; ++ if (dev->archdata.iommu && ++ (!pm_runtime_enabled(dev) || ++ IS_ERR(dev_to_genpd(dev)))) { ++ int i; ++ for (i = 0; i < client->num_sysmmu; i++) { ++ struct sysmmu_drvdata *data; ++ pm_runtime_disable(client->sysmmu[i]); ++ data = dev_get_drvdata(client->sysmmu[i]); ++ if (!data) ++ continue; ++ data->runtime_active = ++ !pm_runtime_enabled(data->sysmmu); ++ if (data->runtime_active && ++ is_sysmmu_active(data)) ++ __sysmmu_enable_nocount(data); ++ } ++ } ++ break; ++ } ++ case BUS_NOTIFY_UNBOUND_DRIVER: ++ { ++ if (dev->archdata.iommu) { ++ __pm_genpd_remove_callbacks(dev, false); ++ ++ devm_kfree(dev, dev->archdata.iommu); ++ ++ dev->archdata.iommu = NULL; ++ } ++ break; ++ } ++ } /* switch (val) */ ++ ++ return 0; ++} ++ ++static struct notifier_block sysmmu_notifier = { ++ .notifier_call = &sysmmu_hook_driver_register, ++}; ++ ++static int __init exynos_iommu_prepare(void) ++{ ++ return bus_register_notifier(&platform_bus_type, &sysmmu_notifier); ++} ++arch_initcall(exynos_iommu_prepare); +-- +1.8.3.2 + diff --git a/patches.tizen/0025-iommu-exynos-change-rwlock-to-spinlock.patch b/patches.tizen/0025-iommu-exynos-change-rwlock-to-spinlock.patch new file mode 100644 index 00000000000..b20c902ad5c --- /dev/null +++ b/patches.tizen/0025-iommu-exynos-change-rwlock-to-spinlock.patch @@ -0,0 +1,175 @@ +From 065720fe8b38f878bfa03ec80fb2c677db36c5f6 Mon Sep 17 00:00:00 2001 +From: Cho KyongHo <pullip.cho@samsung.com> +Date: Fri, 26 Jul 2013 20:30:42 +0900 +Subject: [PATCH 0025/1302] iommu/exynos: change rwlock to spinlock + +Since acquiring read_lock is not more frequent than write_lock, it is +not beneficial to use rwlock, this commit changes rwlock to spinlock. + +Signed-off-by: Cho KyongHo <pullip.cho@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + drivers/iommu/exynos-iommu.c | 36 ++++++++++++++++++------------------ + 1 file changed, 18 insertions(+), 18 deletions(-) + +diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c +index c62c244..51e5b35 100644 +--- a/drivers/iommu/exynos-iommu.c ++++ b/drivers/iommu/exynos-iommu.c +@@ -187,7 +187,7 @@ struct sysmmu_drvdata { + struct clk *clk; + struct clk *clk_master; + int activations; +- rwlock_t lock; ++ spinlock_t lock; + struct iommu_domain *domain; + bool runtime_active; + unsigned long pgtable; +@@ -287,7 +287,7 @@ void exynos_sysmmu_set_prefbuf(struct device *dev, + BUG_ON((base0 + size0) <= base0); + BUG_ON((size1 > 0) && ((base1 + size1) <= base1)); + +- read_lock_irqsave(&data->lock, flags); ++ spin_lock_irqsave(&data->lock, flags); + if (!is_sysmmu_active(data)) + goto finish; + +@@ -319,7 +319,7 @@ void exynos_sysmmu_set_prefbuf(struct device *dev, + } + clk_disable(data->clk_master); + finish: +- read_unlock_irqrestore(&data->lock, flags); ++ spin_unlock_irqrestore(&data->lock, flags); + } + + static void show_fault_information(const char *name, +@@ -371,7 +371,7 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) + + if (client) + spin_lock(&client->lock); +- read_lock(&data->lock); ++ spin_lock(&data->lock); + + if (i == data->nsfrs) { + itype = SYSMMU_FAULT_UNKNOWN; +@@ -402,7 +402,7 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) + if (itype != SYSMMU_FAULT_UNKNOWN) + sysmmu_unblock(data->sfrbases[i]); + +- read_unlock(&data->lock); ++ spin_unlock(&data->lock); + if (client) + spin_unlock(&client->lock); + +@@ -429,7 +429,7 @@ static bool __sysmmu_disable(struct sysmmu_drvdata *data) + bool disabled; + unsigned long flags; + +- write_lock_irqsave(&data->lock, flags); ++ spin_lock_irqsave(&data->lock, flags); + + disabled = set_sysmmu_inactive(data); + +@@ -446,7 +446,7 @@ static bool __sysmmu_disable(struct sysmmu_drvdata *data) + data->activations); + } + +- write_unlock_irqrestore(&data->lock, flags); ++ spin_unlock_irqrestore(&data->lock, flags); + + return disabled; + } +@@ -493,7 +493,7 @@ static int __sysmmu_enable(struct sysmmu_drvdata *data, + int ret = 0; + unsigned long flags; + +- write_lock_irqsave(&data->lock, flags); ++ spin_lock_irqsave(&data->lock, flags); + if (set_sysmmu_active(data)) { + data->pgtable = pgtable; + data->domain = domain; +@@ -511,7 +511,7 @@ static int __sysmmu_enable(struct sysmmu_drvdata *data, + if (WARN_ON(ret < 0)) + set_sysmmu_inactive(data); /* decrement count */ + +- write_unlock_irqrestore(&data->lock, flags); ++ spin_unlock_irqrestore(&data->lock, flags); + + return ret; + } +@@ -602,7 +602,7 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, unsigned long iova) + + data = dev_get_drvdata(client->sysmmu[i]); + +- read_lock_irqsave(&data->lock, flags); ++ spin_lock_irqsave(&data->lock, flags); + if (is_sysmmu_active(data) && data->runtime_active) { + int i; + clk_enable(data->clk_master); +@@ -615,7 +615,7 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, unsigned long iova) + "disabled. Skipping TLB invalidation @ %#lx\n", + iova); + } +- read_unlock_irqrestore(&data->lock, flags); ++ spin_unlock_irqrestore(&data->lock, flags); + } + } + +@@ -630,7 +630,7 @@ void exynos_sysmmu_tlb_invalidate(struct device *dev) + + data = dev_get_drvdata(client->sysmmu[i]); + +- read_lock_irqsave(&data->lock, flags); ++ spin_lock_irqsave(&data->lock, flags); + if (is_sysmmu_active(data) && + data->runtime_active) { + int i; +@@ -646,7 +646,7 @@ void exynos_sysmmu_tlb_invalidate(struct device *dev) + } else { + dev_dbg(dev, "disabled. Skipping TLB invalidation\n"); + } +- read_unlock_irqrestore(&data->lock, flags); ++ spin_unlock_irqrestore(&data->lock, flags); + } + } + +@@ -735,7 +735,7 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev) + + data->runtime_active = !pm_runtime_enabled(dev); + +- rwlock_init(&data->lock); ++ spin_lock_init(&data->lock); + INIT_LIST_HEAD(&data->node); + + platform_set_drvdata(pdev, data); +@@ -749,11 +749,11 @@ static int sysmmu_suspend(struct device *dev) + { + struct sysmmu_drvdata *data = dev_get_drvdata(dev); + unsigned long flags; +- read_lock_irqsave(&data->lock, flags); ++ spin_lock_irqsave(&data->lock, flags); + if (is_sysmmu_active(data) && + (!pm_runtime_enabled(dev) || data->runtime_active)) + __sysmmu_disable_nocount(data); +- read_unlock_irqrestore(&data->lock, flags); ++ spin_unlock_irqrestore(&data->lock, flags); + return 0; + } + +@@ -761,11 +761,11 @@ static int sysmmu_resume(struct device *dev) + { + struct sysmmu_drvdata *data = dev_get_drvdata(dev); + unsigned long flags; +- read_lock_irqsave(&data->lock, flags); ++ spin_lock_irqsave(&data->lock, flags); + if (is_sysmmu_active(data) && + (!pm_runtime_enabled(dev) || data->runtime_active)) + __sysmmu_enable_nocount(data); +- read_unlock_irqrestore(&data->lock, flags); ++ spin_unlock_irqrestore(&data->lock, flags); + return 0; + } + #endif +-- +1.8.3.2 + diff --git a/patches.tizen/0026-iommu-exynos-return-0-if-iommu_attach_device-success.patch b/patches.tizen/0026-iommu-exynos-return-0-if-iommu_attach_device-success.patch new file mode 100644 index 00000000000..0caa0a03863 --- /dev/null +++ b/patches.tizen/0026-iommu-exynos-return-0-if-iommu_attach_device-success.patch @@ -0,0 +1,53 @@ +From 0ef8e7b01cbbbca10b0b289935a2ebac3603e948 Mon Sep 17 00:00:00 2001 +From: Cho KyongHo <pullip.cho@samsung.com> +Date: Fri, 26 Jul 2013 20:31:01 +0900 +Subject: [PATCH 0026/1302] iommu/exynos: return 0 if iommu_attach_device() + successes + +iommu_attach_device() against exynos-iommu positive integer on success +if the caller calls iommu_attach_device() with the same iommu_domain +multiple times without call to iommu_detach_device() to inform the +caller how many calls to iommu_detach_device() to really detach iommu. + +However the convention of the return value of success of common API is +zero, this patch makes iommu_attach_device() call against exynos-iommu +always return zero if the given device is successfully attached to +the given iommu_domain even though it is already attached to the same +iommu_domain. + +Signed-off-by: Cho KyongHo <pullip.cho@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + drivers/iommu/exynos-iommu.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c +index 51e5b35..6eed6d6 100644 +--- a/drivers/iommu/exynos-iommu.c ++++ b/drivers/iommu/exynos-iommu.c +@@ -882,15 +882,16 @@ static int exynos_iommu_attach_device(struct iommu_domain *domain, + + spin_unlock_irqrestore(&priv->lock, flags); + +- if (ret < 0) ++ if (ret < 0) { + dev_err(dev, "%s: Failed to attach IOMMU with pgtable %#lx\n", + __func__, __pa(priv->pgtable)); +- else +- dev_dbg(dev, "%s: Attached IOMMU with pgtable 0x%lx%s\n", +- __func__, __pa(priv->pgtable), +- (ret == 0) ? "" : ", again"); ++ return ret; ++ } + +- return ret; ++ dev_dbg(dev, "%s: Attached IOMMU with pgtable 0x%lx%s\n", ++ __func__, __pa(priv->pgtable), (ret == 0) ? "" : ", again"); ++ ++ return 0; + } + + static void exynos_iommu_detach_device(struct iommu_domain *domain, +-- +1.8.3.2 + diff --git a/patches.tizen/0027-drivers-base-add-notifier-for-failed-driver-bind.patch b/patches.tizen/0027-drivers-base-add-notifier-for-failed-driver-bind.patch new file mode 100644 index 00000000000..d7e27e2f06f --- /dev/null +++ b/patches.tizen/0027-drivers-base-add-notifier-for-failed-driver-bind.patch @@ -0,0 +1,75 @@ +From 24773097d72de6063c612ffea60b814c914df977 Mon Sep 17 00:00:00 2001 +From: Marek Szyprowski <m.szyprowski@samsung.com> +Date: Thu, 8 Aug 2013 11:05:57 +0200 +Subject: [PATCH 0027/1302] drivers: base: add notifier for failed driver bind + +Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + drivers/base/dd.c | 10 +++++++--- + include/linux/device.h | 4 +++- + 2 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/drivers/base/dd.c b/drivers/base/dd.c +index 35fa368..2c8a0d6 100644 +--- a/drivers/base/dd.c ++++ b/drivers/base/dd.c +@@ -224,10 +224,14 @@ static int driver_sysfs_add(struct device *dev) + return ret; + } + +-static void driver_sysfs_remove(struct device *dev) ++static void driver_sysfs_remove(struct device *dev, int failed) + { + struct device_driver *drv = dev->driver; + ++ if (failed && dev->bus) ++ blocking_notifier_call_chain(&dev->bus->p->bus_notifier, ++ BUS_NOTIFY_BIND_FAILED, dev); ++ + if (drv) { + sysfs_remove_link(&drv->p->kobj, kobject_name(&dev->kobj)); + sysfs_remove_link(&dev->kobj, "driver"); +@@ -302,7 +306,7 @@ static int really_probe(struct device *dev, struct device_driver *drv) + + probe_failed: + devres_release_all(dev); +- driver_sysfs_remove(dev); ++ driver_sysfs_remove(dev, true); + dev->driver = NULL; + dev_set_drvdata(dev, NULL); + +@@ -492,7 +496,7 @@ static void __device_release_driver(struct device *dev) + if (drv) { + pm_runtime_get_sync(dev); + +- driver_sysfs_remove(dev); ++ driver_sysfs_remove(dev, false); + + if (dev->bus) + blocking_notifier_call_chain(&dev->bus->p->bus_notifier, +diff --git a/include/linux/device.h b/include/linux/device.h +index c0a1261..1ce409f 100644 +--- a/include/linux/device.h ++++ b/include/linux/device.h +@@ -161,7 +161,7 @@ extern int bus_register_notifier(struct bus_type *bus, + extern int bus_unregister_notifier(struct bus_type *bus, + struct notifier_block *nb); + +-/* All 4 notifers below get called with the target struct device * ++/* All 7 notifers below get called with the target struct device * + * as an argument. Note that those functions are likely to be called + * with the device lock held in the core, so be careful. + */ +@@ -174,6 +174,8 @@ extern int bus_unregister_notifier(struct bus_type *bus, + unbound */ + #define BUS_NOTIFY_UNBOUND_DRIVER 0x00000006 /* driver is unbound + from the device */ ++#define BUS_NOTIFY_BIND_FAILED 0x00000007 /* driver failed to bind ++ to device */ + + extern struct kset *bus_get_kset(struct bus_type *bus); + extern struct klist *bus_get_device_klist(struct bus_type *bus); +-- +1.8.3.2 + diff --git a/patches.tizen/0028-ARM-dts-Add-dts-for-exynos4412-slp_pq-board.patch b/patches.tizen/0028-ARM-dts-Add-dts-for-exynos4412-slp_pq-board.patch new file mode 100644 index 00000000000..871d8c8e4ba --- /dev/null +++ b/patches.tizen/0028-ARM-dts-Add-dts-for-exynos4412-slp_pq-board.patch @@ -0,0 +1,497 @@ +From df8f759acbf72ed37f298a113bfd77825630e5f7 Mon Sep 17 00:00:00 2001 +From: Tomasz Figa <t.figa@samsung.com> +Date: Tue, 11 Sep 2012 14:27:22 +0200 +Subject: [PATCH 0028/1302] ARM: dts: Add dts for exynos4412-slp_pq board + +Signed-off-by: Tomasz Figa <t.figa@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/exynos4412-slp_pq.dts | 463 ++++++++++++++++++++++++++++++++ + 2 files changed, 464 insertions(+) + create mode 100644 arch/arm/boot/dts/exynos4412-slp_pq.dts + +diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +index f0895c5..ecdfe00 100644 +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -52,6 +52,7 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \ + exynos4210-universal_c210.dtb \ + exynos4412-odroidx.dtb \ + exynos4412-smdk4412.dtb \ ++ exynos4412-slp_pq.dtb \ + exynos4412-origen.dtb \ + exynos5250-arndale.dtb \ + exynos5440-sd5v1.dtb \ +diff --git a/arch/arm/boot/dts/exynos4412-slp_pq.dts b/arch/arm/boot/dts/exynos4412-slp_pq.dts +new file mode 100644 +index 0000000..8d9d2fb +--- /dev/null ++++ b/arch/arm/boot/dts/exynos4412-slp_pq.dts +@@ -0,0 +1,463 @@ ++/* ++ * Samsung's Exynos4412 based SLP PQ board device tree source ++ * ++ * Copyright (c) 2012 Samsung Electronics Co., Ltd. ++ * http://www.samsung.com ++ * ++ * Device tree source file for Samsung's SLP PQ board which is based on ++ * Samsung's Exynos4412 SoC. ++ * ++ * 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. ++*/ ++ ++/dts-v1/; ++/include/ "exynos4412.dtsi" ++ ++/ { ++ model = "Samsung SLP PQ based on Exynos4412"; ++ compatible = "samsung,slp_pq", "samsung,exynos4412"; ++ ++ memory { ++ reg = <0x40000000 0x10000000 ++ 0x50000000 0x10000000 ++ 0x60000000 0x10000000 ++ 0x70000000 0x10000000>; ++ }; ++ ++ chosen { ++ bootargs = "console=ttySAC2,115200N8 root=/dev/mmcblk0p5 rootwait earlyprintk panic=5"; ++ }; ++ ++ firmware@0204F000 { ++ compatible = "samsung,secure-firmware"; ++ reg = <0x0204F000 0x1000>; ++ }; ++ ++ vemmc_reg: voltage-regulator@0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VMEM_VDD_2.8V"; ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <2800000>; ++ gpio = <&gpk0 2 0>; ++ enable-active-high; ++ }; ++ ++ sdhci_emmc: sdhci@12510000 { ++ bus-width = <8>; ++ non-removable; ++ pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus8>; ++ pinctrl-names = "default"; ++ vmmc-supply = <&vemmc_reg>; ++ status = "okay"; ++ }; ++ ++ serial@13800000 { ++ status = "okay"; ++ }; ++ ++ serial@13810000 { ++ status = "okay"; ++ }; ++ ++ serial@13820000 { ++ status = "okay"; ++ }; ++ ++ serial@13830000 { ++ status = "okay"; ++ }; ++ ++ gpio-keys@0 { ++ compatible = "gpio-keys"; ++ ++ key@114 { ++ interrupt-parent = <&gpj1>; ++ interrupts = <2 0>; ++ gpios = <&gpj1 2 1>; ++ linux,code = <114>; ++ label = "volume down"; ++ debounce-interval = <10>; ++ }; ++ ++ key@115 { ++ interrupt-parent = <&gpj1>; ++ interrupts = <1 0>; ++ gpios = <&gpj1 1 1>; ++ linux,code = <115>; ++ label = "volume up"; ++ debounce-interval = <10>; ++ }; ++ ++ key@116 { ++ interrupt-parent = <&gpx2>; ++ interrupts = <7 0>; ++ gpios = <&gpx2 7 1>; ++ linux,code = <116>; ++ label = "power"; ++ debounce-interval = <10>; ++ gpio-key,wakeup; ++ }; ++ }; ++ ++ i2c@13890000 { ++ samsung,i2c-sda-delay = <100>; ++ samsung,i2c-slave-addr = <0x10>; ++ samsung,i2c-max-bus-freq = <400000>; ++ pinctrl-0 = <&i2c3_bus>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ mms114-touchscreen@48 { ++ compatible = "melfas,mms114"; ++ reg = <0x48>; ++ interrupt-parent = <&gpm2>; ++ interrupts = <3 2>; ++ x-size = <720>; ++ y-size = <1280>; ++ avdd-supply = <&ldo23_reg>; ++ vdd-supply = <&ldo24_reg>; ++ }; ++ }; ++ ++ i2c@138D0000 { ++ samsung,i2c-sda-delay = <100>; ++ samsung,i2c-slave-addr = <0x10>; ++ samsung,i2c-max-bus-freq = <100000>; ++ pinctrl-0 = <&i2c7_bus>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ max77686_pmic@09 { ++ compatible = "maxim,max77686"; ++ interrupt-parent = <&gpx0>; ++ interrupts = <7 0>; ++ reg = <0x09>; ++ ++ voltage-regulators { ++ ldo1_reg: ldo@1 { ++ regulator-compatible = "LDO1"; ++ regulator-name = "VALIVE_1.0V_AP"; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ regulator-always-on; ++ }; ++ ++ ldo2_reg: ldo@2 { ++ regulator-compatible = "LDO2"; ++ regulator-name = "VM1M2_1.2V_AP"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ regulator-always-on; ++ }; ++ ++ ldo3_reg: ldo@3 { ++ regulator-compatible = "LDO3"; ++ regulator-name = "VCC_1.8V_AP"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ }; ++ ++ ldo4_reg: ldo@4 { ++ regulator-compatible = "LDO4"; ++ regulator-name = "VCC_2.8V_AP"; ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <2800000>; ++ regulator-always-on; ++ }; ++ ++ ldo5_reg: ldo@5 { ++ regulator-compatible = "LDO5"; ++ regulator-name = "VCC_1.8V_IO"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ }; ++ ++ ldo6_reg: ldo@6 { ++ regulator-compatible = "LDO6"; ++ regulator-name = "VMPLL_1.0V_AP"; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ regulator-always-on; ++ }; ++ ++ ldo7_reg: ldo@7 { ++ regulator-compatible = "LDO7"; ++ regulator-name = "VPLL_1.0V_AP"; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ regulator-always-on; ++ }; ++ ++ ldo8_reg: ldo@8 { ++ regulator-compatible = "LDO8"; ++ regulator-name = "VMIPI_1.0V"; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ }; ++ ++ ldo9_reg: ldo@9 { ++ regulator-compatible = "LDO9"; ++ regulator-name = "CAM_ISP_MIPI_1.2V"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ }; ++ ++ ldo10_reg: ldo@10 { ++ regulator-compatible = "LDO10"; ++ regulator-name = "VMIPI_1.8V"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++ ++ ldo11_reg: ldo@11 { ++ regulator-compatible = "LDO11"; ++ regulator-name = "VABB1_1.95V"; ++ regulator-min-microvolt = <1950000>; ++ regulator-max-microvolt = <1950000>; ++ regulator-always-on; ++ }; ++ ++ ldo12_reg: ldo@12 { ++ regulator-compatible = "LDO12"; ++ regulator-name = "VUOTG_3.0V"; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; ++ }; ++ ++ ldo13_reg: ldo@13 { ++ regulator-compatible = "LDO13"; ++ regulator-name = "NFC_AVDD_1.8V"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++ ++ ldo14_reg: ldo@14 { ++ regulator-compatible = "LDO14"; ++ regulator-name = "VABB2_1.95V"; ++ regulator-min-microvolt = <1950000>; ++ regulator-max-microvolt = <1950000>; ++ regulator-always-on; ++ }; ++ ++ ldo15_reg: ldo@15 { ++ regulator-compatible = "LDO15"; ++ regulator-name = "VHSIC_1.0V"; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ }; ++ ++ ldo16_reg: ldo@16 { ++ regulator-compatible = "LDO16"; ++ regulator-name = "VHSIC_1.8V"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++ ++ ldo17_reg: ldo@17 { ++ regulator-compatible = "LDO17"; ++ regulator-name = "CAM_SENSOR_CORE_1.2V"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ }; ++ ++ ldo18_reg: ldo@18 { ++ regulator-compatible = "LDO18"; ++ regulator-name = "CAM_ISP_SEN_IO_1.8V"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++ ++ ldo19_reg: ldo@19 { ++ regulator-compatible = "LDO19"; ++ regulator-name = "VT_CAM_1.8V"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++ ++ ldo20_reg: ldo@20 { ++ regulator-compatible = "LDO20"; ++ regulator-name = "VDDQ_PRE_1.8V"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++ ++ ldo21_reg: ldo@21 { ++ regulator-compatible = "LDO21"; ++ regulator-name = "VTF_2.8V"; ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <2800000>; ++ }; ++ ++ ldo22_reg: ldo@22 { ++ regulator-compatible = "LDO22"; ++ regulator-name = "VMEM_VDD_2.8V"; ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <2800000>; ++ regulator-always-on; ++ }; ++ ++ ldo23_reg: ldo@23 { ++ regulator-compatible = "LDO23"; ++ regulator-name = "TSP_AVDD_3.3V"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ++ ldo24_reg: ldo@24 { ++ regulator-compatible = "LDO24"; ++ regulator-name = "TSP_VDD_1.8V"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++ ++ ldo25_reg: ldo@25 { ++ regulator-compatible = "LDO25"; ++ regulator-name = "LCD_VCC_3.3V"; ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <2800000>; ++ }; ++ ++ ldo26_reg: ldo@26 { ++ regulator-compatible = "LDO26"; ++ regulator-name = "MOTOR_VCC_3.0V"; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; ++ }; ++ ++ buck1_reg: buck@1 { ++ regulator-compatible = "BUCK1"; ++ regulator-name = "vdd_mif"; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <1100000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ buck2_reg: buck@2 { ++ regulator-compatible = "BUCK2"; ++ regulator-name = "vdd_arm"; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <1500000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ buck3_reg: buck@3 { ++ regulator-compatible = "BUCK3"; ++ regulator-name = "vdd_int"; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <1150000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ buck4_reg: buck@4 { ++ regulator-compatible = "BUCK4"; ++ regulator-name = "vdd_g3d"; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <1150000>; ++ regulator-boot-on; ++ }; ++ ++ buck5_reg: buck@5 { ++ regulator-compatible = "BUCK5"; ++ regulator-name = "VMEM_1.2V_AP"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ regulator-always-on; ++ }; ++ ++ buck6_reg: buck@6 { ++ regulator-compatible = "BUCK6"; ++ regulator-name = "VCC_SUB_1.35V"; ++ regulator-min-microvolt = <1350000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-always-on; ++ }; ++ buck7_reg: buck@7 { ++ regulator-compatible = "BUCK7"; ++ regulator-name = "VCC_SUB_2.0V"; ++ regulator-min-microvolt = <2000000>; ++ regulator-max-microvolt = <2000000>; ++ regulator-always-on; ++ }; ++ ++ buck8_reg: buck@8 { ++ regulator-compatible = "BUCK8"; ++ regulator-name = "VMEM_VDDF_3.0V"; ++ regulator-min-microvolt = <2850000>; ++ regulator-max-microvolt = <2850000>; ++ regulator-always-on; ++ }; ++ ++ buck9_reg: buck@9 { ++ regulator-compatible = "BUCK9"; ++ regulator-name = "CAM_ISP_CORE_1.2V"; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1200000>; ++ }; ++ }; ++ }; ++ }; ++ ++ lcd_vdd3_reg: voltage-regulator@1 { ++ compatible = "regulator-fixed"; ++ regulator-name = "LCD_VDD_2.2V"; ++ regulator-min-microvolt = <2200000>; ++ regulator-max-microvolt = <2200000>; ++ gpio = <&gpc0 1 0>; ++ enable-active-high; ++ }; ++ ++ fimd0_lcd: panel { ++ compatible = "s6e8ax0"; ++ reset-gpio = <&gpy4 5 0>; ++ reset-delay = <25>; ++ power-off-delay = <0>; ++ power-on-delay= <0>; ++ vdd3-supply = <&lcd_vdd3_reg>; ++ vci-supply = <&ldo25_reg>; ++ lcd-htiming = <5 5 5 720>; ++ lcd-vtiming = <1 13 2 1280>; ++ supports-mipi-panel; ++ }; ++ ++ mipi-dsim@11C80000 { ++ video-interface; ++ virtual-channel = <0>; ++ pixel-format = <7>; ++ burst-mode = <1>; ++ bus-width = <4>; ++ cmd-allow = <0xf>; ++ pms-setting = <12 250 0>; ++ pll-stable-time = <500>; ++ escape-clock = <10000000>; ++ stop-holding-count = <0x7ff>; ++ bta-timeout = <0xff>; ++ rx-timeout = <0xffff>; ++ vdd11-supply = <&ldo8_reg>; ++ vdd18-supply = <&ldo10_reg>; ++ panel-info = <&fimd0_lcd>; ++ status = "okay"; ++ }; ++ ++ fimd@11c00000 { ++ samsung,fimd-display = <&fimd0_lcd>; ++ samsung,fimd-vidout-rgb; ++ samsung,fimd-inv-vclk; ++ samsung,fimd-frame-rate = <60>; ++ samsung,default-window = <3>; ++ samsung,fimd-win-bpp = <32>; ++ status = "okay"; ++ }; ++ ++ hsotg@12480000 { ++ status = "okay"; ++ vusb_d-supply = <&ldo15_reg>; ++ vusb_a-supply = <&ldo12_reg>; ++ }; ++}; +-- +1.8.3.2 + diff --git a/patches.tizen/0029-ARM-dts-exynos4210-trats-Add-node-for-USB-gadget.patch b/patches.tizen/0029-ARM-dts-exynos4210-trats-Add-node-for-USB-gadget.patch new file mode 100644 index 00000000000..7d6f8161a99 --- /dev/null +++ b/patches.tizen/0029-ARM-dts-exynos4210-trats-Add-node-for-USB-gadget.patch @@ -0,0 +1,31 @@ +From 68497a23742fedc0dd4b05df6a7d60c7464aec01 Mon Sep 17 00:00:00 2001 +From: Tomasz Figa <t.figa@samsung.com> +Date: Thu, 4 Oct 2012 12:11:55 +0200 +Subject: [PATCH 0029/1302] ARM: dts: exynos4210-trats: Add node for USB gadget + +Signed-off-by: Tomasz Figa <t.figa@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4210-trats.dts | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts +index 9a14484..ce729c7 100644 +--- a/arch/arm/boot/dts/exynos4210-trats.dts ++++ b/arch/arm/boot/dts/exynos4210-trats.dts +@@ -290,6 +290,12 @@ + }; + }; + ++ hsotg@12480000 { ++ status = "okay"; ++ vusb_d-supply = <&vusb_reg>; ++ vusb_a-supply = <&vusbdac_reg>; ++ }; ++ + fixed-rate-clocks { + xxti { + compatible = "samsung,clock-xxti"; +-- +1.8.3.2 + diff --git a/patches.tizen/0030-ARM-dts-exynos4-Add-node-for-USB-PHY.patch b/patches.tizen/0030-ARM-dts-exynos4-Add-node-for-USB-PHY.patch new file mode 100644 index 00000000000..16711094923 --- /dev/null +++ b/patches.tizen/0030-ARM-dts-exynos4-Add-node-for-USB-PHY.patch @@ -0,0 +1,38 @@ +From 3b12494a4b8938874ae77d4d8acb5a577876d444 Mon Sep 17 00:00:00 2001 +From: Tomasz Figa <t.figa@samsung.com> +Date: Fri, 28 Dec 2012 16:44:10 +0100 +Subject: [PATCH 0030/1302] ARM: dts: exynos4: Add node for USB PHY + +Signed-off-by: Tomasz Figa <t.figa@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4.dtsi | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi +index 77ac4af..9ef9926 100644 +--- a/arch/arm/boot/dts/exynos4.dtsi ++++ b/arch/arm/boot/dts/exynos4.dtsi +@@ -351,6 +351,19 @@ + status = "disabled"; + }; + ++ usbphy@125B0000 { ++ compatible = "samsung,exynos4210-usbphy"; ++ reg = <0x125B0000 0x100>; ++ ranges; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ status = "disabled"; ++ ++ usbphy-sys { ++ reg = <0x10020704 0x8>; ++ }; ++ }; ++ + hsotg@12480000 { + compatible = "samsung,s3c-hsotg"; + reg = <0x12480000 0x20000>; +-- +1.8.3.2 + diff --git a/patches.tizen/0031-ARM-dts-exynos4-Move-usbphy-node-to-SoC-specific-dts.patch b/patches.tizen/0031-ARM-dts-exynos4-Move-usbphy-node-to-SoC-specific-dts.patch new file mode 100644 index 00000000000..076ad5f91af --- /dev/null +++ b/patches.tizen/0031-ARM-dts-exynos4-Move-usbphy-node-to-SoC-specific-dts.patch @@ -0,0 +1,92 @@ +From bd8c4646ef517e146f6c58cfc7a23962fc9b815c Mon Sep 17 00:00:00 2001 +From: Tomasz Figa <t.figa@samsung.com> +Date: Mon, 7 Jan 2013 15:52:58 +0100 +Subject: [PATCH 0031/1302] ARM: dts: exynos4: Move usbphy node to SoC-specific + dts files + +USB PHY of Exynos4210 and Exynos4x12 require different compatible +strings, making usbphy node SoC-specific. + +Signed-off-by: Tomasz Figa <t.figa@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4.dtsi | 13 ------------- + arch/arm/boot/dts/exynos4210.dtsi | 15 +++++++++++++++ + arch/arm/boot/dts/exynos4x12.dtsi | 15 +++++++++++++++ + 3 files changed, 30 insertions(+), 13 deletions(-) + +diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi +index 9ef9926..77ac4af 100644 +--- a/arch/arm/boot/dts/exynos4.dtsi ++++ b/arch/arm/boot/dts/exynos4.dtsi +@@ -351,19 +351,6 @@ + status = "disabled"; + }; + +- usbphy@125B0000 { +- compatible = "samsung,exynos4210-usbphy"; +- reg = <0x125B0000 0x100>; +- ranges; +- #address-cells = <1>; +- #size-cells = <1>; +- status = "disabled"; +- +- usbphy-sys { +- reg = <0x10020704 0x8>; +- }; +- }; +- + hsotg@12480000 { + compatible = "samsung,s3c-hsotg"; + reg = <0x12480000 0x20000>; +diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi +index 7ab619e..501708a 100644 +--- a/arch/arm/boot/dts/exynos4210.dtsi ++++ b/arch/arm/boot/dts/exynos4210.dtsi +@@ -149,4 +149,19 @@ + samsung,power-domain = <&pd_lcd1>; + status = "ok"; + }; ++ ++ usbphy@125B0000 { ++ compatible = "samsung,exynos4210-usb2phy"; ++ reg = <0x125B0000 0x100>; ++ ranges; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ clocks = <&clock 305>; ++ clock-names = "otg"; ++ status = "disabled"; ++ ++ usbphy-sys { ++ reg = <0x10020704 0x8>; ++ }; ++ }; + }; +diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi +index 3bf2d09..6aca431 100644 +--- a/arch/arm/boot/dts/exynos4x12.dtsi ++++ b/arch/arm/boot/dts/exynos4x12.dtsi +@@ -159,4 +159,19 @@ + clocks = <&clock 365>; + status = "ok"; + }; ++ ++ usbphy@125B0000 { ++ compatible = "samsung,exynos4x12-usb2phy"; ++ reg = <0x125B0000 0x100>; ++ ranges; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ clocks = <&clock 305>; ++ clock-names = "otg"; ++ status = "disabled"; ++ ++ usbphy-sys { ++ reg = <0x10020704 0x8>; ++ }; ++ }; + }; +-- +1.8.3.2 + diff --git a/patches.tizen/0032-ARM-dts-exynos4210-trats-Enable-USB-PHY-node.patch b/patches.tizen/0032-ARM-dts-exynos4210-trats-Enable-USB-PHY-node.patch new file mode 100644 index 00000000000..be2e2f2bdbf --- /dev/null +++ b/patches.tizen/0032-ARM-dts-exynos4210-trats-Enable-USB-PHY-node.patch @@ -0,0 +1,29 @@ +From e7f5f027bc00faa267d4cf315b0f18bf4f0e5f34 Mon Sep 17 00:00:00 2001 +From: Tomasz Figa <t.figa@samsung.com> +Date: Fri, 28 Dec 2012 16:44:39 +0100 +Subject: [PATCH 0032/1302] ARM: dts: exynos4210-trats: Enable USB PHY node + +Signed-off-by: Tomasz Figa <t.figa@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4210-trats.dts | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts +index ce729c7..a413897 100644 +--- a/arch/arm/boot/dts/exynos4210-trats.dts ++++ b/arch/arm/boot/dts/exynos4210-trats.dts +@@ -290,6 +290,10 @@ + }; + }; + ++ usbphy@125B0000 { ++ status = "okay"; ++ }; ++ + hsotg@12480000 { + status = "okay"; + vusb_d-supply = <&vusb_reg>; +-- +1.8.3.2 + diff --git a/patches.tizen/0033-ARM-dts-exynos4412-slp_pq-Enable-USB-PHY-node.patch b/patches.tizen/0033-ARM-dts-exynos4412-slp_pq-Enable-USB-PHY-node.patch new file mode 100644 index 00000000000..0161d3c3e21 --- /dev/null +++ b/patches.tizen/0033-ARM-dts-exynos4412-slp_pq-Enable-USB-PHY-node.patch @@ -0,0 +1,29 @@ +From dbfa49a283a249931538719422911eebe82b6c4e Mon Sep 17 00:00:00 2001 +From: Tomasz Figa <t.figa@samsung.com> +Date: Fri, 28 Dec 2012 16:44:57 +0100 +Subject: [PATCH 0033/1302] ARM: dts: exynos4412-slp_pq: Enable USB PHY node + +Signed-off-by: Tomasz Figa <t.figa@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4412-slp_pq.dts | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/arm/boot/dts/exynos4412-slp_pq.dts b/arch/arm/boot/dts/exynos4412-slp_pq.dts +index 8d9d2fb..bd34a51 100644 +--- a/arch/arm/boot/dts/exynos4412-slp_pq.dts ++++ b/arch/arm/boot/dts/exynos4412-slp_pq.dts +@@ -455,6 +455,10 @@ + status = "okay"; + }; + ++ usbphy@125B0000 { ++ status = "okay"; ++ }; ++ + hsotg@12480000 { + status = "okay"; + vusb_d-supply = <&ldo15_reg>; +-- +1.8.3.2 + diff --git a/patches.tizen/0034-ARM-dts-exynos4210-trats-Add-display-support-on-Trat.patch b/patches.tizen/0034-ARM-dts-exynos4210-trats-Add-display-support-on-Trat.patch new file mode 100644 index 00000000000..6ba02c4222a --- /dev/null +++ b/patches.tizen/0034-ARM-dts-exynos4210-trats-Add-display-support-on-Trat.patch @@ -0,0 +1,74 @@ +From 128e292dc4439c5584af2479841157a985d0c2e7 Mon Sep 17 00:00:00 2001 +From: Tomasz Figa <t.figa@samsung.com> +Date: Fri, 31 Aug 2012 12:32:35 +0200 +Subject: [PATCH 0034/1302] ARM: dts: exynos4210-trats: Add display support on + Trats + +This commit adds nodes and attributes necessary to enable support of +MIPI DSIM, LCD and FIMD on Trats board. + +Signed-off-by: Tomasz Figa <t.figa@samsung.com> + +Conflicts: + arch/arm/boot/dts/exynos4210-trats.dts + +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4210-trats.dts | 43 ++++++++++++++++++++++++++++++++++ + 1 file changed, 43 insertions(+) + +diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts +index a413897..39fcc8a 100644 +--- a/arch/arm/boot/dts/exynos4210-trats.dts ++++ b/arch/arm/boot/dts/exynos4210-trats.dts +@@ -311,4 +311,47 @@ + clock-frequency = <24000000>; + }; + }; ++ ++ fimd0_lcd: panel { ++ compatible = "s6e8ax0"; ++ panel-reverse; ++ reset-gpio = <&gpy4 5 0>; ++ reset-delay = <25>; ++ power-off-delay = <0>; ++ power-on-delay= <0>; ++ vdd3-supply = <&vcclcd_reg>; ++ vci-supply = <&vlcd_reg>; ++ lcd-htiming = <5 5 5 720>; ++ lcd-vtiming = <1 13 2 1280>; ++ supports-mipi-panel; ++ }; ++ ++ mipi-dsim@11C80000 { ++ video-interface; ++ virtual-channel = <0>; ++ pixel-format = <7>; ++ burst-mode = <1>; ++ bus-width = <4>; ++ cmd-allow = <0xf>; ++ pms-setting = <12 250 0>; ++ pll-stable-time = <500>; ++ escape-clock = <10000000>; ++ stop-holding-count = <0x7ff>; ++ bta-timeout = <0xff>; ++ rx-timeout = <0xffff>; ++ vdd11-supply = <&vusb_reg>; ++ vdd18-supply = <&vmipi_reg>; ++ panel-info = <&fimd0_lcd>; ++ status = "okay"; ++ }; ++ ++ fimd@11c00000 { ++ samsung,fimd-display = <&fimd0_lcd>; ++ samsung,fimd-vidout-rgb; ++ samsung,fimd-inv-vclk; ++ samsung,fimd-frame-rate = <60>; ++ samsung,default-window = <3>; ++ samsung,fimd-win-bpp = <32>; ++ status = "okay"; ++ }; + }; +-- +1.8.3.2 + diff --git a/patches.tizen/0035-ARM-dts-exynos4210-trats-Fix-vdd_arm-regulator-name.patch b/patches.tizen/0035-ARM-dts-exynos4210-trats-Fix-vdd_arm-regulator-name.patch new file mode 100644 index 00000000000..aa3362a8fbb --- /dev/null +++ b/patches.tizen/0035-ARM-dts-exynos4210-trats-Fix-vdd_arm-regulator-name.patch @@ -0,0 +1,28 @@ +From 98d6d2ec0a2217c908e92b8440793b61fcd3ce55 Mon Sep 17 00:00:00 2001 +From: Tomasz Figa <t.figa@samsung.com> +Date: Thu, 3 Jan 2013 17:53:55 +0100 +Subject: [PATCH 0035/1302] ARM: dts: exynos4210-trats: Fix vdd_arm regulator + name + +Signed-off-by: Tomasz Figa <t.figa@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4210-trats.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts +index 39fcc8a..c49ec79 100644 +--- a/arch/arm/boot/dts/exynos4210-trats.dts ++++ b/arch/arm/boot/dts/exynos4210-trats.dts +@@ -244,7 +244,7 @@ + }; + + varm_breg: BUCK1 { +- regulator-name = "VARM_1.2V_C210"; ++ regulator-name = "vdd_arm"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; +-- +1.8.3.2 + diff --git a/patches.tizen/0036-drm-exynos-fimd-clear-channel-before-enabling-iommu.patch b/patches.tizen/0036-drm-exynos-fimd-clear-channel-before-enabling-iommu.patch new file mode 100644 index 00000000000..bb2c47274d6 --- /dev/null +++ b/patches.tizen/0036-drm-exynos-fimd-clear-channel-before-enabling-iommu.patch @@ -0,0 +1,72 @@ +From 3d8e597cc926df5641751736edc3f0d9d21e1eba Mon Sep 17 00:00:00 2001 +From: Akshu Agrawal <akshu.a@samsung.com> +Date: Wed, 26 Dec 2012 06:27:41 -0500 +Subject: [PATCH 0036/1302] drm/exynos: fimd: clear channel before enabling + iommu + +If any fimd channel was already active, initializing iommu will result +in a PAGE FAULT (e.g. u-boot could have turned on the display and +not disabled it before the kernel starts). This patch checks if any +channel is active before initializing iommu and disables it. + +Signed-off-by: Akshu Agrawal <akshu.a@samsung.com> +Signed-off-by: Prathyush K <prathyush.k@samsung.com> +Signed-off-by: Inki Dae <inki.dae@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + drivers/gpu/drm/exynos/exynos_drm_fimd.c | 31 +++++++++++++++++++++++++++++-- + 1 file changed, 29 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c +index 97c61db..8ffbe2d 100644 +--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c ++++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c +@@ -695,6 +695,28 @@ out: + return IRQ_HANDLED; + } + ++static void fimd_clear_channel(struct device *dev) ++{ ++ struct fimd_context *ctx = get_fimd_context(dev); ++ int win, ch_enabled = 0; ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ /* Check if any channel is enabled */ ++ for (win = 0; win < WINDOWS_NR; win++) { ++ u32 val = readl(ctx->regs + SHADOWCON); ++ if (val & SHADOWCON_CHx_ENABLE(win)) { ++ val &= ~SHADOWCON_CHx_ENABLE(win); ++ writel(val, ctx->regs + SHADOWCON); ++ ch_enabled = 1; ++ } ++ } ++ ++ /* Wait for vsync, as disable channel takes effect at next vsync */ ++ if (ch_enabled) ++ fimd_wait_for_vblank(dev); ++} ++ + static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev) + { + DRM_DEBUG_KMS("%s\n", __FILE__); +@@ -717,9 +739,14 @@ static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev) + drm_dev->vblank_disable_allowed = 1; + + /* attach this sub driver to iommu mapping if supported. */ +- if (is_drm_iommu_supported(drm_dev)) ++ if (is_drm_iommu_supported(drm_dev)) { ++ /* ++ * If any channel is already active, iommu will throw ++ * a PAGE FAULT when enabled. So clear any channel if enabled. ++ */ ++ fimd_clear_channel(dev); + drm_iommu_attach_device(drm_dev, dev); +- ++ } + return 0; + } + +-- +1.8.3.2 + diff --git a/patches.tizen/0037-ARM-EXYNOS-add-ARM_HAS_SG_CHAIN-config.patch b/patches.tizen/0037-ARM-EXYNOS-add-ARM_HAS_SG_CHAIN-config.patch new file mode 100644 index 00000000000..c34dccb8e3e --- /dev/null +++ b/patches.tizen/0037-ARM-EXYNOS-add-ARM_HAS_SG_CHAIN-config.patch @@ -0,0 +1,26 @@ +From a0a270f57148a54699e09241278a211397909862 Mon Sep 17 00:00:00 2001 +From: Inki Dae <inki.dae@samsung.com> +Date: Thu, 3 Jan 2013 14:00:30 +0900 +Subject: [PATCH 0037/1302] ARM: EXYNOS: add ARM_HAS_SG_CHAIN config + +Signed-off-by: Inki Dae <inki.dae@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/plat-samsung/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig +index f8ed2de..a072524 100644 +--- a/arch/arm/plat-samsung/Kconfig ++++ b/arch/arm/plat-samsung/Kconfig +@@ -22,6 +22,7 @@ config PLAT_S5P + select ARM_VIC if !ARCH_EXYNOS + select GIC_NON_BANKED if ARCH_EXYNOS4 + select NO_IOPORT ++ select ARM_HAS_SG_CHAIN + select PLAT_SAMSUNG + select S3C_GPIO_TRACK + select S5P_GPIO_DRVSTR +-- +1.8.3.2 + diff --git a/patches.tizen/0038-ARM-EXYNOS-select-ARM_DMA_USE_IOMMU-for-MACH_EXYNOS4.patch b/patches.tizen/0038-ARM-EXYNOS-select-ARM_DMA_USE_IOMMU-for-MACH_EXYNOS4.patch new file mode 100644 index 00000000000..efc6cafdbe2 --- /dev/null +++ b/patches.tizen/0038-ARM-EXYNOS-select-ARM_DMA_USE_IOMMU-for-MACH_EXYNOS4.patch @@ -0,0 +1,31 @@ +From 98aa4c80a62ac52748d81a6457e5ae0fa1e256b1 Mon Sep 17 00:00:00 2001 +From: Inki Dae <inki.dae@samsung.com> +Date: Thu, 3 Jan 2013 19:01:41 +0900 +Subject: [PATCH 0038/1302] ARM: EXYNOS: select ARM_DMA_USE_IOMMU for + MACH_EXYNOS4_DT + +if EXYNOS_IOMMU is enabled then ARM_DMA_USE_IOMMU +will be enabled also. + +Signed-off-by: Inki Dae <inki.dae@samsung.com> +Signed-off-by: Tomasz Figa <t.figa@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/mach-exynos/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig +index ff18fc2..0020f87 100644 +--- a/arch/arm/mach-exynos/Kconfig ++++ b/arch/arm/mach-exynos/Kconfig +@@ -417,6 +417,7 @@ config MACH_EXYNOS4_DT + select PINCTRL_EXYNOS + select S5P_DEV_MFC + select USE_OF ++ select ARM_DMA_USE_IOMMU if EXYNOS_IOMMU + help + Machine support for Samsung Exynos4 machine with device tree enabled. + Select this if a fdt blob is available for the Exynos4 SoC based board. +-- +1.8.3.2 + diff --git a/patches.tizen/0039-ARM-dts-exynos4412-slp_pq-add-fimd-iommu-support.patch b/patches.tizen/0039-ARM-dts-exynos4412-slp_pq-add-fimd-iommu-support.patch new file mode 100644 index 00000000000..0c0e83ea806 --- /dev/null +++ b/patches.tizen/0039-ARM-dts-exynos4412-slp_pq-add-fimd-iommu-support.patch @@ -0,0 +1,29 @@ +From 6eb924c0471b1709f33496cf76c632132cec33f2 Mon Sep 17 00:00:00 2001 +From: Inki Dae <inki.dae@samsung.com> +Date: Thu, 3 Jan 2013 19:03:19 +0900 +Subject: [PATCH 0039/1302] ARM: dts: exynos4412-slp_pq: add fimd iommu support + +Signed-off-by: Inki Dae <inki.dae@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4412-slp_pq.dts | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/arm/boot/dts/exynos4412-slp_pq.dts b/arch/arm/boot/dts/exynos4412-slp_pq.dts +index bd34a51..d506149 100644 +--- a/arch/arm/boot/dts/exynos4412-slp_pq.dts ++++ b/arch/arm/boot/dts/exynos4412-slp_pq.dts +@@ -455,6 +455,10 @@ + status = "okay"; + }; + ++ sysmmu-fimd0 { ++ mmu-master = <&fimd>; ++ }; ++ + usbphy@125B0000 { + status = "okay"; + }; +-- +1.8.3.2 + diff --git a/patches.tizen/0040-ARM-DTS-SLP-PQ-add-drm-virtual-display-node.patch b/patches.tizen/0040-ARM-DTS-SLP-PQ-add-drm-virtual-display-node.patch new file mode 100644 index 00000000000..55030effb3e --- /dev/null +++ b/patches.tizen/0040-ARM-DTS-SLP-PQ-add-drm-virtual-display-node.patch @@ -0,0 +1,29 @@ +From ecfb835fff3829e3fa8da3ce5f81bf800a551cf2 Mon Sep 17 00:00:00 2001 +From: Inki Dae <inki.dae@samsung.com> +Date: Fri, 4 Jan 2013 16:25:52 +0900 +Subject: [PATCH 0040/1302] ARM: DTS: SLP-PQ: add drm virtual display node. + +Signed-off-by: Inki Dae <inki.dae@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4412-slp_pq.dts | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/arm/boot/dts/exynos4412-slp_pq.dts b/arch/arm/boot/dts/exynos4412-slp_pq.dts +index d506149..fe5a458 100644 +--- a/arch/arm/boot/dts/exynos4412-slp_pq.dts ++++ b/arch/arm/boot/dts/exynos4412-slp_pq.dts +@@ -455,6 +455,10 @@ + status = "okay"; + }; + ++ vidi { ++ compatible = "samsung,exynos-drm-vidi"; ++ }; ++ + sysmmu-fimd0 { + mmu-master = <&fimd>; + }; +-- +1.8.3.2 + diff --git a/patches.tizen/0041-drm-exynos-add-dt-match-table-for-vidi-module.patch b/patches.tizen/0041-drm-exynos-add-dt-match-table-for-vidi-module.patch new file mode 100644 index 00000000000..414c33aa4f1 --- /dev/null +++ b/patches.tizen/0041-drm-exynos-add-dt-match-table-for-vidi-module.patch @@ -0,0 +1,40 @@ +From b96dacd547b581341447efd317da886856802878 Mon Sep 17 00:00:00 2001 +From: Inki Dae <inki.dae@samsung.com> +Date: Fri, 4 Jan 2013 16:27:03 +0900 +Subject: [PATCH 0041/1302] drm/exynos: add dt match table for vidi module. + +Signed-off-by: Inki Dae <inki.dae@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + drivers/gpu/drm/exynos/exynos_drm_vidi.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c +index 24376c1..c966e23 100644 +--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c ++++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c +@@ -85,6 +85,14 @@ static const char fake_edid_info[] = { + 0x00, 0x00, 0x00, 0x06 + }; + ++#ifdef CONFIG_OF ++static const struct of_device_id vidi_driver_dt_match[] = { ++ { .compatible = "samsung,exynos-drm-vidi" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, vidi_driver_dt_match); ++#endif ++ + static bool vidi_display_is_connected(struct device *dev) + { + struct vidi_context *ctx = get_vidi_context(dev); +@@ -664,5 +672,6 @@ struct platform_driver vidi_driver = { + .name = "exynos-drm-vidi", + .owner = THIS_MODULE, + .pm = &vidi_pm_ops, ++ .of_match_table = of_match_ptr(vidi_driver_dt_match), + }, + }; +-- +1.8.3.2 + diff --git a/patches.tizen/0042-ARM-dts-exynos4210-trats-Add-nodes-for-xxti-and-xusb.patch b/patches.tizen/0042-ARM-dts-exynos4210-trats-Add-nodes-for-xxti-and-xusb.patch new file mode 100644 index 00000000000..197bba1d380 --- /dev/null +++ b/patches.tizen/0042-ARM-dts-exynos4210-trats-Add-nodes-for-xxti-and-xusb.patch @@ -0,0 +1,38 @@ +From 52add51cd571f8ddb8870f0ce64e731a6452d31f Mon Sep 17 00:00:00 2001 +From: Tomasz Figa <t.figa@samsung.com> +Date: Mon, 7 Jan 2013 18:09:08 +0100 +Subject: [PATCH 0042/1302] ARM: dts: exynos4210-trats: Add nodes for xxti and + xusbxti clocks + +Signed-off-by: Tomasz Figa <t.figa@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4210-trats.dts | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts +index c49ec79..f9a57fd 100644 +--- a/arch/arm/boot/dts/exynos4210-trats.dts ++++ b/arch/arm/boot/dts/exynos4210-trats.dts +@@ -30,6 +30,18 @@ + bootargs = "console=ttySAC2,115200N8 root=/dev/mmcblk0p5 rootwait earlyprintk panic=5"; + }; + ++ fixed-rate-clocks { ++ xxti { ++ compatible = "samsung,clock-xxti", "fixed-clock"; ++ clock-frequency = <0>; ++ }; ++ ++ xusbxti { ++ compatible = "samsung,clock-xusbxti", "fixed-clock"; ++ clock-frequency = <24000000>; ++ }; ++ }; ++ + vemmc_reg: voltage-regulator@0 { + compatible = "regulator-fixed"; + regulator-name = "VMEM_VDD_2.8V"; +-- +1.8.3.2 + diff --git a/patches.tizen/0043-ARM-dts-exynos4412-slp_pq-Add-nodes-for-xxti-and-xus.patch b/patches.tizen/0043-ARM-dts-exynos4412-slp_pq-Add-nodes-for-xxti-and-xus.patch new file mode 100644 index 00000000000..30b5ce87fce --- /dev/null +++ b/patches.tizen/0043-ARM-dts-exynos4412-slp_pq-Add-nodes-for-xxti-and-xus.patch @@ -0,0 +1,38 @@ +From d1bb3d04acad2d7dd21e195603ae4e4b1b83d289 Mon Sep 17 00:00:00 2001 +From: Tomasz Figa <t.figa@samsung.com> +Date: Mon, 7 Jan 2013 18:10:22 +0100 +Subject: [PATCH 0043/1302] ARM: dts: exynos4412-slp_pq: Add nodes for xxti and + xusbxti clocks + +Signed-off-by: Tomasz Figa <t.figa@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4412-slp_pq.dts | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/arch/arm/boot/dts/exynos4412-slp_pq.dts b/arch/arm/boot/dts/exynos4412-slp_pq.dts +index fe5a458..e28bc60 100644 +--- a/arch/arm/boot/dts/exynos4412-slp_pq.dts ++++ b/arch/arm/boot/dts/exynos4412-slp_pq.dts +@@ -35,6 +35,18 @@ + reg = <0x0204F000 0x1000>; + }; + ++ fixed-rate-clocks { ++ xxti { ++ compatible = "samsung,clock-xxti", "fixed-clock"; ++ clock-frequency = <0>; ++ }; ++ ++ xusbxti { ++ compatible = "samsung,clock-xusbxti", "fixed-clock"; ++ clock-frequency = <24000000>; ++ }; ++ }; ++ + vemmc_reg: voltage-regulator@0 { + compatible = "regulator-fixed"; + regulator-name = "VMEM_VDD_2.8V"; +-- +1.8.3.2 + diff --git a/patches.tizen/0044-ARM-dts-exynos4-Add-clock-lookups-to-hsotg-node.patch b/patches.tizen/0044-ARM-dts-exynos4-Add-clock-lookups-to-hsotg-node.patch new file mode 100644 index 00000000000..e3adaa35149 --- /dev/null +++ b/patches.tizen/0044-ARM-dts-exynos4-Add-clock-lookups-to-hsotg-node.patch @@ -0,0 +1,27 @@ +From 142965e2afd8cee8efbad05a8699d686a1af9a81 Mon Sep 17 00:00:00 2001 +From: Tomasz Figa <t.figa@samsung.com> +Date: Mon, 7 Jan 2013 18:23:04 +0100 +Subject: [PATCH 0044/1302] ARM: dts: exynos4: Add clock lookups to hsotg node + +Signed-off-by: Tomasz Figa <t.figa@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4.dtsi | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi +index 77ac4af..3b09373 100644 +--- a/arch/arm/boot/dts/exynos4.dtsi ++++ b/arch/arm/boot/dts/exynos4.dtsi +@@ -355,6 +355,8 @@ + compatible = "samsung,s3c-hsotg"; + reg = <0x12480000 0x20000>; + interrupts = <0 71 0>; ++ clocks = <&clock 305>; ++ clock-names = "otg"; + status = "disabled"; + }; + +-- +1.8.3.2 + diff --git a/patches.tizen/0045-V4L-s5c73m3-Initial-device-tree-support.patch b/patches.tizen/0045-V4L-s5c73m3-Initial-device-tree-support.patch new file mode 100644 index 00000000000..431905373ef --- /dev/null +++ b/patches.tizen/0045-V4L-s5c73m3-Initial-device-tree-support.patch @@ -0,0 +1,223 @@ +From cd7aa493bbb6b0b92acca162b143eeab23ef2c85 Mon Sep 17 00:00:00 2001 +From: Sylwester Nawrocki <s.nawrocki@samsung.com> +Date: Wed, 23 Jan 2013 12:32:05 +0100 +Subject: [PATCH 0045/1302] V4L: s5c73m3: Initial device tree support + +Add OF match table for the I2C client and SPI device driver, +and GPIO handling for DT. This is minimum required to make +the driver work with DT. + +Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + drivers/media/i2c/s5c73m3/s5c73m3-core.c | 110 +++++++++++++++++++++---------- + drivers/media/i2c/s5c73m3/s5c73m3-spi.c | 6 ++ + 2 files changed, 81 insertions(+), 35 deletions(-) + +diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c +index 9eac531..e6ce92a 100644 +--- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c ++++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c +@@ -23,6 +23,7 @@ + #include <linux/init.h> + #include <linux/media.h> + #include <linux/module.h> ++#include <linux/of_gpio.h> + #include <linux/regulator/consumer.h> + #include <linux/slab.h> + #include <linux/spi/spi.h> +@@ -1511,17 +1512,28 @@ static const struct v4l2_subdev_ops oif_subdev_ops = { + .video = &s5c73m3_oif_video_ops, + }; + +-static int s5c73m3_configure_gpio(int nr, int val, const char *name) ++/* ++ * GPIO control helpers ++ */ ++static int s5c73m3_configure_gpio(struct s5c73m3_gpio *gpio, int idx, ++ const char *name, struct device_node *node) + { +- unsigned long flags = val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; +- int ret; ++ enum of_gpio_flags of_flags; ++ unsigned long flags; ++ ++ if (node) { ++ gpio->gpio = of_get_gpio_flags(node, idx, &of_flags); ++ gpio->level = !(of_flags & OF_GPIO_ACTIVE_LOW); ++ } + +- if (!gpio_is_valid(nr)) ++ if (!gpio_is_valid(gpio->gpio)) + return 0; +- ret = gpio_request_one(nr, flags, name); +- if (!ret) +- gpio_export(nr, 0); +- return ret; ++ ++ flags = gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; ++ pr_debug("gpio[%d]: %d, flags: %#lx, of_flags: %#x\n", ++ idx, gpio->gpio, flags, of_flags); ++ ++ return gpio_request_one(gpio->gpio, flags, name); + } + + static int s5c73m3_free_gpios(struct s5c73m3 *state) +@@ -1538,33 +1550,59 @@ static int s5c73m3_free_gpios(struct s5c73m3 *state) + } + + static int s5c73m3_configure_gpios(struct s5c73m3 *state, +- const struct s5c73m3_platform_data *pdata) ++ struct device *dev) + { +- const struct s5c73m3_gpio *gpio = &pdata->gpio_stby; ++ const struct s5c73m3_platform_data *pdata = dev->platform_data; ++ struct s5c73m3_gpio gpio; + int ret; + + state->gpio[STBY].gpio = -EINVAL; + state->gpio[RST].gpio = -EINVAL; + +- ret = s5c73m3_configure_gpio(gpio->gpio, gpio->level, "S5C73M3_STBY"); +- if (ret) { +- s5c73m3_free_gpios(state); +- return ret; ++ if (pdata) ++ gpio = pdata->gpio_stby; ++ else ++ gpio.gpio = -EINVAL; ++ ret = s5c73m3_configure_gpio(&gpio, STBY, "S5C73M3_STBY", ++ dev->of_node); ++ if (!ret) { ++ state->gpio[STBY] = gpio; ++ if (gpio_is_valid(gpio.gpio)) ++ gpio_set_value(gpio.gpio, 0); ++ if (pdata) ++ gpio = pdata->gpio_reset; ++ else ++ gpio.gpio = -EINVAL; ++ ret = s5c73m3_configure_gpio(&gpio, RST, "S5C73M3_RST", ++ dev->of_node); ++ if (!ret && gpio_is_valid(gpio.gpio)) ++ gpio_set_value(gpio.gpio, 0); + } +- state->gpio[STBY] = *gpio; +- if (gpio_is_valid(gpio->gpio)) +- gpio_set_value(gpio->gpio, 0); +- +- gpio = &pdata->gpio_reset; +- ret = s5c73m3_configure_gpio(gpio->gpio, gpio->level, "S5C73M3_RST"); +- if (ret) { ++ if (!ret) ++ state->gpio[RST] = gpio; ++ else + s5c73m3_free_gpios(state); +- return ret; ++ ++ return ret; ++} ++ ++static int s5c73m3_get_platform_data(struct s5c73m3 *state, struct device *dev) ++{ ++ const struct s5c73m3_platform_data *pdata = dev->platform_data; ++ struct device_node *node = dev->of_node; ++ ++ if (!node) { ++ if (!pdata) { ++ dev_err(dev, "Platform data not specified\n"); ++ return -EINVAL; ++ } ++ ++ state->mclk_frequency = pdata->mclk_frequency; ++ state->bus_type = pdata->bus_type; ++ return 0; + } +- state->gpio[RST] = *gpio; +- if (gpio_is_valid(gpio->gpio)) +- gpio_set_value(gpio->gpio, 0); + ++ of_property_read_u32(node, "clock-frequency", &state->mclk_frequency); + return 0; + } + +@@ -1572,21 +1610,19 @@ static int s5c73m3_probe(struct i2c_client *client, + const struct i2c_device_id *id) + { + struct device *dev = &client->dev; +- const struct s5c73m3_platform_data *pdata = client->dev.platform_data; + struct v4l2_subdev *sd; + struct v4l2_subdev *oif_sd; + struct s5c73m3 *state; + int ret, i; + +- if (pdata == NULL) { +- dev_err(&client->dev, "Platform data not specified\n"); +- return -EINVAL; +- } +- + state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + ++ ret = s5c73m3_get_platform_data(state, dev); ++ if (ret < 0) ++ return ret; ++ + mutex_init(&state->lock); + sd = &state->sensor_sd; + oif_sd = &state->oif_sd; +@@ -1624,10 +1660,7 @@ static int s5c73m3_probe(struct i2c_client *client, + if (ret < 0) + return ret; + +- state->mclk_frequency = pdata->mclk_frequency; +- state->bus_type = pdata->bus_type; +- +- ret = s5c73m3_configure_gpios(state, pdata); ++ ret = s5c73m3_configure_gpios(state, dev); + if (ret) + goto out_err1; + +@@ -1699,8 +1732,15 @@ static const struct i2c_device_id s5c73m3_id[] = { + }; + MODULE_DEVICE_TABLE(i2c, s5c73m3_id); + ++static const struct of_device_id s5c73m3_of_match[] = { ++ { .compatible = "samsung,s5c73m3" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, s5c73m3_of_match); ++ + static struct i2c_driver s5c73m3_i2c_driver = { + .driver = { ++ .of_match_table = s5c73m3_of_match, + .name = DRIVER_NAME, + }, + .probe = s5c73m3_probe, +diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c +index 6f3a9c0..cd1074f 100644 +--- a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c ++++ b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c +@@ -27,6 +27,11 @@ + + #define S5C73M3_SPI_DRV_NAME "S5C73M3-SPI" + ++static const struct of_device_id s5c73m3_spi_ids[] = { ++ { .compatible = "samsung,s5c73m3" }, ++ { } ++}; ++ + enum spi_direction { + SPI_DIR_RX, + SPI_DIR_TX +@@ -146,6 +151,7 @@ int s5c73m3_register_spi_driver(struct s5c73m3 *state) + spidrv->driver.name = S5C73M3_SPI_DRV_NAME; + spidrv->driver.bus = &spi_bus_type; + spidrv->driver.owner = THIS_MODULE; ++ spidrv->driver.of_match_table = s5c73m3_spi_ids; + + return spi_register_driver(spidrv); + } +-- +1.8.3.2 + diff --git a/patches.tizen/0046-s5c73m3-Disable-boot_from_rom.patch b/patches.tizen/0046-s5c73m3-Disable-boot_from_rom.patch new file mode 100644 index 00000000000..3d7522dc73c --- /dev/null +++ b/patches.tizen/0046-s5c73m3-Disable-boot_from_rom.patch @@ -0,0 +1,29 @@ +From 0f0fce93bf74031922d9a6041f86b2e8b599f3f9 Mon Sep 17 00:00:00 2001 +From: Sylwester Nawrocki <s.nawrocki@samsung.com> +Date: Wed, 23 Jan 2013 12:37:03 +0100 +Subject: [PATCH 0046/1302] s5c73m3: Disable boot_from_rom + +Boot from FROM memory is only for the mainline kernel. + +Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + drivers/media/i2c/s5c73m3/s5c73m3-core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c +index e6ce92a..77f59fa 100644 +--- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c ++++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c +@@ -40,7 +40,7 @@ + int s5c73m3_dbg; + module_param_named(debug, s5c73m3_dbg, int, 0644); + +-static int boot_from_rom = 1; ++static int boot_from_rom = 0; + module_param(boot_from_rom, int, 0644); + + static int update_fw; +-- +1.8.3.2 + diff --git a/patches.tizen/0047-ARM-dts-Add-camera-to-node-exynos4.dtsi.patch b/patches.tizen/0047-ARM-dts-Add-camera-to-node-exynos4.dtsi.patch new file mode 100644 index 00000000000..7c4ebe540d2 --- /dev/null +++ b/patches.tizen/0047-ARM-dts-Add-camera-to-node-exynos4.dtsi.patch @@ -0,0 +1,99 @@ +From 37f865b3f66b6b564f44b3c46eb7834022767cca Mon Sep 17 00:00:00 2001 +From: Sylwester Nawrocki <s.nawrocki@samsung.com> +Date: Wed, 24 Oct 2012 17:00:57 +0200 +Subject: [PATCH 0047/1302] ARM: dts: Add camera to node exynos4.dtsi + +This patch adds common FIMC device nodes for all Exynos4 SoCs. + +Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> +Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4.dtsi | 64 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 64 insertions(+) + +diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi +index 3b09373..5a3955b 100644 +--- a/arch/arm/boot/dts/exynos4.dtsi ++++ b/arch/arm/boot/dts/exynos4.dtsi +@@ -36,6 +36,12 @@ + i2c5 = &i2c_5; + i2c6 = &i2c_6; + i2c7 = &i2c_7; ++ csis0 = &csis_0; ++ csis1 = &csis_1; ++ fimc0 = &fimc_0; ++ fimc1 = &fimc_1; ++ fimc2 = &fimc_2; ++ fimc3 = &fimc_3; + }; + + chipid@10000000 { +@@ -98,6 +104,64 @@ + arm,tag-latency = <1 1 0>; + }; + ++ camera { ++ compatible = "samsung,fimc", "simple-bus"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ fimc_0: fimc@11800000 { ++ compatible = "samsung,exynos4210-fimc"; ++ reg = <0x11800000 0x1000>; ++ interrupts = <0 84 0>; ++ samsung,power-domain = <&pd_cam>; ++ status = "disabled"; ++ }; ++ ++ fimc_1: fimc@11810000 { ++ compatible = "samsung,exynos4210-fimc"; ++ reg = <0x11810000 0x1000>; ++ interrupts = <0 85 0>; ++ samsung,power-domain = <&pd_cam>; ++ status = "disabled"; ++ }; ++ ++ fimc_2: fimc@11820000 { ++ compatible = "samsung,exynos4210-fimc"; ++ reg = <0x11820000 0x1000>; ++ interrupts = <0 86 0>; ++ samsung,power-domain = <&pd_cam>; ++ status = "disabled"; ++ }; ++ ++ fimc_3: fimc@11830000 { ++ compatible = "samsung,exynos4210-fimc"; ++ reg = <0x11830000 0x1000>; ++ interrupts = <0 87 0>; ++ samsung,power-domain = <&pd_cam>; ++ status = "disabled"; ++ }; ++ ++ csis_0: csis@11880000 { ++ compatible = "samsung,exynos4210-csis"; ++ reg = <0x11880000 0x4000>; ++ interrupts = <0 78 0>; ++ bus-width = <4>; ++ samsung,power-domain = <&pd_cam>; ++ status = "disabled"; ++ }; ++ ++ csis_1: csis@11890000 { ++ compatible = "samsung,exynos4210-csis"; ++ reg = <0x11890000 0x4000>; ++ interrupts = <0 80 0>; ++ bus-width = <2>; ++ samsung,power-domain = <&pd_cam>; ++ status = "disabled"; ++ }; ++ }; ++ + watchdog@10060000 { + compatible = "samsung,s3c2410-wdt"; + reg = <0x10060000 0x100>; +-- +1.8.3.2 + diff --git a/patches.tizen/0048-ARM-dts-Add-ISP-power-domain-node-for-Exynos4x12.patch b/patches.tizen/0048-ARM-dts-Add-ISP-power-domain-node-for-Exynos4x12.patch new file mode 100644 index 00000000000..605bb799f0a --- /dev/null +++ b/patches.tizen/0048-ARM-dts-Add-ISP-power-domain-node-for-Exynos4x12.patch @@ -0,0 +1,34 @@ +From 1e881c2001e9d00c04a0cef8887d093c0027e76b Mon Sep 17 00:00:00 2001 +From: Sylwester Nawrocki <s.nawrocki@samsung.com> +Date: Mon, 10 Dec 2012 15:23:38 +0100 +Subject: [PATCH 0048/1302] ARM: dts: Add ISP power domain node for Exynos4x12 + +The ISP power domain is a common power domain for fimc-lite +and fimc-is (ISP) devices. + +Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> +Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4x12.dtsi | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi +index 6aca431..2a5ac7b 100644 +--- a/arch/arm/boot/dts/exynos4x12.dtsi ++++ b/arch/arm/boot/dts/exynos4x12.dtsi +@@ -28,6 +28,11 @@ + pinctrl3 = &pinctrl_3; + }; + ++ pd_isp: isp-power-domain@10023CA0 { ++ compatible = "samsung,exynos4210-pd"; ++ reg = <0x10023CA0 0x20>; ++ }; ++ + combiner:interrupt-controller@10440000 { + interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>, + <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>, +-- +1.8.3.2 + diff --git a/patches.tizen/0049-ARM-dts-Add-FIMC-and-MIPI-CSIS-device-nodes-for-Exyn.patch b/patches.tizen/0049-ARM-dts-Add-FIMC-and-MIPI-CSIS-device-nodes-for-Exyn.patch new file mode 100644 index 00000000000..391d528b29e --- /dev/null +++ b/patches.tizen/0049-ARM-dts-Add-FIMC-and-MIPI-CSIS-device-nodes-for-Exyn.patch @@ -0,0 +1,85 @@ +From 13abd305c654983547b8cd6a1e13641a570ddd74 Mon Sep 17 00:00:00 2001 +From: Sylwester Nawrocki <s.nawrocki@samsung.com> +Date: Mon, 7 Jan 2013 17:13:58 +0100 +Subject: [PATCH 0049/1302] ARM: dts: Add FIMC and MIPI CSIS device nodes for + Exynos4x12 + +Add common camera node and fimc nodes specific to Exynos4212 and +Exynos4412 SoCs. fimc-is is a node for the Exynos4x12 FIMC-IS +subsystem and fimc-lite nodes are created as its child nodes, +among others due to FIMC-LITE device dependencies on FIMC-IS +related clocks. + +Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> +Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4x12.dtsi | 47 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 47 insertions(+) + +diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi +index 2a5ac7b..3b4a16b 100644 +--- a/arch/arm/boot/dts/exynos4x12.dtsi ++++ b/arch/arm/boot/dts/exynos4x12.dtsi +@@ -26,6 +26,8 @@ + pinctrl1 = &pinctrl_1; + pinctrl2 = &pinctrl_2; + pinctrl3 = &pinctrl_3; ++ fimc-lite0 = &fimc_lite_0; ++ fimc-lite1 = &fimc_lite_1; + }; + + pd_isp: isp-power-domain@10023CA0 { +@@ -179,4 +181,49 @@ + reg = <0x10020704 0x8>; + }; + }; ++ ++ camera { ++ fimc_0: fimc@11800000 { ++ compatible = "samsung,exynos4212-fimc"; ++ }; ++ ++ fimc_1: fimc@11810000 { ++ compatible = "samsung,exynos4212-fimc"; ++ }; ++ ++ fimc_2: fimc@11820000 { ++ compatible = "samsung,exynos4212-fimc"; ++ }; ++ ++ fimc_3: fimc@11830000 { ++ compatible = "samsung,exynos4212-fimc"; ++ }; ++ ++ fimc_is: fimc-is@12000000 { ++ compatible = "samsung,exynos4212-fimc-is", "simple-bus"; ++ reg = <0x12000000 0x260000>; ++ interrupts = <0 90 0>, <0 95 0>; ++ samsung,power-domain = <&pd_isp>; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ fimc_lite_0: fimc-lite@12390000 { ++ compatible = "samsung,exynos4212-fimc-lite"; ++ reg = <0x12390000 0x1000>; ++ interrupts = <0 105 0>; ++ samsung,power-domain = <&pd_isp>; ++ status = "disabled"; ++ }; ++ ++ fimc_lite_1: fimc-lite@123A0000 { ++ compatible = "samsung,exynos4212-fimc-lite"; ++ reg = <0x123A0000 0x1000>; ++ interrupts = <0 106 0>; ++ samsung,power-domain = <&pd_isp>; ++ status = "disabled"; ++ }; ++ }; ++ }; + }; +-- +1.8.3.2 + diff --git a/patches.tizen/0050-ARM-dts-Correct-camera-pinctrl-nodes-for-Exynos4x12-.patch b/patches.tizen/0050-ARM-dts-Correct-camera-pinctrl-nodes-for-Exynos4x12-.patch new file mode 100644 index 00000000000..02065483a64 --- /dev/null +++ b/patches.tizen/0050-ARM-dts-Correct-camera-pinctrl-nodes-for-Exynos4x12-.patch @@ -0,0 +1,90 @@ +From ac696fa80bf5addd9bb72d7e07903f19c71dbfb0 Mon Sep 17 00:00:00 2001 +From: Sylwester Nawrocki <s.nawrocki@samsung.com> +Date: Wed, 24 Oct 2012 16:42:12 +0200 +Subject: [PATCH 0050/1302] ARM: dts: Correct camera pinctrl nodes for + Exynos4x12 SoCs + +Add separate nodes for the CAMCLK pin and turn off pull-up on camera +ports A, B. The video bus pins and the clock output (CAMCLK) pin need +separate nodes since full camera port is not used in some configurations, +e.g. for MIPI CSI-2 bus on CAMCLK is required and data/clock signal +use separate dedicated pins. + +Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> +Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4x12-pinctrl.dtsi | 40 +++++++++++++++++++++++++------ + 1 file changed, 33 insertions(+), 7 deletions(-) + +diff --git a/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi b/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi +index 099cec7..950ef30 100644 +--- a/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi ++++ b/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi +@@ -401,13 +401,26 @@ + samsung,pin-drv = <0>; + }; + +- cam_port_a: cam-port-a { ++ cam_port_a_io: cam-port-a-io { + samsung,pins = "gpj0-0", "gpj0-1", "gpj0-2", "gpj0-3", + "gpj0-4", "gpj0-5", "gpj0-6", "gpj0-7", +- "gpj1-0", "gpj1-1", "gpj1-2", "gpj1-3", +- "gpj1-4"; ++ "gpj1-0", "gpj1-1", "gpj1-2", "gpj1-4"; + samsung,pin-function = <2>; +- samsung,pin-pud = <3>; ++ samsung,pin-pud = <0>; ++ samsung,pin-drv = <0>; ++ }; ++ ++ cam_port_a_clk_active: cam-port-a-clk-active { ++ samsung,pins = "gpj1-3"; ++ samsung,pin-function = <2>; ++ samsung,pin-pud = <0>; ++ samsung,pin-drv = <3>; ++ }; ++ ++ cam_port_a_clk_idle: cam-port-a-clk-idle { ++ samsung,pins = "gpj1-3"; ++ samsung,pin-function = <0>; ++ samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + }; +@@ -834,16 +847,29 @@ + samsung,pin-drv = <0>; + }; + +- cam_port_b: cam-port-b { ++ cam_port_b_io: cam-port-b-io { + samsung,pins = "gpm0-0", "gpm0-1", "gpm0-2", "gpm0-3", + "gpm0-4", "gpm0-5", "gpm0-6", "gpm0-7", +- "gpm1-0", "gpm1-1", "gpm2-0", "gpm2-1", +- "gpm2-2"; ++ "gpm1-0", "gpm1-1", "gpm2-0", "gpm2-1"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + ++ cam_port_b_clk_active: cam-port-b-clk-active { ++ samsung,pins = "gpm2-2"; ++ samsung,pin-function = <3>; ++ samsung,pin-pud = <0>; ++ samsung,pin-drv = <3>; ++ }; ++ ++ cam_port_b_clk_idle: cam-port-b-clk-idle { ++ samsung,pins = "gpm2-2"; ++ samsung,pin-function = <0>; ++ samsung,pin-pud = <0>; ++ samsung,pin-drv = <0>; ++ }; ++ + eint0: ext-int0 { + samsung,pins = "gpx0-0"; + samsung,pin-function = <0xf>; +-- +1.8.3.2 + diff --git a/patches.tizen/0051-ARM-dts-Add-camera-device-nodes-for-PQ-board.patch b/patches.tizen/0051-ARM-dts-Add-camera-device-nodes-for-PQ-board.patch new file mode 100644 index 00000000000..fe7c638f023 --- /dev/null +++ b/patches.tizen/0051-ARM-dts-Add-camera-device-nodes-for-PQ-board.patch @@ -0,0 +1,225 @@ +From b58b47b20440051cb5351aad2f25acbce85e7e09 Mon Sep 17 00:00:00 2001 +From: Sylwester Nawrocki <s.nawrocki@samsung.com> +Date: Wed, 6 Feb 2013 18:34:42 +0100 +Subject: [PATCH 0051/1302] ARM: dts: Add camera device nodes for PQ board + +This patch adds all nodes for camera devices on an example Exynos4412 SoC +based board. This is all what's required in the board dts file to enable +rear facing camera (S5C73M3 sensor). + +The aliases node contains entries required for the camera processing +data path entity drivers. + +The sensor nodes use standard port/remote-endpoint nodes convention. +Internal SoC links between entities are not specified this way and +are coded in the driver instead. + +The S5C73M3 sensor uses two control buses: I2C and SPI. There are +two, i2c_0 and spi_1 bus controller child nodes assigned to it. + +Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> +Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4412-slp_pq.dts | 173 ++++++++++++++++++++++++++++++++ + 1 file changed, 173 insertions(+) + +diff --git a/arch/arm/boot/dts/exynos4412-slp_pq.dts b/arch/arm/boot/dts/exynos4412-slp_pq.dts +index e28bc60..fa47f9a 100644 +--- a/arch/arm/boot/dts/exynos4412-slp_pq.dts ++++ b/arch/arm/boot/dts/exynos4412-slp_pq.dts +@@ -113,6 +113,35 @@ + }; + }; + ++ i2c_0: i2c@13860000 { ++ samsung,i2c-sda-delay = <100>; ++ samsung,i2c-slave-addr = <0x10>; ++ samsung,i2c-max-bus-freq = <400000>; ++ pinctrl-0 = <&i2c0_bus>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ s5c73m3@3c { ++ compatible = "samsung,s5c73m3"; ++ reg = <0x3c>; ++ gpios = <&gpm0 1 1>, /* ISP_STANDBY */ ++ <&gpf1 3 1>; /* ISP_RESET */ ++ vdd-int-supply = <&buck9_reg>; ++ vddio-cis-supply = <&ldo9_reg>; ++ vdda-supply = <&ldo17_reg>; ++ vddio-host-supply = <&ldo18_reg>; ++ vdd-af-supply = <&cam_af_reg>; ++ vdd-reg-supply = <&cam_io_reg>; ++ clock-frequency = <24000000>; ++ ++ port { ++ s5c73m3_ep: endpoint { ++ remote-endpoint = <&csis0_ep>; ++ }; ++ }; ++ }; ++ }; ++ + i2c@13890000 { + samsung,i2c-sda-delay = <100>; + samsung,i2c-slave-addr = <0x10>; +@@ -425,6 +454,34 @@ + enable-active-high; + }; + ++ cam_af_reg: voltage-regulator@2 { ++ compatible = "regulator-fixed"; ++ regulator-name = "CAM_AF"; ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <2800000>; ++ gpio = <&gpm0 4 0>; ++ enable-active-high; ++ }; ++ ++ cam_io_reg: voltage-regulator@3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "CAM_SENSOR_A"; ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <2800000>; ++ gpio = <&gpm0 2 0>; ++ enable-active-high; ++ }; ++ ++ cam_isp_core_reg: voltage-regulator@4 { ++ compatible = "regulator-fixed"; ++ regulator-name = "CAM_ISP_CORE_1.2V_EN"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ gpio = <&gpm0 3 0>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ + fimd0_lcd: panel { + compatible = "s6e8ax0"; + reset-gpio = <&gpy4 5 0>; +@@ -484,4 +541,120 @@ + vusb_d-supply = <&ldo15_reg>; + vusb_a-supply = <&ldo12_reg>; + }; ++ ++ spi_1: spi@13930000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi1_bus>; ++ status = "okay"; ++ ++ s5c73m3_spi: s5c73m3 { ++ compatible = "samsung,s5c73m3"; ++ spi-max-frequency = <50000000>; ++ reg = <0>; ++ controller-data { ++ cs-gpio = <&gpb 5 0>; ++ samsung,spi-feedback-delay = <2>; ++ }; ++ }; ++ }; ++ ++ camera { ++ compatible = "samsung,fimc", "simple-bus"; ++ status = "okay"; ++ ++ pinctrl-names = "default", "inactive"; ++ pinctrl-0 = <&cam_port_a_clk_active>; ++ pinctrl-1 = <&cam_port_a_clk_idle>; ++ ++ fimc_0: fimc@11800000 { ++ clock-frequency = <176000000>; ++ status = "okay"; ++ }; ++ ++ fimc_1: fimc@11810000 { ++ clock-frequency = <176000000>; ++ status = "okay"; ++ }; ++ ++ fimc_2: fimc@11820000 { ++ clock-frequency = <176000000>; ++ status = "okay"; ++ }; ++ ++ fimc_3: fimc@11830000 { ++ clock-frequency = <176000000>; ++ status = "okay"; ++ }; ++ ++ csis_0: csis@11880000 { ++ status = "okay"; ++ vddcore-supply = <&ldo8_reg>; ++ vddio-supply = <&ldo10_reg>; ++ clock-frequency = <160000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* Camera C (3) MIPI CSI-2 (CSIS0) */ ++ port@3 { ++ reg = <3>; ++ csis0_ep: endpoint { ++ remote-endpoint = <&s5c73m3_ep>; ++ data-lanes = <1 2 3 4>; ++ samsung,csis-hs-settle = <12>; ++ }; ++ }; ++ }; ++ ++ csis_1: csis@11890000 { ++ status = "okay"; ++ vddcore-supply = <&ldo8_reg>; ++ vddio-supply = <&ldo10_reg>; ++ clock-frequency = <160000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* Camera D (4) MIPI CSI-2 (CSIS1) */ ++ port@4 { ++ reg = <4>; ++ csis1_ep: endpoint { ++ remote-endpoint = <&is_s5k6a3_ep>; ++ data-lanes = <1>; ++ samsung,csis-hs-settle = <18>; ++ samsung,csis-wclk; ++ }; ++ }; ++ }; ++ ++ fimc-is@12000000 { ++ status = "okay"; ++ ++ fimc_lite_0: fimc-lite@12390000 { ++ status = "okay"; ++ }; ++ ++ fimc_lite_1: fimc-lite@123A0000 { ++ status = "okay"; ++ }; ++ ++ fimc-is-i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ s5k6a3@10 { ++ compatible = "samsung,s5k6a3"; ++ reg = <0x10>; ++ svdda-supply = <&cam_io_reg>; ++ svddio-supply = <&ldo19_reg>; ++ clock-frequency = <24000000>; ++ gpios = <&gpm1 6 0>; ++ port { ++ is_s5k6a3_ep: endpoint { ++ remote-endpoint = <&csis1_ep>; ++ data-lanes = <1>; ++ }; ++ }; ++ }; ++ }; ++ }; ++ }; + }; +-- +1.8.3.2 + diff --git a/patches.tizen/0052-ARM-EXYNOS-change-the-value-of-EXYNOS4X12_ISP_LOWPWR.patch b/patches.tizen/0052-ARM-EXYNOS-change-the-value-of-EXYNOS4X12_ISP_LOWPWR.patch new file mode 100644 index 00000000000..c45beddeb57 --- /dev/null +++ b/patches.tizen/0052-ARM-EXYNOS-change-the-value-of-EXYNOS4X12_ISP_LOWPWR.patch @@ -0,0 +1,34 @@ +From 143103659b069afb92881584f7f3d777a6d8ee6a Mon Sep 17 00:00:00 2001 +From: Younghwan Joo <yhwan.joo@samsung.com> +Date: Thu, 15 Nov 2012 21:02:27 +0900 +Subject: [PATCH 0052/1302] ARM: EXYNOS: change the value of + EXYNOS4X12_ISP_LOWPWR + +This patch is to fix the value of EXYNOS4X12_ISP_LOWPWR register +to zero at AFTR mode. It ensure the sub selection mux of mcuisp400 +and isp200 reset a default position after power down + +Signed-off-by: Younghwan Joo <yhwan.joo@samsung.com> +Signed-off-by: JaeYong Shin <jy2.shin@samsung.com> +Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/mach-exynos/pmu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/mach-exynos/pmu.c b/arch/arm/mach-exynos/pmu.c +index 97d6885..21cef18 100644 +--- a/arch/arm/mach-exynos/pmu.c ++++ b/arch/arm/mach-exynos/pmu.c +@@ -140,7 +140,7 @@ static struct exynos_pmu_conf exynos4x12_pmu_config[] = { + { S5P_CMU_RESET_MFC_LOWPWR, { 0x1, 0x0, 0x0 } }, + { S5P_CMU_RESET_G3D_LOWPWR, { 0x1, 0x0, 0x0 } }, + { S5P_CMU_RESET_LCD0_LOWPWR, { 0x1, 0x0, 0x0 } }, +- { S5P_CMU_RESET_ISP_LOWPWR, { 0x1, 0x0, 0x0 } }, ++ { S5P_CMU_RESET_ISP_LOWPWR, { 0x0, 0x0, 0x0 } }, + { S5P_CMU_RESET_MAUDIO_LOWPWR, { 0x1, 0x1, 0x0 } }, + { S5P_CMU_RESET_GPS_LOWPWR, { 0x1, 0x0, 0x0 } }, + { S5P_TOP_BUS_LOWPWR, { 0x3, 0x0, 0x0 } }, +-- +1.8.3.2 + diff --git a/patches.tizen/0053-ARM-dts-Add-pinctrl-entries-for-FIMC-IS-peripherals.patch b/patches.tizen/0053-ARM-dts-Add-pinctrl-entries-for-FIMC-IS-peripherals.patch new file mode 100644 index 00000000000..77710f7e64c --- /dev/null +++ b/patches.tizen/0053-ARM-dts-Add-pinctrl-entries-for-FIMC-IS-peripherals.patch @@ -0,0 +1,47 @@ +From 67f415c5868ecfb99ced79a4805cb9cc07c2ce3a Mon Sep 17 00:00:00 2001 +From: Sylwester Nawrocki <s.nawrocki@samsung.com> +Date: Mon, 7 Jan 2013 20:27:53 +0100 +Subject: [PATCH 0053/1302] ARM: dts: Add pinctrl entries for FIMC-IS + peripherals + +Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4x12-pinctrl.dtsi | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi b/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi +index 950ef30..b4919a6 100644 +--- a/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi ++++ b/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi +@@ -904,6 +904,27 @@ + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; ++ ++ fimc_is_i2c0: fimc-is-i2c0 { ++ samsung,pins = "gpm4-0", "gpm4-1"; ++ samsung,pin-function = <2>; ++ samsung,pin-pud = <0>; ++ samsung,pin-drv = <0>; ++ }; ++ ++ fimc_is_i2c1: fimc-is-i2c1 { ++ samsung,pins = "gpm4-2", "gpm4-3"; ++ samsung,pin-function = <2>; ++ samsung,pin-pud = <0>; ++ samsung,pin-drv = <0>; ++ }; ++ ++ fimc_is_uart: fimc-is-uart { ++ samsung,pins = "gpm3-5", "gpm3-7"; ++ samsung,pin-function = <3>; ++ samsung,pin-pud = <0>; ++ samsung,pin-drv = <0>; ++ }; + }; + + pinctrl@03860000 { +-- +1.8.3.2 + diff --git a/patches.tizen/0054-ARM-dts-Add-pinctrl-property-to-fimc-is-node-for-PQ-.patch b/patches.tizen/0054-ARM-dts-Add-pinctrl-property-to-fimc-is-node-for-PQ-.patch new file mode 100644 index 00000000000..40eebfd2685 --- /dev/null +++ b/patches.tizen/0054-ARM-dts-Add-pinctrl-property-to-fimc-is-node-for-PQ-.patch @@ -0,0 +1,35 @@ +From a6bd16a03a97317a3d79977ced76b0f6b345f553 Mon Sep 17 00:00:00 2001 +From: Sylwester Nawrocki <s.nawrocki@samsung.com> +Date: Wed, 23 Jan 2013 17:25:56 +0100 +Subject: [PATCH 0054/1302] ARM: dts: Add pinctrl property to fimc-is node for + PQ board + +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4412-slp_pq.dts | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/arm/boot/dts/exynos4412-slp_pq.dts b/arch/arm/boot/dts/exynos4412-slp_pq.dts +index fa47f9a..3ff029f 100644 +--- a/arch/arm/boot/dts/exynos4412-slp_pq.dts ++++ b/arch/arm/boot/dts/exynos4412-slp_pq.dts +@@ -627,6 +627,8 @@ + + fimc-is@12000000 { + status = "okay"; ++ pinctrl-0 = <&fimc_is_i2c0 &fimc_is_i2c1 &fimc_is_uart>; ++ pinctrl-names = "default"; + + fimc_lite_0: fimc-lite@12390000 { + status = "okay"; +@@ -637,6 +639,7 @@ + }; + + fimc-is-i2c@0 { ++ /* compatible = "samsung,exynos4212-is-i2c"; */ + #address-cells = <1>; + #size-cells = <0>; + +-- +1.8.3.2 + diff --git a/patches.tizen/0055-ARM-dts-Add-MFC-node-for-Exynos4-SoC-series.patch b/patches.tizen/0055-ARM-dts-Add-MFC-node-for-Exynos4-SoC-series.patch new file mode 100644 index 00000000000..2836ea1174c --- /dev/null +++ b/patches.tizen/0055-ARM-dts-Add-MFC-node-for-Exynos4-SoC-series.patch @@ -0,0 +1,27 @@ +From d1934f1b374955632b5cc71c2628e048bfe38a5b Mon Sep 17 00:00:00 2001 +From: Sylwester Nawrocki <s.nawrocki@samsung.com> +Date: Tue, 29 Jan 2013 14:44:19 +0100 +Subject: [PATCH 0055/1302] ARM: dts: Add MFC node for Exynos4 SoC series + +Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4.dtsi | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi +index 5a3955b..e81937c 100644 +--- a/arch/arm/boot/dts/exynos4.dtsi ++++ b/arch/arm/boot/dts/exynos4.dtsi +@@ -230,6 +230,8 @@ + reg = <0x13400000 0x10000>; + interrupts = <0 94 0>; + samsung,power-domain = <&pd_mfc>; ++ clocks = <&clock 273>, <&clock 170>; ++ clock-names = "mfc", "sclk_mfc"; + status = "disabled"; + iommu = <&sysmmu_mfc_l>, <&sysmmu_mfc_r>; + }; +-- +1.8.3.2 + diff --git a/patches.tizen/0056-ARM-dts-Add-camera-clocks-definitions-to-exynos4-x12.patch b/patches.tizen/0056-ARM-dts-Add-camera-clocks-definitions-to-exynos4-x12.patch new file mode 100644 index 00000000000..45af53dca41 --- /dev/null +++ b/patches.tizen/0056-ARM-dts-Add-camera-clocks-definitions-to-exynos4-x12.patch @@ -0,0 +1,122 @@ +From 2804ec5fe10232797945a2fd0239175c88aef877 Mon Sep 17 00:00:00 2001 +From: Sylwester Nawrocki <s.nawrocki@samsung.com> +Date: Fri, 18 Jan 2013 19:14:50 +0100 +Subject: [PATCH 0056/1302] ARM: dts: Add camera clocks definitions to + exynos4/x12.dtsi + +Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> +Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> +--- + arch/arm/boot/dts/exynos4.dtsi | 17 +++++++++++++++++ + arch/arm/boot/dts/exynos4x12.dtsi | 8 ++++++++ + 2 files changed, 25 insertions(+) + +diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi +index e81937c..758e321 100644 +--- a/arch/arm/boot/dts/exynos4.dtsi ++++ b/arch/arm/boot/dts/exynos4.dtsi +@@ -106,16 +106,23 @@ + + camera { + compatible = "samsung,fimc", "simple-bus"; ++ clocks = <&clock 132>, <&clock 133>, <&clock 351>, <&clock 352>, ++ <&clock 388>, <&clock 389>, <&clock 17>; ++ clock-names = "sclk_cam0", "sclk_cam1", "pxl_async0", ++ "pxl_async1", "mux_cam0", "mux_cam1", "parent"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + ++ + fimc_0: fimc@11800000 { + compatible = "samsung,exynos4210-fimc"; + reg = <0x11800000 0x1000>; + interrupts = <0 84 0>; + samsung,power-domain = <&pd_cam>; ++ clocks = <&clock 256>, <&clock 128>, <&clock 384>, <&clock 17>; ++ clock-names = "fimc", "sclk_fimc", "mux", "parent"; + status = "disabled"; + }; + +@@ -124,6 +131,8 @@ + reg = <0x11810000 0x1000>; + interrupts = <0 85 0>; + samsung,power-domain = <&pd_cam>; ++ clocks = <&clock 257>, <&clock 129>, <&clock 385>, <&clock 17>; ++ clock-names = "fimc", "sclk_fimc", "mux", "parent"; + status = "disabled"; + }; + +@@ -132,6 +141,8 @@ + reg = <0x11820000 0x1000>; + interrupts = <0 86 0>; + samsung,power-domain = <&pd_cam>; ++ clocks = <&clock 258>, <&clock 130>, <&clock 386>, <&clock 17>; ++ clock-names = "fimc", "sclk_fimc", "mux", "parent"; + status = "disabled"; + }; + +@@ -140,6 +151,8 @@ + reg = <0x11830000 0x1000>; + interrupts = <0 87 0>; + samsung,power-domain = <&pd_cam>; ++ clocks = <&clock 259>, <&clock 131>, <&clock 387>, <&clock 17>; ++ clock-names = "fimc", "sclk_fimc", "mux", "parent"; + status = "disabled"; + }; + +@@ -149,6 +162,8 @@ + interrupts = <0 78 0>; + bus-width = <4>; + samsung,power-domain = <&pd_cam>; ++ clocks = <&clock 260>, <&clock 134>, <&clock 390>, <&clock 17>; ++ clock-names = "csis", "sclk_csis", "mux", "parent"; + status = "disabled"; + }; + +@@ -158,6 +173,8 @@ + interrupts = <0 80 0>; + bus-width = <2>; + samsung,power-domain = <&pd_cam>; ++ clocks = <&clock 261>, <&clock 135>, <&clock 391>, <&clock 17>; ++ clock-names = "csis", "sclk_csis", "mux", "parent"; + status = "disabled"; + }; + }; +diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi +index 3b4a16b..621301c 100644 +--- a/arch/arm/boot/dts/exynos4x12.dtsi ++++ b/arch/arm/boot/dts/exynos4x12.dtsi +@@ -204,6 +204,10 @@ + reg = <0x12000000 0x260000>; + interrupts = <0 90 0>, <0 95 0>; + samsung,power-domain = <&pd_isp>; ++ clocks = <&clock 353>, <&clock 354>, <&clock 355>, ++ <&clock 356>, <&clock 342>, <&clock 17>; ++ clock-names = "flite0", "flite1", "ppmuispx", ++ "ppmuispmx", "sysreg", "mpll"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; +@@ -214,6 +218,8 @@ + reg = <0x12390000 0x1000>; + interrupts = <0 105 0>; + samsung,power-domain = <&pd_isp>; ++ clocks = <&clock 353>; ++ clock-names = "flite"; + status = "disabled"; + }; + +@@ -222,6 +228,8 @@ + |