From 5cfb203a304deaaa8c7c5368722b214d24583137 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 8 Aug 2015 15:16:20 +0930 Subject: modpost: abort if a module symbol is too long Module symbols have a limited length, but currently the build system allows the build finishing even if the driver code contains a too long symbol name, which eventually overflows the modversion_info[] item. The compiler may catch at compiling *.mod.c like CC xxx.mod.o xxx.mod.c:18:16: warning: initializer-string for array of chars is too long but it's merely a warning. This patch adds the check of the symbol length in modpost and stops the build properly. Currently MODULE_NAME_LEN is defined in modpost.c instead of referring to the definition in kernel header because including linux/module.h is messy and we must cover cross-compilation. Signed-off-by: Takashi Iwai Signed-off-by: Rusty Russell diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 12d3db3..d583c98 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -2133,6 +2133,11 @@ static void add_staging_flag(struct buffer *b, const char *name) buf_printf(b, "\nMODULE_INFO(staging, \"Y\");\n"); } +/* In kernel, this size is defined in linux/module.h; + * here we use Elf_Addr instead of long for covering cross-compile + */ +#define MODULE_NAME_LEN (64 - sizeof(Elf_Addr)) + /** * Record CRCs for unresolved symbols **/ @@ -2177,6 +2182,12 @@ static int add_versions(struct buffer *b, struct module *mod) s->name, mod->name); continue; } + if (strlen(s->name) >= MODULE_NAME_LEN) { + merror("too long symbol \"%s\" [%s.ko]\n", + s->name, mod->name); + err = 1; + break; + } buf_printf(b, "\t{ %#8x, __VMLINUX_SYMBOL_STR(%s) },\n", s->crc, s->name); } -- cgit v0.10.2 From 09120d4e88b13967d44d46280fb74d3ac4ac2f73 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 29 Jul 2015 17:23:45 +0100 Subject: drm/i915: Remove unnecessary gen8_clamp_pd gen8_clamp_pd clamps to the next page directory boundary, but the macro gen8_for_each_pde already has a check to stop at the page directory boundary. Furthermore, i915_pte_count also restricts to the next page table boundary. v2: Rebase after Mika's ppgtt cleanup / scratch merge patch series. Suggested-by: Akash Goel Signed-off-by: Michel Thierry Reviewed-by: "Akash Goel" Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 96054a5..566466f 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -955,7 +955,7 @@ static int gen8_alloc_va_range(struct i915_address_space *vm, gen8_for_each_pdpe(pd, &ppgtt->pdp, start, length, temp, pdpe) { gen8_pde_t *const page_directory = kmap_px(pd); struct i915_page_table *pt; - uint64_t pd_len = gen8_clamp_pd(start, length); + uint64_t pd_len = length; uint64_t pd_start = start; uint32_t pde; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index e1cfa29..d5bf953 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -444,17 +444,6 @@ static inline uint32_t gen6_pde_index(uint32_t addr) temp = min(temp, length), \ start += temp, length -= temp) -/* Clamp length to the next page_directory boundary */ -static inline uint64_t gen8_clamp_pd(uint64_t start, uint64_t length) -{ - uint64_t next_pd = ALIGN(start + 1, 1 << GEN8_PDPE_SHIFT); - - if (next_pd > (start + length)) - return length; - - return next_pd - start; -} - static inline uint32_t gen8_pte_index(uint64_t address) { return i915_pte_index(address, GEN8_PDE_SHIFT); -- cgit v0.10.2 From 6ac1850220732f47bc6ae767fa41542009674ad7 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 29 Jul 2015 17:23:46 +0100 Subject: drm/i915/gen8: Make pdp allocation more dynamic This transitional patch doesn't do much for the existing code. However, it should make upcoming patches to use the full 48b address space a bit easier. 32-bit ppgtt uses just 4 PDPs, while 48-bit ppgtt will have up-to 512; this patch prepares the existing functions to query the right number of pdps at run-time. This also means that used_pdpes should also be allocated during ppgtt_init, as the bitmap size will depend on the ppgtt address range selected. v2: Renamed pdp_free to be similar to pd/pt (unmap_and_free_pdp). v3: To facilitate testing, 48b mode will be available on Broadwell and GEN9+, when i915.enable_ppgtt = 3. v4: Rebase after s/page_tables/page_table/, added extra information about 4-level page table formats and use IS_ENABLED macro. v5: Check CONFIG_X86_64 instead of CONFIG_64BIT. v6: Rebase after Mika's ppgtt cleanup / scratch merge patch series, and follow his nomenclature in pdp functions (there is no alloc_pdp yet). v7: Rebase after merged version of Mika's ppgtt cleanup patch series. v8: Rebase after final merged version of Mika's ppgtt/scratch patches. v9: Introduce PML4 (and 48-bit checks) until next patch (Akash). v10: Also use test_bit to detect when pd/pt are already allocated (Akash) Cc: Akash Goel Signed-off-by: Ben Widawsky Signed-off-by: Michel Thierry (v2+) Reviewed-by: Akash Goel [danvet: Amend commit message as suggested by Michel.] Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 566466f..6724e71 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -522,6 +522,43 @@ static void gen8_initialize_pd(struct i915_address_space *vm, fill_px(vm->dev, pd, scratch_pde); } +static int __pdp_init(struct drm_device *dev, + struct i915_page_directory_pointer *pdp) +{ + size_t pdpes = I915_PDPES_PER_PDP(dev); + + pdp->used_pdpes = kcalloc(BITS_TO_LONGS(pdpes), + sizeof(unsigned long), + GFP_KERNEL); + if (!pdp->used_pdpes) + return -ENOMEM; + + pdp->page_directory = kcalloc(pdpes, sizeof(*pdp->page_directory), + GFP_KERNEL); + if (!pdp->page_directory) { + kfree(pdp->used_pdpes); + /* the PDP might be the statically allocated top level. Keep it + * as clean as possible */ + pdp->used_pdpes = NULL; + return -ENOMEM; + } + + return 0; +} + +static void __pdp_fini(struct i915_page_directory_pointer *pdp) +{ + kfree(pdp->used_pdpes); + kfree(pdp->page_directory); + pdp->page_directory = NULL; +} + +static void free_pdp(struct drm_device *dev, + struct i915_page_directory_pointer *pdp) +{ + __pdp_fini(pdp); +} + /* Broadwell Page Directory Pointer Descriptors */ static int gen8_write_pdp(struct drm_i915_gem_request *req, unsigned entry, @@ -720,7 +757,8 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm) container_of(vm, struct i915_hw_ppgtt, base); int i; - for_each_set_bit(i, ppgtt->pdp.used_pdpes, GEN8_LEGACY_PDPES) { + for_each_set_bit(i, ppgtt->pdp.used_pdpes, + I915_PDPES_PER_PDP(ppgtt->base.dev)) { if (WARN_ON(!ppgtt->pdp.page_directory[i])) continue; @@ -729,6 +767,7 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm) free_pd(ppgtt->base.dev, ppgtt->pdp.page_directory[i]); } + free_pdp(ppgtt->base.dev, &ppgtt->pdp); gen8_free_scratch(vm); } @@ -763,7 +802,7 @@ static int gen8_ppgtt_alloc_pagetabs(struct i915_hw_ppgtt *ppgtt, gen8_for_each_pde(pt, pd, start, length, temp, pde) { /* Don't reallocate page tables */ - if (pt) { + if (test_bit(pde, pd->used_pdes)) { /* Scratch is never allocated this way */ WARN_ON(pt == ppgtt->base.scratch_pt); continue; @@ -820,11 +859,12 @@ static int gen8_ppgtt_alloc_page_directories(struct i915_hw_ppgtt *ppgtt, struct i915_page_directory *pd; uint64_t temp; uint32_t pdpe; + uint32_t pdpes = I915_PDPES_PER_PDP(dev); - WARN_ON(!bitmap_empty(new_pds, GEN8_LEGACY_PDPES)); + WARN_ON(!bitmap_empty(new_pds, pdpes)); gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) { - if (pd) + if (test_bit(pdpe, pdp->used_pdpes)) continue; pd = alloc_pd(dev); @@ -839,18 +879,19 @@ static int gen8_ppgtt_alloc_page_directories(struct i915_hw_ppgtt *ppgtt, return 0; unwind_out: - for_each_set_bit(pdpe, new_pds, GEN8_LEGACY_PDPES) + for_each_set_bit(pdpe, new_pds, pdpes) free_pd(dev, pdp->page_directory[pdpe]); return -ENOMEM; } static void -free_gen8_temp_bitmaps(unsigned long *new_pds, unsigned long **new_pts) +free_gen8_temp_bitmaps(unsigned long *new_pds, unsigned long **new_pts, + uint32_t pdpes) { int i; - for (i = 0; i < GEN8_LEGACY_PDPES; i++) + for (i = 0; i < pdpes; i++) kfree(new_pts[i]); kfree(new_pts); kfree(new_pds); @@ -861,23 +902,24 @@ free_gen8_temp_bitmaps(unsigned long *new_pds, unsigned long **new_pts) */ static int __must_check alloc_gen8_temp_bitmaps(unsigned long **new_pds, - unsigned long ***new_pts) + unsigned long ***new_pts, + uint32_t pdpes) { int i; unsigned long *pds; unsigned long **pts; - pds = kcalloc(BITS_TO_LONGS(GEN8_LEGACY_PDPES), sizeof(unsigned long), GFP_KERNEL); + pds = kcalloc(BITS_TO_LONGS(pdpes), sizeof(unsigned long), GFP_KERNEL); if (!pds) return -ENOMEM; - pts = kcalloc(GEN8_LEGACY_PDPES, sizeof(unsigned long *), GFP_KERNEL); + pts = kcalloc(pdpes, sizeof(unsigned long *), GFP_KERNEL); if (!pts) { kfree(pds); return -ENOMEM; } - for (i = 0; i < GEN8_LEGACY_PDPES; i++) { + for (i = 0; i < pdpes; i++) { pts[i] = kcalloc(BITS_TO_LONGS(I915_PDES), sizeof(unsigned long), GFP_KERNEL); if (!pts[i]) @@ -890,7 +932,7 @@ int __must_check alloc_gen8_temp_bitmaps(unsigned long **new_pds, return 0; err_out: - free_gen8_temp_bitmaps(pds, pts); + free_gen8_temp_bitmaps(pds, pts, pdpes); return -ENOMEM; } @@ -916,6 +958,7 @@ static int gen8_alloc_va_range(struct i915_address_space *vm, const uint64_t orig_length = length; uint64_t temp; uint32_t pdpe; + uint32_t pdpes = I915_PDPES_PER_PDP(ppgtt->base.dev); int ret; /* Wrap is never okay since we can only represent 48b, and we don't @@ -927,7 +970,7 @@ static int gen8_alloc_va_range(struct i915_address_space *vm, if (WARN_ON(start + length > ppgtt->base.total)) return -ENODEV; - ret = alloc_gen8_temp_bitmaps(&new_page_dirs, &new_page_tables); + ret = alloc_gen8_temp_bitmaps(&new_page_dirs, &new_page_tables, pdpes); if (ret) return ret; @@ -935,7 +978,7 @@ static int gen8_alloc_va_range(struct i915_address_space *vm, ret = gen8_ppgtt_alloc_page_directories(ppgtt, &ppgtt->pdp, start, length, new_page_dirs); if (ret) { - free_gen8_temp_bitmaps(new_page_dirs, new_page_tables); + free_gen8_temp_bitmaps(new_page_dirs, new_page_tables, pdpes); return ret; } @@ -989,7 +1032,7 @@ static int gen8_alloc_va_range(struct i915_address_space *vm, __set_bit(pdpe, ppgtt->pdp.used_pdpes); } - free_gen8_temp_bitmaps(new_page_dirs, new_page_tables); + free_gen8_temp_bitmaps(new_page_dirs, new_page_tables, pdpes); mark_tlbs_dirty(ppgtt); return 0; @@ -999,10 +1042,10 @@ err_out: free_pt(vm->dev, ppgtt->pdp.page_directory[pdpe]->page_table[temp]); } - for_each_set_bit(pdpe, new_page_dirs, GEN8_LEGACY_PDPES) + for_each_set_bit(pdpe, new_page_dirs, pdpes) free_pd(vm->dev, ppgtt->pdp.page_directory[pdpe]); - free_gen8_temp_bitmaps(new_page_dirs, new_page_tables); + free_gen8_temp_bitmaps(new_page_dirs, new_page_tables, pdpes); mark_tlbs_dirty(ppgtt); return ret; } @@ -1040,7 +1083,16 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) ppgtt->switch_mm = gen8_mm_switch; + ret = __pdp_init(false, &ppgtt->pdp); + + if (ret) + goto free_scratch; + return 0; + +free_scratch: + gen8_free_scratch(&ppgtt->base); + return ret; } static void gen6_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index d5bf953..87e389c 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -98,6 +98,9 @@ typedef uint64_t gen8_pde_t; #define GEN8_LEGACY_PDPES 4 #define GEN8_PTES I915_PTES(sizeof(gen8_pte_t)) +/* FIXME: Next patch will use dev */ +#define I915_PDPES_PER_PDP(dev) GEN8_LEGACY_PDPES + #define PPAT_UNCACHED_INDEX (_PAGE_PWT | _PAGE_PCD) #define PPAT_CACHED_PDE_INDEX 0 /* WB LLC */ #define PPAT_CACHED_INDEX _PAGE_PAT /* WB LLCeLLC */ @@ -241,9 +244,10 @@ struct i915_page_directory { }; struct i915_page_directory_pointer { - /* struct page *page; */ - DECLARE_BITMAP(used_pdpes, GEN8_LEGACY_PDPES); - struct i915_page_directory *page_directory[GEN8_LEGACY_PDPES]; + struct i915_page_dma base; + + unsigned long *used_pdpes; + struct i915_page_directory **page_directory; }; struct i915_address_space { @@ -436,9 +440,10 @@ static inline uint32_t gen6_pde_index(uint32_t addr) temp = min(temp, length), \ start += temp, length -= temp) -#define gen8_for_each_pdpe(pd, pdp, start, length, temp, iter) \ - for (iter = gen8_pdpe_index(start); \ - pd = (pdp)->page_directory[iter], length > 0 && iter < GEN8_LEGACY_PDPES; \ +#define gen8_for_each_pdpe(pd, pdp, start, length, temp, iter) \ + for (iter = gen8_pdpe_index(start); \ + pd = (pdp)->page_directory[iter], \ + length > 0 && (iter < I915_PDPES_PER_PDP(dev)); \ iter++, \ temp = ALIGN(start+1, 1 << GEN8_PDPE_SHIFT) - start, \ temp = min(temp, length), \ -- cgit v0.10.2 From d4ec9da0e17cb6a86c0b76c5b254981601d25031 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Thu, 30 Jul 2015 11:02:03 +0100 Subject: drm/i915/gen8: Abstract PDP usage Up until now, ppgtt->pdp has always been the root of our page tables. Legacy 32b addresses acted like it had 1 PDP with 4 PDPEs. In preparation for 4 level page tables, we need to stop using ppgtt->pdp directly unless we know it's what we want. The future structure will use ppgtt->pml4 for the top level, and the pdp is just one of the entries being pointed to by a pml4e. The temporal pdp local variable will be removed once the rest of the 4-level code lands. Also, start passing the vm pointer to the alloc functions, instead of ppgtt. v2: Updated after dynamic page allocation changes. v3: Rebase after s/page_tables/page_table/. v4: Rebase after changes in "Dynamic page table allocations" patch. v5: Rebase after Mika's ppgtt cleanup / scratch merge patch series. v6: Rebase after final merged version of Mika's ppgtt/scratch patches. v7: Keep pagetable map in-line (and avoid unnecessary for_each_pde loops), remove redundant ppgtt pointer in _alloc_pagetabs (Akash) v8: Fix text indentation in _alloc_pagetabs/page_directories (Chris) v9: Defer gen8_alloc_va_range_4lvl definition until 4lvl is implemented, clean-up gen8_ppgtt_cleanup [pun intended] (Akash). v10: Clean-up commit message (Akash). Cc: Akash Goel Signed-off-by: Ben Widawsky Signed-off-by: Michel Thierry (v2+) Reviewed-by: "Akash Goel" Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 6724e71..95a4688 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -607,6 +607,7 @@ static void gen8_ppgtt_clear_range(struct i915_address_space *vm, { struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); + struct i915_page_directory_pointer *pdp = &ppgtt->pdp; /* FIXME: 48b */ gen8_pte_t *pt_vaddr, scratch_pte; unsigned pdpe = start >> GEN8_PDPE_SHIFT & GEN8_PDPE_MASK; unsigned pde = start >> GEN8_PDE_SHIFT & GEN8_PDE_MASK; @@ -621,10 +622,10 @@ static void gen8_ppgtt_clear_range(struct i915_address_space *vm, struct i915_page_directory *pd; struct i915_page_table *pt; - if (WARN_ON(!ppgtt->pdp.page_directory[pdpe])) + if (WARN_ON(!pdp->page_directory[pdpe])) break; - pd = ppgtt->pdp.page_directory[pdpe]; + pd = pdp->page_directory[pdpe]; if (WARN_ON(!pd->page_table[pde])) break; @@ -662,6 +663,7 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm, { struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); + struct i915_page_directory_pointer *pdp = &ppgtt->pdp; /* FIXME: 48b */ gen8_pte_t *pt_vaddr; unsigned pdpe = start >> GEN8_PDPE_SHIFT & GEN8_PDPE_MASK; unsigned pde = start >> GEN8_PDE_SHIFT & GEN8_PDE_MASK; @@ -675,7 +677,7 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm, break; if (pt_vaddr == NULL) { - struct i915_page_directory *pd = ppgtt->pdp.page_directory[pdpe]; + struct i915_page_directory *pd = pdp->page_directory[pdpe]; struct i915_page_table *pt = pd->page_table[pde]; pt_vaddr = kmap_px(pt); } @@ -755,28 +757,29 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm) { struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); + struct i915_page_directory_pointer *pdp = &ppgtt->pdp; /* FIXME: 48b */ + struct drm_device *dev = ppgtt->base.dev; int i; - for_each_set_bit(i, ppgtt->pdp.used_pdpes, - I915_PDPES_PER_PDP(ppgtt->base.dev)) { - if (WARN_ON(!ppgtt->pdp.page_directory[i])) + for_each_set_bit(i, pdp->used_pdpes, I915_PDPES_PER_PDP(dev)) { + if (WARN_ON(!pdp->page_directory[i])) continue; - gen8_free_page_tables(ppgtt->base.dev, - ppgtt->pdp.page_directory[i]); - free_pd(ppgtt->base.dev, ppgtt->pdp.page_directory[i]); + gen8_free_page_tables(dev, pdp->page_directory[i]); + free_pd(dev, pdp->page_directory[i]); } - free_pdp(ppgtt->base.dev, &ppgtt->pdp); + free_pdp(dev, pdp); + gen8_free_scratch(vm); } /** * gen8_ppgtt_alloc_pagetabs() - Allocate page tables for VA range. - * @ppgtt: Master ppgtt structure. - * @pd: Page directory for this address range. + * @vm: Master vm structure. + * @pd: Page directory for this address range. * @start: Starting virtual address to begin allocations. - * @length Size of the allocations. + * @length: Size of the allocations. * @new_pts: Bitmap set by function with new allocations. Likely used by the * caller to free on error. * @@ -789,13 +792,13 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm) * * Return: 0 if success; negative error code otherwise. */ -static int gen8_ppgtt_alloc_pagetabs(struct i915_hw_ppgtt *ppgtt, +static int gen8_ppgtt_alloc_pagetabs(struct i915_address_space *vm, struct i915_page_directory *pd, uint64_t start, uint64_t length, unsigned long *new_pts) { - struct drm_device *dev = ppgtt->base.dev; + struct drm_device *dev = vm->dev; struct i915_page_table *pt; uint64_t temp; uint32_t pde; @@ -804,7 +807,7 @@ static int gen8_ppgtt_alloc_pagetabs(struct i915_hw_ppgtt *ppgtt, /* Don't reallocate page tables */ if (test_bit(pde, pd->used_pdes)) { /* Scratch is never allocated this way */ - WARN_ON(pt == ppgtt->base.scratch_pt); + WARN_ON(pt == vm->scratch_pt); continue; } @@ -812,7 +815,7 @@ static int gen8_ppgtt_alloc_pagetabs(struct i915_hw_ppgtt *ppgtt, if (IS_ERR(pt)) goto unwind_out; - gen8_initialize_pt(&ppgtt->base, pt); + gen8_initialize_pt(vm, pt); pd->page_table[pde] = pt; __set_bit(pde, new_pts); } @@ -828,11 +831,11 @@ unwind_out: /** * gen8_ppgtt_alloc_page_directories() - Allocate page directories for VA range. - * @ppgtt: Master ppgtt structure. + * @vm: Master vm structure. * @pdp: Page directory pointer for this address range. * @start: Starting virtual address to begin allocations. - * @length Size of the allocations. - * @new_pds Bitmap set by function with new allocations. Likely used by the + * @length: Size of the allocations. + * @new_pds: Bitmap set by function with new allocations. Likely used by the * caller to free on error. * * Allocate the required number of page directories starting at the pde index of @@ -849,13 +852,14 @@ unwind_out: * * Return: 0 if success; negative error code otherwise. */ -static int gen8_ppgtt_alloc_page_directories(struct i915_hw_ppgtt *ppgtt, - struct i915_page_directory_pointer *pdp, - uint64_t start, - uint64_t length, - unsigned long *new_pds) +static int +gen8_ppgtt_alloc_page_directories(struct i915_address_space *vm, + struct i915_page_directory_pointer *pdp, + uint64_t start, + uint64_t length, + unsigned long *new_pds) { - struct drm_device *dev = ppgtt->base.dev; + struct drm_device *dev = vm->dev; struct i915_page_directory *pd; uint64_t temp; uint32_t pdpe; @@ -871,7 +875,7 @@ static int gen8_ppgtt_alloc_page_directories(struct i915_hw_ppgtt *ppgtt, if (IS_ERR(pd)) goto unwind_out; - gen8_initialize_pd(&ppgtt->base, pd); + gen8_initialize_pd(vm, pd); pdp->page_directory[pdpe] = pd; __set_bit(pdpe, new_pds); } @@ -947,18 +951,19 @@ static void mark_tlbs_dirty(struct i915_hw_ppgtt *ppgtt) } static int gen8_alloc_va_range(struct i915_address_space *vm, - uint64_t start, - uint64_t length) + uint64_t start, uint64_t length) { struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); unsigned long *new_page_dirs, **new_page_tables; + struct drm_device *dev = vm->dev; + struct i915_page_directory_pointer *pdp = &ppgtt->pdp; /* FIXME: 48b */ struct i915_page_directory *pd; const uint64_t orig_start = start; const uint64_t orig_length = length; uint64_t temp; uint32_t pdpe; - uint32_t pdpes = I915_PDPES_PER_PDP(ppgtt->base.dev); + uint32_t pdpes = I915_PDPES_PER_PDP(dev); int ret; /* Wrap is never okay since we can only represent 48b, and we don't @@ -967,7 +972,7 @@ static int gen8_alloc_va_range(struct i915_address_space *vm, if (WARN_ON(start + length < start)) return -ENODEV; - if (WARN_ON(start + length > ppgtt->base.total)) + if (WARN_ON(start + length > vm->total)) return -ENODEV; ret = alloc_gen8_temp_bitmaps(&new_page_dirs, &new_page_tables, pdpes); @@ -975,16 +980,16 @@ static int gen8_alloc_va_range(struct i915_address_space *vm, return ret; /* Do the allocations first so we can easily bail out */ - ret = gen8_ppgtt_alloc_page_directories(ppgtt, &ppgtt->pdp, start, length, - new_page_dirs); + ret = gen8_ppgtt_alloc_page_directories(vm, pdp, start, length, + new_page_dirs); if (ret) { free_gen8_temp_bitmaps(new_page_dirs, new_page_tables, pdpes); return ret; } /* For every page directory referenced, allocate page tables */ - gen8_for_each_pdpe(pd, &ppgtt->pdp, start, length, temp, pdpe) { - ret = gen8_ppgtt_alloc_pagetabs(ppgtt, pd, start, length, + gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) { + ret = gen8_ppgtt_alloc_pagetabs(vm, pd, start, length, new_page_tables[pdpe]); if (ret) goto err_out; @@ -995,7 +1000,7 @@ static int gen8_alloc_va_range(struct i915_address_space *vm, /* Allocations have completed successfully, so set the bitmaps, and do * the mappings. */ - gen8_for_each_pdpe(pd, &ppgtt->pdp, start, length, temp, pdpe) { + gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) { gen8_pde_t *const page_directory = kmap_px(pd); struct i915_page_table *pt; uint64_t pd_len = length; @@ -1028,8 +1033,7 @@ static int gen8_alloc_va_range(struct i915_address_space *vm, } kunmap_px(ppgtt, page_directory); - - __set_bit(pdpe, ppgtt->pdp.used_pdpes); + __set_bit(pdpe, pdp->used_pdpes); } free_gen8_temp_bitmaps(new_page_dirs, new_page_tables, pdpes); @@ -1039,11 +1043,11 @@ static int gen8_alloc_va_range(struct i915_address_space *vm, err_out: while (pdpe--) { for_each_set_bit(temp, new_page_tables[pdpe], I915_PDES) - free_pt(vm->dev, ppgtt->pdp.page_directory[pdpe]->page_table[temp]); + free_pt(dev, pdp->page_directory[pdpe]->page_table[temp]); } for_each_set_bit(pdpe, new_page_dirs, pdpes) - free_pd(vm->dev, ppgtt->pdp.page_directory[pdpe]); + free_pd(dev, pdp->page_directory[pdpe]); free_gen8_temp_bitmaps(new_page_dirs, new_page_tables, pdpes); mark_tlbs_dirty(ppgtt); -- cgit v0.10.2 From f9b5b782c4720f6c353088b559af5842ce66aa6f Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Thu, 30 Jul 2015 11:02:49 +0100 Subject: drm/i915/gen8: Generalize PTE writing for GEN8 PPGTT The insert_entries function was the function used to write PTEs. For the PPGTT it was "hardcoded" to only understand two level page tables, which was the case for GEN7. We can reuse this for 4 level page tables, and remove the concept of insert_entries, which was never viable past 2 level page tables anyway, but it requires a bit of rework to make the function a bit more generic. v2: Rebase after Mika's ppgtt cleanup / scratch merge patch series. v3: Rebase after final merged version of Mika's ppgtt/scratch patches. v4: Check and warn for NULL value of pdp pointer (Akash). Cc: Akash Goel Signed-off-by: Ben Widawsky Signed-off-by: Michel Thierry (v2) Reviewed-by: Akash Goel Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 95a4688..fc58f54 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -600,23 +600,23 @@ static int gen8_mm_switch(struct i915_hw_ppgtt *ppgtt, return 0; } -static void gen8_ppgtt_clear_range(struct i915_address_space *vm, - uint64_t start, - uint64_t length, - bool use_scratch) +static void gen8_ppgtt_clear_pte_range(struct i915_address_space *vm, + struct i915_page_directory_pointer *pdp, + uint64_t start, + uint64_t length, + gen8_pte_t scratch_pte) { struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); - struct i915_page_directory_pointer *pdp = &ppgtt->pdp; /* FIXME: 48b */ - gen8_pte_t *pt_vaddr, scratch_pte; + gen8_pte_t *pt_vaddr; unsigned pdpe = start >> GEN8_PDPE_SHIFT & GEN8_PDPE_MASK; unsigned pde = start >> GEN8_PDE_SHIFT & GEN8_PDE_MASK; unsigned pte = start >> GEN8_PTE_SHIFT & GEN8_PTE_MASK; unsigned num_entries = length >> PAGE_SHIFT; unsigned last_pte, i; - scratch_pte = gen8_pte_encode(px_dma(ppgtt->base.scratch_page), - I915_CACHE_LLC, use_scratch); + if (WARN_ON(!pdp)) + return; while (num_entries) { struct i915_page_directory *pd; @@ -656,14 +656,30 @@ static void gen8_ppgtt_clear_range(struct i915_address_space *vm, } } -static void gen8_ppgtt_insert_entries(struct i915_address_space *vm, - struct sg_table *pages, - uint64_t start, - enum i915_cache_level cache_level, u32 unused) +static void gen8_ppgtt_clear_range(struct i915_address_space *vm, + uint64_t start, + uint64_t length, + bool use_scratch) { struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); struct i915_page_directory_pointer *pdp = &ppgtt->pdp; /* FIXME: 48b */ + + gen8_pte_t scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page), + I915_CACHE_LLC, use_scratch); + + gen8_ppgtt_clear_pte_range(vm, pdp, start, length, scratch_pte); +} + +static void +gen8_ppgtt_insert_pte_entries(struct i915_address_space *vm, + struct i915_page_directory_pointer *pdp, + struct sg_table *pages, + uint64_t start, + enum i915_cache_level cache_level) +{ + struct i915_hw_ppgtt *ppgtt = + container_of(vm, struct i915_hw_ppgtt, base); gen8_pte_t *pt_vaddr; unsigned pdpe = start >> GEN8_PDPE_SHIFT & GEN8_PDPE_MASK; unsigned pde = start >> GEN8_PDE_SHIFT & GEN8_PDE_MASK; @@ -700,6 +716,19 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm, kunmap_px(ppgtt, pt_vaddr); } +static void gen8_ppgtt_insert_entries(struct i915_address_space *vm, + struct sg_table *pages, + uint64_t start, + enum i915_cache_level cache_level, + u32 unused) +{ + struct i915_hw_ppgtt *ppgtt = + container_of(vm, struct i915_hw_ppgtt, base); + struct i915_page_directory_pointer *pdp = &ppgtt->pdp; /* FIXME: 48b */ + + gen8_ppgtt_insert_pte_entries(vm, pdp, pages, start, cache_level); +} + static void gen8_free_page_tables(struct drm_device *dev, struct i915_page_directory *pd) { -- cgit v0.10.2 From 4c06ec8d13d2b0e57479bb135e49afd56ebe9275 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 29 Jul 2015 17:23:49 +0100 Subject: drm/i915/gen8: Add dynamic page trace events The dynamic page allocation patch series added it for GEN6, this patch adds them for GEN8. v2: Consolidate pagetable/page_directory events v3: Multiple rebases. v4: Rebase after s/page_tables/page_table/. v5: Rebase after Mika's ppgtt cleanup / scratch merge patch series. v6: Rebase after gen8_map_pagetable_range removal. v7: Use generic page name (px) in DECLARE_EVENT_CLASS (Akash) v8: Defer define of i915_page_directory_pointer_entry_alloc (Akash) Cc: Akash Goel Signed-off-by: Ben Widawsky Signed-off-by: Michel Thierry (v3+) Reviewed-by: Akash Goel Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index fc58f54..72f4777f 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -847,6 +847,7 @@ static int gen8_ppgtt_alloc_pagetabs(struct i915_address_space *vm, gen8_initialize_pt(vm, pt); pd->page_table[pde] = pt; __set_bit(pde, new_pts); + trace_i915_page_table_entry_alloc(vm, pde, start, GEN8_PDE_SHIFT); } return 0; @@ -907,6 +908,7 @@ gen8_ppgtt_alloc_page_directories(struct i915_address_space *vm, gen8_initialize_pd(vm, pd); pdp->page_directory[pdpe] = pd; __set_bit(pdpe, new_pds); + trace_i915_page_directory_entry_alloc(vm, pdpe, start, GEN8_PDPE_SHIFT); } return 0; @@ -1056,6 +1058,10 @@ static int gen8_alloc_va_range(struct i915_address_space *vm, /* Map the PDE to the page table */ page_directory[pde] = gen8_pde_encode(px_dma(pt), I915_CACHE_LLC); + trace_i915_page_table_entry_map(&ppgtt->base, pde, pt, + gen8_pte_index(start), + gen8_pte_count(start, length), + GEN8_PTES); /* NB: We haven't yet mapped ptes to pages. At this * point we're still relying on insert_entries() */ diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index 2f34c47..f230d76 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -186,33 +186,41 @@ DEFINE_EVENT(i915_va, i915_va_alloc, TP_ARGS(vm, start, length, name) ); -DECLARE_EVENT_CLASS(i915_page_table_entry, - TP_PROTO(struct i915_address_space *vm, u32 pde, u64 start, u64 pde_shift), - TP_ARGS(vm, pde, start, pde_shift), +DECLARE_EVENT_CLASS(i915_px_entry, + TP_PROTO(struct i915_address_space *vm, u32 px, u64 start, u64 px_shift), + TP_ARGS(vm, px, start, px_shift), TP_STRUCT__entry( __field(struct i915_address_space *, vm) - __field(u32, pde) + __field(u32, px) __field(u64, start) __field(u64, end) ), TP_fast_assign( __entry->vm = vm; - __entry->pde = pde; + __entry->px = px; __entry->start = start; - __entry->end = ((start + (1ULL << pde_shift)) & ~((1ULL << pde_shift)-1)) - 1; + __entry->end = ((start + (1ULL << px_shift)) & ~((1ULL << px_shift)-1)) - 1; ), TP_printk("vm=%p, pde=%d (0x%llx-0x%llx)", - __entry->vm, __entry->pde, __entry->start, __entry->end) + __entry->vm, __entry->px, __entry->start, __entry->end) ); -DEFINE_EVENT(i915_page_table_entry, i915_page_table_entry_alloc, +DEFINE_EVENT(i915_px_entry, i915_page_table_entry_alloc, TP_PROTO(struct i915_address_space *vm, u32 pde, u64 start, u64 pde_shift), TP_ARGS(vm, pde, start, pde_shift) ); +DEFINE_EVENT_PRINT(i915_px_entry, i915_page_directory_entry_alloc, + TP_PROTO(struct i915_address_space *vm, u32 pdpe, u64 start, u64 pdpe_shift), + TP_ARGS(vm, pdpe, start, pdpe_shift), + + TP_printk("vm=%p, pdpe=%d (0x%llx-0x%llx)", + __entry->vm, __entry->px, __entry->start, __entry->end) +); + /* Avoid extra math because we only support two sizes. The format is defined by * bitmap_scnprintf. Each 32 bits is 8 HEX digits followed by comma */ #define TRACE_PT_SIZE(bits) \ -- cgit v0.10.2 From 81ba8aefd03803a8aec3395d18f7b1dda5942105 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Mon, 3 Aug 2015 09:52:01 +0100 Subject: drm/i915/gen8: Add PML4 structure Introduces the Page Map Level 4 (PML4), ie. the new top level structure of the page tables. To facilitate testing, 48b mode will be available on Broadwell and GEN9+, when i915.enable_ppgtt = 3. v2: Remove unnecessary CONFIG_X86_64 checks, ppgtt code is already 32/64-bit safe (Chris). v3: Add goto free_scratch in temp 48-bit mode init code (Akash). v4: kfree the pdp until the 4lvl alloc/free patch (Akash). v5: Postpone 48-bit code in sanitize_enable_ppgtt (Akash). v6: Keep _insert_pte_entries changes outside this patch (Akash). Cc: Akash Goel Signed-off-by: Michel Thierry Reviewed-by: Akash Goel Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4273c28..79d2dcb 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2510,7 +2510,8 @@ struct drm_i915_cmd_table { #define HAS_HW_CONTEXTS(dev) (INTEL_INFO(dev)->gen >= 6) #define HAS_LOGICAL_RING_CONTEXTS(dev) (INTEL_INFO(dev)->gen >= 8) #define USES_PPGTT(dev) (i915.enable_ppgtt) -#define USES_FULL_PPGTT(dev) (i915.enable_ppgtt == 2) +#define USES_FULL_PPGTT(dev) (i915.enable_ppgtt >= 2) +#define USES_FULL_48BIT_PPGTT(dev) (i915.enable_ppgtt == 3) #define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay) #define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 72f4777f..da7863b 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1105,14 +1105,6 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) return ret; ppgtt->base.start = 0; - ppgtt->base.total = 1ULL << 32; - if (IS_ENABLED(CONFIG_X86_32)) - /* While we have a proliferation of size_t variables - * we cannot represent the full ppgtt size on 32bit, - * so limit it to the same size as the GGTT (currently - * 2GiB). - */ - ppgtt->base.total = to_i915(ppgtt->base.dev)->gtt.base.total; ppgtt->base.cleanup = gen8_ppgtt_cleanup; ppgtt->base.allocate_va_range = gen8_alloc_va_range; ppgtt->base.insert_entries = gen8_ppgtt_insert_entries; @@ -1122,10 +1114,25 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) ppgtt->switch_mm = gen8_mm_switch; - ret = __pdp_init(false, &ppgtt->pdp); + if (!USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) { + ret = __pdp_init(false, &ppgtt->pdp); - if (ret) + if (ret) + goto free_scratch; + + ppgtt->base.total = 1ULL << 32; + if (IS_ENABLED(CONFIG_X86_32)) + /* While we have a proliferation of size_t variables + * we cannot represent the full ppgtt size on 32bit, + * so limit it to the same size as the GGTT (currently + * 2GiB). + */ + ppgtt->base.total = to_i915(ppgtt->base.dev)->gtt.base.total; + } else { + ppgtt->base.total = 1ULL << 48; + ret = -EPERM; /* Not yet implemented */ goto free_scratch; + } return 0; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 87e389c..04bc66f 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -88,9 +88,17 @@ typedef uint64_t gen8_pde_t; * PDPE | PDE | PTE | offset * The difference as compared to normal x86 3 level page table is the PDPEs are * programmed via register. + * + * GEN8 48b legacy style address is defined as a 4 level page table: + * 47:39 | 38:30 | 29:21 | 20:12 | 11:0 + * PML4E | PDPE | PDE | PTE | offset */ +#define GEN8_PML4ES_PER_PML4 512 +#define GEN8_PML4E_SHIFT 39 #define GEN8_PDPE_SHIFT 30 -#define GEN8_PDPE_MASK 0x3 +/* NB: GEN8_PDPE_MASK is untrue for 32b platforms, but it has no impact on 32b page + * tables */ +#define GEN8_PDPE_MASK 0x1ff #define GEN8_PDE_SHIFT 21 #define GEN8_PDE_MASK 0x1ff #define GEN8_PTE_SHIFT 12 @@ -98,8 +106,8 @@ typedef uint64_t gen8_pde_t; #define GEN8_LEGACY_PDPES 4 #define GEN8_PTES I915_PTES(sizeof(gen8_pte_t)) -/* FIXME: Next patch will use dev */ -#define I915_PDPES_PER_PDP(dev) GEN8_LEGACY_PDPES +#define I915_PDPES_PER_PDP(dev) (USES_FULL_48BIT_PPGTT(dev) ?\ + GEN8_PML4ES_PER_PML4 : GEN8_LEGACY_PDPES) #define PPAT_UNCACHED_INDEX (_PAGE_PWT | _PAGE_PCD) #define PPAT_CACHED_PDE_INDEX 0 /* WB LLC */ @@ -250,6 +258,13 @@ struct i915_page_directory_pointer { struct i915_page_directory **page_directory; }; +struct i915_pml4 { + struct i915_page_dma base; + + DECLARE_BITMAP(used_pml4es, GEN8_PML4ES_PER_PML4); + struct i915_page_directory_pointer *pdps[GEN8_PML4ES_PER_PML4]; +}; + struct i915_address_space { struct drm_mm mm; struct drm_device *dev; @@ -345,8 +360,9 @@ struct i915_hw_ppgtt { struct drm_mm_node node; unsigned long pd_dirty_rings; union { - struct i915_page_directory_pointer pdp; - struct i915_page_directory pd; + struct i915_pml4 pml4; /* GEN8+ & 48b PPGTT */ + struct i915_page_directory_pointer pdp; /* GEN8+ */ + struct i915_page_directory pd; /* GEN6-7 */ }; struct drm_i915_file_private *file_priv; -- cgit v0.10.2 From 762d99363dc9bc436f39f8bdc3f8670ea272a5a9 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Thu, 30 Jul 2015 11:05:29 +0100 Subject: drm/i915/gen8: implement alloc/free for 4lvl PML4 has no special attributes, and there will always be a PML4. So simply initialize it at creation, and destroy it at the end. The code for 4lvl is able to call into the existing 3lvl page table code to handle all of the lower levels. v2: Return something at the end of gen8_alloc_va_range_4lvl to keep the compiler happy. And define ret only in one place. Updated gen8_ppgtt_unmap_pages and gen8_ppgtt_free to handle 4lvl. v3: Use i915_dma_unmap_single instead of pci API. Fix a couple of incorrect checks when unmapping pdp and pd pages (Akash). v4: Call __pdp_fini also for 32b PPGTT. Clean up alloc_pdp param list. v5: Prevent (harmless) out of range access in gen8_for_each_pml4e. v6: Simplify alloc_vma_range_4lvl and gen8_ppgtt_init_common error paths. (Akash) v7: Rebase, s/gen8_ppgtt_free_*/gen8_ppgtt_cleanup_*/. v8: Change location of pml4_init/fini. It will make next patches cleaner. v9: Rebase after Mika's ppgtt cleanup / scratch merge patch series, while trying to reuse as much as possible for pdp alloc. pml4_init/fini replaced by setup/cleanup_px macros. v10: Rebase after Mika's merged ppgtt cleanup patch series. v11: Rebase after final merged version of Mika's ppgtt/scratch patches. v12: Fix pdpe start value in trace (Akash) v13: Define all 4lvl functions in this patch directly, instead of previous patches, add i915_page_directory_pointer_entry_alloc here, use test_bit to detect when pdp is already allocated (Akash). v14: Move pdp allocation into a new gen8_ppgtt_alloc_page_dirpointers funtion, as we do for pds and pts; move pd and pdp setup functions to this patch (Akash). v15: Added kfree(pdp) from previous patch to this (Akash). Cc: Akash Goel Signed-off-by: Ben Widawsky Signed-off-by: Michel Thierry (v2+) Reviewed-by: Akash Goel Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index da7863b..229a317 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -204,6 +204,9 @@ static gen8_pde_t gen8_pde_encode(const dma_addr_t addr, return pde; } +#define gen8_pdpe_encode gen8_pde_encode +#define gen8_pml4e_encode gen8_pde_encode + static gen6_pte_t snb_pte_encode(dma_addr_t addr, enum i915_cache_level level, bool valid, u32 unused) @@ -553,10 +556,73 @@ static void __pdp_fini(struct i915_page_directory_pointer *pdp) pdp->page_directory = NULL; } +static struct +i915_page_directory_pointer *alloc_pdp(struct drm_device *dev) +{ + struct i915_page_directory_pointer *pdp; + int ret = -ENOMEM; + + WARN_ON(!USES_FULL_48BIT_PPGTT(dev)); + + pdp = kzalloc(sizeof(*pdp), GFP_KERNEL); + if (!pdp) + return ERR_PTR(-ENOMEM); + + ret = __pdp_init(dev, pdp); + if (ret) + goto fail_bitmap; + + ret = setup_px(dev, pdp); + if (ret) + goto fail_page_m; + + return pdp; + +fail_page_m: + __pdp_fini(pdp); +fail_bitmap: + kfree(pdp); + + return ERR_PTR(ret); +} + static void free_pdp(struct drm_device *dev, struct i915_page_directory_pointer *pdp) { __pdp_fini(pdp); + if (USES_FULL_48BIT_PPGTT(dev)) { + cleanup_px(dev, pdp); + kfree(pdp); + } +} + +static void +gen8_setup_page_directory(struct i915_hw_ppgtt *ppgtt, + struct i915_page_directory_pointer *pdp, + struct i915_page_directory *pd, + int index) +{ + gen8_ppgtt_pdpe_t *page_directorypo; + + if (!USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) + return; + + page_directorypo = kmap_px(pdp); + page_directorypo[index] = gen8_pdpe_encode(px_dma(pd), I915_CACHE_LLC); + kunmap_px(ppgtt, page_directorypo); +} + +static void +gen8_setup_page_directory_pointer(struct i915_hw_ppgtt *ppgtt, + struct i915_pml4 *pml4, + struct i915_page_directory_pointer *pdp, + int index) +{ + gen8_ppgtt_pml4e_t *pagemap = kmap_px(pml4); + + WARN_ON(!USES_FULL_48BIT_PPGTT(ppgtt->base.dev)); + pagemap[index] = gen8_pml4e_encode(px_dma(pdp), I915_CACHE_LLC); + kunmap_px(ppgtt, pagemap); } /* Broadwell Page Directory Pointer Descriptors */ @@ -782,12 +848,9 @@ static void gen8_free_scratch(struct i915_address_space *vm) free_scratch_page(dev, vm->scratch_page); } -static void gen8_ppgtt_cleanup(struct i915_address_space *vm) +static void gen8_ppgtt_cleanup_3lvl(struct drm_device *dev, + struct i915_page_directory_pointer *pdp) { - struct i915_hw_ppgtt *ppgtt = - container_of(vm, struct i915_hw_ppgtt, base); - struct i915_page_directory_pointer *pdp = &ppgtt->pdp; /* FIXME: 48b */ - struct drm_device *dev = ppgtt->base.dev; int i; for_each_set_bit(i, pdp->used_pdpes, I915_PDPES_PER_PDP(dev)) { @@ -799,6 +862,31 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm) } free_pdp(dev, pdp); +} + +static void gen8_ppgtt_cleanup_4lvl(struct i915_hw_ppgtt *ppgtt) +{ + int i; + + for_each_set_bit(i, ppgtt->pml4.used_pml4es, GEN8_PML4ES_PER_PML4) { + if (WARN_ON(!ppgtt->pml4.pdps[i])) + continue; + + gen8_ppgtt_cleanup_3lvl(ppgtt->base.dev, ppgtt->pml4.pdps[i]); + } + + cleanup_px(ppgtt->base.dev, &ppgtt->pml4); +} + +static void gen8_ppgtt_cleanup(struct i915_address_space *vm) +{ + struct i915_hw_ppgtt *ppgtt = + container_of(vm, struct i915_hw_ppgtt, base); + + if (!USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) + gen8_ppgtt_cleanup_3lvl(ppgtt->base.dev, &ppgtt->pdp); + else + gen8_ppgtt_cleanup_4lvl(ppgtt); gen8_free_scratch(vm); } @@ -920,6 +1008,60 @@ unwind_out: return -ENOMEM; } +/** + * gen8_ppgtt_alloc_page_dirpointers() - Allocate pdps for VA range. + * @vm: Master vm structure. + * @pml4: Page map level 4 for this address range. + * @start: Starting virtual address to begin allocations. + * @length: Size of the allocations. + * @new_pdps: Bitmap set by function with new allocations. Likely used by the + * caller to free on error. + * + * Allocate the required number of page directory pointers. Extremely similar to + * gen8_ppgtt_alloc_page_directories() and gen8_ppgtt_alloc_pagetabs(). + * The main difference is here we are limited by the pml4 boundary (instead of + * the page directory pointer). + * + * Return: 0 if success; negative error code otherwise. + */ +static int +gen8_ppgtt_alloc_page_dirpointers(struct i915_address_space *vm, + struct i915_pml4 *pml4, + uint64_t start, + uint64_t length, + unsigned long *new_pdps) +{ + struct drm_device *dev = vm->dev; + struct i915_page_directory_pointer *pdp; + uint64_t temp; + uint32_t pml4e; + + WARN_ON(!bitmap_empty(new_pdps, GEN8_PML4ES_PER_PML4)); + + gen8_for_each_pml4e(pdp, pml4, start, length, temp, pml4e) { + if (!test_bit(pml4e, pml4->used_pml4es)) { + pdp = alloc_pdp(dev); + if (IS_ERR(pdp)) + goto unwind_out; + + pml4->pdps[pml4e] = pdp; + __set_bit(pml4e, new_pdps); + trace_i915_page_directory_pointer_entry_alloc(vm, + pml4e, + start, + GEN8_PML4E_SHIFT); + } + } + + return 0; + +unwind_out: + for_each_set_bit(pml4e, new_pdps, GEN8_PML4ES_PER_PML4) + free_pdp(dev, pml4->pdps[pml4e]); + + return -ENOMEM; +} + static void free_gen8_temp_bitmaps(unsigned long *new_pds, unsigned long **new_pts, uint32_t pdpes) @@ -981,14 +1123,15 @@ static void mark_tlbs_dirty(struct i915_hw_ppgtt *ppgtt) ppgtt->pd_dirty_rings = INTEL_INFO(ppgtt->base.dev)->ring_mask; } -static int gen8_alloc_va_range(struct i915_address_space *vm, - uint64_t start, uint64_t length) +static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm, + struct i915_page_directory_pointer *pdp, + uint64_t start, + uint64_t length) { struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); unsigned long *new_page_dirs, **new_page_tables; struct drm_device *dev = vm->dev; - struct i915_page_directory_pointer *pdp = &ppgtt->pdp; /* FIXME: 48b */ struct i915_page_directory *pd; const uint64_t orig_start = start; const uint64_t orig_length = length; @@ -1069,6 +1212,7 @@ static int gen8_alloc_va_range(struct i915_address_space *vm, kunmap_px(ppgtt, page_directory); __set_bit(pdpe, pdp->used_pdpes); + gen8_setup_page_directory(ppgtt, pdp, pd, pdpe); } free_gen8_temp_bitmaps(new_page_dirs, new_page_tables, pdpes); @@ -1089,6 +1233,68 @@ err_out: return ret; } +static int gen8_alloc_va_range_4lvl(struct i915_address_space *vm, + struct i915_pml4 *pml4, + uint64_t start, + uint64_t length) +{ + DECLARE_BITMAP(new_pdps, GEN8_PML4ES_PER_PML4); + struct i915_hw_ppgtt *ppgtt = + container_of(vm, struct i915_hw_ppgtt, base); + struct i915_page_directory_pointer *pdp; + uint64_t temp, pml4e; + int ret = 0; + + /* Do the pml4 allocations first, so we don't need to track the newly + * allocated tables below the pdp */ + bitmap_zero(new_pdps, GEN8_PML4ES_PER_PML4); + + /* The pagedirectory and pagetable allocations are done in the shared 3 + * and 4 level code. Just allocate the pdps. + */ + ret = gen8_ppgtt_alloc_page_dirpointers(vm, pml4, start, length, + new_pdps); + if (ret) + return ret; + + WARN(bitmap_weight(new_pdps, GEN8_PML4ES_PER_PML4) > 2, + "The allocation has spanned more than 512GB. " + "It is highly likely this is incorrect."); + + gen8_for_each_pml4e(pdp, pml4, start, length, temp, pml4e) { + WARN_ON(!pdp); + + ret = gen8_alloc_va_range_3lvl(vm, pdp, start, length); + if (ret) + goto err_out; + + gen8_setup_page_directory_pointer(ppgtt, pml4, pdp, pml4e); + } + + bitmap_or(pml4->used_pml4es, new_pdps, pml4->used_pml4es, + GEN8_PML4ES_PER_PML4); + + return 0; + +err_out: + for_each_set_bit(pml4e, new_pdps, GEN8_PML4ES_PER_PML4) + gen8_ppgtt_cleanup_3lvl(vm->dev, pml4->pdps[pml4e]); + + return ret; +} + +static int gen8_alloc_va_range(struct i915_address_space *vm, + uint64_t start, uint64_t length) +{ + struct i915_hw_ppgtt *ppgtt = + container_of(vm, struct i915_hw_ppgtt, base); + + if (USES_FULL_48BIT_PPGTT(vm->dev)) + return gen8_alloc_va_range_4lvl(vm, &ppgtt->pml4, start, length); + else + return gen8_alloc_va_range_3lvl(vm, &ppgtt->pdp, start, length); +} + /* * GEN8 legacy ppgtt programming is accomplished through a max 4 PDP registers * with a net effect resembling a 2-level page table in normal x86 terms. Each @@ -1114,9 +1320,14 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) ppgtt->switch_mm = gen8_mm_switch; - if (!USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) { - ret = __pdp_init(false, &ppgtt->pdp); + if (USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) { + ret = setup_px(ppgtt->base.dev, &ppgtt->pml4); + if (ret) + goto free_scratch; + ppgtt->base.total = 1ULL << 48; + } else { + ret = __pdp_init(false, &ppgtt->pdp); if (ret) goto free_scratch; @@ -1128,10 +1339,10 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) * 2GiB). */ ppgtt->base.total = to_i915(ppgtt->base.dev)->gtt.base.total; - } else { - ppgtt->base.total = 1ULL << 48; - ret = -EPERM; /* Not yet implemented */ - goto free_scratch; + + trace_i915_page_directory_pointer_entry_alloc(&ppgtt->base, + 0, 0, + GEN8_PML4E_SHIFT); } return 0; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 04bc66f..11d44b3 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -39,6 +39,8 @@ struct drm_i915_file_private; typedef uint32_t gen6_pte_t; typedef uint64_t gen8_pte_t; typedef uint64_t gen8_pde_t; +typedef uint64_t gen8_ppgtt_pdpe_t; +typedef uint64_t gen8_ppgtt_pml4e_t; #define gtt_total_entries(gtt) ((gtt).base.total >> PAGE_SHIFT) @@ -95,6 +97,7 @@ typedef uint64_t gen8_pde_t; */ #define GEN8_PML4ES_PER_PML4 512 #define GEN8_PML4E_SHIFT 39 +#define GEN8_PML4E_MASK (GEN8_PML4ES_PER_PML4 - 1) #define GEN8_PDPE_SHIFT 30 /* NB: GEN8_PDPE_MASK is untrue for 32b platforms, but it has no impact on 32b page * tables */ @@ -465,6 +468,15 @@ static inline uint32_t gen6_pde_index(uint32_t addr) temp = min(temp, length), \ start += temp, length -= temp) +#define gen8_for_each_pml4e(pdp, pml4, start, length, temp, iter) \ + for (iter = gen8_pml4e_index(start); \ + pdp = (pml4)->pdps[iter], \ + length > 0 && iter < GEN8_PML4ES_PER_PML4; \ + iter++, \ + temp = ALIGN(start+1, 1ULL << GEN8_PML4E_SHIFT) - start, \ + temp = min(temp, length), \ + start += temp, length -= temp) + static inline uint32_t gen8_pte_index(uint64_t address) { return i915_pte_index(address, GEN8_PDE_SHIFT); @@ -482,8 +494,7 @@ static inline uint32_t gen8_pdpe_index(uint64_t address) static inline uint32_t gen8_pml4e_index(uint64_t address) { - WARN_ON(1); /* For 64B */ - return 0; + return (address >> GEN8_PML4E_SHIFT) & GEN8_PML4E_MASK; } static inline size_t gen8_pte_count(uint64_t address, uint64_t length) diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index f230d76..e6b5c74 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -221,6 +221,14 @@ DEFINE_EVENT_PRINT(i915_px_entry, i915_page_directory_entry_alloc, __entry->vm, __entry->px, __entry->start, __entry->end) ); +DEFINE_EVENT_PRINT(i915_px_entry, i915_page_directory_pointer_entry_alloc, + TP_PROTO(struct i915_address_space *vm, u32 pml4e, u64 start, u64 pml4e_shift), + TP_ARGS(vm, pml4e, start, pml4e_shift), + + TP_printk("vm=%p, pml4e=%d (0x%llx-0x%llx)", + __entry->vm, __entry->px, __entry->start, __entry->end) +); + /* Avoid extra math because we only support two sizes. The format is defined by * bitmap_scnprintf. Each 32 bits is 8 HEX digits followed by comma */ #define TRACE_PT_SIZE(bits) \ -- cgit v0.10.2 From 2dba3239f5c7511ffac957887facd0a0c9d003a5 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Thu, 30 Jul 2015 11:06:23 +0100 Subject: drm/i915/gen8: Add 4 level switching infrastructure and lrc support In 64b (48bit canonical) PPGTT addressing, the PDP0 register contains the base address to PML4, while the other PDP registers are ignored. In LRC, the addressing mode must be specified in every context descriptor, and the base address to PML4 is stored in the reg state. v2: PML4 update in legacy context switch is left for historic reasons, the preferred mode of operation is with lrc context based submission. v3: s/gen8_map_page_directory/gen8_setup_page_directory and s/gen8_map_page_directory_pointer/gen8_setup_page_directory_pointer. Also, clflush will be needed for bxt. (Akash) v4: Squashed lrc-specific code and use a macro to set PML4 register. v5: Rebase after Mika's ppgtt cleanup / scratch merge patch series. PDP update in bb_start is only for legacy 32b mode. v6: Rebase after final merged version of Mika's ppgtt/scratch patches. v7: There is no need to update the pml4 register value in execlists_update_context. (Akash) v8: Move pd and pdp setup functions to a previous patch, they do not belong here. (Akash) v9: Check USES_FULL_48BIT_PPGTT instead of GEN8_CTX_ADDRESSING_MODE in gen8_emit_bb_start to check if emit pdps is needed. (Akash) Cc: Akash Goel Signed-off-by: Ben Widawsky Signed-off-by: Michel Thierry (v2+) Reviewed-by: Akash Goel Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 229a317..2ab3cef 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -650,8 +650,8 @@ static int gen8_write_pdp(struct drm_i915_gem_request *req, return 0; } -static int gen8_mm_switch(struct i915_hw_ppgtt *ppgtt, - struct drm_i915_gem_request *req) +static int gen8_legacy_mm_switch(struct i915_hw_ppgtt *ppgtt, + struct drm_i915_gem_request *req) { int i, ret; @@ -666,6 +666,12 @@ static int gen8_mm_switch(struct i915_hw_ppgtt *ppgtt, return 0; } +static int gen8_48b_mm_switch(struct i915_hw_ppgtt *ppgtt, + struct drm_i915_gem_request *req) +{ + return gen8_write_pdp(req, 0, px_dma(&ppgtt->pml4)); +} + static void gen8_ppgtt_clear_pte_range(struct i915_address_space *vm, struct i915_page_directory_pointer *pdp, uint64_t start, @@ -1318,14 +1324,13 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) ppgtt->base.unbind_vma = ppgtt_unbind_vma; ppgtt->base.bind_vma = ppgtt_bind_vma; - ppgtt->switch_mm = gen8_mm_switch; - if (USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) { ret = setup_px(ppgtt->base.dev, &ppgtt->pml4); if (ret) goto free_scratch; ppgtt->base.total = 1ULL << 48; + ppgtt->switch_mm = gen8_48b_mm_switch; } else { ret = __pdp_init(false, &ppgtt->pdp); if (ret) @@ -1340,6 +1345,7 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) */ ppgtt->base.total = to_i915(ppgtt->base.dev)->gtt.base.total; + ppgtt->switch_mm = gen8_legacy_mm_switch; trace_i915_page_directory_pointer_entry_alloc(&ppgtt->base, 0, 0, GEN8_PML4E_SHIFT); @@ -1537,8 +1543,9 @@ static void gen8_ppgtt_enable(struct drm_device *dev) int j; for_each_ring(ring, dev_priv, j) { + u32 four_level = USES_FULL_48BIT_PPGTT(dev) ? GEN8_GFX_PPGTT_48B : 0; I915_WRITE(RING_MODE_GEN7(ring), - _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)); + _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE | four_level)); } } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 8e46c34..88f20cc 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1679,6 +1679,7 @@ enum skl_disp_power_wells { #define GFX_REPLAY_MODE (1<<11) #define GFX_PSMI_GRANULARITY (1<<10) #define GFX_PPGTT_ENABLE (1<<9) +#define GEN8_GFX_PPGTT_48B (1<<7) #define VLV_DISPLAY_BASE 0x180000 #define VLV_MIPI_BASE VLV_DISPLAY_BASE diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 5bc0ce1..138964a 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -196,13 +196,21 @@ reg_state[CTX_PDP ## n ## _LDW+1] = lower_32_bits(_addr); \ } +#define ASSIGN_CTX_PML4(ppgtt, reg_state) { \ + reg_state[CTX_PDP0_UDW + 1] = upper_32_bits(px_dma(&ppgtt->pml4)); \ + reg_state[CTX_PDP0_LDW + 1] = lower_32_bits(px_dma(&ppgtt->pml4)); \ +} + enum { ADVANCED_CONTEXT = 0, - LEGACY_CONTEXT, + LEGACY_32B_CONTEXT, ADVANCED_AD_CONTEXT, LEGACY_64B_CONTEXT }; -#define GEN8_CTX_MODE_SHIFT 3 +#define GEN8_CTX_ADDRESSING_MODE_SHIFT 3 +#define GEN8_CTX_ADDRESSING_MODE(dev) (USES_FULL_48BIT_PPGTT(dev) ?\ + LEGACY_64B_CONTEXT :\ + LEGACY_32B_CONTEXT) enum { FAULT_AND_HANG = 0, FAULT_AND_HALT, /* Debug only */ @@ -273,7 +281,7 @@ static uint64_t execlists_ctx_descriptor(struct drm_i915_gem_request *rq) WARN_ON(lrca & 0xFFFFFFFF00000FFFULL); desc = GEN8_CTX_VALID; - desc |= LEGACY_CONTEXT << GEN8_CTX_MODE_SHIFT; + desc |= GEN8_CTX_ADDRESSING_MODE(dev) << GEN8_CTX_ADDRESSING_MODE_SHIFT; if (IS_GEN8(ctx_obj->base.dev)) desc |= GEN8_CTX_L3LLC_COHERENT; desc |= GEN8_CTX_PRIVILEGE; @@ -348,10 +356,12 @@ static int execlists_update_context(struct drm_i915_gem_request *rq) reg_state[CTX_RING_TAIL+1] = rq->tail; reg_state[CTX_RING_BUFFER_START+1] = i915_gem_obj_ggtt_offset(rb_obj); - /* True PPGTT with dynamic page allocation: update PDP registers and - * point the unallocated PDPs to the scratch page - */ - if (ppgtt) { + if (ppgtt && !USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) { + /* True 32b PPGTT with dynamic page allocation: update PDP + * registers and point the unallocated PDPs to scratch page. + * PML4 is allocated during ppgtt init, so this is not needed + * in 48-bit mode. + */ ASSIGN_CTX_PDP(ppgtt, reg_state, 3); ASSIGN_CTX_PDP(ppgtt, reg_state, 2); ASSIGN_CTX_PDP(ppgtt, reg_state, 1); @@ -1515,12 +1525,15 @@ static int gen8_emit_bb_start(struct drm_i915_gem_request *req, * Ideally, we should set Force PD Restore in ctx descriptor, * but we can't. Force Restore would be a second option, but * it is unsafe in case of lite-restore (because the ctx is - * not idle). */ + * not idle). PML4 is allocated during ppgtt init so this is + * not needed in 48-bit.*/ if (req->ctx->ppgtt && (intel_ring_flag(req->ring) & req->ctx->ppgtt->pd_dirty_rings)) { - ret = intel_logical_ring_emit_pdps(req); - if (ret) - return ret; + if (!USES_FULL_48BIT_PPGTT(req->i915)) { + ret = intel_logical_ring_emit_pdps(req); + if (ret) + return ret; + } req->ctx->ppgtt->pd_dirty_rings &= ~intel_ring_flag(req->ring); } @@ -2201,13 +2214,24 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o reg_state[CTX_PDP0_UDW] = GEN8_RING_PDP_UDW(ring, 0); reg_state[CTX_PDP0_LDW] = GEN8_RING_PDP_LDW(ring, 0); - /* With dynamic page allocation, PDPs may not be allocated at this point, - * Point the unallocated PDPs to the scratch page - */ - ASSIGN_CTX_PDP(ppgtt, reg_state, 3); - ASSIGN_CTX_PDP(ppgtt, reg_state, 2); - ASSIGN_CTX_PDP(ppgtt, reg_state, 1); - ASSIGN_CTX_PDP(ppgtt, reg_state, 0); + if (USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) { + /* 64b PPGTT (48bit canonical) + * PDP0_DESCRIPTOR contains the base address to PML4 and + * other PDP Descriptors are ignored. + */ + ASSIGN_CTX_PML4(ppgtt, reg_state); + } else { + /* 32b PPGTT + * PDP*_DESCRIPTOR contains the base address of space supported. + * With dynamic page allocation, PDPs may not be allocated at + * this point. Point the unallocated PDPs to the scratch page + */ + ASSIGN_CTX_PDP(ppgtt, reg_state, 3); + ASSIGN_CTX_PDP(ppgtt, reg_state, 2); + ASSIGN_CTX_PDP(ppgtt, reg_state, 1); + ASSIGN_CTX_PDP(ppgtt, reg_state, 0); + } + if (ring->id == RCS) { reg_state[CTX_LRI_HEADER_2] = MI_LOAD_REGISTER_IMM(1); reg_state[CTX_R_PWR_CLK_STATE] = GEN8_R_PWR_CLK_STATE; -- cgit v0.10.2 From 3387d433b0bbdda53ad51016ae9d10c6c17046a0 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Mon, 3 Aug 2015 09:52:47 +0100 Subject: drm/i915/gen8: Pass sg_iter through pte inserts As a step towards implementing 4 levels, while not discarding the existing pte insert functions, we need to pass the sg_iter through. The current function understands to the page directory granularity. An object's pages may span the page directory, and so using the iter directly as we write the PTEs allows the iterator to stay coherent through a VMA insert operation spanning multiple page table levels. v2: Rebase after s/page_tables/page_table/. v3: Rebase after Mika's ppgtt cleanup / scratch merge patch series; updated commit message (s/map/insert). v4: Rebase. Reviewed-by: Akash Goel (v3) Signed-off-by: Ben Widawsky Signed-off-by: Michel Thierry (v2+) Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 2ab3cef..4080034 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -746,7 +746,7 @@ static void gen8_ppgtt_clear_range(struct i915_address_space *vm, static void gen8_ppgtt_insert_pte_entries(struct i915_address_space *vm, struct i915_page_directory_pointer *pdp, - struct sg_table *pages, + struct sg_page_iter *sg_iter, uint64_t start, enum i915_cache_level cache_level) { @@ -756,11 +756,10 @@ gen8_ppgtt_insert_pte_entries(struct i915_address_space *vm, unsigned pdpe = start >> GEN8_PDPE_SHIFT & GEN8_PDPE_MASK; unsigned pde = start >> GEN8_PDE_SHIFT & GEN8_PDE_MASK; unsigned pte = start >> GEN8_PTE_SHIFT & GEN8_PTE_MASK; - struct sg_page_iter sg_iter; pt_vaddr = NULL; - for_each_sg_page(pages->sgl, &sg_iter, pages->nents, 0) { + while (__sg_page_iter_next(sg_iter)) { if (WARN_ON(pdpe >= GEN8_LEGACY_PDPES)) break; @@ -771,7 +770,7 @@ gen8_ppgtt_insert_pte_entries(struct i915_address_space *vm, } pt_vaddr[pte] = - gen8_pte_encode(sg_page_iter_dma_address(&sg_iter), + gen8_pte_encode(sg_page_iter_dma_address(sg_iter), cache_level, true); if (++pte == GEN8_PTES) { kunmap_px(ppgtt, pt_vaddr); @@ -797,8 +796,10 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm, struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); struct i915_page_directory_pointer *pdp = &ppgtt->pdp; /* FIXME: 48b */ + struct sg_page_iter sg_iter; - gen8_ppgtt_insert_pte_entries(vm, pdp, pages, start, cache_level); + __sg_page_iter_start(&sg_iter, pages->sgl, sg_nents(pages->sgl), 0); + gen8_ppgtt_insert_pte_entries(vm, pdp, &sg_iter, start, cache_level); } static void gen8_free_page_tables(struct drm_device *dev, -- cgit v0.10.2 From de5ba8eb9cefff78ac4951bd68633d2b7a0fc5c1 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Mon, 3 Aug 2015 09:53:27 +0100 Subject: drm/i915/gen8: Add 4 level support in insert_entries and clear_range When 48b is enabled, gen8_ppgtt_insert_entries needs to read the Page Map Level 4 (PML4), before it selects which Page Directory Pointer (PDP) it will write to. Similarly, gen8_ppgtt_clear_range needs to get the correct PDP/PD range. This patch was inspired by Ben's "Depend exclusively on map and unmap_vma". v2: Rebase after s/page_tables/page_table/. v3: Remove unnecessary pdpe loop in gen8_ppgtt_clear_range_4lvl and use clamp_pdp in gen8_ppgtt_insert_entries (Akash). v4: Merge gen8_ppgtt_clear_range_4lvl into gen8_ppgtt_clear_range to maintain symmetry with gen8_ppgtt_insert_entries (Akash). v5: Do not mix pages and bytes in insert_entries (Akash). v6: Prevent overflow in sg_nents << PAGE_SHIFT, when inserting 4GB at once. v7: Rebase after Mika's ppgtt cleanup / scratch merge patch series. Use gen8_px_index functions, and remove unnecessary number of pages parameter in insert_pte_entries. v8: Change gen8_ppgtt_clear_pte_range to stop at PDP boundary, instead of adding and extra clamp function; remove unnecessary pdp_start/pdp_len variables (Akash). v9: pages->orig_nents instead of sg_nents(pages->sgl) to get the length (Akash). v10: Remove pdp warning check ingen8_ppgtt_insert_pte_entries until this commit (Akash). Reviewed-by: Akash Goel (v9) Cc: Akash Goel Signed-off-by: Michel Thierry Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 4080034..032801e 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -681,9 +681,9 @@ static void gen8_ppgtt_clear_pte_range(struct i915_address_space *vm, struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); gen8_pte_t *pt_vaddr; - unsigned pdpe = start >> GEN8_PDPE_SHIFT & GEN8_PDPE_MASK; - unsigned pde = start >> GEN8_PDE_SHIFT & GEN8_PDE_MASK; - unsigned pte = start >> GEN8_PTE_SHIFT & GEN8_PTE_MASK; + unsigned pdpe = gen8_pdpe_index(start); + unsigned pde = gen8_pde_index(start); + unsigned pte = gen8_pte_index(start); unsigned num_entries = length >> PAGE_SHIFT; unsigned last_pte, i; @@ -722,7 +722,8 @@ static void gen8_ppgtt_clear_pte_range(struct i915_address_space *vm, pte = 0; if (++pde == I915_PDES) { - pdpe++; + if (++pdpe == I915_PDPES_PER_PDP(vm->dev)) + break; pde = 0; } } @@ -735,12 +736,21 @@ static void gen8_ppgtt_clear_range(struct i915_address_space *vm, { struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); - struct i915_page_directory_pointer *pdp = &ppgtt->pdp; /* FIXME: 48b */ - gen8_pte_t scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page), I915_CACHE_LLC, use_scratch); - gen8_ppgtt_clear_pte_range(vm, pdp, start, length, scratch_pte); + if (!USES_FULL_48BIT_PPGTT(vm->dev)) { + gen8_ppgtt_clear_pte_range(vm, &ppgtt->pdp, start, length, + scratch_pte); + } else { + uint64_t templ4, pml4e; + struct i915_page_directory_pointer *pdp; + + gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, templ4, pml4e) { + gen8_ppgtt_clear_pte_range(vm, pdp, start, length, + scratch_pte); + } + } } static void @@ -753,16 +763,13 @@ gen8_ppgtt_insert_pte_entries(struct i915_address_space *vm, struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); gen8_pte_t *pt_vaddr; - unsigned pdpe = start >> GEN8_PDPE_SHIFT & GEN8_PDPE_MASK; - unsigned pde = start >> GEN8_PDE_SHIFT & GEN8_PDE_MASK; - unsigned pte = start >> GEN8_PTE_SHIFT & GEN8_PTE_MASK; + unsigned pdpe = gen8_pdpe_index(start); + unsigned pde = gen8_pde_index(start); + unsigned pte = gen8_pte_index(start); pt_vaddr = NULL; while (__sg_page_iter_next(sg_iter)) { - if (WARN_ON(pdpe >= GEN8_LEGACY_PDPES)) - break; - if (pt_vaddr == NULL) { struct i915_page_directory *pd = pdp->page_directory[pdpe]; struct i915_page_table *pt = pd->page_table[pde]; @@ -776,7 +783,8 @@ gen8_ppgtt_insert_pte_entries(struct i915_address_space *vm, kunmap_px(ppgtt, pt_vaddr); pt_vaddr = NULL; if (++pde == I915_PDES) { - pdpe++; + if (++pdpe == I915_PDPES_PER_PDP(vm->dev)) + break; pde = 0; } pte = 0; @@ -795,11 +803,23 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm, { struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); - struct i915_page_directory_pointer *pdp = &ppgtt->pdp; /* FIXME: 48b */ struct sg_page_iter sg_iter; __sg_page_iter_start(&sg_iter, pages->sgl, sg_nents(pages->sgl), 0); - gen8_ppgtt_insert_pte_entries(vm, pdp, &sg_iter, start, cache_level); + + if (!USES_FULL_48BIT_PPGTT(vm->dev)) { + gen8_ppgtt_insert_pte_entries(vm, &ppgtt->pdp, &sg_iter, start, + cache_level); + } else { + struct i915_page_directory_pointer *pdp; + uint64_t templ4, pml4e; + uint64_t length = (uint64_t)pages->orig_nents << PAGE_SHIFT; + + gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, templ4, pml4e) { + gen8_ppgtt_insert_pte_entries(vm, pdp, &sg_iter, + start, cache_level); + } + } } static void gen8_free_page_tables(struct drm_device *dev, -- cgit v0.10.2 From 69ab76fd3d497816992b22dd201d2327cb921c94 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 29 Jul 2015 17:23:55 +0100 Subject: drm/i915/gen8: Initialize PDPs and PML4 Similar to PDs, while setting up a page directory pointer, make all entries of the pdp point to the scratch pd before mapping (and make all its entries point to the scratch page); this is to be safe in case of out of bound access or proactive prefetch. Also add a scratch pdp, which the PML4 entries point to. v2: Handle scratch_pdp allocation failure correctly, and keep initialize_px functions together (Akash) v3: Rebase after Mika's ppgtt cleanup / scratch merge patch series. Rely on the added macros to initialize the pdps. v4: Rebase after final merged version of Mika's ppgtt/scratch patches (and removed commit message part related to v3). v5: Update commit message to also mention PML4 table initialization and the new scratch pdp (Akash). Suggested-by: Akash Goel Signed-off-by: Michel Thierry Reviewed-by: Akash Goel Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 032801e..a4bdef3 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -596,6 +596,27 @@ static void free_pdp(struct drm_device *dev, } } +static void gen8_initialize_pdp(struct i915_address_space *vm, + struct i915_page_directory_pointer *pdp) +{ + gen8_ppgtt_pdpe_t scratch_pdpe; + + scratch_pdpe = gen8_pdpe_encode(px_dma(vm->scratch_pd), I915_CACHE_LLC); + + fill_px(vm->dev, pdp, scratch_pdpe); +} + +static void gen8_initialize_pml4(struct i915_address_space *vm, + struct i915_pml4 *pml4) +{ + gen8_ppgtt_pml4e_t scratch_pml4e; + + scratch_pml4e = gen8_pml4e_encode(px_dma(vm->scratch_pdp), + I915_CACHE_LLC); + + fill_px(vm->dev, pml4, scratch_pml4e); +} + static void gen8_setup_page_directory(struct i915_hw_ppgtt *ppgtt, struct i915_page_directory_pointer *pdp, @@ -860,8 +881,20 @@ static int gen8_init_scratch(struct i915_address_space *vm) return PTR_ERR(vm->scratch_pd); } + if (USES_FULL_48BIT_PPGTT(dev)) { + vm->scratch_pdp = alloc_pdp(dev); + if (IS_ERR(vm->scratch_pdp)) { + free_pd(dev, vm->scratch_pd); + free_pt(dev, vm->scratch_pt); + free_scratch_page(dev, vm->scratch_page); + return PTR_ERR(vm->scratch_pdp); + } + } + gen8_initialize_pt(vm, vm->scratch_pt); gen8_initialize_pd(vm, vm->scratch_pd); + if (USES_FULL_48BIT_PPGTT(dev)) + gen8_initialize_pdp(vm, vm->scratch_pdp); return 0; } @@ -870,6 +903,8 @@ static void gen8_free_scratch(struct i915_address_space *vm) { struct drm_device *dev = vm->dev; + if (USES_FULL_48BIT_PPGTT(dev)) + free_pdp(dev, vm->scratch_pdp); free_pd(dev, vm->scratch_pd); free_pt(dev, vm->scratch_pt); free_scratch_page(dev, vm->scratch_page); @@ -1071,6 +1106,7 @@ gen8_ppgtt_alloc_page_dirpointers(struct i915_address_space *vm, if (IS_ERR(pdp)) goto unwind_out; + gen8_initialize_pdp(vm, pdp); pml4->pdps[pml4e] = pdp; __set_bit(pml4e, new_pdps); trace_i915_page_directory_pointer_entry_alloc(vm, @@ -1350,6 +1386,8 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) if (ret) goto free_scratch; + gen8_initialize_pml4(&ppgtt->base, &ppgtt->pml4); + ppgtt->base.total = 1ULL << 48; ppgtt->switch_mm = gen8_48b_mm_switch; } else { diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 11d44b3..70c50e7 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -278,6 +278,7 @@ struct i915_address_space { struct i915_page_scratch *scratch_page; struct i915_page_table *scratch_pt; struct i915_page_directory *scratch_pd; + struct i915_page_directory_pointer *scratch_pdp; /* GEN8+ & 48b PPGTT */ /** * List of objects currently involved in rendering. -- cgit v0.10.2 From e1f123257a1f7d3af36a31a0fb2d4c6f40039fed Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 29 Jul 2015 17:23:56 +0100 Subject: drm/i915: Expand error state's address width to 64b v2: For semaphore errors, object is mapped to GGTT and offset will not be > 4GB, print only lower 32-bits (Akash) v3: Print gtt_offset in groups of 32-bit (Chris) Cc: Akash Goel Cc: Chris Wilson Signed-off-by: Ben Widawsky Signed-off-by: Michel Thierry Reviewed-by: Akash Goel Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 79d2dcb..91bd778 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -547,7 +547,7 @@ struct drm_i915_error_state { struct drm_i915_error_object { int page_count; - u32 gtt_offset; + u64 gtt_offset; u32 *pages[0]; } *ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page; @@ -573,7 +573,7 @@ struct drm_i915_error_state { u32 size; u32 name; u32 rseqno[I915_NUM_RINGS], wseqno; - u32 gtt_offset; + u64 gtt_offset; u32 read_domains; u32 write_domain; s32 fence_reg:I915_MAX_NUM_FENCE_BITS; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 41d0739..0d0a7b1 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -197,8 +197,9 @@ static void print_error_buffers(struct drm_i915_error_state_buf *m, err_printf(m, " %s [%d]:\n", name, count); while (count--) { - err_printf(m, " %08x %8u %02x %02x [ ", - err->gtt_offset, + err_printf(m, " %08x_%08x %8u %02x %02x [ ", + upper_32_bits(err->gtt_offset), + lower_32_bits(err->gtt_offset), err->size, err->read_domains, err->write_domain); @@ -427,15 +428,17 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, err_printf(m, " (submitted by %s [%d])", error->ring[i].comm, error->ring[i].pid); - err_printf(m, " --- gtt_offset = 0x%08x\n", - obj->gtt_offset); + err_printf(m, " --- gtt_offset = 0x%08x %08x\n", + upper_32_bits(obj->gtt_offset), + lower_32_bits(obj->gtt_offset)); print_error_obj(m, obj); } obj = error->ring[i].wa_batchbuffer; if (obj) { err_printf(m, "%s (w/a) --- gtt_offset = 0x%08x\n", - dev_priv->ring[i].name, obj->gtt_offset); + dev_priv->ring[i].name, + lower_32_bits(obj->gtt_offset)); print_error_obj(m, obj); } @@ -454,14 +457,14 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, if ((obj = error->ring[i].ringbuffer)) { err_printf(m, "%s --- ringbuffer = 0x%08x\n", dev_priv->ring[i].name, - obj->gtt_offset); + lower_32_bits(obj->gtt_offset)); print_error_obj(m, obj); } if ((obj = error->ring[i].hws_page)) { err_printf(m, "%s --- HW Status = 0x%08x\n", dev_priv->ring[i].name, - obj->gtt_offset); + lower_32_bits(obj->gtt_offset)); offset = 0; for (elt = 0; elt < PAGE_SIZE/16; elt += 4) { err_printf(m, "[%04x] %08x %08x %08x %08x\n", @@ -477,13 +480,14 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, if ((obj = error->ring[i].ctx)) { err_printf(m, "%s --- HW Context = 0x%08x\n", dev_priv->ring[i].name, - obj->gtt_offset); + lower_32_bits(obj->gtt_offset)); print_error_obj(m, obj); } } if ((obj = error->semaphore_obj)) { - err_printf(m, "Semaphore page = 0x%08x\n", obj->gtt_offset); + err_printf(m, "Semaphore page = 0x%08x\n", + lower_32_bits(obj->gtt_offset)); for (elt = 0; elt < PAGE_SIZE/16; elt += 4) { err_printf(m, "[%04x] %08x %08x %08x %08x\n", elt * 4, @@ -591,7 +595,7 @@ i915_error_object_create(struct drm_i915_private *dev_priv, int num_pages; bool use_ggtt; int i = 0; - u32 reloc_offset; + u64 reloc_offset; if (src == NULL || src->pages == NULL) return NULL; -- cgit v0.10.2 From ea91e401501a72597554cb5c080fe5671a6ccb84 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 29 Jul 2015 17:23:57 +0100 Subject: drm/i915/gen8: Add ppgtt info and debug_dump v2: Clean up patch after rebases. v3: gen8_dump_ppgtt for 32b and 48b PPGTT. v4: Use used_pml4es/pdpes (Akash). v5: Rebase after Mika's ppgtt cleanup / scratch merge patch series. v6: Rely on used_px bits instead of null checking (Akash) Cc: Akash Goel Signed-off-by: Ben Widawsky Signed-off-by: Michel Thierry (v2+) Reviewed-by: Akash Goel Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index d1c643a..95e7b82 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2250,7 +2250,6 @@ static void gen6_ppgtt_info(struct seq_file *m, struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *ring; - struct drm_file *file; int i; if (INTEL_INFO(dev)->gen == 6) @@ -2273,13 +2272,6 @@ static void gen6_ppgtt_info(struct seq_file *m, struct drm_device *dev) ppgtt->debug_dump(ppgtt, m); } - list_for_each_entry_reverse(file, &dev->filelist, lhead) { - struct drm_i915_file_private *file_priv = file->driver_priv; - - seq_printf(m, "proc: %s\n", - get_pid_task(file->pid, PIDTYPE_PID)->comm); - idr_for_each(&file_priv->context_idr, per_file_ctx, m); - } seq_printf(m, "ECOCHK: 0x%08x\n", I915_READ(GAM_ECOCHK)); } @@ -2288,6 +2280,7 @@ static int i915_ppgtt_info(struct seq_file *m, void *data) struct drm_info_node *node = m->private; struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_file *file; int ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) @@ -2299,6 +2292,15 @@ static int i915_ppgtt_info(struct seq_file *m, void *data) else if (INTEL_INFO(dev)->gen >= 6) gen6_ppgtt_info(m, dev); + list_for_each_entry_reverse(file, &dev->filelist, lhead) { + struct drm_i915_file_private *file_priv = file->driver_priv; + + seq_printf(m, "\nproc: %s\n", + get_pid_task(file->pid, PIDTYPE_PID)->comm); + idr_for_each(&file_priv->context_idr, per_file_ctx, + (void *)(unsigned long)m); + } + intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index a4bdef3..38439fa 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1358,6 +1358,89 @@ static int gen8_alloc_va_range(struct i915_address_space *vm, return gen8_alloc_va_range_3lvl(vm, &ppgtt->pdp, start, length); } +static void gen8_dump_pdp(struct i915_page_directory_pointer *pdp, + uint64_t start, uint64_t length, + gen8_pte_t scratch_pte, + struct seq_file *m) +{ + struct i915_page_directory *pd; + uint64_t temp; + uint32_t pdpe; + + gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) { + struct i915_page_table *pt; + uint64_t pd_len = length; + uint64_t pd_start = start; + uint32_t pde; + + if (!test_bit(pdpe, pdp->used_pdpes)) + continue; + + seq_printf(m, "\tPDPE #%d\n", pdpe); + gen8_for_each_pde(pt, pd, pd_start, pd_len, temp, pde) { + uint32_t pte; + gen8_pte_t *pt_vaddr; + + if (!test_bit(pde, pd->used_pdes)) + continue; + + pt_vaddr = kmap_px(pt); + for (pte = 0; pte < GEN8_PTES; pte += 4) { + uint64_t va = + (pdpe << GEN8_PDPE_SHIFT) | + (pde << GEN8_PDE_SHIFT) | + (pte << GEN8_PTE_SHIFT); + int i; + bool found = false; + + for (i = 0; i < 4; i++) + if (pt_vaddr[pte + i] != scratch_pte) + found = true; + if (!found) + continue; + + seq_printf(m, "\t\t0x%llx [%03d,%03d,%04d]: =", va, pdpe, pde, pte); + for (i = 0; i < 4; i++) { + if (pt_vaddr[pte + i] != scratch_pte) + seq_printf(m, " %llx", pt_vaddr[pte + i]); + else + seq_puts(m, " SCRATCH "); + } + seq_puts(m, "\n"); + } + /* don't use kunmap_px, it could trigger + * an unnecessary flush. + */ + kunmap_atomic(pt_vaddr); + } + } +} + +static void gen8_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m) +{ + struct i915_address_space *vm = &ppgtt->base; + uint64_t start = ppgtt->base.start; + uint64_t length = ppgtt->base.total; + gen8_pte_t scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page), + I915_CACHE_LLC, true); + + if (!USES_FULL_48BIT_PPGTT(vm->dev)) { + gen8_dump_pdp(&ppgtt->pdp, start, length, scratch_pte, m); + } else { + uint64_t templ4, pml4e; + struct i915_pml4 *pml4 = &ppgtt->pml4; + struct i915_page_directory_pointer *pdp; + + gen8_for_each_pml4e(pdp, pml4, start, length, templ4, pml4e) { + if (!test_bit(pml4e, pml4->used_pml4es)) + continue; + + seq_printf(m, " PML4E #%llu\n", pml4e); + gen8_dump_pdp(pdp, start, length, scratch_pte, m); + } + } +} + /* * GEN8 legacy ppgtt programming is accomplished through a max 4 PDP registers * with a net effect resembling a 2-level page table in normal x86 terms. Each @@ -1380,6 +1463,7 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) ppgtt->base.clear_range = gen8_ppgtt_clear_range; ppgtt->base.unbind_vma = ppgtt_unbind_vma; ppgtt->base.bind_vma = ppgtt_bind_vma; + ppgtt->debug_dump = gen8_dump_ppgtt; if (USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) { ret = setup_px(ppgtt->base.dev, &ppgtt->pml4); -- cgit v0.10.2 From 65bd342ff2f1f9f3ca4a17691a825935d2aa13c9 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 29 Jul 2015 17:23:58 +0100 Subject: drm/i915: object size needs to be u64 In a 48b world, users can try to allocate buffers bigger than 4GB; in these cases it is important that size is a 64b variable. v2: Drop the warning about bind with size 0, it shouldn't happen anyway. Signed-off-by: Michel Thierry Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 84f91bc..73293b4 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3355,7 +3355,8 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, { struct drm_device *dev = obj->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - u32 size, fence_size, fence_alignment, unfenced_alignment; + u32 fence_alignment, unfenced_alignment; + u64 size, fence_size; u64 start = flags & PIN_OFFSET_BIAS ? flags & PIN_OFFSET_MASK : 0; u64 end = @@ -3414,7 +3415,7 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, * attempt to find space. */ if (size > end) { - DRM_DEBUG("Attempting to bind an object (view type=%u) larger than the aperture: size=%u > %s aperture=%llu\n", + DRM_DEBUG("Attempting to bind an object (view type=%u) larger than the aperture: size=%llu > %s aperture=%llu\n", ggtt_view ? ggtt_view->type : 0, size, flags & PIN_MAPPABLE ? "mappable" : "total", -- cgit v0.10.2 From af98714e5d05fcbf7638ea4b53d158d96d693bf2 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 29 Jul 2015 17:23:59 +0100 Subject: drm/i915: batch_obj vm offset must be u64 Otherwise it can overflow in 48-bit mode, and cause an incorrect exec_start. Before commit 5f19e2bffa63a91cd4ac1adcec648e14a44277ce ("drm/i915: Merged the many do_execbuf() parameters into a structure"), it was already an u64. Signed-off-by: Michel Thierry Reviewed-by: Akash Goel Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 91bd778..cefb6e9 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1686,7 +1686,7 @@ struct i915_execbuffer_params { struct drm_file *file; uint32_t dispatch_flags; uint32_t args_batch_start_offset; - uint32_t batch_obj_vm_offset; + uint64_t batch_obj_vm_offset; struct intel_engine_cs *ring; struct drm_i915_gem_object *batch_obj; struct intel_context *ctx; -- cgit v0.10.2 From c6d576cc576196593671eabc8aad6c1744b32568 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 29 Jul 2015 17:24:00 +0100 Subject: drm/i915/userptr: Kill user_size limit check GTT was only 32b and its max value is 4GB. In order to allow objects bigger than 4GB in 48b PPGTT, i915_gem_userptr_ioctl we could check against max 48b range (1ULL << 48). But since the check no longer applies, just kill the limit. v2: Use the default ctx to infer the ppgtt max size (Akash). v3: Just kill the limit, it was only there for early detection of an error when used for execbuffer (Chris). Cc: Akash Goel Reviewed-by: Chris Wilson Signed-off-by: Michel Thierry Reviewed-by: Akash Goel Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index 8fd431b..d11901d 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -813,7 +813,6 @@ static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = { int i915_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { - struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_userptr *args = data; struct drm_i915_gem_object *obj; int ret; @@ -826,9 +825,6 @@ i915_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *file if (offset_in_page(args->user_ptr | args->user_size)) return -EINVAL; - if (args->user_size > dev_priv->gtt.base.total) - return -E2BIG; - if (!access_ok(args->flags & I915_USERPTR_READ_ONLY ? VERIFY_READ : VERIFY_WRITE, (char __user *)(unsigned long)args->user_ptr, args->user_size)) return -EFAULT; -- cgit v0.10.2 From e5a1cab5e57d7bd6ef77502f950cfab6e14d92a8 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 23 Jul 2015 16:35:48 -0700 Subject: drm/i915: Force sink crc stop before start. By Vesa DP spec, test counter at DP_TEST_SINK_MISC just reset to 0 when unsetting DP_TEST_SINK_START, so let's force this stop here. But let's minimize the aux transactions and just do it when we know it hasn't been properly stoped. Signed-off-by: Rodrigo Vivi Reviewed-by: Rafael Antognolli Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 016e7bc..1f7cc40 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3995,22 +3995,30 @@ intel_dp_probe_mst(struct intel_dp *intel_dp) return intel_dp->is_mst; } -static void intel_dp_sink_crc_stop(struct intel_dp *intel_dp) +static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc); u8 buf; + int ret = 0; if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK, &buf) < 0) { DRM_DEBUG_KMS("Sink CRC couldn't be stopped properly\n"); - return; + ret = -EIO; + goto out; } if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_SINK, - buf & ~DP_TEST_SINK_START) < 0) + buf & ~DP_TEST_SINK_START) < 0) { DRM_DEBUG_KMS("Sink CRC couldn't be stopped properly\n"); + ret = -EIO; + goto out; + } + intel_dp->sink_crc_started = false; + out: hsw_enable_ips(intel_crtc); + return ret; } static int intel_dp_sink_crc_start(struct intel_dp *intel_dp) @@ -4018,6 +4026,13 @@ static int intel_dp_sink_crc_start(struct intel_dp *intel_dp) struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc); u8 buf; + int ret; + + if (intel_dp->sink_crc_started) { + ret = intel_dp_sink_crc_stop(intel_dp); + if (ret) + return ret; + } if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, &buf) < 0) return -EIO; @@ -4036,6 +4051,7 @@ static int intel_dp_sink_crc_start(struct intel_dp *intel_dp) return -EIO; } + intel_dp->sink_crc_started = true; return 0; } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index e31b95b..8858bb1 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -713,6 +713,7 @@ struct intel_dp { /* sink rates as reported by DP_SUPPORTED_LINK_RATES */ uint8_t num_sink_rates; int sink_rates[DP_MAX_SUPPORTED_RATES]; + bool sink_crc_started; struct drm_dp_aux aux; uint8_t train_set[4]; int panel_power_up_delay; -- cgit v0.10.2 From 621d4c76fd4ce7f648fa59a26e3eb6b2346cf873 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 23 Jul 2015 16:35:49 -0700 Subject: drm/i915: Save latest known sink CRC to compensate delayed counter reset. By Vesa DP 1.2 Spec TEST_CRC_COUNT should be "reset to 0 when TEST_SINK bit 0 = 0." However for some strange reason when PSR is enabled in certain platforms this is not true. At least not immediatelly. So we face cases like this: first get_sink_crc operation: count: 0, crc: 000000000000 count: 1, crc: c101c101c101 returned expected crc: c101c101c101 secont get_sink_crc operation: count: 1, crc: c101c101c101 count: 0, crc: 000000000000 count: 1, crc: 0000c1010000 should return expected crc: 0000c1010000 But also the reset to 0 should be faster resulting into: get_sink_crc operation: count: 1, crc: c101c101c101 count: 1, crc: 0000c1010000 should return expected crc: 0000c1010000 So in order to know that the second one is valid one we need to compare the pair (count, crc) with latest (count, crc). If the pair changed you have your valid CRC. Signed-off-by: Rodrigo Vivi Reviewed-by: Rafael Antognolli Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1f7cc40..abcc2a3 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4015,7 +4015,7 @@ static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp) goto out; } - intel_dp->sink_crc_started = false; + intel_dp->sink_crc.started = false; out: hsw_enable_ips(intel_crtc); return ret; @@ -4028,7 +4028,7 @@ static int intel_dp_sink_crc_start(struct intel_dp *intel_dp) u8 buf; int ret; - if (intel_dp->sink_crc_started) { + if (intel_dp->sink_crc.started) { ret = intel_dp_sink_crc_stop(intel_dp); if (ret) return ret; @@ -4040,6 +4040,8 @@ static int intel_dp_sink_crc_start(struct intel_dp *intel_dp) if (!(buf & DP_TEST_CRC_SUPPORTED)) return -ENOTTY; + intel_dp->sink_crc.last_count = buf & DP_TEST_COUNT_MASK; + if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK, &buf) < 0) return -EIO; @@ -4051,7 +4053,7 @@ static int intel_dp_sink_crc_start(struct intel_dp *intel_dp) return -EIO; } - intel_dp->sink_crc_started = true; + intel_dp->sink_crc.started = true; return 0; } @@ -4061,29 +4063,39 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc) struct drm_device *dev = dig_port->base.base.dev; struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc); u8 buf; - int test_crc_count; + int count, ret; int attempts = 6; - int ret; ret = intel_dp_sink_crc_start(intel_dp); if (ret) return ret; - if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, &buf) < 0) { - ret = -EIO; - goto stop; - } - - test_crc_count = buf & DP_TEST_COUNT_MASK; - do { + intel_wait_for_vblank(dev, intel_crtc->pipe); + if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, &buf) < 0) { ret = -EIO; goto stop; } - intel_wait_for_vblank(dev, intel_crtc->pipe); - } while (--attempts && (buf & DP_TEST_COUNT_MASK) == test_crc_count); + count = buf & DP_TEST_COUNT_MASK; + /* + * Count might be reset during the loop. In this case + * last known count needs to be reset as well. + */ + if (count == 0) + intel_dp->sink_crc.last_count = 0; + + if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR, crc, 6) < 0) { + ret = -EIO; + goto stop; + } + } while (--attempts && (count == 0 || (count == intel_dp->sink_crc.last_count && + !memcmp(intel_dp->sink_crc.last_crc, crc, + 6 * sizeof(u8))))); + + intel_dp->sink_crc.last_count = buf & DP_TEST_COUNT_MASK; + memcpy(intel_dp->sink_crc.last_crc, crc, 6 * sizeof(u8)); if (attempts == 0) { DRM_DEBUG_KMS("Panel is unable to calculate CRC after 6 vblanks\n"); @@ -4091,8 +4103,6 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc) goto stop; } - if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR, crc, 6) < 0) - ret = -EIO; stop: intel_dp_sink_crc_stop(intel_dp); return ret; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8858bb1..6b3e2c6 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -696,6 +696,12 @@ enum link_m_n_set { M2_N2 }; +struct sink_crc { + bool started; + u8 last_crc[6]; + int last_count; +}; + struct intel_dp { uint32_t output_reg; uint32_t aux_ch_ctl_reg; @@ -713,7 +719,7 @@ struct intel_dp { /* sink rates as reported by DP_SUPPORTED_LINK_RATES */ uint8_t num_sink_rates; int sink_rates[DP_MAX_SUPPORTED_RATES]; - bool sink_crc_started; + struct sink_crc sink_crc; struct drm_dp_aux aux; uint8_t train_set[4]; int panel_power_up_delay; -- cgit v0.10.2 From aabc95dcf200908993573b2019ff5210121bcba9 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 23 Jul 2015 16:35:50 -0700 Subject: drm/i915: Dont -ETIMEDOUT on identical new and previous (count, crc). By Vesa DP 1.2 spec TEST_CRC_COUNT is a "4 bit wrap counter which increments each time the TEST_CRC_x_x are updated." However if we are trying to verify the screen hasn't changed we get same (count, crc) pair twice. Without this patch we would return -ETIMEOUT in this case. So, if in 6 vblanks the pair (count, crc) hasn't changed we return it anyway instead of returning error and let test case decide if it was right or not. Signed-off-by: Rodrigo Vivi Reviewed-by: Rafael Antognolli Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index abcc2a3..54e9b53 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4065,6 +4065,7 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc) u8 buf; int count, ret; int attempts = 6; + bool old_equal_new; ret = intel_dp_sink_crc_start(intel_dp); if (ret) @@ -4079,6 +4080,7 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc) goto stop; } count = buf & DP_TEST_COUNT_MASK; + /* * Count might be reset during the loop. In this case * last known count needs to be reset as well. @@ -4090,17 +4092,24 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc) ret = -EIO; goto stop; } - } while (--attempts && (count == 0 || (count == intel_dp->sink_crc.last_count && - !memcmp(intel_dp->sink_crc.last_crc, crc, - 6 * sizeof(u8))))); + + old_equal_new = (count == intel_dp->sink_crc.last_count && + !memcmp(intel_dp->sink_crc.last_crc, crc, + 6 * sizeof(u8))); + + } while (--attempts && (count == 0 || old_equal_new)); intel_dp->sink_crc.last_count = buf & DP_TEST_COUNT_MASK; memcpy(intel_dp->sink_crc.last_crc, crc, 6 * sizeof(u8)); if (attempts == 0) { - DRM_DEBUG_KMS("Panel is unable to calculate CRC after 6 vblanks\n"); - ret = -ETIMEDOUT; - goto stop; + if (old_equal_new) { + DRM_DEBUG_KMS("Unreliable Sink CRC counter: Current returned CRC is identical to the previous one\n"); + } else { + DRM_ERROR("Panel is unable to calculate any CRC after 6 vblanks\n"); + ret = -ETIMEDOUT; + goto stop; + } } stop: -- cgit v0.10.2 From 088e0df4020e30c4952f29dc672ceb4742b98e73 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Fri, 7 Aug 2015 17:40:17 +0100 Subject: drm/i915/gtt: Allow >= 4GB offsets in X86_32 Similar to commit c44ef60e437019b8ca1dab8b4d2e8761fd4ce1e9 ("drm/i915/gtt: Allow >= 4GB sizes for vm"), i915_gem_obj_offset and i915_gem_obj_ggtt_offset return an unsigned long, which in only 4-bytes long in 32-bit kernels. Change return type (and other related offset variables) to u64. Since Global GTT is always limited to 4GB, this change would not be required in i915_gem_obj_ggtt_offset, but this is done for consistency. v2: Remove unnecessary offset variable in do_pin, as we already have vma->node.start (Chris). Update GGTT offset too (Tvrtko). Cc: Chris Wilson Cc: Daniel Vetter Cc: Tvrtko Ursulin Signed-off-by: Michel Thierry Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index cefb6e9..6b85338 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2977,13 +2977,11 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev, struct dma_buf *i915_gem_prime_export(struct drm_device *dev, struct drm_gem_object *gem_obj, int flags); -unsigned long -i915_gem_obj_ggtt_offset_view(struct drm_i915_gem_object *o, - const struct i915_ggtt_view *view); -unsigned long -i915_gem_obj_offset(struct drm_i915_gem_object *o, - struct i915_address_space *vm); -static inline unsigned long +u64 i915_gem_obj_ggtt_offset_view(struct drm_i915_gem_object *o, + const struct i915_ggtt_view *view); +u64 i915_gem_obj_offset(struct drm_i915_gem_object *o, + struct i915_address_space *vm); +static inline u64 i915_gem_obj_ggtt_offset(struct drm_i915_gem_object *o) { return i915_gem_obj_ggtt_offset_view(o, &i915_ggtt_view_normal); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 73293b4..6d0f834 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4012,15 +4012,13 @@ i915_gem_object_do_pin(struct drm_i915_gem_object *obj, return -EBUSY; if (i915_vma_misplaced(vma, alignment, flags)) { - unsigned long offset; - offset = ggtt_view ? i915_gem_obj_ggtt_offset_view(obj, ggtt_view) : - i915_gem_obj_offset(obj, vm); WARN(vma->pin_count, "bo is already pinned in %s with incorrect alignment:" - " offset=%lx, req.alignment=%x, req.map_and_fenceable=%d," + " offset=%08x %08x, req.alignment=%x, req.map_and_fenceable=%d," " obj->map_and_fenceable=%d\n", ggtt_view ? "ggtt" : "ppgtt", - offset, + upper_32_bits(vma->node.start), + lower_32_bits(vma->node.start), alignment, !!(flags & PIN_MAPPABLE), obj->map_and_fenceable); @@ -4975,9 +4973,8 @@ void i915_gem_track_fb(struct drm_i915_gem_object *old, } /* All the new VM stuff */ -unsigned long -i915_gem_obj_offset(struct drm_i915_gem_object *o, - struct i915_address_space *vm) +u64 i915_gem_obj_offset(struct drm_i915_gem_object *o, + struct i915_address_space *vm) { struct drm_i915_private *dev_priv = o->base.dev->dev_private; struct i915_vma *vma; @@ -4997,9 +4994,8 @@ i915_gem_obj_offset(struct drm_i915_gem_object *o, return -1; } -unsigned long -i915_gem_obj_ggtt_offset_view(struct drm_i915_gem_object *o, - const struct i915_ggtt_view *view) +u64 i915_gem_obj_ggtt_offset_view(struct drm_i915_gem_object *o, + const struct i915_ggtt_view *view) { struct i915_address_space *ggtt = i915_obj_to_ggtt(o); struct i915_vma *vma; diff --git a/drivers/gpu/drm/i915/i915_gem_fence.c b/drivers/gpu/drm/i915/i915_gem_fence.c index af1f8c4..6077dff 100644 --- a/drivers/gpu/drm/i915/i915_gem_fence.c +++ b/drivers/gpu/drm/i915/i915_gem_fence.c @@ -128,7 +128,7 @@ static void i915_write_fence_reg(struct drm_device *dev, int reg, WARN((i915_gem_obj_ggtt_offset(obj) & ~I915_FENCE_START_MASK) || (size & -size) != size || (i915_gem_obj_ggtt_offset(obj) & (size - 1)), - "object 0x%08lx [fenceable? %d] not 1M or pot-size (0x%08x) aligned\n", + "object 0x%08llx [fenceable? %d] not 1M or pot-size (0x%08x) aligned\n", i915_gem_obj_ggtt_offset(obj), obj->map_and_fenceable, size); if (obj->tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev)) @@ -171,7 +171,7 @@ static void i830_write_fence_reg(struct drm_device *dev, int reg, WARN((i915_gem_obj_ggtt_offset(obj) & ~I830_FENCE_START_MASK) || (size & -size) != size || (i915_gem_obj_ggtt_offset(obj) & (size - 1)), - "object 0x%08lx not 512K or pot-size 0x%08x aligned\n", + "object 0x%08llx not 512K or pot-size 0x%08x aligned\n", i915_gem_obj_ggtt_offset(obj), size); pitch_val = obj->stride / 128; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 38439fa..7a89e97 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2543,9 +2543,9 @@ static void i915_gtt_color_adjust(struct drm_mm_node *node, } static int i915_gem_setup_global_gtt(struct drm_device *dev, - unsigned long start, - unsigned long mappable_end, - unsigned long end) + u64 start, + u64 mappable_end, + u64 end) { /* Let GEM Manage all of the aperture. * @@ -2584,7 +2584,7 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev, list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { struct i915_vma *vma = i915_gem_obj_to_vma(obj, ggtt_vm); - DRM_DEBUG_KMS("reserving preallocated space: %lx + %zx\n", + DRM_DEBUG_KMS("reserving preallocated space: %llx + %zx\n", i915_gem_obj_ggtt_offset(obj), obj->base.size); WARN_ON(i915_gem_obj_ggtt_bound(obj)); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 70c50e7..8275007 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -149,7 +149,7 @@ struct i915_ggtt_view { union { struct { - unsigned long offset; + u64 offset; unsigned int size; } partial; } params; diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 7eff33f..6c9351b 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -295,7 +295,7 @@ static int intelfb_create(struct drm_fb_helper *helper, /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ - DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08lx, bo %p\n", + DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08llx, bo %p\n", fb->width, fb->height, i915_gem_obj_ggtt_offset(obj), obj); -- cgit v0.10.2 From f365f91181ce862181d0d2f4fb3ca0fe2276874b Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Fri, 7 Aug 2015 17:40:18 +0100 Subject: drm/i915: Use complete virtual address range on 32-bit platforms With the offset length being taken care of in ("drm/i915/gtt: Allow >= 4GB offsets in X86_32"), the code should be finally safe in 32-bit kernels. This reverts commit 501fd70fcaebc911b6b96a7b331e6960e5af67e7 Author: Michel Thierry Date: Fri May 29 14:15:05 2015 +0100 drm/i915: limit PPGTT size to 2GB in 32-bit platforms Signed-off-by: Michel Thierry Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 7a89e97..8fda1fb 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1480,14 +1480,6 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) goto free_scratch; ppgtt->base.total = 1ULL << 32; - if (IS_ENABLED(CONFIG_X86_32)) - /* While we have a proliferation of size_t variables - * we cannot represent the full ppgtt size on 32bit, - * so limit it to the same size as the GGTT (currently - * 2GiB). - */ - ppgtt->base.total = to_i915(ppgtt->base.dev)->gtt.base.total; - ppgtt->switch_mm = gen8_legacy_mm_switch; trace_i915_page_directory_pointer_entry_alloc(&ppgtt->base, 0, 0, -- cgit v0.10.2 From 25f5033761f85a659db729a10b59d80f93a6be0d Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Fri, 7 Aug 2015 17:40:19 +0100 Subject: drm/i915: Always pass dev pointer in pdp_init And fix 0-DAY kernel test infrastructure warning. Reported-by: Fengguang Wu Signed-off-by: Michel Thierry Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 8fda1fb..4a76807 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1475,7 +1475,7 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) ppgtt->base.total = 1ULL << 48; ppgtt->switch_mm = gen8_48b_mm_switch; } else { - ret = __pdp_init(false, &ppgtt->pdp); + ret = __pdp_init(ppgtt->base.dev, &ppgtt->pdp); if (ret) goto free_scratch; -- cgit v0.10.2 From 7f3561bec7cb4e4804bc246069420d3f2f7f3ebe Mon Sep 17 00:00:00 2001 From: Sonika Jindal Date: Mon, 10 Aug 2015 10:35:35 +0530 Subject: drm/i915/bxt: Add HPD support for DDIA Also remove redundant comments. Signed-off-by: Sonika Jindal Reviewed-by: Sivakumar Thulasimani Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 1118c39..a051045 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -90,6 +90,7 @@ static const u32 hpd_status_i915[HPD_NUM_PINS] = { /* BXT hpd list */ static const u32 hpd_bxt[HPD_NUM_PINS] = { + [HPD_PORT_A] = BXT_DE_PORT_HP_DDIA, [HPD_PORT_B] = BXT_DE_PORT_HP_DDIB, [HPD_PORT_C] = BXT_DE_PORT_HP_DDIC }; @@ -3014,30 +3015,25 @@ static void bxt_hpd_irq_setup(struct drm_device *dev) u32 hotplug_port = 0; u32 hotplug_ctrl; - /* Now, enable HPD */ for_each_intel_encoder(dev, intel_encoder) { if (dev_priv->hotplug.stats[intel_encoder->hpd_pin].state == HPD_ENABLED) hotplug_port |= hpd_bxt[intel_encoder->hpd_pin]; } - /* Mask all HPD control bits */ hotplug_ctrl = I915_READ(BXT_HOTPLUG_CTL) & ~BXT_HOTPLUG_CTL_MASK; - /* Enable requested port in hotplug control */ - /* TODO: implement (short) HPD support on port A */ - WARN_ON_ONCE(hotplug_port & BXT_DE_PORT_HP_DDIA); + if (hotplug_port & BXT_DE_PORT_HP_DDIA) + hotplug_ctrl |= BXT_DDIA_HPD_ENABLE; if (hotplug_port & BXT_DE_PORT_HP_DDIB) hotplug_ctrl |= BXT_DDIB_HPD_ENABLE; if (hotplug_port & BXT_DE_PORT_HP_DDIC) hotplug_ctrl |= BXT_DDIC_HPD_ENABLE; I915_WRITE(BXT_HOTPLUG_CTL, hotplug_ctrl); - /* Unmask DDI hotplug in IMR */ hotplug_ctrl = I915_READ(GEN8_DE_PORT_IMR) & ~hotplug_port; I915_WRITE(GEN8_DE_PORT_IMR, hotplug_ctrl); - /* Enable DDI hotplug in IER */ hotplug_ctrl = I915_READ(GEN8_DE_PORT_IER) | hotplug_port; I915_WRITE(GEN8_DE_PORT_IER, hotplug_ctrl); POSTING_READ(GEN8_DE_PORT_IER); -- cgit v0.10.2 From cf1d58833f07afbb4534b15caa3fd48baa313b2c Mon Sep 17 00:00:00 2001 From: Sonika Jindal Date: Mon, 10 Aug 2015 10:35:36 +0530 Subject: drm/i915/bxt: WA for swapped HPD pins in A stepping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit WA for BXT A0/A1, where DDIB's HPD pin is swapped to DDIA, so enabling DDIA HPD pin in place of DDIB. v2: For DP, irq_port is used to determine the encoder instead of hpd_pin and removing the edp HPD logic because port A HPD is not present(Imre) v3: Rebased on top of Imre's patchset for enabling HPD on PORT A. Added hpd_pin swapping for intel_dp_init_connector, setting encoder for PORT_A as per the WA in irq_port (Imre) v4: Dont enable interrupt for edp, also reframe the description (Siva) v5: Don’t check for PORT_A in intel_ddi_init to update dig_port, instead avoid setting hpd_pin itself (Imre) Signed-off-by: Sonika Jindal Reviewed-by: Sivakumar Thulasimani Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 6cfe65d..d5c331d 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -3243,7 +3243,15 @@ void intel_ddi_init(struct drm_device *dev, enum port port) goto err; intel_dig_port->hpd_pulse = intel_dp_hpd_pulse; - dev_priv->hotplug.irq_port[port] = intel_dig_port; + /* + * On BXT A0/A1, sw needs to activate DDIA HPD logic and + * interrupts to check the external panel connection. + */ + if (IS_BROXTON(dev_priv) && (INTEL_REVID(dev) < BXT_REVID_B0) + && port == PORT_B) + dev_priv->hotplug.irq_port[PORT_A] = intel_dig_port; + else + dev_priv->hotplug.irq_port[port] = intel_dig_port; } /* In theory we don't need the encoder->type check, but leave it just in diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 54e9b53..a028246 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -5876,6 +5876,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, break; case PORT_B: intel_encoder->hpd_pin = HPD_PORT_B; + if (IS_BROXTON(dev_priv) && (INTEL_REVID(dev) < BXT_REVID_B0)) + intel_encoder->hpd_pin = HPD_PORT_A; break; case PORT_C: intel_encoder->hpd_pin = HPD_PORT_C; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 51cbea8..0cfbe85 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1973,7 +1973,14 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, intel_hdmi->ddc_bus = GMBUS_PIN_1_BXT; else intel_hdmi->ddc_bus = GMBUS_PIN_DPB; - intel_encoder->hpd_pin = HPD_PORT_B; + /* + * On BXT A0/A1, sw needs to activate DDIA HPD logic and + * interrupts to check the external panel connection. + */ + if (IS_BROXTON(dev_priv) && (INTEL_REVID(dev) < BXT_REVID_B0)) + intel_encoder->hpd_pin = HPD_PORT_A; + else + intel_encoder->hpd_pin = HPD_PORT_B; break; case PORT_C: if (IS_BROXTON(dev_priv)) -- cgit v0.10.2 From ed75a55bb36dec17b9e0f878cea7c8ccb037d8f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 11 Aug 2015 19:47:10 +0300 Subject: drm/i915: clflush on pin_to_display after pwrite to UC bo in LLC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we don't clflush on pin_to_display if the bo is already UC/WT and is not in the CPU write domain. This causes problems with pwrite since pwrite doesn't change the write domain, and it avoids clflushing on UC/WT buffers on LLC platforms unless the buffer is currently being scanned out. Fix the problem by marking the cache dirty and adjusting i915_gem_object_set_cache_level() to clflush when the cache is dirty even if the cache_level doesn't change. My last attempt [1] at fixing this via write domain frobbing was shot down, but now with the cache_dirty flag we can do things in a nicer way. [1] http://lists.freedesktop.org/archives/intel-gfx/2014-November/055390.html v2: Drop the I915_CACHE_NONE/WT checks from pwrite Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=86422 Testcase: igt/kms_pwrite_crc Testcase: igt/gem_pwrite_snooped Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6d0f834..407b6b3 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1005,12 +1005,14 @@ out: if (!needs_clflush_after && obj->base.write_domain != I915_GEM_DOMAIN_CPU) { if (i915_gem_clflush_object(obj, obj->pin_display)) - i915_gem_chipset_flush(dev); + needs_clflush_after = true; } } if (needs_clflush_after) i915_gem_chipset_flush(dev); + else + obj->cache_dirty = true; intel_fb_obj_flush(obj, false, ORIGIN_CPU); return ret; @@ -3639,10 +3641,10 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, { struct drm_device *dev = obj->base.dev; struct i915_vma *vma, *next; - int ret; + int ret = 0; if (obj->cache_level == cache_level) - return 0; + goto out; if (i915_gem_obj_is_pinned(obj)) { DRM_DEBUG("can not change the cache level of pinned objects\n"); @@ -3687,6 +3689,7 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, vma->node.color = cache_level; obj->cache_level = cache_level; +out: if (obj->cache_dirty && obj->base.write_domain != I915_GEM_DOMAIN_CPU && cpu_write_needs_clflush(obj)) { -- cgit v0.10.2 From 908565c20888f790b96b03ae5be9cd175f3d8d72 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 12 Aug 2015 13:08:22 +0100 Subject: drm/i915: Do not check or a stalled pageflip prior to it being queued MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we queue the command or operation to change the scanout address, we mark the flip as in progress. We can use this flag to prevent us from checking for a stalled flip prior to its existence! Signed-off-by: Chris Wilson Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7f6d5fd..dc3e6b2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11236,6 +11236,9 @@ static bool __intel_pageflip_stall_check(struct drm_device *dev, if (atomic_read(&work->pending) >= INTEL_FLIP_COMPLETE) return true; + if (atomic_read(&work->pending) < INTEL_FLIP_PENDING) + return false; + if (!work->enable_stall_check) return false; -- cgit v0.10.2 From 0f2a2a756e862e1936ef599451015ca4c12efde8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 6 Jul 2015 15:10:00 +0300 Subject: drm/i915: Clean up DP/HDMI limited color range handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we treat intel_{dp,hdmi}->color_range as partly user controller value (via the property) but we also change it during .compute_config() when using the "Automatic" mode. That is a bit confusing, so let's just change things so that we store the user property values in intel_dp, and only change what's stored in pipe_config during .compute_config(). There should be no functional change. Signed-off-by: Ville Syrjälä Reviewed-by: Sivakumar Thulasimani Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index a028246..df1b663 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1492,15 +1492,13 @@ found: * CEA-861-E - 5.1 Default Encoding Parameters * VESA DisplayPort Ver.1.2a - 5.1.1.1 Video Colorimetry */ - if (bpp != 18 && drm_match_cea_mode(adjusted_mode) > 1) - intel_dp->color_range = DP_COLOR_RANGE_16_235; - else - intel_dp->color_range = 0; + pipe_config->limited_color_range = + bpp != 18 && drm_match_cea_mode(adjusted_mode) > 1; + } else { + pipe_config->limited_color_range = + intel_dp->limited_color_range; } - if (intel_dp->color_range) - pipe_config->limited_color_range = true; - intel_dp->lane_count = lane_count; if (intel_dp->num_sink_rates) { @@ -1642,8 +1640,9 @@ static void intel_dp_prepare(struct intel_encoder *encoder) trans_dp &= ~TRANS_DP_ENH_FRAMING; I915_WRITE(TRANS_DP_CTL(crtc->pipe), trans_dp); } else { - if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev)) - intel_dp->DP |= intel_dp->color_range; + if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev) && + crtc->config->limited_color_range) + intel_dp->DP |= DP_COLOR_RANGE_16_235; if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) intel_dp->DP |= DP_SYNC_HS_HIGH; @@ -4751,7 +4750,7 @@ intel_dp_set_property(struct drm_connector *connector, if (property == dev_priv->broadcast_rgb_property) { bool old_auto = intel_dp->color_range_auto; - uint32_t old_range = intel_dp->color_range; + bool old_range = intel_dp->limited_color_range; switch (val) { case INTEL_BROADCAST_RGB_AUTO: @@ -4759,18 +4758,18 @@ intel_dp_set_property(struct drm_connector *connector, break; case INTEL_BROADCAST_RGB_FULL: intel_dp->color_range_auto = false; - intel_dp->color_range = 0; + intel_dp->limited_color_range = false; break; case INTEL_BROADCAST_RGB_LIMITED: intel_dp->color_range_auto = false; - intel_dp->color_range = DP_COLOR_RANGE_16_235; + intel_dp->limited_color_range = true; break; default: return -EINVAL; } if (old_auto == intel_dp->color_range_auto && - old_range == intel_dp->color_range) + old_range == intel_dp->limited_color_range) return 0; goto done; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 6b3e2c6..e2456bc 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -657,7 +657,7 @@ struct cxsr_latency { struct intel_hdmi { u32 hdmi_reg; int ddc_bus; - uint32_t color_range; + bool limited_color_range; bool color_range_auto; bool has_hdmi_sink; bool has_audio; @@ -708,7 +708,7 @@ struct intel_dp { uint32_t DP; bool has_audio; enum hdmi_force_audio force_audio; - uint32_t color_range; + bool limited_color_range; bool color_range_auto; uint8_t link_bw; uint8_t rate_select; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 0cfbe85..7185062 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -848,8 +848,8 @@ static void intel_hdmi_prepare(struct intel_encoder *encoder) u32 hdmi_val; hdmi_val = SDVO_ENCODING_HDMI; - if (!HAS_PCH_SPLIT(dev)) - hdmi_val |= intel_hdmi->color_range; + if (!HAS_PCH_SPLIT(dev) && crtc->config->limited_color_range) + hdmi_val |= HDMI_COLOR_RANGE_16_235; if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) hdmi_val |= SDVO_VSYNC_ACTIVE_HIGH; if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) @@ -1260,11 +1260,12 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, if (intel_hdmi->color_range_auto) { /* See CEA-861-E - 5.1 Default Encoding Parameters */ - if (pipe_config->has_hdmi_sink && - drm_match_cea_mode(adjusted_mode) > 1) - intel_hdmi->color_range = HDMI_COLOR_RANGE_16_235; - else - intel_hdmi->color_range = 0; + pipe_config->limited_color_range = + pipe_config->has_hdmi_sink && + drm_match_cea_mode(adjusted_mode) > 1; + } else { + pipe_config->limited_color_range = + intel_hdmi->limited_color_range; } if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) { @@ -1273,9 +1274,6 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, clock_12bpc *= 2; } - if (intel_hdmi->color_range) - pipe_config->limited_color_range = true; - if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev)) pipe_config->has_pch_encoder = true; @@ -1470,7 +1468,7 @@ intel_hdmi_set_property(struct drm_connector *connector, if (property == dev_priv->broadcast_rgb_property) { bool old_auto = intel_hdmi->color_range_auto; - uint32_t old_range = intel_hdmi->color_range; + bool old_range = intel_hdmi->limited_color_range; switch (val) { case INTEL_BROADCAST_RGB_AUTO: @@ -1478,18 +1476,18 @@ intel_hdmi_set_property(struct drm_connector *connector, break; case INTEL_BROADCAST_RGB_FULL: intel_hdmi->color_range_auto = false; - intel_hdmi->color_range = 0; + intel_hdmi->limited_color_range = false; break; case INTEL_BROADCAST_RGB_LIMITED: intel_hdmi->color_range_auto = false; - intel_hdmi->color_range = HDMI_COLOR_RANGE_16_235; + intel_hdmi->limited_color_range = true; break; default: return -EINVAL; } if (old_auto == intel_hdmi->color_range_auto && - old_range == intel_hdmi->color_range) + old_range == intel_hdmi->limited_color_range) return 0; goto done; -- cgit v0.10.2 From 840b32b7eda7837db6e0236293f71fc6644dedf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 11 Aug 2015 20:21:46 +0300 Subject: drm/i915: Don't use link_bw for PLL setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use port_clock instead of link_bw when picking the PLL parameters for DP. link_bw may be zero with an eDP 1.4 sink that supports DP_LINK_RATE_SET so we shouldn't use it for anything other than feed it to the sink appropriately. v2: Fix typo in commit message (Sivakumar) Reviewed-by: Sivakumar Thulasimani Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index d5c331d..0e2f982 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1579,17 +1579,14 @@ skl_ddi_pll_select(struct intel_crtc *intel_crtc, DPLL_CFGCR2_PDIV(wrpll_params.pdiv) | wrpll_params.central_freq; } else if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) { - struct drm_encoder *encoder = &intel_encoder->base; - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - - switch (intel_dp->link_bw) { - case DP_LINK_BW_1_62: + switch (crtc_state->port_clock / 2) { + case 81000: ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0); break; - case DP_LINK_BW_2_7: + case 135000: ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0); break; - case DP_LINK_BW_5_4: + case 270000: ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0); break; } diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index df1b663..3f885f6 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -48,28 +48,28 @@ #define INTEL_DP_RESOLUTION_FAILSAFE (3 << INTEL_DP_RESOLUTION_SHIFT_MASK) struct dp_link_dpll { - int link_bw; + int clock; struct dpll dpll; }; static const struct dp_link_dpll gen4_dpll[] = { - { DP_LINK_BW_1_62, + { 162000, { .p1 = 2, .p2 = 10, .n = 2, .m1 = 23, .m2 = 8 } }, - { DP_LINK_BW_2_7, + { 270000, { .p1 = 1, .p2 = 10, .n = 1, .m1 = 14, .m2 = 2 } } }; static const struct dp_link_dpll pch_dpll[] = { - { DP_LINK_BW_1_62, + { 162000, { .p1 = 2, .p2 = 10, .n = 1, .m1 = 12, .m2 = 9 } }, - { DP_LINK_BW_2_7, + { 270000, { .p1 = 1, .p2 = 10, .n = 2, .m1 = 14, .m2 = 8 } } }; static const struct dp_link_dpll vlv_dpll[] = { - { DP_LINK_BW_1_62, + { 162000, { .p1 = 3, .p2 = 2, .n = 5, .m1 = 3, .m2 = 81 } }, - { DP_LINK_BW_2_7, + { 270000, { .p1 = 2, .p2 = 2, .n = 1, .m1 = 2, .m2 = 27 } } }; @@ -83,11 +83,11 @@ static const struct dp_link_dpll chv_dpll[] = { * m2 is stored in fixed point format using formula below * (m2_int << 22) | m2_fraction */ - { DP_LINK_BW_1_62, /* m2_int = 32, m2_fraction = 1677722 */ + { 162000, /* m2_int = 32, m2_fraction = 1677722 */ { .p1 = 4, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a } }, - { DP_LINK_BW_2_7, /* m2_int = 27, m2_fraction = 0 */ + { 270000, /* m2_int = 27, m2_fraction = 0 */ { .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } }, - { DP_LINK_BW_5_4, /* m2_int = 27, m2_fraction = 0 */ + { 540000, /* m2_int = 27, m2_fraction = 0 */ { .p1 = 2, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } } }; @@ -1133,7 +1133,7 @@ intel_dp_connector_unregister(struct intel_connector *intel_connector) } static void -skl_edp_set_pll_config(struct intel_crtc_state *pipe_config, int link_clock) +skl_edp_set_pll_config(struct intel_crtc_state *pipe_config) { u32 ctrl1; @@ -1145,7 +1145,7 @@ skl_edp_set_pll_config(struct intel_crtc_state *pipe_config, int link_clock) pipe_config->dpll_hw_state.cfgcr2 = 0; ctrl1 = DPLL_CTRL1_OVERRIDE(SKL_DPLL0); - switch (link_clock / 2) { + switch (pipe_config->port_clock / 2) { case 81000: ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, SKL_DPLL0); @@ -1179,19 +1179,19 @@ skl_edp_set_pll_config(struct intel_crtc_state *pipe_config, int link_clock) } static void -hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config, int link_bw) +hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config) { memset(&pipe_config->dpll_hw_state, 0, sizeof(pipe_config->dpll_hw_state)); - switch (link_bw) { - case DP_LINK_BW_1_62: + switch (pipe_config->port_clock / 2) { + case 81000: pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_810; break; - case DP_LINK_BW_2_7: + case 135000: pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_1350; break; - case DP_LINK_BW_5_4: + case 270000: pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_2700; break; } @@ -1238,7 +1238,7 @@ intel_dp_source_rates(struct drm_device *dev, const int **source_rates) static void intel_dp_set_clock(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, int link_bw) + struct intel_crtc_state *pipe_config) { struct drm_device *dev = encoder->base.dev; const struct dp_link_dpll *divisor = NULL; @@ -1260,7 +1260,7 @@ intel_dp_set_clock(struct intel_encoder *encoder, if (divisor && count) { for (i = 0; i < count; i++) { - if (link_bw == divisor[i].link_bw) { + if (pipe_config->port_clock == divisor[i].clock) { pipe_config->dpll = divisor[i].dpll; pipe_config->clock_set = true; break; @@ -1535,13 +1535,13 @@ found: } if (IS_SKYLAKE(dev) && is_edp(intel_dp)) - skl_edp_set_pll_config(pipe_config, common_rates[clock]); + skl_edp_set_pll_config(pipe_config); else if (IS_BROXTON(dev)) /* handled in ddi */; else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) - hsw_dp_set_ddi_pll_sel(pipe_config, intel_dp->link_bw); + hsw_dp_set_ddi_pll_sel(pipe_config); else - intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw); + intel_dp_set_clock(encoder, pipe_config); return true; } -- cgit v0.10.2 From 96f3f1f905e9c4977220fa07477cd8a8ed4af4da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 6 Jul 2015 15:10:02 +0300 Subject: drm/i915: Don't pass clock to DDI PLL select functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All the *_ddi_pll_select() functions get passed the port_clock and pipe config as parameters. We only need to pass the pipe config, and the functions can dig up the port_clock themselves. Signed-off-by: Ville Syrjälä Reviewed-by: Sivakumar Thulasimani Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 0e2f982..b6d1ab2 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1267,9 +1267,10 @@ hsw_ddi_calculate_wrpll(int clock /* in Hz */, static bool hsw_ddi_pll_select(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state, - struct intel_encoder *intel_encoder, - int clock) + struct intel_encoder *intel_encoder) { + int clock = crtc_state->port_clock; + if (intel_encoder->type == INTEL_OUTPUT_HDMI) { struct intel_shared_dpll *pll; uint32_t val; @@ -1548,11 +1549,11 @@ skip_remaining_dividers: static bool skl_ddi_pll_select(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state, - struct intel_encoder *intel_encoder, - int clock) + struct intel_encoder *intel_encoder) { struct intel_shared_dpll *pll; uint32_t ctrl1, cfgcr1, cfgcr2; + int clock = crtc_state->port_clock; /* * See comment in intel_dpll_hw_state to understand why we always use 0 @@ -1640,14 +1641,14 @@ static const struct bxt_clk_div bxt_dp_clk_val[] = { static bool bxt_ddi_pll_select(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state, - struct intel_encoder *intel_encoder, - int clock) + struct intel_encoder *intel_encoder) { struct intel_shared_dpll *pll; struct bxt_clk_div clk_div = {0}; int vco = 0; uint32_t prop_coef, int_coef, gain_ctl, targ_cnt; uint32_t lanestagger; + int clock = crtc_state->port_clock; if (intel_encoder->type == INTEL_OUTPUT_HDMI) { intel_clock_t best_clock; @@ -1775,17 +1776,16 @@ bool intel_ddi_pll_select(struct intel_crtc *intel_crtc, struct drm_device *dev = intel_crtc->base.dev; struct intel_encoder *intel_encoder = intel_ddi_get_crtc_new_encoder(crtc_state); - int clock = crtc_state->port_clock; if (IS_SKYLAKE(dev)) return skl_ddi_pll_select(intel_crtc, crtc_state, - intel_encoder, clock); + intel_encoder); else if (IS_BROXTON(dev)) return bxt_ddi_pll_select(intel_crtc, crtc_state, - intel_encoder, clock); + intel_encoder); else return hsw_ddi_pll_select(intel_crtc, crtc_state, - intel_encoder, clock); + intel_encoder); } void intel_ddi_set_pipe_settings(struct drm_crtc *crtc) -- cgit v0.10.2 From b81e34c29e67f5b3e5ce28b5055ae2ca59c36f7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 6 Jul 2015 15:10:03 +0300 Subject: drm/i915: Avoid confusion between DP and TRANS_DP_CTL in DP .get_config() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use a separate variable for the TRANS_DP_CTL value instead of reusing 'tmp' that otherwise contains the DP port register value. Signed-off-by: Ville Syrjälä Reviewed-by: Sivakumar Thulasimani Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 3f885f6..3a9b8e4 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2282,13 +2282,14 @@ static void intel_dp_get_config(struct intel_encoder *encoder, pipe_config->has_audio = tmp & DP_AUDIO_OUTPUT_ENABLE && port != PORT_A; if (HAS_PCH_CPT(dev) && port != PORT_A) { - tmp = I915_READ(TRANS_DP_CTL(crtc->pipe)); - if (tmp & TRANS_DP_HSYNC_ACTIVE_HIGH) + u32 trans_dp = I915_READ(TRANS_DP_CTL(crtc->pipe)); + + if (trans_dp & TRANS_DP_HSYNC_ACTIVE_HIGH) flags |= DRM_MODE_FLAG_PHSYNC; else flags |= DRM_MODE_FLAG_NHSYNC; - if (tmp & TRANS_DP_VSYNC_ACTIVE_HIGH) + if (trans_dp & TRANS_DP_VSYNC_ACTIVE_HIGH) flags |= DRM_MODE_FLAG_PVSYNC; else flags |= DRM_MODE_FLAG_NVSYNC; -- cgit v0.10.2 From 90a6b7b052b1aa17fbb98b049e9c8b7f729c35a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 6 Jul 2015 16:39:15 +0300 Subject: drm/i915: Move intel_dp->lane_count into pipe_config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we clobber intel_dp->lane_count in compute config, which means after a rejected modeset we may no longer be able to retrain the current link. Move lane_count into pipe_config to avoid that. v2: Add missing ':' to the pipe config debug dump Signed-off-by: Ville Syrjälä Reviewed-by: Sivakumar Thulasimani Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 88f20cc..f22aca3 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4108,6 +4108,7 @@ enum skl_disp_power_wells { /* How many wires to use. I guess 3 was too hard */ #define DP_PORT_WIDTH(width) (((width) - 1) << 19) #define DP_PORT_WIDTH_MASK (7 << 19) +#define DP_PORT_WIDTH_SHIFT 19 /* Mystic DPCD version 1.1 special mode */ #define DP_ENHANCED_FRAMING (1 << 18) @@ -7148,6 +7149,8 @@ enum skl_disp_power_wells { #define DDI_BUF_IS_IDLE (1<<7) #define DDI_A_4_LANES (1<<4) #define DDI_PORT_WIDTH(width) (((width) - 1) << 1) +#define DDI_PORT_WIDTH_MASK (7 << 1) +#define DDI_PORT_WIDTH_SHIFT 1 #define DDI_INIT_DISPLAY_DETECTED (1<<0) /* DDI Buffer Translations */ diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index b6d1ab2..56d778f 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -728,11 +728,11 @@ void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder) struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); struct intel_digital_port *intel_dig_port = enc_to_dig_port(&encoder->base); + struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); intel_dp->DP = intel_dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE | DDI_BUF_TRANS_SELECT(0); - intel_dp->DP |= DDI_PORT_WIDTH(intel_dp->lane_count); - + intel_dp->DP |= DDI_PORT_WIDTH(crtc->config->lane_count); } static struct intel_encoder * @@ -1918,7 +1918,7 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc) } else temp |= TRANS_DDI_MODE_SELECT_DP_SST; - temp |= DDI_PORT_WIDTH(intel_dp->lane_count); + temp |= DDI_PORT_WIDTH(intel_crtc->config->lane_count); } else if (type == INTEL_OUTPUT_DP_MST) { struct intel_dp *intel_dp = &enc_to_mst(encoder)->primary->dp; @@ -1927,7 +1927,7 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc) } else temp |= TRANS_DDI_MODE_SELECT_DP_SST; - temp |= DDI_PORT_WIDTH(intel_dp->lane_count); + temp |= DDI_PORT_WIDTH(intel_crtc->config->lane_count); } else { WARN(1, "Invalid encoder type %d for pipe %c\n", intel_encoder->type, pipe_name(pipe)); @@ -3094,6 +3094,8 @@ void intel_ddi_get_config(struct intel_encoder *encoder, case TRANS_DDI_MODE_SELECT_DP_SST: case TRANS_DDI_MODE_SELECT_DP_MST: pipe_config->has_dp_encoder = true; + pipe_config->lane_count = + ((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1; intel_dp_get_m_n(intel_crtc, pipe_config); break; default: diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index dc3e6b2..40e70f2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11902,14 +11902,16 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, pipe_config->fdi_m_n.gmch_m, pipe_config->fdi_m_n.gmch_n, pipe_config->fdi_m_n.link_m, pipe_config->fdi_m_n.link_n, pipe_config->fdi_m_n.tu); - DRM_DEBUG_KMS("dp: %i, gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n", + DRM_DEBUG_KMS("dp: %i, lanes: %i, gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n", pipe_config->has_dp_encoder, + pipe_config->lane_count, pipe_config->dp_m_n.gmch_m, pipe_config->dp_m_n.gmch_n, pipe_config->dp_m_n.link_m, pipe_config->dp_m_n.link_n, pipe_config->dp_m_n.tu); - DRM_DEBUG_KMS("dp: %i, gmch_m2: %u, gmch_n2: %u, link_m2: %u, link_n2: %u, tu2: %u\n", + DRM_DEBUG_KMS("dp: %i, lanes: %i, gmch_m2: %u, gmch_n2: %u, link_m2: %u, link_n2: %u, tu2: %u\n", pipe_config->has_dp_encoder, + pipe_config->lane_count, pipe_config->dp_m2_n2.gmch_m, pipe_config->dp_m2_n2.gmch_n, pipe_config->dp_m2_n2.link_m, @@ -12416,6 +12418,7 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_M_N(fdi_m_n); PIPE_CONF_CHECK_I(has_dp_encoder); + PIPE_CONF_CHECK_I(lane_count); if (INTEL_INFO(dev)->gen < 8) { PIPE_CONF_CHECK_M_N(dp_m_n); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 3a9b8e4..3d3a908 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1499,7 +1499,7 @@ found: intel_dp->limited_color_range; } - intel_dp->lane_count = lane_count; + pipe_config->lane_count = lane_count; if (intel_dp->num_sink_rates) { intel_dp->link_bw = 0; @@ -1515,7 +1515,7 @@ found: pipe_config->port_clock = common_rates[clock]; DRM_DEBUG_KMS("DP link bw %02x lane count %d clock %d bpp %d\n", - intel_dp->link_bw, intel_dp->lane_count, + intel_dp->link_bw, pipe_config->lane_count, pipe_config->port_clock, bpp); DRM_DEBUG_KMS("DP link bw required %i available %i\n", mode_rate, link_avail); @@ -1610,7 +1610,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder) /* Handle DP bits in common between all three register formats */ intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; - intel_dp->DP |= DP_PORT_WIDTH(intel_dp->lane_count); + intel_dp->DP |= DP_PORT_WIDTH(crtc->config->lane_count); if (crtc->config->has_audio) intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE; @@ -2313,6 +2313,9 @@ static void intel_dp_get_config(struct intel_encoder *encoder, pipe_config->has_dp_encoder = true; + pipe_config->lane_count = + ((tmp & DP_PORT_WIDTH_MASK) >> DP_PORT_WIDTH_SHIFT) + 1; + intel_dp_get_m_n(crtc, pipe_config); if (port == PORT_A) { @@ -3338,13 +3341,15 @@ static void intel_get_adjust_train(struct intel_dp *intel_dp, const uint8_t link_status[DP_LINK_STATUS_SIZE]) { + struct intel_crtc *crtc = + to_intel_crtc(dp_to_dig_port(intel_dp)->base.base.crtc); uint8_t v = 0; uint8_t p = 0; int lane; uint8_t voltage_max; uint8_t preemph_max; - for (lane = 0; lane < intel_dp->lane_count; lane++) { + for (lane = 0; lane < crtc->config->lane_count; lane++) { uint8_t this_v = drm_dp_get_adjust_request_voltage(link_status, lane); uint8_t this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, lane); @@ -3513,8 +3518,10 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, uint8_t dp_train_pat) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = intel_dig_port->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = + to_i915(intel_dig_port->base.base.dev); + struct intel_crtc *crtc = + to_intel_crtc(intel_dig_port->base.base.crtc); uint8_t buf[sizeof(intel_dp->train_set) + 1]; int ret, len; @@ -3530,8 +3537,8 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, len = 1; } else { /* DP_TRAINING_LANEx_SET follow DP_TRAINING_PATTERN_SET */ - memcpy(buf + 1, intel_dp->train_set, intel_dp->lane_count); - len = intel_dp->lane_count + 1; + memcpy(buf + 1, intel_dp->train_set, crtc->config->lane_count); + len = crtc->config->lane_count + 1; } ret = drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_PATTERN_SET, @@ -3555,8 +3562,10 @@ intel_dp_update_link_train(struct intel_dp *intel_dp, uint32_t *DP, const uint8_t link_status[DP_LINK_STATUS_SIZE]) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = intel_dig_port->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = + to_i915(intel_dig_port->base.base.dev); + struct intel_crtc *crtc = + to_intel_crtc(intel_dig_port->base.base.crtc); int ret; intel_get_adjust_train(intel_dp, link_status); @@ -3566,9 +3575,9 @@ intel_dp_update_link_train(struct intel_dp *intel_dp, uint32_t *DP, POSTING_READ(intel_dp->output_reg); ret = drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_LANE0_SET, - intel_dp->train_set, intel_dp->lane_count); + intel_dp->train_set, crtc->config->lane_count); - return ret == intel_dp->lane_count; + return ret == crtc->config->lane_count; } static void intel_dp_set_idle_link_train(struct intel_dp *intel_dp) @@ -3607,6 +3616,8 @@ void intel_dp_start_link_train(struct intel_dp *intel_dp) { struct drm_encoder *encoder = &dp_to_dig_port(intel_dp)->base.base; + struct intel_crtc *crtc = + to_intel_crtc(dp_to_dig_port(intel_dp)->base.base.crtc); struct drm_device *dev = encoder->dev; int i; uint8_t voltage; @@ -3619,7 +3630,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) /* Write the link configuration data */ link_config[0] = intel_dp->link_bw; - link_config[1] = intel_dp->lane_count; + link_config[1] = crtc->config->lane_count; if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, 2); @@ -3653,7 +3664,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) break; } - if (drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) { + if (drm_dp_clock_recovery_ok(link_status, crtc->config->lane_count)) { DRM_DEBUG_KMS("clock recovery OK\n"); break; } @@ -3676,10 +3687,10 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) } /* Check to see if we've tried the max voltage */ - for (i = 0; i < intel_dp->lane_count; i++) + for (i = 0; i < crtc->config->lane_count; i++) if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) break; - if (i == intel_dp->lane_count) { + if (i == crtc->config->lane_count) { ++loop_tries; if (loop_tries == 5) { DRM_ERROR("too many full retries, give up\n"); @@ -3716,6 +3727,8 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) void intel_dp_complete_link_train(struct intel_dp *intel_dp) { + struct intel_crtc *crtc = + to_intel_crtc(dp_to_dig_port(intel_dp)->base.base.crtc); bool channel_eq = false; int tries, cr_tries; uint32_t DP = intel_dp->DP; @@ -3751,7 +3764,8 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) } /* Make sure clock is still ok */ - if (!drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) { + if (!drm_dp_clock_recovery_ok(link_status, + crtc->config->lane_count)) { intel_dp->train_set_valid = false; intel_dp_start_link_train(intel_dp); intel_dp_set_link_train(intel_dp, &DP, @@ -3761,7 +3775,8 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) continue; } - if (drm_dp_channel_eq_ok(link_status, intel_dp->lane_count)) { + if (drm_dp_channel_eq_ok(link_status, + crtc->config->lane_count)) { channel_eq = true; break; } @@ -4259,6 +4274,8 @@ update_status: static int intel_dp_check_mst_status(struct intel_dp *intel_dp) { + struct intel_crtc *crtc = + to_intel_crtc(dp_to_dig_port(intel_dp)->base.base.crtc); bool bret; if (intel_dp->is_mst) { @@ -4271,7 +4288,8 @@ go_again: if (bret == true) { /* check link status - esi[10] = 0x200c */ - if (intel_dp->active_mst_links && !drm_dp_channel_eq_ok(&esi[10], intel_dp->lane_count)) { + if (intel_dp->active_mst_links && + !drm_dp_channel_eq_ok(&esi[10], crtc->config->lane_count)) { DRM_DEBUG_KMS("channel EQ not ok, retraining\n"); intel_dp_start_link_train(intel_dp); intel_dp_complete_link_train(intel_dp); @@ -4326,6 +4344,8 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base; + struct intel_crtc *crtc = + to_intel_crtc(dp_to_dig_port(intel_dp)->base.base.crtc); u8 sink_irq_vector; u8 link_status[DP_LINK_STATUS_SIZE]; @@ -4361,7 +4381,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n"); } - if (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count)) { + if (!drm_dp_channel_eq_ok(link_status, crtc->config->lane_count)) { DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n", intel_encoder->base.name); intel_dp_start_link_train(intel_dp); diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index f4fe118..fdb5e31 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -65,7 +65,7 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, intel_dp->rate_select = 0; } - intel_dp->lane_count = lane_count; + pipe_config->lane_count = lane_count; pipe_config->pipe_bpp = 24; pipe_config->port_clock = rate; @@ -276,6 +276,10 @@ static void intel_dp_mst_enc_get_config(struct intel_encoder *encoder, break; } pipe_config->base.adjusted_mode.flags |= flags; + + pipe_config->lane_count = + ((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1; + intel_dp_get_m_n(crtc, pipe_config); intel_ddi_clock_get(&intel_dig_port->base, pipe_config); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index e2456bc..0a11041 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -423,6 +423,8 @@ struct intel_crtc_state { /* Used by SDVO (and if we ever fix it, HDMI). */ unsigned pixel_multiplier; + uint8_t lane_count; + /* Panel fitter controls for gen2-gen4 + VLV */ struct { u32 control; @@ -712,7 +714,6 @@ struct intel_dp { bool color_range_auto; uint8_t link_bw; uint8_t rate_select; - uint8_t lane_count; uint8_t dpcd[DP_RECEIVER_CAP_SIZE]; uint8_t psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE]; uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS]; -- cgit v0.10.2 From a79b8165beed02a96dc54737feb20700ddf71127 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 6 Jul 2015 15:10:05 +0300 Subject: drm/i915: Don't use link_bw to select between TP1 and TP3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_dp->link_bw is going away, so consul the port_clock instead when choosing between TP1 and TP3. Signed-off-by: Ville Syrjälä Reviewed-by: Sivakumar Thulasimani Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 3d3a908..6231eb1 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3734,8 +3734,8 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) uint32_t DP = intel_dp->DP; uint32_t training_pattern = DP_TRAINING_PATTERN_2; - /* Training Pattern 3 for HBR2 ot 1.2 devices that support it*/ - if (intel_dp->link_bw == DP_LINK_BW_5_4 || intel_dp->use_tps3) + /* Training Pattern 3 for HBR2 or 1.2 devices that support it*/ + if (crtc->config->port_clock == 540000 || intel_dp->use_tps3) training_pattern = DP_TRAINING_PATTERN_3; /* channel equalization */ -- cgit v0.10.2 From 04a60f9ffa9a9ac05d5616408e3f11115ed1450a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 6 Jul 2015 15:10:06 +0300 Subject: drm/i915: Kill intel_dp->{link_bw, rate_select} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We only need the link_bw/rate_select parameters when starting link training, and they should be computed based on the currently active config, so throw them out from intel_dp and just compute on demand. Toss in an extra debug print to see rate_select in addition to link_bw, as the latter may be 0 for eDP 1.4. Signed-off-by: Ville Syrjälä Reviewed-by: Sivakumar Thulasimani Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 6231eb1..b905c19 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1376,6 +1376,19 @@ int intel_dp_rate_select(struct intel_dp *intel_dp, int rate) return rate_to_index(rate, intel_dp->sink_rates); } +static void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock, + uint8_t *link_bw, uint8_t *rate_select) +{ + if (intel_dp->num_sink_rates) { + *link_bw = 0; + *rate_select = + intel_dp_rate_select(intel_dp, port_clock); + } else { + *link_bw = drm_dp_link_rate_to_bw_code(port_clock); + *rate_select = 0; + } +} + bool intel_dp_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) @@ -1397,6 +1410,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, int link_avail, link_clock; int common_rates[DP_MAX_SUPPORTED_RATES] = {}; int common_len; + uint8_t link_bw, rate_select; common_len = intel_dp_common_rates(intel_dp, common_rates); @@ -1501,21 +1515,14 @@ found: pipe_config->lane_count = lane_count; - if (intel_dp->num_sink_rates) { - intel_dp->link_bw = 0; - intel_dp->rate_select = - intel_dp_rate_select(intel_dp, common_rates[clock]); - } else { - intel_dp->link_bw = - drm_dp_link_rate_to_bw_code(common_rates[clock]); - intel_dp->rate_select = 0; - } - pipe_config->pipe_bpp = bpp; pipe_config->port_clock = common_rates[clock]; - DRM_DEBUG_KMS("DP link bw %02x lane count %d clock %d bpp %d\n", - intel_dp->link_bw, pipe_config->lane_count, + intel_dp_compute_rate(intel_dp, pipe_config->port_clock, + &link_bw, &rate_select); + + DRM_DEBUG_KMS("DP link bw %02x rate select %02x lane count %d clock %d bpp %d\n", + link_bw, rate_select, pipe_config->lane_count, pipe_config->port_clock, bpp); DRM_DEBUG_KMS("DP link bw required %i available %i\n", mode_rate, link_avail); @@ -3624,19 +3631,23 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) int voltage_tries, loop_tries; uint32_t DP = intel_dp->DP; uint8_t link_config[2]; + uint8_t link_bw, rate_select; if (HAS_DDI(dev)) intel_ddi_prepare_link_retrain(encoder); + intel_dp_compute_rate(intel_dp, crtc->config->port_clock, + &link_bw, &rate_select); + /* Write the link configuration data */ - link_config[0] = intel_dp->link_bw; + link_config[0] = link_bw; link_config[1] = crtc->config->lane_count; if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, 2); if (intel_dp->num_sink_rates) drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_RATE_SET, - &intel_dp->rate_select, 1); + &rate_select, 1); link_config[0] = 0; link_config[1] = DP_SET_ANSI_8B10B; diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index fdb5e31..1dd2b37 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -38,7 +38,7 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, struct intel_dp *intel_dp = &intel_dig_port->dp; struct drm_atomic_state *state; int bpp, i; - int lane_count, slots, rate; + int lane_count, slots; struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; struct drm_connector *drm_connector; struct intel_connector *connector, *found = NULL; @@ -55,20 +55,11 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, */ lane_count = drm_dp_max_lane_count(intel_dp->dpcd); - rate = intel_dp_max_link_rate(intel_dp); - - if (intel_dp->num_sink_rates) { - intel_dp->link_bw = 0; - intel_dp->rate_select = intel_dp_rate_select(intel_dp, rate); - } else { - intel_dp->link_bw = drm_dp_link_rate_to_bw_code(rate); - intel_dp->rate_select = 0; - } pipe_config->lane_count = lane_count; pipe_config->pipe_bpp = 24; - pipe_config->port_clock = rate; + pipe_config->port_clock = intel_dp_max_link_rate(intel_dp); state = pipe_config->base.state; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 0a11041..22dc8b6 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -712,8 +712,6 @@ struct intel_dp { enum hdmi_force_audio force_audio; bool limited_color_range; bool color_range_auto; - uint8_t link_bw; - uint8_t rate_select; uint8_t dpcd[DP_RECEIVER_CAP_SIZE]; uint8_t psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE]; uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS]; -- cgit v0.10.2 From 33a732f407fed464df687370d7bb4d64533f9920 Mon Sep 17 00:00:00 2001 From: Alex Dai Date: Wed, 12 Aug 2015 15:43:36 +0100 Subject: drm/i915: GuC-specific firmware loader This fetches the required firmware image from the filesystem, then loads it into the GuC's memory via a dedicated DMA engine. This patch is derived from GuC loading work originally done by Vinit Azad and Ben Widawsky. v2: Various improvements per review comments by Chris Wilson v3: Removed 'wait' parameter to intel_guc_ucode_load() as firmware prefetch is no longer supported in the common firmware loader, per Daniel Vetter's request. Firmware checker callback fn now returns errno rather than bool. v4: Squash uC-independent code into GuC-specifc loader [Daniel Vetter] Don't keep the driver working (by falling back to execlist mode) if GuC firmware loading fails [Daniel Vetter] v5: Clarify WOPCM-related #defines [Tom O'Rourke] Delete obsolete code no longer required with current h/w & f/w [Tom O'Rourke] Move the call to intel_guc_ucode_init() later, so that it can allocate GEM objects, and have it fetch the firmware; then intel_guc_ucode_load() doesn't need to fetch it later. [Daniel Vetter]. v6: Update comment describing intel_guc_ucode_load() [Tom O'Rourke] Issue: VIZ-4884 Signed-off-by: Alex Dai Signed-off-by: Dave Gordon Reviewed-by: Tom O'Rourke Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 41fb8a9..cc359e0 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -40,6 +40,9 @@ i915-y += i915_cmd_parser.o \ intel_ringbuffer.o \ intel_uncore.o +# general-purpose microcontroller (GuC) support +i915-y += intel_guc_loader.o + # autogenerated null render state i915-y += intel_renderstate_gen6.o \ intel_renderstate_gen7.o \ diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index ab37d11..2193cc2 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -435,6 +435,11 @@ static int i915_load_modeset_init(struct drm_device *dev) * working irqs for e.g. gmbus and dp aux transfers. */ intel_modeset_init(dev); + /* intel_guc_ucode_init() needs the mutex to allocate GEM objects */ + mutex_lock(&dev->struct_mutex); + intel_guc_ucode_init(dev); + mutex_unlock(&dev->struct_mutex); + ret = i915_gem_init(dev); if (ret) goto cleanup_irq; @@ -476,6 +481,9 @@ cleanup_gem: i915_gem_context_fini(dev); mutex_unlock(&dev->struct_mutex); cleanup_irq: + mutex_lock(&dev->struct_mutex); + intel_guc_ucode_fini(dev); + mutex_unlock(&dev->struct_mutex); drm_irq_uninstall(dev); cleanup_gem_stolen: i915_gem_cleanup_stolen(dev); @@ -1128,6 +1136,7 @@ int i915_driver_unload(struct drm_device *dev) flush_workqueue(dev_priv->wq); mutex_lock(&dev->struct_mutex); + intel_guc_ucode_fini(dev); i915_gem_cleanup_ringbuffer(dev); i915_gem_context_fini(dev); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6b85338..6124445 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -50,6 +50,7 @@ #include #include #include +#include "intel_guc.h" /* General customization: */ @@ -1709,6 +1710,8 @@ struct drm_i915_private { struct i915_virtual_gpu vgpu; + struct intel_guc guc; + struct intel_csr csr; /* Display CSR-related protection */ @@ -1953,6 +1956,11 @@ static inline struct drm_i915_private *dev_to_i915(struct device *dev) return to_i915(dev_get_drvdata(dev)); } +static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc) +{ + return container_of(guc, struct drm_i915_private, guc); +} + /* Iterate over initialised rings */ #define for_each_ring(ring__, dev_priv__, i__) \ for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \ @@ -2557,6 +2565,9 @@ struct drm_i915_cmd_table { #define HAS_CSR(dev) (IS_SKYLAKE(dev)) +#define HAS_GUC_UCODE(dev) (IS_GEN9(dev)) +#define HAS_GUC_SCHED(dev) (IS_GEN9(dev)) + #define HAS_RESOURCE_STREAMER(dev) (IS_HASWELL(dev) || \ INTEL_INFO(dev)->gen >= 8) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 407b6b3..1ac57ec 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4681,6 +4681,22 @@ i915_gem_init_hw(struct drm_device *dev) goto out; } + /* We can't enable contexts until all firmware is loaded */ + ret = intel_guc_ucode_load(dev); + if (ret) { + /* + * If we got an error and GuC submission is enabled, map + * the error to -EIO so the GPU will be declared wedged. + * OTOH, if we didn't intend to use the GuC anyway, just + * discard the error and carry on. + */ + DRM_ERROR("Failed to initialize GuC, error %d%s\n", ret, + i915.enable_guc_submission ? "" : " (ignored)"); + ret = i915.enable_guc_submission ? -EIO : 0; + if (ret) + goto out; + } + /* Now it is safe to go back round and do everything else: */ for_each_ring(ring, dev_priv, i) { struct drm_i915_gem_request *req; diff --git a/drivers/gpu/drm/i915/i915_guc_reg.h b/drivers/gpu/drm/i915/i915_guc_reg.h index ccdc6c8..8c8e574 100644 --- a/drivers/gpu/drm/i915/i915_guc_reg.h +++ b/drivers/gpu/drm/i915/i915_guc_reg.h @@ -38,10 +38,6 @@ #define GS_MIA_SHIFT 16 #define GS_MIA_MASK (0x07 << GS_MIA_SHIFT) -#define GUC_WOPCM_SIZE 0xc050 -#define GUC_WOPCM_SIZE_VALUE (0x80 << 12) /* 512KB */ -#define GUC_WOPCM_OFFSET 0x80000 /* 512KB */ - #define SOFT_SCRATCH(n) (0xc180 + ((n) * 4)) #define UOS_RSA_SCRATCH_0 0xc200 @@ -56,10 +52,18 @@ #define UOS_MOVE (1<<4) #define START_DMA (1<<0) #define DMA_GUC_WOPCM_OFFSET 0xc340 +#define GUC_WOPCM_OFFSET_VALUE 0x80000 /* 512KB */ + +#define GUC_WOPCM_SIZE 0xc050 +#define GUC_WOPCM_SIZE_VALUE (0x80 << 12) /* 512KB */ + +/* GuC addresses below GUC_WOPCM_TOP don't map through the GTT */ +#define GUC_WOPCM_TOP (GUC_WOPCM_SIZE_VALUE) #define GEN8_GT_PM_CONFIG 0x138140 +#define GEN9LP_GT_PM_CONFIG 0x138140 #define GEN9_GT_PM_CONFIG 0x13816c -#define GEN8_GT_DOORBELL_ENABLE (1<<0) +#define GT_DOORBELL_ENABLE (1<<0) #define GEN8_GTCR 0x4274 #define GEN8_GTCR_INVALIDATE (1<<0) @@ -80,7 +84,8 @@ GUC_ENABLE_READ_CACHE_LOGIC | \ GUC_ENABLE_MIA_CACHING | \ GUC_ENABLE_READ_CACHE_FOR_SRAM_DATA | \ - GUC_ENABLE_READ_CACHE_FOR_WOPCM_DATA) + GUC_ENABLE_READ_CACHE_FOR_WOPCM_DATA | \ + GUC_ENABLE_MIA_CLOCK_GATING) #define HOST2GUC_INTERRUPT 0xc4c8 #define HOST2GUC_TRIGGER (1<<0) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f22aca3..651d0dd 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6860,7 +6860,9 @@ enum skl_disp_power_wells { #define GEN9_PGCTL_SSB_EU311_ACK (1 << 14) #define GEN7_MISCCPCTL (0x9424) -#define GEN7_DOP_CLOCK_GATE_ENABLE (1<<0) +#define GEN7_DOP_CLOCK_GATE_ENABLE (1<<0) +#define GEN8_DOP_CLOCK_GATE_CFCLK_ENABLE (1<<2) +#define GEN8_DOP_CLOCK_GATE_GUC_ENABLE (1<<4) #define GEN8_GARBCNTL 0xB004 #define GEN9_GAPS_TSV_CREDIT_DISABLE (1<<7) diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h new file mode 100644 index 0000000..2846b6d --- /dev/null +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -0,0 +1,67 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ +#ifndef _INTEL_GUC_H_ +#define _INTEL_GUC_H_ + +#include "intel_guc_fwif.h" +#include "i915_guc_reg.h" + +enum intel_guc_fw_status { + GUC_FIRMWARE_FAIL = -1, + GUC_FIRMWARE_NONE = 0, + GUC_FIRMWARE_PENDING, + GUC_FIRMWARE_SUCCESS +}; + +/* + * This structure encapsulates all the data needed during the process + * of fetching, caching, and loading the firmware image into the GuC. + */ +struct intel_guc_fw { + struct drm_device * guc_dev; + const char * guc_fw_path; + size_t guc_fw_size; + struct drm_i915_gem_object * guc_fw_obj; + enum intel_guc_fw_status guc_fw_fetch_status; + enum intel_guc_fw_status guc_fw_load_status; + + uint16_t guc_fw_major_wanted; + uint16_t guc_fw_minor_wanted; + uint16_t guc_fw_major_found; + uint16_t guc_fw_minor_found; +}; + +struct intel_guc { + struct intel_guc_fw guc_fw; + + uint32_t log_flags; +}; + +/* intel_guc_loader.c */ +extern void intel_guc_ucode_init(struct drm_device *dev); +extern int intel_guc_ucode_load(struct drm_device *dev); +extern void intel_guc_ucode_fini(struct drm_device *dev); +extern const char *intel_guc_fw_status_repr(enum intel_guc_fw_status status); + +#endif diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h index 18d7f20..06aad6f 100644 --- a/drivers/gpu/drm/i915/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h @@ -32,9 +32,8 @@ * EDITING THIS FILE IS THEREFORE NOT RECOMMENDED - YOUR CHANGES MAY BE LOST. */ -#define GFXCORE_FAMILY_GEN8 11 #define GFXCORE_FAMILY_GEN9 12 -#define GFXCORE_FAMILY_FORCE_ULONG 0x7fffffff +#define GFXCORE_FAMILY_UNKNOWN 0x7fffffff #define GUC_CTX_PRIORITY_CRITICAL 0 #define GUC_CTX_PRIORITY_HIGH 1 diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c new file mode 100644 index 0000000..dd62c31 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -0,0 +1,529 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Vinit Azad + * Ben Widawsky + * Dave Gordon + * Alex Dai + */ +#include +#include "i915_drv.h" +#include "intel_guc.h" + +/** + * DOC: GuC + * + * intel_guc: + * Top level structure of guc. It handles firmware loading and manages client + * pool and doorbells. intel_guc owns a i915_guc_client to replace the legacy + * ExecList submission. + * + * Firmware versioning: + * The firmware build process will generate a version header file with major and + * minor version defined. The versions are built into CSS header of firmware. + * i915 kernel driver set the minimal firmware version required per platform. + * The firmware installation package will install (symbolic link) proper version + * of firmware. + * + * GuC address space: + * GuC does not allow any gfx GGTT address that falls into range [0, WOPCM_TOP), + * which is reserved for Boot ROM, SRAM and WOPCM. Currently this top address is + * 512K. In order to exclude 0-512K address space from GGTT, all gfx objects + * used by GuC is pinned with PIN_OFFSET_BIAS along with size of WOPCM. + * + * Firmware log: + * Firmware log is enabled by setting i915.guc_log_level to non-negative level. + * Log data is printed out via reading debugfs i915_guc_log_dump. Reading from + * i915_guc_load_status will print out firmware loading status and scratch + * registers value. + * + */ + +#define I915_SKL_GUC_UCODE "i915/skl_guc_ver3.bin" +MODULE_FIRMWARE(I915_SKL_GUC_UCODE); + +/* User-friendly representation of an enum */ +const char *intel_guc_fw_status_repr(enum intel_guc_fw_status status) +{ + switch (status) { + case GUC_FIRMWARE_FAIL: + return "FAIL"; + case GUC_FIRMWARE_NONE: + return "NONE"; + case GUC_FIRMWARE_PENDING: + return "PENDING"; + case GUC_FIRMWARE_SUCCESS: + return "SUCCESS"; + default: + return "UNKNOWN!"; + } +}; + +static u32 get_gttype(struct drm_i915_private *dev_priv) +{ + /* XXX: GT type based on PCI device ID? field seems unused by fw */ + return 0; +} + +static u32 get_core_family(struct drm_i915_private *dev_priv) +{ + switch (INTEL_INFO(dev_priv)->gen) { + case 9: + return GFXCORE_FAMILY_GEN9; + + default: + DRM_ERROR("GUC: unsupported core family\n"); + return GFXCORE_FAMILY_UNKNOWN; + } +} + +static void set_guc_init_params(struct drm_i915_private *dev_priv) +{ + struct intel_guc *guc = &dev_priv->guc; + u32 params[GUC_CTL_MAX_DWORDS]; + int i; + + memset(¶ms, 0, sizeof(params)); + + params[GUC_CTL_DEVICE_INFO] |= + (get_gttype(dev_priv) << GUC_CTL_GTTYPE_SHIFT) | + (get_core_family(dev_priv) << GUC_CTL_COREFAMILY_SHIFT); + + /* + * GuC ARAT increment is 10 ns. GuC default scheduler quantum is one + * second. This ARAR is calculated by: + * Scheduler-Quantum-in-ns / ARAT-increment-in-ns = 1000000000 / 10 + */ + params[GUC_CTL_ARAT_HIGH] = 0; + params[GUC_CTL_ARAT_LOW] = 100000000; + + params[GUC_CTL_WA] |= GUC_CTL_WA_UK_BY_DRIVER; + + params[GUC_CTL_FEATURE] |= GUC_CTL_DISABLE_SCHEDULER | + GUC_CTL_VCS2_ENABLED; + + if (i915.guc_log_level >= 0) { + params[GUC_CTL_LOG_PARAMS] = guc->log_flags; + params[GUC_CTL_DEBUG] = + i915.guc_log_level << GUC_LOG_VERBOSITY_SHIFT; + } + + I915_WRITE(SOFT_SCRATCH(0), 0); + + for (i = 0; i < GUC_CTL_MAX_DWORDS; i++) + I915_WRITE(SOFT_SCRATCH(1 + i), params[i]); +} + +/* + * Read the GuC status register (GUC_STATUS) and store it in the + * specified location; then return a boolean indicating whether + * the value matches either of two values representing completion + * of the GuC boot process. + * + * This is used for polling the GuC status in a wait_for_atomic() + * loop below. + */ +static inline bool guc_ucode_response(struct drm_i915_private *dev_priv, + u32 *status) +{ + u32 val = I915_READ(GUC_STATUS); + *status = val; + return ((val & GS_UKERNEL_MASK) == GS_UKERNEL_READY || + (val & GS_UKERNEL_MASK) == GS_UKERNEL_LAPIC_DONE); +} + +/* + * Transfer the firmware image to RAM for execution by the microcontroller. + * + * GuC Firmware layout: + * +-------------------------------+ ---- + * | CSS header | 128B + * | contains major/minor version | + * +-------------------------------+ ---- + * | uCode | + * +-------------------------------+ ---- + * | RSA signature | 256B + * +-------------------------------+ ---- + * | RSA public Key | 256B + * +-------------------------------+ ---- + * | Public key modulus | 4B + * +-------------------------------+ ---- + * + * Architecturally, the DMA engine is bidirectional, and can potentially even + * transfer between GTT locations. This functionality is left out of the API + * for now as there is no need for it. + * + * Note that GuC needs the CSS header plus uKernel code to be copied by the + * DMA engine in one operation, whereas the RSA signature is loaded via MMIO. + */ + +#define UOS_CSS_HEADER_OFFSET 0 +#define UOS_VER_MINOR_OFFSET 0x44 +#define UOS_VER_MAJOR_OFFSET 0x46 +#define UOS_CSS_HEADER_SIZE 0x80 +#define UOS_RSA_SIG_SIZE 0x100 +#define UOS_CSS_SIGNING_SIZE 0x204 + +static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv) +{ + struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; + struct drm_i915_gem_object *fw_obj = guc_fw->guc_fw_obj; + unsigned long offset; + struct sg_table *sg = fw_obj->pages; + u32 status, ucode_size, rsa[UOS_RSA_SIG_SIZE / sizeof(u32)]; + int i, ret = 0; + + /* uCode size, also is where RSA signature starts */ + offset = ucode_size = guc_fw->guc_fw_size - UOS_CSS_SIGNING_SIZE; + I915_WRITE(DMA_COPY_SIZE, ucode_size); + + /* Copy RSA signature from the fw image to HW for verification */ + sg_pcopy_to_buffer(sg->sgl, sg->nents, rsa, UOS_RSA_SIG_SIZE, offset); + for (i = 0; i < UOS_RSA_SIG_SIZE / sizeof(u32); i++) + I915_WRITE(UOS_RSA_SCRATCH_0 + i * sizeof(u32), rsa[i]); + + /* Set the source address for the new blob */ + offset = i915_gem_obj_ggtt_offset(fw_obj); + I915_WRITE(DMA_ADDR_0_LOW, lower_32_bits(offset)); + I915_WRITE(DMA_ADDR_0_HIGH, upper_32_bits(offset) & 0xFFFF); + + /* + * Set the DMA destination. Current uCode expects the code to be + * loaded at 8k; locations below this are used for the stack. + */ + I915_WRITE(DMA_ADDR_1_LOW, 0x2000); + I915_WRITE(DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM); + + /* Finally start the DMA */ + I915_WRITE(DMA_CTRL, _MASKED_BIT_ENABLE(UOS_MOVE | START_DMA)); + + /* + * Spin-wait for the DMA to complete & the GuC to start up. + * NB: Docs recommend not using the interrupt for completion. + * Measurements indicate this should take no more than 20ms, so a + * timeout here indicates that the GuC has failed and is unusable. + * (Higher levels of the driver will attempt to fall back to + * execlist mode if this happens.) + */ + ret = wait_for_atomic(guc_ucode_response(dev_priv, &status), 100); + + DRM_DEBUG_DRIVER("DMA status 0x%x, GuC status 0x%x\n", + I915_READ(DMA_CTRL), status); + + if ((status & GS_BOOTROM_MASK) == GS_BOOTROM_RSA_FAILED) { + DRM_ERROR("GuC firmware signature verification failed\n"); + ret = -ENOEXEC; + } + + DRM_DEBUG_DRIVER("returning %d\n", ret); + + return ret; +} + +/* + * Load the GuC firmware blob into the MinuteIA. + */ +static int guc_ucode_xfer(struct drm_i915_private *dev_priv) +{ + struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; + struct drm_device *dev = dev_priv->dev; + int ret; + + ret = i915_gem_object_set_to_gtt_domain(guc_fw->guc_fw_obj, false); + if (ret) { + DRM_DEBUG_DRIVER("set-domain failed %d\n", ret); + return ret; + } + + ret = i915_gem_obj_ggtt_pin(guc_fw->guc_fw_obj, 0, 0); + if (ret) { + DRM_DEBUG_DRIVER("pin failed %d\n", ret); + return ret; + } + + /* Invalidate GuC TLB to let GuC take the latest updates to GTT. */ + I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE); + + intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); + + /* init WOPCM */ + I915_WRITE(GUC_WOPCM_SIZE, GUC_WOPCM_SIZE_VALUE); + I915_WRITE(DMA_GUC_WOPCM_OFFSET, GUC_WOPCM_OFFSET_VALUE); + + /* Enable MIA caching. GuC clock gating is disabled. */ + I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE); + + /* WaC6DisallowByGfxPause*/ + I915_WRITE(GEN6_GFXPAUSE, 0x30FFF); + + if (IS_BROXTON(dev)) + I915_WRITE(GEN9LP_GT_PM_CONFIG, GT_DOORBELL_ENABLE); + else + I915_WRITE(GEN9_GT_PM_CONFIG, GT_DOORBELL_ENABLE); + + if (IS_GEN9(dev)) { + /* DOP Clock Gating Enable for GuC clocks */ + I915_WRITE(GEN7_MISCCPCTL, (GEN8_DOP_CLOCK_GATE_GUC_ENABLE | + I915_READ(GEN7_MISCCPCTL))); + + /* allows for 5us before GT can go to RC6 */ + I915_WRITE(GUC_ARAT_C6DIS, 0x1FF); + } + + set_guc_init_params(dev_priv); + + ret = guc_ucode_xfer_dma(dev_priv); + + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); + + /* + * We keep the object pages for reuse during resume. But we can unpin it + * now that DMA has completed, so it doesn't continue to take up space. + */ + i915_gem_object_ggtt_unpin(guc_fw->guc_fw_obj); + + return ret; +} + +/** + * intel_guc_ucode_load() - load GuC uCode into the device + * @dev: drm device + * + * Called from gem_init_hw() during driver loading and also after a GPU reset. + * + * The firmware image should have already been fetched into memory by the + * earlier call to intel_guc_ucode_init(), so here we need only check that + * is succeeded, and then transfer the image to the h/w. + * + * Return: non-zero code on error + */ +int intel_guc_ucode_load(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; + int err = 0; + + DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n", + intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status), + intel_guc_fw_status_repr(guc_fw->guc_fw_load_status)); + + if (guc_fw->guc_fw_fetch_status == GUC_FIRMWARE_NONE) + return 0; + + if (guc_fw->guc_fw_fetch_status == GUC_FIRMWARE_SUCCESS && + guc_fw->guc_fw_load_status == GUC_FIRMWARE_FAIL) + return -ENOEXEC; + + guc_fw->guc_fw_load_status = GUC_FIRMWARE_PENDING; + + DRM_DEBUG_DRIVER("GuC fw fetch status %s\n", + intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status)); + + switch (guc_fw->guc_fw_fetch_status) { + case GUC_FIRMWARE_FAIL: + /* something went wrong :( */ + err = -EIO; + goto fail; + + case GUC_FIRMWARE_NONE: + case GUC_FIRMWARE_PENDING: + default: + /* "can't happen" */ + WARN_ONCE(1, "GuC fw %s invalid guc_fw_fetch_status %s [%d]\n", + guc_fw->guc_fw_path, + intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status), + guc_fw->guc_fw_fetch_status); + err = -ENXIO; + goto fail; + + case GUC_FIRMWARE_SUCCESS: + break; + } + + err = guc_ucode_xfer(dev_priv); + if (err) + goto fail; + + guc_fw->guc_fw_load_status = GUC_FIRMWARE_SUCCESS; + + DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n", + intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status), + intel_guc_fw_status_repr(guc_fw->guc_fw_load_status)); + + return 0; + +fail: + if (guc_fw->guc_fw_load_status == GUC_FIRMWARE_PENDING) + guc_fw->guc_fw_load_status = GUC_FIRMWARE_FAIL; + + return err; +} + +static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw) +{ + struct drm_i915_gem_object *obj; + const struct firmware *fw; + const u8 *css_header; + const size_t minsize = UOS_CSS_HEADER_SIZE + UOS_CSS_SIGNING_SIZE; + const size_t maxsize = GUC_WOPCM_SIZE_VALUE + UOS_CSS_SIGNING_SIZE + - 0x8000; /* 32k reserved (8K stack + 24k context) */ + int err; + + DRM_DEBUG_DRIVER("before requesting firmware: GuC fw fetch status %s\n", + intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status)); + + err = request_firmware(&fw, guc_fw->guc_fw_path, &dev->pdev->dev); + if (err) + goto fail; + if (!fw) + goto fail; + + DRM_DEBUG_DRIVER("fetch GuC fw from %s succeeded, fw %p\n", + guc_fw->guc_fw_path, fw); + DRM_DEBUG_DRIVER("firmware file size %zu (minimum %zu, maximum %zu)\n", + fw->size, minsize, maxsize); + + /* Check the size of the blob befoe examining buffer contents */ + if (fw->size < minsize || fw->size > maxsize) + goto fail; + + /* + * The GuC firmware image has the version number embedded at a well-known + * offset within the firmware blob; note that major / minor version are + * TWO bytes each (i.e. u16), although all pointers and offsets are defined + * in terms of bytes (u8). + */ + css_header = fw->data + UOS_CSS_HEADER_OFFSET; + guc_fw->guc_fw_major_found = *(u16 *)(css_header + UOS_VER_MAJOR_OFFSET); + guc_fw->guc_fw_minor_found = *(u16 *)(css_header + UOS_VER_MINOR_OFFSET); + + if (guc_fw->guc_fw_major_found != guc_fw->guc_fw_major_wanted || + guc_fw->guc_fw_minor_found < guc_fw->guc_fw_minor_wanted) { + DRM_ERROR("GuC firmware version %d.%d, required %d.%d\n", + guc_fw->guc_fw_major_found, guc_fw->guc_fw_minor_found, + guc_fw->guc_fw_major_wanted, guc_fw->guc_fw_minor_wanted); + err = -ENOEXEC; + goto fail; + } + + DRM_DEBUG_DRIVER("firmware version %d.%d OK (minimum %d.%d)\n", + guc_fw->guc_fw_major_found, guc_fw->guc_fw_minor_found, + guc_fw->guc_fw_major_wanted, guc_fw->guc_fw_minor_wanted); + + obj = i915_gem_object_create_from_data(dev, fw->data, fw->size); + if (IS_ERR_OR_NULL(obj)) { + err = obj ? PTR_ERR(obj) : -ENOMEM; + goto fail; + } + + guc_fw->guc_fw_obj = obj; + guc_fw->guc_fw_size = fw->size; + + DRM_DEBUG_DRIVER("GuC fw fetch status SUCCESS, obj %p\n", + guc_fw->guc_fw_obj); + + release_firmware(fw); + guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_SUCCESS; + return; + +fail: + DRM_DEBUG_DRIVER("GuC fw fetch status FAIL; err %d, fw %p, obj %p\n", + err, fw, guc_fw->guc_fw_obj); + DRM_ERROR("Failed to fetch GuC firmware from %s (error %d)\n", + guc_fw->guc_fw_path, err); + + obj = guc_fw->guc_fw_obj; + if (obj) + drm_gem_object_unreference(&obj->base); + guc_fw->guc_fw_obj = NULL; + + release_firmware(fw); /* OK even if fw is NULL */ + guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_FAIL; +} + +/** + * intel_guc_ucode_init() - define parameters and fetch firmware + * @dev: drm device + * + * Called early during driver load, but after GEM is initialised. + * The device struct_mutex must be held by the caller, as we're + * going to allocate a GEM object to hold the firmware image. + * + * The firmware will be transferred to the GuC's memory later, + * when intel_guc_ucode_load() is called. + */ +void intel_guc_ucode_init(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; + const char *fw_path; + + if (!HAS_GUC_SCHED(dev)) + i915.enable_guc_submission = false; + + if (!HAS_GUC_UCODE(dev)) { + fw_path = NULL; + } else if (IS_SKYLAKE(dev)) { + fw_path = I915_SKL_GUC_UCODE; + guc_fw->guc_fw_major_wanted = 3; + guc_fw->guc_fw_minor_wanted = 0; + } else { + i915.enable_guc_submission = false; + fw_path = ""; /* unknown device */ + } + + guc_fw->guc_dev = dev; + guc_fw->guc_fw_path = fw_path; + guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_NONE; + guc_fw->guc_fw_load_status = GUC_FIRMWARE_NONE; + + if (fw_path == NULL) + return; + + if (*fw_path == '\0') { + DRM_ERROR("No GuC firmware known for this platform\n"); + guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_FAIL; + return; + } + + guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_PENDING; + DRM_DEBUG_DRIVER("GuC firmware pending, path %s\n", fw_path); + guc_fw_fetch(dev, guc_fw); + /* status must now be FAIL or SUCCESS */ +} + +/** + * intel_guc_ucode_fini() - clean up all allocated resources + * @dev: drm device + */ +void intel_guc_ucode_fini(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; + + if (guc_fw->guc_fw_obj) + drm_gem_object_unreference(&guc_fw->guc_fw_obj->base); + guc_fw->guc_fw_obj = NULL; + + guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_NONE; +} -- cgit v0.10.2 From fdf5d3572fd1f2103a6bda0dba643e76a3ea978e Mon Sep 17 00:00:00 2001 From: Alex Dai Date: Wed, 12 Aug 2015 15:43:37 +0100 Subject: drm/i915: Debugfs interface to read GuC load status The new node provides access to the status of the GuC-specific loader; also the scratch registers used for communication between the i915 driver and the GuC firmware. v2: Changes to output formats per Chris Wilson's suggestions v6: Rebased Issue: VIZ-4884 Signed-off-by: Alex Dai Signed-off-by: Dave Gordon Reviewed-by: Tom O'Rourke Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 95e7b82..1946411 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2374,6 +2374,44 @@ static int i915_llc(struct seq_file *m, void *data) return 0; } +static int i915_guc_load_status_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = m->private; + struct drm_i915_private *dev_priv = node->minor->dev->dev_private; + struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; + u32 tmp, i; + + if (!HAS_GUC_UCODE(dev_priv->dev)) + return 0; + + seq_printf(m, "GuC firmware status:\n"); + seq_printf(m, "\tpath: %s\n", + guc_fw->guc_fw_path); + seq_printf(m, "\tfetch: %s\n", + intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status)); + seq_printf(m, "\tload: %s\n", + intel_guc_fw_status_repr(guc_fw->guc_fw_load_status)); + seq_printf(m, "\tversion wanted: %d.%d\n", + guc_fw->guc_fw_major_wanted, guc_fw->guc_fw_minor_wanted); + seq_printf(m, "\tversion found: %d.%d\n", + guc_fw->guc_fw_major_found, guc_fw->guc_fw_minor_found); + + tmp = I915_READ(GUC_STATUS); + + seq_printf(m, "\nGuC status 0x%08x:\n", tmp); + seq_printf(m, "\tBootrom status = 0x%x\n", + (tmp & GS_BOOTROM_MASK) >> GS_BOOTROM_SHIFT); + seq_printf(m, "\tuKernel status = 0x%x\n", + (tmp & GS_UKERNEL_MASK) >> GS_UKERNEL_SHIFT); + seq_printf(m, "\tMIA Core status = 0x%x\n", + (tmp & GS_MIA_MASK) >> GS_MIA_SHIFT); + seq_puts(m, "\nScratch registers:\n"); + for (i = 0; i < 16; i++) + seq_printf(m, "\t%2d: \t0x%x\n", i, I915_READ(SOFT_SCRATCH(i))); + + return 0; +} + static int i915_edp_psr_status(struct seq_file *m, void *data) { struct drm_info_node *node = m->private; @@ -5033,6 +5071,7 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_gem_hws_bsd", i915_hws_info, 0, (void *)VCS}, {"i915_gem_hws_vebox", i915_hws_info, 0, (void *)VECS}, {"i915_gem_batch_pool", i915_gem_batch_pool_info, 0}, + {"i915_guc_load_status", i915_guc_load_status_info, 0}, {"i915_frequency_info", i915_frequency_info, 0}, {"i915_hangcheck_info", i915_hangcheck_info, 0}, {"i915_drpc_info", i915_drpc_info, 0}, -- cgit v0.10.2 From 919f1f55d90b5487a9f38e94842e486509474f09 Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Wed, 12 Aug 2015 15:43:38 +0100 Subject: drm/i915: Expose one LRC function for GuC submission mode GuC submission is basically execlist submission, but with the GuC handling the actual writes to the ELSP and the resulting context switch interrupts. So to describe a context for submission via the GuC, we need one of the same functions used in execlist mode. This commit exposes one such function, changing its name to better describe what it does (it's related to logical ring contexts rather than to execlists per se). v2: Replaces previous "drm/i915: Move execlists defines from .c to .h" v3: Incorporates a change to one of the functions exposed here that was previously part of an internal patch, but which was omitted from the version recently committed to drm-intel-nightly: 7a01a0a drm/i915/lrc: Update PDPx registers with lri commands So we reinstate this change here. v4: Drop v3 change, update function parameters due to collision with 8ee3615 drm/i915: Convert execlists_ctx_descriptor() for requests v5: Don't expose execlists_update_context() after all. The current version is no longer compatible with GuC submission; trying to share the execlist version of this function results in both GuC and CPU updating TAIL in the context image, with bad results when they get out of step. The GuC submission path now has its own private version that just updates the ringbuffer start address, and not TAIL or PDPx. v6: Rebased Issue: VIZ-4884 Signed-off-by: Dave Gordon Reviewed-by: Tom O'Rourke Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 138964a..f3411f8 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -270,11 +270,11 @@ u32 intel_execlists_ctx_id(struct drm_i915_gem_object *ctx_obj) return lrca >> 12; } -static uint64_t execlists_ctx_descriptor(struct drm_i915_gem_request *rq) +uint64_t intel_lr_context_descriptor(struct intel_context *ctx, + struct intel_engine_cs *ring) { - struct intel_engine_cs *ring = rq->ring; struct drm_device *dev = ring->dev; - struct drm_i915_gem_object *ctx_obj = rq->ctx->engine[ring->id].state; + struct drm_i915_gem_object *ctx_obj = ctx->engine[ring->id].state; uint64_t desc; uint64_t lrca = i915_gem_obj_ggtt_offset(ctx_obj); @@ -312,13 +312,13 @@ static void execlists_elsp_write(struct drm_i915_gem_request *rq0, uint64_t desc[2]; if (rq1) { - desc[1] = execlists_ctx_descriptor(rq1); + desc[1] = intel_lr_context_descriptor(rq1->ctx, rq1->ring); rq1->elsp_submitted++; } else { desc[1] = 0; } - desc[0] = execlists_ctx_descriptor(rq0); + desc[0] = intel_lr_context_descriptor(rq0->ctx, rq0->ring); rq0->elsp_submitted++; /* You must always write both descriptors in the order below. */ diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index 64f89f99..5e5788c 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -74,6 +74,8 @@ int intel_lr_context_deferred_create(struct intel_context *ctx, void intel_lr_context_unpin(struct drm_i915_gem_request *req); void intel_lr_context_reset(struct drm_device *dev, struct intel_context *ctx); +uint64_t intel_lr_context_descriptor(struct intel_context *ctx, + struct intel_engine_cs *ring); /* Execlists */ int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists); -- cgit v0.10.2 From bac427f8abfc8c11e10274d5edd9db4e4b8e74d3 Mon Sep 17 00:00:00 2001 From: Alex Dai Date: Wed, 12 Aug 2015 15:43:39 +0100 Subject: drm/i915: Prepare for GuC-based command submission This adds the first of the data structures used to communicate with the GuC (the pool of guc_context structures). We create a GuC-specific wrapper round the GEM object allocator as all GEM objects shared with the GuC must be pinned into GGTT space at an address that is NOT in the range [0..WOPCM_TOP), as that range of GGTT addresses is not accessible to the GuC (from the GuC's point of view, it's permanently reserved for other objects such as the BootROM & SRAM). Later, we will need to allocate additional GuC-sharable objects for the submission client(s) and the GuC's debug log. v2: Remove redundant initialisation [Chris Wilson] Defer adding struct members until needed [Chris Wilson] Local functions should pass dev_priv rather than dev [Chris Wilson] v5: Invalidate GuC TLB after allocating and pinning a new object v6: Rebased Issue: VIZ-4884 Signed-off-by: Alex Dai Signed-off-by: Dave Gordon Reviewed-by: Tom O'Rourke Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index cc359e0..ddb69f3 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -41,7 +41,8 @@ i915-y += i915_cmd_parser.o \ intel_uncore.o # general-purpose microcontroller (GuC) support -i915-y += intel_guc_loader.o +i915-y += intel_guc_loader.o \ + i915_guc_submission.o # autogenerated null render state i915-y += intel_renderstate_gen6.o \ diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c new file mode 100644 index 0000000..8ff59aa --- /dev/null +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -0,0 +1,118 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ +#include +#include +#include "i915_drv.h" +#include "intel_guc.h" + +/** + * gem_allocate_guc_obj() - Allocate gem object for GuC usage + * @dev: drm device + * @size: size of object + * + * This is a wrapper to create a gem obj. In order to use it inside GuC, the + * object needs to be pinned lifetime. Also we must pin it to gtt space other + * than [0, GUC_WOPCM_TOP) because this range is reserved inside GuC. + * + * Return: A drm_i915_gem_object if successful, otherwise NULL. + */ +static struct drm_i915_gem_object *gem_allocate_guc_obj(struct drm_device *dev, + u32 size) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj; + + obj = i915_gem_alloc_object(dev, size); + if (!obj) + return NULL; + + if (i915_gem_object_get_pages(obj)) { + drm_gem_object_unreference(&obj->base); + return NULL; + } + + if (i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, + PIN_OFFSET_BIAS | GUC_WOPCM_TOP)) { + drm_gem_object_unreference(&obj->base); + return NULL; + } + + /* Invalidate GuC TLB to let GuC take the latest updates to GTT. */ + I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE); + + return obj; +} + +/** + * gem_release_guc_obj() - Release gem object allocated for GuC usage + * @obj: gem obj to be released + */ +static void gem_release_guc_obj(struct drm_i915_gem_object *obj) +{ + if (!obj) + return; + + if (i915_gem_obj_is_pinned(obj)) + i915_gem_object_ggtt_unpin(obj); + + drm_gem_object_unreference(&obj->base); +} + +/* + * Set up the memory resources to be shared with the GuC. At this point, + * we require just one object that can be mapped through the GGTT. + */ +int i915_guc_submission_init(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + const size_t ctxsize = sizeof(struct guc_context_desc); + const size_t poolsize = GUC_MAX_GPU_CONTEXTS * ctxsize; + const size_t gemsize = round_up(poolsize, PAGE_SIZE); + struct intel_guc *guc = &dev_priv->guc; + + if (!i915.enable_guc_submission) + return 0; /* not enabled */ + + if (guc->ctx_pool_obj) + return 0; /* already allocated */ + + guc->ctx_pool_obj = gem_allocate_guc_obj(dev_priv->dev, gemsize); + if (!guc->ctx_pool_obj) + return -ENOMEM; + + ida_init(&guc->ctx_ids); + + return 0; +} + +void i915_guc_submission_fini(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_guc *guc = &dev_priv->guc; + + if (guc->ctx_pool_obj) + ida_destroy(&guc->ctx_ids); + gem_release_guc_obj(guc->ctx_pool_obj); + guc->ctx_pool_obj = NULL; +} diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index 2846b6d..be3cad8 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -56,6 +56,9 @@ struct intel_guc { struct intel_guc_fw guc_fw; uint32_t log_flags; + + struct drm_i915_gem_object *ctx_pool_obj; + struct ida ctx_ids; }; /* intel_guc_loader.c */ @@ -64,4 +67,8 @@ extern int intel_guc_ucode_load(struct drm_device *dev); extern void intel_guc_ucode_fini(struct drm_device *dev); extern const char *intel_guc_fw_status_repr(enum intel_guc_fw_status status); +/* i915_guc_submission.c */ +int i915_guc_submission_init(struct drm_device *dev); +void i915_guc_submission_fini(struct drm_device *dev); + #endif diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index dd62c31..6ff7fea 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -128,6 +128,21 @@ static void set_guc_init_params(struct drm_i915_private *dev_priv) i915.guc_log_level << GUC_LOG_VERBOSITY_SHIFT; } + /* If GuC submission is enabled, set up additional parameters here */ + if (i915.enable_guc_submission) { + u32 pgs = i915_gem_obj_ggtt_offset(dev_priv->guc.ctx_pool_obj); + u32 ctx_in_16 = GUC_MAX_GPU_CONTEXTS / 16; + + pgs >>= PAGE_SHIFT; + params[GUC_CTL_CTXINFO] = (pgs << GUC_CTL_BASE_ADDR_SHIFT) | + (ctx_in_16 << GUC_CTL_CTXNUM_IN16_SHIFT); + + params[GUC_CTL_FEATURE] |= GUC_CTL_KERNEL_SUBMISSIONS; + + /* Unmask this bit to enable the GuC's internal scheduler */ + params[GUC_CTL_FEATURE] &= ~GUC_CTL_DISABLE_SCHEDULER; + } + I915_WRITE(SOFT_SCRATCH(0), 0); for (i = 0; i < GUC_CTL_MAX_DWORDS; i++) @@ -360,6 +375,10 @@ int intel_guc_ucode_load(struct drm_device *dev) break; } + err = i915_guc_submission_init(dev); + if (err) + goto fail; + err = guc_ucode_xfer(dev_priv); if (err) goto fail; @@ -521,6 +540,8 @@ void intel_guc_ucode_fini(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; + i915_guc_submission_fini(dev); + if (guc_fw->guc_fw_obj) drm_gem_object_unreference(&guc_fw->guc_fw_obj->base); guc_fw->guc_fw_obj = NULL; -- cgit v0.10.2 From 4c7e77fc1007b1e12d25c6e5083369863346f5dd Mon Sep 17 00:00:00 2001 From: Alex Dai Date: Wed, 12 Aug 2015 15:43:40 +0100 Subject: drm/i915: Enable GuC firmware log Allocate a GEM object to hold GuC log data. A debugfs interface (i915_guc_log_dump) is provided to print out the log content. v2: Add struct members at point of use [Chris Wilson] v6: Rebased Issue: VIZ-4884 Signed-off-by: Alex Dai Signed-off-by: Dave Gordon Reviewed-by: Tom O'Rourke Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 1946411..1123b8e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2412,6 +2412,34 @@ static int i915_guc_load_status_info(struct seq_file *m, void *data) return 0; } +static int i915_guc_log_dump(struct seq_file *m, void *data) +{ + struct drm_info_node *node = m->private; + struct drm_device *dev = node->minor->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_gem_object *log_obj = dev_priv->guc.log_obj; + u32 *log; + int i = 0, pg; + + if (!log_obj) + return 0; + + for (pg = 0; pg < log_obj->base.size / PAGE_SIZE; pg++) { + log = kmap_atomic(i915_gem_object_get_page(log_obj, pg)); + + for (i = 0; i < PAGE_SIZE / sizeof(u32); i += 4) + seq_printf(m, "0x%08x 0x%08x 0x%08x 0x%08x\n", + *(log + i), *(log + i + 1), + *(log + i + 2), *(log + i + 3)); + + kunmap_atomic(log); + } + + seq_putc(m, '\n'); + + return 0; +} + static int i915_edp_psr_status(struct seq_file *m, void *data) { struct drm_info_node *node = m->private; @@ -5072,6 +5100,7 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_gem_hws_vebox", i915_hws_info, 0, (void *)VECS}, {"i915_gem_batch_pool", i915_gem_batch_pool_info, 0}, {"i915_guc_load_status", i915_guc_load_status_info, 0}, + {"i915_guc_log_dump", i915_guc_log_dump, 0}, {"i915_frequency_info", i915_frequency_info, 0}, {"i915_hangcheck_info", i915_hangcheck_info, 0}, {"i915_drpc_info", i915_drpc_info, 0}, diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 8ff59aa..669c889 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -79,6 +79,47 @@ static void gem_release_guc_obj(struct drm_i915_gem_object *obj) drm_gem_object_unreference(&obj->base); } +static void guc_create_log(struct intel_guc *guc) +{ + struct drm_i915_private *dev_priv = guc_to_i915(guc); + struct drm_i915_gem_object *obj; + unsigned long offset; + uint32_t size, flags; + + if (i915.guc_log_level < GUC_LOG_VERBOSITY_MIN) + return; + + if (i915.guc_log_level > GUC_LOG_VERBOSITY_MAX) + i915.guc_log_level = GUC_LOG_VERBOSITY_MAX; + + /* The first page is to save log buffer state. Allocate one + * extra page for others in case for overlap */ + size = (1 + GUC_LOG_DPC_PAGES + 1 + + GUC_LOG_ISR_PAGES + 1 + + GUC_LOG_CRASH_PAGES + 1) << PAGE_SHIFT; + + obj = guc->log_obj; + if (!obj) { + obj = gem_allocate_guc_obj(dev_priv->dev, size); + if (!obj) { + /* logging will be off */ + i915.guc_log_level = -1; + return; + } + + guc->log_obj = obj; + } + + /* each allocated unit is a page */ + flags = GUC_LOG_VALID | GUC_LOG_NOTIFY_ON_HALF_FULL | + (GUC_LOG_DPC_PAGES << GUC_LOG_DPC_SHIFT) | + (GUC_LOG_ISR_PAGES << GUC_LOG_ISR_SHIFT) | + (GUC_LOG_CRASH_PAGES << GUC_LOG_CRASH_SHIFT); + + offset = i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT; /* in pages */ + guc->log_flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags; +} + /* * Set up the memory resources to be shared with the GuC. At this point, * we require just one object that can be mapped through the GGTT. @@ -103,6 +144,8 @@ int i915_guc_submission_init(struct drm_device *dev) ida_init(&guc->ctx_ids); + guc_create_log(guc); + return 0; } @@ -111,6 +154,9 @@ void i915_guc_submission_fini(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_guc *guc = &dev_priv->guc; + gem_release_guc_obj(dev_priv->guc.log_obj); + guc->log_obj = NULL; + if (guc->ctx_pool_obj) ida_destroy(&guc->ctx_ids); gem_release_guc_obj(guc->ctx_pool_obj); diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index be3cad8..5b51b05 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -56,6 +56,7 @@ struct intel_guc { struct intel_guc_fw guc_fw; uint32_t log_flags; + struct drm_i915_gem_object *log_obj; struct drm_i915_gem_object *ctx_pool_obj; struct ida ctx_ids; -- cgit v0.10.2 From 44a28b1d36762499de6fd701fcce6814eefe31d7 Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Wed, 12 Aug 2015 15:43:41 +0100 Subject: drm/i915: Implementation of GuC submission client A GuC client has its own doorbell and workqueue. It maintains the doorbell cache line, process description object and work queue item. A default guc_client is created for the i915 driver to use for normal-priority in-order submission. Note that the created client is not yet ready for use; doorbell allocation will fail as we haven't yet linked the GuC's context descriptor to the default contexts for each ring (see later patch). v2: Defer adding structure members until needed [Chris Wilson] Rationalise type declarations [Chris Wilson] v5: Add GuC per-engine submission & seqno statistics. Move wq locking to encompass both get_space() and add_item(). Take forcewake lock in host2guc_action() [Tom O'Rourke] v6: Fix GuC doorbell cacheline selection code (the cacheline-within-page calculation was wrong). Rename GuC priorities to make them closer to the names used in the GuC firmware source, matching what the autogenerated versions will (probably) be. Add per-ring statistics to client. Issue: VIZ-4884 Signed-off-by: Alex Dai Signed-off-by: Dave Gordon Reviewed-by: Tom O'Rourke Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 669c889..3352b85 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -27,6 +27,529 @@ #include "intel_guc.h" /** + * DOC: GuC Client + * + * i915_guc_client: + * We use the term client to avoid confusion with contexts. A i915_guc_client is + * equivalent to GuC object guc_context_desc. This context descriptor is + * allocated from a pool of 1024 entries. Kernel driver will allocate doorbell + * and workqueue for it. Also the process descriptor (guc_process_desc), which + * is mapped to client space. So the client can write Work Item then ring the + * doorbell. + * + * To simplify the implementation, we allocate one gem object that contains all + * pages for doorbell, process descriptor and workqueue. + * + * The Scratch registers: + * There are 16 MMIO-based registers start from 0xC180. The kernel driver writes + * a value to the action register (SOFT_SCRATCH_0) along with any data. It then + * triggers an interrupt on the GuC via another register write (0xC4C8). + * Firmware writes a success/fail code back to the action register after + * processes the request. The kernel driver polls waiting for this update and + * then proceeds. + * See host2guc_action() + * + * Doorbells: + * Doorbells are interrupts to uKernel. A doorbell is a single cache line (QW) + * mapped into process space. + * + * Work Items: + * There are several types of work items that the host may place into a + * workqueue, each with its own requirements and limitations. Currently only + * WQ_TYPE_INORDER is needed to support legacy submission via GuC, which + * represents in-order queue. The kernel driver packs ring tail pointer and an + * ELSP context descriptor dword into Work Item. + * See guc_add_workqueue_item() + * + */ + +/* + * Read GuC command/status register (SOFT_SCRATCH_0) + * Return true if it contains a response rather than a command + */ +static inline bool host2guc_action_response(struct drm_i915_private *dev_priv, + u32 *status) +{ + u32 val = I915_READ(SOFT_SCRATCH(0)); + *status = val; + return GUC2HOST_IS_RESPONSE(val); +} + +static int host2guc_action(struct intel_guc *guc, u32 *data, u32 len) +{ + struct drm_i915_private *dev_priv = guc_to_i915(guc); + u32 status; + int i; + int ret; + + if (WARN_ON(len < 1 || len > 15)) + return -EINVAL; + + intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); + spin_lock(&dev_priv->guc.host2guc_lock); + + dev_priv->guc.action_count += 1; + dev_priv->guc.action_cmd = data[0]; + + for (i = 0; i < len; i++) + I915_WRITE(SOFT_SCRATCH(i), data[i]); + + POSTING_READ(SOFT_SCRATCH(i - 1)); + + I915_WRITE(HOST2GUC_INTERRUPT, HOST2GUC_TRIGGER); + + /* No HOST2GUC command should take longer than 10ms */ + ret = wait_for_atomic(host2guc_action_response(dev_priv, &status), 10); + if (status != GUC2HOST_STATUS_SUCCESS) { + /* + * Either the GuC explicitly returned an error (which + * we convert to -EIO here) or no response at all was + * received within the timeout limit (-ETIMEDOUT) + */ + if (ret != -ETIMEDOUT) + ret = -EIO; + + DRM_ERROR("GUC: host2guc action 0x%X failed. ret=%d " + "status=0x%08X response=0x%08X\n", + data[0], ret, status, + I915_READ(SOFT_SCRATCH(15))); + + dev_priv->guc.action_fail += 1; + dev_priv->guc.action_err = ret; + } + dev_priv->guc.action_status = status; + + spin_unlock(&dev_priv->guc.host2guc_lock); + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); + + return ret; +} + +/* + * Tell the GuC to allocate or deallocate a specific doorbell + */ + +static int host2guc_allocate_doorbell(struct intel_guc *guc, + struct i915_guc_client *client) +{ + u32 data[2]; + + data[0] = HOST2GUC_ACTION_ALLOCATE_DOORBELL; + data[1] = client->ctx_index; + + return host2guc_action(guc, data, 2); +} + +static int host2guc_release_doorbell(struct intel_guc *guc, + struct i915_guc_client *client) +{ + u32 data[2]; + + data[0] = HOST2GUC_ACTION_DEALLOCATE_DOORBELL; + data[1] = client->ctx_index; + + return host2guc_action(guc, data, 2); +} + +/* + * Initialise, update, or clear doorbell data shared with the GuC + * + * These functions modify shared data and so need access to the mapped + * client object which contains the page being used for the doorbell + */ + +static void guc_init_doorbell(struct intel_guc *guc, + struct i915_guc_client *client) +{ + struct guc_doorbell_info *doorbell; + void *base; + + base = kmap_atomic(i915_gem_object_get_page(client->client_obj, 0)); + doorbell = base + client->doorbell_offset; + + doorbell->db_status = 1; + doorbell->cookie = 0; + + kunmap_atomic(base); +} + +static int guc_ring_doorbell(struct i915_guc_client *gc) +{ + struct guc_process_desc *desc; + union guc_doorbell_qw db_cmp, db_exc, db_ret; + union guc_doorbell_qw *db; + void *base; + int attempt = 2, ret = -EAGAIN; + + base = kmap_atomic(i915_gem_object_get_page(gc->client_obj, 0)); + desc = base + gc->proc_desc_offset; + + /* Update the tail so it is visible to GuC */ + desc->tail = gc->wq_tail; + + /* current cookie */ + db_cmp.db_status = GUC_DOORBELL_ENABLED; + db_cmp.cookie = gc->cookie; + + /* cookie to be updated */ + db_exc.db_status = GUC_DOORBELL_ENABLED; + db_exc.cookie = gc->cookie + 1; + if (db_exc.cookie == 0) + db_exc.cookie = 1; + + /* pointer of current doorbell cacheline */ + db = base + gc->doorbell_offset; + + while (attempt--) { + /* lets ring the doorbell */ + db_ret.value_qw = atomic64_cmpxchg((atomic64_t *)db, + db_cmp.value_qw, db_exc.value_qw); + + /* if the exchange was successfully executed */ + if (db_ret.value_qw == db_cmp.value_qw) { + /* db was successfully rung */ + gc->cookie = db_exc.cookie; + ret = 0; + break; + } + + /* XXX: doorbell was lost and need to acquire it again */ + if (db_ret.db_status == GUC_DOORBELL_DISABLED) + break; + + DRM_ERROR("Cookie mismatch. Expected %d, returned %d\n", + db_cmp.cookie, db_ret.cookie); + + /* update the cookie to newly read cookie from GuC */ + db_cmp.cookie = db_ret.cookie; + db_exc.cookie = db_ret.cookie + 1; + if (db_exc.cookie == 0) + db_exc.cookie = 1; + } + + kunmap_atomic(base); + return ret; +} + +static void guc_disable_doorbell(struct intel_guc *guc, + struct i915_guc_client *client) +{ + struct drm_i915_private *dev_priv = guc_to_i915(guc); + struct guc_doorbell_info *doorbell; + void *base; + int drbreg = GEN8_DRBREGL(client->doorbell_id); + int value; + + base = kmap_atomic(i915_gem_object_get_page(client->client_obj, 0)); + doorbell = base + client->doorbell_offset; + + doorbell->db_status = 0; + + kunmap_atomic(base); + + I915_WRITE(drbreg, I915_READ(drbreg) & ~GEN8_DRB_VALID); + + value = I915_READ(drbreg); + WARN_ON((value & GEN8_DRB_VALID) != 0); + + I915_WRITE(GEN8_DRBREGU(client->doorbell_id), 0); + I915_WRITE(drbreg, 0); + + /* XXX: wait for any interrupts */ + /* XXX: wait for workqueue to drain */ +} + +/* + * Select, assign and relase doorbell cachelines + * + * These functions track which doorbell cachelines are in use. + * The data they manipulate is protected by the host2guc lock. + */ + +static uint32_t select_doorbell_cacheline(struct intel_guc *guc) +{ + const uint32_t cacheline_size = cache_line_size(); + uint32_t offset; + + spin_lock(&guc->host2guc_lock); + + /* Doorbell uses a single cache line within a page */ + offset = offset_in_page(guc->db_cacheline); + + /* Moving to next cache line to reduce contention */ + guc->db_cacheline += cacheline_size; + + spin_unlock(&guc->host2guc_lock); + + DRM_DEBUG_DRIVER("selected doorbell cacheline 0x%x, next 0x%x, linesize %u\n", + offset, guc->db_cacheline, cacheline_size); + + return offset; +} + +static uint16_t assign_doorbell(struct intel_guc *guc, uint32_t priority) +{ + /* + * The bitmap is split into two halves; the first half is used for + * normal priority contexts, the second half for high-priority ones. + * Note that logically higher priorities are numerically less than + * normal ones, so the test below means "is it high-priority?" + */ + const bool hi_pri = (priority <= GUC_CTX_PRIORITY_HIGH); + const uint16_t half = GUC_MAX_DOORBELLS / 2; + const uint16_t start = hi_pri ? half : 0; + const uint16_t end = start + half; + uint16_t id; + + spin_lock(&guc->host2guc_lock); + id = find_next_zero_bit(guc->doorbell_bitmap, end, start); + if (id == end) + id = GUC_INVALID_DOORBELL_ID; + else + bitmap_set(guc->doorbell_bitmap, id, 1); + spin_unlock(&guc->host2guc_lock); + + DRM_DEBUG_DRIVER("assigned %s priority doorbell id 0x%x\n", + hi_pri ? "high" : "normal", id); + + return id; +} + +static void release_doorbell(struct intel_guc *guc, uint16_t id) +{ + spin_lock(&guc->host2guc_lock); + bitmap_clear(guc->doorbell_bitmap, id, 1); + spin_unlock(&guc->host2guc_lock); +} + +/* + * Initialise the process descriptor shared with the GuC firmware. + */ +static void guc_init_proc_desc(struct intel_guc *guc, + struct i915_guc_client *client) +{ + struct guc_process_desc *desc; + void *base; + + base = kmap_atomic(i915_gem_object_get_page(client->client_obj, 0)); + desc = base + client->proc_desc_offset; + + memset(desc, 0, sizeof(*desc)); + + /* + * XXX: pDoorbell and WQVBaseAddress are pointers in process address + * space for ring3 clients (set them as in mmap_ioctl) or kernel + * space for kernel clients (map on demand instead? May make debug + * easier to have it mapped). + */ + desc->wq_base_addr = 0; + desc->db_base_addr = 0; + + desc->context_id = client->ctx_index; + desc->wq_size_bytes = client->wq_size; + desc->wq_status = WQ_STATUS_ACTIVE; + desc->priority = client->priority; + + kunmap_atomic(base); +} + +/* + * Initialise/clear the context descriptor shared with the GuC firmware. + * + * This descriptor tells the GuC where (in GGTT space) to find the important + * data structures relating to this client (doorbell, process descriptor, + * write queue, etc). + */ + +static void guc_init_ctx_desc(struct intel_guc *guc, + struct i915_guc_client *client) +{ + struct guc_context_desc desc; + struct sg_table *sg; + + memset(&desc, 0, sizeof(desc)); + + desc.attribute = GUC_CTX_DESC_ATTR_ACTIVE | GUC_CTX_DESC_ATTR_KERNEL; + desc.context_id = client->ctx_index; + desc.priority = client->priority; + desc.engines_used = (1 << RCS) | (1 << VCS) | (1 << BCS) | + (1 << VECS) | (1 << VCS2); /* all engines */ + desc.db_id = client->doorbell_id; + + /* + * The CPU address is only needed at certain points, so kmap_atomic on + * demand instead of storing it in the ctx descriptor. + * XXX: May make debug easier to have it mapped + */ + desc.db_trigger_cpu = 0; + desc.db_trigger_uk = client->doorbell_offset + + i915_gem_obj_ggtt_offset(client->client_obj); + desc.db_trigger_phy = client->doorbell_offset + + sg_dma_address(client->client_obj->pages->sgl); + + desc.process_desc = client->proc_desc_offset + + i915_gem_obj_ggtt_offset(client->client_obj); + + desc.wq_addr = client->wq_offset + + i915_gem_obj_ggtt_offset(client->client_obj); + + desc.wq_size = client->wq_size; + + /* + * XXX: Take LRCs from an existing intel_context if this is not an + * IsKMDCreatedContext client + */ + desc.desc_private = (uintptr_t)client; + + /* Pool context is pinned already */ + sg = guc->ctx_pool_obj->pages; + sg_pcopy_from_buffer(sg->sgl, sg->nents, &desc, sizeof(desc), + sizeof(desc) * client->ctx_index); +} + +static void guc_fini_ctx_desc(struct intel_guc *guc, + struct i915_guc_client *client) +{ + struct guc_context_desc desc; + struct sg_table *sg; + + memset(&desc, 0, sizeof(desc)); + + sg = guc->ctx_pool_obj->pages; + sg_pcopy_from_buffer(sg->sgl, sg->nents, &desc, sizeof(desc), + sizeof(desc) * client->ctx_index); +} + +/* Get valid workqueue item and return it back to offset */ +static int guc_get_workqueue_space(struct i915_guc_client *gc, u32 *offset) +{ + struct guc_process_desc *desc; + void *base; + u32 size = sizeof(struct guc_wq_item); + int ret = 0, timeout_counter = 200; + + base = kmap_atomic(i915_gem_object_get_page(gc->client_obj, 0)); + desc = base + gc->proc_desc_offset; + + while (timeout_counter-- > 0) { + ret = wait_for_atomic(CIRC_SPACE(gc->wq_tail, desc->head, + gc->wq_size) >= size, 1); + + if (!ret) { + *offset = gc->wq_tail; + + /* advance the tail for next workqueue item */ + gc->wq_tail += size; + gc->wq_tail &= gc->wq_size - 1; + + /* this will break the loop */ + timeout_counter = 0; + } + }; + + kunmap_atomic(base); + + return ret; +} + +static int guc_add_workqueue_item(struct i915_guc_client *gc, + struct drm_i915_gem_request *rq) +{ + enum intel_ring_id ring_id = rq->ring->id; + struct guc_wq_item *wqi; + void *base; + u32 tail, wq_len, wq_off = 0; + int ret; + + ret = guc_get_workqueue_space(gc, &wq_off); + if (ret) + return ret; + + /* For now workqueue item is 4 DWs; workqueue buffer is 2 pages. So we + * should not have the case where structure wqi is across page, neither + * wrapped to the beginning. This simplifies the implementation below. + * + * XXX: if not the case, we need save data to a temp wqi and copy it to + * workqueue buffer dw by dw. + */ + WARN_ON(sizeof(struct guc_wq_item) != 16); + WARN_ON(wq_off & 3); + + /* wq starts from the page after doorbell / process_desc */ + base = kmap_atomic(i915_gem_object_get_page(gc->client_obj, + (wq_off + GUC_DB_SIZE) >> PAGE_SHIFT)); + wq_off &= PAGE_SIZE - 1; + wqi = (struct guc_wq_item *)((char *)base + wq_off); + + /* len does not include the header */ + wq_len = sizeof(struct guc_wq_item) / sizeof(u32) - 1; + wqi->header = WQ_TYPE_INORDER | + (wq_len << WQ_LEN_SHIFT) | + (ring_id << WQ_TARGET_SHIFT) | + WQ_NO_WCFLUSH_WAIT; + + /* The GuC wants only the low-order word of the context descriptor */ + wqi->context_desc = (u32)intel_lr_context_descriptor(rq->ctx, rq->ring); + + /* The GuC firmware wants the tail index in QWords, not bytes */ + tail = rq->ringbuf->tail >> 3; + wqi->ring_tail = tail << WQ_RING_TAIL_SHIFT; + wqi->fence_id = 0; /*XXX: what fence to be here */ + + kunmap_atomic(base); + + return 0; +} + +/** + * i915_guc_submit() - Submit commands through GuC + * @client: the guc client where commands will go through + * @ctx: LRC where commands come from + * @ring: HW engine that will excute the commands + * + * Return: 0 if succeed + */ +int i915_guc_submit(struct i915_guc_client *client, + struct drm_i915_gem_request *rq) +{ + struct intel_guc *guc = client->guc; + enum intel_ring_id ring_id = rq->ring->id; + unsigned long flags; + int q_ret, b_ret; + + spin_lock_irqsave(&client->wq_lock, flags); + + q_ret = guc_add_workqueue_item(client, rq); + if (q_ret == 0) + b_ret = guc_ring_doorbell(client); + + client->submissions[ring_id] += 1; + if (q_ret) { + client->q_fail += 1; + client->retcode = q_ret; + } else if (b_ret) { + client->b_fail += 1; + client->retcode = q_ret = b_ret; + } else { + client->retcode = 0; + } + spin_unlock_irqrestore(&client->wq_lock, flags); + + spin_lock(&guc->host2guc_lock); + guc->submissions[ring_id] += 1; + guc->last_seqno[ring_id] = rq->seqno; + spin_unlock(&guc->host2guc_lock); + + return q_ret; +} + +/* + * Everything below here is concerned with setup & teardown, and is + * therefore not part of the somewhat time-critical batch-submission + * path of i915_guc_submit() above. + */ + +/** * gem_allocate_guc_obj() - Allocate gem object for GuC usage * @dev: drm device * @size: size of object @@ -79,6 +602,121 @@ static void gem_release_guc_obj(struct drm_i915_gem_object *obj) drm_gem_object_unreference(&obj->base); } +static void guc_client_free(struct drm_device *dev, + struct i915_guc_client *client) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_guc *guc = &dev_priv->guc; + + if (!client) + return; + + if (client->doorbell_id != GUC_INVALID_DOORBELL_ID) { + /* + * First disable the doorbell, then tell the GuC we've + * finished with it, finally deallocate it in our bitmap + */ + guc_disable_doorbell(guc, client); + host2guc_release_doorbell(guc, client); + release_doorbell(guc, client->doorbell_id); + } + + /* + * XXX: wait for any outstanding submissions before freeing memory. + * Be sure to drop any locks + */ + + gem_release_guc_obj(client->client_obj); + + if (client->ctx_index != GUC_INVALID_CTX_ID) { + guc_fini_ctx_desc(guc, client); + ida_simple_remove(&guc->ctx_ids, client->ctx_index); + } + + kfree(client); +} + +/** + * guc_client_alloc() - Allocate an i915_guc_client + * @dev: drm device + * @priority: four levels priority _CRITICAL, _HIGH, _NORMAL and _LOW + * The kernel client to replace ExecList submission is created with + * NORMAL priority. Priority of a client for scheduler can be HIGH, + * while a preemption context can use CRITICAL. + * + * Return: An i915_guc_client object if success. + */ +static struct i915_guc_client *guc_client_alloc(struct drm_device *dev, + uint32_t priority) +{ + struct i915_guc_client *client; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_guc *guc = &dev_priv->guc; + struct drm_i915_gem_object *obj; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) + return NULL; + + client->doorbell_id = GUC_INVALID_DOORBELL_ID; + client->priority = priority; + client->guc = guc; + + client->ctx_index = (uint32_t)ida_simple_get(&guc->ctx_ids, 0, + GUC_MAX_GPU_CONTEXTS, GFP_KERNEL); + if (client->ctx_index >= GUC_MAX_GPU_CONTEXTS) { + client->ctx_index = GUC_INVALID_CTX_ID; + goto err; + } + + /* The first page is doorbell/proc_desc. Two followed pages are wq. */ + obj = gem_allocate_guc_obj(dev, GUC_DB_SIZE + GUC_WQ_SIZE); + if (!obj) + goto err; + + client->client_obj = obj; + client->wq_offset = GUC_DB_SIZE; + client->wq_size = GUC_WQ_SIZE; + spin_lock_init(&client->wq_lock); + + client->doorbell_offset = select_doorbell_cacheline(guc); + + /* + * Since the doorbell only requires a single cacheline, we can save + * space by putting the application process descriptor in the same + * page. Use the half of the page that doesn't include the doorbell. + */ + if (client->doorbell_offset >= (GUC_DB_SIZE / 2)) + client->proc_desc_offset = 0; + else + client->proc_desc_offset = (GUC_DB_SIZE / 2); + + client->doorbell_id = assign_doorbell(guc, client->priority); + if (client->doorbell_id == GUC_INVALID_DOORBELL_ID) + /* XXX: evict a doorbell instead */ + goto err; + + guc_init_proc_desc(guc, client); + guc_init_ctx_desc(guc, client); + guc_init_doorbell(guc, client); + + /* XXX: Any cache flushes needed? General domain mgmt calls? */ + + if (host2guc_allocate_doorbell(guc, client)) + goto err; + + DRM_DEBUG_DRIVER("new priority %u client %p: ctx_index %u db_id %u\n", + priority, client, client->ctx_index, client->doorbell_id); + + return client; + +err: + DRM_ERROR("FAILED to create priority %u GuC client!\n", priority); + + guc_client_free(dev, client); + return NULL; +} + static void guc_create_log(struct intel_guc *guc) { struct drm_i915_private *dev_priv = guc_to_i915(guc); @@ -142,6 +780,8 @@ int i915_guc_submission_init(struct drm_device *dev) if (!guc->ctx_pool_obj) return -ENOMEM; + spin_lock_init(&dev_priv->guc.host2guc_lock); + ida_init(&guc->ctx_ids); guc_create_log(guc); @@ -149,6 +789,32 @@ int i915_guc_submission_init(struct drm_device *dev) return 0; } +int i915_guc_submission_enable(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_guc *guc = &dev_priv->guc; + struct i915_guc_client *client; + + /* client for execbuf submission */ + client = guc_client_alloc(dev, GUC_CTX_PRIORITY_KMD_NORMAL); + if (!client) { + DRM_ERROR("Failed to create execbuf guc_client\n"); + return -ENOMEM; + } + + guc->execbuf_client = client; + return 0; +} + +void i915_guc_submission_disable(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_guc *guc = &dev_priv->guc; + + guc_client_free(dev, guc->execbuf_client); + guc->execbuf_client = NULL; +} + void i915_guc_submission_fini(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index 5b51b05..92658ce 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -27,6 +27,31 @@ #include "intel_guc_fwif.h" #include "i915_guc_reg.h" +struct i915_guc_client { + struct drm_i915_gem_object *client_obj; + struct intel_guc *guc; + uint32_t priority; + uint32_t ctx_index; + + uint32_t proc_desc_offset; + uint32_t doorbell_offset; + uint32_t cookie; + uint16_t doorbell_id; + uint16_t padding; /* Maintain alignment */ + + uint32_t wq_offset; + uint32_t wq_size; + + spinlock_t wq_lock; /* Protects all data below */ + uint32_t wq_tail; + + /* GuC submission statistics & status */ + uint64_t submissions[I915_NUM_RINGS]; + uint32_t q_fail; + uint32_t b_fail; + int retcode; +}; + enum intel_guc_fw_status { GUC_FIRMWARE_FAIL = -1, GUC_FIRMWARE_NONE = 0, @@ -60,6 +85,23 @@ struct intel_guc { struct drm_i915_gem_object *ctx_pool_obj; struct ida ctx_ids; + + struct i915_guc_client *execbuf_client; + + spinlock_t host2guc_lock; /* Protects all data below */ + + DECLARE_BITMAP(doorbell_bitmap, GUC_MAX_DOORBELLS); + uint32_t db_cacheline; /* Cyclic counter mod pagesize */ + + /* Action status & statistics */ + uint64_t action_count; /* Total commands issued */ + uint32_t action_cmd; /* Last command word */ + uint32_t action_status; /* Last return status */ + uint32_t action_fail; /* Total number of failures */ + int32_t action_err; /* Last error code */ + + uint64_t submissions[I915_NUM_RINGS]; + uint32_t last_seqno[I915_NUM_RINGS]; }; /* intel_guc_loader.c */ @@ -70,6 +112,10 @@ extern const char *intel_guc_fw_status_repr(enum intel_guc_fw_status status); /* i915_guc_submission.c */ int i915_guc_submission_init(struct drm_device *dev); +int i915_guc_submission_enable(struct drm_device *dev); +int i915_guc_submit(struct i915_guc_client *client, + struct drm_i915_gem_request *rq); +void i915_guc_submission_disable(struct drm_device *dev); void i915_guc_submission_fini(struct drm_device *dev); #endif diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h index 06aad6f..950c7e7 100644 --- a/drivers/gpu/drm/i915/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h @@ -35,10 +35,10 @@ #define GFXCORE_FAMILY_GEN9 12 #define GFXCORE_FAMILY_UNKNOWN 0x7fffffff -#define GUC_CTX_PRIORITY_CRITICAL 0 +#define GUC_CTX_PRIORITY_KMD_HIGH 0 #define GUC_CTX_PRIORITY_HIGH 1 -#define GUC_CTX_PRIORITY_NORMAL 2 -#define GUC_CTX_PRIORITY_LOW 3 +#define GUC_CTX_PRIORITY_KMD_NORMAL 2 +#define GUC_CTX_PRIORITY_NORMAL 3 #define GUC_MAX_GPU_CONTEXTS 1024 #define GUC_INVALID_CTX_ID (GUC_MAX_GPU_CONTEXTS + 1) diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 6ff7fea..8b4b057 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -342,6 +342,8 @@ int intel_guc_ucode_load(struct drm_device *dev) intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status), intel_guc_fw_status_repr(guc_fw->guc_fw_load_status)); + i915_guc_submission_disable(dev); + if (guc_fw->guc_fw_fetch_status == GUC_FIRMWARE_NONE) return 0; @@ -389,12 +391,20 @@ int intel_guc_ucode_load(struct drm_device *dev) intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status), intel_guc_fw_status_repr(guc_fw->guc_fw_load_status)); + if (i915.enable_guc_submission) { + err = i915_guc_submission_enable(dev); + if (err) + goto fail; + } + return 0; fail: if (guc_fw->guc_fw_load_status == GUC_FIRMWARE_PENDING) guc_fw->guc_fw_load_status = GUC_FIRMWARE_FAIL; + i915_guc_submission_disable(dev); + return err; } -- cgit v0.10.2 From 4df001d3989ed319bc5abf2058dc5173bb02c53b Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Wed, 12 Aug 2015 15:43:42 +0100 Subject: drm/i915: Interrupt routing for GuC submission Turn on interrupt steering to route necessary interrupts to GuC. v6: Rebased Issue: VIZ-4884 Signed-off-by: Alex Dai Signed-off-by: Dave Gordon Reviewed-by: Tom O'Rourke Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 651d0dd..5cdb328 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1674,6 +1674,7 @@ enum skl_disp_power_wells { #define GFX_MODE_GEN7 0x0229c #define RING_MODE_GEN7(ring) ((ring)->mmio_base+0x29c) #define GFX_RUN_LIST_ENABLE (1<<15) +#define GFX_INTERRUPT_STEERING (1<<14) #define GFX_TLB_INVALIDATE_EXPLICIT (1<<13) #define GFX_SURFACE_FAULT_ENABLE (1<<12) #define GFX_REPLAY_MODE (1<<11) @@ -1681,6 +1682,11 @@ enum skl_disp_power_wells { #define GFX_PPGTT_ENABLE (1<<9) #define GEN8_GFX_PPGTT_48B (1<<7) +#define GFX_FORWARD_VBLANK_MASK (3<<5) +#define GFX_FORWARD_VBLANK_NEVER (0<<5) +#define GFX_FORWARD_VBLANK_ALWAYS (1<<5) +#define GFX_FORWARD_VBLANK_COND (2<<5) + #define VLV_DISPLAY_BASE 0x180000 #define VLV_MIPI_BASE VLV_DISPLAY_BASE @@ -5695,11 +5701,12 @@ enum skl_disp_power_wells { #define GEN8_GT_IIR(which) (0x44308 + (0x10 * (which))) #define GEN8_GT_IER(which) (0x4430c + (0x10 * (which))) -#define GEN8_BCS_IRQ_SHIFT 16 #define GEN8_RCS_IRQ_SHIFT 0 -#define GEN8_VCS2_IRQ_SHIFT 16 +#define GEN8_BCS_IRQ_SHIFT 16 #define GEN8_VCS1_IRQ_SHIFT 0 +#define GEN8_VCS2_IRQ_SHIFT 16 #define GEN8_VECS_IRQ_SHIFT 0 +#define GEN8_WD_IRQ_SHIFT 16 #define GEN8_DE_PIPE_ISR(pipe) (0x44400 + (0x10 * (pipe))) #define GEN8_DE_PIPE_IMR(pipe) (0x44404 + (0x10 * (pipe))) diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 8b4b057..13e75f6 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -79,6 +79,53 @@ const char *intel_guc_fw_status_repr(enum intel_guc_fw_status status) } }; +static void direct_interrupts_to_host(struct drm_i915_private *dev_priv) +{ + struct intel_engine_cs *ring; + int i, irqs; + + /* tell all command streamers NOT to forward interrupts and vblank to GuC */ + irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_NEVER); + irqs |= _MASKED_BIT_DISABLE(GFX_INTERRUPT_STEERING); + for_each_ring(ring, dev_priv, i) + I915_WRITE(RING_MODE_GEN7(ring), irqs); + + /* tell DE to send nothing to GuC */ + I915_WRITE(DE_GUCRMR, ~0); + + /* route all GT interrupts to the host */ + I915_WRITE(GUC_BCS_RCS_IER, 0); + I915_WRITE(GUC_VCS2_VCS1_IER, 0); + I915_WRITE(GUC_WD_VECS_IER, 0); +} + +static void direct_interrupts_to_guc(struct drm_i915_private *dev_priv) +{ + struct intel_engine_cs *ring; + int i, irqs; + + /* tell all command streamers to forward interrupts and vblank to GuC */ + irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_ALWAYS); + irqs |= _MASKED_BIT_ENABLE(GFX_INTERRUPT_STEERING); + for_each_ring(ring, dev_priv, i) + I915_WRITE(RING_MODE_GEN7(ring), irqs); + + /* tell DE to send (all) flip_done to GuC */ + irqs = DERRMR_PIPEA_PRI_FLIP_DONE | DERRMR_PIPEA_SPR_FLIP_DONE | + DERRMR_PIPEB_PRI_FLIP_DONE | DERRMR_PIPEB_SPR_FLIP_DONE | + DERRMR_PIPEC_PRI_FLIP_DONE | DERRMR_PIPEC_SPR_FLIP_DONE; + /* Unmasked bits will cause GuC response message to be sent */ + I915_WRITE(DE_GUCRMR, ~irqs); + + /* route USER_INTERRUPT to Host, all others are sent to GuC. */ + irqs = GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT | + GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT; + /* These three registers have the same bit definitions */ + I915_WRITE(GUC_BCS_RCS_IER, ~irqs); + I915_WRITE(GUC_VCS2_VCS1_IER, ~irqs); + I915_WRITE(GUC_WD_VECS_IER, ~irqs); +} + static u32 get_gttype(struct drm_i915_private *dev_priv) { /* XXX: GT type based on PCI device ID? field seems unused by fw */ @@ -342,6 +389,7 @@ int intel_guc_ucode_load(struct drm_device *dev) intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status), intel_guc_fw_status_repr(guc_fw->guc_fw_load_status)); + direct_interrupts_to_host(dev_priv); i915_guc_submission_disable(dev); if (guc_fw->guc_fw_fetch_status == GUC_FIRMWARE_NONE) @@ -395,6 +443,7 @@ int intel_guc_ucode_load(struct drm_device *dev) err = i915_guc_submission_enable(dev); if (err) goto fail; + direct_interrupts_to_guc(dev_priv); } return 0; @@ -403,6 +452,7 @@ fail: if (guc_fw->guc_fw_load_status == GUC_FIRMWARE_PENDING) guc_fw->guc_fw_load_status = GUC_FIRMWARE_FAIL; + direct_interrupts_to_host(dev_priv); i915_guc_submission_disable(dev); return err; @@ -550,6 +600,7 @@ void intel_guc_ucode_fini(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; + direct_interrupts_to_host(dev_priv); i915_guc_submission_fini(dev); if (guc_fw->guc_fw_obj) -- cgit v0.10.2 From d1675198ed1f21aec6e036336e4340c40b726497 Mon Sep 17 00:00:00 2001 From: Alex Dai Date: Wed, 12 Aug 2015 15:43:43 +0100 Subject: drm/i915: Integrate GuC-based command submission GuC-based submission is mostly the same as execlist mode, up to intel_logical_ring_advance_and_submit(), where the context being dispatched would be added to the execlist queue; at this point we submit the context to the GuC backend instead. There are, however, a few other changes also required, notably: 1. Contexts must be pinned at GGTT addresses accessible by the GuC i.e. NOT in the range [0..WOPCM_SIZE), so we have to add the PIN_OFFSET_BIAS flag to the relevant GGTT-pinning calls. 2. The GuC's TLB must be invalidated after a context is pinned at a new GGTT address. 3. GuC firmware uses the one page before Ring Context as shared data. Therefore, whenever driver wants to get base address of LRC, we will offset one page for it. LRC_PPHWSP_PN is defined as the page number of LRCA. 4. In the work queue used to pass requests to the GuC, the GuC firmware requires the ring-tail-offset to be represented as an 11-bit value, expressed in QWords. Therefore, the ringbuffer size must be reduced to the representable range (4 pages). v2: Defer adding #defines until needed [Chris Wilson] Rationalise type declarations [Chris Wilson] v4: Squashed kerneldoc patch into here [Daniel Vetter] v5: Update request->tail in code common to both GuC and execlist modes. Add a private version of lr_context_update(), as sharing the execlist version leads to race conditions when the CPU and the GuC both update TAIL in the context image. Conversion of error-captured HWS page to string must account for offset from start of object to actual HWS (LRC_PPHWSP_PN). Issue: VIZ-4884 Signed-off-by: Alex Dai Signed-off-by: Dave Gordon Reviewed-by: Tom O'Rourke Signed-off-by: Daniel Vetter diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 9ddf8c6..069958c 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -4238,6 +4238,20 @@ int num_ioctls; + GuC-based Command Submission + + GuC +!Pdrivers/gpu/drm/i915/intel_guc_loader.c GuC-specific firmware loader +!Idrivers/gpu/drm/i915/intel_guc_loader.c + + + GuC Client +!Pdrivers/gpu/drm/i915/intel_guc_submission.c GuC-based command submissison +!Idrivers/gpu/drm/i915/intel_guc_submission.c + + + + Tracing This sections covers all things related to the tracepoints implemented in diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 1123b8e..a815fcc 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1995,7 +1995,7 @@ static void i915_dump_lrc_obj(struct seq_file *m, return; } - page = i915_gem_object_get_page(ctx_obj, 1); + page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); if (!WARN_ON(page == NULL)) { reg_state = kmap_atomic(page); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 0d0a7b1..493e9b2 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -462,17 +462,17 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, } if ((obj = error->ring[i].hws_page)) { - err_printf(m, "%s --- HW Status = 0x%08x\n", - dev_priv->ring[i].name, - lower_32_bits(obj->gtt_offset)); + err_printf(m, "%s --- HW Status = 0x%08llx\n", + dev_priv->ring[i].name, + obj->gtt_offset + LRC_PPHWSP_PN * PAGE_SIZE); offset = 0; for (elt = 0; elt < PAGE_SIZE/16; elt += 4) { err_printf(m, "[%04x] %08x %08x %08x %08x\n", offset, - obj->pages[0][elt], - obj->pages[0][elt+1], - obj->pages[0][elt+2], - obj->pages[0][elt+3]); + obj->pages[LRC_PPHWSP_PN][elt], + obj->pages[LRC_PPHWSP_PN][elt+1], + obj->pages[LRC_PPHWSP_PN][elt+2], + obj->pages[LRC_PPHWSP_PN][elt+3]); offset += 16; } } diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 3352b85..ec70393 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -364,18 +364,58 @@ static void guc_init_proc_desc(struct intel_guc *guc, static void guc_init_ctx_desc(struct intel_guc *guc, struct i915_guc_client *client) { + struct intel_context *ctx = client->owner; struct guc_context_desc desc; struct sg_table *sg; + int i; memset(&desc, 0, sizeof(desc)); desc.attribute = GUC_CTX_DESC_ATTR_ACTIVE | GUC_CTX_DESC_ATTR_KERNEL; desc.context_id = client->ctx_index; desc.priority = client->priority; - desc.engines_used = (1 << RCS) | (1 << VCS) | (1 << BCS) | - (1 << VECS) | (1 << VCS2); /* all engines */ desc.db_id = client->doorbell_id; + for (i = 0; i < I915_NUM_RINGS; i++) { + struct guc_execlist_context *lrc = &desc.lrc[i]; + struct intel_ringbuffer *ringbuf = ctx->engine[i].ringbuf; + struct intel_engine_cs *ring; + struct drm_i915_gem_object *obj; + uint64_t ctx_desc; + + /* TODO: We have a design issue to be solved here. Only when we + * receive the first batch, we know which engine is used by the + * user. But here GuC expects the lrc and ring to be pinned. It + * is not an issue for default context, which is the only one + * for now who owns a GuC client. But for future owner of GuC + * client, need to make sure lrc is pinned prior to enter here. + */ + obj = ctx->engine[i].state; + if (!obj) + break; /* XXX: continue? */ + + ring = ringbuf->ring; + ctx_desc = intel_lr_context_descriptor(ctx, ring); + lrc->context_desc = (u32)ctx_desc; + + /* The state page is after PPHWSP */ + lrc->ring_lcra = i915_gem_obj_ggtt_offset(obj) + + LRC_STATE_PN * PAGE_SIZE; + lrc->context_id = (client->ctx_index << GUC_ELC_CTXID_OFFSET) | + (ring->id << GUC_ELC_ENGINE_OFFSET); + + obj = ringbuf->obj; + + lrc->ring_begin = i915_gem_obj_ggtt_offset(obj); + lrc->ring_end = lrc->ring_begin + obj->base.size - 1; + lrc->ring_next_free_location = lrc->ring_begin; + lrc->ring_current_tail_pointer_value = 0; + + desc.engines_used |= (1 << ring->id); + } + + WARN_ON(desc.engines_used == 0); + /* * The CPU address is only needed at certain points, so kmap_atomic on * demand instead of storing it in the ctx descriptor. @@ -501,6 +541,29 @@ static int guc_add_workqueue_item(struct i915_guc_client *gc, return 0; } +#define CTX_RING_BUFFER_START 0x08 + +/* Update the ringbuffer pointer in a saved context image */ +static void lr_context_update(struct drm_i915_gem_request *rq) +{ + enum intel_ring_id ring_id = rq->ring->id; + struct drm_i915_gem_object *ctx_obj = rq->ctx->engine[ring_id].state; + struct drm_i915_gem_object *rb_obj = rq->ringbuf->obj; + struct page *page; + uint32_t *reg_state; + + BUG_ON(!ctx_obj); + WARN_ON(!i915_gem_obj_is_pinned(ctx_obj)); + WARN_ON(!i915_gem_obj_is_pinned(rb_obj)); + + page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); + reg_state = kmap_atomic(page); + + reg_state[CTX_RING_BUFFER_START+1] = i915_gem_obj_ggtt_offset(rb_obj); + + kunmap_atomic(reg_state); +} + /** * i915_guc_submit() - Submit commands through GuC * @client: the guc client where commands will go through @@ -517,6 +580,10 @@ int i915_guc_submit(struct i915_guc_client *client, unsigned long flags; int q_ret, b_ret; + /* Need this because of the deferred pin ctx and ring */ + /* Shall we move this right after ring is pinned? */ + lr_context_update(rq); + spin_lock_irqsave(&client->wq_lock, flags); q_ret = guc_add_workqueue_item(client, rq); @@ -643,11 +710,13 @@ static void guc_client_free(struct drm_device *dev, * The kernel client to replace ExecList submission is created with * NORMAL priority. Priority of a client for scheduler can be HIGH, * while a preemption context can use CRITICAL. + * @ctx the context to own the client (we use the default render context) * * Return: An i915_guc_client object if success. */ static struct i915_guc_client *guc_client_alloc(struct drm_device *dev, - uint32_t priority) + uint32_t priority, + struct intel_context *ctx) { struct i915_guc_client *client; struct drm_i915_private *dev_priv = dev->dev_private; @@ -660,6 +729,7 @@ static struct i915_guc_client *guc_client_alloc(struct drm_device *dev, client->doorbell_id = GUC_INVALID_DOORBELL_ID; client->priority = priority; + client->owner = ctx; client->guc = guc; client->ctx_index = (uint32_t)ida_simple_get(&guc->ctx_ids, 0, @@ -793,10 +863,11 @@ int i915_guc_submission_enable(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_guc *guc = &dev_priv->guc; + struct intel_context *ctx = dev_priv->ring[RCS].default_context; struct i915_guc_client *client; /* client for execbuf submission */ - client = guc_client_alloc(dev, GUC_CTX_PRIORITY_KMD_NORMAL); + client = guc_client_alloc(dev, GUC_CTX_PRIORITY_KMD_NORMAL, ctx); if (!client) { DRM_ERROR("Failed to create execbuf guc_client\n"); return -ENOMEM; diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index 92658ce..4ec2d27 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -29,6 +29,7 @@ struct i915_guc_client { struct drm_i915_gem_object *client_obj; + struct intel_context *owner; struct intel_guc *guc; uint32_t priority; uint32_t ctx_index; diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index f3411f8..e77b6b0 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -263,7 +263,8 @@ int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists */ u32 intel_execlists_ctx_id(struct drm_i915_gem_object *ctx_obj) { - u32 lrca = i915_gem_obj_ggtt_offset(ctx_obj); + u32 lrca = i915_gem_obj_ggtt_offset(ctx_obj) + + LRC_PPHWSP_PN * PAGE_SIZE; /* LRCA is required to be 4K aligned so the more significant 20 bits * are globally unique */ @@ -276,7 +277,8 @@ uint64_t intel_lr_context_descriptor(struct intel_context *ctx, struct drm_device *dev = ring->dev; struct drm_i915_gem_object *ctx_obj = ctx->engine[ring->id].state; uint64_t desc; - uint64_t lrca = i915_gem_obj_ggtt_offset(ctx_obj); + uint64_t lrca = i915_gem_obj_ggtt_offset(ctx_obj) + + LRC_PPHWSP_PN * PAGE_SIZE; WARN_ON(lrca & 0xFFFFFFFF00000FFFULL); @@ -350,7 +352,7 @@ static int execlists_update_context(struct drm_i915_gem_request *rq) WARN_ON(!i915_gem_obj_is_pinned(ctx_obj)); WARN_ON(!i915_gem_obj_is_pinned(rb_obj)); - page = i915_gem_object_get_page(ctx_obj, 1); + page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); reg_state = kmap_atomic(page); reg_state[CTX_RING_TAIL+1] = rq->tail; @@ -548,8 +550,6 @@ static int execlists_context_queue(struct drm_i915_gem_request *request) i915_gem_request_reference(request); - request->tail = request->ringbuf->tail; - spin_lock_irq(&ring->execlist_lock); list_for_each_entry(cursor, &ring->execlist_queue, execlist_link) @@ -702,13 +702,19 @@ static void intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request) { struct intel_engine_cs *ring = request->ring; + struct drm_i915_private *dev_priv = request->i915; intel_logical_ring_advance(request->ringbuf); + request->tail = request->ringbuf->tail; + if (intel_ring_stopped(ring)) return; - execlists_context_queue(request); + if (dev_priv->guc.execbuf_client) + i915_guc_submit(dev_priv->guc.execbuf_client, request); + else + execlists_context_queue(request); } static void __wrap_ring_buffer(struct intel_ringbuffer *ringbuf) @@ -998,6 +1004,7 @@ int logical_ring_flush_all_caches(struct drm_i915_gem_request *req) static int intel_lr_context_pin(struct drm_i915_gem_request *rq) { + struct drm_i915_private *dev_priv = rq->i915; struct intel_engine_cs *ring = rq->ring; struct drm_i915_gem_object *ctx_obj = rq->ctx->engine[ring->id].state; struct intel_ringbuffer *ringbuf = rq->ringbuf; @@ -1005,14 +1012,18 @@ static int intel_lr_context_pin(struct drm_i915_gem_request *rq) WARN_ON(!mutex_is_locked(&ring->dev->struct_mutex)); if (rq->ctx->engine[ring->id].pin_count++ == 0) { - ret = i915_gem_obj_ggtt_pin(ctx_obj, - GEN8_LR_CONTEXT_ALIGN, 0); + ret = i915_gem_obj_ggtt_pin(ctx_obj, GEN8_LR_CONTEXT_ALIGN, + PIN_OFFSET_BIAS | GUC_WOPCM_TOP); if (ret) goto reset_pin_count; ret = intel_pin_and_map_ringbuffer_obj(ring->dev, ringbuf); if (ret) goto unpin_ctx_obj; + + /* Invalidate GuC TLB. */ + if (i915.enable_guc_submission) + I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE); } return ret; @@ -2137,7 +2148,7 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o /* The second page of the context object contains some fields which must * be set up prior to the first execution. */ - page = i915_gem_object_get_page(ctx_obj, 1); + page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); reg_state = kmap_atomic(page); /* A context is actually a big batch buffer with several MI_LOAD_REGISTER_IMM @@ -2307,12 +2318,13 @@ static void lrc_setup_hardware_status_page(struct intel_engine_cs *ring, struct drm_i915_gem_object *default_ctx_obj) { struct drm_i915_private *dev_priv = ring->dev->dev_private; + struct page *page; - /* The status page is offset 0 from the default context object - * in LRC mode. */ - ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(default_ctx_obj); - ring->status_page.page_addr = - kmap(sg_page(default_ctx_obj->pages->sgl)); + /* The HWSP is part of the default context object in LRC mode. */ + ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(default_ctx_obj) + + LRC_PPHWSP_PN * PAGE_SIZE; + page = i915_gem_object_get_page(default_ctx_obj, LRC_PPHWSP_PN); + ring->status_page.page_addr = kmap(page); ring->status_page.obj = default_ctx_obj; I915_WRITE(RING_HWS_PGA(ring->mmio_base), @@ -2338,6 +2350,7 @@ int intel_lr_context_deferred_create(struct intel_context *ctx, { const bool is_global_default_ctx = (ctx == ring->default_context); struct drm_device *dev = ring->dev; + struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_object *ctx_obj; uint32_t context_size; struct intel_ringbuffer *ringbuf; @@ -2348,6 +2361,9 @@ int intel_lr_context_deferred_create(struct intel_context *ctx, context_size = round_up(get_lr_context_size(ring), 4096); + /* One extra page as the sharing data between driver and GuC */ + context_size += PAGE_SIZE * LRC_PPHWSP_PN; + ctx_obj = i915_gem_alloc_object(dev, context_size); if (!ctx_obj) { DRM_DEBUG_DRIVER("Alloc LRC backing obj failed.\n"); @@ -2355,13 +2371,18 @@ int intel_lr_context_deferred_create(struct intel_context *ctx, } if (is_global_default_ctx) { - ret = i915_gem_obj_ggtt_pin(ctx_obj, GEN8_LR_CONTEXT_ALIGN, 0); + ret = i915_gem_obj_ggtt_pin(ctx_obj, GEN8_LR_CONTEXT_ALIGN, + PIN_OFFSET_BIAS | GUC_WOPCM_TOP); if (ret) { DRM_DEBUG_DRIVER("Pin LRC backing obj failed: %d\n", ret); drm_gem_object_unreference(&ctx_obj->base); return ret; } + + /* Invalidate GuC TLB. */ + if (i915.enable_guc_submission) + I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE); } ringbuf = kzalloc(sizeof(*ringbuf), GFP_KERNEL); @@ -2374,7 +2395,7 @@ int intel_lr_context_deferred_create(struct intel_context *ctx, ringbuf->ring = ring; - ringbuf->size = 32 * PAGE_SIZE; + ringbuf->size = 4 * PAGE_SIZE; ringbuf->effective_size = ringbuf->size; ringbuf->head = 0; ringbuf->tail = 0; @@ -2474,7 +2495,7 @@ void intel_lr_context_reset(struct drm_device *dev, WARN(1, "Failed get_pages for context obj\n"); continue; } - page = i915_gem_object_get_page(ctx_obj, 1); + page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); reg_state = kmap_atomic(page); reg_state[CTX_RING_HEAD+1] = 0; diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index 5e5788c..4cc54b3 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -68,6 +68,12 @@ static inline void intel_logical_ring_emit(struct intel_ringbuffer *ringbuf, } /* Logical Ring Contexts */ + +/* One extra page is added before LRC for GuC as shared data */ +#define LRC_GUCSHR_PN (0) +#define LRC_PPHWSP_PN (LRC_GUCSHR_PN + 1) +#define LRC_STATE_PN (LRC_PPHWSP_PN + 1) + void intel_lr_context_free(struct intel_context *ctx); int intel_lr_context_deferred_create(struct intel_context *ctx, struct intel_engine_cs *ring); -- cgit v0.10.2 From 8b417c266b715b3797cd3e65342149372b9ac0c8 Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Wed, 12 Aug 2015 15:43:44 +0100 Subject: drm/i915: Debugfs interface for GuC submission statistics This provides a means of reading status and counts relating to GuC actions and submissions. v2: Remove surplus blank line in output [Chris Wilson] v5: Added GuC per-engine submission & seqno statistics v6: Add per-ring statistics to client, refactor client-dumper. Signed-off-by: Dave Gordon Signed-off-by: Alex Dai Reviewed-by: Tom O'Rourke Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index a815fcc..e192f02 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2412,6 +2412,81 @@ static int i915_guc_load_status_info(struct seq_file *m, void *data) return 0; } +static void i915_guc_client_info(struct seq_file *m, + struct drm_i915_private *dev_priv, + struct i915_guc_client *client) +{ + struct intel_engine_cs *ring; + uint64_t tot = 0; + uint32_t i; + + seq_printf(m, "\tPriority %d, GuC ctx index: %u, PD offset 0x%x\n", + client->priority, client->ctx_index, client->proc_desc_offset); + seq_printf(m, "\tDoorbell id %d, offset: 0x%x, cookie 0x%x\n", + client->doorbell_id, client->doorbell_offset, client->cookie); + seq_printf(m, "\tWQ size %d, offset: 0x%x, tail %d\n", + client->wq_size, client->wq_offset, client->wq_tail); + + seq_printf(m, "\tFailed to queue: %u\n", client->q_fail); + seq_printf(m, "\tFailed doorbell: %u\n", client->b_fail); + seq_printf(m, "\tLast submission result: %d\n", client->retcode); + + for_each_ring(ring, dev_priv, i) { + seq_printf(m, "\tSubmissions: %llu %s\n", + client->submissions[i], + ring->name); + tot += client->submissions[i]; + } + seq_printf(m, "\tTotal: %llu\n", tot); +} + +static int i915_guc_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = m->private; + struct drm_device *dev = node->minor->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_guc guc; + struct i915_guc_client client = { .client_obj = 0 }; + struct intel_engine_cs *ring; + enum intel_ring_id i; + u64 total = 0; + + if (!HAS_GUC_SCHED(dev_priv->dev)) + return 0; + + /* Take a local copy of the GuC data, so we can dump it at leisure */ + spin_lock(&dev_priv->guc.host2guc_lock); + guc = dev_priv->guc; + if (guc.execbuf_client) { + spin_lock(&guc.execbuf_client->wq_lock); + client = *guc.execbuf_client; + spin_unlock(&guc.execbuf_client->wq_lock); + } + spin_unlock(&dev_priv->guc.host2guc_lock); + + seq_printf(m, "GuC total action count: %llu\n", guc.action_count); + seq_printf(m, "GuC action failure count: %u\n", guc.action_fail); + seq_printf(m, "GuC last action command: 0x%x\n", guc.action_cmd); + seq_printf(m, "GuC last action status: 0x%x\n", guc.action_status); + seq_printf(m, "GuC last action error code: %d\n", guc.action_err); + + seq_printf(m, "\nGuC submissions:\n"); + for_each_ring(ring, dev_priv, i) { + seq_printf(m, "\t%-24s: %10llu, last seqno 0x%08x %9d\n", + ring->name, guc.submissions[i], + guc.last_seqno[i], guc.last_seqno[i]); + total += guc.submissions[i]; + } + seq_printf(m, "\t%s: %llu\n", "Total", total); + + seq_printf(m, "\nGuC execbuf client @ %p:\n", guc.execbuf_client); + i915_guc_client_info(m, dev_priv, &client); + + /* Add more as required ... */ + + return 0; +} + static int i915_guc_log_dump(struct seq_file *m, void *data) { struct drm_info_node *node = m->private; @@ -5099,6 +5174,7 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_gem_hws_bsd", i915_hws_info, 0, (void *)VCS}, {"i915_gem_hws_vebox", i915_hws_info, 0, (void *)VECS}, {"i915_gem_batch_pool", i915_gem_batch_pool_info, 0}, + {"i915_guc_info", i915_guc_info, 0}, {"i915_guc_load_status", i915_guc_load_status_info, 0}, {"i915_guc_log_dump", i915_guc_log_dump, 0}, {"i915_frequency_info", i915_frequency_info, 0}, -- cgit v0.10.2 From 66e2806656b12bbb98ff36b7beb1538b87cb2f2f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 14 Aug 2015 15:59:53 +0300 Subject: drm/i915: remove excessive scaler debugging messages There's so much scaler debugging messages that it makes other debugging hard. Remove them. Signed-off-by: Jani Nikula Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index e2531cf..9336e80 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -149,9 +149,6 @@ int intel_atomic_setup_scalers(struct drm_device *dev, int i, j; num_scalers_need = hweight32(scaler_state->scaler_users); - DRM_DEBUG_KMS("crtc_state = %p need = %d avail = %d scaler_users = 0x%x\n", - crtc_state, num_scalers_need, intel_crtc->num_scalers, - scaler_state->scaler_users); /* * High level flow: diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 40e70f2..364104d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2933,8 +2933,6 @@ static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id) I915_WRITE(SKL_PS_CTRL(intel_crtc->pipe, id), 0); I915_WRITE(SKL_PS_WIN_POS(intel_crtc->pipe, id), 0); I915_WRITE(SKL_PS_WIN_SZ(intel_crtc->pipe, id), 0); - DRM_DEBUG_KMS("CRTC:%d Disabled scaler id %u.%u\n", - intel_crtc->base.base.id, intel_crtc->pipe, id); } /* -- cgit v0.10.2 From cff4f55bf4fb1e32483885bf0e571847668d9d67 Mon Sep 17 00:00:00 2001 From: Graham Whaley Date: Mon, 24 Aug 2015 14:41:21 +0100 Subject: doc: drm: Fix mis-spelling of i915_guc_submission includes In commit d1675198e: drm/i915: Integrate GuC-based command submission the drm.tmpl include lines reference the intel_guc_submission.c but the patch adds the file i915_guc_submission.c. drm.tmpl fails to build with: docproc: .//drivers/gpu/drm/i915/intel_guc_submission.c: No such file or directory Change the file reference to the actual file. Signed-off-by: Graham Whaley Signed-off-by: Daniel Vetter diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 069958c..1f9dc3e 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -4246,8 +4246,8 @@ int num_ioctls; GuC Client -!Pdrivers/gpu/drm/i915/intel_guc_submission.c GuC-based command submissison -!Idrivers/gpu/drm/i915/intel_guc_submission.c +!Pdrivers/gpu/drm/i915/i915_guc_submission.c GuC-based command submissison +!Idrivers/gpu/drm/i915/i915_guc_submission.c -- cgit v0.10.2 From 74b22c465cd2b6ff4b8cec3997512ec807e6e495 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Wed, 26 Aug 2015 09:42:34 +0930 Subject: params: don't ignore the rest of cmdline if parse_one() fails parse_args() just aborts after it hits an error, so other args at the same initcall level are simply ignored. This can lead to other hard-to-understand problems, for example my testing machine panics during the boot if I pass "locktorture.verbose=true". Change parse_args() to save the err code for return and continue. Signed-off-by: Oleg Nesterov Signed-off-by: Rusty Russell diff --git a/kernel/params.c b/kernel/params.c index b6554aa..ed1e0a1 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -223,7 +223,7 @@ char *parse_args(const char *doing, int (*unknown)(char *param, char *val, const char *doing, void *arg)) { - char *param, *val; + char *param, *val, *err = NULL; /* Chew leading spaces */ args = skip_spaces(args); @@ -238,7 +238,7 @@ char *parse_args(const char *doing, args = next_arg(args, ¶m, &val); /* Stop at -- */ if (!val && strcmp(param, "--") == 0) - return args; + return err ?: args; irq_was_disabled = irqs_disabled(); ret = parse_one(param, val, doing, params, num, min_level, max_level, arg, unknown); @@ -247,24 +247,25 @@ char *parse_args(const char *doing, doing, param); switch (ret) { + case 0: + continue; case -ENOENT: pr_err("%s: Unknown parameter `%s'\n", doing, param); - return ERR_PTR(ret); + break; case -ENOSPC: pr_err("%s: `%s' too large for parameter `%s'\n", doing, val ?: "", param); - return ERR_PTR(ret); - case 0: break; default: pr_err("%s: `%s' invalid for parameter `%s'\n", doing, val ?: "", param); - return ERR_PTR(ret); + break; } + + err = ERR_PTR(ret); } - /* All parsed OK. */ - return NULL; + return err; } /* Lazy bastard, eh? */ -- cgit v0.10.2 From f1afe24f0e736b9d7f2275e2b1504af3fe612f2a Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Tue, 4 Aug 2015 16:22:20 +0100 Subject: drm/i915: Change SRM, LRM instructions to use correct length MI_STORE_REGISTER_MEM, MI_LOAD_REGISTER_MEM instructions are not really variable length instructions unlike MI_LOAD_REGISTER_IMM where it expects (reg, addr) pairs so use fixed length for these instructions. v2: rebase Cc: Dave Gordon Signed-off-by: Arun Siluvery Reviewed-by: Mika Kuoppala [danvet: Appease checkpatch as Mika spotted in i915_reg.h - it seems terminally unhappy about i915_cmd_parser.c so that would be a separate patch.] Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 237ff68..3977bf3 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -94,7 +94,7 @@ #define CMD(op, opm, f, lm, fl, ...) \ { \ .flags = (fl) | ((f) ? CMD_DESC_FIXED : 0), \ - .cmd = { (op), (opm) }, \ + .cmd = { (op), (opm) }, \ .length = { (lm) }, \ __VA_ARGS__ \ } @@ -124,14 +124,14 @@ static const struct drm_i915_cmd_descriptor common_cmds[] = { CMD( MI_STORE_DWORD_INDEX, SMI, !F, 0xFF, R ), CMD( MI_LOAD_REGISTER_IMM(1), SMI, !F, 0xFF, W, .reg = { .offset = 1, .mask = 0x007FFFFC, .step = 2 } ), - CMD( MI_STORE_REGISTER_MEM(1), SMI, !F, 0xFF, W | B, + CMD( MI_STORE_REGISTER_MEM, SMI, F, 1, W | B, .reg = { .offset = 1, .mask = 0x007FFFFC }, .bits = {{ .offset = 0, .mask = MI_GLOBAL_GTT, .expected = 0, }}, ), - CMD( MI_LOAD_REGISTER_MEM(1), SMI, !F, 0xFF, W | B, + CMD( MI_LOAD_REGISTER_MEM, SMI, F, 1, W | B, .reg = { .offset = 1, .mask = 0x007FFFFC }, .bits = {{ .offset = 0, @@ -1021,7 +1021,7 @@ static bool check_cmd(const struct intel_engine_cs *ring, * only MI_LOAD_REGISTER_IMM commands. */ if (reg_addr == OACONTROL) { - if (desc->cmd.value == MI_LOAD_REGISTER_MEM(1)) { + if (desc->cmd.value == MI_LOAD_REGISTER_MEM) { DRM_DEBUG_DRIVER("CMD: Rejected LRM to OACONTROL\n"); return false; } @@ -1035,7 +1035,7 @@ static bool check_cmd(const struct intel_engine_cs *ring, * allowed mask/value pair given in the whitelist entry. */ if (reg->mask) { - if (desc->cmd.value == MI_LOAD_REGISTER_MEM(1)) { + if (desc->cmd.value == MI_LOAD_REGISTER_MEM) { DRM_DEBUG_DRIVER("CMD: Rejected LRM to masked register 0x%08X\n", reg_addr); return false; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5cdb328..211b73a 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -352,8 +352,8 @@ */ #define MI_LOAD_REGISTER_IMM(x) MI_INSTR(0x22, 2*(x)-1) #define MI_LRI_FORCE_POSTED (1<<12) -#define MI_STORE_REGISTER_MEM(x) MI_INSTR(0x24, 2*(x)-1) -#define MI_STORE_REGISTER_MEM_GEN8(x) MI_INSTR(0x24, 3*(x)-1) +#define MI_STORE_REGISTER_MEM MI_INSTR(0x24, 1) +#define MI_STORE_REGISTER_MEM_GEN8 MI_INSTR(0x24, 2) #define MI_SRM_LRM_GLOBAL_GTT (1<<22) #define MI_FLUSH_DW MI_INSTR(0x26, 1) /* for GEN6 */ #define MI_FLUSH_DW_STORE_INDEX (1<<21) @@ -364,8 +364,8 @@ #define MI_INVALIDATE_BSD (1<<7) #define MI_FLUSH_DW_USE_GTT (1<<2) #define MI_FLUSH_DW_USE_PPGTT (0<<2) -#define MI_LOAD_REGISTER_MEM(x) MI_INSTR(0x29, 2*(x)-1) -#define MI_LOAD_REGISTER_MEM_GEN8(x) MI_INSTR(0x29, 3*(x)-1) +#define MI_LOAD_REGISTER_MEM MI_INSTR(0x29, 1) +#define MI_LOAD_REGISTER_MEM_GEN8 MI_INSTR(0x29, 2) #define MI_BATCH_BUFFER MI_INSTR(0x30, 1) #define MI_BATCH_NON_SECURE (1) /* for snb/ivb/vlv this also means "batch in ppgtt" when ppgtt is enabled. */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 364104d..542fb8c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11031,10 +11031,10 @@ static int intel_gen7_queue_flip(struct drm_device *dev, DERRMR_PIPEB_PRI_FLIP_DONE | DERRMR_PIPEC_PRI_FLIP_DONE)); if (IS_GEN8(dev)) - intel_ring_emit(ring, MI_STORE_REGISTER_MEM_GEN8(1) | + intel_ring_emit(ring, MI_STORE_REGISTER_MEM_GEN8 | MI_SRM_LRM_GLOBAL_GTT); else - intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1) | + intel_ring_emit(ring, MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT); intel_ring_emit(ring, DERRMR); intel_ring_emit(ring, ring->scratch.gtt_offset + 256); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index e77b6b0..8e9a85b 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1130,7 +1130,7 @@ static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *ring, if (IS_SKYLAKE(ring->dev) && INTEL_REVID(ring->dev) <= SKL_REVID_E0) l3sqc4_flush |= GEN8_LQSC_RO_PERF_DIS; - wa_ctx_emit(batch, index, (MI_STORE_REGISTER_MEM_GEN8(1) | + wa_ctx_emit(batch, index, (MI_STORE_REGISTER_MEM_GEN8 | MI_SRM_LRM_GLOBAL_GTT)); wa_ctx_emit(batch, index, GEN8_L3SQCREG4); wa_ctx_emit(batch, index, ring->scratch.gtt_offset + 256); @@ -1148,7 +1148,7 @@ static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *ring, wa_ctx_emit(batch, index, 0); wa_ctx_emit(batch, index, 0); - wa_ctx_emit(batch, index, (MI_LOAD_REGISTER_MEM_GEN8(1) | + wa_ctx_emit(batch, index, (MI_LOAD_REGISTER_MEM_GEN8 | MI_SRM_LRM_GLOBAL_GTT)); wa_ctx_emit(batch, index, GEN8_L3SQCREG4); wa_ctx_emit(batch, index, ring->scratch.gtt_offset + 256); -- cgit v0.10.2 From 8be6ca8537e1230da8e92c753df4125151a3f6b1 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Mon, 24 Aug 2015 16:38:23 -0700 Subject: drm/i915: Also call frontbuffer flip when disabling planes. We also need to call the frontbuffer flip to trigger proper invalidations when disabling planes. Otherwise we will miss screen updates when disabling sprites or cursor. On core platforms where HW tracking also works, this issue is totally masked because HW tracking triggers PSR exit however on VLV/CHV that has only SW tracking we miss screen updates when disabling planes. It was caught with kms_psr_sink_crc sprite_plane_onoff and cursor_plane_onoff subtests running on VLV/CHV. This is probably a regression since I can also get this with the manual test case, but with so many changes on atomic modeset I couldn't track exactly when this was introduced. Reviewed-by: Paulo Zanoni Signed-off-by: Rodrigo Vivi Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 542fb8c..cf8dfa5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11627,7 +11627,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, intel_crtc->atomic.update_wm_pre = true; } - if (visible) + if (visible || was_visible) intel_crtc->atomic.fb_bits |= to_intel_plane(plane)->frontbuffer_bit; -- cgit v0.10.2 From 319404df2f682ddabf98cbf6421bb43b951ca978 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 14 Aug 2015 18:35:27 +0300 Subject: drm/i915/bxt: work around HW coherency issue when accessing GPU seqno By running igt/store_dword_loop_render on BXT we can hit a coherency problem where the seqno written at GPU command completion time is not seen by the CPU. This results in __i915_wait_request seeing the stale seqno and not completing the request (not considering the lost interrupt/GPU reset mechanism). I also verified that this isn't a case of a lost interrupt, or that the command didn't complete somehow: when the coherency issue occured I read the seqno via an uncached GTT mapping too. While the cached version of the seqno still showed the stale value the one read via the uncached mapping was the correct one. Work around this issue by clflushing the corresponding CPU cacheline following any store of the seqno and preceding any reading of it. When reading it do this only when the caller expects a coherent view. v2: - fix using the proper logical && instead of a bitwise & (Jani, Mika) - limit the workaround to A stepping, on later steppings this HW issue is fixed v3: - use a separate get_seqno/set_seqno vfunc (Chris) Testcase: igt/store_dword_loop_render Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 8e9a85b..1af84c5 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1710,6 +1710,34 @@ static void gen8_set_seqno(struct intel_engine_cs *ring, u32 seqno) intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno); } +static u32 bxt_a_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) +{ + + /* + * On BXT A steppings there is a HW coherency issue whereby the + * MI_STORE_DATA_IMM storing the completed request's seqno + * occasionally doesn't invalidate the CPU cache. Work around this by + * clflushing the corresponding cacheline whenever the caller wants + * the coherency to be guaranteed. Note that this cacheline is known + * to be clean at this point, since we only write it in + * bxt_a_set_seqno(), where we also do a clflush after the write. So + * this clflush in practice becomes an invalidate operation. + */ + + if (!lazy_coherency) + intel_flush_status_page(ring, I915_GEM_HWS_INDEX); + + return intel_read_status_page(ring, I915_GEM_HWS_INDEX); +} + +static void bxt_a_set_seqno(struct intel_engine_cs *ring, u32 seqno) +{ + intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno); + + /* See bxt_a_get_seqno() explaining the reason for the clflush. */ + intel_flush_status_page(ring, I915_GEM_HWS_INDEX); +} + static int gen8_emit_request(struct drm_i915_gem_request *request) { struct intel_ringbuffer *ringbuf = request->ringbuf; @@ -1879,8 +1907,13 @@ static int logical_render_ring_init(struct drm_device *dev) ring->init_hw = gen8_init_render_ring; ring->init_context = gen8_init_rcs_context; ring->cleanup = intel_fini_pipe_control; - ring->get_seqno = gen8_get_seqno; - ring->set_seqno = gen8_set_seqno; + if (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0) { + ring->get_seqno = bxt_a_get_seqno; + ring->set_seqno = bxt_a_set_seqno; + } else { + ring->get_seqno = gen8_get_seqno; + ring->set_seqno = gen8_set_seqno; + } ring->emit_request = gen8_emit_request; ring->emit_flush = gen8_emit_flush_render; ring->irq_get = gen8_logical_ring_get_irq; @@ -1926,8 +1959,13 @@ static int logical_bsd_ring_init(struct drm_device *dev) GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; ring->init_hw = gen8_init_common_ring; - ring->get_seqno = gen8_get_seqno; - ring->set_seqno = gen8_set_seqno; + if (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0) { + ring->get_seqno = bxt_a_get_seqno; + ring->set_seqno = bxt_a_set_seqno; + } else { + ring->get_seqno = gen8_get_seqno; + ring->set_seqno = gen8_set_seqno; + } ring->emit_request = gen8_emit_request; ring->emit_flush = gen8_emit_flush; ring->irq_get = gen8_logical_ring_get_irq; @@ -1976,8 +2014,13 @@ static int logical_blt_ring_init(struct drm_device *dev) GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT; ring->init_hw = gen8_init_common_ring; - ring->get_seqno = gen8_get_seqno; - ring->set_seqno = gen8_set_seqno; + if (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0) { + ring->get_seqno = bxt_a_get_seqno; + ring->set_seqno = bxt_a_set_seqno; + } else { + ring->get_seqno = gen8_get_seqno; + ring->set_seqno = gen8_set_seqno; + } ring->emit_request = gen8_emit_request; ring->emit_flush = gen8_emit_flush; ring->irq_get = gen8_logical_ring_get_irq; @@ -2001,8 +2044,13 @@ static int logical_vebox_ring_init(struct drm_device *dev) GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT; ring->init_hw = gen8_init_common_ring; - ring->get_seqno = gen8_get_seqno; - ring->set_seqno = gen8_set_seqno; + if (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0) { + ring->get_seqno = bxt_a_get_seqno; + ring->set_seqno = bxt_a_set_seqno; + } else { + ring->get_seqno = gen8_get_seqno; + ring->set_seqno = gen8_set_seqno; + } ring->emit_request = gen8_emit_request; ring->emit_flush = gen8_emit_flush; ring->irq_get = gen8_logical_ring_get_irq; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 2e85fda..95b0b4b 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -377,6 +377,13 @@ intel_ring_sync_index(struct intel_engine_cs *ring, return idx; } +static inline void +intel_flush_status_page(struct intel_engine_cs *ring, int reg) +{ + drm_clflush_virt_range(&ring->status_page.page_addr[reg], + sizeof(uint32_t)); +} + static inline u32 intel_read_status_page(struct intel_engine_cs *ring, int reg) -- cgit v0.10.2 From e5756c10d841ddb448293c849392f3d6b809561f Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 14 Aug 2015 18:43:30 +0300 Subject: drm/i915/bxt: don't allow cached GEM mappings on A stepping Due to a coherency issue on BXT A steppings we can't guarantee a coherent view of cached (CPU snooped) GPU mappings, so fail such requests. User space is supposed to fall back to uncached mappings in this case. v2: - limit the WA to A steppings, on later stepping this HW issue is fixed v3: - return error instead of trying to work around the issue in kernel, since that could confuse user space (Chris) Testcast: igt/gem_store_dword_batches_loop/cached-mapping Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 1ac57ec..41263cd 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3742,6 +3742,15 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data, level = I915_CACHE_NONE; break; case I915_CACHING_CACHED: + /* + * Due to a HW issue on BXT A stepping, GPU stores via a + * snooped mapping may leave stale data in a corresponding CPU + * cacheline, whereas normally such cachelines would get + * invalidated. + */ + if (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0) + return -ENODEV; + level = I915_CACHE_LLC; break; case I915_CACHING_DISPLAY: -- cgit v0.10.2 From 901c2daf05c8ae6c3f85370fc96b9b6892f5da2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 17 Aug 2015 18:05:12 +0300 Subject: drm/i915: Put back lane_count into intel_dp and add link_rate too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With MST there won't be a crtc assigned to the main link encoder, so trying to dig up the pipe_config from there is a recipe for an oops. Instead store the parameters (lane_count and link_rate) in the encoder, and use those values during link training etc. Since those parameters are now assigned only when the link is actually enabled, .compute_config() won't clobber them as it did before. Hardware state readout is still bonkers though as we don't transfer the link parameters from pipe_config intel_dp. We should do that during encoder sanitation. But since we don't even do a proper job of reading out the main link encoder state for MST there's littel point in worrying about this now. Fixes a regression with MST caused by: commit 90a6b7b052b1aa17fbb98b049e9c8b7f729c35a7 Author: Ville Syrjälä Date: Mon Jul 6 16:39:15 2015 +0300 drm/i915: Move intel_dp->lane_count into pipe_config v2: Different apporoach that should keep intel_dp_check_mst_status() somewhat less oopsy Cc: Maarten Lankhorst Reported-by: Maarten Lankhorst Signed-off-by: Ville Syrjälä Tested-by: Maarten Lankhorst Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 56d778f..5dff8b7 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -728,11 +728,10 @@ void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder) struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); struct intel_digital_port *intel_dig_port = enc_to_dig_port(&encoder->base); - struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); intel_dp->DP = intel_dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE | DDI_BUF_TRANS_SELECT(0); - intel_dp->DP |= DDI_PORT_WIDTH(crtc->config->lane_count); + intel_dp->DP |= DDI_PORT_WIDTH(intel_dp->lane_count); } static struct intel_encoder * @@ -2314,6 +2313,8 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + intel_dp_set_link_params(intel_dp, crtc->config); + intel_ddi_init_dp_buf_reg(intel_encoder); intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index b905c19..dcda86a 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1584,6 +1584,13 @@ static void ironlake_set_pll_cpu_edp(struct intel_dp *intel_dp) udelay(500); } +void intel_dp_set_link_params(struct intel_dp *intel_dp, + const struct intel_crtc_state *pipe_config) +{ + intel_dp->link_rate = pipe_config->port_clock; + intel_dp->lane_count = pipe_config->lane_count; +} + static void intel_dp_prepare(struct intel_encoder *encoder) { struct drm_device *dev = encoder->base.dev; @@ -1593,6 +1600,8 @@ static void intel_dp_prepare(struct intel_encoder *encoder) struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; + intel_dp_set_link_params(intel_dp, crtc->config); + /* * There are four kinds of DP registers: * @@ -3348,15 +3357,13 @@ static void intel_get_adjust_train(struct intel_dp *intel_dp, const uint8_t link_status[DP_LINK_STATUS_SIZE]) { - struct intel_crtc *crtc = - to_intel_crtc(dp_to_dig_port(intel_dp)->base.base.crtc); uint8_t v = 0; uint8_t p = 0; int lane; uint8_t voltage_max; uint8_t preemph_max; - for (lane = 0; lane < crtc->config->lane_count; lane++) { + for (lane = 0; lane < intel_dp->lane_count; lane++) { uint8_t this_v = drm_dp_get_adjust_request_voltage(link_status, lane); uint8_t this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, lane); @@ -3527,8 +3534,6 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); - struct intel_crtc *crtc = - to_intel_crtc(intel_dig_port->base.base.crtc); uint8_t buf[sizeof(intel_dp->train_set) + 1]; int ret, len; @@ -3544,8 +3549,8 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, len = 1; } else { /* DP_TRAINING_LANEx_SET follow DP_TRAINING_PATTERN_SET */ - memcpy(buf + 1, intel_dp->train_set, crtc->config->lane_count); - len = crtc->config->lane_count + 1; + memcpy(buf + 1, intel_dp->train_set, intel_dp->lane_count); + len = intel_dp->lane_count + 1; } ret = drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_PATTERN_SET, @@ -3571,8 +3576,6 @@ intel_dp_update_link_train(struct intel_dp *intel_dp, uint32_t *DP, struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); - struct intel_crtc *crtc = - to_intel_crtc(intel_dig_port->base.base.crtc); int ret; intel_get_adjust_train(intel_dp, link_status); @@ -3582,9 +3585,9 @@ intel_dp_update_link_train(struct intel_dp *intel_dp, uint32_t *DP, POSTING_READ(intel_dp->output_reg); ret = drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_LANE0_SET, - intel_dp->train_set, crtc->config->lane_count); + intel_dp->train_set, intel_dp->lane_count); - return ret == crtc->config->lane_count; + return ret == intel_dp->lane_count; } static void intel_dp_set_idle_link_train(struct intel_dp *intel_dp) @@ -3623,8 +3626,6 @@ void intel_dp_start_link_train(struct intel_dp *intel_dp) { struct drm_encoder *encoder = &dp_to_dig_port(intel_dp)->base.base; - struct intel_crtc *crtc = - to_intel_crtc(dp_to_dig_port(intel_dp)->base.base.crtc); struct drm_device *dev = encoder->dev; int i; uint8_t voltage; @@ -3636,12 +3637,12 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) if (HAS_DDI(dev)) intel_ddi_prepare_link_retrain(encoder); - intel_dp_compute_rate(intel_dp, crtc->config->port_clock, + intel_dp_compute_rate(intel_dp, intel_dp->link_rate, &link_bw, &rate_select); /* Write the link configuration data */ link_config[0] = link_bw; - link_config[1] = crtc->config->lane_count; + link_config[1] = intel_dp->lane_count; if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, 2); @@ -3675,7 +3676,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) break; } - if (drm_dp_clock_recovery_ok(link_status, crtc->config->lane_count)) { + if (drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) { DRM_DEBUG_KMS("clock recovery OK\n"); break; } @@ -3698,10 +3699,10 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) } /* Check to see if we've tried the max voltage */ - for (i = 0; i < crtc->config->lane_count; i++) + for (i = 0; i < intel_dp->lane_count; i++) if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) break; - if (i == crtc->config->lane_count) { + if (i == intel_dp->lane_count) { ++loop_tries; if (loop_tries == 5) { DRM_ERROR("too many full retries, give up\n"); @@ -3738,15 +3739,13 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) void intel_dp_complete_link_train(struct intel_dp *intel_dp) { - struct intel_crtc *crtc = - to_intel_crtc(dp_to_dig_port(intel_dp)->base.base.crtc); bool channel_eq = false; int tries, cr_tries; uint32_t DP = intel_dp->DP; uint32_t training_pattern = DP_TRAINING_PATTERN_2; /* Training Pattern 3 for HBR2 or 1.2 devices that support it*/ - if (crtc->config->port_clock == 540000 || intel_dp->use_tps3) + if (intel_dp->link_rate == 540000 || intel_dp->use_tps3) training_pattern = DP_TRAINING_PATTERN_3; /* channel equalization */ @@ -3776,7 +3775,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) /* Make sure clock is still ok */ if (!drm_dp_clock_recovery_ok(link_status, - crtc->config->lane_count)) { + intel_dp->lane_count)) { intel_dp->train_set_valid = false; intel_dp_start_link_train(intel_dp); intel_dp_set_link_train(intel_dp, &DP, @@ -3787,7 +3786,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) } if (drm_dp_channel_eq_ok(link_status, - crtc->config->lane_count)) { + intel_dp->lane_count)) { channel_eq = true; break; } @@ -4285,8 +4284,6 @@ update_status: static int intel_dp_check_mst_status(struct intel_dp *intel_dp) { - struct intel_crtc *crtc = - to_intel_crtc(dp_to_dig_port(intel_dp)->base.base.crtc); bool bret; if (intel_dp->is_mst) { @@ -4300,7 +4297,7 @@ go_again: /* check link status - esi[10] = 0x200c */ if (intel_dp->active_mst_links && - !drm_dp_channel_eq_ok(&esi[10], crtc->config->lane_count)) { + !drm_dp_channel_eq_ok(&esi[10], intel_dp->lane_count)) { DRM_DEBUG_KMS("channel EQ not ok, retraining\n"); intel_dp_start_link_train(intel_dp); intel_dp_complete_link_train(intel_dp); @@ -4355,8 +4352,6 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base; - struct intel_crtc *crtc = - to_intel_crtc(dp_to_dig_port(intel_dp)->base.base.crtc); u8 sink_irq_vector; u8 link_status[DP_LINK_STATUS_SIZE]; @@ -4392,7 +4387,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n"); } - if (!drm_dp_channel_eq_ok(link_status, crtc->config->lane_count)) { + if (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count)) { DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n", intel_encoder->base.name); intel_dp_start_link_train(intel_dp); diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 1dd2b37..dd291d1 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -165,6 +165,8 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder) if (intel_dp->active_mst_links == 0) { enum port port = intel_ddi_get_encoder_port(encoder); + intel_dp_set_link_params(intel_dp, intel_crtc->config); + /* FIXME: add support for SKL */ if (INTEL_INFO(dev)->gen < 9) I915_WRITE(PORT_CLK_SEL(port), diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 22dc8b6..8383442 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -708,6 +708,8 @@ struct intel_dp { uint32_t output_reg; uint32_t aux_ch_ctl_reg; uint32_t DP; + int link_rate; + uint8_t lane_count; bool has_audio; enum hdmi_force_audio force_audio; bool limited_color_range; @@ -1161,6 +1163,8 @@ void assert_csr_loaded(struct drm_i915_private *dev_priv); void intel_dp_init(struct drm_device *dev, int output_reg, enum port port); bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port, struct intel_connector *intel_connector); +void intel_dp_set_link_params(struct intel_dp *intel_dp, + const struct intel_crtc_state *pipe_config); void intel_dp_start_link_train(struct intel_dp *intel_dp); void intel_dp_complete_link_train(struct intel_dp *intel_dp); void intel_dp_stop_link_train(struct intel_dp *intel_dp); -- cgit v0.10.2 From 4eee4920f05e39e22571deb57f1c314ce7a46e7f Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Mon, 17 Aug 2015 17:30:52 +0100 Subject: drm/i915: fix driver's versions of WARN_ON & WARN_ON_ONCE The current versions of these two macros don't work correctly if the argument expression happens to contain a modulo operator (%) -- when stringified, it gets interpreted as a printf formatting character! With a specifically crafted parameter, this could probably cause a kernel OOPS; consider WARN_ON(p%s) or WARN_ON(f %*pEp). Instead, we should use an explicit "%s" format, with the stringified expression as the coresponding literal-string argument. Signed-off-by: Dave Gordon Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6124445..ce41d24 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -68,11 +68,11 @@ BUILD_BUG_ON(__i915_warn_cond); \ WARN(__i915_warn_cond, "WARN_ON(" #x ")"); }) #else -#define WARN_ON(x) WARN((x), "WARN_ON(" #x ")") +#define WARN_ON(x) WARN((x), "WARN_ON(%s)", #x ) #endif #undef WARN_ON_ONCE -#define WARN_ON_ONCE(x) WARN_ONCE((x), "WARN_ON_ONCE(" #x ")") +#define WARN_ON_ONCE(x) WARN_ONCE((x), "WARN_ON_ONCE(%s)", #x ) #define MISSING_CASE(x) WARN(1, "Missing switch case (%lu) in %s\n", \ (long) (x), __func__); -- cgit v0.10.2 From 25a25dfce4e678bb18c4d63937d240839ecd19cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 8 Jul 2015 23:45:47 +0300 Subject: drm/i915: Always program m2 fractional value on CHV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When fractional m2 divider isn't used on CHV the fractional part is ignore by the hardware. Despite that, program the fractional value (0 in this case) to the hardware register just to keep things a bit more consistent. Might at least make register dumps a bit less confusing when there isn't some stale fractional part hanging around. Signed-off-by: Ville Syrjälä Reviewed-by: Deepak S Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index cf8dfa5..a64da67 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7374,8 +7374,7 @@ static void chv_prepare_pll(struct intel_crtc *crtc, 1 << DPIO_CHV_N_DIV_SHIFT); /* M2 fraction division */ - if (bestm2_frac) - vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW2(port), bestm2_frac); + vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW2(port), bestm2_frac); /* M2 fraction division enable */ dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW3(port)); -- cgit v0.10.2 From 67fa24b4041436f1a21f7640d1d7ab56d023d7e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 8 Jul 2015 23:45:48 +0300 Subject: drm/i915: Always program unique transition scale for CHV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The docs give you the impression that the unique transition scale value shouldn't matter when unique transition scale is enabled. But as Imre found on BXT (and I verfied also on BSW) the value does matter. So from now on just program the same value 0x9a always. Cc: Imre Deak Signed-off-by: Ville Syrjälä Reviewed-by: Deepak S Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index dcda86a..da7d1ae 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3179,6 +3179,12 @@ static uint32_t vlv_signal_levels(struct intel_dp *intel_dp) return 0; } +static bool chv_need_uniq_trans_scale(uint8_t train_set) +{ + return (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) == DP_TRAIN_PRE_EMPH_LEVEL_0 && + (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) == DP_TRAIN_VOLTAGE_SWING_LEVEL_3; +} + static uint32_t chv_signal_levels(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); @@ -3297,41 +3303,34 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp) /* Program swing margin */ for (i = 0; i < 4; i++) { val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i)); + val &= ~DPIO_SWING_MARGIN000_MASK; val |= margin_reg_value << DPIO_SWING_MARGIN000_SHIFT; + + /* + * Supposedly this value shouldn't matter when unique transition + * scale is disabled, but in fact it does matter. Let's just + * always program the same value and hope it's OK. + */ + val &= ~(0xff << DPIO_UNIQ_TRANS_SCALE_SHIFT); + val |= 0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT; + vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val); } - /* Disable unique transition scale */ + /* + * The document said it needs to set bit 27 for ch0 and bit 26 + * for ch1. Might be a typo in the doc. + * For now, for this unique transition scale selection, set bit + * 27 for ch0 and ch1. + */ for (i = 0; i < 4; i++) { val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW3(ch, i)); - val &= ~DPIO_TX_UNIQ_TRANS_SCALE_EN; - vlv_dpio_write(dev_priv, pipe, CHV_TX_DW3(ch, i), val); - } - - if (((train_set & DP_TRAIN_PRE_EMPHASIS_MASK) - == DP_TRAIN_PRE_EMPH_LEVEL_0) && - ((train_set & DP_TRAIN_VOLTAGE_SWING_MASK) - == DP_TRAIN_VOLTAGE_SWING_LEVEL_3)) { - - /* - * The document said it needs to set bit 27 for ch0 and bit 26 - * for ch1. Might be a typo in the doc. - * For now, for this unique transition scale selection, set bit - * 27 for ch0 and ch1. - */ - for (i = 0; i < 4; i++) { - val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW3(ch, i)); + if (chv_need_uniq_trans_scale(train_set)) val |= DPIO_TX_UNIQ_TRANS_SCALE_EN; - vlv_dpio_write(dev_priv, pipe, CHV_TX_DW3(ch, i), val); - } - - for (i = 0; i < 4; i++) { - val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i)); - val &= ~(0xff << DPIO_UNIQ_TRANS_SCALE_SHIFT); - val |= (0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT); - vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val); - } + else + val &= ~DPIO_TX_UNIQ_TRANS_SCALE_EN; + vlv_dpio_write(dev_priv, pipe, CHV_TX_DW3(ch, i), val); } /* Start swing calculation */ diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 7185062..c25835f 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1849,31 +1849,33 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder) for (i = 0; i < 4; i++) { val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i)); + val &= ~DPIO_SWING_MARGIN000_MASK; val |= 102 << DPIO_SWING_MARGIN000_SHIFT; + + /* + * Supposedly this value shouldn't matter when unique transition + * scale is disabled, but in fact it does matter. Let's just + * always program the same value and hope it's OK. + */ + val &= ~(0xff << DPIO_UNIQ_TRANS_SCALE_SHIFT); + val |= 0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT; + vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val); } - /* Disable unique transition scale */ + /* + * The document said it needs to set bit 27 for ch0 and bit 26 + * for ch1. Might be a typo in the doc. + * For now, for this unique transition scale selection, set bit + * 27 for ch0 and ch1. + */ for (i = 0; i < 4; i++) { val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW3(ch, i)); val &= ~DPIO_TX_UNIQ_TRANS_SCALE_EN; vlv_dpio_write(dev_priv, pipe, CHV_TX_DW3(ch, i), val); } - /* Additional steps for 1200mV-0dB */ -#if 0 - val = vlv_dpio_read(dev_priv, pipe, VLV_TX_DW3(ch)); - if (ch) - val |= DPIO_TX_UNIQ_TRANS_SCALE_CH1; - else - val |= DPIO_TX_UNIQ_TRANS_SCALE_CH0; - vlv_dpio_write(dev_priv, pipe, VLV_TX_DW3(ch), val); - - vlv_dpio_write(dev_priv, pipe, VLV_TX_DW2(ch), - vlv_dpio_read(dev_priv, pipe, VLV_TX_DW2(ch)) | - (0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT)); -#endif /* Start swing calculation */ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch)); val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3; -- cgit v0.10.2 From d6db995fe36c7460a30c8c6250bb47937d38c482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 8 Jul 2015 23:45:49 +0300 Subject: drm/i915: Add encoder->post_pll_disable() hooks and move CHV clock buffer disables there MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the CHV clock buffer disable from chv_disable_pll() to the new encoder .post_pll_disable() hook. This is more symmetric since the clock buffer enable happens from the .pre_pll_enable() hook. We'll have more use for the new hook soon. Signed-off-by: Ville Syrjälä Reviewed-by: Deepak S Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a64da67..328d1ee 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1828,17 +1828,6 @@ static void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) val &= ~DPIO_DCLKP_EN; vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), val); - /* disable left/right clock distribution */ - if (pipe != PIPE_B) { - val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0); - val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK); - vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val); - } else { - val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1); - val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK); - vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val); - } - mutex_unlock(&dev_priv->sb_lock); } @@ -6193,6 +6182,10 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) i9xx_disable_pll(intel_crtc); } + for_each_encoder_on_crtc(dev, crtc, encoder) + if (encoder->post_pll_disable) + encoder->post_pll_disable(encoder); + if (!IS_GEN2(dev)) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index da7d1ae..4e5bd87 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2943,6 +2943,28 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder) mutex_unlock(&dev_priv->sb_lock); } +static void chv_dp_post_pll_disable(struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum pipe pipe = to_intel_crtc(encoder->base.crtc)->pipe; + u32 val; + + mutex_lock(&dev_priv->sb_lock); + + /* disable left/right clock distribution */ + if (pipe != PIPE_B) { + val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0); + val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK); + vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val); + } else { + val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1); + val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK); + vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val); + } + + mutex_unlock(&dev_priv->sb_lock); +} + /* * Native read with retry for link status and receiver capability reads for * cases where the sink may still be asleep. @@ -6000,6 +6022,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) intel_encoder->pre_enable = chv_pre_enable_dp; intel_encoder->enable = vlv_enable_dp; intel_encoder->post_disable = chv_post_disable_dp; + intel_encoder->post_pll_disable = chv_dp_post_pll_disable; } else if (IS_VALLEYVIEW(dev)) { intel_encoder->pre_pll_enable = vlv_dp_pre_pll_enable; intel_encoder->pre_enable = vlv_pre_enable_dp; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8383442..525e457 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -142,6 +142,7 @@ struct intel_encoder { void (*mode_set)(struct intel_encoder *intel_encoder); void (*disable)(struct intel_encoder *); void (*post_disable)(struct intel_encoder *); + void (*post_pll_disable)(struct intel_encoder *); /* Read out the current hw state of this connector, returning true if * the encoder is active. If the encoder is enabled it also set the pipe * it is connected to in the pipe parameter. */ diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index c25835f..269937a 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1681,6 +1681,28 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder) mutex_unlock(&dev_priv->sb_lock); } +static void chv_hdmi_post_pll_disable(struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum pipe pipe = to_intel_crtc(encoder->base.crtc)->pipe; + u32 val; + + mutex_lock(&dev_priv->sb_lock); + + /* disable left/right clock distribution */ + if (pipe != PIPE_B) { + val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0); + val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK); + vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val); + } else { + val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1); + val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK); + vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val); + } + + mutex_unlock(&dev_priv->sb_lock); +} + static void vlv_hdmi_post_disable(struct intel_encoder *encoder) { struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); @@ -2083,6 +2105,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) intel_encoder->pre_enable = chv_hdmi_pre_enable; intel_encoder->enable = vlv_enable_hdmi; intel_encoder->post_disable = chv_hdmi_post_disable; + intel_encoder->post_pll_disable = chv_hdmi_post_pll_disable; } else if (IS_VALLEYVIEW(dev)) { intel_encoder->pre_pll_enable = vlv_hdmi_pre_pll_enable; intel_encoder->pre_enable = vlv_hdmi_pre_enable; -- cgit v0.10.2 From e27f299ec3ddd03373bb07db23dd19747eecef72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 8 Jul 2015 23:45:50 +0300 Subject: drm/i915: Move DPIO port init earlier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To implement DPIO lane power gating on CHV we're going to need to access DPIO registers from the cmn power well enable hook. That gets called rather early, so we need to move the DPIO port IOSF sideband port assignment earlier as well. Signed-off-by: Ville Syrjälä Reviewed-by: Deepak S Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 2193cc2..097d4ba 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -799,6 +799,24 @@ static void intel_device_info_runtime_init(struct drm_device *dev) info->has_eu_pg ? "y" : "n"); } +static void intel_init_dpio(struct drm_i915_private *dev_priv) +{ + if (!IS_VALLEYVIEW(dev_priv)) + return; + + /* + * IOSF_PORT_DPIO is used for VLV x2 PHY (DP/HDMI B and C), + * CHV x1 PHY (DP/HDMI D) + * IOSF_PORT_DPIO_2 is used for CHV x2 PHY (DP/HDMI B and C) + */ + if (IS_CHERRYVIEW(dev_priv)) { + DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO_2; + DPIO_PHY_IOSF_PORT(DPIO_PHY1) = IOSF_PORT_DPIO; + } else { + DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO; + } +} + /** * i915_driver_load - setup chip and create an initial config * @dev: DRM device @@ -999,6 +1017,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) intel_device_info_runtime_init(dev); + intel_init_dpio(dev_priv); + if (INTEL_INFO(dev)->num_pipes) { ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes); if (ret) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 328d1ee..3c2c76b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1582,26 +1582,6 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMID); } -static void intel_init_dpio(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - if (!IS_VALLEYVIEW(dev)) - return; - - /* - * IOSF_PORT_DPIO is used for VLV x2 PHY (DP/HDMI B and C), - * CHV x1 PHY (DP/HDMI D) - * IOSF_PORT_DPIO_2 is used for CHV x2 PHY (DP/HDMI B and C) - */ - if (IS_CHERRYVIEW(dev)) { - DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO_2; - DPIO_PHY_IOSF_PORT(DPIO_PHY1) = IOSF_PORT_DPIO; - } else { - DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO; - } -} - static void vlv_enable_pll(struct intel_crtc *crtc, const struct intel_crtc_state *pipe_config) { @@ -14767,8 +14747,6 @@ void intel_modeset_init(struct drm_device *dev) } } - intel_init_dpio(dev); - intel_shared_dpll_init(dev); /* Just disable it once at startup */ -- cgit v0.10.2 From 770effb19fbdcb44c6bdacf4a78571d28393f48f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 8 Jul 2015 23:45:51 +0300 Subject: drm/i915: Add locking around chv_phy_control_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dev_priv->chv_phy_control is protected by the power_domains->lock elsewhere, so also grab it when initializing chv_phy_control. Signed-off-by: Ville Syrjälä Reviewed-by: Deepak S Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 821644d..974c4cb 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -1685,7 +1685,9 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv) power_domains->initializing = true; if (IS_CHERRYVIEW(dev)) { + mutex_lock(&power_domains->lock); chv_phy_control_init(dev_priv); + mutex_unlock(&power_domains->lock); } else if (IS_VALLEYVIEW(dev)) { mutex_lock(&power_domains->lock); vlv_cmnlane_wa(dev_priv); -- cgit v0.10.2 From c0b4c660311c73c8ee4ed0e58b65ae9b4b75276d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 8 Jul 2015 23:45:52 +0300 Subject: drm/i915: Move VLV/CHV prepare_pll later MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With DPIO powergating active on CHV, we can't even access the DPIO PLL registers until the lane power state overrides have been enabled. That will happen from the encoder .pre_pll_enable() hook, so move chv_prepare_pll() to happen after that point, which puts it just before chv_enable_pll() actually. Do the same for VLV to avoid accumulating weird differences between the platforms. Both platforms seem happy with the new arrangement. Signed-off-by: Ville Syrjälä Reviewed-by: Deepak S Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3c2c76b..50cbc7e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6001,13 +6001,6 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) is_dsi = intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI); - if (!is_dsi) { - if (IS_CHERRYVIEW(dev)) - chv_prepare_pll(intel_crtc, intel_crtc->config); - else - vlv_prepare_pll(intel_crtc, intel_crtc->config); - } - if (intel_crtc->config->has_dp_encoder) intel_dp_set_m_n(intel_crtc, M1_N1); @@ -6031,10 +6024,13 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) encoder->pre_pll_enable(encoder); if (!is_dsi) { - if (IS_CHERRYVIEW(dev)) + if (IS_CHERRYVIEW(dev)) { + chv_prepare_pll(intel_crtc, intel_crtc->config); chv_enable_pll(intel_crtc, intel_crtc->config); - else + } else { + vlv_prepare_pll(intel_crtc, intel_crtc->config); vlv_enable_pll(intel_crtc, intel_crtc->config); + } } for_each_encoder_on_crtc(dev, crtc, encoder) -- cgit v0.10.2 From 65d64cc5bb7aee1f5a8d6717f4d421623c58ea30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 8 Jul 2015 23:45:53 +0300 Subject: drm/i915: Add vlv_dport_to_phy() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add vlv_dport_to_phy() and fix up the return values of vlv_dport_to_channel() and vlv_pipe_to_channel() to use the appropriate enums. Signed-off-by: Ville Syrjälä Reviewed-by: Deepak S Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 525e457..49d1b61 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -788,7 +788,7 @@ struct intel_dp_mst_encoder { void *port; /* store this opaque as its illegal to dereference it */ }; -static inline int +static inline enum dpio_channel vlv_dport_to_channel(struct intel_digital_port *dport) { switch (dport->port) { @@ -802,7 +802,21 @@ vlv_dport_to_channel(struct intel_digital_port *dport) } } -static inline int +static inline enum dpio_phy +vlv_dport_to_phy(struct intel_digital_port *dport) +{ + switch (dport->port) { + case PORT_B: + case PORT_C: + return DPIO_PHY0; + case PORT_D: + return DPIO_PHY1; + default: + BUG(); + } +} + +static inline enum dpio_channel vlv_pipe_to_channel(enum pipe pipe) { switch (pipe) { -- cgit v0.10.2 From adafdc6fcb66ea6541a88884ec522273f857c145 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Tue, 18 Aug 2015 14:36:59 +0300 Subject: drm/i915: Store max dotclock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Store max dotclock into dev_priv structure so we are able to filter out the modes that are not supported by our platforms. V2: - limit the max dot clock frequency to max CD clock frequency for the gen9 and above - limit the max dot clock frequency to 90% of the max CD clock frequency for the older gens - for Cherryview the max dot clock frequency is limited to 95% of the max CD clock frequency - for gen2 and gen3 the max dot clock limit is set to 90% of the 2X max CD clock frequency V3: - max_dotclk variable renamed as max_dotclk_freq in i915_drv.h - in intel_compute_max_dotclk() the rounding method changed from round up to round down when computing max dotclock V4: - Haswell and Broadwell supports now dot clocks up to max CD clock frequency Signed-off-by: Mika Kahola Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ce41d24..705f208 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1792,6 +1792,7 @@ struct drm_i915_private { unsigned int fsb_freq, mem_freq, is_ddr3; unsigned int skl_boot_cdclk; unsigned int cdclk_freq, max_cdclk_freq; + unsigned int max_dotclk_freq; unsigned int hpll_freq; /** diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 50cbc7e..03e84ac 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5240,6 +5240,21 @@ static void modeset_update_crtc_power_domains(struct drm_atomic_state *state) modeset_put_power_domains(dev_priv, put_domains[i]); } +static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv) +{ + int max_cdclk_freq = dev_priv->max_cdclk_freq; + + if (INTEL_INFO(dev_priv)->gen >= 9 || + IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) + return max_cdclk_freq; + else if (IS_CHERRYVIEW(dev_priv)) + return max_cdclk_freq*95/100; + else if (INTEL_INFO(dev_priv)->gen < 4) + return 2*max_cdclk_freq*90/100; + else + return max_cdclk_freq*90/100; +} + static void intel_update_max_cdclk(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -5279,8 +5294,13 @@ static void intel_update_max_cdclk(struct drm_device *dev) dev_priv->max_cdclk_freq = dev_priv->cdclk_freq; } + dev_priv->max_dotclk_freq = intel_compute_max_dotclk(dev_priv); + DRM_DEBUG_DRIVER("Max CD clock rate: %d kHz\n", dev_priv->max_cdclk_freq); + + DRM_DEBUG_DRIVER("Max dotclock rate: %d kHz\n", + dev_priv->max_dotclk_freq); } static void intel_update_cdclk(struct drm_device *dev) -- cgit v0.10.2 From 7f7b58cc61883bd16dfd4cae67d7404f7905d0a7 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Tue, 18 Aug 2015 14:37:00 +0300 Subject: drm/i915: LVDS pixel clock check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is possible the we request to have a mode that has higher pixel clock than our HW can support. This patch checks if requested pixel clock is lower than the one supported by the HW. The requested mode is discarded if we cannot support the requested pixel clock. This patch applies to LVDS. V2: - removed computation for max pixel clock V3: - cleanup by removing unnecessary lines V4: - moved supported dotclock check from mode_valid() to intel_lvds_init() V5: - dotclock check moved back to mode_valid() function - dotclock check for fixed mode Signed-off-by: Mika Kahola Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 881b5d1..0794dc8 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -289,11 +289,14 @@ intel_lvds_mode_valid(struct drm_connector *connector, { struct intel_connector *intel_connector = to_intel_connector(connector); struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; + int max_pixclk = to_i915(connector->dev)->max_dotclk_freq; if (mode->hdisplay > fixed_mode->hdisplay) return MODE_PANEL; if (mode->vdisplay > fixed_mode->vdisplay) return MODE_PANEL; + if (fixed_mode->clock > max_pixclk) + return MODE_CLOCK_HIGH; return MODE_OK; } -- cgit v0.10.2 From 759a1e98213f17d51926495e6754fdaced5f7d81 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Tue, 18 Aug 2015 14:37:01 +0300 Subject: drm/i915: DSI pixel clock check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is possible the we request to have a mode that has higher pixel clock than our HW can support. This patch checks if requested pixel clock is lower than the one supported by the HW. The requested mode is discarded if we cannot support the requested pixel clock. This patch applies to DSI. V2: - removed computation for max pixel clock V3: - cleanup by removing unnecessary lines V4: - max_pixclk variable renamed as max_dotclk - moved dot clock checking inside 'if (fixed_mode)' V5: - dot clock checked against fixed_mode clock Signed-off-by: Mika Kahola Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 4a601cf..781c267 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -654,6 +654,7 @@ intel_dsi_mode_valid(struct drm_connector *connector, { struct intel_connector *intel_connector = to_intel_connector(connector); struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; + int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; DRM_DEBUG_KMS("\n"); @@ -667,6 +668,8 @@ intel_dsi_mode_valid(struct drm_connector *connector, return MODE_PANEL; if (mode->vdisplay > fixed_mode->vdisplay) return MODE_PANEL; + if (fixed_mode->clock > max_dotclk) + return MODE_CLOCK_HIGH; } return MODE_OK; -- cgit v0.10.2 From 26a91555bd27b0672ab4efaf4de04fe7321540dc Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Tue, 18 Aug 2015 14:37:02 +0300 Subject: drm/i915: DVO pixel clock check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is possible the we request to have a mode that has higher pixel clock than our HW can support. This patch checks if requested pixel clock is lower than the one supported by the HW. The requested mode is discarded if we cannot support the requested pixel clock. This patch applies to DVO. V2: - removed computation for max pixel clock V3: - cleanup by removing unnecessary lines V4: - clock check against max dotclock moved inside 'if (fixed_mode)' V5: - dot clock check against fixed_mode clock when available Signed-off-by: Mika Kahola Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index dc532bb..c80fe1f 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -201,6 +201,8 @@ intel_dvo_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { struct intel_dvo *intel_dvo = intel_attached_dvo(connector); + int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; + int target_clock = mode->clock; if (mode->flags & DRM_MODE_FLAG_DBLSCAN) return MODE_NO_DBLESCAN; @@ -212,8 +214,13 @@ intel_dvo_mode_valid(struct drm_connector *connector, return MODE_PANEL; if (mode->vdisplay > intel_dvo->panel_fixed_mode->vdisplay) return MODE_PANEL; + + target_clock = intel_dvo->panel_fixed_mode->clock; } + if (target_clock > max_dotclk) + return MODE_CLOCK_HIGH; + return intel_dvo->dev.dev_ops->mode_valid(&intel_dvo->dev, mode); } -- cgit v0.10.2 From b93433ccf64846820b9448f5ff5dd4348b58a8ed Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 20 Aug 2015 10:47:36 +0300 Subject: drm/i915: move ibx_digital_port_connected to intel_dp.c The function can be made static there. No functional changes. Reviewed-by: Durgadoss R Signed-off-by: Jani Nikula Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 03e84ac..f32206d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1061,51 +1061,6 @@ static void intel_wait_for_pipe_off(struct intel_crtc *crtc) } } -/* - * ibx_digital_port_connected - is the specified port connected? - * @dev_priv: i915 private structure - * @port: the port to test - * - * Returns true if @port is connected, false otherwise. - */ -bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, - struct intel_digital_port *port) -{ - u32 bit; - - if (HAS_PCH_IBX(dev_priv->dev)) { - switch (port->port) { - case PORT_B: - bit = SDE_PORTB_HOTPLUG; - break; - case PORT_C: - bit = SDE_PORTC_HOTPLUG; - break; - case PORT_D: - bit = SDE_PORTD_HOTPLUG; - break; - default: - return true; - } - } else { - switch (port->port) { - case PORT_B: - bit = SDE_PORTB_HOTPLUG_CPT; - break; - case PORT_C: - bit = SDE_PORTC_HOTPLUG_CPT; - break; - case PORT_D: - bit = SDE_PORTD_HOTPLUG_CPT; - break; - default: - return true; - } - } - - return I915_READ(SDEISR) & bit; -} - static const char *state_string(bool enabled) { return enabled ? "on" : "off"; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 4e5bd87..307a45b 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4480,17 +4480,49 @@ edp_detect(struct intel_dp *intel_dp) return status; } -static enum drm_connector_status -ironlake_dp_detect(struct intel_dp *intel_dp) +/* + * ibx_digital_port_connected - is the specified port connected? + * @dev_priv: i915 private structure + * @port: the port to test + * + * Returns true if @port is connected, false otherwise. + */ +static bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, + struct intel_digital_port *port) { - struct drm_device *dev = intel_dp_to_dev(intel_dp); - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + u32 bit; - if (!ibx_digital_port_connected(dev_priv, intel_dig_port)) - return connector_status_disconnected; + if (HAS_PCH_IBX(dev_priv->dev)) { + switch (port->port) { + case PORT_B: + bit = SDE_PORTB_HOTPLUG; + break; + case PORT_C: + bit = SDE_PORTC_HOTPLUG; + break; + case PORT_D: + bit = SDE_PORTD_HOTPLUG; + break; + default: + return true; + } + } else { + switch (port->port) { + case PORT_B: + bit = SDE_PORTB_HOTPLUG_CPT; + break; + case PORT_C: + bit = SDE_PORTC_HOTPLUG_CPT; + break; + case PORT_D: + bit = SDE_PORTD_HOTPLUG_CPT; + break; + default: + return true; + } + } - return intel_dp_detect_dpcd(intel_dp); + return I915_READ(SDEISR) & bit; } static int g4x_digital_port_connected(struct drm_device *dev, @@ -4535,6 +4567,19 @@ static int g4x_digital_port_connected(struct drm_device *dev, } static enum drm_connector_status +ironlake_dp_detect(struct intel_dp *intel_dp) +{ + struct drm_device *dev = intel_dp_to_dev(intel_dp); + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + + if (!ibx_digital_port_connected(dev_priv, intel_dig_port)) + return connector_status_disconnected; + + return intel_dp_detect_dpcd(intel_dp); +} + +static enum drm_connector_status g4x_dp_detect(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 49d1b61..aa79717 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1018,8 +1018,6 @@ void intel_encoder_destroy(struct drm_encoder *encoder); int intel_connector_init(struct intel_connector *); struct intel_connector *intel_connector_alloc(void); bool intel_connector_get_hw_state(struct intel_connector *connector); -bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, - struct intel_digital_port *port); void intel_connector_attach_encoder(struct intel_connector *connector, struct intel_encoder *encoder); struct drm_encoder *intel_best_encoder(struct drm_connector *connector); -- cgit v0.10.2 From 1d245987754f8cd0bf21c77ecda2023ca13ff8c1 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 20 Aug 2015 10:47:37 +0300 Subject: drm/i915: make g4x_digital_port_connected return boolean status We should not be hitting any of the default cases in g4x_digital_port_connected, so add MISSING_CASE annotation and return boolean status. The current behaviour is just cargo culting from the days of yonder when the display port support was added to i915. Signed-off-by: Jani Nikula Reviewed-by: Durgadoss R Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 307a45b..be53e36 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4525,14 +4525,14 @@ static bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, return I915_READ(SDEISR) & bit; } -static int g4x_digital_port_connected(struct drm_device *dev, - struct intel_digital_port *intel_dig_port) +static bool g4x_digital_port_connected(struct drm_device *dev, + struct intel_digital_port *port) { struct drm_i915_private *dev_priv = dev->dev_private; uint32_t bit; if (IS_VALLEYVIEW(dev)) { - switch (intel_dig_port->port) { + switch (port->port) { case PORT_B: bit = PORTB_HOTPLUG_LIVE_STATUS_VLV; break; @@ -4543,10 +4543,11 @@ static int g4x_digital_port_connected(struct drm_device *dev, bit = PORTD_HOTPLUG_LIVE_STATUS_VLV; break; default: - return -EINVAL; + MISSING_CASE(port->port); + return false; } } else { - switch (intel_dig_port->port) { + switch (port->port) { case PORT_B: bit = PORTB_HOTPLUG_LIVE_STATUS_G4X; break; @@ -4557,13 +4558,12 @@ static int g4x_digital_port_connected(struct drm_device *dev, bit = PORTD_HOTPLUG_LIVE_STATUS_G4X; break; default: - return -EINVAL; + MISSING_CASE(port->port); + return false; } } - if ((I915_READ(PORT_HOTPLUG_STAT) & bit) == 0) - return 0; - return 1; + return I915_READ(PORT_HOTPLUG_STAT) & bit; } static enum drm_connector_status @@ -4584,7 +4584,6 @@ g4x_dp_detect(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - int ret; /* Can't disconnect eDP, but you can close the lid... */ if (is_edp(intel_dp)) { @@ -4596,10 +4595,7 @@ g4x_dp_detect(struct intel_dp *intel_dp) return status; } - ret = g4x_digital_port_connected(dev, intel_dig_port); - if (ret == -EINVAL) - return connector_status_unknown; - else if (ret == 0) + if (!g4x_digital_port_connected(dev, intel_dig_port)) return connector_status_disconnected; return intel_dp_detect_dpcd(intel_dp); @@ -5066,7 +5062,7 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) if (!ibx_digital_port_connected(dev_priv, intel_dig_port)) goto mst_fail; } else { - if (g4x_digital_port_connected(dev, intel_dig_port) != 1) + if (!g4x_digital_port_connected(dev, intel_dig_port)) goto mst_fail; } -- cgit v0.10.2 From 196cabd4a39496038ee81c2755496955e7355bd5 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 20 Aug 2015 10:47:38 +0300 Subject: drm/i915: add MISSING_CASE annotation to ibx_digital_port_connected With the case added for eDP on port A (always connected from this function's point of view), we should not be hitting any of the default cases in ibx_digital_port_connected, so add MISSING_CASE annotation. Signed-off-by: Jani Nikula Reviewed-by: Durgadoss R Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index be53e36..8c8070e 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4494,6 +4494,8 @@ static bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, if (HAS_PCH_IBX(dev_priv->dev)) { switch (port->port) { + case PORT_A: + return true; case PORT_B: bit = SDE_PORTB_HOTPLUG; break; @@ -4504,10 +4506,13 @@ static bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, bit = SDE_PORTD_HOTPLUG; break; default: - return true; + MISSING_CASE(port->port); + return false; } } else { switch (port->port) { + case PORT_A: + return true; case PORT_B: bit = SDE_PORTB_HOTPLUG_CPT; break; @@ -4518,7 +4523,8 @@ static bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, bit = SDE_PORTD_HOTPLUG_CPT; break; default: - return true; + MISSING_CASE(port->port); + return false; } } -- cgit v0.10.2 From 7e66bcf2656ad2e53de939c5a5f211288a332ede Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 20 Aug 2015 10:47:39 +0300 Subject: drm/i915: add common intel_digital_port_connected function Add a common intel_digital_port_connected() that splits out to functions for different platforms. No functional changes. v2: make the function return a boolean Signed-off-by: Jani Nikula Reviewed-by: Durgadoss R Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 8c8070e..1db7e1e 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4480,13 +4480,6 @@ edp_detect(struct intel_dp *intel_dp) return status; } -/* - * ibx_digital_port_connected - is the specified port connected? - * @dev_priv: i915 private structure - * @port: the port to test - * - * Returns true if @port is connected, false otherwise. - */ static bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, struct intel_digital_port *port) { @@ -4531,13 +4524,12 @@ static bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, return I915_READ(SDEISR) & bit; } -static bool g4x_digital_port_connected(struct drm_device *dev, +static bool g4x_digital_port_connected(struct drm_i915_private *dev_priv, struct intel_digital_port *port) { - struct drm_i915_private *dev_priv = dev->dev_private; uint32_t bit; - if (IS_VALLEYVIEW(dev)) { + if (IS_VALLEYVIEW(dev_priv)) { switch (port->port) { case PORT_B: bit = PORTB_HOTPLUG_LIVE_STATUS_VLV; @@ -4572,6 +4564,22 @@ static bool g4x_digital_port_connected(struct drm_device *dev, return I915_READ(PORT_HOTPLUG_STAT) & bit; } +/* + * intel_digital_port_connected - is the specified port connected? + * @dev_priv: i915 private structure + * @port: the port to test + * + * Return %true if @port is connected, %false otherwise. + */ +static bool intel_digital_port_connected(struct drm_i915_private *dev_priv, + struct intel_digital_port *port) +{ + if (HAS_PCH_SPLIT(dev_priv)) + return ibx_digital_port_connected(dev_priv, port); + else + return g4x_digital_port_connected(dev_priv, port); +} + static enum drm_connector_status ironlake_dp_detect(struct intel_dp *intel_dp) { @@ -4579,7 +4587,7 @@ ironlake_dp_detect(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - if (!ibx_digital_port_connected(dev_priv, intel_dig_port)) + if (!intel_digital_port_connected(dev_priv, intel_dig_port)) return connector_status_disconnected; return intel_dp_detect_dpcd(intel_dp); @@ -4601,7 +4609,7 @@ g4x_dp_detect(struct intel_dp *intel_dp) return status; } - if (!g4x_digital_port_connected(dev, intel_dig_port)) + if (!intel_digital_port_connected(dev->dev_private, intel_dig_port)) return connector_status_disconnected; return intel_dp_detect_dpcd(intel_dp); @@ -5064,13 +5072,8 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) /* indicate that we need to restart link training */ intel_dp->train_set_valid = false; - if (HAS_PCH_SPLIT(dev)) { - if (!ibx_digital_port_connected(dev_priv, intel_dig_port)) - goto mst_fail; - } else { - if (!g4x_digital_port_connected(dev, intel_dig_port)) - goto mst_fail; - } + if (!intel_digital_port_connected(dev_priv, intel_dig_port)) + goto mst_fail; if (!intel_dp_get_dpcd(intel_dp)) { goto mst_fail; -- cgit v0.10.2 From 0df53b77287198502ff2eb51120c041ba317f059 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 20 Aug 2015 10:47:40 +0300 Subject: drm/i915: split ibx_digital_port_connected to ibx and cpt variants Choose the right function at the intel_digital_port_connected level. Signed-off-by: Jani Nikula Reviewed-by: Durgadoss R Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1db7e1e..689dfe6 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4485,40 +4485,46 @@ static bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, { u32 bit; - if (HAS_PCH_IBX(dev_priv->dev)) { - switch (port->port) { - case PORT_A: - return true; - case PORT_B: - bit = SDE_PORTB_HOTPLUG; - break; - case PORT_C: - bit = SDE_PORTC_HOTPLUG; - break; - case PORT_D: - bit = SDE_PORTD_HOTPLUG; - break; - default: - MISSING_CASE(port->port); - return false; - } - } else { - switch (port->port) { - case PORT_A: - return true; - case PORT_B: - bit = SDE_PORTB_HOTPLUG_CPT; - break; - case PORT_C: - bit = SDE_PORTC_HOTPLUG_CPT; - break; - case PORT_D: - bit = SDE_PORTD_HOTPLUG_CPT; - break; - default: - MISSING_CASE(port->port); - return false; - } + switch (port->port) { + case PORT_A: + return true; + case PORT_B: + bit = SDE_PORTB_HOTPLUG; + break; + case PORT_C: + bit = SDE_PORTC_HOTPLUG; + break; + case PORT_D: + bit = SDE_PORTD_HOTPLUG; + break; + default: + MISSING_CASE(port->port); + return false; + } + + return I915_READ(SDEISR) & bit; +} + +static bool cpt_digital_port_connected(struct drm_i915_private *dev_priv, + struct intel_digital_port *port) +{ + u32 bit; + + switch (port->port) { + case PORT_A: + return true; + case PORT_B: + bit = SDE_PORTB_HOTPLUG_CPT; + break; + case PORT_C: + bit = SDE_PORTC_HOTPLUG_CPT; + break; + case PORT_D: + bit = SDE_PORTD_HOTPLUG_CPT; + break; + default: + MISSING_CASE(port->port); + return false; } return I915_READ(SDEISR) & bit; @@ -4574,8 +4580,10 @@ static bool g4x_digital_port_connected(struct drm_i915_private *dev_priv, static bool intel_digital_port_connected(struct drm_i915_private *dev_priv, struct intel_digital_port *port) { - if (HAS_PCH_SPLIT(dev_priv)) + if (HAS_PCH_IBX(dev_priv)) return ibx_digital_port_connected(dev_priv, port); + if (HAS_PCH_SPLIT(dev_priv)) + return cpt_digital_port_connected(dev_priv, port); else return g4x_digital_port_connected(dev_priv, port); } -- cgit v0.10.2 From 9642c81c225a43982536fcb7a3fa212dcfaa67ea Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 20 Aug 2015 10:47:41 +0300 Subject: drm/i915: split g4x_digital_port_connected to g4x and vlv variants Choose the right function at the intel_digital_port_connected level. Signed-off-by: Jani Nikula Reviewed-by: Durgadoss R Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 689dfe6..e7ebacd5 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4533,38 +4533,44 @@ static bool cpt_digital_port_connected(struct drm_i915_private *dev_priv, static bool g4x_digital_port_connected(struct drm_i915_private *dev_priv, struct intel_digital_port *port) { - uint32_t bit; + u32 bit; - if (IS_VALLEYVIEW(dev_priv)) { - switch (port->port) { - case PORT_B: - bit = PORTB_HOTPLUG_LIVE_STATUS_VLV; - break; - case PORT_C: - bit = PORTC_HOTPLUG_LIVE_STATUS_VLV; - break; - case PORT_D: - bit = PORTD_HOTPLUG_LIVE_STATUS_VLV; - break; - default: - MISSING_CASE(port->port); - return false; - } - } else { - switch (port->port) { - case PORT_B: - bit = PORTB_HOTPLUG_LIVE_STATUS_G4X; - break; - case PORT_C: - bit = PORTC_HOTPLUG_LIVE_STATUS_G4X; - break; - case PORT_D: - bit = PORTD_HOTPLUG_LIVE_STATUS_G4X; - break; - default: - MISSING_CASE(port->port); - return false; - } + switch (port->port) { + case PORT_B: + bit = PORTB_HOTPLUG_LIVE_STATUS_G4X; + break; + case PORT_C: + bit = PORTC_HOTPLUG_LIVE_STATUS_G4X; + break; + case PORT_D: + bit = PORTD_HOTPLUG_LIVE_STATUS_G4X; + break; + default: + MISSING_CASE(port->port); + return false; + } + + return I915_READ(PORT_HOTPLUG_STAT) & bit; +} + +static bool vlv_digital_port_connected(struct drm_i915_private *dev_priv, + struct intel_digital_port *port) +{ + u32 bit; + + switch (port->port) { + case PORT_B: + bit = PORTB_HOTPLUG_LIVE_STATUS_VLV; + break; + case PORT_C: + bit = PORTC_HOTPLUG_LIVE_STATUS_VLV; + break; + case PORT_D: + bit = PORTD_HOTPLUG_LIVE_STATUS_VLV; + break; + default: + MISSING_CASE(port->port); + return false; } return I915_READ(PORT_HOTPLUG_STAT) & bit; @@ -4584,6 +4590,8 @@ static bool intel_digital_port_connected(struct drm_i915_private *dev_priv, return ibx_digital_port_connected(dev_priv, port); if (HAS_PCH_SPLIT(dev_priv)) return cpt_digital_port_connected(dev_priv, port); + else if (IS_VALLEYVIEW(dev_priv)) + return vlv_digital_port_connected(dev_priv, port); else return g4x_digital_port_connected(dev_priv, port); } -- cgit v0.10.2 From e464bfdeda3da3b0ef29ca84960715993ccbb1fc Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 20 Aug 2015 10:47:42 +0300 Subject: drm/i915/bxt: Use correct live status register for BXT platform BXT platform uses live status bits from 0x44440 register to obtain DP status on hotplug. The existing g4x_digital_port_connected() uses a different register and hence misses DP hotplug events on BXT platform. This patch fixes it by using the appropriate register(0x44440) and live status bits(3:5). Based on a patch by Durgadoss R , from whom the commit message is shamelessly copy pasted. Reported-by: Durgadoss R Signed-off-by: Jani Nikula Reviewed-by: Durgadoss R Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index e7ebacd5..1ff063e 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4576,6 +4576,29 @@ static bool vlv_digital_port_connected(struct drm_i915_private *dev_priv, return I915_READ(PORT_HOTPLUG_STAT) & bit; } +static bool bxt_digital_port_connected(struct drm_i915_private *dev_priv, + struct intel_digital_port *port) +{ + u32 bit; + + switch (port->port) { + case PORT_A: + bit = BXT_DE_PORT_HP_DDIA; + break; + case PORT_B: + bit = BXT_DE_PORT_HP_DDIB; + break; + case PORT_C: + bit = BXT_DE_PORT_HP_DDIC; + break; + default: + MISSING_CASE(port->port); + return false; + } + + return I915_READ(GEN8_DE_PORT_ISR) & bit; +} + /* * intel_digital_port_connected - is the specified port connected? * @dev_priv: i915 private structure @@ -4590,6 +4613,8 @@ static bool intel_digital_port_connected(struct drm_i915_private *dev_priv, return ibx_digital_port_connected(dev_priv, port); if (HAS_PCH_SPLIT(dev_priv)) return cpt_digital_port_connected(dev_priv, port); + else if (IS_BROXTON(dev_priv)) + return bxt_digital_port_connected(dev_priv, port); else if (IS_VALLEYVIEW(dev_priv)) return vlv_digital_port_connected(dev_priv, port); else -- cgit v0.10.2 From 0a0b457fbf765d0b98fa48495b9bb7901eb8b091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 21 Aug 2015 20:45:27 +0300 Subject: drm/i915: Fix some gcc warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simple one: drivers/gpu/drm/i915/i915_debugfs.c:2449:57: warning: Using plain integer as NULL pointer And something a bit more peculiar: drivers/gpu/drm/i915/i915_debugfs.c:4953:18: warning: Variable length array is used. drivers/gpu/drm/i915/i915_debugfs.c:4953:32: warning: Variable length array is used. We pass a 'const int' as the array size which results in the warning, dropping the const gets rid of the warning. Weird, but I think getting rid of the warnings is better than holding on to the const. Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e192f02..624024c 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2446,7 +2446,7 @@ static int i915_guc_info(struct seq_file *m, void *data) struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_guc guc; - struct i915_guc_client client = { .client_obj = 0 }; + struct i915_guc_client client = {}; struct intel_engine_cs *ring; enum intel_ring_id i; u64 total = 0; @@ -4948,7 +4948,7 @@ static void cherryview_sseu_device_status(struct drm_device *dev, struct sseu_dev_status *stat) { struct drm_i915_private *dev_priv = dev->dev_private; - const int ss_max = 2; + int ss_max = 2; int ss; u32 sig1[ss_max], sig2[ss_max]; -- cgit v0.10.2 From 53abb6794ac022e6c0b5f239fc26d99ea054ee86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 21 Aug 2015 20:45:28 +0300 Subject: drm/i915: Use ARRAY_SIZE() instead of hand rolling it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A couple of hand rolled ARRAY_SIZE()s caught my eye. Get rid of them. Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index c98098e..25d74d2 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -63,7 +63,7 @@ static const char *tv_format_names[] = { "SECAM_60" }; -#define TV_FORMAT_NUM (sizeof(tv_format_names) / sizeof(*tv_format_names)) +#define TV_FORMAT_NUM ARRAY_SIZE(tv_format_names) struct intel_sdvo { struct intel_encoder base; diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 0568ae6..cbe39dc 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1291,7 +1291,7 @@ static void intel_tv_find_better_format(struct drm_connector *connector) return; - for (i = 0; i < sizeof(tv_modes) / sizeof(*tv_modes); i++) { + for (i = 0; i < ARRAY_SIZE(tv_modes); i++) { tv_mode = tv_modes + i; if ((intel_tv->type == DRM_MODE_CONNECTOR_Component) == diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 9d3c2e4..ad4e421 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -52,8 +52,7 @@ static const char * const forcewake_domain_names[] = { const char * intel_uncore_forcewake_domain_to_str(const enum forcewake_domain_id id) { - BUILD_BUG_ON((sizeof(forcewake_domain_names)/sizeof(const char *)) != - FW_DOMAIN_ID_COUNT); + BUILD_BUG_ON(ARRAY_SIZE(forcewake_domain_names) != FW_DOMAIN_ID_COUNT); if (id >= 0 && id < FW_DOMAIN_ID_COUNT) return forcewake_domain_names[id]; -- cgit v0.10.2 From 4d9194dec37a9bf22354f6a5872e285e1bb8c1da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 21 Aug 2015 20:45:29 +0300 Subject: drm/i915: Make some string arrays const MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most of our char* arrays are markes as const already, but a few slipped through the cracks. Fix it. Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 25d74d2..ca3dd7c 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -53,7 +53,7 @@ #define IS_DIGITAL(c) (c->output_flag & (SDVO_TMDS_MASK | SDVO_LVDS_MASK)) -static const char *tv_format_names[] = { +static const char * const tv_format_names[] = { "NTSC_M" , "NTSC_J" , "NTSC_443", "PAL_B" , "PAL_D" , "PAL_G" , "PAL_H" , "PAL_I" , "PAL_M" , @@ -452,7 +452,7 @@ static void intel_sdvo_debug_write(struct intel_sdvo *intel_sdvo, u8 cmd, DRM_DEBUG_KMS("%s: W: %02X %s\n", SDVO_NAME(intel_sdvo), cmd, buffer); } -static const char *cmd_status_names[] = { +static const char * const cmd_status_names[] = { "Power on", "Success", "Not supported", -- cgit v0.10.2 From 5a8fbb7d192b96de3d258164e5fc95b769d698c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 29 Jun 2015 15:25:53 +0300 Subject: drm/i915: Move DPLL ref/cri/VGA mode frobbing to the disp2d well enable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bunch of stuff needs the DPLL ref/cri clocks on both VLV and CHV, and having VGA mode enabled causes some problems for CHV. So let's just pull the code to configure those bits into the disp2d well enable hook. With the DPLL disable code also fixed to leave those bits alone we should now have a consistent DPLL state all the time even if the DPLL is disabled. This also neatly removes some duplicated code between the VLV and CHV codepaths. Signed-off-by: Ville Syrjälä Reviewed-by: Sivakumar Thulasimani Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 974c4cb..0588baa 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -853,6 +853,25 @@ static bool vlv_power_well_enabled(struct drm_i915_private *dev_priv, static void vlv_display_power_well_init(struct drm_i915_private *dev_priv) { + enum pipe pipe; + + /* + * Enable the CRI clock source so we can get at the + * display and the reference clock for VGA + * hotplug / manual detection. Supposedly DSI also + * needs the ref clock up and running. + * + * CHV DPLL B/C have some issues if VGA mode is enabled. + */ + for_each_pipe(dev_priv->dev, pipe) { + u32 val = I915_READ(DPLL(pipe)); + + val |= DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS; + if (pipe != PIPE_A) + val |= DPLL_INTEGRATED_CRI_CLK_VLV; + + I915_WRITE(DPLL(pipe), val); + } spin_lock_irq(&dev_priv->irq_lock); valleyview_enable_display_irqs(dev_priv); @@ -904,13 +923,7 @@ static void vlv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, { WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC); - /* - * Enable the CRI clock source so we can get at the - * display and the reference clock for VGA - * hotplug / manual detection. - */ - I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) | DPLL_VGA_MODE_DIS | - DPLL_REF_CLK_ENABLE_VLV | DPLL_INTEGRATED_CRI_CLK_VLV); + /* since ref/cri clock was enabled */ udelay(1); /* >10ns for cmnreset, >0ns for sidereset */ vlv_set_power_well(dev_priv, power_well, true); @@ -953,22 +966,12 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC && power_well->data != PUNIT_POWER_WELL_DPIO_CMN_D); - /* - * Enable the CRI clock source so we can get at the - * display and the reference clock for VGA - * hotplug / manual detection. - */ - if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) { + if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) phy = DPIO_PHY0; - I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) | DPLL_VGA_MODE_DIS | - DPLL_REF_CLK_ENABLE_VLV); - I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) | DPLL_VGA_MODE_DIS | - DPLL_REF_CLK_ENABLE_VLV | DPLL_INTEGRATED_CRI_CLK_VLV); - } else { + else phy = DPIO_PHY1; - I915_WRITE(DPLL(PIPE_C), I915_READ(DPLL(PIPE_C)) | DPLL_VGA_MODE_DIS | - DPLL_REF_CLK_ENABLE_VLV | DPLL_INTEGRATED_CRI_CLK_VLV); - } + + /* since ref/cri clock was enabled */ udelay(1); /* >10ns for cmnreset, >0ns for sidereset */ vlv_set_power_well(dev_priv, power_well, true); -- cgit v0.10.2 From e0fce78f041014846d77940d3a350a4cffe4ab2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 8 Jul 2015 23:45:54 +0300 Subject: drm/i915: Implement PHY lane power gating for CHV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Powergate the PHY lanes when they're not needed. For HDMI all four lanes are needed always, but for DP we can enable only the needed lanes. To power down the unused lanes we use some power down override bits in the DISPLAY_PHY_CONTROL register. Without the overrides it appears that the hardware always powers on all the lanes. When the port is disabled the power down override is not needed and the lanes will shut off on their own. That also means the override is critical to actually be able to access the DPIO registers before the port is actually enabled. Additionally the common lanes will power down when not needed. CL1 remains on as long as anything else is on, CL2 will shut down when all the lanes in the same channel will shut down. There is one exception for CL2 that will be dealt in a separate patch for clarity. With potentially some lanes powered down, the DP code now has to check the number of active lanes before accessing PCS/TX registers. All registers in powered down blocks will reads as 0xffffffff, and soe we would drown in warnings from vlv_dpio_read() if we allowed the code to access all those registers. Another important detail in the DP code is the "TX latency optimal" setting. Normally the second TX lane acts as some kind of reset master, with the other lanes as slaves. But when only a single lane is enabled, that single lane obviously has to be the master. A bit of extra care is needed to reconstruct the initial state of the DISPLAY_PHY_CONTROL register since it can't be read safely. So instead read the actual lane status from the DPLL/PHY_STATUS registers and use that to determine which lanes ought to be powergated initially. We also need to switch the PHY power modes to "deep PSR" to avoid a hard system hang when powering down the single channel PHY. Also sprinkle a few debug prints around so that we can monitor the DISPLAY_PHY_STATUS changes without having to read it and risk corrupting it. v2: Add locking to chv_powergate_phy_lanes() v3: Actually enable dynamic powerdown in the PHY and deal with the fallout Signed-off-by: Ville Syrjälä Reviewed-by: Deepak S Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 211b73a..6918ffa 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1135,9 +1135,15 @@ enum skl_disp_power_wells { #define _CHV_CMN_DW19_CH0 0x814c #define _CHV_CMN_DW6_CH1 0x8098 +#define DPIO_DYNPWRDOWNEN_CH1 (1 << 28) /* CL2 DW6 only */ #define CHV_CMN_USEDCLKCHANNEL (1 << 13) + #define CHV_CMN_DW19(ch) _PIPE(ch, _CHV_CMN_DW19_CH0, _CHV_CMN_DW6_CH1) +#define CHV_CMN_DW28 0x8170 +#define DPIO_CL1POWERDOWNEN (1 << 23) +#define DPIO_DYNPWRDOWNEN_CH0 (1 << 22) + #define CHV_CMN_DW30 0x8178 #define DPIO_LRC_BYPASS (1 << 3) @@ -2192,10 +2198,12 @@ enum skl_disp_power_wells { #define DPIO_PHY_STATUS (VLV_DISPLAY_BASE + 0x6240) #define DPLL_PORTD_READY_MASK (0xf) #define DISPLAY_PHY_CONTROL (VLV_DISPLAY_BASE + 0x60100) +#define PHY_CH_POWER_DOWN_OVRD_EN(phy, ch) (1 << (2*(phy)+(ch)+27)) #define PHY_LDO_DELAY_0NS 0x0 #define PHY_LDO_DELAY_200NS 0x1 #define PHY_LDO_DELAY_600NS 0x2 #define PHY_LDO_SEQ_DELAY(delay, phy) ((delay) << (2*(phy)+23)) +#define PHY_CH_POWER_DOWN_OVRD(mask, phy, ch) ((mask) << (8*(phy)+4*(ch)+11)) #define PHY_CH_SU_PSR 0x1 #define PHY_CH_DEEP_PSR 0x7 #define PHY_CH_POWER_MODE(mode, phy, ch) ((mode) << (6*(phy)+3*(ch)+2)) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1ff063e..c0eaf13 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -133,6 +133,11 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp); static void vlv_steal_power_sequencer(struct drm_device *dev, enum pipe pipe); +static unsigned int intel_dp_unused_lane_mask(int lane_count) +{ + return ~((1 << lane_count) - 1) & 0xf; +} + static int intel_dp_max_link_bw(struct intel_dp *intel_dp) { @@ -2432,17 +2437,21 @@ static void chv_post_disable_dp(struct intel_encoder *encoder) val |= CHV_PCS_REQ_SOFTRESET_EN; vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val); - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch)); - val |= CHV_PCS_REQ_SOFTRESET_EN; - vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val); + if (intel_crtc->config->lane_count > 2) { + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch)); + val |= CHV_PCS_REQ_SOFTRESET_EN; + vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val); + } val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch)); val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val); - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch)); - val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val); + if (intel_crtc->config->lane_count > 2) { + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch)); + val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); + vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val); + } mutex_unlock(&dev_priv->sb_lock); } @@ -2562,7 +2571,6 @@ static void intel_enable_dp(struct intel_encoder *encoder) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); uint32_t dp_reg = I915_READ(intel_dp->output_reg); - unsigned int lane_mask = 0x0; if (WARN_ON(dp_reg & DP_PORT_EN)) return; @@ -2580,9 +2588,15 @@ static void intel_enable_dp(struct intel_encoder *encoder) pps_unlock(intel_dp); - if (IS_VALLEYVIEW(dev)) + if (IS_VALLEYVIEW(dev)) { + unsigned int lane_mask = 0x0; + + if (IS_CHERRYVIEW(dev)) + lane_mask = intel_dp_unused_lane_mask(crtc->config->lane_count); + vlv_wait_port_ready(dev_priv, dp_to_dig_port(intel_dp), lane_mask); + } intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); intel_dp_start_link_train(intel_dp); @@ -2809,31 +2823,40 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder) val &= ~DPIO_LANEDESKEW_STRAP_OVRD; vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW11(ch), val); - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch)); - val &= ~DPIO_LANEDESKEW_STRAP_OVRD; - vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val); + if (intel_crtc->config->lane_count > 2) { + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch)); + val &= ~DPIO_LANEDESKEW_STRAP_OVRD; + vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val); + } /* Deassert soft data lane reset*/ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch)); val |= CHV_PCS_REQ_SOFTRESET_EN; vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val); - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch)); - val |= CHV_PCS_REQ_SOFTRESET_EN; - vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val); + if (intel_crtc->config->lane_count > 2) { + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch)); + val |= CHV_PCS_REQ_SOFTRESET_EN; + vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val); + } val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch)); val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val); - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch)); - val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val); + if (intel_crtc->config->lane_count > 2) { + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch)); + val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); + vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val); + } /* Program Tx lane latency optimal setting*/ - for (i = 0; i < 4; i++) { + for (i = 0; i < intel_crtc->config->lane_count; i++) { /* Set the upar bit */ - data = (i == 1) ? 0x0 : 0x1; + if (intel_crtc->config->lane_count == 1) + data = 0x0; + else + data = (i == 1) ? 0x0 : 0x1; vlv_dpio_write(dev_priv, pipe, CHV_TX_DW14(ch, i), data << DPIO_UPAR_SHIFT); } @@ -2854,9 +2877,11 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder) val |= DPIO_TX2_STAGGER_MASK(0x1f); vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW11(ch), val); - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch)); - val |= DPIO_TX2_STAGGER_MASK(0x1f); - vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val); + if (intel_crtc->config->lane_count > 2) { + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch)); + val |= DPIO_TX2_STAGGER_MASK(0x1f); + vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val); + } vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW12(ch), DPIO_LANESTAGGER_STRAP(stagger) | @@ -2865,12 +2890,14 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder) DPIO_TX1_STAGGER_MULT(6) | DPIO_TX2_STAGGER_MULT(0)); - vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW12(ch), - DPIO_LANESTAGGER_STRAP(stagger) | - DPIO_LANESTAGGER_STRAP_OVRD | - DPIO_TX1_STAGGER_MASK(0x1f) | - DPIO_TX1_STAGGER_MULT(7) | - DPIO_TX2_STAGGER_MULT(5)); + if (intel_crtc->config->lane_count > 2) { + vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW12(ch), + DPIO_LANESTAGGER_STRAP(stagger) | + DPIO_LANESTAGGER_STRAP_OVRD | + DPIO_TX1_STAGGER_MASK(0x1f) | + DPIO_TX1_STAGGER_MULT(7) | + DPIO_TX2_STAGGER_MULT(5)); + } mutex_unlock(&dev_priv->sb_lock); @@ -2886,10 +2913,14 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder) to_intel_crtc(encoder->base.crtc); enum dpio_channel ch = vlv_dport_to_channel(dport); enum pipe pipe = intel_crtc->pipe; + unsigned int lane_mask = + intel_dp_unused_lane_mask(intel_crtc->config->lane_count); u32 val; intel_dp_prepare(encoder); + chv_phy_powergate_lanes(encoder, true, lane_mask); + mutex_lock(&dev_priv->sb_lock); /* program left/right clock distribution */ @@ -2920,13 +2951,15 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder) val |= CHV_PCS_USEDCLKCHANNEL; vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW8(ch), val); - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW8(ch)); - val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE; - if (pipe != PIPE_B) - val &= ~CHV_PCS_USEDCLKCHANNEL; - else - val |= CHV_PCS_USEDCLKCHANNEL; - vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW8(ch), val); + if (intel_crtc->config->lane_count > 2) { + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW8(ch)); + val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE; + if (pipe != PIPE_B) + val &= ~CHV_PCS_USEDCLKCHANNEL; + else + val |= CHV_PCS_USEDCLKCHANNEL; + vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW8(ch), val); + } /* * This a a bit weird since generally CL @@ -2963,6 +2996,8 @@ static void chv_dp_post_pll_disable(struct intel_encoder *encoder) } mutex_unlock(&dev_priv->sb_lock); + + chv_phy_powergate_lanes(encoder, false, 0x0); } /* @@ -3298,24 +3333,28 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp) val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5; vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW10(ch), val); - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch)); - val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3); - val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK); - val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5; - vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val); + if (intel_crtc->config->lane_count > 2) { + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch)); + val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3); + val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK); + val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5; + vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val); + } val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW9(ch)); val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK); val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000; vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW9(ch), val); - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW9(ch)); - val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK); - val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000; - vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW9(ch), val); + if (intel_crtc->config->lane_count > 2) { + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW9(ch)); + val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK); + val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000; + vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW9(ch), val); + } /* Program swing deemph */ - for (i = 0; i < 4; i++) { + for (i = 0; i < intel_crtc->config->lane_count; i++) { val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW4(ch, i)); val &= ~DPIO_SWING_DEEMPH9P5_MASK; val |= deemph_reg_value << DPIO_SWING_DEEMPH9P5_SHIFT; @@ -3323,7 +3362,7 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp) } /* Program swing margin */ - for (i = 0; i < 4; i++) { + for (i = 0; i < intel_crtc->config->lane_count; i++) { val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i)); val &= ~DPIO_SWING_MARGIN000_MASK; @@ -3346,7 +3385,7 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp) * For now, for this unique transition scale selection, set bit * 27 for ch0 and ch1. */ - for (i = 0; i < 4; i++) { + for (i = 0; i < intel_crtc->config->lane_count; i++) { val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW3(ch, i)); if (chv_need_uniq_trans_scale(train_set)) val |= DPIO_TX_UNIQ_TRANS_SCALE_EN; @@ -3360,9 +3399,11 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp) val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3; vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW10(ch), val); - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch)); - val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3; - vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val); + if (intel_crtc->config->lane_count > 2) { + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch)); + val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3; + vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val); + } /* LRC Bypass */ val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW30); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index aa79717..df420d8 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1361,6 +1361,10 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv); void intel_display_set_init_power(struct drm_i915_private *dev, bool enable); +void chv_phy_powergate_lanes(struct intel_encoder *encoder, + bool override, unsigned int mask); + + /* intel_pm.c */ void intel_init_clock_gating(struct drm_device *dev); void intel_suspend_hw(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 269937a..f1ecc2c 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1628,6 +1628,8 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder) intel_hdmi_prepare(encoder); + chv_phy_powergate_lanes(encoder, true, 0x0); + mutex_lock(&dev_priv->sb_lock); /* program left/right clock distribution */ @@ -1701,6 +1703,8 @@ static void chv_hdmi_post_pll_disable(struct intel_encoder *encoder) } mutex_unlock(&dev_priv->sb_lock); + + chv_phy_powergate_lanes(encoder, false, 0x0); } static void vlv_hdmi_post_disable(struct intel_encoder *encoder) diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 0588baa..a159771 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -962,14 +962,19 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { enum dpio_phy phy; + enum pipe pipe; + uint32_t tmp; WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC && power_well->data != PUNIT_POWER_WELL_DPIO_CMN_D); - if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) + if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) { + pipe = PIPE_A; phy = DPIO_PHY0; - else + } else { + pipe = PIPE_C; phy = DPIO_PHY1; + } /* since ref/cri clock was enabled */ udelay(1); /* >10ns for cmnreset, >0ns for sidereset */ @@ -979,8 +984,26 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, if (wait_for(I915_READ(DISPLAY_PHY_STATUS) & PHY_POWERGOOD(phy), 1)) DRM_ERROR("Display PHY %d is not power up\n", phy); + mutex_lock(&dev_priv->sb_lock); + + /* Enable dynamic power down */ + tmp = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW28); + tmp |= DPIO_DYNPWRDOWNEN_CH0 | DPIO_CL1POWERDOWNEN; + vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW28, tmp); + + if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) { + tmp = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW6_CH1); + tmp |= DPIO_DYNPWRDOWNEN_CH1; + vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW6_CH1, tmp); + } + + mutex_unlock(&dev_priv->sb_lock); + dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(phy); I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control); + + DRM_DEBUG_KMS("Enabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n", + phy, dev_priv->chv_phy_control); } static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, @@ -1004,6 +1027,35 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control); vlv_set_power_well(dev_priv, power_well, false); + + DRM_DEBUG_KMS("Disabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n", + phy, dev_priv->chv_phy_control); +} + +void chv_phy_powergate_lanes(struct intel_encoder *encoder, + bool override, unsigned int mask) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct i915_power_domains *power_domains = &dev_priv->power_domains; + enum dpio_phy phy = vlv_dport_to_phy(enc_to_dig_port(&encoder->base)); + enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base)); + + mutex_lock(&power_domains->lock); + + dev_priv->chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD(0xf, phy, ch); + dev_priv->chv_phy_control |= PHY_CH_POWER_DOWN_OVRD(mask, phy, ch); + + if (override) + dev_priv->chv_phy_control |= PHY_CH_POWER_DOWN_OVRD_EN(phy, ch); + else + dev_priv->chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD_EN(phy, ch); + + I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control); + + DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d lanes 0x%x (PHY_CONTROL=0x%08x)\n", + phy, ch, mask, dev_priv->chv_phy_control); + + mutex_unlock(&power_domains->lock); } static bool chv_pipe_power_well_enabled(struct drm_i915_private *dev_priv, @@ -1630,19 +1682,72 @@ static void chv_phy_control_init(struct drm_i915_private *dev_priv) * DISPLAY_PHY_CONTROL can get corrupted if read. As a * workaround never ever read DISPLAY_PHY_CONTROL, and * instead maintain a shadow copy ourselves. Use the actual - * power well state to reconstruct the expected initial - * value. + * power well state and lane status to reconstruct the + * expected initial value. */ dev_priv->chv_phy_control = PHY_LDO_SEQ_DELAY(PHY_LDO_DELAY_600NS, DPIO_PHY0) | PHY_LDO_SEQ_DELAY(PHY_LDO_DELAY_600NS, DPIO_PHY1) | - PHY_CH_POWER_MODE(PHY_CH_SU_PSR, DPIO_PHY0, DPIO_CH0) | - PHY_CH_POWER_MODE(PHY_CH_SU_PSR, DPIO_PHY0, DPIO_CH1) | - PHY_CH_POWER_MODE(PHY_CH_SU_PSR, DPIO_PHY1, DPIO_CH0); - if (cmn_bc->ops->is_enabled(dev_priv, cmn_bc)) + PHY_CH_POWER_MODE(PHY_CH_DEEP_PSR, DPIO_PHY0, DPIO_CH0) | + PHY_CH_POWER_MODE(PHY_CH_DEEP_PSR, DPIO_PHY0, DPIO_CH1) | + PHY_CH_POWER_MODE(PHY_CH_DEEP_PSR, DPIO_PHY1, DPIO_CH0); + + /* + * If all lanes are disabled we leave the override disabled + * with all power down bits cleared to match the state we + * would use after disabling the port. Otherwise enable the + * override and set the lane powerdown bits accding to the + * current lane status. + */ + if (cmn_bc->ops->is_enabled(dev_priv, cmn_bc)) { + uint32_t status = I915_READ(DPLL(PIPE_A)); + unsigned int mask; + + mask = status & DPLL_PORTB_READY_MASK; + if (mask == 0xf) + mask = 0x0; + else + dev_priv->chv_phy_control |= + PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH0); + + dev_priv->chv_phy_control |= + PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY0, DPIO_CH0); + + mask = (status & DPLL_PORTC_READY_MASK) >> 4; + if (mask == 0xf) + mask = 0x0; + else + dev_priv->chv_phy_control |= + PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH1); + + dev_priv->chv_phy_control |= + PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY0, DPIO_CH1); + dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(DPIO_PHY0); - if (cmn_d->ops->is_enabled(dev_priv, cmn_d)) + } + + if (cmn_d->ops->is_enabled(dev_priv, cmn_d)) { + uint32_t status = I915_READ(DPIO_PHY_STATUS); + unsigned int mask; + + mask = status & DPLL_PORTD_READY_MASK; + + if (mask == 0xf) + mask = 0x0; + else + dev_priv->chv_phy_control |= + PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY1, DPIO_CH0); + + dev_priv->chv_phy_control |= + PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY1, DPIO_CH0); + dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(DPIO_PHY1); + } + + I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control); + + DRM_DEBUG_KMS("Initial PHY_CONTROL=0x%08x\n", + dev_priv->chv_phy_control); } static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv) -- cgit v0.10.2 From b0b3384612bd4ce608c5d95626149311bb43f121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 8 Jul 2015 23:45:55 +0300 Subject: drm/i915: Trick CL2 into life on CHV when using pipe B with port B MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Normmally the common lane in a PHY channel gets powered up when some of the data lanes get powered up. But when we're driving port B with pipe B we don't want to enabled any of the data lanes, and just want the DPLL in the common lane to be active. To make that happens we have to temporarily enable some data lanes after which we can access the DPLL registers in the common lane. Once the pipe is up and running we can drop the power override on the data lanes allowing them to shut down. From this point forward the common lane will in fact stay powered on until the data lanes in the other channel get powered down. Ville's extended explanation from the review thread: On Wed, Aug 19, 2015 at 07:47:41AM +0530, Deepak wrote: > One Q, why only for port B? Port C is also in same common lane right? Port B is in the first PHY channel which also houses CL1. CL1 always powers up whenever any lanes in either PHY channel are powered up. CL2 only powers up if lanes in the second channel (ie. the one with port C) powers up. So in this scenario (pipe B->port B) we want the DPLL from CL2, but ideally we only want to power up the lanes for port B. Powering up port B lanes will only power up CL1, but as we need CL2 instead we need to, temporarily, power up some lanes in port C as well. Crossing the streams the other way (pipe A->port C) is not a problem since CL1 powers up whenever anything else powers up. So powering up some port C lanes is enough on its own to make the CL1 DPLL operational, even though CL1 and the lanes live in separate channels. Signed-off-by: Ville Syrjälä Reviewed-by: Deepak S [danvet: Amend commit message with extended explanation.] Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index c0eaf13..b032eef 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2902,6 +2902,12 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder) mutex_unlock(&dev_priv->sb_lock); intel_enable_dp(encoder); + + /* Second common lane will stay alive on its own now */ + if (dport->release_cl2_override) { + chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, false); + dport->release_cl2_override = false; + } } static void chv_dp_pre_pll_enable(struct intel_encoder *encoder) @@ -2919,6 +2925,14 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder) intel_dp_prepare(encoder); + /* + * Must trick the second common lane into life. + * Otherwise we can't even access the PLL. + */ + if (ch == DPIO_CH0 && pipe == PIPE_B) + dport->release_cl2_override = + !chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, true); + chv_phy_powergate_lanes(encoder, true, lane_mask); mutex_lock(&dev_priv->sb_lock); @@ -2997,6 +3011,15 @@ static void chv_dp_post_pll_disable(struct intel_encoder *encoder) mutex_unlock(&dev_priv->sb_lock); + /* + * Leave the power down bit cleared for at least one + * lane so that chv_powergate_phy_ch() will power + * on something when the channel is otherwise unused. + * When the port is off and the override is removed + * the lanes power down anyway, so otherwise it doesn't + * really matter what the state of power down bits is + * after this. + */ chv_phy_powergate_lanes(encoder, false, 0x0); } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index df420d8..72c1181 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -779,6 +779,7 @@ struct intel_digital_port { struct intel_dp dp; struct intel_hdmi hdmi; enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool); + bool release_cl2_override; }; struct intel_dp_mst_encoder { @@ -1363,6 +1364,8 @@ void intel_display_set_init_power(struct drm_i915_private *dev, bool enable); void chv_phy_powergate_lanes(struct intel_encoder *encoder, bool override, unsigned int mask); +bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy, + enum dpio_channel ch, bool override); /* intel_pm.c */ diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index f1ecc2c..7c56053 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1628,6 +1628,14 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder) intel_hdmi_prepare(encoder); + /* + * Must trick the second common lane into life. + * Otherwise we can't even access the PLL. + */ + if (ch == DPIO_CH0 && pipe == PIPE_B) + dport->release_cl2_override = + !chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, true); + chv_phy_powergate_lanes(encoder, true, 0x0); mutex_lock(&dev_priv->sb_lock); @@ -1704,6 +1712,15 @@ static void chv_hdmi_post_pll_disable(struct intel_encoder *encoder) mutex_unlock(&dev_priv->sb_lock); + /* + * Leave the power down bit cleared for at least one + * lane so that chv_powergate_phy_ch() will power + * on something when the channel is otherwise unused. + * When the port is off and the override is removed + * the lanes power down anyway, so otherwise it doesn't + * really matter what the state of power down bits is + * after this. + */ chv_phy_powergate_lanes(encoder, false, 0x0); } @@ -1925,6 +1942,12 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder) g4x_enable_hdmi(encoder); vlv_wait_port_ready(dev_priv, dport, 0x0); + + /* Second common lane will stay alive on its own now */ + if (dport->release_cl2_override) { + chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, false); + dport->release_cl2_override = false; + } } static void intel_hdmi_destroy(struct drm_connector *connector) diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index a159771..4a43885 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -1032,6 +1032,35 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, phy, dev_priv->chv_phy_control); } +bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy, + enum dpio_channel ch, bool override) +{ + struct i915_power_domains *power_domains = &dev_priv->power_domains; + bool was_override; + + mutex_lock(&power_domains->lock); + + was_override = dev_priv->chv_phy_control & PHY_CH_POWER_DOWN_OVRD_EN(phy, ch); + + if (override == was_override) + goto out; + + if (override) + dev_priv->chv_phy_control |= PHY_CH_POWER_DOWN_OVRD_EN(phy, ch); + else + dev_priv->chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD_EN(phy, ch); + + I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control); + + DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d (DPIO_PHY_CONTROL=0x%08x)\n", + phy, ch, dev_priv->chv_phy_control); + +out: + mutex_unlock(&power_domains->lock); + + return was_override; +} + void chv_phy_powergate_lanes(struct intel_encoder *encoder, bool override, unsigned int mask) { -- cgit v0.10.2 From 0047eedc48869f8c7797dd10f0cf976ac34c1d33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 10 Jul 2015 10:56:24 +0300 Subject: drm/i915: Force common lane on for the PPS kick on CHV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With DPIO powergating active the DPLL can't be accessed unless something else is keeping the common lane in the channel on. That means the PPS kick procedure could fail to enable the PLL. Power up some data lanes to force the common lane to power up so that the PLL can be enabled temporarily. v2: Avoid gcc uninitilized variable warning Signed-off-by: Ville Syrjälä Reviewed-by: Deepak S Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index b032eef..ea11469 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -341,7 +341,9 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; enum pipe pipe = intel_dp->pps_pipe; - bool pll_enabled; + bool pll_enabled, release_cl_override = false; + enum dpio_phy phy = DPIO_PHY(pipe); + enum dpio_channel ch = vlv_pipe_to_channel(pipe); uint32_t DP; if (WARN(I915_READ(intel_dp->output_reg) & DP_PORT_EN, @@ -371,9 +373,13 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) * The DPLL for the pipe must be enabled for this to work. * So enable temporarily it if it's not already enabled. */ - if (!pll_enabled) + if (!pll_enabled) { + release_cl_override = IS_CHERRYVIEW(dev) && + !chv_phy_powergate_ch(dev_priv, phy, ch, true); + vlv_force_pll_on(dev, pipe, IS_CHERRYVIEW(dev) ? &chv_dpll[0].dpll : &vlv_dpll[0].dpll); + } /* * Similar magic as in intel_dp_enable_port(). @@ -390,8 +396,12 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN); POSTING_READ(intel_dp->output_reg); - if (!pll_enabled) + if (!pll_enabled) { vlv_force_pll_off(dev, pipe); + + if (release_cl_override) + chv_phy_powergate_ch(dev_priv, phy, ch, false); + } } static enum pipe -- cgit v0.10.2 From ee27921824e6ad0ca2d8e5abfa12cf4d853ded6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 8 Jul 2015 23:45:57 +0300 Subject: drm/i915: Enable DPIO SUS clock gating on CHV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CHV has supports some form of automagic clock gating for the DPIO SUS clock. We can simply enable the magic bits and the hardware should take care of the rest. Signed-off-by: Ville Syrjälä Reviewed-by: Deepak S Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 6918ffa..6ed7141 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1143,6 +1143,10 @@ enum skl_disp_power_wells { #define CHV_CMN_DW28 0x8170 #define DPIO_CL1POWERDOWNEN (1 << 23) #define DPIO_DYNPWRDOWNEN_CH0 (1 << 22) +#define DPIO_SUS_CLK_CONFIG_ON (0 << 0) +#define DPIO_SUS_CLK_CONFIG_CLKREQ (1 << 0) +#define DPIO_SUS_CLK_CONFIG_GATE (2 << 0) +#define DPIO_SUS_CLK_CONFIG_GATE_CLKREQ (3 << 0) #define CHV_CMN_DW30 0x8178 #define DPIO_LRC_BYPASS (1 << 3) diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 4a43885..ef043b2 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -988,7 +988,8 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, /* Enable dynamic power down */ tmp = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW28); - tmp |= DPIO_DYNPWRDOWNEN_CH0 | DPIO_CL1POWERDOWNEN; + tmp |= DPIO_DYNPWRDOWNEN_CH0 | DPIO_CL1POWERDOWNEN | + DPIO_SUS_CLK_CONFIG_GATE_CLKREQ; vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW28, tmp); if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) { -- cgit v0.10.2 From 3e28878635cc3bb3159445dc9cfbdc3d34eb8daf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 8 Jul 2015 23:45:58 +0300 Subject: drm/i915: Force CL2 off in CHV x1 PHY MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can choose to leave the display PHY CL2 powerdown up to some hardware signals, or we can force it. The BXT code forces the nonexistent CL2 in the x1 PHY to power down. Follow suit on CHV. Maybe it can still save some extra power by disabling some extra logic in CL1, or something. Signed-off-by: Ville Syrjälä Reviewed-by: Deepak S Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 6ed7141..439bb27 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1149,6 +1149,7 @@ enum skl_disp_power_wells { #define DPIO_SUS_CLK_CONFIG_GATE_CLKREQ (3 << 0) #define CHV_CMN_DW30 0x8178 +#define DPIO_CL2_LDOFUSE_PWRENB (1 << 6) #define DPIO_LRC_BYPASS (1 << 3) #define _TXLANE(ch, lane, offset) ((ch ? 0x2400 : 0) + \ diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index ef043b2..a0df156 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -996,6 +996,15 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, tmp = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW6_CH1); tmp |= DPIO_DYNPWRDOWNEN_CH1; vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW6_CH1, tmp); + } else { + /* + * Force the non-existing CL2 off. BXT does this + * too, so maybe it saves some power even though + * CL2 doesn't exist? + */ + tmp = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW30); + tmp |= DPIO_CL2_LDOFUSE_PWRENB; + vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW30, tmp); } mutex_unlock(&dev_priv->sb_lock); -- cgit v0.10.2 From 6c908bf43df417b10917c3a463d3bd413eb476fd Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 25 Aug 2015 19:03:41 -0300 Subject: drm/i915: gen 9 can check for unclaimed registers too Dear git bisect user, Even though this is the patch that introduced the WARN() you're bisecting, please notice that it's very likely that the problem you're facing was already present before this commit. In other words: this commit adds code to detect errors and give WARN()s about them, but the errors were already there. In order to continue your debug, please use the i915.mmio_debug option, check the backtraces and try to discover which read or write operation is causing the error message. Then check if this is happening because the register does not exist or because its power well is down when the operation is being done. On my SKL machine, if I use i915.mmio_debug=999, this patch triggers 42 WARNs just by booting. I didn't investigate them yet. Normal users are only going to get a single WARN due to the default i915.mmio_debug setting. Thank you for your comprehension, Paulo Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 1d88745..6e03e11 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -362,6 +362,7 @@ static const struct intel_device_info intel_skylake_info = { .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, .has_llc = 1, .has_ddi = 1, + .has_fpga_dbg = 1, .has_fbc = 1, GEN_DEFAULT_PIPEOFFSETS, IVB_CURSOR_OFFSETS, @@ -374,6 +375,7 @@ static const struct intel_device_info intel_skylake_gt3_info = { .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, .has_llc = 1, .has_ddi = 1, + .has_fpga_dbg = 1, .has_fbc = 1, GEN_DEFAULT_PIPEOFFSETS, IVB_CURSOR_OFFSETS, @@ -386,6 +388,7 @@ static const struct intel_device_info intel_broxton_info = { .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, .num_pipes = 3, .has_ddi = 1, + .has_fpga_dbg = 1, .has_fbc = 1, GEN_DEFAULT_PIPEOFFSETS, IVB_CURSOR_OFFSETS, diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index ad4e421..dec20d6 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -769,6 +769,7 @@ static u##x \ gen9_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ enum forcewake_domains fw_engine; \ GEN6_READ_HEADER(x); \ + hsw_unclaimed_reg_debug(dev_priv, reg, true, true); \ if (!SKL_NEEDS_FORCE_WAKE((dev_priv), (reg))) \ fw_engine = 0; \ else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg)) \ @@ -782,6 +783,7 @@ gen9_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ if (fw_engine) \ __force_wake_get(dev_priv, fw_engine); \ val = __raw_i915_read##x(dev_priv, reg); \ + hsw_unclaimed_reg_debug(dev_priv, reg, true, false); \ GEN6_READ_FOOTER; \ } @@ -982,6 +984,7 @@ gen9_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, \ bool trace) { \ enum forcewake_domains fw_engine; \ GEN6_WRITE_HEADER; \ + hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \ if (!SKL_NEEDS_FORCE_WAKE((dev_priv), (reg)) || \ is_gen9_shadowed(dev_priv, reg)) \ fw_engine = 0; \ @@ -996,6 +999,8 @@ gen9_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, \ if (fw_engine) \ __force_wake_get(dev_priv, fw_engine); \ __raw_i915_write##x(dev_priv, reg, val); \ + hsw_unclaimed_reg_debug(dev_priv, reg, false, false); \ + hsw_unclaimed_reg_detect(dev_priv); \ GEN6_WRITE_FOOTER; \ } -- cgit v0.10.2 From c5b852f33e7844f4664794a3b3c738d07b09ce0a Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 26 Aug 2015 09:29:56 +0200 Subject: Partially revert "drm/i915: Use full atomic modeset." This partially reverts commit 74c090b1bdc57b1c9f1361908cca5a3d8a80fb08. The DRIVER_ATOMIC cap cannot yet be exported because i915 lacks async support. Signed-off-by: Maarten Lankhorst Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 6e03e11..ce3bd0c 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1726,7 +1726,7 @@ static int __init i915_init(void) * to the atomic ioctl and the atomic properties. Only plane operations on * a single CRTC will actually work. */ - if (driver.driver_features & DRIVER_MODESET) + if (i915.nuclear_pageflip) driver.driver_features |= DRIVER_ATOMIC; return drm_pci_init(&driver, &i915_pci_driver); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 705f208..7cd1555 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2640,6 +2640,7 @@ struct i915_params { int use_mmio_flip; int mmio_debug; bool verbose_state_checks; + bool nuclear_pageflip; int edp_vswing; }; extern struct i915_params i915 __read_mostly; diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 5ae4b0a..05053e2 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -51,6 +51,7 @@ struct i915_params i915 __read_mostly = { .use_mmio_flip = 0, .mmio_debug = 0, .verbose_state_checks = 1, + .nuclear_pageflip = 0, .edp_vswing = 0, .enable_guc_submission = false, .guc_log_level = -1, @@ -177,6 +178,10 @@ module_param_named(verbose_state_checks, i915.verbose_state_checks, bool, 0600); MODULE_PARM_DESC(verbose_state_checks, "Enable verbose logs (ie. WARN_ON()) in case of unexpected hw state conditions."); +module_param_named_unsafe(nuclear_pageflip, i915.nuclear_pageflip, bool, 0600); +MODULE_PARM_DESC(nuclear_pageflip, + "Force atomic modeset functionality; asynchronous mode is not yet supported. (default: false)."); + /* WA to get away with the default setting in VBT for early platforms.Will be removed */ module_param_named_unsafe(edp_vswing, i915.edp_vswing, int, 0400); MODULE_PARM_DESC(edp_vswing, -- cgit v0.10.2 From 01302d4d17ed524e7d855f5fbbac5822f14f9c5e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 28 Aug 2015 18:05:26 +0200 Subject: drm/i915: Update DRIVER_DATE to 20150828 Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7cd1555..e1bbe46 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -57,7 +57,7 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20150731" +#define DRIVER_DATE "20150828" #undef WARN_ON /* Many gcc seem to no see through this and fall over :( */ -- cgit v0.10.2 From 7cc53cf01e61bd1a774d2ba492bbe3e93e58ca79 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 26 Aug 2015 14:33:31 +0300 Subject: drm/dp: add drm_dp_tps3_supported helper Cc: Thierry Reding Signed-off-by: Jani Nikula Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 94898f6..6aa59b9 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -633,6 +633,13 @@ drm_dp_enhanced_frame_cap(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) (dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP); } +static inline bool +drm_dp_tps3_supported(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) +{ + return dpcd[DP_DPCD_REV] >= 0x12 && + dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED; +} + /* * DisplayPort AUX channel */ -- cgit v0.10.2 From caa860d919865ade32e029631bd0d531eead9212 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 27 Aug 2015 13:25:37 +0300 Subject: drm/i915/dp: use the drm dp helper for determining sink tps3 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No functional changes. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä [danvet: s/intel_dp_tps/drm_dp_tps/.] Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index ea11469..b794439 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4023,8 +4023,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) } /* Training Pattern 3 support, both source and sink */ - if (intel_dp->dpcd[DP_DPCD_REV] >= 0x12 && - intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED && + if (drm_dp_tps3_supported(intel_dp->dpcd) && (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8)) { intel_dp->use_tps3 = true; DRM_DEBUG_KMS("Displayport TPS3 supported\n"); -- cgit v0.10.2 From 2bbe6bbb0dc94fd4ce287bdac9e1bd184e23057b Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Mon, 15 Jun 2015 14:03:29 +0300 Subject: drm/i915: Bump command parser version number. This was forgotten in commit d351f6d94893f3ba98b1b20c5ef44c35fc1da124 Author: Francisco Jerez Date: Fri May 29 16:44:15 2015 +0300 drm/i915: Add SCRATCH1 and ROW_CHICKEN3 to the register whitelist. Signed-off-by: Francisco Jerez Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 3977bf3..ad7d7ab 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -1213,6 +1213,7 @@ int i915_cmd_parser_get_version(void) * 2. Allow access to the MI_PREDICATE_SRC0 and * MI_PREDICATE_SRC1 registers. * 3. Allow access to the GPGPU_THREADS_DISPATCHED register. + * 4. L3 atomic chicken bits of HSW_SCRATCH1 and HSW_ROW_CHICKEN3. */ - return 3; + return 4; } -- cgit v0.10.2 From a8f327fb8464875e5b764008a1c50dbc0b384c17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 9 Jul 2015 20:14:11 +0300 Subject: drm/i915: Clean up CHV lane soft reset programming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we release the lane soft reset before lane stagger settings have been programmed. I believe that means we don't actually do lane staggering. So move the soft reset deassert to happen after lane staggering has been programmed. The one confusing thing in this is that when we remove the power down override from the lanes, they power up with defaul register values, which do not have the soft reset overrides enabled. And according to some docs by default the data lane resets are tied to cmnreset. So that would mean that lanes would come out of reset without staggering as soon as the power down overrides are removed. But since we can't access either the lane stagger register nor the soft reset override registers until the lanes are powered on, we can't really do anything about it. So let's just set the soft reset overrides as soon as the lane is powered on and hope for the best. v2: Fix typos in commit message (Daniel) Signed-off-by: Ville Syrjälä Reviewed-by: Deepak S Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index b794439..3a9c43d 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2426,42 +2426,62 @@ static void vlv_post_disable_dp(struct intel_encoder *encoder) intel_dp_link_down(intel_dp); } -static void chv_post_disable_dp(struct intel_encoder *encoder) +static void chv_data_lane_soft_reset(struct intel_encoder *encoder, + bool reset) { - struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); - struct intel_digital_port *dport = dp_to_dig_port(intel_dp); - struct drm_device *dev = encoder->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = - to_intel_crtc(encoder->base.crtc); - enum dpio_channel ch = vlv_dport_to_channel(dport); - enum pipe pipe = intel_crtc->pipe; - u32 val; + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base)); + struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); + enum pipe pipe = crtc->pipe; + uint32_t val; - intel_dp_link_down(intel_dp); + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch)); + if (reset) + val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); + else + val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET; + vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val); - mutex_lock(&dev_priv->sb_lock); + if (crtc->config->lane_count > 2) { + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch)); + if (reset) + val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); + else + val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET; + vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val); + } - /* Propagate soft reset to data lane reset */ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch)); val |= CHV_PCS_REQ_SOFTRESET_EN; + if (reset) + val &= ~DPIO_PCS_CLK_SOFT_RESET; + else + val |= DPIO_PCS_CLK_SOFT_RESET; vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val); - if (intel_crtc->config->lane_count > 2) { + if (crtc->config->lane_count > 2) { val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch)); val |= CHV_PCS_REQ_SOFTRESET_EN; + if (reset) + val &= ~DPIO_PCS_CLK_SOFT_RESET; + else + val |= DPIO_PCS_CLK_SOFT_RESET; vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val); } +} - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch)); - val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val); +static void chv_post_disable_dp(struct intel_encoder *encoder) +{ + struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); + struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; - if (intel_crtc->config->lane_count > 2) { - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch)); - val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val); - } + intel_dp_link_down(intel_dp); + + mutex_lock(&dev_priv->sb_lock); + + /* Assert data lane reset */ + chv_data_lane_soft_reset(encoder, true); mutex_unlock(&dev_priv->sb_lock); } @@ -2839,27 +2859,6 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder) vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val); } - /* Deassert soft data lane reset*/ - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch)); - val |= CHV_PCS_REQ_SOFTRESET_EN; - vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val); - - if (intel_crtc->config->lane_count > 2) { - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch)); - val |= CHV_PCS_REQ_SOFTRESET_EN; - vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val); - } - - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch)); - val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val); - - if (intel_crtc->config->lane_count > 2) { - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch)); - val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val); - } - /* Program Tx lane latency optimal setting*/ for (i = 0; i < intel_crtc->config->lane_count; i++) { /* Set the upar bit */ @@ -2909,6 +2908,9 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder) DPIO_TX2_STAGGER_MULT(5)); } + /* Deassert data lane reset */ + chv_data_lane_soft_reset(encoder, false); + mutex_unlock(&dev_priv->sb_lock); intel_enable_dp(encoder); @@ -2947,6 +2949,9 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder) mutex_lock(&dev_priv->sb_lock); + /* Assert data lane reset */ + chv_data_lane_soft_reset(encoder, true); + /* program left/right clock distribution */ if (pipe != PIPE_B) { val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0); diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 7c56053..4da737c 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1615,6 +1615,50 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder) mutex_unlock(&dev_priv->sb_lock); } +static void chv_data_lane_soft_reset(struct intel_encoder *encoder, + bool reset) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base)); + struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); + enum pipe pipe = crtc->pipe; + uint32_t val; + + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch)); + if (reset) + val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); + else + val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET; + vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val); + + if (crtc->config->lane_count > 2) { + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch)); + if (reset) + val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); + else + val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET; + vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val); + } + + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch)); + val |= CHV_PCS_REQ_SOFTRESET_EN; + if (reset) + val &= ~DPIO_PCS_CLK_SOFT_RESET; + else + val |= DPIO_PCS_CLK_SOFT_RESET; + vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val); + + if (crtc->config->lane_count > 2) { + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch)); + val |= CHV_PCS_REQ_SOFTRESET_EN; + if (reset) + val &= ~DPIO_PCS_CLK_SOFT_RESET; + else + val |= DPIO_PCS_CLK_SOFT_RESET; + vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val); + } +} + static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder) { struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); @@ -1640,6 +1684,9 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder) mutex_lock(&dev_priv->sb_lock); + /* Assert data lane reset */ + chv_data_lane_soft_reset(encoder, true); + /* program left/right clock distribution */ if (pipe != PIPE_B) { val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0); @@ -1742,33 +1789,13 @@ static void vlv_hdmi_post_disable(struct intel_encoder *encoder) static void chv_hdmi_post_disable(struct intel_encoder *encoder) { - struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = - to_intel_crtc(encoder->base.crtc); - enum dpio_channel ch = vlv_dport_to_channel(dport); - enum pipe pipe = intel_crtc->pipe; - u32 val; mutex_lock(&dev_priv->sb_lock); - /* Propagate soft reset to data lane reset */ - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch)); - val |= CHV_PCS_REQ_SOFTRESET_EN; - vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val); - - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch)); - val |= CHV_PCS_REQ_SOFTRESET_EN; - vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val); - - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch)); - val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val); - - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch)); - val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val); + /* Assert data lane reset */ + chv_data_lane_soft_reset(encoder, true); mutex_unlock(&dev_priv->sb_lock); } @@ -1799,23 +1826,6 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder) val &= ~DPIO_LANEDESKEW_STRAP_OVRD; vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val); - /* Deassert soft data lane reset*/ - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch)); - val |= CHV_PCS_REQ_SOFTRESET_EN; - vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val); - - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch)); - val |= CHV_PCS_REQ_SOFTRESET_EN; - vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val); - - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch)); - val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val); - - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch)); - val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val); - /* Program Tx latency optimal setting */ for (i = 0; i < 4; i++) { /* Set the upar bit */ @@ -1858,6 +1868,9 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder) DPIO_TX1_STAGGER_MULT(7) | DPIO_TX2_STAGGER_MULT(5)); + /* Deassert data lane reset */ + chv_data_lane_soft_reset(encoder, false); + /* Clear calc init */ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch)); val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3); -- cgit v0.10.2 From 6669e39f95b5530ca8cb9137703ceb5e83e5d648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 8 Jul 2015 23:46:00 +0300 Subject: drm/i915: Add some CHV DPIO lane power state asserts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add some checks that the state of the DPIO lanes is more or less what we expect based on the overrides. The hardware only provides two bits per channel indicating whether all or some of the lanes are powered down, so we can't do an exact check. Additionally, CL2 powering down before we can check it adds another twist. To work around this we simply check for the 0 value of the CL2 register (which is what we get when it's powered down) and adjust our expectations. Signed-off-by: Ville Syrjälä Reviewed-by: Deepak S Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 439bb27..8a18023 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1099,6 +1099,12 @@ enum skl_disp_power_wells { #define DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE 1 /* 1: coarse & 0 : fine */ #define CHV_PLL_DW9(ch) _PIPE(ch, _CHV_PLL_DW9_CH0, _CHV_PLL_DW9_CH1) +#define _CHV_CMN_DW0_CH0 0x8100 +#define DPIO_ALLDL_POWERDOWN_SHIFT_CH0 19 +#define DPIO_ANYDL_POWERDOWN_SHIFT_CH0 18 +#define DPIO_ALLDL_POWERDOWN (1 << 1) +#define DPIO_ANYDL_POWERDOWN (1 << 0) + #define _CHV_CMN_DW5_CH0 0x8114 #define CHV_BUFRIGHTENA1_DISABLE (0 << 20) #define CHV_BUFRIGHTENA1_NORMAL (1 << 20) @@ -1135,6 +1141,8 @@ enum skl_disp_power_wells { #define _CHV_CMN_DW19_CH0 0x814c #define _CHV_CMN_DW6_CH1 0x8098 +#define DPIO_ALLDL_POWERDOWN_SHIFT_CH1 30 /* CL2 DW6 only */ +#define DPIO_ANYDL_POWERDOWN_SHIFT_CH1 29 /* CL2 DW6 only */ #define DPIO_DYNPWRDOWNEN_CH1 (1 << 28) /* CL2 DW6 only */ #define CHV_CMN_USEDCLKCHANNEL (1 << 13) diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index a0df156..7991eff 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -1042,6 +1042,58 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, phy, dev_priv->chv_phy_control); } +static void assert_chv_phy_powergate(struct drm_i915_private *dev_priv, enum dpio_phy phy, + enum dpio_channel ch, bool override, unsigned int mask) +{ + enum pipe pipe = phy == DPIO_PHY0 ? PIPE_A : PIPE_C; + u32 reg, val, expected, actual; + + if (ch == DPIO_CH0) + reg = _CHV_CMN_DW0_CH0; + else + reg = _CHV_CMN_DW6_CH1; + + mutex_lock(&dev_priv->sb_lock); + val = vlv_dpio_read(dev_priv, pipe, reg); + mutex_unlock(&dev_priv->sb_lock); + + /* + * This assumes !override is only used when the port is disabled. + * All lanes should power down even without the override when + * the port is disabled. + */ + if (!override || mask == 0xf) { + expected = DPIO_ALLDL_POWERDOWN | DPIO_ANYDL_POWERDOWN; + /* + * If CH1 common lane is not active anymore + * (eg. for pipe B DPLL) the entire channel will + * shut down, which causes the common lane registers + * to read as 0. That means we can't actually check + * the lane power down status bits, but as the entire + * register reads as 0 it's a good indication that the + * channel is indeed entirely powered down. + */ + if (ch == DPIO_CH1 && val == 0) + expected = 0; + } else if (mask != 0x0) { + expected = DPIO_ANYDL_POWERDOWN; + } else { + expected = 0; + } + + if (ch == DPIO_CH0) + actual = val >> DPIO_ANYDL_POWERDOWN_SHIFT_CH0; + else + actual = val >> DPIO_ANYDL_POWERDOWN_SHIFT_CH1; + actual &= DPIO_ALLDL_POWERDOWN | DPIO_ANYDL_POWERDOWN; + + WARN(actual != expected, + "Unexpected DPIO lane power down: all %d, any %d. Expected: all %d, any %d. (0x%x = 0x%08x)\n", + !!(actual & DPIO_ALLDL_POWERDOWN), !!(actual & DPIO_ANYDL_POWERDOWN), + !!(expected & DPIO_ALLDL_POWERDOWN), !!(expected & DPIO_ANYDL_POWERDOWN), + reg, val); +} + bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy, enum dpio_channel ch, bool override) { @@ -1094,6 +1146,8 @@ void chv_phy_powergate_lanes(struct intel_encoder *encoder, DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d lanes 0x%x (PHY_CONTROL=0x%08x)\n", phy, ch, mask, dev_priv->chv_phy_control); + assert_chv_phy_powergate(dev_priv, phy, ch, override, mask); + mutex_unlock(&power_domains->lock); } -- cgit v0.10.2 From 30142273a3e83936fd7b45aa5339311a9295ca51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 8 Jul 2015 23:46:01 +0300 Subject: drm/i915: Add CHV PHY LDO power sanity checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At various points when changing the DPIO lane/phy power states, construct an expected value of the DISPLAY_PHY_STATUS register and compare it with the real thing. To construct the expected value we look at our shadow PHY_CONTROL register value (which should match what we've just written to the hardware), and we also need to look at the actual state of the cmn power wells as a disabled power well causes the relevant LDO status to be reported as 'on' in DISPLAY_PHY_STATUS. When initially powering up the PHY it performs various internal calibrations for which it fully powers up. That means that if we check for the expetected power state immediately upon releasing cmnreset we would get the occasional false positive. But we can of course poll until the expected value appears. It shouldn't be too long so this shouldn't make modesets substantially longer. One extra complication is introduced when we cross the streams, ie. drive port B with pipe B. In this case we trick CL2 (where the DPLL lives) into life by temporaily powering up the lanes in the second channel, and once the pipe is up and runnign we release the lane power override. At that point the power state of CL2 has somehow gotten entangled with the power state of the first channel. That means that constructing the expected DISPLAY_PHY_STATUS value is a bit tricky since based on the lane power states in the second channel, CL2 should also be powered down. But we can use the DPLL enable bit to determine when CL2 should be alive even if the lanes are powered down. However the power state of CL2 isn't actually tied in with the DPLL state, but to the state of the lanes in first channel, so we have to avoid checking the expected state between shutting down the DPLL and powering down the lanes in the first channel. So no calling assert_chv_phy_status() before the DISPLAY_PHY_CONTROL write in chv_phy_powergate_lanes(), but after the write is a safe time to check. Signed-off-by: Ville Syrjälä Reviewed-by: Deepak S Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 8a18023..c82db2a 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2223,6 +2223,8 @@ enum skl_disp_power_wells { #define PHY_COM_LANE_RESET_DEASSERT(phy) (1 << (phy)) #define DISPLAY_PHY_STATUS (VLV_DISPLAY_BASE + 0x60104) #define PHY_POWERGOOD(phy) (((phy) == DPIO_PHY0) ? (1<<31) : (1<<30)) +#define PHY_STATUS_CMN_LDO(phy, ch) (1 << (6-(6*(phy)+3*(ch)))) +#define PHY_STATUS_SPLINE_LDO(phy, ch, spline) (1 << (8-(6*(phy)+3*(ch)+(spline)))) /* * The i830 generation, in LVDS mode, defines P1 as the bit number set within diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 7991eff..b1bd25e 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -958,6 +958,107 @@ static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, vlv_set_power_well(dev_priv, power_well, false); } +#define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1) + +static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv, + int power_well_id) +{ + struct i915_power_domains *power_domains = &dev_priv->power_domains; + struct i915_power_well *power_well; + int i; + + for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) { + if (power_well->data == power_well_id) + return power_well; + } + + return NULL; +} + +#define BITS_SET(val, bits) (((val) & (bits)) == (bits)) + +static void assert_chv_phy_status(struct drm_i915_private *dev_priv) +{ + struct i915_power_well *cmn_bc = + lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC); + struct i915_power_well *cmn_d = + lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_D); + u32 phy_control = dev_priv->chv_phy_control; + u32 phy_status = 0; + u32 tmp; + + if (cmn_bc->ops->is_enabled(dev_priv, cmn_bc)) { + phy_status |= PHY_POWERGOOD(DPIO_PHY0); + + /* this assumes override is only used to enable lanes */ + if ((phy_control & PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH0)) == 0) + phy_control |= PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH0); + + if ((phy_control & PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH1)) == 0) + phy_control |= PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH1); + + /* CL1 is on whenever anything is on in either channel */ + if (BITS_SET(phy_control, + PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH0) | + PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH1))) + phy_status |= PHY_STATUS_CMN_LDO(DPIO_PHY0, DPIO_CH0); + + /* + * The DPLLB check accounts for the pipe B + port A usage + * with CL2 powered up but all the lanes in the second channel + * powered down. + */ + if (BITS_SET(phy_control, + PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH1)) && + (I915_READ(DPLL(PIPE_B)) & DPLL_VCO_ENABLE) == 0) + phy_status |= PHY_STATUS_CMN_LDO(DPIO_PHY0, DPIO_CH1); + + if (BITS_SET(phy_control, + PHY_CH_POWER_DOWN_OVRD(0x3, DPIO_PHY0, DPIO_CH0))) + phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH0, 0); + if (BITS_SET(phy_control, + PHY_CH_POWER_DOWN_OVRD(0xc, DPIO_PHY0, DPIO_CH0))) + phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH0, 1); + + if (BITS_SET(phy_control, + PHY_CH_POWER_DOWN_OVRD(0x3, DPIO_PHY0, DPIO_CH1))) + phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 0); + if (BITS_SET(phy_control, + PHY_CH_POWER_DOWN_OVRD(0xc, DPIO_PHY0, DPIO_CH1))) + phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 1); + } + + if (cmn_d->ops->is_enabled(dev_priv, cmn_d)) { + phy_status |= PHY_POWERGOOD(DPIO_PHY1); + + /* this assumes override is only used to enable lanes */ + if ((phy_control & PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY1, DPIO_CH0)) == 0) + phy_control |= PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY1, DPIO_CH0); + + if (BITS_SET(phy_control, + PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY1, DPIO_CH0))) + phy_status |= PHY_STATUS_CMN_LDO(DPIO_PHY1, DPIO_CH0); + + if (BITS_SET(phy_control, + PHY_CH_POWER_DOWN_OVRD(0x3, DPIO_PHY1, DPIO_CH0))) + phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 0); + if (BITS_SET(phy_control, + PHY_CH_POWER_DOWN_OVRD(0xc, DPIO_PHY1, DPIO_CH0))) + phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 1); + } + + /* + * The PHY may be busy with some initial calibration and whatnot, + * so the power state can take a while to actually change. + */ + if (wait_for((tmp = I915_READ(DISPLAY_PHY_STATUS)) == phy_status, 10)) + WARN(phy_status != tmp, + "Unexpected PHY_STATUS 0x%08x, expected 0x%08x (PHY_CONTROL=0x%08x)\n", + tmp, phy_status, dev_priv->chv_phy_control); +} + +#undef BITS_SET + static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { @@ -1014,6 +1115,8 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, DRM_DEBUG_KMS("Enabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n", phy, dev_priv->chv_phy_control); + + assert_chv_phy_status(dev_priv); } static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, @@ -1040,6 +1143,8 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, DRM_DEBUG_KMS("Disabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n", phy, dev_priv->chv_phy_control); + + assert_chv_phy_status(dev_priv); } static void assert_chv_phy_powergate(struct drm_i915_private *dev_priv, enum dpio_phy phy, @@ -1117,6 +1222,8 @@ bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy, DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d (DPIO_PHY_CONTROL=0x%08x)\n", phy, ch, dev_priv->chv_phy_control); + assert_chv_phy_status(dev_priv); + out: mutex_unlock(&power_domains->lock); @@ -1146,6 +1253,8 @@ void chv_phy_powergate_lanes(struct intel_encoder *encoder, DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d lanes 0x%x (PHY_CONTROL=0x%08x)\n", phy, ch, mask, dev_priv->chv_phy_control); + assert_chv_phy_status(dev_priv); + assert_chv_phy_powergate(dev_priv, phy, ch, override, mask); mutex_unlock(&power_domains->lock); @@ -1312,8 +1421,6 @@ void intel_display_power_put(struct drm_i915_private *dev_priv, intel_runtime_pm_put(dev_priv); } -#define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1) - #define HSW_ALWAYS_ON_POWER_DOMAINS ( \ BIT(POWER_DOMAIN_PIPE_A) | \ BIT(POWER_DOMAIN_TRANSCODER_EDP) | \ @@ -1575,21 +1682,6 @@ static struct i915_power_well chv_power_wells[] = { }, }; -static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv, - int power_well_id) -{ - struct i915_power_domains *power_domains = &dev_priv->power_domains; - struct i915_power_well *power_well; - int i; - - for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) { - if (power_well->data == power_well_id) - return power_well; - } - - return NULL; -} - bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv, int power_well_id) { -- cgit v0.10.2 From 0f64614dde172e4f4b2734a55091a4d307863cbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 26 Aug 2015 19:39:18 +0300 Subject: drm/i915: Fix clock readout when pipes are enabled w/o ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The BIOS sometimes likes to enable pipes w/o any ports, at least on older machines. Currently we fail to assign anything sensible to crtc->hwmode.crtc_clock which leads to complaints from the vblank code. Deal with active pipes w/o ports and assign something sensible to crtc_clock in i9xx_get_pipe_config(). The encoder .get_config() will override this if the port is enabled. Gets rid of rest of these on my gen4: [drm:drm_calc_timestamping_constants [drm]] *ERROR* crtc 24: Can't calculate constants, dotclock = 0! [drm:i915_get_vblank_timestamp] crtc 1 is disabled v2: Fill out crtc_clock already in i9xx_get_pipe_config() (Maarten) Cc: Maarten Lankhorst Signed-off-by: Ville Syrjälä Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f32206d..ba0c85e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8059,6 +8059,14 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, else i9xx_crtc_clock_get(crtc, pipe_config); + /* + * Normally the dotclock is filled in by the encoder .get_config() + * but in case the pipe is enabled w/o any ports we need a sane + * default. + */ + pipe_config->base.adjusted_mode.crtc_clock = + pipe_config->port_clock / pipe_config->pixel_multiplier; + return true; } -- cgit v0.10.2 From 02e93c3537d5b496bbf4d6a97c0d02becc501b5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 26 Aug 2015 19:39:19 +0300 Subject: drm/i915: Factor out intel_crtc_has_encoders() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the code mode readable by pulling the "does this crtc have any encoders?" deduction into a separate function. Cc: Maarten Lankhorst Signed-off-by: Ville Syrjälä Reviewed-by: Maarten Lankhorst Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ba0c85e..439e66e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14807,13 +14807,22 @@ intel_check_plane_mapping(struct intel_crtc *crtc) return true; } +static bool intel_crtc_has_encoders(struct intel_crtc *crtc) +{ + struct drm_device *dev = crtc->base.dev; + struct intel_encoder *encoder; + + for_each_encoder_on_crtc(dev, &crtc->base, encoder) + return true; + + return false; +} + static void intel_sanitize_crtc(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_encoder *encoder; u32 reg; - bool enable; /* Clear any frame start delays used for debugging left by the BIOS */ reg = PIPECONF(crtc->config->cpu_transcoder); @@ -14857,16 +14866,11 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) /* Adjust the state of the output pipe according to whether we * have active connectors/encoders. */ - enable = false; - for_each_encoder_on_crtc(dev, &crtc->base, encoder) { - enable = true; - break; - } - - if (!enable) + if (!intel_crtc_has_encoders(crtc)) intel_crtc_disable_noatomic(&crtc->base); if (crtc->active != crtc->base.state->active) { + struct intel_encoder *encoder; /* This can happen either due to bugs in the get_hw_state * functions or because of calls to intel_crtc_disable_noatomic, -- cgit v0.10.2 From 1751fcf9f92ebfd230260230956535b19b4ec675 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 27 Aug 2015 15:15:15 +0200 Subject: drm/i915: Fix module initialisation, v2. The driver doesn't support UMS any more, so set DRIVER_MODESET by default, remove the legacy s/r callbacks, and rename the s/r functions to make it more clear they're only in use by switcheroo now. Also remove an obsolete comment about atomic. Normal updates are supported only async updates aren't yet. v2: Don't unconditionally set DRIVER_ATOMIC, we're not yet there. Signed-off-by: Maarten Lankhorst Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 097d4ba..f0eaa6f 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -364,12 +364,12 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_ dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; /* i915 resume handler doesn't set to D0 */ pci_set_power_state(dev->pdev, PCI_D0); - i915_resume_legacy(dev); + i915_resume_switcheroo(dev); dev->switch_power_state = DRM_SWITCH_POWER_ON; } else { pr_err("switched off\n"); dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; - i915_suspend_legacy(dev, pmm); + i915_suspend_switcheroo(dev, pmm); dev->switch_power_state = DRM_SWITCH_POWER_OFF; } } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index ce3bd0c..4646fe1 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -679,7 +679,7 @@ static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation) return 0; } -int i915_suspend_legacy(struct drm_device *dev, pm_message_t state) +int i915_suspend_switcheroo(struct drm_device *dev, pm_message_t state) { int error; @@ -812,7 +812,7 @@ static int i915_drm_resume_early(struct drm_device *dev) return ret; } -int i915_resume_legacy(struct drm_device *dev) +int i915_resume_switcheroo(struct drm_device *dev) { int ret; @@ -1649,7 +1649,7 @@ static struct drm_driver driver = { */ .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | DRIVER_PRIME | - DRIVER_RENDER, + DRIVER_RENDER | DRIVER_MODESET, .load = i915_driver_load, .unload = i915_driver_unload, .open = i915_driver_open, @@ -1658,10 +1658,6 @@ static struct drm_driver driver = { .postclose = i915_driver_postclose, .set_busid = drm_pci_set_busid, - /* Used in place of i915_pm_ops for non-DRIVER_MODESET */ - .suspend = i915_suspend_legacy, - .resume = i915_resume_legacy, - #if defined(CONFIG_DEBUG_FS) .debugfs_init = i915_debugfs_init, .debugfs_cleanup = i915_debugfs_cleanup, @@ -1704,7 +1700,6 @@ static int __init i915_init(void) * either the i915.modeset prarameter or by the * vga_text_mode_force boot option. */ - driver.driver_features |= DRIVER_MODESET; if (i915.modeset == 0) driver.driver_features &= ~DRIVER_MODESET; @@ -1715,17 +1710,11 @@ static int __init i915_init(void) #endif if (!(driver.driver_features & DRIVER_MODESET)) { - driver.get_vblank_timestamp = NULL; /* Silently fail loading to not upset userspace. */ DRM_DEBUG_DRIVER("KMS and UMS disabled.\n"); return 0; } - /* - * FIXME: Note that we're lying to the DRM core here so that we can get access - * to the atomic ioctl and the atomic properties. Only plane operations on - * a single CRTC will actually work. - */ if (i915.nuclear_pageflip) driver.driver_features |= DRIVER_ATOMIC; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e1bbe46..d2c4449 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2606,8 +2606,8 @@ struct drm_i915_cmd_table { extern const struct drm_ioctl_desc i915_ioctls[]; extern int i915_max_ioctl; -extern int i915_suspend_legacy(struct drm_device *dev, pm_message_t state); -extern int i915_resume_legacy(struct drm_device *dev); +extern int i915_suspend_switcheroo(struct drm_device *dev, pm_message_t state); +extern int i915_resume_switcheroo(struct drm_device *dev); /* i915_params.c */ struct i915_params { -- cgit v0.10.2 From aa557ab01576531c39fa3e7ceaa33314f65164fd Mon Sep 17 00:00:00 2001 From: Alex Dai Date: Tue, 18 Aug 2015 14:32:35 -0700 Subject: drm/i915/guc: Support GuC version 4.3 The firmware layout changes that now it only has css header + uCode + RSA signature. Plus, other trivial changes to support GuC V4.3. Signed-off-by: Alex Dai Reviewed-by: Dave Gordon Reviewed-by: Dave Gordon Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h index 950c7e7..e1f47ba 100644 --- a/drivers/gpu/drm/i915/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h @@ -41,7 +41,7 @@ #define GUC_CTX_PRIORITY_NORMAL 3 #define GUC_MAX_GPU_CONTEXTS 1024 -#define GUC_INVALID_CTX_ID (GUC_MAX_GPU_CONTEXTS + 1) +#define GUC_INVALID_CTX_ID GUC_MAX_GPU_CONTEXTS /* Work queue item header definitions */ #define WQ_STATUS_ACTIVE 1 @@ -75,6 +75,7 @@ #define GUC_CTX_DESC_ATTR_RESET (1 << 4) #define GUC_CTX_DESC_ATTR_WQLOCKED (1 << 5) #define GUC_CTX_DESC_ATTR_PCH (1 << 6) +#define GUC_CTX_DESC_ATTR_TERMINATED (1 << 7) /* The guc control data is 10 DWORDs */ #define GUC_CTL_CTXINFO 0 @@ -107,6 +108,7 @@ #define GUC_CTL_DISABLE_SCHEDULER (1 << 4) #define GUC_CTL_PREEMPTION_LOG (1 << 5) #define GUC_CTL_ENABLE_SLPC (1 << 7) +#define GUC_CTL_RESET_ON_PREMPT_FAILURE (1 << 8) #define GUC_CTL_DEBUG 8 #define GUC_LOG_VERBOSITY_SHIFT 0 #define GUC_LOG_VERBOSITY_LOW (0 << GUC_LOG_VERBOSITY_SHIFT) @@ -116,8 +118,9 @@ /* Verbosity range-check limits, without the shift */ #define GUC_LOG_VERBOSITY_MIN 0 #define GUC_LOG_VERBOSITY_MAX 3 +#define GUC_CTL_RSRVD 9 -#define GUC_CTL_MAX_DWORDS (GUC_CTL_DEBUG + 1) +#define GUC_CTL_MAX_DWORDS (GUC_CTL_RSRVD + 1) struct guc_doorbell_info { u32 db_status; @@ -207,7 +210,9 @@ struct guc_context_desc { u32 engine_presence; - u32 reserved0[1]; + u8 engine_suspended; + + u8 reserved0[3]; u64 reserved1[1]; u64 desc_private; diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 13e75f6..5eafd31 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -59,7 +59,7 @@ * */ -#define I915_SKL_GUC_UCODE "i915/skl_guc_ver3.bin" +#define I915_SKL_GUC_UCODE "i915/skl_guc_ver4.bin" MODULE_FIRMWARE(I915_SKL_GUC_UCODE); /* User-friendly representation of an enum */ @@ -226,10 +226,6 @@ static inline bool guc_ucode_response(struct drm_i915_private *dev_priv, * +-------------------------------+ ---- * | RSA signature | 256B * +-------------------------------+ ---- - * | RSA public Key | 256B - * +-------------------------------+ ---- - * | Public key modulus | 4B - * +-------------------------------+ ---- * * Architecturally, the DMA engine is bidirectional, and can potentially even * transfer between GTT locations. This functionality is left out of the API @@ -244,7 +240,6 @@ static inline bool guc_ucode_response(struct drm_i915_private *dev_priv, #define UOS_VER_MAJOR_OFFSET 0x46 #define UOS_CSS_HEADER_SIZE 0x80 #define UOS_RSA_SIG_SIZE 0x100 -#define UOS_CSS_SIGNING_SIZE 0x204 static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv) { @@ -256,7 +251,7 @@ static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv) int i, ret = 0; /* uCode size, also is where RSA signature starts */ - offset = ucode_size = guc_fw->guc_fw_size - UOS_CSS_SIGNING_SIZE; + offset = ucode_size = guc_fw->guc_fw_size - UOS_RSA_SIG_SIZE; I915_WRITE(DMA_COPY_SIZE, ucode_size); /* Copy RSA signature from the fw image to HW for verification */ @@ -463,8 +458,8 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw) struct drm_i915_gem_object *obj; const struct firmware *fw; const u8 *css_header; - const size_t minsize = UOS_CSS_HEADER_SIZE + UOS_CSS_SIGNING_SIZE; - const size_t maxsize = GUC_WOPCM_SIZE_VALUE + UOS_CSS_SIGNING_SIZE + const size_t minsize = UOS_CSS_HEADER_SIZE + UOS_RSA_SIG_SIZE; + const size_t maxsize = GUC_WOPCM_SIZE_VALUE + UOS_RSA_SIG_SIZE - 0x8000; /* 32k reserved (8K stack + 24k context) */ int err; @@ -564,8 +559,8 @@ void intel_guc_ucode_init(struct drm_device *dev) fw_path = NULL; } else if (IS_SKYLAKE(dev)) { fw_path = I915_SKL_GUC_UCODE; - guc_fw->guc_fw_major_wanted = 3; - guc_fw->guc_fw_minor_wanted = 0; + guc_fw->guc_fw_major_wanted = 4; + guc_fw->guc_fw_minor_wanted = 3; } else { i915.enable_guc_submission = false; fw_path = ""; /* unknown device */ -- cgit v0.10.2 From f5d3c3eaab1d9e38854deb0251e659d04e3bc771 Mon Sep 17 00:00:00 2001 From: Alex Dai Date: Tue, 18 Aug 2015 14:34:47 -0700 Subject: drm/i915: Notify GuC rc6 state If rc6 is enabled, notify GuC so it can do proper forcewake before command submission. Signed-off-by: Alex Dai Reviewed-by: Tom O'Rourke Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index ec70393..792d0b9 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -151,6 +151,18 @@ static int host2guc_release_doorbell(struct intel_guc *guc, return host2guc_action(guc, data, 2); } +static int host2guc_sample_forcewake(struct intel_guc *guc, + struct i915_guc_client *client) +{ + struct drm_i915_private *dev_priv = guc_to_i915(guc); + u32 data[2]; + + data[0] = HOST2GUC_ACTION_SAMPLE_FORCEWAKE; + data[1] = (intel_enable_rc6(dev_priv->dev)) ? 1 : 0; + + return host2guc_action(guc, data, 2); +} + /* * Initialise, update, or clear doorbell data shared with the GuC * @@ -874,6 +886,9 @@ int i915_guc_submission_enable(struct drm_device *dev) } guc->execbuf_client = client; + + host2guc_sample_forcewake(guc, client); + return 0; } -- cgit v0.10.2 From 79e50a4f7228e5f27d2e9785fad5509d1392a0d3 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 26 Aug 2015 10:58:20 +0300 Subject: drm/i915: move intel_hrawclk() to intel_display.c Make it available outside of intel_dp.c. Signed-off-by: Jani Nikula Reviewed-by: Clint Taylor Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 439e66e..3f60cf4 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -135,6 +135,39 @@ intel_pch_rawclk(struct drm_device *dev) return I915_READ(PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK; } +/* hrawclock is 1/4 the FSB frequency */ +int intel_hrawclk(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t clkcfg; + + /* There is no CLKCFG reg in Valleyview. VLV hrawclk is 200 MHz */ + if (IS_VALLEYVIEW(dev)) + return 200; + + clkcfg = I915_READ(CLKCFG); + switch (clkcfg & CLKCFG_FSB_MASK) { + case CLKCFG_FSB_400: + return 100; + case CLKCFG_FSB_533: + return 133; + case CLKCFG_FSB_667: + return 166; + case CLKCFG_FSB_800: + return 200; + case CLKCFG_FSB_1067: + return 266; + case CLKCFG_FSB_1333: + return 333; + /* these two are just a guess; one of them might be right */ + case CLKCFG_FSB_1600: + case CLKCFG_FSB_1600_ALT: + return 400; + default: + return 133; + } +} + static inline u32 /* units of 100MHz */ intel_fdi_link_freq(struct drm_device *dev) { diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 3a9c43d..f45872c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -261,40 +261,6 @@ static void intel_dp_unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes) dst[i] = src >> ((3-i) * 8); } -/* hrawclock is 1/4 the FSB frequency */ -static int -intel_hrawclk(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - uint32_t clkcfg; - - /* There is no CLKCFG reg in Valleyview. VLV hrawclk is 200 MHz */ - if (IS_VALLEYVIEW(dev)) - return 200; - - clkcfg = I915_READ(CLKCFG); - switch (clkcfg & CLKCFG_FSB_MASK) { - case CLKCFG_FSB_400: - return 100; - case CLKCFG_FSB_533: - return 133; - case CLKCFG_FSB_667: - return 166; - case CLKCFG_FSB_800: - return 200; - case CLKCFG_FSB_1067: - return 266; - case CLKCFG_FSB_1333: - return 333; - /* these two are just a guess; one of them might be right */ - case CLKCFG_FSB_1600: - case CLKCFG_FSB_1600_ALT: - return 400; - default: - return 133; - } -} - static void intel_dp_init_panel_power_sequencer(struct drm_device *dev, struct intel_dp *intel_dp); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 72c1181..30012c8 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1011,6 +1011,7 @@ void i915_audio_component_cleanup(struct drm_i915_private *dev_priv); extern const struct drm_plane_funcs intel_plane_funcs; bool intel_has_pending_fb_unpin(struct drm_device *dev); int intel_pch_rawclk(struct drm_device *dev); +int intel_hrawclk(struct drm_device *dev); void intel_mark_busy(struct drm_device *dev); void intel_mark_idle(struct drm_device *dev); void intel_crtc_restore_mode(struct drm_crtc *crtc); -- cgit v0.10.2 From 42a8ca4cb4a48ddbf40e8edb291425e76bcdc230 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 27 Aug 2015 16:23:30 +0300 Subject: drm/i915: add yesno utility function Add a common function to return "yes" or "no" string based on the argument, and drop the local versions of it. Signed-off-by: Jani Nikula Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 624024c..2f1b693 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -46,11 +46,6 @@ enum { PINNED_LIST, }; -static const char *yesno(int v) -{ - return v ? "yes" : "no"; -} - /* As the drm_debugfs_init() routines are called before dev->dev_private is * allocated we need to hook into the minor for release. */ static int diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d2c4449..1d99402 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -106,6 +106,11 @@ unlikely(__ret_warn_on); \ }) +static inline const char *yesno(bool v) +{ + return v ? "yes" : "no"; +} + enum pipe { INVALID_PIPE = -1, PIPE_A = 0, diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 493e9b2..3379f9c 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -30,11 +30,6 @@ #include #include "i915_drv.h" -static const char *yesno(int v) -{ - return v ? "yes" : "no"; -} - static const char *ring_str(int ring) { switch (ring) { -- cgit v0.10.2 From 331f38e77d4519d2ca60cea232c7f2bfad5e4d28 Mon Sep 17 00:00:00 2001 From: Zhiyuan Lv Date: Fri, 28 Aug 2015 15:41:14 +0800 Subject: drm/i915: preallocate pdps for 32 bit vgpu This is based on Mika Kuoppala's patch below: http://article.gmane.org/gmane.comp.freedesktop.xorg.drivers.intel/61104/match=workaround+hw+preload The patch will preallocate the page directories for 32-bit PPGTT when i915 runs inside a virtual machine with Intel GVT-g. With this change, the root pointers in EXECLIST context will always keep the same. The change is needed for vGPU because Intel GVT-g will do page table shadowing, and needs to track all the page table changes from guest i915 driver. However, if guest PPGTT is modified through GPU commands like LRI, it is not possible to trap the operations in the right time, so it will be hard to make shadow PPGTT to work correctly. Shadow PPGTT could be much simpler with this change. Meanwhile hypervisor could simply prohibit any attempt of PPGTT modification through GPU command for security. The function gen8_preallocate_top_level_pdps() in the patch is from Mika, with only one change to set "used_pdpes" to avoid duplicated allocation later. Cc: Mika Kuoppala Cc: Dave Gordon Cc: Michel Thierry Signed-off-by: Zhiyuan Lv Signed-off-by: Zhi Wang Reviewed-by: Joonas Lahtinen Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 4a76807..ed10e77 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1441,6 +1441,33 @@ static void gen8_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m) } } +static int gen8_preallocate_top_level_pdps(struct i915_hw_ppgtt *ppgtt) +{ + unsigned long *new_page_dirs, **new_page_tables; + uint32_t pdpes = I915_PDPES_PER_PDP(dev); + int ret; + + /* We allocate temp bitmap for page tables for no gain + * but as this is for init only, lets keep the things simple + */ + ret = alloc_gen8_temp_bitmaps(&new_page_dirs, &new_page_tables, pdpes); + if (ret) + return ret; + + /* Allocate for all pdps regardless of how the ppgtt + * was defined. + */ + ret = gen8_ppgtt_alloc_page_directories(&ppgtt->base, &ppgtt->pdp, + 0, 1ULL << 32, + new_page_dirs); + if (!ret) + *ppgtt->pdp.used_pdpes = *new_page_dirs; + + free_gen8_temp_bitmaps(new_page_dirs, new_page_tables, pdpes); + + return ret; +} + /* * GEN8 legacy ppgtt programming is accomplished through a max 4 PDP registers * with a net effect resembling a 2-level page table in normal x86 terms. Each @@ -1484,6 +1511,12 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) trace_i915_page_directory_pointer_entry_alloc(&ppgtt->base, 0, 0, GEN8_PML4E_SHIFT); + + if (intel_vgpu_active(ppgtt->base.dev)) { + ret = gen8_preallocate_top_level_pdps(ppgtt); + if (ret) + goto free_scratch; + } } return 0; diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 1af84c5..258af9b 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1540,7 +1540,8 @@ static int gen8_emit_bb_start(struct drm_i915_gem_request *req, * not needed in 48-bit.*/ if (req->ctx->ppgtt && (intel_ring_flag(req->ring) & req->ctx->ppgtt->pd_dirty_rings)) { - if (!USES_FULL_48BIT_PPGTT(req->i915)) { + if (!USES_FULL_48BIT_PPGTT(req->i915) && + !intel_vgpu_active(req->i915->dev)) { ret = intel_logical_ring_emit_pdps(req); if (ret) return ret; -- cgit v0.10.2 From a0bd6c3183a164970e934ee4f514956dd577a628 Mon Sep 17 00:00:00 2001 From: Zhiyuan Lv Date: Fri, 28 Aug 2015 15:41:16 +0800 Subject: drm/i915: Always enable execlists on BDW for vgpu Broadwell hardware supports both ring buffer mode and execlist mode. When i915 runs inside a VM with Intel GVT-g, we allow execlist mode only. The main reason of EXECLIST only is that GVT-g does not support the dynamic mode switch between ring buffer mode and execlist mode when running multiple virtual machines. v2: - Adjust the position of vgpu check in sanitize function (Joonas) - Add vgpu error check in context initialization. (Joonas, Daniel) Signed-off-by: Zhiyuan Lv Signed-off-by: Zhi Wang Reviewed-by: Joonas Lahtinen Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 8e893b3..74aa0c9 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -332,6 +332,13 @@ int i915_gem_context_init(struct drm_device *dev) if (WARN_ON(dev_priv->ring[RCS].default_context)) return 0; + if (intel_vgpu_active(dev) && HAS_LOGICAL_RING_CONTEXTS(dev)) { + if (!i915.enable_execlists) { + DRM_INFO("Only EXECLIST mode is supported in vgpu.\n"); + return -EINVAL; + } + } + if (i915.enable_execlists) { /* NB: intentionally left blank. We will allocate our own * backing objects as we need them, thank you very much */ diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 258af9b..e9520af 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -236,6 +236,12 @@ int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists { WARN_ON(i915.enable_ppgtt == -1); + /* On platforms with execlist available, vGPU will only + * support execlist mode, no ring buffer mode. + */ + if (HAS_LOGICAL_RING_CONTEXTS(dev) && intel_vgpu_active(dev)) + return 1; + if (INTEL_INFO(dev)->gen >= 9) return 1; -- cgit v0.10.2 From 532beabf343d16d269491c63ed4590e5a675ea2b Mon Sep 17 00:00:00 2001 From: Zhiyuan Lv Date: Fri, 28 Aug 2015 15:41:17 +0800 Subject: drm/i915: Update PV INFO page definition for Intel GVT-g Some more definitions in the PV info page are added. They are mainly for the guest notification to Intel GVT-g device model. They are used for Broadwell enabling. The notification of PPGTT page table creation/destroy is to notify GVT-g device model the life cycle of guest page tables. Then device model will implement shadow page table for guests. The notification of context create/destroy is optional. If it is used, the device model will create/destroy shadow context corresponding to the context's life cycle. Guest driver needs to make sure that the context's LRCA and backing storage address unchanged. If it is not used, the device model will perform the context shadow work in the context scheduling time. Signed-off-by: Zhiyuan Lv Signed-off-by: Zhi Wang Reviewed-by: Joonas Lahtinen Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_vgpu.h b/drivers/gpu/drm/i915/i915_vgpu.h index 97a88b5..21c97f4 100644 --- a/drivers/gpu/drm/i915/i915_vgpu.h +++ b/drivers/gpu/drm/i915/i915_vgpu.h @@ -40,6 +40,19 @@ #define INTEL_VGT_IF_VERSION \ INTEL_VGT_IF_VERSION_ENCODE(VGT_VERSION_MAJOR, VGT_VERSION_MINOR) +/* + * notifications from guest to vgpu device model + */ +enum vgt_g2v_type { + VGT_G2V_PPGTT_L3_PAGE_TABLE_CREATE = 2, + VGT_G2V_PPGTT_L3_PAGE_TABLE_DESTROY, + VGT_G2V_PPGTT_L4_PAGE_TABLE_CREATE, + VGT_G2V_PPGTT_L4_PAGE_TABLE_DESTROY, + VGT_G2V_EXECLIST_CONTEXT_CREATE, + VGT_G2V_EXECLIST_CONTEXT_DESTROY, + VGT_G2V_MAX, +}; + struct vgt_if { uint64_t magic; /* VGT_MAGIC */ uint16_t version_major; @@ -70,11 +83,28 @@ struct vgt_if { uint32_t rsv3[0x200 - 24]; /* pad to half page */ /* * The bottom half page is for response from Gfx driver to hypervisor. - * Set to reserved fields temporarily by now. */ uint32_t rsv4; uint32_t display_ready; /* ready for display owner switch */ - uint32_t rsv5[0x200 - 2]; /* pad to one page */ + + uint32_t rsv5[4]; + + uint32_t g2v_notify; + uint32_t rsv6[7]; + + uint32_t pdp0_lo; + uint32_t pdp0_hi; + uint32_t pdp1_lo; + uint32_t pdp1_hi; + uint32_t pdp2_lo; + uint32_t pdp2_hi; + uint32_t pdp3_lo; + uint32_t pdp3_hi; + + uint32_t execlist_context_descriptor_lo; + uint32_t execlist_context_descriptor_hi; + + uint32_t rsv7[0x200 - 24]; /* pad to one page */ } __packed; #define vgtif_reg(x) \ -- cgit v0.10.2 From 650da34c4af12921e0148bbc0dba7419d7776189 Mon Sep 17 00:00:00 2001 From: Zhiyuan Lv Date: Fri, 28 Aug 2015 15:41:18 +0800 Subject: drm/i915: guest i915 notification for Intel GVT-g When i915 drivers run inside a VM with Intel GVT-g, some explicit notifications are needed from guest to host device model through PV INFO page write. The notifications include: PPGTT create PPGTT destroy They are used for the shadow implementation of PPGTT. Intel GVT-g needs to write-protect the guest pages of PPGTT, and clear the write protection when they end their life cycle. v2: - Use lower_32_bits()/upper_32_bits() for qword operations; - Remove the notification of guest context creation/destroy; Signed-off-by: Zhiyuan Lv Signed-off-by: Zhi Wang Reviewed-by: Joonas Lahtinen Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index ed10e77..bdb7adc 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -899,6 +899,41 @@ static int gen8_init_scratch(struct i915_address_space *vm) return 0; } +static int gen8_ppgtt_notify_vgt(struct i915_hw_ppgtt *ppgtt, bool create) +{ + enum vgt_g2v_type msg; + struct drm_device *dev = ppgtt->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + unsigned int offset = vgtif_reg(pdp0_lo); + int i; + + if (USES_FULL_48BIT_PPGTT(dev)) { + u64 daddr = px_dma(&ppgtt->pml4); + + I915_WRITE(offset, lower_32_bits(daddr)); + I915_WRITE(offset + 4, upper_32_bits(daddr)); + + msg = (create ? VGT_G2V_PPGTT_L4_PAGE_TABLE_CREATE : + VGT_G2V_PPGTT_L4_PAGE_TABLE_DESTROY); + } else { + for (i = 0; i < GEN8_LEGACY_PDPES; i++) { + u64 daddr = i915_page_dir_dma_addr(ppgtt, i); + + I915_WRITE(offset, lower_32_bits(daddr)); + I915_WRITE(offset + 4, upper_32_bits(daddr)); + + offset += 8; + } + + msg = (create ? VGT_G2V_PPGTT_L3_PAGE_TABLE_CREATE : + VGT_G2V_PPGTT_L3_PAGE_TABLE_DESTROY); + } + + I915_WRITE(vgtif_reg(g2v_notify), msg); + + return 0; +} + static void gen8_free_scratch(struct i915_address_space *vm) { struct drm_device *dev = vm->dev; @@ -945,6 +980,9 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm) struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); + if (intel_vgpu_active(vm->dev)) + gen8_ppgtt_notify_vgt(ppgtt, false); + if (!USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) gen8_ppgtt_cleanup_3lvl(ppgtt->base.dev, &ppgtt->pdp); else @@ -1519,6 +1557,9 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) } } + if (intel_vgpu_active(ppgtt->base.dev)) + gen8_ppgtt_notify_vgt(ppgtt, true); + return 0; free_scratch: -- cgit v0.10.2 From 34e0adbb4508a318e8039ee3959383e4bf080f04 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 31 Aug 2015 13:04:25 +0200 Subject: drm/i915: Remove start frame argument to pipe_update_begin/end. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's already a per crtc member that can be used for it. Signed-off-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3f60cf4..d38ceb0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11142,11 +11142,10 @@ static void ilk_do_mmio_flip(struct intel_crtc *intel_crtc) static void intel_do_mmio_flip(struct intel_crtc *intel_crtc) { struct drm_device *dev = intel_crtc->base.dev; - u32 start_vbl_count; intel_mark_page_flip_active(intel_crtc); - intel_pipe_update_start(intel_crtc, &start_vbl_count); + intel_pipe_update_start(intel_crtc); if (INTEL_INFO(dev)->gen >= 9) skl_do_mmio_flip(intel_crtc); @@ -11154,7 +11153,7 @@ static void intel_do_mmio_flip(struct intel_crtc *intel_crtc) /* use_mmio_flip() retricts MMIO flips to ilk+ */ ilk_do_mmio_flip(intel_crtc); - intel_pipe_update_end(intel_crtc, start_vbl_count); + intel_pipe_update_end(intel_crtc); } static void intel_mmio_flip_work_func(struct work_struct *work) @@ -13463,7 +13462,7 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc, /* Perform vblank evasion around commit operation */ if (crtc->state->active) - intel_pipe_update_start(intel_crtc, &intel_crtc->start_vbl_count); + intel_pipe_update_start(intel_crtc); if (!needs_modeset(crtc->state) && INTEL_INFO(dev)->gen >= 9) skl_detach_scalers(intel_crtc); @@ -13475,7 +13474,7 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); if (crtc->state->active) - intel_pipe_update_end(intel_crtc, intel_crtc->start_vbl_count); + intel_pipe_update_end(intel_crtc); } /** diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 30012c8..8f8d320 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1414,9 +1414,8 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob); int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane); int intel_sprite_set_colorkey(struct drm_device *dev, void *data, struct drm_file *file_priv); -void intel_pipe_update_start(struct intel_crtc *crtc, - uint32_t *start_vbl_count); -void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count); +void intel_pipe_update_start(struct intel_crtc *crtc); +void intel_pipe_update_end(struct intel_crtc *crtc); /* intel_tv.c */ void intel_tv_init(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 9d8af2f..c35c233 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -76,7 +76,7 @@ static int usecs_to_scanlines(const struct drm_display_mode *mode, int usecs) * avoid random delays. The value written to @start_vbl_count should be * supplied to intel_pipe_update_end() for error checking. */ -void intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl_count) +void intel_pipe_update_start(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; const struct drm_display_mode *mode = &crtc->config->base.adjusted_mode; @@ -95,7 +95,7 @@ void intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl_count) max = vblank_start - 1; local_irq_disable(); - *start_vbl_count = 0; + crtc->start_vbl_count = 0; if (min <= 0 || max <= 0) return; @@ -134,9 +134,10 @@ void intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl_count) drm_crtc_vblank_put(&crtc->base); - *start_vbl_count = dev->driver->get_vblank_counter(dev, pipe); + crtc->start_vbl_count = dev->driver->get_vblank_counter(dev, pipe); - trace_i915_pipe_update_vblank_evaded(crtc, min, max, *start_vbl_count); + trace_i915_pipe_update_vblank_evaded(crtc, min, max, + crtc->start_vbl_count); } /** @@ -148,7 +149,7 @@ void intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl_count) * re-enables interrupts and verifies the update was actually completed * before a vblank using the value of @start_vbl_count. */ -void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count) +void intel_pipe_update_end(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; enum pipe pipe = crtc->pipe; @@ -158,9 +159,9 @@ void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count) local_irq_enable(); - if (start_vbl_count && start_vbl_count != end_vbl_count) + if (crtc->start_vbl_count && crtc->start_vbl_count != end_vbl_count) DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u)\n", - pipe_name(pipe), start_vbl_count, end_vbl_count); + pipe_name(pipe), crtc->start_vbl_count, end_vbl_count); } static void -- cgit v0.10.2 From 85a62bf9d8ef8d533635270ae985281c58e8c974 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 1 Sep 2015 12:15:33 +0200 Subject: drm/i915: Also record time difference if vblank evasion fails, v2. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes the error message slightly more useful. Changes since v1: - Use ktime_get() while irqs are still disabled. (vsyrjala) Signed-off-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8f8d320..090d67b 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -564,6 +564,8 @@ struct intel_crtc { int scanline_offset; unsigned start_vbl_count; + ktime_t start_vbl_time; + struct intel_crtc_atomic_commit atomic; /* scalers available on this crtc */ diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index c35c233..ca7e264 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -134,6 +134,7 @@ void intel_pipe_update_start(struct intel_crtc *crtc) drm_crtc_vblank_put(&crtc->base); + crtc->start_vbl_time = ktime_get(); crtc->start_vbl_count = dev->driver->get_vblank_counter(dev, pipe); trace_i915_pipe_update_vblank_evaded(crtc, min, max, @@ -154,14 +155,16 @@ void intel_pipe_update_end(struct intel_crtc *crtc) struct drm_device *dev = crtc->base.dev; enum pipe pipe = crtc->pipe; u32 end_vbl_count = dev->driver->get_vblank_counter(dev, pipe); + ktime_t end_vbl_time = ktime_get(); trace_i915_pipe_update_end(crtc, end_vbl_count); local_irq_enable(); if (crtc->start_vbl_count && crtc->start_vbl_count != end_vbl_count) - DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u)\n", - pipe_name(pipe), crtc->start_vbl_count, end_vbl_count); + DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u) time %lld us\n", + pipe_name(pipe), crtc->start_vbl_count, end_vbl_count, + ktime_us_delta(end_vbl_time, crtc->start_vbl_time)); } static void -- cgit v0.10.2 From 62f0ace531b2ca69a1defe5a01a85539fd28353f Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 26 Aug 2015 18:57:26 +0200 Subject: drm/i915: Update comments around base bpp Forgot to do that in commit d328c9d78d64ca11e744fe227096990430a88477 Author: Daniel Vetter Date: Fri Apr 10 16:22:37 2015 +0200 drm/i915: Select starting pipe bpp irrespective or the primary plane and it's confusing. Fix it. Cc: Jesse Barnes Acked-by: Jesse Barnes Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index deba333..ae485e7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12102,10 +12102,6 @@ intel_modeset_pipe_config(struct drm_crtc *crtc, (DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC))) pipe_config->base.adjusted_mode.flags |= DRM_MODE_FLAG_NVSYNC; - /* Compute a starting value for pipe_config->pipe_bpp taking the source - * plane pixel format and any sink constraints into account. Returns the - * source plane bpp so that dithering can be selected on mismatches - * after encoders and crtc also have had their say. */ base_bpp = compute_baseline_pipe_bpp(to_intel_crtc(crtc), pipe_config); if (base_bpp < 0) @@ -12174,7 +12170,7 @@ encoder_retry: /* Dithering seems to not pass-through bits correctly when it should, so * only enable it on 6bpc panels. */ pipe_config->dither = pipe_config->pipe_bpp == 6*3; - DRM_DEBUG_KMS("plane bpp: %i, pipe bpp: %i, dithering: %i\n", + DRM_DEBUG_KMS("hw max bpp: %i, pipe bpp: %i, dithering: %i\n", base_bpp, pipe_config->pipe_bpp, pipe_config->dither); fail: -- cgit v0.10.2 From 40bfd7a3303b7c383493c80a250c59b61d812ce5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 27 Aug 2015 23:55:56 +0300 Subject: drm/i915: Clean up various HPD defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Indent the PORTx_HOTPLUG_... defines appropriately, and fix some space vs. tab issues. v2: Document pre-HSW/LPT bits, and order another tab (Paulo) Reviewed-by: Paulo Zanoni Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e7c9dc8..e36baca 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5394,15 +5394,17 @@ enum skl_disp_power_wells { #define CPU_VGACNTRL 0x41000 -#define DIGITAL_PORT_HOTPLUG_CNTRL 0x44030 -#define DIGITAL_PORTA_HOTPLUG_ENABLE (1 << 4) -#define DIGITAL_PORTA_SHORT_PULSE_2MS (0 << 2) -#define DIGITAL_PORTA_SHORT_PULSE_4_5MS (1 << 2) -#define DIGITAL_PORTA_SHORT_PULSE_6MS (2 << 2) -#define DIGITAL_PORTA_SHORT_PULSE_100MS (3 << 2) -#define DIGITAL_PORTA_NO_DETECT (0 << 0) -#define DIGITAL_PORTA_LONG_PULSE_DETECT_MASK (1 << 1) -#define DIGITAL_PORTA_SHORT_PULSE_DETECT_MASK (1 << 0) +#define DIGITAL_PORT_HOTPLUG_CNTRL 0x44030 +#define DIGITAL_PORTA_HOTPLUG_ENABLE (1 << 4) +#define DIGITAL_PORTA_PULSE_DURATION_2ms (0 << 2) /* pre-HSW */ +#define DIGITAL_PORTA_PULSE_DURATION_4_5ms (1 << 2) /* pre-HSW */ +#define DIGITAL_PORTA_PULSE_DURATION_6ms (2 << 2) /* pre-HSW */ +#define DIGITAL_PORTA_PULSE_DURATION_100ms (3 << 2) /* pre-HSW */ +#define DIGITAL_PORTA_PULSE_DURATION_MASK (3 << 2) /* pre-HSW */ +#define DIGITAL_PORTA_HOTPLUG_STATUS_MASK (3 << 0) +#define DIGITAL_PORTA_HOTPLUG_NO_DETECT (0 << 0) +#define DIGITAL_PORTA_HOTPLUG_SHORT_DETECT (1 << 0) +#define DIGITAL_PORTA_HOTPLUG_LONG_DETECT (2 << 0) /* refresh rate hardware control */ #define RR_HW_CTL 0x45300 @@ -6030,46 +6032,46 @@ enum skl_disp_power_wells { #define SERR_INT_TRANS_FIFO_UNDERRUN(pipe) (1<<(pipe*3)) /* digital port hotplug */ -#define PCH_PORT_HOTPLUG 0xc4030 /* SHOTPLUG_CTL */ -#define BXT_PORTA_HOTPLUG_ENABLE (1 << 28) -#define BXT_PORTA_HOTPLUG_STATUS_MASK (0x3 << 24) +#define PCH_PORT_HOTPLUG 0xc4030 /* SHOTPLUG_CTL */ +#define BXT_PORTA_HOTPLUG_ENABLE (1 << 28) +#define BXT_PORTA_HOTPLUG_STATUS_MASK (3 << 24) #define BXT_PORTA_HOTPLUG_NO_DETECT (0 << 24) #define BXT_PORTA_HOTPLUG_SHORT_DETECT (1 << 24) #define BXT_PORTA_HOTPLUG_LONG_DETECT (2 << 24) -#define PORTD_HOTPLUG_ENABLE (1 << 20) -#define PORTD_PULSE_DURATION_2ms (0) -#define PORTD_PULSE_DURATION_4_5ms (1 << 18) -#define PORTD_PULSE_DURATION_6ms (2 << 18) -#define PORTD_PULSE_DURATION_100ms (3 << 18) -#define PORTD_PULSE_DURATION_MASK (3 << 18) -#define PORTD_HOTPLUG_STATUS_MASK (0x3 << 16) +#define PORTD_HOTPLUG_ENABLE (1 << 20) +#define PORTD_PULSE_DURATION_2ms (0 << 18) /* pre-LPT */ +#define PORTD_PULSE_DURATION_4_5ms (1 << 18) /* pre-LPT */ +#define PORTD_PULSE_DURATION_6ms (2 << 18) /* pre-LPT */ +#define PORTD_PULSE_DURATION_100ms (3 << 18) /* pre-LPT */ +#define PORTD_PULSE_DURATION_MASK (3 << 18) /* pre-LPT */ +#define PORTD_HOTPLUG_STATUS_MASK (3 << 16) #define PORTD_HOTPLUG_NO_DETECT (0 << 16) #define PORTD_HOTPLUG_SHORT_DETECT (1 << 16) #define PORTD_HOTPLUG_LONG_DETECT (2 << 16) -#define PORTC_HOTPLUG_ENABLE (1 << 12) -#define PORTC_PULSE_DURATION_2ms (0) -#define PORTC_PULSE_DURATION_4_5ms (1 << 10) -#define PORTC_PULSE_DURATION_6ms (2 << 10) -#define PORTC_PULSE_DURATION_100ms (3 << 10) -#define PORTC_PULSE_DURATION_MASK (3 << 10) -#define PORTC_HOTPLUG_STATUS_MASK (0x3 << 8) +#define PORTC_HOTPLUG_ENABLE (1 << 12) +#define PORTC_PULSE_DURATION_2ms (0 << 10) /* pre-LPT */ +#define PORTC_PULSE_DURATION_4_5ms (1 << 10) /* pre-LPT */ +#define PORTC_PULSE_DURATION_6ms (2 << 10) /* pre-LPT */ +#define PORTC_PULSE_DURATION_100ms (3 << 10) /* pre-LPT */ +#define PORTC_PULSE_DURATION_MASK (3 << 10) /* pre-LPT */ +#define PORTC_HOTPLUG_STATUS_MASK (3 << 8) #define PORTC_HOTPLUG_NO_DETECT (0 << 8) #define PORTC_HOTPLUG_SHORT_DETECT (1 << 8) #define PORTC_HOTPLUG_LONG_DETECT (2 << 8) -#define PORTB_HOTPLUG_ENABLE (1 << 4) -#define PORTB_PULSE_DURATION_2ms (0) -#define PORTB_PULSE_DURATION_4_5ms (1 << 2) -#define PORTB_PULSE_DURATION_6ms (2 << 2) -#define PORTB_PULSE_DURATION_100ms (3 << 2) -#define PORTB_PULSE_DURATION_MASK (3 << 2) -#define PORTB_HOTPLUG_STATUS_MASK (0x3 << 0) +#define PORTB_HOTPLUG_ENABLE (1 << 4) +#define PORTB_PULSE_DURATION_2ms (0 << 2) /* pre-LPT */ +#define PORTB_PULSE_DURATION_4_5ms (1 << 2) /* pre-LPT */ +#define PORTB_PULSE_DURATION_6ms (2 << 2) /* pre-LPT */ +#define PORTB_PULSE_DURATION_100ms (3 << 2) /* pre-LPT */ +#define PORTB_PULSE_DURATION_MASK (3 << 2) /* pre-LPT */ +#define PORTB_HOTPLUG_STATUS_MASK (3 << 0) #define PORTB_HOTPLUG_NO_DETECT (0 << 0) #define PORTB_HOTPLUG_SHORT_DETECT (1 << 0) #define PORTB_HOTPLUG_LONG_DETECT (2 << 0) -#define PCH_PORT_HOTPLUG2 0xc403C /* SHOTPLUG_CTL2 */ -#define PORTE_HOTPLUG_ENABLE (1 << 4) -#define PORTE_HOTPLUG_STATUS_MASK (0x3 << 0) +#define PCH_PORT_HOTPLUG2 0xc403C /* SHOTPLUG_CTL2 SPT+ */ +#define PORTE_HOTPLUG_ENABLE (1 << 4) +#define PORTE_HOTPLUG_STATUS_MASK (3 << 0) #define PORTE_HOTPLUG_NO_DETECT (0 << 0) #define PORTE_HOTPLUG_SHORT_DETECT (1 << 0) #define PORTE_HOTPLUG_LONG_DETECT (2 << 0) -- cgit v0.10.2 From 87a0210665eeca7c5fa237592da025650b216831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 27 Aug 2015 23:55:57 +0300 Subject: drm/i915: Extract intel_hpd_enabled_irqs() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Eliminate a bunch of duplicated code that calculates the currently enabled HPD interrupt bits. v2: s/;/:/ in patch subject (Paulo) Reviewed-by: Paulo Zanoni Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 8485bea..de0edbd 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3002,27 +3002,34 @@ static void cherryview_irq_preinstall(struct drm_device *dev) vlv_display_irq_reset(dev_priv); } +static u32 intel_hpd_enabled_irqs(struct drm_device *dev, + const u32 hpd[HPD_NUM_PINS]) +{ + struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_encoder *encoder; + u32 enabled_irqs = 0; + + for_each_intel_encoder(dev, encoder) + if (dev_priv->hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED) + enabled_irqs |= hpd[encoder->hpd_pin]; + + return enabled_irqs; +} + static void ibx_hpd_irq_setup(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_encoder *intel_encoder; - u32 hotplug_irqs, hotplug, enabled_irqs = 0; + u32 hotplug_irqs, hotplug, enabled_irqs; if (HAS_PCH_IBX(dev)) { hotplug_irqs = SDE_HOTPLUG_MASK; - for_each_intel_encoder(dev, intel_encoder) - if (dev_priv->hotplug.stats[intel_encoder->hpd_pin].state == HPD_ENABLED) - enabled_irqs |= hpd_ibx[intel_encoder->hpd_pin]; + enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_ibx); } else if (HAS_PCH_SPT(dev)) { hotplug_irqs = SDE_HOTPLUG_MASK_SPT; - for_each_intel_encoder(dev, intel_encoder) - if (dev_priv->hotplug.stats[intel_encoder->hpd_pin].state == HPD_ENABLED) - enabled_irqs |= hpd_spt[intel_encoder->hpd_pin]; + enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_spt); } else { hotplug_irqs = SDE_HOTPLUG_MASK_CPT; - for_each_intel_encoder(dev, intel_encoder) - if (dev_priv->hotplug.stats[intel_encoder->hpd_pin].state == HPD_ENABLED) - enabled_irqs |= hpd_cpt[intel_encoder->hpd_pin]; + enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_cpt); } ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); @@ -3051,15 +3058,10 @@ static void ibx_hpd_irq_setup(struct drm_device *dev) static void bxt_hpd_irq_setup(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_encoder *intel_encoder; - u32 hotplug_port = 0; + u32 hotplug_port; u32 hotplug_ctrl; - for_each_intel_encoder(dev, intel_encoder) { - if (dev_priv->hotplug.stats[intel_encoder->hpd_pin].state - == HPD_ENABLED) - hotplug_port |= hpd_bxt[intel_encoder->hpd_pin]; - } + hotplug_port = intel_hpd_enabled_irqs(dev, hpd_bxt); hotplug_ctrl = I915_READ(BXT_HOTPLUG_CTL) & ~BXT_HOTPLUG_CTL_MASK; @@ -3935,7 +3937,6 @@ static int i965_irq_postinstall(struct drm_device *dev) static void i915_hpd_irq_setup(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_encoder *intel_encoder; u32 hotplug_en; assert_spin_locked(&dev_priv->irq_lock); @@ -3944,9 +3945,7 @@ static void i915_hpd_irq_setup(struct drm_device *dev) hotplug_en &= ~HOTPLUG_INT_EN_MASK; /* Note HDMI and DP share hotplug bits */ /* enable bits are the same for all generations */ - for_each_intel_encoder(dev, intel_encoder) - if (dev_priv->hotplug.stats[intel_encoder->hpd_pin].state == HPD_ENABLED) - hotplug_en |= hpd_mask_i915[intel_encoder->hpd_pin]; + hotplug_en |= intel_hpd_enabled_irqs(dev, hpd_mask_i915); /* Programming the CRT detection parameters tends to generate a spurious hotplug event about three seconds later. So just do it once. -- cgit v0.10.2 From d9dc34f1a1e9649f6e1e3709f6177f7883ce75ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 27 Aug 2015 23:55:58 +0300 Subject: drm/i915: Factor out ilk_update_display_irq() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract the core of ironlake_{enable,disable}_display_irq() into a new function. We'll have further use for it later. v2: Warn about invalid mask vs. enable bits (Paulo) Reviewed-by: Paulo Zanoni Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index de0edbd..baff963 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -154,35 +154,46 @@ static const u32 hpd_bxt[HPD_NUM_PINS] = { static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir); -/* For display hotplug interrupt */ -void -ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask) +/** + * ilk_update_display_irq - update DEIMR + * @dev_priv: driver private + * @interrupt_mask: mask of interrupt bits to update + * @enabled_irq_mask: mask of interrupt bits to enable + */ +static void ilk_update_display_irq(struct drm_i915_private *dev_priv, + uint32_t interrupt_mask, + uint32_t enabled_irq_mask) { + uint32_t new_val; + assert_spin_locked(&dev_priv->irq_lock); + WARN_ON(enabled_irq_mask & ~interrupt_mask); + if (WARN_ON(!intel_irqs_enabled(dev_priv))) return; - if ((dev_priv->irq_mask & mask) != 0) { - dev_priv->irq_mask &= ~mask; + new_val = dev_priv->irq_mask; + new_val &= ~interrupt_mask; + new_val |= (~enabled_irq_mask & interrupt_mask); + + if (new_val != dev_priv->irq_mask) { + dev_priv->irq_mask = new_val; I915_WRITE(DEIMR, dev_priv->irq_mask); POSTING_READ(DEIMR); } } void -ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask) +ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask) { - assert_spin_locked(&dev_priv->irq_lock); - - if (WARN_ON(!intel_irqs_enabled(dev_priv))) - return; + ilk_update_display_irq(dev_priv, mask, mask); +} - if ((dev_priv->irq_mask & mask) != mask) { - dev_priv->irq_mask |= mask; - I915_WRITE(DEIMR, dev_priv->irq_mask); - POSTING_READ(DEIMR); - } +void +ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask) +{ + ilk_update_display_irq(dev_priv, mask, 0); } /** -- cgit v0.10.2 From c2699524d666bd606a2de0aa68691c984efb1fec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 27 Aug 2015 23:55:59 +0300 Subject: drm/i915: Add HAS_PCH_LPT_LP() macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make LPT:LP checks look neater by wrapping the details in a new HAS_PCH_LPT_LP() macro. Reviewed-by: Paulo Zanoni Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4eabe19..482ddb7 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2599,6 +2599,7 @@ struct drm_i915_cmd_table { #define INTEL_PCH_TYPE(dev) (__I915__(dev)->pch_type) #define HAS_PCH_SPT(dev) (INTEL_PCH_TYPE(dev) == PCH_SPT) #define HAS_PCH_LPT(dev) (INTEL_PCH_TYPE(dev) == PCH_LPT) +#define HAS_PCH_LPT_LP(dev) (__I915__(dev)->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) #define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX) #define HAS_PCH_NOP(dev) (INTEL_PCH_TYPE(dev) == PCH_NOP) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ae485e7..888175c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8359,8 +8359,7 @@ static void lpt_enable_clkout_dp(struct drm_device *dev, bool with_spread, if (WARN(with_fdi && !with_spread, "FDI requires downspread\n")) with_spread = true; - if (WARN(dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE && - with_fdi, "LP PCH doesn't have FDI\n")) + if (WARN(HAS_PCH_LPT_LP(dev) && with_fdi, "LP PCH doesn't have FDI\n")) with_fdi = false; mutex_lock(&dev_priv->sb_lock); @@ -8383,8 +8382,7 @@ static void lpt_enable_clkout_dp(struct drm_device *dev, bool with_spread, } } - reg = (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) ? - SBI_GEN0 : SBI_DBUFF0; + reg = HAS_PCH_LPT_LP(dev) ? SBI_GEN0 : SBI_DBUFF0; tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK); tmp |= SBI_GEN0_CFG_BUFFENABLE_DISABLE; intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK); @@ -8400,8 +8398,7 @@ static void lpt_disable_clkout_dp(struct drm_device *dev) mutex_lock(&dev_priv->sb_lock); - reg = (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) ? - SBI_GEN0 : SBI_DBUFF0; + reg = HAS_PCH_LPT_LP(dev) ? SBI_GEN0 : SBI_DBUFF0; tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK); tmp &= ~SBI_GEN0_CFG_BUFFENABLE_DISABLE; intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK); @@ -9413,7 +9410,7 @@ void hsw_enable_pc8(struct drm_i915_private *dev_priv) DRM_DEBUG_KMS("Enabling package C8+\n"); - if (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) { + if (HAS_PCH_LPT_LP(dev)) { val = I915_READ(SOUTH_DSPCLK_GATE_D); val &= ~PCH_LP_PARTITION_LEVEL_DISABLE; I915_WRITE(SOUTH_DSPCLK_GATE_D, val); @@ -9433,7 +9430,7 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv) hsw_restore_lcpll(dev_priv); lpt_init_pch_refclk(dev); - if (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) { + if (HAS_PCH_LPT_LP(dev)) { val = I915_READ(SOUTH_DSPCLK_GATE_D); val |= PCH_LP_PARTITION_LEVEL_DISABLE; I915_WRITE(SOUTH_DSPCLK_GATE_D, val); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index fff0c22..ea49661 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6588,7 +6588,7 @@ static void lpt_init_clock_gating(struct drm_device *dev) * TODO: this bit should only be enabled when really needed, then * disabled when not needed anymore in order to save power. */ - if (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) + if (HAS_PCH_LPT_LP(dev)) I915_WRITE(SOUTH_DSPCLK_GATE_D, I915_READ(SOUTH_DSPCLK_GATE_D) | PCH_LP_PARTITION_LEVEL_DISABLE); @@ -6603,7 +6603,7 @@ static void lpt_suspend_hw(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - if (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) { + if (HAS_PCH_LPT_LP(dev)) { uint32_t val = I915_READ(SOUTH_DSPCLK_GATE_D); val &= ~PCH_LP_PARTITION_LEVEL_DISABLE; -- cgit v0.10.2 From 195baa0673345c70f04d19e9e18470c9cbf88bcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 27 Aug 2015 23:56:00 +0300 Subject: drm/i915: Rename BXT PORTA HPD defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PORTA HPD defines are not BXT specific. They also exist on SPT, and partially already on LPT:LP. Reviewed-by: Paulo Zanoni Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index baff963..3388b64 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1250,7 +1250,7 @@ static bool bxt_port_hotplug_long_detect(enum port port, u32 val) { switch (port) { case PORT_A: - return val & BXT_PORTA_HOTPLUG_LONG_DETECT; + return val & PORTA_HOTPLUG_LONG_DETECT; case PORT_B: return val & PORTB_HOTPLUG_LONG_DETECT; case PORT_C: diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e36baca..7eb76b7 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6033,11 +6033,11 @@ enum skl_disp_power_wells { /* digital port hotplug */ #define PCH_PORT_HOTPLUG 0xc4030 /* SHOTPLUG_CTL */ -#define BXT_PORTA_HOTPLUG_ENABLE (1 << 28) -#define BXT_PORTA_HOTPLUG_STATUS_MASK (3 << 24) -#define BXT_PORTA_HOTPLUG_NO_DETECT (0 << 24) -#define BXT_PORTA_HOTPLUG_SHORT_DETECT (1 << 24) -#define BXT_PORTA_HOTPLUG_LONG_DETECT (2 << 24) +#define PORTA_HOTPLUG_ENABLE (1 << 28) /* LPT:LP+ & BXT */ +#define PORTA_HOTPLUG_STATUS_MASK (3 << 24) /* SPT+ & BXT */ +#define PORTA_HOTPLUG_NO_DETECT (0 << 24) /* SPT+ & BXT */ +#define PORTA_HOTPLUG_SHORT_DETECT (1 << 24) /* SPT+ & BXT */ +#define PORTA_HOTPLUG_LONG_DETECT (2 << 24) /* SPT+ & BXT */ #define PORTD_HOTPLUG_ENABLE (1 << 20) #define PORTD_PULSE_DURATION_2ms (0 << 18) /* pre-LPT */ #define PORTD_PULSE_DURATION_4_5ms (1 << 18) /* pre-LPT */ -- cgit v0.10.2 From 42db67d664af417e946211c7f1f4178c782a582a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 28 Aug 2015 21:26:27 +0300 Subject: drm/i915: Move {pin, long}_mask initialization to caller from intel_get_hpd_pins() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the 0 initialization of pin_mask and long_mask from intel_get_hpd_pins() into each caller. This we we can call intel_get_hpd_pins() multiple times to accumulate more pins from several sources. v2: Add a comment explaining the dangers of intel_get_hpd_pins() (Paulo) Reviewed-by: Paulo Zanoni Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 3388b64..7129389 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1292,7 +1292,13 @@ static bool i9xx_port_hotplug_long_detect(enum port port, u32 val) } } -/* Get a bit mask of pins that have triggered, and which ones may be long. */ +/* + * Get a bit mask of pins that have triggered, and which ones may be long. + * This can be called multiple times with the same masks to accumulate + * hotplug detection results from several registers. + * + * Note that the caller is expected to zero out the masks initially. + */ static void intel_get_hpd_pins(u32 *pin_mask, u32 *long_mask, u32 hotplug_trigger, u32 dig_hotplug_reg, const u32 hpd[HPD_NUM_PINS], @@ -1301,9 +1307,6 @@ static void intel_get_hpd_pins(u32 *pin_mask, u32 *long_mask, enum port port; int i; - *pin_mask = 0; - *long_mask = 0; - for_each_hpd_pin(i) { if ((hpd[i] & hotplug_trigger) == 0) continue; @@ -1544,7 +1547,7 @@ static void i9xx_hpd_irq_handler(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT); - u32 pin_mask, long_mask; + u32 pin_mask = 0, long_mask = 0; if (!hotplug_status) return; @@ -1673,7 +1676,7 @@ static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir) u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK; if (hotplug_trigger) { - u32 dig_hotplug_reg, pin_mask, long_mask; + u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg); @@ -1781,7 +1784,7 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir) hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT; if (hotplug_trigger) { - u32 dig_hotplug_reg, pin_mask, long_mask; + u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg); @@ -2004,7 +2007,7 @@ static void bxt_hpd_handler(struct drm_device *dev, uint32_t iir_status) { struct drm_i915_private *dev_priv = dev->dev_private; u32 hp_control, hp_trigger; - u32 pin_mask, long_mask; + u32 pin_mask = 0, long_mask = 0; /* Get the status */ hp_trigger = iir_status & BXT_DE_PORT_HOTPLUG_MASK; -- cgit v0.10.2 From 6dbf30ce234925e4770f0b52950b601e816b6586 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 27 Aug 2015 23:56:02 +0300 Subject: drm/i915: Introduce spt_irq_handler() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Starting from SPT the only interrupts living in the south are GMBUS and HPD. What's worse some of the SPT specific new bits conflict with some other bits on earlier PCH generations. So better not use the cpt_irq_handler() for SPT+ anymore. Also kill the hand rolled port E handling with something more standardish. This also avoids accidentally confusing port B and port E long pulses since the bits occupy the same positions, just in different registers. Also add a comment noting that the short pulse duration bits are reserved on LPT+. The 2ms value we program is 0, so no issue wrt. the MBZ in the spec. v2: Call intel_hpd_irq_handler() only once (Paulo) Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 7129389..755d9ce 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1262,6 +1262,16 @@ static bool bxt_port_hotplug_long_detect(enum port port, u32 val) } } +static bool spt_port_hotplug2_long_detect(enum port port, u32 val) +{ + switch (port) { + case PORT_E: + return val & PORTE_HOTPLUG_LONG_DETECT; + default: + return false; + } +} + static bool pch_port_hotplug_long_detect(enum port port, u32 val) { switch (port) { @@ -1271,8 +1281,6 @@ static bool pch_port_hotplug_long_detect(enum port port, u32 val) return val & PORTC_HOTPLUG_LONG_DETECT; case PORT_D: return val & PORTD_HOTPLUG_LONG_DETECT; - case PORT_E: - return val & PORTE_HOTPLUG_LONG_DETECT; default: return false; } @@ -1776,12 +1784,7 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir) { struct drm_i915_private *dev_priv = dev->dev_private; int pipe; - u32 hotplug_trigger; - - if (HAS_PCH_SPT(dev)) - hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_SPT; - else - hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT; + u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT; if (hotplug_trigger) { u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; @@ -1789,22 +1792,10 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir) dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg); - if (HAS_PCH_SPT(dev)) { - intel_get_hpd_pins(&pin_mask, &long_mask, - hotplug_trigger, - dig_hotplug_reg, hpd_spt, - pch_port_hotplug_long_detect); - - /* detect PORTE HP event */ - dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG2); - if (pch_port_hotplug_long_detect(PORT_E, - dig_hotplug_reg)) - long_mask |= 1 << HPD_PORT_E; - } else - intel_get_hpd_pins(&pin_mask, &long_mask, - hotplug_trigger, - dig_hotplug_reg, hpd_cpt, - pch_port_hotplug_long_detect); + intel_get_hpd_pins(&pin_mask, &long_mask, + hotplug_trigger, + dig_hotplug_reg, hpd_cpt, + pch_port_hotplug_long_detect); intel_hpd_irq_handler(dev, pin_mask, long_mask); } @@ -1838,6 +1829,43 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir) cpt_serr_int_handler(dev); } +static void spt_irq_handler(struct drm_device *dev, u32 pch_iir) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_SPT & + ~SDE_PORTE_HOTPLUG_SPT; + u32 hotplug2_trigger = pch_iir & SDE_PORTE_HOTPLUG_SPT; + u32 pin_mask = 0, long_mask = 0; + + if (hotplug_trigger) { + u32 dig_hotplug_reg; + + dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); + I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg); + + intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger, + dig_hotplug_reg, hpd_spt, + pch_port_hotplug_long_detect); + } + + if (hotplug2_trigger) { + u32 dig_hotplug_reg; + + dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG2); + I915_WRITE(PCH_PORT_HOTPLUG2, dig_hotplug_reg); + + intel_get_hpd_pins(&pin_mask, &long_mask, hotplug2_trigger, + dig_hotplug_reg, hpd_spt, + spt_port_hotplug2_long_detect); + } + + if (pin_mask) + intel_hpd_irq_handler(dev, pin_mask, long_mask); + + if (pch_iir & SDE_GMBUS_CPT) + gmbus_irq_handler(dev); +} + static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -2156,7 +2184,11 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) if (pch_iir) { I915_WRITE(SDEIIR, pch_iir); ret = IRQ_HANDLED; - cpt_irq_handler(dev, pch_iir); + + if (HAS_PCH_SPT(dev_priv)) + spt_irq_handler(dev, pch_iir); + else + cpt_irq_handler(dev, pch_iir); } else DRM_ERROR("The master control interrupt lied (SDE)!\n"); @@ -3038,9 +3070,6 @@ static void ibx_hpd_irq_setup(struct drm_device *dev) if (HAS_PCH_IBX(dev)) { hotplug_irqs = SDE_HOTPLUG_MASK; enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_ibx); - } else if (HAS_PCH_SPT(dev)) { - hotplug_irqs = SDE_HOTPLUG_MASK_SPT; - enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_spt); } else { hotplug_irqs = SDE_HOTPLUG_MASK_CPT; enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_cpt); @@ -3050,9 +3079,8 @@ static void ibx_hpd_irq_setup(struct drm_device *dev) /* * Enable digital hotplug on the PCH, and configure the DP short pulse - * duration to 2ms (which is the minimum in the Display Port spec) - * - * This register is the same on all known PCH chips. + * duration to 2ms (which is the minimum in the Display Port spec). + * The pulse duration bits are reserved on LPT+. */ hotplug = I915_READ(PCH_PORT_HOTPLUG); hotplug &= ~(PORTD_PULSE_DURATION_MASK|PORTC_PULSE_DURATION_MASK|PORTB_PULSE_DURATION_MASK); @@ -3060,13 +3088,27 @@ static void ibx_hpd_irq_setup(struct drm_device *dev) hotplug |= PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_2ms; hotplug |= PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_2ms; I915_WRITE(PCH_PORT_HOTPLUG, hotplug); +} - /* enable SPT PORTE hot plug */ - if (HAS_PCH_SPT(dev)) { - hotplug = I915_READ(PCH_PORT_HOTPLUG2); - hotplug |= PORTE_HOTPLUG_ENABLE; - I915_WRITE(PCH_PORT_HOTPLUG2, hotplug); - } +static void spt_hpd_irq_setup(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 hotplug_irqs, hotplug, enabled_irqs; + + hotplug_irqs = SDE_HOTPLUG_MASK_SPT; + enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_spt); + + ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); + + /* Enable digital hotplug on the PCH */ + hotplug = I915_READ(PCH_PORT_HOTPLUG); + hotplug |= PORTD_HOTPLUG_ENABLE | PORTC_HOTPLUG_ENABLE | + PORTB_HOTPLUG_ENABLE; + I915_WRITE(PCH_PORT_HOTPLUG, hotplug); + + hotplug = I915_READ(PCH_PORT_HOTPLUG2); + hotplug |= PORTE_HOTPLUG_ENABLE; + I915_WRITE(PCH_PORT_HOTPLUG2, hotplug); } static void bxt_hpd_irq_setup(struct drm_device *dev) @@ -4171,10 +4213,12 @@ void intel_irq_init(struct drm_i915_private *dev_priv) dev->driver->irq_uninstall = gen8_irq_uninstall; dev->driver->enable_vblank = gen8_enable_vblank; dev->driver->disable_vblank = gen8_disable_vblank; - if (HAS_PCH_SPLIT(dev)) - dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup; - else + if (IS_BROXTON(dev)) dev_priv->display.hpd_irq_setup = bxt_hpd_irq_setup; + else if (HAS_PCH_SPT(dev)) + dev_priv->display.hpd_irq_setup = spt_hpd_irq_setup; + else + dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup; } else if (HAS_PCH_SPLIT(dev)) { dev->driver->irq_handler = ironlake_irq_handler; dev->driver->irq_preinstall = ironlake_irq_reset; -- cgit v0.10.2 From e4ce95aa661e411d7da554eb8e6c7f81504acae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 27 Aug 2015 23:56:03 +0300 Subject: drm/i915: Add port A HPD support for ILK/SNB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ILK/SNB support port A HPD. While HPD is optional on eDP let's at least try to wite it up so that we might notice if the link has issues. The eDP spec suggests that if HPD is not wired up, one should poll the link status instead. We don't even do that currently. v2: 0 initialize pin_mask/long_mask due to intel_get_hpd_pins() changes Reviewed-by: Paulo Zanoni Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 755d9ce..57d23f0 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -45,6 +45,10 @@ * and related files, but that will be described in separate chapters. */ +static const u32 hpd_ilk[HPD_NUM_PINS] = { + [HPD_PORT_A] = DE_DP_A_HOTPLUG, +}; + static const u32 hpd_ibx[HPD_NUM_PINS] = { [HPD_CRT] = SDE_CRT_HOTPLUG, [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG, @@ -1272,6 +1276,16 @@ static bool spt_port_hotplug2_long_detect(enum port port, u32 val) } } +static bool ilk_port_hotplug_long_detect(enum port port, u32 val) +{ + switch (port) { + case PORT_A: + return val & DIGITAL_PORTA_HOTPLUG_LONG_DETECT; + default: + return false; + } +} + static bool pch_port_hotplug_long_detect(enum port port, u32 val) { switch (port) { @@ -1870,6 +1884,19 @@ static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir) { struct drm_i915_private *dev_priv = dev->dev_private; enum pipe pipe; + u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG; + + if (hotplug_trigger) { + u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; + + dig_hotplug_reg = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL); + I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, dig_hotplug_reg); + + intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger, + dig_hotplug_reg, hpd_ilk, + ilk_port_hotplug_long_detect); + intel_hpd_irq_handler(dev, pin_mask, long_mask); + } if (de_iir & DE_AUX_CHANNEL_A) dp_aux_irq_handler(dev); @@ -3111,6 +3138,28 @@ static void spt_hpd_irq_setup(struct drm_device *dev) I915_WRITE(PCH_PORT_HOTPLUG2, hotplug); } +static void ilk_hpd_irq_setup(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 hotplug_irqs, hotplug, enabled_irqs; + + hotplug_irqs = DE_DP_A_HOTPLUG; + enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_ilk); + + ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs); + + /* + * Enable digital hotplug on the CPU, and configure the DP short pulse + * duration to 2ms (which is the minimum in the Display Port spec) + */ + hotplug = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL); + hotplug &= ~DIGITAL_PORTA_PULSE_DURATION_MASK; + hotplug |= DIGITAL_PORTA_HOTPLUG_ENABLE | DIGITAL_PORTA_PULSE_DURATION_2ms; + I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, hotplug); + + ibx_hpd_irq_setup(dev); +} + static void bxt_hpd_irq_setup(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -3209,8 +3258,9 @@ static int ironlake_irq_postinstall(struct drm_device *dev) DE_AUX_CHANNEL_A | DE_PIPEB_CRC_DONE | DE_PIPEA_CRC_DONE | DE_POISON); - extra_mask = DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT | - DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN; + extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT | + DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN | + DE_DP_A_HOTPLUG); } dev_priv->irq_mask = ~display_mask; @@ -4226,7 +4276,10 @@ void intel_irq_init(struct drm_i915_private *dev_priv) dev->driver->irq_uninstall = ironlake_irq_uninstall; dev->driver->enable_vblank = ironlake_enable_vblank; dev->driver->disable_vblank = ironlake_disable_vblank; - dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup; + if (INTEL_INFO(dev)->gen >= 7) + dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup; + else + dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup; } else { if (INTEL_INFO(dev_priv)->gen == 2) { dev->driver->irq_preinstall = i8xx_irq_preinstall; -- cgit v0.10.2 From 23bb4cb5122c2c6379be38aaa5c0fd6786ae6c3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 27 Aug 2015 23:56:04 +0300 Subject: drm/i915: Add port A HPD support for IVB/HSW MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As with ILK/SNB wire up the port A HPD on IVB/HSW. This might be more important on HSW with PSR. BSpec tells us that if the automagic link training performed by the hardware fails for some reason, we're going to get a short HPD and are supposed to re-train the link manyally. v2: 0 initialize pin_mask/long_mask due to intel_get_hpd_pins() changes Add a comment about the pulse duration bits being reserved on HSW+ like we have for LPT+ in ibx_hpd_irq_setup() Reviewed-by: Paulo Zanoni Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 57d23f0..8864aaf 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -49,6 +49,10 @@ static const u32 hpd_ilk[HPD_NUM_PINS] = { [HPD_PORT_A] = DE_DP_A_HOTPLUG, }; +static const u32 hpd_ivb[HPD_NUM_PINS] = { + [HPD_PORT_A] = DE_DP_A_HOTPLUG_IVB, +}; + static const u32 hpd_ibx[HPD_NUM_PINS] = { [HPD_CRT] = SDE_CRT_HOTPLUG, [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG, @@ -1946,6 +1950,19 @@ static void ivb_display_irq_handler(struct drm_device *dev, u32 de_iir) { struct drm_i915_private *dev_priv = dev->dev_private; enum pipe pipe; + u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG_IVB; + + if (hotplug_trigger) { + u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; + + dig_hotplug_reg = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL); + I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, dig_hotplug_reg); + + intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger, + dig_hotplug_reg, hpd_ivb, + ilk_port_hotplug_long_detect); + intel_hpd_irq_handler(dev, pin_mask, long_mask); + } if (de_iir & DE_ERR_INT_IVB) ivb_err_int_handler(dev); @@ -3143,14 +3160,20 @@ static void ilk_hpd_irq_setup(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; u32 hotplug_irqs, hotplug, enabled_irqs; - hotplug_irqs = DE_DP_A_HOTPLUG; - enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_ilk); + if (INTEL_INFO(dev)->gen >= 7) { + hotplug_irqs = DE_DP_A_HOTPLUG_IVB; + enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_ivb); + } else { + hotplug_irqs = DE_DP_A_HOTPLUG; + enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_ilk); + } ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs); /* * Enable digital hotplug on the CPU, and configure the DP short pulse * duration to 2ms (which is the minimum in the Display Port spec) + * The pulse duration bits are reserved on HSW+. */ hotplug = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL); hotplug &= ~DIGITAL_PORTA_PULSE_DURATION_MASK; @@ -3251,7 +3274,8 @@ static int ironlake_irq_postinstall(struct drm_device *dev) DE_PLANEB_FLIP_DONE_IVB | DE_PLANEA_FLIP_DONE_IVB | DE_AUX_CHANNEL_A_IVB); extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB | - DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB); + DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB | + DE_DP_A_HOTPLUG_IVB); } else { display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE | @@ -4276,10 +4300,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv) dev->driver->irq_uninstall = ironlake_irq_uninstall; dev->driver->enable_vblank = ironlake_enable_vblank; dev->driver->disable_vblank = ironlake_disable_vblank; - if (INTEL_INFO(dev)->gen >= 7) - dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup; - else - dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup; + dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup; } else { if (INTEL_INFO(dev_priv)->gen == 2) { dev->driver->irq_preinstall = i8xx_irq_preinstall; -- cgit v0.10.2 From 0b2eb33e5e2b4aaeaa786d551a1b5f08904a9bfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 27 Aug 2015 23:56:05 +0300 Subject: drm/i915: LPT:LP needs port A HPD enabled in both north and south MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the CPU and PCH are on the same package we must enabled the port A HPD also in the south hotplug register. To identify the package type we simply look at the PCH type: LPT-H means separate package, and LPT-LP means multi chip package (MCP). v2: Add comment and pimp commit message Reviewed-by: Paulo Zanoni Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 8864aaf..0aa87d0 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3131,6 +3131,12 @@ static void ibx_hpd_irq_setup(struct drm_device *dev) hotplug |= PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_2ms; hotplug |= PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_2ms; hotplug |= PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_2ms; + /* + * When CPU and PCH are on the same package, port A + * HPD must be enabled in both north and south. + */ + if (HAS_PCH_LPT_LP(dev)) + hotplug |= PORTA_HOTPLUG_ENABLE; I915_WRITE(PCH_PORT_HOTPLUG, hotplug); } -- cgit v0.10.2 From 3a3b3c7da37b35955c7c6a36a1f059d02f17eafb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 27 Aug 2015 23:56:06 +0300 Subject: drm/i915: Add port A HPD support for BDW MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wire up the port A HPD for BDW. Compared to earlier platforms the interrupt setup is a bit different, but basically everything else looks the same. v2: 0 initialize pin_mask/long_mask due to intel_get_hpd_pins() changes Check for BDW before processing the HPD to not break BXT Set found=true when processing port A HPD Sort out the mess I made of the irq setup in v1 Warn about bad irq mask vs. enable bits in bdw_update_port_irq() (Paulo) Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 0aa87d0..03c79f6 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -53,6 +53,10 @@ static const u32 hpd_ivb[HPD_NUM_PINS] = { [HPD_PORT_A] = DE_DP_A_HOTPLUG_IVB, }; +static const u32 hpd_bdw[HPD_NUM_PINS] = { + [HPD_PORT_A] = GEN8_PORT_DP_A_HOTPLUG, +}; + static const u32 hpd_ibx[HPD_NUM_PINS] = { [HPD_CRT] = SDE_CRT_HOTPLUG, [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG, @@ -371,6 +375,38 @@ void gen6_disable_rps_interrupts(struct drm_device *dev) } /** + * bdw_update_port_irq - update DE port interrupt + * @dev_priv: driver private + * @interrupt_mask: mask of interrupt bits to update + * @enabled_irq_mask: mask of interrupt bits to enable + */ +static void bdw_update_port_irq(struct drm_i915_private *dev_priv, + uint32_t interrupt_mask, + uint32_t enabled_irq_mask) +{ + uint32_t new_val; + uint32_t old_val; + + assert_spin_locked(&dev_priv->irq_lock); + + WARN_ON(enabled_irq_mask & ~interrupt_mask); + + if (WARN_ON(!intel_irqs_enabled(dev_priv))) + return; + + old_val = I915_READ(GEN8_DE_PORT_IMR); + + new_val = old_val; + new_val &= ~interrupt_mask; + new_val |= (~enabled_irq_mask & interrupt_mask); + + if (new_val != old_val) { + I915_WRITE(GEN8_DE_PORT_IMR, new_val); + POSTING_READ(GEN8_DE_PORT_IMR); + } +} + +/** * ibx_display_interrupt_update - update SDEIMR * @dev_priv: driver private * @interrupt_mask: mask of interrupt bits to update @@ -2145,10 +2181,24 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) tmp = I915_READ(GEN8_DE_PORT_IIR); if (tmp) { bool found = false; + u32 hotplug_trigger = tmp & GEN8_PORT_DP_A_HOTPLUG; I915_WRITE(GEN8_DE_PORT_IIR, tmp); ret = IRQ_HANDLED; + if (IS_BROADWELL(dev) && hotplug_trigger) { + u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; + + dig_hotplug_reg = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL); + I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, dig_hotplug_reg); + + intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger, + dig_hotplug_reg, hpd_bdw, + ilk_port_hotplug_long_detect); + intel_hpd_irq_handler(dev, pin_mask, long_mask); + found = true; + } + if (tmp & aux_mask) { dp_aux_irq_handler(dev); found = true; @@ -3166,15 +3216,22 @@ static void ilk_hpd_irq_setup(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; u32 hotplug_irqs, hotplug, enabled_irqs; - if (INTEL_INFO(dev)->gen >= 7) { + if (INTEL_INFO(dev)->gen >= 8) { + hotplug_irqs = GEN8_PORT_DP_A_HOTPLUG; + enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_bdw); + + bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs); + } else if (INTEL_INFO(dev)->gen >= 7) { hotplug_irqs = DE_DP_A_HOTPLUG_IVB; enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_ivb); + + ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs); } else { hotplug_irqs = DE_DP_A_HOTPLUG; enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_ilk); - } - ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs); + ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs); + } /* * Enable digital hotplug on the CPU, and configure the DP short pulse @@ -3486,24 +3543,29 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) { uint32_t de_pipe_masked = GEN8_PIPE_CDCLK_CRC_DONE; uint32_t de_pipe_enables; - int pipe; - u32 de_port_en = GEN8_AUX_CHANNEL_A; + u32 de_port_masked = GEN8_AUX_CHANNEL_A; + u32 de_port_enables; + enum pipe pipe; if (IS_GEN9(dev_priv)) { de_pipe_masked |= GEN9_PIPE_PLANE1_FLIP_DONE | GEN9_DE_PIPE_IRQ_FAULT_ERRORS; - de_port_en |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C | - GEN9_AUX_CHANNEL_D; - + de_port_masked |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C | + GEN9_AUX_CHANNEL_D; if (IS_BROXTON(dev_priv)) - de_port_en |= BXT_DE_PORT_GMBUS; - } else + de_port_masked |= BXT_DE_PORT_GMBUS; + } else { de_pipe_masked |= GEN8_PIPE_PRIMARY_FLIP_DONE | GEN8_DE_PIPE_IRQ_FAULT_ERRORS; + } de_pipe_enables = de_pipe_masked | GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN; + de_port_enables = de_port_masked; + if (IS_BROADWELL(dev_priv)) + de_port_enables |= GEN8_PORT_DP_A_HOTPLUG; + dev_priv->de_irq_mask[PIPE_A] = ~de_pipe_masked; dev_priv->de_irq_mask[PIPE_B] = ~de_pipe_masked; dev_priv->de_irq_mask[PIPE_C] = ~de_pipe_masked; @@ -3515,7 +3577,7 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) dev_priv->de_irq_mask[pipe], de_pipe_enables); - GEN5_IRQ_INIT(GEN8_DE_PORT_, ~de_port_en, de_port_en); + GEN5_IRQ_INIT(GEN8_DE_PORT_, ~de_port_masked, de_port_enables); } static int gen8_irq_postinstall(struct drm_device *dev) @@ -4298,7 +4360,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv) else if (HAS_PCH_SPT(dev)) dev_priv->display.hpd_irq_setup = spt_hpd_irq_setup; else - dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup; + dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup; } else if (HAS_PCH_SPLIT(dev)) { dev->driver->irq_handler = ironlake_irq_handler; dev->driver->irq_preinstall = ironlake_irq_reset; -- cgit v0.10.2 From 74c0b395fce4c807a49c404fb59462b22069b001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 27 Aug 2015 23:56:07 +0300 Subject: drm/i915: Add port A HPD support for SPT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On SKL the port A HPD has moved to the PCH. Hook it up. Reviewed-by: Paulo Zanoni Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 03c79f6..c3edcce 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -74,6 +74,7 @@ static const u32 hpd_cpt[HPD_NUM_PINS] = { }; static const u32 hpd_spt[HPD_NUM_PINS] = { + [HPD_PORT_A] = SDE_PORTA_HOTPLUG_SPT, [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT, [HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT, [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT, @@ -1316,6 +1317,22 @@ static bool spt_port_hotplug2_long_detect(enum port port, u32 val) } } +static bool spt_port_hotplug_long_detect(enum port port, u32 val) +{ + switch (port) { + case PORT_A: + return val & PORTA_HOTPLUG_LONG_DETECT; + case PORT_B: + return val & PORTB_HOTPLUG_LONG_DETECT; + case PORT_C: + return val & PORTC_HOTPLUG_LONG_DETECT; + case PORT_D: + return val & PORTD_HOTPLUG_LONG_DETECT; + default: + return false; + } +} + static bool ilk_port_hotplug_long_detect(enum port port, u32 val) { switch (port) { @@ -1899,7 +1916,7 @@ static void spt_irq_handler(struct drm_device *dev, u32 pch_iir) intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger, dig_hotplug_reg, hpd_spt, - pch_port_hotplug_long_detect); + spt_port_hotplug_long_detect); } if (hotplug2_trigger) { @@ -3203,7 +3220,7 @@ static void spt_hpd_irq_setup(struct drm_device *dev) /* Enable digital hotplug on the PCH */ hotplug = I915_READ(PCH_PORT_HOTPLUG); hotplug |= PORTD_HOTPLUG_ENABLE | PORTC_HOTPLUG_ENABLE | - PORTB_HOTPLUG_ENABLE; + PORTB_HOTPLUG_ENABLE | PORTA_HOTPLUG_ENABLE; I915_WRITE(PCH_PORT_HOTPLUG, hotplug); hotplug = I915_READ(PCH_PORT_HOTPLUG2); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 7eb76b7..689b428 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5984,6 +5984,7 @@ enum skl_disp_power_wells { #define SDE_AUXB_CPT (1 << 25) #define SDE_AUX_MASK_CPT (7 << 25) #define SDE_PORTE_HOTPLUG_SPT (1 << 25) +#define SDE_PORTA_HOTPLUG_SPT (1 << 24) #define SDE_PORTD_HOTPLUG_CPT (1 << 23) #define SDE_PORTC_HOTPLUG_CPT (1 << 22) #define SDE_PORTB_HOTPLUG_CPT (1 << 21) @@ -5997,7 +5998,8 @@ enum skl_disp_power_wells { #define SDE_HOTPLUG_MASK_SPT (SDE_PORTE_HOTPLUG_SPT | \ SDE_PORTD_HOTPLUG_CPT | \ SDE_PORTC_HOTPLUG_CPT | \ - SDE_PORTB_HOTPLUG_CPT) + SDE_PORTB_HOTPLUG_CPT | \ + SDE_PORTA_HOTPLUG_SPT) #define SDE_GMBUS_CPT (1 << 17) #define SDE_ERROR_CPT (1 << 16) #define SDE_AUDIO_CP_REQ_C_CPT (1 << 10) -- cgit v0.10.2 From 08d8a232aa5e145f995a98ac7f3de55e2fe6832b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 27 Aug 2015 23:56:08 +0300 Subject: drm/i915: Reinitialize HPD after runtime D3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Runtime suspends disabled all interrupts, so in order to get them back fully we need to also do the HPD irq setup on runtime resume. Except on VLV/CHV where the display interrupt initialization is part of the display power well powerup. Reviewed-by: Paulo Zanoni Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 4737d15..bdec64c 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1555,6 +1555,15 @@ static int intel_runtime_resume(struct device *device) gen6_update_ring_freq(dev); intel_runtime_pm_enable_interrupts(dev_priv); + + /* + * On VLV/CHV display interrupts are part of the display + * power well, so hpd is reinitialized from there. For + * everyone else do it here. + */ + if (!IS_VALLEYVIEW(dev_priv)) + intel_hpd_init(dev_priv); + intel_enable_gt_powersave(dev); if (ret) -- cgit v0.10.2 From cebd87a07748b649f22356efd56f478248aec300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 27 Aug 2015 23:56:09 +0300 Subject: drm/i915: Rewrite bxt_hpd_handler() to look like everyone else MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bxt_hpd_handler() looks different to everyone else for no good reason. Rewrite it to use the standard variable namees etc. Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index c3edcce..f0dedff 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2128,27 +2128,17 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) return ret; } -static void bxt_hpd_handler(struct drm_device *dev, uint32_t iir_status) +static void bxt_hpd_irq_handler(struct drm_device *dev, u32 hotplug_trigger) { - struct drm_i915_private *dev_priv = dev->dev_private; - u32 hp_control, hp_trigger; - u32 pin_mask = 0, long_mask = 0; - - /* Get the status */ - hp_trigger = iir_status & BXT_DE_PORT_HOTPLUG_MASK; - hp_control = I915_READ(BXT_HOTPLUG_CTL); - - /* Hotplug not enabled ? */ - if (!(hp_control & BXT_HOTPLUG_CTL_MASK)) { - DRM_ERROR("Interrupt when HPD disabled\n"); - return; - } + struct drm_i915_private *dev_priv = to_i915(dev); + u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; - /* Clear sticky bits in hpd status */ - I915_WRITE(BXT_HOTPLUG_CTL, hp_control); + dig_hotplug_reg = I915_READ(BXT_HOTPLUG_CTL); + I915_WRITE(BXT_HOTPLUG_CTL, dig_hotplug_reg); - intel_get_hpd_pins(&pin_mask, &long_mask, hp_trigger, hp_control, - hpd_bxt, bxt_port_hotplug_long_detect); + intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger, + dig_hotplug_reg, hpd_bxt, + bxt_port_hotplug_long_detect); intel_hpd_irq_handler(dev, pin_mask, long_mask); } @@ -2198,7 +2188,12 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) tmp = I915_READ(GEN8_DE_PORT_IIR); if (tmp) { bool found = false; - u32 hotplug_trigger = tmp & GEN8_PORT_DP_A_HOTPLUG; + u32 hotplug_trigger = 0; + + if (IS_BROXTON(dev_priv)) + hotplug_trigger = tmp & BXT_DE_PORT_HOTPLUG_MASK; + else if (IS_BROADWELL(dev_priv)) + hotplug_trigger = tmp & GEN8_PORT_DP_A_HOTPLUG; I915_WRITE(GEN8_DE_PORT_IIR, tmp); ret = IRQ_HANDLED; @@ -2221,8 +2216,8 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) found = true; } - if (IS_BROXTON(dev) && tmp & BXT_DE_PORT_HOTPLUG_MASK) { - bxt_hpd_handler(dev, tmp); + if (IS_BROXTON(dev) && hotplug_trigger) { + bxt_hpd_irq_handler(dev, hotplug_trigger); found = true; } -- cgit v0.10.2 From 40e5641086f6f64acb13ff6893cf82c4fb30a6d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 27 Aug 2015 23:56:10 +0300 Subject: drm/i915: Refactor the hpd irq handling functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A lot of the hpd irq handling is duplicated code, so refactor it a bit by observing that in several places the only difference is the hpd[] array. So pull the code to a few functions and pass in the hpd[] array from the caller. Another option would be to determine the correct array to use within the functions themselves, but somehow passing it in felt nicer. Further code reduction could be achieved by passing in the hotplug register offset, and the long pulse detection function pointer. But that didn't feel as good for some reason, so I left it at the middle ground. Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index f0dedff..d7a37a5 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1748,23 +1748,30 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) return ret; } +static void ibx_hpd_irq_handler(struct drm_device *dev, u32 hotplug_trigger, + const u32 hpd[HPD_NUM_PINS]) +{ + struct drm_i915_private *dev_priv = to_i915(dev); + u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; + + dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); + I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg); + + intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger, + dig_hotplug_reg, hpd, + pch_port_hotplug_long_detect); + + intel_hpd_irq_handler(dev, pin_mask, long_mask); +} + static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir) { struct drm_i915_private *dev_priv = dev->dev_private; int pipe; u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK; - if (hotplug_trigger) { - u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; - - dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); - I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg); - - intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger, - dig_hotplug_reg, hpd_ibx, - pch_port_hotplug_long_detect); - intel_hpd_irq_handler(dev, pin_mask, long_mask); - } + if (hotplug_trigger) + ibx_hpd_irq_handler(dev, hotplug_trigger, hpd_ibx); if (pch_iir & SDE_AUDIO_POWER_MASK) { int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >> @@ -1857,19 +1864,8 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir) int pipe; u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT; - if (hotplug_trigger) { - u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; - - dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); - I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg); - - intel_get_hpd_pins(&pin_mask, &long_mask, - hotplug_trigger, - dig_hotplug_reg, hpd_cpt, - pch_port_hotplug_long_detect); - - intel_hpd_irq_handler(dev, pin_mask, long_mask); - } + if (hotplug_trigger) + ibx_hpd_irq_handler(dev, hotplug_trigger, hpd_cpt); if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) { int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >> @@ -1937,23 +1933,30 @@ static void spt_irq_handler(struct drm_device *dev, u32 pch_iir) gmbus_irq_handler(dev); } +static void ilk_hpd_irq_handler(struct drm_device *dev, u32 hotplug_trigger, + const u32 hpd[HPD_NUM_PINS]) +{ + struct drm_i915_private *dev_priv = to_i915(dev); + u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; + + dig_hotplug_reg = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL); + I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, dig_hotplug_reg); + + intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger, + dig_hotplug_reg, hpd, + ilk_port_hotplug_long_detect); + + intel_hpd_irq_handler(dev, pin_mask, long_mask); +} + static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir) { struct drm_i915_private *dev_priv = dev->dev_private; enum pipe pipe; u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG; - if (hotplug_trigger) { - u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; - - dig_hotplug_reg = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL); - I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, dig_hotplug_reg); - - intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger, - dig_hotplug_reg, hpd_ilk, - ilk_port_hotplug_long_detect); - intel_hpd_irq_handler(dev, pin_mask, long_mask); - } + if (hotplug_trigger) + ilk_hpd_irq_handler(dev, hotplug_trigger, hpd_ilk); if (de_iir & DE_AUX_CHANNEL_A) dp_aux_irq_handler(dev); @@ -2005,17 +2008,8 @@ static void ivb_display_irq_handler(struct drm_device *dev, u32 de_iir) enum pipe pipe; u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG_IVB; - if (hotplug_trigger) { - u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; - - dig_hotplug_reg = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL); - I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, dig_hotplug_reg); - - intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger, - dig_hotplug_reg, hpd_ivb, - ilk_port_hotplug_long_detect); - intel_hpd_irq_handler(dev, pin_mask, long_mask); - } + if (hotplug_trigger) + ilk_hpd_irq_handler(dev, hotplug_trigger, hpd_ivb); if (de_iir & DE_ERR_INT_IVB) ivb_err_int_handler(dev); @@ -2128,7 +2122,8 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) return ret; } -static void bxt_hpd_irq_handler(struct drm_device *dev, u32 hotplug_trigger) +static void bxt_hpd_irq_handler(struct drm_device *dev, u32 hotplug_trigger, + const u32 hpd[HPD_NUM_PINS]) { struct drm_i915_private *dev_priv = to_i915(dev); u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; @@ -2137,8 +2132,9 @@ static void bxt_hpd_irq_handler(struct drm_device *dev, u32 hotplug_trigger) I915_WRITE(BXT_HOTPLUG_CTL, dig_hotplug_reg); intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger, - dig_hotplug_reg, hpd_bxt, + dig_hotplug_reg, hpd, bxt_port_hotplug_long_detect); + intel_hpd_irq_handler(dev, pin_mask, long_mask); } @@ -2198,26 +2194,16 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) I915_WRITE(GEN8_DE_PORT_IIR, tmp); ret = IRQ_HANDLED; - if (IS_BROADWELL(dev) && hotplug_trigger) { - u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; - - dig_hotplug_reg = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL); - I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, dig_hotplug_reg); - - intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger, - dig_hotplug_reg, hpd_bdw, - ilk_port_hotplug_long_detect); - intel_hpd_irq_handler(dev, pin_mask, long_mask); - found = true; - } - if (tmp & aux_mask) { dp_aux_irq_handler(dev); found = true; } - if (IS_BROXTON(dev) && hotplug_trigger) { - bxt_hpd_irq_handler(dev, hotplug_trigger); + if (hotplug_trigger) { + if (IS_BROXTON(dev)) + bxt_hpd_irq_handler(dev, hotplug_trigger, hpd_bxt); + else + ilk_hpd_irq_handler(dev, hotplug_trigger, hpd_bdw); found = true; } -- cgit v0.10.2 From a52bb15bfad09115cff2433e76b164be94c42af5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 27 Aug 2015 23:56:11 +0300 Subject: drm/i915: Rewrite BXT HPD code to conform to pre-existing style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rewrite the BXT hpd setup to match the way we do it on other platforms: - Throw out BXT_HOTPLUG_CTL since it's the same as PCH_PORT_HOTPLUG - Enable the HPD bits in the DE port IER in gen8_de_irq_postinstall() - Update DE port IMR using bdw_update_port_irq() Also throw out port D from bxt_port_hotplug_long_detect() since BXT only goes up to C. Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index d7a37a5..218fe12 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1300,8 +1300,6 @@ static bool bxt_port_hotplug_long_detect(enum port port, u32 val) return val & PORTB_HOTPLUG_LONG_DETECT; case PORT_C: return val & PORTC_HOTPLUG_LONG_DETECT; - case PORT_D: - return val & PORTD_HOTPLUG_LONG_DETECT; default: return false; } @@ -2128,8 +2126,8 @@ static void bxt_hpd_irq_handler(struct drm_device *dev, u32 hotplug_trigger, struct drm_i915_private *dev_priv = to_i915(dev); u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; - dig_hotplug_reg = I915_READ(BXT_HOTPLUG_CTL); - I915_WRITE(BXT_HOTPLUG_CTL, dig_hotplug_reg); + dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); + I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg); intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger, dig_hotplug_reg, hpd, @@ -3247,27 +3245,17 @@ static void ilk_hpd_irq_setup(struct drm_device *dev) static void bxt_hpd_irq_setup(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - u32 hotplug_port; - u32 hotplug_ctrl; - - hotplug_port = intel_hpd_enabled_irqs(dev, hpd_bxt); - - hotplug_ctrl = I915_READ(BXT_HOTPLUG_CTL) & ~BXT_HOTPLUG_CTL_MASK; + u32 hotplug_irqs, hotplug, enabled_irqs; - if (hotplug_port & BXT_DE_PORT_HP_DDIA) - hotplug_ctrl |= BXT_DDIA_HPD_ENABLE; - if (hotplug_port & BXT_DE_PORT_HP_DDIB) - hotplug_ctrl |= BXT_DDIB_HPD_ENABLE; - if (hotplug_port & BXT_DE_PORT_HP_DDIC) - hotplug_ctrl |= BXT_DDIC_HPD_ENABLE; - I915_WRITE(BXT_HOTPLUG_CTL, hotplug_ctrl); + enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_bxt); + hotplug_irqs = BXT_DE_PORT_HOTPLUG_MASK; - hotplug_ctrl = I915_READ(GEN8_DE_PORT_IMR) & ~hotplug_port; - I915_WRITE(GEN8_DE_PORT_IMR, hotplug_ctrl); + bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs); - hotplug_ctrl = I915_READ(GEN8_DE_PORT_IER) | hotplug_port; - I915_WRITE(GEN8_DE_PORT_IER, hotplug_ctrl); - POSTING_READ(GEN8_DE_PORT_IER); + hotplug = I915_READ(PCH_PORT_HOTPLUG); + hotplug |= PORTC_HOTPLUG_ENABLE | PORTB_HOTPLUG_ENABLE | + PORTA_HOTPLUG_ENABLE; + I915_WRITE(PCH_PORT_HOTPLUG, hotplug); } static void ibx_irq_postinstall(struct drm_device *dev) @@ -3561,7 +3549,9 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) GEN8_PIPE_FIFO_UNDERRUN; de_port_enables = de_port_masked; - if (IS_BROADWELL(dev_priv)) + if (IS_BROXTON(dev_priv)) + de_port_enables |= BXT_DE_PORT_HOTPLUG_MASK; + else if (IS_BROADWELL(dev_priv)) de_port_enables |= GEN8_PORT_DP_A_HOTPLUG; dev_priv->de_irq_mask[PIPE_A] = ~de_pipe_masked; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 689b428..5811eeb 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5797,21 +5797,6 @@ enum skl_disp_power_wells { #define GEN8_PCU_IIR 0x444e8 #define GEN8_PCU_IER 0x444ec -/* BXT hotplug control */ -#define BXT_HOTPLUG_CTL 0xC4030 -#define BXT_DDIA_HPD_ENABLE (1 << 28) -#define BXT_DDIA_HPD_STATUS (3 << 24) -#define BXT_DDIC_HPD_ENABLE (1 << 12) -#define BXT_DDIC_HPD_STATUS (3 << 8) -#define BXT_DDIB_HPD_ENABLE (1 << 4) -#define BXT_DDIB_HPD_STATUS (3 << 0) -#define BXT_HOTPLUG_CTL_MASK (BXT_DDIA_HPD_ENABLE | \ - BXT_DDIB_HPD_ENABLE | \ - BXT_DDIC_HPD_ENABLE) -#define BXT_HPD_STATUS_MASK (BXT_DDIA_HPD_STATUS | \ - BXT_DDIB_HPD_STATUS | \ - BXT_DDIC_HPD_STATUS) - #define ILK_DISPLAY_CHICKEN2 0x42004 /* Required on all Ironlake and Sandybridge according to the B-Spec. */ #define ILK_ELPIN_409_SELECT (1 << 25) -- cgit v0.10.2 From 58f2cf241fb98414e2e35fc3d4d0494eb30b3245 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 28 Aug 2015 22:59:08 +0300 Subject: drm/i915: Don't call intel_get_hpd_pins() when there's no hotplug interrupt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On GMCH plaforms we are now getting the following spew on aux interrupts: [drm:intel_get_hpd_pins] hotplug event received, stat 0x00000000, dig 0x00000000, pins 0x00000000 [drm:intel_get_hpd_pins] hotplug event received, stat 0x00000000, dig 0x00000000, pins 0x00000000 [drm:intel_get_hpd_pins] hotplug event received, stat 0x00000000, dig 0x00000000, pins 0x00000000 [drm:intel_get_hpd_pins] hotplug event received, stat 0x00000000, dig 0x00000000, pins 0x00000000 [drm:intel_get_hpd_pins] hotplug event received, stat 0x00000000, dig 0x00000000, pins 0x00000000 [drm:intel_dp_aux_ch] dp_aux_ch timeout status 0x71450064 Prevent it by not calling intel_get_hpd_pins() unless one of the HPD interrupt bits are actually set. I already fixed similar annoyance once with 4bca26d0a6518d51a9abe64fbde4b12f04c74053 drm/i915: Use HOTPLUG_INT_STATUS_G4X on VLV/CHV but another source for it got added in fd63e2a972c670887e5e8a08440111d3812c0996 drm/i915: combine i9xx_get_hpd_pins and pch_get_hpd_pins due to pch_get_hpd_pins() being chosen over i9xx_get_hpd_pins() to serve as the new unified piece of code. pch_get_hpd_pins() had the debug print, and i9xx_get_hpd_pins() didn't. Cc: Imre Deak Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 218fe12..ff543a4 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1639,20 +1639,26 @@ static void i9xx_hpd_irq_handler(struct drm_device *dev) if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) { u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X; - intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger, - hotplug_trigger, hpd_status_g4x, - i9xx_port_hotplug_long_detect); - intel_hpd_irq_handler(dev, pin_mask, long_mask); + if (hotplug_trigger) { + intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger, + hotplug_trigger, hpd_status_g4x, + i9xx_port_hotplug_long_detect); + + intel_hpd_irq_handler(dev, pin_mask, long_mask); + } if (hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X) dp_aux_irq_handler(dev); } else { u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915; - intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger, - hotplug_trigger, hpd_status_g4x, - i9xx_port_hotplug_long_detect); - intel_hpd_irq_handler(dev, pin_mask, long_mask); + if (hotplug_trigger) { + intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger, + hotplug_trigger, hpd_status_g4x, + i9xx_port_hotplug_long_detect); + + intel_hpd_irq_handler(dev, pin_mask, long_mask); + } } } -- cgit v0.10.2 From 395ab7541a0e141ffbde127b534e44f28d39a050 Mon Sep 17 00:00:00 2001 From: "Kumar, Mahesh" Date: Thu, 3 Sep 2015 16:17:08 +0530 Subject: drm/i915/skl: Avoid using un-initialized bits_per_pixel Don't rely on fb->bits_per_pixel as intel_framebuffer_init is not filling bits_per_pixel field of fb-struct for YUV pixel format. This leads to divide by zero error during watermark calculation. Signed-off-by: Kumar, Mahesh Cc: Konduru, Chandra Reviewed-by: Sonika Jindal Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index ea49661..1b90f03 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3170,7 +3170,8 @@ static void skl_compute_wm_pipe_parameters(struct drm_crtc *crtc, if (fb) { p->plane[0].enabled = true; p->plane[0].bytes_per_pixel = fb->pixel_format == DRM_FORMAT_NV12 ? - drm_format_plane_cpp(fb->pixel_format, 1) : fb->bits_per_pixel / 8; + drm_format_plane_cpp(fb->pixel_format, 1) : + drm_format_plane_cpp(fb->pixel_format, 0); p->plane[0].y_bytes_per_pixel = fb->pixel_format == DRM_FORMAT_NV12 ? drm_format_plane_cpp(fb->pixel_format, 0) : 0; p->plane[0].tiling = fb->modifier[0]; -- cgit v0.10.2 From ea916ea057299f66e774c9131e269df070a84779 Mon Sep 17 00:00:00 2001 From: "Kumar, Mahesh" Date: Thu, 3 Sep 2015 16:17:09 +0530 Subject: drm/i915/skl+: Add YUV pixel format in Capability list GEN >= 9 supports YUV format for all planes, but it's not exported in Capability list of primary plane. Add YUV formats in skl_primary_formats list. Testcase: igt/kms_universal_plane.c Signed-off-by: Kumar, Mahesh Cc: Konduru, Chandra Reviewed-by: Sonika Jindal Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 888175c..6985f6f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -72,6 +72,10 @@ static const uint32_t skl_primary_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_XRGB2101010, DRM_FORMAT_XBGR2101010, + DRM_FORMAT_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_UYVY, + DRM_FORMAT_VYUY, }; /* Cursor formats */ -- cgit v0.10.2 From 3a41a05d70b4fb455256fd3a8348e186f156c310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Winiarski?= Date: Thu, 3 Sep 2015 19:22:18 +0200 Subject: drm/i915/gtt: Avoid calling kcalloc in a loop when allocating temp bitmaps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On each call to gen8_alloc_va_range_3lvl we're allocating temporary bitmaps needed for error handling. Unfortunately, when we increase address space size (48b ppgtt) we do additional (512 - 4) calls to kcalloc, increasing latency between exec and actual start of execution on the GPU. Let's just do a single kcalloc, we can also drop the size from free_gen8_temp_bitmaps since it's no longer used. v2: Use GFP_TEMPORARY to make the allocations reclaimable. v3: Drop the 2D array, just allocate a single block. v4: Rebase to handle gen8_preallocate_top_level_pdps. v5: Align misaligned bracket. Cc: Chris Wilson Cc: Mika Kuoppala Cc: Michel Thierry Signed-off-by: Michał Winiarski Reviewed-by: Chris Wilson [danvet: Correct kcalloc arguments as suggested by Chris.] Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index bdb7adc..8786281 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1164,13 +1164,8 @@ unwind_out: } static void -free_gen8_temp_bitmaps(unsigned long *new_pds, unsigned long **new_pts, - uint32_t pdpes) +free_gen8_temp_bitmaps(unsigned long *new_pds, unsigned long *new_pts) { - int i; - - for (i = 0; i < pdpes; i++) - kfree(new_pts[i]); kfree(new_pts); kfree(new_pds); } @@ -1180,29 +1175,20 @@ free_gen8_temp_bitmaps(unsigned long *new_pds, unsigned long **new_pts, */ static int __must_check alloc_gen8_temp_bitmaps(unsigned long **new_pds, - unsigned long ***new_pts, + unsigned long **new_pts, uint32_t pdpes) { - int i; unsigned long *pds; - unsigned long **pts; + unsigned long *pts; - pds = kcalloc(BITS_TO_LONGS(pdpes), sizeof(unsigned long), GFP_KERNEL); + pds = kcalloc(BITS_TO_LONGS(pdpes), sizeof(unsigned long), GFP_TEMPORARY); if (!pds) return -ENOMEM; - pts = kcalloc(pdpes, sizeof(unsigned long *), GFP_KERNEL); - if (!pts) { - kfree(pds); - return -ENOMEM; - } - - for (i = 0; i < pdpes; i++) { - pts[i] = kcalloc(BITS_TO_LONGS(I915_PDES), - sizeof(unsigned long), GFP_KERNEL); - if (!pts[i]) - goto err_out; - } + pts = kcalloc(pdpes, BITS_TO_LONGS(I915_PDES) * sizeof(unsigned long), + GFP_TEMPORARY); + if (!pts) + goto err_out; *new_pds = pds; *new_pts = pts; @@ -1210,7 +1196,7 @@ int __must_check alloc_gen8_temp_bitmaps(unsigned long **new_pds, return 0; err_out: - free_gen8_temp_bitmaps(pds, pts, pdpes); + free_gen8_temp_bitmaps(pds, pts); return -ENOMEM; } @@ -1231,7 +1217,7 @@ static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm, { struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); - unsigned long *new_page_dirs, **new_page_tables; + unsigned long *new_page_dirs, *new_page_tables; struct drm_device *dev = vm->dev; struct i915_page_directory *pd; const uint64_t orig_start = start; @@ -1258,14 +1244,14 @@ static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm, ret = gen8_ppgtt_alloc_page_directories(vm, pdp, start, length, new_page_dirs); if (ret) { - free_gen8_temp_bitmaps(new_page_dirs, new_page_tables, pdpes); + free_gen8_temp_bitmaps(new_page_dirs, new_page_tables); return ret; } /* For every page directory referenced, allocate page tables */ gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) { ret = gen8_ppgtt_alloc_pagetabs(vm, pd, start, length, - new_page_tables[pdpe]); + new_page_tables + pdpe * BITS_TO_LONGS(I915_PDES)); if (ret) goto err_out; } @@ -1316,20 +1302,21 @@ static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm, gen8_setup_page_directory(ppgtt, pdp, pd, pdpe); } - free_gen8_temp_bitmaps(new_page_dirs, new_page_tables, pdpes); + free_gen8_temp_bitmaps(new_page_dirs, new_page_tables); mark_tlbs_dirty(ppgtt); return 0; err_out: while (pdpe--) { - for_each_set_bit(temp, new_page_tables[pdpe], I915_PDES) + for_each_set_bit(temp, new_page_tables + pdpe * + BITS_TO_LONGS(I915_PDES), I915_PDES) free_pt(dev, pdp->page_directory[pdpe]->page_table[temp]); } for_each_set_bit(pdpe, new_page_dirs, pdpes) free_pd(dev, pdp->page_directory[pdpe]); - free_gen8_temp_bitmaps(new_page_dirs, new_page_tables, pdpes); + free_gen8_temp_bitmaps(new_page_dirs, new_page_tables); mark_tlbs_dirty(ppgtt); return ret; } @@ -1481,7 +1468,7 @@ static void gen8_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m) static int gen8_preallocate_top_level_pdps(struct i915_hw_ppgtt *ppgtt) { - unsigned long *new_page_dirs, **new_page_tables; + unsigned long *new_page_dirs, *new_page_tables; uint32_t pdpes = I915_PDPES_PER_PDP(dev); int ret; @@ -1501,7 +1488,7 @@ static int gen8_preallocate_top_level_pdps(struct i915_hw_ppgtt *ppgtt) if (!ret) *ppgtt->pdp.used_pdpes = *new_page_dirs; - free_gen8_temp_bitmaps(new_page_dirs, new_page_tables, pdpes); + free_gen8_temp_bitmaps(new_page_dirs, new_page_tables); return ret; } -- cgit v0.10.2 From b4834a508a1c25773c929c3d8eb7a29ad1041e19 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Wed, 2 Sep 2015 15:19:24 -0700 Subject: drm/i915: Future proof interrupt handler. These functions are already being called for gen >= 9, so let's be sure when this happens we use whatever is there already for the latest platform. No functional change. Signed-off-by: Rodrigo Vivi Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index ff543a4..ca6d806 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2155,7 +2155,7 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) if (!intel_irqs_enabled(dev_priv)) return IRQ_NONE; - if (IS_GEN9(dev)) + if (INTEL_INFO(dev_priv)->gen >= 9) aux_mask |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C | GEN9_AUX_CHANNEL_D; @@ -2238,7 +2238,7 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) intel_pipe_handle_vblank(dev, pipe)) intel_check_page_flip(dev, pipe); - if (IS_GEN9(dev)) + if (INTEL_INFO(dev_priv)->gen >= 9) flip_done = pipe_iir & GEN9_PIPE_PLANE1_FLIP_DONE; else flip_done = pipe_iir & GEN8_PIPE_PRIMARY_FLIP_DONE; @@ -2256,7 +2256,7 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) pipe); - if (IS_GEN9(dev)) + if (INTEL_INFO(dev_priv)->gen >= 9) fault_errors = pipe_iir & GEN9_DE_PIPE_IRQ_FAULT_ERRORS; else fault_errors = pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS; @@ -3539,7 +3539,7 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) u32 de_port_enables; enum pipe pipe; - if (IS_GEN9(dev_priv)) { + if (INTEL_INFO(dev_priv)->gen >= 9) { de_pipe_masked |= GEN9_PIPE_PLANE1_FLIP_DONE | GEN9_DE_PIPE_IRQ_FAULT_ERRORS; de_port_masked |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C | -- cgit v0.10.2 From 22cc27bb7a47cf6ad33b983539b14bc46e65f9b2 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 3 Sep 2015 14:38:00 -0700 Subject: drm/i915: Future proof uncore_init. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unless future specs tells otherwise we can assume future gens inherit some stuff from the previous so let's handle missed cases when we know tehy should't be there and assume default equals newest one. No functional changes. v2: Remove useless case as pointed out by Ville. Cc: Ville Syrjälä Signed-off-by: Rodrigo Vivi Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index dec20d6..440e2a5 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1202,8 +1202,6 @@ void intel_uncore_init(struct drm_device *dev) switch (INTEL_INFO(dev)->gen) { default: - MISSING_CASE(INTEL_INFO(dev)->gen); - return; case 9: ASSIGN_WRITE_MMIO_VFUNCS(gen9); ASSIGN_READ_MMIO_VFUNCS(gen9); -- cgit v0.10.2 From 1c132b44f0eabaaf801e79a3e4b98770431a4274 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Wed, 2 Sep 2015 15:19:26 -0700 Subject: drm/i915: Future proof panel fitter. This is another case where we can consider the default is the newest available and not actually a missed case. No functional change. Signed-off-by: Rodrigo Vivi Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 6985f6f..b59717a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4919,12 +4919,10 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) intel_ddi_enable_pipe_clock(intel_crtc); - if (INTEL_INFO(dev)->gen == 9) + if (INTEL_INFO(dev)->gen >= 9) skylake_pfit_enable(intel_crtc); - else if (INTEL_INFO(dev)->gen < 9) - ironlake_pfit_enable(intel_crtc); else - MISSING_CASE(INTEL_INFO(dev)->gen); + ironlake_pfit_enable(intel_crtc); /* * On ILK+ LUT must be loaded before the pipe is running but with @@ -5056,12 +5054,10 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder); - if (INTEL_INFO(dev)->gen == 9) + if (INTEL_INFO(dev)->gen >= 9) skylake_scaler_disable(intel_crtc); - else if (INTEL_INFO(dev)->gen < 9) - ironlake_pfit_disable(intel_crtc); else - MISSING_CASE(INTEL_INFO(dev)->gen); + ironlake_pfit_disable(intel_crtc); intel_ddi_disable_pipe_clock(intel_crtc); @@ -9784,12 +9780,10 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, } if (intel_display_power_is_enabled(dev_priv, pfit_domain)) { - if (INTEL_INFO(dev)->gen == 9) + if (INTEL_INFO(dev)->gen >= 9) skylake_get_pfit_config(crtc, pipe_config); - else if (INTEL_INFO(dev)->gen < 9) - ironlake_get_pfit_config(crtc, pipe_config); else - MISSING_CASE(INTEL_INFO(dev)->gen); + ironlake_get_pfit_config(crtc, pipe_config); } if (IS_HASWELL(dev)) -- cgit v0.10.2 From bc5133d595a0ddfaaa5edb4b077f44d92cc8fb0d Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 3 Sep 2015 11:16:07 +0300 Subject: drm/i915/dp: move TPS3 logic to where it's used MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no need to have a separate flag for tps3 as the information is only used at one location. Move the logic there to make it easier to follow. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index f8f4d99..9a6fb5d 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3812,13 +3812,25 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) void intel_dp_complete_link_train(struct intel_dp *intel_dp) { + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = dig_port->base.base.dev; bool channel_eq = false; int tries, cr_tries; uint32_t DP = intel_dp->DP; uint32_t training_pattern = DP_TRAINING_PATTERN_2; - /* Training Pattern 3 for HBR2 or 1.2 devices that support it*/ - if (intel_dp->link_rate == 540000 || intel_dp->use_tps3) + /* + * Training Pattern 3 for HBR2 or 1.2 devices that support it. + * + * Intel platforms that support HBR2 also support TPS3. TPS3 support is + * also mandatory for downstream devices that support HBR2. + * + * Due to WaDisableHBR2 SKL < B0 is the only exception where TPS3 is + * supported but still not enabled. + */ + if (intel_dp->link_rate == 540000 || + (intel_dp_source_supports_hbr2(dev) && + drm_dp_tps3_supported(intel_dp->dpcd))) training_pattern = DP_TRAINING_PATTERN_3; /* channel equalization */ @@ -4000,18 +4012,9 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) } } - /* Training Pattern 3 support, Intel platforms that support HBR2 alone - * have support for TP3 hence that check is used along with dpcd check - * to ensure TP3 can be enabled. - * SKL < B0: due it's WaDisableHBR2 is the only exception where TP3 is - * supported but still not enabled. - */ - if (drm_dp_tps3_supported(intel_dp->dpcd) && - intel_dp_source_supports_hbr2(dev)) { - intel_dp->use_tps3 = true; - DRM_DEBUG_KMS("Displayport TPS3 supported\n"); - } else - intel_dp->use_tps3 = false; + DRM_DEBUG_KMS("Display Port TPS3 support: source %s, sink %s\n", + intel_dp_source_supports_hbr2(dev) ? "yes" : "no", + drm_dp_tps3_supported(intel_dp->dpcd) ? "yes" : "no"); /* Intermediate frequency support */ if (is_edp(intel_dp) && diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 40e825d..2bdd544 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -746,7 +746,6 @@ struct intel_dp { enum pipe pps_pipe; struct edp_power_seq pps_delays; - bool use_tps3; bool can_mst; /* this port supports mst */ bool is_mst; int active_mst_links; -- cgit v0.10.2 From 1da7d7131c35cde83f1bab8ec732b57b69bef814 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 3 Sep 2015 11:16:08 +0300 Subject: drm/i915: ignore link rate in TPS3 selection TPS3 is mandatory for downstream devices that support HBR2, and Intel platforms that support HBR2 also support TPS3. Whenever TPS3 is supported by both the source and sink, it should be used. In other words, whenever the source and sink are capable of 5.4 Gbps link, we should anyway go for TPS3, regardless of the link rate being selected. Log an error if the sink has advertized HBR2 capability without TPS3 capability. Reviewed-by: Chris Wilson Signed-off-by: Jani Nikula Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 9a6fb5d..44e753d 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3828,10 +3828,11 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) * Due to WaDisableHBR2 SKL < B0 is the only exception where TPS3 is * supported but still not enabled. */ - if (intel_dp->link_rate == 540000 || - (intel_dp_source_supports_hbr2(dev) && - drm_dp_tps3_supported(intel_dp->dpcd))) + if (intel_dp_source_supports_hbr2(dev) && + drm_dp_tps3_supported(intel_dp->dpcd)) training_pattern = DP_TRAINING_PATTERN_3; + else if (intel_dp->link_rate == 540000) + DRM_ERROR("5.4 Gbps link rate without HBR2/TPS3 support\n"); /* channel equalization */ if (!intel_dp_set_link_train(intel_dp, &DP, -- cgit v0.10.2 From 742f491d2c204204086d2bc85cc5100daa6ff336 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 3 Sep 2015 11:16:09 +0300 Subject: drm/i915: use the yesno helper for logging Reviewed-by: Chris Wilson Signed-off-by: Jani Nikula Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 4563f8b..41629fa 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1382,17 +1382,16 @@ static int ironlake_drpc_info(struct seq_file *m) intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); - seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ? - "yes" : "no"); + seq_printf(m, "HD boost: %s\n", yesno(rgvmodectl & MEMMODE_BOOST_EN)); seq_printf(m, "Boost freq: %d\n", (rgvmodectl & MEMMODE_BOOST_FREQ_MASK) >> MEMMODE_BOOST_FREQ_SHIFT); seq_printf(m, "HW control enabled: %s\n", - rgvmodectl & MEMMODE_HWIDLE_EN ? "yes" : "no"); + yesno(rgvmodectl & MEMMODE_HWIDLE_EN)); seq_printf(m, "SW control enabled: %s\n", - rgvmodectl & MEMMODE_SWMODE_EN ? "yes" : "no"); + yesno(rgvmodectl & MEMMODE_SWMODE_EN)); seq_printf(m, "Gated voltage change: %s\n", - rgvmodectl & MEMMODE_RCLK_GATE ? "yes" : "no"); + yesno(rgvmodectl & MEMMODE_RCLK_GATE)); seq_printf(m, "Starting frequency: P%d\n", (rgvmodectl & MEMMODE_FSTART_MASK) >> MEMMODE_FSTART_SHIFT); seq_printf(m, "Max P-state: P%d\n", @@ -1401,7 +1400,7 @@ static int ironlake_drpc_info(struct seq_file *m) seq_printf(m, "RS1 VID: %d\n", (crstandvid & 0x3f)); seq_printf(m, "RS2 VID: %d\n", ((crstandvid >> 8) & 0x3f)); seq_printf(m, "Render standby enabled: %s\n", - (rstdbyctl & RCX_SW_EXIT) ? "no" : "yes"); + yesno(!(rstdbyctl & RCX_SW_EXIT))); seq_puts(m, "Current RS state: "); switch (rstdbyctl & RSX_STATUS_MASK) { case RSX_STATUS_ON: @@ -2844,8 +2843,7 @@ static void intel_dp_info(struct seq_file *m, struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base); seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]); - seq_printf(m, "\taudio support: %s\n", intel_dp->has_audio ? "yes" : - "no"); + seq_printf(m, "\taudio support: %s\n", yesno(intel_dp->has_audio)); if (intel_encoder->type == INTEL_OUTPUT_EDP) intel_panel_info(m, &intel_connector->panel); } @@ -2856,8 +2854,7 @@ static void intel_hdmi_info(struct seq_file *m, struct intel_encoder *intel_encoder = intel_connector->encoder; struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&intel_encoder->base); - seq_printf(m, "\taudio support: %s\n", intel_hdmi->has_audio ? "yes" : - "no"); + seq_printf(m, "\taudio support: %s\n", yesno(intel_hdmi->has_audio)); } static void intel_lvds_info(struct seq_file *m, diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 44e753d..45ab25e 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4014,8 +4014,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) } DRM_DEBUG_KMS("Display Port TPS3 support: source %s, sink %s\n", - intel_dp_source_supports_hbr2(dev) ? "yes" : "no", - drm_dp_tps3_supported(intel_dp->dpcd) ? "yes" : "no"); + yesno(intel_dp_source_supports_hbr2(dev)), + yesno(drm_dp_tps3_supported(intel_dp->dpcd))); /* Intermediate frequency support */ if (is_edp(intel_dp) && diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 1b90f03..79cd987 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5550,7 +5550,7 @@ static void cherryview_enable_rps(struct drm_device *dev) /* RPS code assumes GPLL is used */ WARN_ONCE((val & GPLLENABLE) == 0, "GPLL not enabled\n"); - DRM_DEBUG_DRIVER("GPLL enabled? %s\n", val & GPLLENABLE ? "yes" : "no"); + DRM_DEBUG_DRIVER("GPLL enabled? %s\n", yesno(val & GPLLENABLE)); DRM_DEBUG_DRIVER("GPU status: 0x%08x\n", val); dev_priv->rps.cur_freq = (val >> 8) & 0xff; @@ -5640,7 +5640,7 @@ static void valleyview_enable_rps(struct drm_device *dev) /* RPS code assumes GPLL is used */ WARN_ONCE((val & GPLLENABLE) == 0, "GPLL not enabled\n"); - DRM_DEBUG_DRIVER("GPLL enabled? %s\n", val & GPLLENABLE ? "yes" : "no"); + DRM_DEBUG_DRIVER("GPLL enabled? %s\n", yesno(val & GPLLENABLE)); DRM_DEBUG_DRIVER("GPU status: 0x%08x\n", val); dev_priv->rps.cur_freq = (val >> 8) & 0xff; -- cgit v0.10.2 From 01101fa7cc85fffc95798d1f67970dad96063fc6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 3 Sep 2015 13:01:39 +0100 Subject: drm/i915: Refactor common ringbuffer allocation code A small, very small, step to sharing the duplicate code between execlists and legacy submission engines, starting with the ringbuffer allocation code. Signed-off-by: Chris Wilson Cc: Arun Siluvery Cc: Mika Kuoppala Cc: Dave Gordon Reviewed-by: Paulo Zanoni Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 40cbba4..28a712e 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -2340,8 +2340,7 @@ void intel_lr_context_free(struct intel_context *ctx) i915_gem_object_ggtt_unpin(ctx_obj); } WARN_ON(ctx->engine[ring->id].pin_count); - intel_destroy_ringbuffer_obj(ringbuf); - kfree(ringbuf); + intel_ringbuffer_free(ringbuf); drm_gem_object_unreference(&ctx_obj->base); } } @@ -2442,42 +2441,20 @@ int intel_lr_context_deferred_create(struct intel_context *ctx, I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE); } - ringbuf = kzalloc(sizeof(*ringbuf), GFP_KERNEL); - if (!ringbuf) { - DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s\n", - ring->name); - ret = -ENOMEM; + ringbuf = intel_engine_create_ringbuffer(ring, 4 * PAGE_SIZE); + if (IS_ERR(ringbuf)) { + ret = PTR_ERR(ringbuf); goto error_unpin_ctx; } - ringbuf->ring = ring; - - ringbuf->size = 4 * PAGE_SIZE; - ringbuf->effective_size = ringbuf->size; - ringbuf->head = 0; - ringbuf->tail = 0; - ringbuf->last_retired_head = -1; - intel_ring_update_space(ringbuf); - - if (ringbuf->obj == NULL) { - ret = intel_alloc_ringbuffer_obj(dev, ringbuf); + if (is_global_default_ctx) { + ret = intel_pin_and_map_ringbuffer_obj(dev, ringbuf); if (ret) { - DRM_DEBUG_DRIVER( - "Failed to allocate ringbuffer obj %s: %d\n", - ring->name, ret); - goto error_free_rbuf; + DRM_ERROR( + "Failed to pin and map ringbuffer %s: %d\n", + ring->name, ret); + goto error_ringbuf; } - - if (is_global_default_ctx) { - ret = intel_pin_and_map_ringbuffer_obj(dev, ringbuf); - if (ret) { - DRM_ERROR( - "Failed to pin and map ringbuffer %s: %d\n", - ring->name, ret); - goto error_destroy_rbuf; - } - } - } ret = populate_lr_context(ctx, ctx_obj, ring, ringbuf); @@ -2519,10 +2496,8 @@ int intel_lr_context_deferred_create(struct intel_context *ctx, error: if (is_global_default_ctx) intel_unpin_ringbuffer_obj(ringbuf); -error_destroy_rbuf: - intel_destroy_ringbuffer_obj(ringbuf); -error_free_rbuf: - kfree(ringbuf); +error_ringbuf: + intel_ringbuffer_free(ringbuf); error_unpin_ctx: if (is_global_default_ctx) i915_gem_object_ggtt_unpin(ctx_obj); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 6e6b8db..20a75bb 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1996,14 +1996,14 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev, return 0; } -void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf) +static void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf) { drm_gem_object_unreference(&ringbuf->obj->base); ringbuf->obj = NULL; } -int intel_alloc_ringbuffer_obj(struct drm_device *dev, - struct intel_ringbuffer *ringbuf) +static int intel_alloc_ringbuffer_obj(struct drm_device *dev, + struct intel_ringbuffer *ringbuf) { struct drm_i915_gem_object *obj; @@ -2023,6 +2023,48 @@ int intel_alloc_ringbuffer_obj(struct drm_device *dev, return 0; } +struct intel_ringbuffer * +intel_engine_create_ringbuffer(struct intel_engine_cs *engine, int size) +{ + struct intel_ringbuffer *ring; + int ret; + + ring = kzalloc(sizeof(*ring), GFP_KERNEL); + if (ring == NULL) + return ERR_PTR(-ENOMEM); + + ring->ring = engine; + + ring->size = size; + /* Workaround an erratum on the i830 which causes a hang if + * the TAIL pointer points to within the last 2 cachelines + * of the buffer. + */ + ring->effective_size = size; + if (IS_I830(engine->dev) || IS_845G(engine->dev)) + ring->effective_size -= 2 * CACHELINE_BYTES; + + ring->last_retired_head = -1; + intel_ring_update_space(ring); + + ret = intel_alloc_ringbuffer_obj(engine->dev, ring); + if (ret) { + DRM_ERROR("Failed to allocate ringbuffer %s: %d\n", + engine->name, ret); + kfree(ring); + return ERR_PTR(ret); + } + + return ring; +} + +void +intel_ringbuffer_free(struct intel_ringbuffer *ring) +{ + intel_destroy_ringbuffer_obj(ring); + kfree(ring); +} + static int intel_init_ring_buffer(struct drm_device *dev, struct intel_engine_cs *ring) { @@ -2031,22 +2073,20 @@ static int intel_init_ring_buffer(struct drm_device *dev, WARN_ON(ring->buffer); - ringbuf = kzalloc(sizeof(*ringbuf), GFP_KERNEL); - if (!ringbuf) - return -ENOMEM; - ring->buffer = ringbuf; - ring->dev = dev; INIT_LIST_HEAD(&ring->active_list); INIT_LIST_HEAD(&ring->request_list); INIT_LIST_HEAD(&ring->execlist_queue); i915_gem_batch_pool_init(dev, &ring->batch_pool); - ringbuf->size = 32 * PAGE_SIZE; - ringbuf->ring = ring; memset(ring->semaphore.sync_seqno, 0, sizeof(ring->semaphore.sync_seqno)); init_waitqueue_head(&ring->irq_queue); + ringbuf = intel_engine_create_ringbuffer(ring, 32 * PAGE_SIZE); + if (IS_ERR(ringbuf)) + return PTR_ERR(ringbuf); + ring->buffer = ringbuf; + if (I915_NEED_GFX_HWS(dev)) { ret = init_status_page(ring); if (ret) @@ -2058,15 +2098,6 @@ static int intel_init_ring_buffer(struct drm_device *dev, goto error; } - WARN_ON(ringbuf->obj); - - ret = intel_alloc_ringbuffer_obj(dev, ringbuf); - if (ret) { - DRM_ERROR("Failed to allocate ringbuffer %s: %d\n", - ring->name, ret); - goto error; - } - ret = intel_pin_and_map_ringbuffer_obj(dev, ringbuf); if (ret) { DRM_ERROR("Failed to pin and map ringbuffer %s: %d\n", @@ -2075,14 +2106,6 @@ static int intel_init_ring_buffer(struct drm_device *dev, goto error; } - /* Workaround an erratum on the i830 which causes a hang if - * the TAIL pointer points to within the last 2 cachelines - * of the buffer. - */ - ringbuf->effective_size = ringbuf->size; - if (IS_I830(dev) || IS_845G(dev)) - ringbuf->effective_size -= 2 * CACHELINE_BYTES; - ret = i915_cmd_parser_init_ring(ring); if (ret) goto error; @@ -2090,7 +2113,7 @@ static int intel_init_ring_buffer(struct drm_device *dev, return 0; error: - kfree(ringbuf); + intel_ringbuffer_free(ringbuf); ring->buffer = NULL; return ret; } @@ -2098,19 +2121,18 @@ error: void intel_cleanup_ring_buffer(struct intel_engine_cs *ring) { struct drm_i915_private *dev_priv; - struct intel_ringbuffer *ringbuf; if (!intel_ring_initialized(ring)) return; dev_priv = to_i915(ring->dev); - ringbuf = ring->buffer; intel_stop_ring_buffer(ring); WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0); - intel_unpin_ringbuffer_obj(ringbuf); - intel_destroy_ringbuffer_obj(ringbuf); + intel_unpin_ringbuffer_obj(ring->buffer); + intel_ringbuffer_free(ring->buffer); + ring->buffer = NULL; if (ring->cleanup) ring->cleanup(ring); @@ -2119,9 +2141,6 @@ void intel_cleanup_ring_buffer(struct intel_engine_cs *ring) i915_cmd_parser_fini_ring(ring); i915_gem_batch_pool_fini(&ring->batch_pool); - - kfree(ringbuf); - ring->buffer = NULL; } static int ring_wait_for_space(struct intel_engine_cs *ring, int n) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 95b0b4b..49fa41d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -420,12 +420,12 @@ intel_write_status_page(struct intel_engine_cs *ring, #define I915_GEM_HWS_SCRATCH_INDEX 0x40 #define I915_GEM_HWS_SCRATCH_ADDR (I915_GEM_HWS_SCRATCH_INDEX << MI_STORE_DWORD_INDEX_SHIFT) -void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf); +struct intel_ringbuffer * +intel_engine_create_ringbuffer(struct intel_engine_cs *engine, int size); int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev, struct intel_ringbuffer *ringbuf); -void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf); -int intel_alloc_ringbuffer_obj(struct drm_device *dev, - struct intel_ringbuffer *ringbuf); +void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf); +void intel_ringbuffer_free(struct intel_ringbuffer *ring); void intel_stop_ring_buffer(struct intel_engine_cs *ring); void intel_cleanup_ring_buffer(struct intel_engine_cs *ring); -- cgit v0.10.2 From c5796b7126b2497513bfa9a9341d02cb833d83d6 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 3 Sep 2015 16:24:35 +0300 Subject: drm/i915: access the PP_CONTROL reg only pre GEN5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This register exists only pre GEN5, but atm we also access it on VLV/BXT/CHV. Prevent accessing it on these latter platforms. Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 0794dc8..a16308a 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -955,7 +955,7 @@ void intel_lvds_init(struct drm_device *dev) if (HAS_PCH_SPLIT(dev)) { I915_WRITE(PCH_PP_CONTROL, I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS); - } else { + } else if (INTEL_INFO(dev_priv)->gen < 5) { I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS); } -- cgit v0.10.2 From 96d12cbdbd03a9ce87a75520512ef9ad8c585e92 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 3 Sep 2015 16:24:36 +0300 Subject: drm/i915: access the PP_ON_DELAYS/PP_OFF_DELAYS regs only pre GEN5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These registers exist only before GEN5, so currently we may access undefined registers on VLV/CHV and BXT. Apply the workaround only pre GEN5. Since the workaround is relevant only when LVDS is present, for clarity apply it only if this is the case. This triggered an unclaimed register access warning on BXT. v2: (Ville) - move the workaround to the LVDS init code - print a debug note about the workaround Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index f0eaa6f..066a0ef 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -997,8 +997,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) intel_setup_gmbus(dev); intel_opregion_setup(dev); - intel_setup_bios(dev); - i915_gem_load(dev); /* On the 945G/GM, the chipset reports the MSI capability on the diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index b3e437b..c8acc29 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -1340,21 +1340,3 @@ intel_parse_bios(struct drm_device *dev) return 0; } - -/* Ensure that vital registers have been initialised, even if the BIOS - * is absent or just failing to do its job. - */ -void intel_setup_bios(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - /* Set the Panel Power On/Off timings if uninitialized. */ - if (!HAS_PCH_SPLIT(dev) && - I915_READ(PP_ON_DELAYS) == 0 && I915_READ(PP_OFF_DELAYS) == 0) { - /* Set T2 to 40ms and T5 to 200ms */ - I915_WRITE(PP_ON_DELAYS, 0x019007d0); - - /* Set T3 to 35ms and Tx to 200ms */ - I915_WRITE(PP_OFF_DELAYS, 0x015e07d0); - } -} diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 46cd5c7..1b7417e 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -588,7 +588,6 @@ struct bdb_psr { struct psr_table psr_table[16]; } __packed; -void intel_setup_bios(struct drm_device *dev); int intel_parse_bios(struct drm_device *dev); /* diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index a16308a..2c2d1f0 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -985,6 +985,18 @@ void intel_lvds_init(struct drm_device *dev) DRM_DEBUG_KMS("LVDS is not present in VBT, but enabled anyway\n"); } + /* Set the Panel Power On/Off timings if uninitialized. */ + if (INTEL_INFO(dev_priv)->gen < 5 && + I915_READ(PP_ON_DELAYS) == 0 && I915_READ(PP_OFF_DELAYS) == 0) { + /* Set T2 to 40ms and T5 to 200ms */ + I915_WRITE(PP_ON_DELAYS, 0x019007d0); + + /* Set T3 to 35ms and Tx to 200ms */ + I915_WRITE(PP_OFF_DELAYS, 0x015e07d0); + + DRM_DEBUG_KMS("Panel power timings uninitialized, setting defaults\n"); + } + lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL); if (!lvds_encoder) return; -- cgit v0.10.2 From 333b8ca8cfcafc8c556d4333fe660283fea691d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 3 Sep 2015 21:50:16 +0300 Subject: drm/i915: Dump pfit state as hex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pfit state is stored as register values, so dump them as hex instead of decimal to make some sense of the error messages. Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b59717a..110b8dc 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12439,16 +12439,16 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_I(pipe_src_w); PIPE_CONF_CHECK_I(pipe_src_h); - PIPE_CONF_CHECK_I(gmch_pfit.control); + PIPE_CONF_CHECK_X(gmch_pfit.control); /* pfit ratios are autocomputed by the hw on gen4+ */ if (INTEL_INFO(dev)->gen < 4) PIPE_CONF_CHECK_I(gmch_pfit.pgm_ratios); - PIPE_CONF_CHECK_I(gmch_pfit.lvds_border_bits); + PIPE_CONF_CHECK_X(gmch_pfit.lvds_border_bits); PIPE_CONF_CHECK_I(pch_pfit.enabled); if (current_config->pch_pfit.enabled) { - PIPE_CONF_CHECK_I(pch_pfit.pos); - PIPE_CONF_CHECK_I(pch_pfit.size); + PIPE_CONF_CHECK_X(pch_pfit.pos); + PIPE_CONF_CHECK_X(pch_pfit.size); } PIPE_CONF_CHECK_I(scaler_state.scaler_id); -- cgit v0.10.2 From 614f4ad7984f930623bf0d25adba707d0d36c6dc Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 2 Sep 2015 12:29:40 +0100 Subject: drm/i915: Fix cmdparser STORE/LOAD command descriptors Fixes regression from commit f1afe24f0e736b9d7f2275e2b1504af3fe612f2a Author: Arun Siluvery Date: Tue Aug 4 16:22:20 2015 +0100 drm/i915: Change SRM, LRM instructions to use correct length which forgot to account for the length bias when declaring the fixed length. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=91844 Reported-by: Andreas Reis Signed-off-by: Chris Wilson Cc: Dave Gordon Cc: Arun Siluvery Cc: Mika Kuoppala Cc: Daniel Vetter Reviewed-by: Arun Siluvery Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index ad7d7ab..09932ca 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -124,14 +124,14 @@ static const struct drm_i915_cmd_descriptor common_cmds[] = { CMD( MI_STORE_DWORD_INDEX, SMI, !F, 0xFF, R ), CMD( MI_LOAD_REGISTER_IMM(1), SMI, !F, 0xFF, W, .reg = { .offset = 1, .mask = 0x007FFFFC, .step = 2 } ), - CMD( MI_STORE_REGISTER_MEM, SMI, F, 1, W | B, + CMD( MI_STORE_REGISTER_MEM, SMI, F, 3, W | B, .reg = { .offset = 1, .mask = 0x007FFFFC }, .bits = {{ .offset = 0, .mask = MI_GLOBAL_GTT, .expected = 0, }}, ), - CMD( MI_LOAD_REGISTER_MEM, SMI, F, 1, W | B, + CMD( MI_LOAD_REGISTER_MEM, SMI, F, 3, W | B, .reg = { .offset = 1, .mask = 0x007FFFFC }, .bits = {{ .offset = 0, -- cgit v0.10.2 From a7546159718171ba9f2a4df37b574c64b1589b5d Mon Sep 17 00:00:00 2001 From: Nick Hoath Date: Mon, 29 Jun 2015 14:07:32 +0100 Subject: drm/i915/bxt: Clean up bxt_init_clock_gating Add stepping check for A0 workarounds, and remove the associated FIXME tags. Split out unrelated WAs for later condition checking. v2: Fixed format (PeterL) v3: Corrected stepping check for WaDisableSDEUnitClockGating - Ignoring comment, following hardware spec instead. (ChrisH) Added description for TILECTL setting (JonB) Cc: Peter Lawthers Cc: Chris Harris Cc: Jon Bloomfield Signed-off-by: Nick Hoath Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 79cd987..64bc77e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -116,18 +116,24 @@ static void bxt_init_clock_gating(struct drm_device *dev) gen9_init_clock_gating(dev); + /* WaDisableSDEUnitClockGating:bxt */ + I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) | + GEN8_SDEUNIT_CLOCK_GATE_DISABLE); + /* * FIXME: - * GEN8_SDEUNIT_CLOCK_GATE_DISABLE applies on A0 only. * GEN8_HDCUNIT_CLOCK_GATE_DISABLE_HDCREQ applies on 3x6 GT SKUs only. */ - /* WaDisableSDEUnitClockGating:bxt */ I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) | - GEN8_SDEUNIT_CLOCK_GATE_DISABLE | GEN8_HDCUNIT_CLOCK_GATE_DISABLE_HDCREQ); - /* FIXME: apply on A0 only */ - I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF); + if (INTEL_REVID(dev) == BXT_REVID_A0) { + /* + * Hardware specification requires this bit to be + * set to 1 for A0 + */ + I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF); + } } static void i915_pineview_get_mem_freq(struct drm_device *dev) -- cgit v0.10.2 From 437b15b8017e0d946453c10794b0c5d4591cf180 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 4 Sep 2015 16:55:13 +0300 Subject: drm/i915: use pch backlight override on hsw too Currently the difference between backlight control on HSW vs. BDW/SKL is that on HSW we modify the duty cycle on the CPU register, and have the hardware pass the changes on to the PCH registers. We still drive the PCH PWM on both. While HSW and BDW use the same LPT PCH, BDW does not pass these messages on to the PCH. Therefore on BDW we need to enable the PCH override bit, and program the PCH directly. (On SPT PCH, this mode is the default.) We could as well do this on HSW too, and in fact I've been told this is what a certain other operating system does. So use PCH backlight override on HSW too. This simplifies some follow-up code, but it does have the danger of breaking backlight on HSW machines. It should work, but mysterious are the ways of backlight. While at it, name the related backlight hooks according to the PCH rather than the CPU for clarity. Cc: Clint Taylor Signed-off-by: Jani Nikula Reviewed-by: Clint Taylor Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index e2ab3f6..681686e 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -484,7 +484,7 @@ static u32 intel_panel_compute_brightness(struct intel_connector *connector, return val; } -static u32 bdw_get_backlight(struct intel_connector *connector) +static u32 lpt_get_backlight(struct intel_connector *connector) { struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -576,7 +576,7 @@ static u32 intel_panel_get_backlight(struct intel_connector *connector) return val; } -static void bdw_set_backlight(struct intel_connector *connector, u32 level) +static void lpt_set_backlight(struct intel_connector *connector, u32 level) { struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -729,6 +729,18 @@ void intel_panel_set_backlight_acpi(struct intel_connector *connector, mutex_unlock(&dev_priv->backlight_lock); } +static void lpt_disable_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + u32 tmp; + + intel_panel_actually_set_backlight(connector, 0); + + tmp = I915_READ(BLC_PWM_PCH_CTL1); + I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE); +} + static void pch_disable_backlight(struct intel_connector *connector) { struct drm_device *dev = connector->base.dev; @@ -829,7 +841,7 @@ void intel_panel_disable_backlight(struct intel_connector *connector) mutex_unlock(&dev_priv->backlight_lock); } -static void bdw_enable_backlight(struct intel_connector *connector) +static void lpt_enable_backlight(struct intel_connector *connector) { struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -1243,7 +1255,7 @@ static u32 get_backlight_min_vbt(struct intel_connector *connector) return scale(min, 0, 255, 0, panel->backlight.max); } -static int bdw_setup_backlight(struct intel_connector *connector, enum pipe unused) +static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unused) { struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -1260,7 +1272,7 @@ static int bdw_setup_backlight(struct intel_connector *connector, enum pipe unus panel->backlight.min = get_backlight_min_vbt(connector); - val = bdw_get_backlight(connector); + val = lpt_get_backlight(connector); panel->backlight.level = intel_panel_compute_brightness(connector, val); panel->backlight.enabled = (pch_ctl1 & BLM_PCH_PWM_ENABLE) && @@ -1519,12 +1531,12 @@ void intel_panel_init_backlight_funcs(struct drm_device *dev) dev_priv->display.disable_backlight = bxt_disable_backlight; dev_priv->display.set_backlight = bxt_set_backlight; dev_priv->display.get_backlight = bxt_get_backlight; - } else if (IS_BROADWELL(dev) || IS_SKYLAKE(dev)) { - dev_priv->display.setup_backlight = bdw_setup_backlight; - dev_priv->display.enable_backlight = bdw_enable_backlight; - dev_priv->display.disable_backlight = pch_disable_backlight; - dev_priv->display.set_backlight = bdw_set_backlight; - dev_priv->display.get_backlight = bdw_get_backlight; + } else if (HAS_PCH_LPT(dev) || HAS_PCH_SPT(dev)) { + dev_priv->display.setup_backlight = lpt_setup_backlight; + dev_priv->display.enable_backlight = lpt_enable_backlight; + dev_priv->display.disable_backlight = lpt_disable_backlight; + dev_priv->display.set_backlight = lpt_set_backlight; + dev_priv->display.get_backlight = lpt_get_backlight; } else if (HAS_PCH_SPLIT(dev)) { dev_priv->display.setup_backlight = pch_setup_backlight; dev_priv->display.enable_backlight = pch_enable_backlight; -- cgit v0.10.2 From aa17cdb4f8367875d3a53c41e004fc02e983e317 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 4 Sep 2015 16:55:14 +0300 Subject: drm/i915: initialize backlight max from VBT Normally we determine the backlight PWM modulation frequency (which we also use as backlight max value) from the backlight registers at module load time, expecting the registers have been initialized by the BIOS. If this is not the case, we fail. The VBT contains the backlight modulation frequency in Hz. Add platform specific functions to convert the frequency in Hz to backlight PWM modulation frequency, and use them to initialize the backlight when the registers are not initialized by the BIOS. v2: Fix SPT and VLV. Thanks to Clint for the VLV code. Cc: Clint Taylor Signed-off-by: Jani Nikula Reviewed-by: Clint Taylor Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 482ddb7..3e46187 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -671,6 +671,8 @@ struct drm_i915_display_funcs { uint32_t level); void (*disable_backlight)(struct intel_connector *connector); void (*enable_backlight)(struct intel_connector *connector); + uint32_t (*backlight_hz_to_pwm)(struct intel_connector *connector, + uint32_t hz); }; enum forcewake_domain_id { diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5811eeb..65b5682 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4648,6 +4648,7 @@ enum skl_disp_power_wells { #define CBR1_VLV (VLV_DISPLAY_BASE + 0x70400) #define CBR_PND_DEADLINE_DISABLE (1<<31) +#define CBR_PWM_CLOCK_MUX_SELECT (1<<30) /* FIFO watermark sizes etc */ #define G4X_FIFO_LINE_SIZE 64 @@ -6325,9 +6326,11 @@ enum skl_disp_power_wells { #define FDI_PHASE_SYNC_OVR(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_OVR - ((pipe) * 2))) #define FDI_PHASE_SYNC_EN(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_EN - ((pipe) * 2))) #define FDI_BC_BIFURCATION_SELECT (1 << 12) +#define SPT_PWM_GRANULARITY (1<<0) #define SOUTH_CHICKEN2 0xc2004 #define FDI_MPHY_IOSFSB_RESET_STATUS (1<<13) #define FDI_MPHY_IOSFSB_RESET_CTL (1<<12) +#define LPT_PWM_GRANULARITY (1<<5) #define DPLS_EDP_PPS_FIX_DIS (1<<0) #define _FDI_RXA_CHICKEN 0xc200c diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 681686e..d3a312c 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -1224,10 +1224,149 @@ static void intel_backlight_device_unregister(struct intel_connector *connector) #endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */ /* - * Note: The setup hooks can't assume pipe is set! + * SPT: This value represents the period of the PWM stream in clock periods + * multiplied by 16 (default increment) or 128 (alternate increment selected in + * SCHICKEN_1 bit 0). PWM clock is 24 MHz. + */ +static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + u32 mul, clock; + + if (I915_READ(SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY) + mul = 128; + else + mul = 16; + + clock = MHz(24); + + return clock / (pwm_freq_hz * mul); +} + +/* + * LPT: This value represents the period of the PWM stream in clock periods + * multiplied by 128 (default increment) or 16 (alternate increment, selected in + * LPT SOUTH_CHICKEN2 register bit 5). + */ +static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + u32 mul, clock; + + if (I915_READ(SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY) + mul = 16; + else + mul = 128; + + if (dev_priv->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE) + clock = MHz(135); /* LPT:H */ + else + clock = MHz(24); /* LPT:LP */ + + return clock / (pwm_freq_hz * mul); +} + +/* + * ILK/SNB/IVB: This value represents the period of the PWM stream in PCH + * display raw clocks multiplied by 128. + */ +static u32 pch_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) +{ + struct drm_device *dev = connector->base.dev; + int clock = MHz(intel_pch_rawclk(dev)); + + return clock / (pwm_freq_hz * 128); +} + +/* + * Gen2: This field determines the number of time base events (display core + * clock frequency/32) in total for a complete cycle of modulated backlight + * control. * - * XXX: Query mode clock or hardware clock and program PWM modulation frequency - * appropriately when it's 0. Use VBT and/or sane defaults. + * Gen3: A time base event equals the display core clock ([DevPNV] HRAW clock) + * divided by 32. + */ +static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + int clock; + + if (IS_PINEVIEW(dev)) + clock = intel_hrawclk(dev); + else + clock = 1000 * dev_priv->display.get_display_clock_speed(dev); + + return clock / (pwm_freq_hz * 32); +} + +/* + * Gen4: This value represents the period of the PWM stream in display core + * clocks multiplied by 128. + */ +static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + int clock = 1000 * dev_priv->display.get_display_clock_speed(dev); + + return clock / (pwm_freq_hz * 128); +} + +/* + * VLV: This value represents the period of the PWM stream in display core + * clocks ([DevCTG] 200MHz HRAW clocks) multiplied by 128 or 25MHz S0IX clocks + * multiplied by 16. CHV uses a 19.2MHz S0IX clock. + */ +static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + int clock; + + if ((I915_READ(CBR1_VLV) & CBR_PWM_CLOCK_MUX_SELECT) == 0) { + if (IS_CHERRYVIEW(dev)) + return KHz(19200) / (pwm_freq_hz * 16); + else + return MHz(25) / (pwm_freq_hz * 16); + } else { + clock = intel_hrawclk(dev); + return MHz(clock) / (pwm_freq_hz * 128); + } +} + +static u32 get_backlight_max_vbt(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + u16 pwm_freq_hz = dev_priv->vbt.backlight.pwm_freq_hz; + u32 pwm; + + if (!pwm_freq_hz) { + DRM_DEBUG_KMS("backlight frequency not specified in VBT\n"); + return 0; + } + + if (!dev_priv->display.backlight_hz_to_pwm) { + DRM_DEBUG_KMS("backlight frequency setting from VBT currently not supported on this platform\n"); + return 0; + } + + pwm = dev_priv->display.backlight_hz_to_pwm(connector, pwm_freq_hz); + if (!pwm) { + DRM_DEBUG_KMS("backlight frequency conversion failed\n"); + return 0; + } + + DRM_DEBUG_KMS("backlight frequency %u Hz from VBT\n", pwm_freq_hz); + + return pwm; +} + +/* + * Note: The setup hooks can't assume pipe is set! */ static u32 get_backlight_min_vbt(struct intel_connector *connector) { @@ -1267,6 +1406,10 @@ static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unus pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); panel->backlight.max = pch_ctl2 >> 16; + + if (!panel->backlight.max) + panel->backlight.max = get_backlight_max_vbt(connector); + if (!panel->backlight.max) return -ENODEV; @@ -1293,6 +1436,10 @@ static int pch_setup_backlight(struct intel_connector *connector, enum pipe unus pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); panel->backlight.max = pch_ctl2 >> 16; + + if (!panel->backlight.max) + panel->backlight.max = get_backlight_max_vbt(connector); + if (!panel->backlight.max) return -ENODEV; @@ -1324,12 +1471,18 @@ static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unu panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV; panel->backlight.max = ctl >> 17; - if (panel->backlight.combination_mode) - panel->backlight.max *= 0xff; + + if (!panel->backlight.max) { + panel->backlight.max = get_backlight_max_vbt(connector); + panel->backlight.max >>= 1; + } if (!panel->backlight.max) return -ENODEV; + if (panel->backlight.combination_mode) + panel->backlight.max *= 0xff; + panel->backlight.min = get_backlight_min_vbt(connector); val = i9xx_get_backlight(connector); @@ -1353,12 +1506,16 @@ static int i965_setup_backlight(struct intel_connector *connector, enum pipe unu ctl = I915_READ(BLC_PWM_CTL); panel->backlight.max = ctl >> 16; - if (panel->backlight.combination_mode) - panel->backlight.max *= 0xff; + + if (!panel->backlight.max) + panel->backlight.max = get_backlight_max_vbt(connector); if (!panel->backlight.max) return -ENODEV; + if (panel->backlight.combination_mode) + panel->backlight.max *= 0xff; + panel->backlight.min = get_backlight_min_vbt(connector); val = i9xx_get_backlight(connector); @@ -1398,6 +1555,10 @@ static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe ctl = I915_READ(VLV_BLC_PWM_CTL(pipe)); panel->backlight.max = ctl >> 16; + + if (!panel->backlight.max) + panel->backlight.max = get_backlight_max_vbt(connector); + if (!panel->backlight.max) return -ENODEV; @@ -1424,6 +1585,10 @@ bxt_setup_backlight(struct intel_connector *connector, enum pipe unused) panel->backlight.active_low_pwm = pwm_ctl & BXT_BLC_PWM_POLARITY; panel->backlight.max = I915_READ(BXT_BLC_PWM_FREQ1); + + if (!panel->backlight.max) + panel->backlight.max = get_backlight_max_vbt(connector); + if (!panel->backlight.max) return -ENODEV; @@ -1537,12 +1702,17 @@ void intel_panel_init_backlight_funcs(struct drm_device *dev) dev_priv->display.disable_backlight = lpt_disable_backlight; dev_priv->display.set_backlight = lpt_set_backlight; dev_priv->display.get_backlight = lpt_get_backlight; + if (HAS_PCH_LPT(dev)) + dev_priv->display.backlight_hz_to_pwm = lpt_hz_to_pwm; + else + dev_priv->display.backlight_hz_to_pwm = spt_hz_to_pwm; } else if (HAS_PCH_SPLIT(dev)) { dev_priv->display.setup_backlight = pch_setup_backlight; dev_priv->display.enable_backlight = pch_enable_backlight; dev_priv->display.disable_backlight = pch_disable_backlight; dev_priv->display.set_backlight = pch_set_backlight; dev_priv->display.get_backlight = pch_get_backlight; + dev_priv->display.backlight_hz_to_pwm = pch_hz_to_pwm; } else if (IS_VALLEYVIEW(dev)) { if (dev_priv->vbt.has_mipi) { dev_priv->display.setup_backlight = pwm_setup_backlight; @@ -1556,6 +1726,7 @@ void intel_panel_init_backlight_funcs(struct drm_device *dev) dev_priv->display.disable_backlight = vlv_disable_backlight; dev_priv->display.set_backlight = vlv_set_backlight; dev_priv->display.get_backlight = vlv_get_backlight; + dev_priv->display.backlight_hz_to_pwm = vlv_hz_to_pwm; } } else if (IS_GEN4(dev)) { dev_priv->display.setup_backlight = i965_setup_backlight; @@ -1563,12 +1734,14 @@ void intel_panel_init_backlight_funcs(struct drm_device *dev) dev_priv->display.disable_backlight = i965_disable_backlight; dev_priv->display.set_backlight = i9xx_set_backlight; dev_priv->display.get_backlight = i9xx_get_backlight; + dev_priv->display.backlight_hz_to_pwm = i965_hz_to_pwm; } else { dev_priv->display.setup_backlight = i9xx_setup_backlight; dev_priv->display.enable_backlight = i9xx_enable_backlight; dev_priv->display.disable_backlight = i9xx_disable_backlight; dev_priv->display.set_backlight = i9xx_set_backlight; dev_priv->display.get_backlight = i9xx_get_backlight; + dev_priv->display.backlight_hz_to_pwm = i9xx_hz_to_pwm; } } -- cgit v0.10.2 From 4a999d253195db87f18215049cf7a44f795f4ca0 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 4 Sep 2015 16:55:15 +0300 Subject: drm/i915: don't hard code vlv backlight frequency if unset Fall back to VBT based backlight modulation frequency if it's not set. Do not hard code. This could be a problem if there is no VBT. Cc: Clint Taylor Signed-off-by: Jani Nikula Tested-by: Clint Taylor Reviewed-by: Clint Taylor Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index d3a312c..2034438a 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -1532,21 +1532,8 @@ static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_panel *panel = &connector->panel; - enum pipe p; u32 ctl, ctl2, val; - for_each_pipe(dev_priv, p) { - u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(p)); - - /* Skip if the modulation freq is already set */ - if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK) - continue; - - cur_val &= BACKLIGHT_DUTY_CYCLE_MASK; - I915_WRITE(VLV_BLC_PWM_CTL(p), (0xf42 << 16) | - cur_val); - } - if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B)) return -ENODEV; -- cgit v0.10.2 From bcfe0c0954f3336c44993e5ce444e09ad6087637 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 13 Aug 2015 17:06:39 -0300 Subject: drm: WARN_ON if a modeset driver uses legacy suspend/resume helpers Legacy s/r hooks are only used for shadow-attaching drivers, warn when a KMS driver tries to use them. Signed-off-by: Gustavo Padovan Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 53d09a1..dc93c88 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -566,6 +566,8 @@ struct drm_device *drm_dev_alloc(struct drm_driver *driver, ret = drm_minor_alloc(dev, DRM_MINOR_CONTROL); if (ret) goto err_minors; + + WARN_ON(driver->suspend || driver->resume); } if (drm_core_check_feature(dev, DRIVER_RENDER)) { -- cgit v0.10.2 From fafecc01bcce4a21c0644c79de833e659882d33a Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Sun, 16 Aug 2015 04:02:28 +0100 Subject: drm/mm: Do DRM_MM_CREATE_TOP adj_start calculation after color_adjust The adj_start calculation for DRM_MM_CREATE_TOP should happen after mm->color_adjust. There was an inconsistency between drm_mm_insert_helper_range and drm_mm_insert_helper, as the later was already updating after color_adjust. Didn't spot it before, as color_adjust is only done in systems without LLC. But I'm not aware of anybody using this test case yet. Signed-off-by: Michel Thierry Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 3427b11..04de6fd 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -267,12 +267,12 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, if (adj_end > end) adj_end = end; - if (flags & DRM_MM_CREATE_TOP) - adj_start = adj_end - size; - if (mm->color_adjust) mm->color_adjust(hole_node, color, &adj_start, &adj_end); + if (flags & DRM_MM_CREATE_TOP) + adj_start = adj_end - size; + if (alignment) { u64 tmp = adj_start; unsigned rem; -- cgit v0.10.2 From bbda9c1f170e4b31f5d827372ee9a3fb8389f7fa Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 19 Aug 2015 19:21:14 -0400 Subject: drm: cleanup modesetting ioctls, one param per line Since this already confused me once when adding addfb2.1, let's clean up the header to split params one per line. Signed-off-by: Rob Clark Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 359107a..6c11ca4 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -105,8 +105,16 @@ struct drm_mode_modeinfo { __u32 clock; - __u16 hdisplay, hsync_start, hsync_end, htotal, hskew; - __u16 vdisplay, vsync_start, vsync_end, vtotal, vscan; + __u16 hdisplay; + __u16 hsync_start; + __u16 hsync_end; + __u16 htotal; + __u16 hskew; + __u16 vdisplay; + __u16 vsync_start; + __u16 vsync_end; + __u16 vtotal; + __u16 vscan; __u32 vrefresh; @@ -124,8 +132,10 @@ struct drm_mode_card_res { __u32 count_crtcs; __u32 count_connectors; __u32 count_encoders; - __u32 min_width, max_width; - __u32 min_height, max_height; + __u32 min_width; + __u32 max_width; + __u32 min_height; + __u32 max_height; }; struct drm_mode_crtc { @@ -135,7 +145,8 @@ struct drm_mode_crtc { __u32 crtc_id; /**< Id */ __u32 fb_id; /**< Id of framebuffer */ - __u32 x, y; /**< Position on the frameuffer */ + __u32 x; /**< x Position on the framebuffer */ + __u32 y; /**< y Position on the framebuffer */ __u32 gamma_size; __u32 mode_valid; @@ -153,12 +164,16 @@ struct drm_mode_set_plane { __u32 flags; /* see above flags */ /* Signed dest location allows it to be partially off screen */ - __s32 crtc_x, crtc_y; - __u32 crtc_w, crtc_h; + __s32 crtc_x; + __s32 crtc_y; + __u32 crtc_w; + __u32 crtc_h; /* Source values are 16.16 fixed point */ - __u32 src_x, src_y; - __u32 src_h, src_w; + __u32 src_x; + __u32 src_y; + __u32 src_h; + __u32 src_w; }; struct drm_mode_get_plane { @@ -244,7 +259,8 @@ struct drm_mode_get_connector { __u32 connector_type_id; __u32 connection; - __u32 mm_width, mm_height; /**< HxW in millimeters */ + __u32 mm_width; /**< width in millimeters */ + __u32 mm_height; /**< height in millimeters */ __u32 subpixel; __u32 pad; @@ -327,7 +343,8 @@ struct drm_mode_get_blob { struct drm_mode_fb_cmd { __u32 fb_id; - __u32 width, height; + __u32 width; + __u32 height; __u32 pitch; __u32 bpp; __u32 depth; @@ -340,7 +357,8 @@ struct drm_mode_fb_cmd { struct drm_mode_fb_cmd2 { __u32 fb_id; - __u32 width, height; + __u32 width; + __u32 height; __u32 pixel_format; /* fourcc code from drm_fourcc.h */ __u32 flags; /* see above flags */ -- cgit v0.10.2 From fe8660acd8853ad9f95b94a04cce384949ddecfe Mon Sep 17 00:00:00 2001 From: Danilo Cesar Lemes de Paula Date: Fri, 21 Aug 2015 16:46:14 -0300 Subject: drm/doc: Fixing xml documentation warning "/**" should be used for kernel-doc documentation only. It causes a warning with the new "in struct body" format. Signed-off-by: Danilo Cesar Lemes de Paula Cc: Randy Dunlap Cc: Daniel Vetter Cc: Laurent Pinchart Cc: Jonathan Corbet Cc: Herbert Xu Cc: Stephan Mueller Cc: Michal Marek Cc: linux-kernel@vger.kernel.org Cc: linux-doc@vger.kernel.org Cc: intel-gfx Cc: dri-devel Cc: Graham Whaley Signed-off-by: Daniel Vetter diff --git a/include/drm/drm_modeset_lock.h b/include/drm/drm_modeset_lock.h index 5dd18bf..94938d8 100644 --- a/include/drm/drm_modeset_lock.h +++ b/include/drm/drm_modeset_lock.h @@ -43,19 +43,19 @@ struct drm_modeset_acquire_ctx { struct ww_acquire_ctx ww_ctx; - /** + /* * Contended lock: if a lock is contended you should only call * drm_modeset_backoff() which drops locks and slow-locks the * contended lock. */ struct drm_modeset_lock *contended; - /** + /* * list of held locks (drm_modeset_lock) */ struct list_head locked; - /** + /* * Trylock mode, use only for panic handlers! */ bool trylock_only; @@ -70,12 +70,12 @@ struct drm_modeset_acquire_ctx { * Used for locking CRTCs and other modeset resources. */ struct drm_modeset_lock { - /** + /* * modeset lock */ struct ww_mutex mutex; - /** + /* * Resources that are locked as part of an atomic update are added * to a list (so we know what to unlock at the end). */ -- cgit v0.10.2 From 26196f7e11f4b2494a2c14eb789fc61a91207e79 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 25 Aug 2015 16:26:03 +0200 Subject: drm/atomic-helper: properly annotate functions in kerneldoc Without the () the markup and more important hyperlinking wont happen. v2: Also fix nearby type Laurent spotted. v3: Actually git add. Argh! Acked-by: Laurent Pinchart Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index d432348..a2629ee 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -42,14 +42,14 @@ * add their own additional internal state. * * This library also provides default implementations for the check callback in - * drm_atomic_helper_check and for the commit callback with - * drm_atomic_helper_commit. But the individual stages and callbacks are expose - * to allow drivers to mix and match and e.g. use the plane helpers only + * drm_atomic_helper_check() and for the commit callback with + * drm_atomic_helper_commit(). But the individual stages and callbacks are + * exposed to allow drivers to mix and match and e.g. use the plane helpers only * together with a driver private modeset implementation. * * This library also provides implementations for all the legacy driver - * interfaces on top of the atomic interface. See drm_atomic_helper_set_config, - * drm_atomic_helper_disable_plane, drm_atomic_helper_disable_plane and the + * interfaces on top of the atomic interface. See drm_atomic_helper_set_config(), + * drm_atomic_helper_disable_plane(), drm_atomic_helper_disable_plane() and the * various functions to implement set_property callbacks. New drivers must not * implement these functions themselves but must use the provided helpers. */ @@ -1077,7 +1077,7 @@ EXPORT_SYMBOL(drm_atomic_helper_commit); * work item, which allows nice concurrent updates on disjoint sets of crtcs. * * 3. The software state is updated synchronously with - * drm_atomic_helper_swap_state. Doing this under the protection of all modeset + * drm_atomic_helper_swap_state(). Doing this under the protection of all modeset * locks means concurrent callers never see inconsistent state. And doing this * while it's guaranteed that no relevant async worker runs means that async * workers do not need grab any locks. Actually they must not grab locks, for @@ -1334,7 +1334,7 @@ EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes); * * 4. Actually commit the hardware state. * - * 5. Call drm_atomic_helper_cleanup_planes with @state, which since step 3 + * 5. Call drm_atomic_helper_cleanup_planes() with @state, which since step 3 * contains the old state. Also do any other cleanup required with that state. */ void drm_atomic_helper_swap_state(struct drm_device *dev, -- cgit v0.10.2 From b7bdf0a87add0fead1550533e328a290d8f9da6c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 25 Aug 2015 17:20:28 +0200 Subject: drm/fb-helper: Use -errno return in restore_mode_unlocked Using bool and returning true upon error is very uncommon. Also an int return value is actually what all the callers which did check it seem to have expected. v2: Restore hunk misplaced in a rebase, spotted by Rob. Cc: Rob Clark Reviewed-by: Rob Clark Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 418d299..859134e 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -320,11 +320,10 @@ int drm_fb_helper_debug_leave(struct fb_info *info) } EXPORT_SYMBOL(drm_fb_helper_debug_leave); -static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper) +static int restore_fbdev_mode(struct drm_fb_helper *fb_helper) { struct drm_device *dev = fb_helper->dev; struct drm_plane *plane; - bool error = false; int i; drm_warn_on_modeset_not_all_locked(dev); @@ -348,14 +347,15 @@ static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper) if (crtc->funcs->cursor_set) { ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0); if (ret) - error = true; + return ret; } ret = drm_mode_set_config_internal(mode_set); if (ret) - error = true; + return ret; } - return error; + + return 0; } /** @@ -365,12 +365,15 @@ static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper) * This should be called from driver's drm ->lastclose callback * when implementing an fbcon on top of kms using this helper. This ensures that * the user isn't greeted with a black screen when e.g. X dies. + * + * RETURNS: + * Zero if everything went ok, negative error code otherwise. */ -bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper) +int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper) { struct drm_device *dev = fb_helper->dev; - bool ret; - bool do_delayed = false; + bool do_delayed; + int ret; drm_modeset_lock_all(dev); ret = restore_fbdev_mode(fb_helper); diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index dbab462..67de1f1 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -136,7 +136,7 @@ int drm_fb_helper_set_par(struct fb_info *info); int drm_fb_helper_check_var(struct fb_var_screeninfo *var, struct fb_info *info); -bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper); +int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper); struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper); void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper); @@ -226,10 +226,10 @@ static inline int drm_fb_helper_check_var(struct fb_var_screeninfo *var, return 0; } -static inline bool +static inline int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper) { - return true; + return 0; } static inline struct fb_info * -- cgit v0.10.2 From a39a357c6ca3c88ad64e9b51bd7607c06cd6d35d Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 25 Aug 2015 15:45:11 +0200 Subject: drm: Make drm_fb_unregister/remove accept NULL fb These functions are used by drivers to release fbdev emulation buffers. We need to make them resilient to NULL pointers to make the fbdev compile/runtime knobs not cause Oopses on module unload. Cc: Archit Taneja Reviewed-by: Rob Clark Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 33d877c..884690c 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -538,7 +538,12 @@ EXPORT_SYMBOL(drm_framebuffer_reference); */ void drm_framebuffer_unregister_private(struct drm_framebuffer *fb) { - struct drm_device *dev = fb->dev; + struct drm_device *dev; + + if (!fb) + return; + + dev = fb->dev; mutex_lock(&dev->mode_config.fb_lock); /* Mark fb as reaped and drop idr ref. */ @@ -589,12 +594,17 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup); */ void drm_framebuffer_remove(struct drm_framebuffer *fb) { - struct drm_device *dev = fb->dev; + struct drm_device *dev; struct drm_crtc *crtc; struct drm_plane *plane; struct drm_mode_set set; int ret; + if (!fb) + return; + + dev = fb->dev; + WARN_ON(!list_empty(&fb->filp_head)); /* -- cgit v0.10.2 From f64c5573d253ab3f9c01b4056c5f75a889d18502 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 25 Aug 2015 15:45:13 +0200 Subject: drm/fb-helper: Add module option to disable fbdev emulation Faster than recompiling. Note that restore_fbdev_mode_unlocked is a bit special and the only one which returns an error code when fbdev isn't there - i915 needs that one to not fall over with some additional fbcon related restore code. Everyone else just ignores the return value or only prints a DRM_DEBUG level message. Reviewed-by: Archit Taneja Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 859134e..ba12f51 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -39,6 +39,11 @@ #include #include +static bool drm_fbdev_emulation = true; +module_param_named(fbdev_emulation, drm_fbdev_emulation, bool, 0600); +MODULE_PARM_DESC(fbdev_emulation, + "Enable legacy fbdev emulation [default=true]"); + static LIST_HEAD(kernel_fb_helper_list); /** @@ -99,6 +104,9 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) struct drm_connector *connector; int i; + if (!drm_fbdev_emulation) + return 0; + mutex_lock(&dev->mode_config.mutex); drm_for_each_connector(connector, dev) { struct drm_fb_helper_connector *fb_helper_connector; @@ -129,6 +137,9 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_ struct drm_fb_helper_connector **temp; struct drm_fb_helper_connector *fb_helper_connector; + if (!drm_fbdev_emulation) + return 0; + WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex)); if (fb_helper->connector_count + 1 > fb_helper->connector_info_alloc_count) { temp = krealloc(fb_helper->connector_info, sizeof(struct drm_fb_helper_connector *) * (fb_helper->connector_count + 1), GFP_KERNEL); @@ -184,6 +195,9 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, struct drm_fb_helper_connector *fb_helper_connector; int i, j; + if (!drm_fbdev_emulation) + return 0; + WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex)); for (i = 0; i < fb_helper->connector_count; i++) { @@ -375,6 +389,9 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper) bool do_delayed; int ret; + if (!drm_fbdev_emulation) + return -ENODEV; + drm_modeset_lock_all(dev); ret = restore_fbdev_mode(fb_helper); @@ -591,6 +608,9 @@ int drm_fb_helper_init(struct drm_device *dev, struct drm_crtc *crtc; int i; + if (!drm_fbdev_emulation) + return 0; + if (!max_conn_count) return -EINVAL; @@ -713,6 +733,9 @@ EXPORT_SYMBOL(drm_fb_helper_release_fbi); void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) { + if (!drm_fbdev_emulation) + return; + if (!list_empty(&fb_helper->kernel_fb_list)) { list_del(&fb_helper->kernel_fb_list); if (list_empty(&kernel_fb_helper_list)) { @@ -1933,6 +1956,9 @@ int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) struct drm_device *dev = fb_helper->dev; int count = 0; + if (!drm_fbdev_emulation) + return 0; + mutex_lock(&dev->mode_config.mutex); count = drm_fb_helper_probe_connector_modes(fb_helper, dev->mode_config.max_width, @@ -1976,6 +2002,9 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) struct drm_device *dev = fb_helper->dev; u32 max_width, max_height; + if (!drm_fbdev_emulation) + return 0; + mutex_lock(&fb_helper->dev->mode_config.mutex); if (!fb_helper->fb || !drm_fb_helper_is_bound(fb_helper)) { fb_helper->delayed_hotplug = true; -- cgit v0.10.2 From f8aeb41c4b7e9de0a4df4ed1ba78cd6ee5c87281 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 26 Aug 2015 21:49:42 +0200 Subject: drm/atomic: refuse changing CRTC for planes directly Very strictly speaking this is possible if you have special hw and genlocked CRTCs. In general switching a plane between two active CRTC just won't work so well and is probably not tested at all. Just forbid it. I've put this into the core since right now no helper or driver copes with it, no userspace has code for it and no one asks for it. Yes there's piles of corner-cases where this would be possible to do this like: - switch from inactive crtc to active crtc - switch from active crtc to inactive crtc - genlocked display - invisible plane (to do whatever) - idle plane hw due to dsi cmd mode/psr - whatever but looking at details it's not that easy to implement this correctly. Hence just put it into the core and add a comment, since the only userspace we have right now for atomic (weston) doesn't want to use direct plane switching either. v2: don't bother with complexity and just outright disallow plane switching without the intermediate OFF state. Simplifies drivers, we don't have any hw that could do it anyway and current atomic userspace (weston) works like this already anyway. v3: Bikeshed function name (Ville) and add comment (Rob). v4: Also bikeshed commit message (Rob). v5: Fix compile warnings reported by 0-day. Cc: Thierry Reding Cc: Maarten Lankhorst Cc: Daniel Stone Acked-by: Daniel Stone Reviewed-by: Rob Clark Acked-by: Maarten Lankhorst Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 4349154..e515261 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -663,6 +663,25 @@ drm_atomic_plane_get_property(struct drm_plane *plane, return 0; } +static bool +plane_switching_crtc(struct drm_atomic_state *state, + struct drm_plane *plane, + struct drm_plane_state *plane_state) +{ + if (!plane->state->crtc || !plane_state->crtc) + return false; + + if (plane->state->crtc == plane_state->crtc) + return false; + + /* This could be refined, but currently there's no helper or driver code + * to implement direct switching of active planes nor userspace to take + * advantage of more direct plane switching without the intermediate + * full OFF state. + */ + return true; +} + /** * drm_atomic_plane_check - check plane state * @plane: plane to check @@ -734,6 +753,12 @@ static int drm_atomic_plane_check(struct drm_plane *plane, return -ENOSPC; } + if (plane_switching_crtc(state->state, plane, state)) { + DRM_DEBUG_ATOMIC("[PLANE:%d] switching CRTC directly\n", + plane->base.id); + return -EINVAL; + } + return 0; } -- cgit v0.10.2 From 96206e2922c114b13cadefa03b9f340b58fee13c Mon Sep 17 00:00:00 2001 From: Bob Paauwe Date: Thu, 27 Aug 2015 10:04:13 -0700 Subject: dtrm/edid: Allow comma separated edid binaries. (v3) Allow comma separated filenames in the edid_firmware parameter. For example: edid_firmware=eDP-1:edid/1280x480.bin,DP-2:edid/1920x1080.bin v2: Use strsep() to simplify parsing of comma seperated string. (Matt) Move initial bail before strdup. (Matt) v3: Changed conditionals after while loop to make more readable (Jani) Updated kernel-parameters.txt to reflect changes (Jani) Reviewed-by: Jani Nikula Reviewed-by: Matt Roper Signed-off-by: Bob Paauwe [danvet: Flatten else control flow and appease checkpatch.] Signed-off-by: Daniel Vetter diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 1d6f045..caf0fd4 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -927,11 +927,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted. The filter can be disabled or changed to another driver later using sysfs. - drm_kms_helper.edid_firmware=[:] - Broken monitors, graphic adapters and KVMs may - send no or incorrect EDID data sets. This parameter - allows to specify an EDID data set in the - /lib/firmware directory that is used instead. + drm_kms_helper.edid_firmware=[:][,[:]] + Broken monitors, graphic adapters, KVMs and EDIDless + panels may send no or incorrect EDID data sets. + This parameter allows to specify an EDID data sets + in the /lib/firmware directory that are used instead. Generic built-in EDID data sets are used, if one of edid/1024x768.bin, edid/1280x1024.bin, edid/1680x1050.bin, or edid/1920x1080.bin is given @@ -940,7 +940,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. available in Documentation/EDID/HOWTO.txt. An EDID data set will only be used for a particular connector, if its name and a colon are prepended to the EDID - name. + name. Each connector may use a unique EDID data + set by separating the files with a comma. An EDID + data set with no connector name will be used for + any connectors not explicitly specified. dscc4.setup= [NET] diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c index c5605fe..1f445e9 100644 --- a/drivers/gpu/drm/drm_edid_load.c +++ b/drivers/gpu/drm/drm_edid_load.c @@ -264,20 +264,43 @@ out: int drm_load_edid_firmware(struct drm_connector *connector) { const char *connector_name = connector->name; - char *edidname = edid_firmware, *last, *colon; + char *edidname, *last, *colon, *fwstr, *edidstr, *fallback = NULL; int ret; struct edid *edid; - if (*edidname == '\0') + if (edid_firmware[0] == '\0') return 0; - colon = strchr(edidname, ':'); - if (colon != NULL) { - if (strncmp(connector_name, edidname, colon - edidname)) - return 0; - edidname = colon + 1; - if (*edidname == '\0') + /* + * If there are multiple edid files specified and separated + * by commas, search through the list looking for one that + * matches the connector. + * + * If there's one or more that don't't specify a connector, keep + * the last one found one as a fallback. + */ + fwstr = kstrdup(edid_firmware, GFP_KERNEL); + edidstr = fwstr; + + while ((edidname = strsep(&edidstr, ","))) { + colon = strchr(edidname, ':'); + if (colon != NULL) { + if (strncmp(connector_name, edidname, colon - edidname)) + continue; + edidname = colon + 1; + break; + } + + if (*edidname != '\0') /* corner case: multiple ',' */ + fallback = edidname; + } + + if (!edidname) { + if (!fallback) { + kfree(fwstr); return 0; + } + edidname = fallback; } last = edidname + strlen(edidname) - 1; @@ -285,6 +308,8 @@ int drm_load_edid_firmware(struct drm_connector *connector) *last = '\0'; edid = edid_load(connector, edidname, connector_name); + kfree(fwstr); + if (IS_ERR_OR_NULL(edid)) return 0; -- cgit v0.10.2 From a5b62374618f629f5d9d6d86f3bef9b552fc980b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 31 Aug 2015 15:09:25 +0300 Subject: drm: Constify generic_edid_names[] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make generic_edid_names[] const since it's supposed to be immutable. Signed-off-by: Ville Syrjälä Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c index 1f445e9..698b8c3 100644 --- a/drivers/gpu/drm/drm_edid_load.c +++ b/drivers/gpu/drm/drm_edid_load.c @@ -32,7 +32,7 @@ MODULE_PARM_DESC(edid_firmware, "Do not probe monitor, use specified EDID blob " "from built-in data or /lib/firmware instead. "); #define GENERIC_EDIDS 6 -static const char *generic_edid_name[GENERIC_EDIDS] = { +static const char * const generic_edid_name[GENERIC_EDIDS] = { "edid/800x600.bin", "edid/1024x768.bin", "edid/1280x1024.bin", -- cgit v0.10.2 From b7c914b3d94e93bd9b442226231b0bba84c9fa2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 31 Aug 2015 15:09:26 +0300 Subject: drm: Constify TV mode names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the mode names passed to drm_mode_create_tv_properties() const. drivers/gpu/drm/i2c/ch7006.ko: -.rodata 596 +.rodata 664 -.data 7064 +.data 6992 drivers/gpu/drm/nouveau/nouveau.ko: -.rodata 146808 +.rodata 146904 -.data 178624 +.data 178528 Signed-off-by: Ville Syrjälä Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 884690c..474f328 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1519,7 +1519,7 @@ EXPORT_SYMBOL(drm_mode_create_dvi_i_properties); */ int drm_mode_create_tv_properties(struct drm_device *dev, unsigned int num_modes, - char *modes[]) + const char * const modes[]) { struct drm_property *tv_selector; struct drm_property *tv_subconnector; diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c index 51fa323..d9a72c9 100644 --- a/drivers/gpu/drm/i2c/ch7006_drv.c +++ b/drivers/gpu/drm/i2c/ch7006_drv.c @@ -119,8 +119,8 @@ static void ch7006_encoder_mode_set(struct drm_encoder *encoder, struct ch7006_encoder_params *params = &priv->params; struct ch7006_state *state = &priv->state; uint8_t *regs = state->regs; - struct ch7006_mode *mode = priv->mode; - struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; + const struct ch7006_mode *mode = priv->mode; + const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; int start_active; ch7006_dbg(client, "\n"); @@ -226,7 +226,7 @@ static int ch7006_encoder_get_modes(struct drm_encoder *encoder, struct drm_connector *connector) { struct ch7006_priv *priv = to_ch7006_priv(encoder); - struct ch7006_mode *mode; + const struct ch7006_mode *mode; int n = 0; for (mode = ch7006_modes; mode->mode.clock; mode++) { diff --git a/drivers/gpu/drm/i2c/ch7006_mode.c b/drivers/gpu/drm/i2c/ch7006_mode.c index 9b83574..f4dca53 100644 --- a/drivers/gpu/drm/i2c/ch7006_mode.c +++ b/drivers/gpu/drm/i2c/ch7006_mode.c @@ -26,7 +26,7 @@ #include "ch7006_priv.h" -char *ch7006_tv_norm_names[] = { +const char * const ch7006_tv_norm_names[] = { [TV_NORM_PAL] = "PAL", [TV_NORM_PAL_M] = "PAL-M", [TV_NORM_PAL_N] = "PAL-N", @@ -202,7 +202,7 @@ void ch7006_setup_levels(struct drm_encoder *encoder) struct i2c_client *client = drm_i2c_encoder_get_client(encoder); struct ch7006_priv *priv = to_ch7006_priv(encoder); uint8_t *regs = priv->state.regs; - struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; + const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; int gain; int black_level; diff --git a/drivers/gpu/drm/i2c/ch7006_priv.h b/drivers/gpu/drm/i2c/ch7006_priv.h index ce57784..cef6ce7 100644 --- a/drivers/gpu/drm/i2c/ch7006_priv.h +++ b/drivers/gpu/drm/i2c/ch7006_priv.h @@ -106,7 +106,7 @@ extern int ch7006_debug; extern char *ch7006_tv_norm; extern int ch7006_scale; -extern char *ch7006_tv_norm_names[]; +extern const char * const ch7006_tv_norm_names[]; extern struct ch7006_tv_norm_info ch7006_tv_norms[]; extern struct ch7006_mode ch7006_modes[]; diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 0568ae6..590ceab 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1579,7 +1579,7 @@ intel_tv_init(struct drm_device *dev) struct intel_encoder *intel_encoder; struct intel_connector *intel_connector; u32 tv_dac_on, tv_dac_off, save_tv_dac; - char *tv_format_names[ARRAY_SIZE(tv_modes)]; + const char *tv_format_names[ARRAY_SIZE(tv_modes)]; int i, initial_mode = 0; if ((I915_READ(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED) @@ -1677,7 +1677,7 @@ intel_tv_init(struct drm_device *dev) /* Create TV properties then attach current values */ for (i = 0; i < ARRAY_SIZE(tv_modes); i++) - tv_format_names[i] = (char *)tv_modes[i].name; + tv_format_names[i] = tv_modes[i].name; drm_mode_create_tv_properties(dev, ARRAY_SIZE(tv_modes), tv_format_names); diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c index 08c6f5e..903c473 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c @@ -32,7 +32,7 @@ #include "hw.h" #include "tvnv17.h" -char *nv17_tv_norm_names[NUM_TV_NORMS] = { +const char * const nv17_tv_norm_names[NUM_TV_NORMS] = { [TV_NORM_PAL] = "PAL", [TV_NORM_PAL_M] = "PAL-M", [TV_NORM_PAL_N] = "PAL-N", diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h index 459910b..1b07521c 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h @@ -85,7 +85,7 @@ struct nv17_tv_encoder { #define to_tv_enc(x) container_of(nouveau_encoder(x), \ struct nv17_tv_encoder, base) -extern char *nv17_tv_norm_names[NUM_TV_NORMS]; +extern const char * const nv17_tv_norm_names[NUM_TV_NORMS]; extern struct nv17_tv_norm_params { enum { diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index faaeff7..75f49c1 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1390,7 +1390,7 @@ extern int drm_property_add_enum(struct drm_property *property, int index, extern int drm_mode_create_dvi_i_properties(struct drm_device *dev); extern int drm_mode_create_tv_properties(struct drm_device *dev, unsigned int num_modes, - char *modes[]); + const char * const modes[]); extern int drm_mode_create_scaling_mode_property(struct drm_device *dev); extern int drm_mode_create_aspect_ratio_property(struct drm_device *dev); extern int drm_mode_create_dirty_info_property(struct drm_device *dev); -- cgit v0.10.2 From 53edb2c62e1a884f53a74899cc7e9558fd89051a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 31 Aug 2015 15:09:27 +0300 Subject: drm/i2c/ch7006: Constify ch7006_tv_norms[] and ch7006_modes[] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/gpu/drm/i2c/ch7006.ko: -.text 5913 +.text 5897 -.rodata 664 +.rodata 7256 -.data 6992 +.data 416 Signed-off-by: Ville Syrjälä Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i2c/ch7006_mode.c b/drivers/gpu/drm/i2c/ch7006_mode.c index f4dca53..bb5f67f 100644 --- a/drivers/gpu/drm/i2c/ch7006_mode.c +++ b/drivers/gpu/drm/i2c/ch7006_mode.c @@ -46,7 +46,7 @@ const char * const ch7006_tv_norm_names[] = { .vtotal = 625, \ .hvirtual = 810 -struct ch7006_tv_norm_info ch7006_tv_norms[] = { +const struct ch7006_tv_norm_info ch7006_tv_norms[] = { [TV_NORM_NTSC_M] = { NTSC_LIKE_TIMINGS, .black_level = 0.339 * fixed1, @@ -142,7 +142,7 @@ struct ch7006_tv_norm_info ch7006_tv_norms[] = { #define PAL_LIKE (1 << TV_NORM_PAL | 1 << TV_NORM_PAL_N | 1 << TV_NORM_PAL_NC) -struct ch7006_mode ch7006_modes[] = { +const struct ch7006_mode ch7006_modes[] = { MODE(21000, 512, 384, 840, 500, N, N, 181.797557582, 5_4, 0x6, PAL_LIKE), MODE(26250, 512, 384, 840, 625, N, N, 145.438046066, 1_1, 0x1, PAL_LIKE), MODE(20140, 512, 384, 800, 420, N, N, 213.257083791, 5_4, 0x4, NTSC_LIKE), @@ -171,11 +171,11 @@ struct ch7006_mode ch7006_modes[] = { {} }; -struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder, - const struct drm_display_mode *drm_mode) +const struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder, + const struct drm_display_mode *drm_mode) { struct ch7006_priv *priv = to_ch7006_priv(encoder); - struct ch7006_mode *mode; + const struct ch7006_mode *mode; for (mode = ch7006_modes; mode->mode.clock; mode++) { @@ -233,8 +233,8 @@ void ch7006_setup_subcarrier(struct drm_encoder *encoder) struct i2c_client *client = drm_i2c_encoder_get_client(encoder); struct ch7006_priv *priv = to_ch7006_priv(encoder); struct ch7006_state *state = &priv->state; - struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; - struct ch7006_mode *mode = priv->mode; + const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; + const struct ch7006_mode *mode = priv->mode; uint32_t subc_inc; subc_inc = round_fixed((mode->subc_coeff >> 8) @@ -257,7 +257,7 @@ void ch7006_setup_pll(struct drm_encoder *encoder) struct i2c_client *client = drm_i2c_encoder_get_client(encoder); struct ch7006_priv *priv = to_ch7006_priv(encoder); uint8_t *regs = priv->state.regs; - struct ch7006_mode *mode = priv->mode; + const struct ch7006_mode *mode = priv->mode; int n, best_n = 0; int m, best_m = 0; int freq, best_freq = 0; @@ -328,9 +328,9 @@ void ch7006_setup_properties(struct drm_encoder *encoder) struct i2c_client *client = drm_i2c_encoder_get_client(encoder); struct ch7006_priv *priv = to_ch7006_priv(encoder); struct ch7006_state *state = &priv->state; - struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; - struct ch7006_mode *ch_mode = priv->mode; - struct drm_display_mode *mode = &ch_mode->mode; + const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; + const struct ch7006_mode *ch_mode = priv->mode; + const struct drm_display_mode *mode = &ch_mode->mode; uint8_t *regs = state->regs; int flicker, contrast, hpos, vpos; uint64_t scale, aspect; diff --git a/drivers/gpu/drm/i2c/ch7006_priv.h b/drivers/gpu/drm/i2c/ch7006_priv.h index cef6ce7..dc6414a 100644 --- a/drivers/gpu/drm/i2c/ch7006_priv.h +++ b/drivers/gpu/drm/i2c/ch7006_priv.h @@ -78,7 +78,7 @@ struct ch7006_state { struct ch7006_priv { struct ch7006_encoder_params params; - struct ch7006_mode *mode; + const struct ch7006_mode *mode; struct ch7006_state state; struct ch7006_state saved_state; @@ -107,11 +107,11 @@ extern char *ch7006_tv_norm; extern int ch7006_scale; extern const char * const ch7006_tv_norm_names[]; -extern struct ch7006_tv_norm_info ch7006_tv_norms[]; -extern struct ch7006_mode ch7006_modes[]; +extern const struct ch7006_tv_norm_info ch7006_tv_norms[]; +extern const struct ch7006_mode ch7006_modes[]; -struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder, - const struct drm_display_mode *drm_mode); +const struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder, + const struct drm_display_mode *drm_mode); void ch7006_setup_levels(struct drm_encoder *encoder); void ch7006_setup_subcarrier(struct drm_encoder *encoder); -- cgit v0.10.2 From 825926d8e0bfa6f933706236603bb74a8cea002c Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 27 Aug 2015 13:58:09 +0200 Subject: drm/atomic: Make sure lock is held in trylock contexts. This will make sure we get a lockdep spat in all cases even if the context is a complete garbage pointer. Signed-off-by: Maarten Lankhorst Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c index fba321c..6675b14 100644 --- a/drivers/gpu/drm/drm_modeset_lock.c +++ b/drivers/gpu/drm/drm_modeset_lock.c @@ -307,6 +307,8 @@ static inline int modeset_lock(struct drm_modeset_lock *lock, WARN_ON(ctx->contended); if (ctx->trylock_only) { + lockdep_assert_held(&ctx->ww_ctx); + if (!ww_mutex_trylock(&lock->mutex)) return -EBUSY; else -- cgit v0.10.2 From 844f9111f6f54f88eb2f0fac121b82ce77193866 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 2 Sep 2015 10:42:40 +0200 Subject: drm/atomic: Make prepare_fb/cleanup_fb only take state, v3. This removes the need to separately track fb changes i915. That will be done as a separate commit, however. Changes since v1: - Add dri-devel to cc. - Fix a check in intel's prepare and cleanup fb to take rotation into account. Changes since v2: - Split out i915 changes to a separate commit. Cc: dri-devel@lists.freedesktop.org Signed-off-by: Maarten Lankhorst Reviewed-by: Daniel Stone [danvet: Squash in msm fixup from Maarten.] Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index be9fa82..36fda86 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -712,11 +712,13 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p, } static int atmel_hlcdc_plane_prepare_fb(struct drm_plane *p, - struct drm_framebuffer *fb, const struct drm_plane_state *new_state) { struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); + if (!new_state->fb) + return 0; + return atmel_hlcdc_layer_update_start(&plane->layer); } diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index a2629ee..9b0c476 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1111,17 +1111,14 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev, const struct drm_plane_helper_funcs *funcs; struct drm_plane *plane = state->planes[i]; struct drm_plane_state *plane_state = state->plane_states[i]; - struct drm_framebuffer *fb; if (!plane) continue; funcs = plane->helper_private; - fb = plane_state->fb; - - if (fb && funcs->prepare_fb) { - ret = funcs->prepare_fb(plane, fb, plane_state); + if (funcs->prepare_fb) { + ret = funcs->prepare_fb(plane, plane_state); if (ret) goto fail; } @@ -1134,17 +1131,14 @@ fail: const struct drm_plane_helper_funcs *funcs; struct drm_plane *plane = state->planes[i]; struct drm_plane_state *plane_state = state->plane_states[i]; - struct drm_framebuffer *fb; if (!plane) continue; funcs = plane->helper_private; - fb = state->plane_states[i]->fb; - - if (fb && funcs->cleanup_fb) - funcs->cleanup_fb(plane, fb, plane_state); + if (funcs->cleanup_fb) + funcs->cleanup_fb(plane, plane_state); } @@ -1300,14 +1294,11 @@ void drm_atomic_helper_cleanup_planes(struct drm_device *dev, for_each_plane_in_state(old_state, plane, plane_state, i) { const struct drm_plane_helper_funcs *funcs; - struct drm_framebuffer *old_fb; funcs = plane->helper_private; - old_fb = plane_state->fb; - - if (old_fb && funcs->cleanup_fb) - funcs->cleanup_fb(plane, old_fb, plane_state); + if (funcs->cleanup_fb) + funcs->cleanup_fb(plane, plane_state); } } EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes); diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index 5e5a07a..d384ebc 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -426,7 +426,7 @@ int drm_plane_helper_commit(struct drm_plane *plane, if (plane_funcs->prepare_fb && plane_state->fb && plane_state->fb != old_fb) { - ret = plane_funcs->prepare_fb(plane, plane_state->fb, + ret = plane_funcs->prepare_fb(plane, plane_state); if (ret) goto out; @@ -479,8 +479,8 @@ int drm_plane_helper_commit(struct drm_plane *plane, ret = 0; } - if (plane_funcs->cleanup_fb && old_fb) - plane_funcs->cleanup_fb(plane, old_fb, plane_state); + if (plane_funcs->cleanup_fb) + plane_funcs->cleanup_fb(plane, plane_state); out: if (plane_state) { if (plane->funcs->atomic_destroy_state) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ca9278b..4eb03b4 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13313,10 +13313,10 @@ static void intel_shared_dpll_init(struct drm_device *dev) */ int intel_prepare_plane_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *new_state) { struct drm_device *dev = plane->dev; + struct drm_framebuffer *fb = new_state->fb; struct intel_plane *intel_plane = to_intel_plane(plane); struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); @@ -13354,19 +13354,18 @@ intel_prepare_plane_fb(struct drm_plane *plane, */ void intel_cleanup_plane_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *old_state) { struct drm_device *dev = plane->dev; - struct drm_i915_gem_object *obj = intel_fb_obj(fb); + struct drm_i915_gem_object *obj = intel_fb_obj(old_state->fb); - if (WARN_ON(!obj)) + if (!obj) return; if (plane->type != DRM_PLANE_TYPE_CURSOR || !INTEL_INFO(dev)->cursor_needs_physical) { mutex_lock(&dev->struct_mutex); - intel_unpin_fb_obj(fb, old_state); + intel_unpin_fb_obj(old_state->fb, old_state); mutex_unlock(&dev->struct_mutex); } } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 2b9e6f9..bfd1204 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1038,10 +1038,8 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe); void intel_finish_page_flip_plane(struct drm_device *dev, int plane); void intel_check_page_flip(struct drm_device *dev, int pipe); int intel_prepare_plane_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *new_state); void intel_cleanup_plane_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *old_state); int intel_plane_atomic_get_property(struct drm_plane *plane, const struct drm_plane_state *state, diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c index e9dee36..30d57e7 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c @@ -99,22 +99,28 @@ static const struct drm_plane_funcs mdp4_plane_funcs = { }; static int mdp4_plane_prepare_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *new_state) { struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane); struct mdp4_kms *mdp4_kms = get_kms(plane); + struct drm_framebuffer *fb = new_state->fb; + + if (!fb) + return 0; DBG("%s: prepare: FB[%u]", mdp4_plane->name, fb->base.id); return msm_framebuffer_prepare(fb, mdp4_kms->id); } static void mdp4_plane_cleanup_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *old_state) { struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane); struct mdp4_kms *mdp4_kms = get_kms(plane); + struct drm_framebuffer *fb = old_state->fb; + + if (!fb) + return; DBG("%s: cleanup: FB[%u]", mdp4_plane->name, fb->base.id); msm_framebuffer_cleanup(fb, mdp4_kms->id); diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index 07fb62f..a0f5ff0 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c @@ -250,22 +250,28 @@ static const struct drm_plane_funcs mdp5_plane_funcs = { }; static int mdp5_plane_prepare_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *new_state) { struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); struct mdp5_kms *mdp5_kms = get_kms(plane); + struct drm_framebuffer *fb = new_state->fb; + + if (!new_state->fb) + return 0; DBG("%s: prepare: FB[%u]", mdp5_plane->name, fb->base.id); return msm_framebuffer_prepare(fb, mdp5_kms->id); } static void mdp5_plane_cleanup_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *old_state) { struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); struct mdp5_kms *mdp5_kms = get_kms(plane); + struct drm_framebuffer *fb = old_state->fb; + + if (!fb) + return; DBG("%s: cleanup: FB[%u]", mdp5_plane->name, fb->base.id); msm_framebuffer_cleanup(fb, mdp5_kms->id); diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 0989046..09e363b 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -60,17 +60,19 @@ to_omap_plane_state(struct drm_plane_state *state) } static int omap_plane_prepare_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *new_state) { - return omap_framebuffer_pin(fb); + if (!new_state->fb) + return 0; + + return omap_framebuffer_pin(new_state->fb); } static void omap_plane_cleanup_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *old_state) { - omap_framebuffer_unpin(fb); + if (old_state->fb) + omap_framebuffer_unpin(old_state->fb); } static void omap_plane_atomic_update(struct drm_plane *plane, diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index ddefb85..b4af4ab 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -480,14 +480,12 @@ static const struct drm_plane_funcs tegra_primary_plane_funcs = { }; static int tegra_plane_prepare_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *new_state) { return 0; } static void tegra_plane_cleanup_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *old_fb) { } diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index dda401b..5a7f9d4 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h @@ -58,10 +58,8 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, */ struct drm_plane_helper_funcs { int (*prepare_fb)(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *new_state); void (*cleanup_fb)(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *old_state); int (*atomic_check)(struct drm_plane *plane, -- cgit v0.10.2 From aef9dbb8f779ae0ffb46313b07700cac72b58ff4 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 8 Sep 2015 12:02:07 +0200 Subject: drm/atomic-helper: Add option to update planes only on active crtc With drivers supporting runtime pm it's generally not a good idea to touch the hardware when it's off. Add an option to the commit_planes helper to support this case. Note that the helpers already add all planes on a crtc when a modeset happens, hence plane updates will not be lost if drivers set this to true. v2: Check for NULL state->crtc before chasing the pointer. Also check both old and new crtc if there's a switch. Finally just outright disallow switching crtcs for a plane if the plane is in active use, on most hardware that doesn't make sense. v3: Since commit_planes(active_only = true) is for enabling things only after all the crtc are on we should only look at the new crtc to decide whether to call the plane hooks - if the current CRTC isn't on then skip. If the old crtc (when moving a plane) went down then the plane should have been disabled as part of the pipe shutdown work already. For which there's currently no helper really unfortunately. Also move the check for wether a plane gets a new CRTC assigned while still in active use out of this patch. v4: Rebase over exynos changes. Cc: Maarten Lankhorst Cc: Thierry Reding Cc: Laurent Pinchart Reviewed-by: Thierry Reding Tested-by: Thierry Reding Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 9b0c476..12c25c5 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1037,7 +1037,7 @@ int drm_atomic_helper_commit(struct drm_device *dev, drm_atomic_helper_commit_modeset_disables(dev, state); - drm_atomic_helper_commit_planes(dev, state); + drm_atomic_helper_commit_planes(dev, state, false); drm_atomic_helper_commit_modeset_enables(dev, state); @@ -1146,10 +1146,16 @@ fail: } EXPORT_SYMBOL(drm_atomic_helper_prepare_planes); +bool plane_crtc_active(struct drm_plane_state *state) +{ + return state->crtc && state->crtc->state->active; +} + /** * drm_atomic_helper_commit_planes - commit plane state * @dev: DRM device * @old_state: atomic state object with old state structures + * @active_only: Only commit on active CRTC if set * * This function commits the new plane state using the plane and atomic helper * functions for planes and crtcs. It assumes that the atomic state has already @@ -1164,7 +1170,8 @@ EXPORT_SYMBOL(drm_atomic_helper_prepare_planes); * drm_atomic_helper_commit_planes_on_crtc() instead. */ void drm_atomic_helper_commit_planes(struct drm_device *dev, - struct drm_atomic_state *old_state) + struct drm_atomic_state *old_state, + bool active_only) { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; @@ -1180,6 +1187,9 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, if (!funcs || !funcs->atomic_begin) continue; + if (active_only && !crtc->state->active) + continue; + funcs->atomic_begin(crtc, old_crtc_state); } @@ -1191,6 +1201,9 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, if (!funcs) continue; + if (active_only && !plane_crtc_active(plane->state)) + continue; + /* * Special-case disabling the plane if drivers support it. */ @@ -1210,6 +1223,9 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, if (!funcs || !funcs->atomic_flush) continue; + if (active_only && !crtc->state->active) + continue; + funcs->atomic_flush(crtc, old_crtc_state); } } diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 831d2e4..f0a5839 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -105,7 +105,7 @@ static void exynos_atomic_commit_complete(struct exynos_atomic_commit *commit) atomic_inc(&exynos_crtc->pending_update); } - drm_atomic_helper_commit_planes(dev, state); + drm_atomic_helper_commit_planes(dev, state, false); exynos_atomic_wait_for_commit(state); diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index 1ceb4f2..7eb253b 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -125,7 +125,7 @@ static void complete_commit(struct msm_commit *c) drm_atomic_helper_commit_modeset_disables(dev, state); - drm_atomic_helper_commit_planes(dev, state); + drm_atomic_helper_commit_planes(dev, state, false); drm_atomic_helper_commit_modeset_enables(dev, state); diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 419c2e4..a5f9d8b 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -96,7 +96,7 @@ static void omap_atomic_complete(struct omap_atomic_state_commit *commit) dispc_runtime_get(); drm_atomic_helper_commit_modeset_disables(dev, old_state); - drm_atomic_helper_commit_planes(dev, old_state); + drm_atomic_helper_commit_planes(dev, old_state, false); drm_atomic_helper_commit_modeset_enables(dev, old_state); omap_atomic_wait_for_completion(dev, old_state); diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 56518eb..ca12e8c 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -456,7 +456,7 @@ static void rcar_du_atomic_complete(struct rcar_du_commit *commit) /* Apply the atomic update. */ drm_atomic_helper_commit_modeset_disables(dev, old_state); drm_atomic_helper_commit_modeset_enables(dev, old_state); - drm_atomic_helper_commit_planes(dev, old_state); + drm_atomic_helper_commit_planes(dev, old_state, false); drm_atomic_helper_wait_for_vblanks(dev, old_state); diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index 6f4af6a..9f85988 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c @@ -59,7 +59,7 @@ static void sti_atomic_complete(struct sti_private *private, */ drm_atomic_helper_commit_modeset_disables(drm, state); - drm_atomic_helper_commit_planes(drm, state); + drm_atomic_helper_commit_planes(drm, state, false); drm_atomic_helper_commit_modeset_enables(drm, state); drm_atomic_helper_wait_for_vblanks(drm, state); diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 6d88cf1..2486bc2 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -56,7 +56,7 @@ static void tegra_atomic_complete(struct tegra_drm *tegra, */ drm_atomic_helper_commit_modeset_disables(drm, state); - drm_atomic_helper_commit_planes(drm, state); + drm_atomic_helper_commit_planes(drm, state, false); drm_atomic_helper_commit_modeset_enables(drm, state); drm_atomic_helper_wait_for_vblanks(drm, state); diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 11266d1..4ffe9dc 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -55,7 +55,8 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, int drm_atomic_helper_prepare_planes(struct drm_device *dev, struct drm_atomic_state *state); void drm_atomic_helper_commit_planes(struct drm_device *dev, - struct drm_atomic_state *state); + struct drm_atomic_state *state, + bool active_only); void drm_atomic_helper_cleanup_planes(struct drm_device *dev, struct drm_atomic_state *old_state); void drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state); -- cgit v0.10.2 From 6e48ae3269e3b89d8014d0eb2e35678b0d242b3d Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 8 Sep 2015 13:52:45 +0200 Subject: drm/atomic-helper: Pimp docs with recommendations for rpm drivers Requested by Laurent. Note that this uses the new markdown support which will only land in kernel 4.4 (for the code snippet). v2: A few spelling fixes I spotted myself. v3: Big reword for commit_planes() kerneldoc based on a text from Laurent. Cc: Laurent Pinchart Reviewed-by: Thierry Reding (v1 on irc) Acked-by: Laurent Pinchart Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 12c25c5..77d55a9 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -993,6 +993,22 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks); * object. This can still fail when e.g. the framebuffer reservation fails. For * now this doesn't implement asynchronous commits. * + * Note that right now this function does not support async commits, and hence + * driver writers must implement their own version for now. Also note that the + * default ordering of how the various stages are called is to match the legacy + * modeset helper library closest. One peculiarity of that is that it doesn't + * mesh well with runtime PM at all. + * + * For drivers supporting runtime PM the recommended sequence is + * + * drm_atomic_helper_commit_modeset_disables(dev, state); + * + * drm_atomic_helper_commit_modeset_enables(dev, state); + * + * drm_atomic_helper_commit_planes(dev, state, true); + * + * See the kerneldoc entries for these three functions for more details. + * * RETURNS * Zero for success or -errno. */ @@ -1168,6 +1184,22 @@ bool plane_crtc_active(struct drm_plane_state *state) * Note that this function does all plane updates across all CRTCs in one step. * If the hardware can't support this approach look at * drm_atomic_helper_commit_planes_on_crtc() instead. + * + * Plane parameters can be updated by applications while the associated CRTC is + * disabled. The DRM/KMS core will store the parameters in the plane state, + * which will be available to the driver when the CRTC is turned on. As a result + * most drivers don't need to be immediately notified of plane updates for a + * disabled CRTC. + * + * Unless otherwise needed, drivers are advised to set the @active_only + * parameters to true in order not to receive plane update notifications related + * to a disabled CRTC. This avoids the need to manually ignore plane updates in + * driver code when the driver and/or hardware can't or just don't need to deal + * with updates on disabled CRTCs, for example when supporting runtime PM. + * + * The drm_atomic_helper_commit() default implementation only sets @active_only + * to false to most closely match the behaviour of the legacy helpers. This should + * not be copied blindly by drivers. */ void drm_atomic_helper_commit_planes(struct drm_device *dev, struct drm_atomic_state *old_state, -- cgit v0.10.2 From 397fd77c0491ceb0ed4783eb88fc05d0222e2030 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 8 Sep 2015 15:00:45 +0200 Subject: drm/atomic-helper: Implement drm_atomic_helper_duplicate_state() This function can be used to duplicate an atomic state object. This is useful for example to implement suspend/resume, where the state before suspend can be saved and restored upon resume. v2: move locking to caller, be more explicit about prerequisites v3: explicitly pass lock acquisition context, improve kerneldoc Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 77d55a9..9941167 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2372,6 +2372,84 @@ drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector) EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state); /** + * drm_atomic_helper_duplicate_state - duplicate an atomic state object + * @dev: DRM device + * @ctx: lock acquisition context + * + * Makes a copy of the current atomic state by looping over all objects and + * duplicating their respective states. + * + * Note that this treats atomic state as persistent between save and restore. + * Drivers must make sure that this is possible and won't result in confusion + * or erroneous behaviour. + * + * Note that if callers haven't already acquired all modeset locks this might + * return -EDEADLK, which must be handled by calling drm_modeset_backoff(). + * + * Returns: + * A pointer to the copy of the atomic state object on success or an + * ERR_PTR()-encoded error code on failure. + */ +struct drm_atomic_state * +drm_atomic_helper_duplicate_state(struct drm_device *dev, + struct drm_modeset_acquire_ctx *ctx) +{ + struct drm_atomic_state *state; + struct drm_connector *conn; + struct drm_plane *plane; + struct drm_crtc *crtc; + int err = 0; + + state = drm_atomic_state_alloc(dev); + if (!state) + return ERR_PTR(-ENOMEM); + + state->acquire_ctx = ctx; + + drm_for_each_crtc(crtc, dev) { + struct drm_crtc_state *crtc_state; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) { + err = PTR_ERR(crtc_state); + goto free; + } + } + + drm_for_each_plane(plane, dev) { + struct drm_plane_state *plane_state; + + plane_state = drm_atomic_get_plane_state(state, plane); + if (IS_ERR(plane_state)) { + err = PTR_ERR(plane_state); + goto free; + } + } + + drm_for_each_connector(conn, dev) { + struct drm_connector_state *conn_state; + + conn_state = drm_atomic_get_connector_state(state, conn); + if (IS_ERR(conn_state)) { + err = PTR_ERR(conn_state); + goto free; + } + } + + /* clear the acquire context so that it isn't accidentally reused */ + state->acquire_ctx = NULL; + +free: + if (err < 0) { + drm_atomic_state_free(state); + state = ERR_PTR(err); + } + + return state; +} +EXPORT_SYMBOL(drm_atomic_helper_duplicate_state); + +/** * __drm_atomic_helper_connector_destroy_state - release connector state * @connector: connector object * @state: connector state object to release diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 4ffe9dc..1547eb4 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -118,6 +118,9 @@ __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector, struct drm_connector_state *state); struct drm_connector_state * drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector); +struct drm_atomic_state * +drm_atomic_helper_duplicate_state(struct drm_device *dev, + struct drm_modeset_acquire_ctx *ctx); void __drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, struct drm_connector_state *state); -- cgit v0.10.2 From 2b712be72fddc74ac12c2857af24a20a93d9e9c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 27 Aug 2015 17:23:26 +0300 Subject: drm/dp: s/I2C_STATUS/I2C_WRITE_STATUS_UPDATE/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename the I2C_STATUS request to I2C_WRITE_STATUS_UPDATE to match the spec. Acked-by: Alex Deucher Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c index 224a7dc..1cc09ff 100644 --- a/drivers/gpu/drm/tegra/dpaux.c +++ b/drivers/gpu/drm/tegra/dpaux.c @@ -149,7 +149,7 @@ static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux, break; - case DP_AUX_I2C_STATUS: + case DP_AUX_I2C_WRITE_STATUS_UPDATE: if (msg->request & DP_AUX_I2C_MOT) value |= DPAUX_DP_AUXCTL_CMD_MOT_RQ; else diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 499e9f6..d0c8810 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -46,7 +46,7 @@ #define DP_AUX_I2C_WRITE 0x0 #define DP_AUX_I2C_READ 0x1 -#define DP_AUX_I2C_STATUS 0x2 +#define DP_AUX_I2C_WRITE_STATUS_UPDATE 0x2 #define DP_AUX_I2C_MOT 0x4 #define DP_AUX_NATIVE_WRITE 0x8 #define DP_AUX_NATIVE_READ 0x9 -- cgit v0.10.2 From c1e74122fb029d30b66d9364122aef50265354aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 27 Aug 2015 17:23:27 +0300 Subject: drm/i915: Handle DP_AUX_I2C_WRITE_STATUS_UPDATE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we get an i2c defer or short ack for i2c-over-aux write we need to switch to WRITE_STATUS_UPDATE to poll for the completion of the original request. i915 doesn't try to interpret wht request type apart from separating reads from writes, and so we should be able to treat this the same as a normal i2c write. Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 0a2e33f..7bb96d5 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -974,6 +974,7 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) switch (msg->request & ~DP_AUX_I2C_MOT) { case DP_AUX_NATIVE_WRITE: case DP_AUX_I2C_WRITE: + case DP_AUX_I2C_WRITE_STATUS_UPDATE: txsize = msg->size ? HEADER_SIZE + msg->size : BARE_ADDRESS_SIZE; rxsize = 2; /* 0 or 1 data bytes */ -- cgit v0.10.2 From 1f75b29d3fc9abb06b095860f9312f8190e6015b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 27 Aug 2015 17:23:28 +0300 Subject: drm/radeon: Handle DP_AUX_I2C_WRITE_STATUS_UPDATE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we get an i2c defer or short ack for i2c-over-aux write we need to switch to WRITE_STATUS_UPDATE to poll for the completion of the original request. Looks like radeon doesn't do anything special with the request type, so hopefully just treating it the same as a i2c write is enough. Cc: Alex Deucher Cc: "Christian König" Acked-by: Alex Deucher Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 9cd49c5..bd73b40 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -179,6 +179,7 @@ radeon_dp_aux_transfer_atom(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) switch (msg->request & ~DP_AUX_I2C_MOT) { case DP_AUX_NATIVE_WRITE: case DP_AUX_I2C_WRITE: + case DP_AUX_I2C_WRITE_STATUS_UPDATE: /* The atom implementation only supports writes with a max payload of * 12 bytes since it uses 4 bits for the total count (header + payload) * in the parameter space. The atom interface supports 16 byte -- cgit v0.10.2 From f993406182b3ffad7c53ffc180b65e2b7e3d8986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 27 Aug 2015 17:23:29 +0300 Subject: drm/tegra: Handle I2C_WRITE_STATUS_UPDATE for address only writes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A address-only I2C_WRITE can't be replied with a short i2c ack, but I suppose it could be replied with an i2c defer. So the code should be prepared for an address-only I2C_WRITE_STATUS_UPDATE. Cc: Thierry Reding Cc: "Terje Bergström" Signed-off-by: Ville Syrjälä Acked-by: Thierry Reding Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c index 1cc09ff..6aecb66 100644 --- a/drivers/gpu/drm/tegra/dpaux.c +++ b/drivers/gpu/drm/tegra/dpaux.c @@ -119,6 +119,7 @@ static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux, */ if (msg->size < 1) { switch (msg->request & ~DP_AUX_I2C_MOT) { + case DP_AUX_I2C_WRITE_STATUS_UPDATE: case DP_AUX_I2C_WRITE: case DP_AUX_I2C_READ: value = DPAUX_DP_AUXCTL_CMD_ADDRESS_ONLY; -- cgit v0.10.2 From 68ec2a2a24815c0ee359b1327b60a276cd2280d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 27 Aug 2015 17:23:30 +0300 Subject: drm/dp: Use I2C_WRITE_STATUS_UPDATE to drain partial I2C_WRITE requests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When an i2c WRITE gets an i2c defer or short i2c ack reply, we are supposed to switch the request from I2C_WRITE to I2C_WRITE_STATUS_UPDATE when we continue to poll for the completion of the request. v2: Don't assume DP_AUX_I2C_WRITE is 0 even though it is, to make the code more obvious to the casual reader (Jani) Acked-by: Alex Deucher Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä [danvet: Resolve conflict due to changed context.] Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 80a02a4..5a55d90 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -422,6 +422,19 @@ static u32 drm_dp_i2c_functionality(struct i2c_adapter *adapter) I2C_FUNC_10BIT_ADDR; } +static void drm_dp_i2c_msg_write_status_update(struct drm_dp_aux_msg *msg) +{ + /* + * In case of i2c defer or short i2c ack reply to a write, + * we need to switch to WRITE_STATUS_UPDATE to drain the + * rest of the message + */ + if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_I2C_WRITE) { + msg->request &= DP_AUX_I2C_MOT; + msg->request |= DP_AUX_I2C_WRITE_STATUS_UPDATE; + } +} + /* * Transfer a single I2C-over-AUX message and handle various error conditions, * retrying the transaction as appropriate. It is assumed that the @@ -490,6 +503,8 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) * Both native ACK and I2C ACK replies received. We * can assume the transfer was successful. */ + if (ret != msg->size) + drm_dp_i2c_msg_write_status_update(msg); return ret; case DP_AUX_I2C_REPLY_NACK: @@ -507,6 +522,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) if (defer_i2c < 7) defer_i2c++; usleep_range(400, 500); + drm_dp_i2c_msg_write_status_update(msg); continue; default: @@ -519,6 +535,14 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) return -EREMOTEIO; } +static void drm_dp_i2c_msg_set_request(struct drm_dp_aux_msg *msg, + const struct i2c_msg *i2c_msg) +{ + msg->request = (i2c_msg->flags & I2C_M_RD) ? + DP_AUX_I2C_READ : DP_AUX_I2C_WRITE; + msg->request |= DP_AUX_I2C_MOT; +} + /* * Keep retrying drm_dp_i2c_do_msg until all data has been transferred. * @@ -572,10 +596,7 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, for (i = 0; i < num; i++) { msg.address = msgs[i].addr; - msg.request = (msgs[i].flags & I2C_M_RD) ? - DP_AUX_I2C_READ : - DP_AUX_I2C_WRITE; - msg.request |= DP_AUX_I2C_MOT; + drm_dp_i2c_msg_set_request(&msg, &msgs[i]); /* Send a bare address packet to start the transaction. * Zero sized messages specify an address only (bare * address) transaction. @@ -583,6 +604,13 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, msg.buffer = NULL; msg.size = 0; err = drm_dp_i2c_do_msg(aux, &msg); + + /* + * Reset msg.request in case in case it got + * changed into a WRITE_STATUS_UPDATE. + */ + drm_dp_i2c_msg_set_request(&msg, &msgs[i]); + if (err < 0) break; /* We want each transaction to be as large as possible, but @@ -595,6 +623,13 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, msg.size = min(transfer_size, msgs[i].len - j); err = drm_dp_i2c_drain_msg(aux, &msg); + + /* + * Reset msg.request in case in case it got + * changed into a WRITE_STATUS_UPDATE. + */ + drm_dp_i2c_msg_set_request(&msg, &msgs[i]); + if (err < 0) break; transfer_size = err; -- cgit v0.10.2 From 85f8fcd619d161d65c53b067e2d99590c0d7bbad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 7 Sep 2015 18:22:56 +0300 Subject: drm: Make some modes const when iterating through them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit valid_inferred_mode() don't change the modes over which it iterates, so make the iterator const. Signed-off-by: Ville Syrjälä Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 05bb731..9afb1fc 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2044,7 +2044,7 @@ mode_in_range(const struct drm_display_mode *mode, struct edid *edid, static bool valid_inferred_mode(const struct drm_connector *connector, const struct drm_display_mode *mode) { - struct drm_display_mode *m; + const struct drm_display_mode *m; bool ok = false; list_for_each_entry(m, &connector->probed_modes, head) { -- cgit v0.10.2 From 9e5a3b529e8419db1dd2b32c86a1fb42fc07347d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 7 Sep 2015 18:22:57 +0300 Subject: drm: Remove the 'mode' argument from drm_select_eld() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm_select_eld() doesn't look at the passed in mode, so don't pass it in. Signed-off-by: Ville Syrjälä Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 9afb1fc..e32218f 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -3396,7 +3396,6 @@ EXPORT_SYMBOL(drm_av_sync_delay); /** * drm_select_eld - select one ELD from multiple HDMI/DP sinks * @encoder: the encoder just changed display mode - * @mode: the adjusted display mode * * It's possible for one encoder to be associated with multiple HDMI/DP sinks. * The policy is now hard coded to simply use the first HDMI/DP sink's ELD. @@ -3404,8 +3403,7 @@ EXPORT_SYMBOL(drm_av_sync_delay); * Return: The connector associated with the first HDMI/DP sink that has ELD * attached to it. */ -struct drm_connector *drm_select_eld(struct drm_encoder *encoder, - struct drm_display_mode *mode) +struct drm_connector *drm_select_eld(struct drm_encoder *encoder) { struct drm_connector *connector; struct drm_device *dev = encoder->dev; diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index dc32cf4..1314ebb 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -401,7 +401,7 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder) struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; - connector = drm_select_eld(encoder, mode); + connector = drm_select_eld(encoder); if (!connector) return; diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 53c53c4..31528d9 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -327,8 +327,7 @@ int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads); int drm_edid_to_speaker_allocation(struct edid *edid, u8 **sadb); int drm_av_sync_delay(struct drm_connector *connector, struct drm_display_mode *mode); -struct drm_connector *drm_select_eld(struct drm_encoder *encoder, - struct drm_display_mode *mode); +struct drm_connector *drm_select_eld(struct drm_encoder *encoder); int drm_load_edid_firmware(struct drm_connector *connector); int -- cgit v0.10.2 From 3a818d350f6b5ad542175ab1f71c027787ce952e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 7 Sep 2015 18:22:58 +0300 Subject: drm: Make drm_av_sync_delay() 'mode' argument const MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm_av_sync_delay() doesn't change the passed in mode, so make it const. Signed-off-by: Ville Syrjälä Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index e32218f..d895556 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -3361,7 +3361,7 @@ EXPORT_SYMBOL(drm_edid_to_speaker_allocation); * the sink doesn't support audio or video. */ int drm_av_sync_delay(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { int i = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); int a, v; diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 31528d9..2af9769 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -326,7 +326,7 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid); int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads); int drm_edid_to_speaker_allocation(struct edid *edid, u8 **sadb); int drm_av_sync_delay(struct drm_connector *connector, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); struct drm_connector *drm_select_eld(struct drm_encoder *encoder); int drm_load_edid_firmware(struct drm_connector *connector); -- cgit v0.10.2 From 26b91ae4732be89228d207c76827071c6aecc4d8 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Wed, 9 Sep 2015 14:21:29 +0200 Subject: drm: simplify drm_sysfs_destroy() via IS_ERR_OR_NULL() Simplify `foo == NULL || IS_ERR(foo)` via IS_ERR_OR_NULL(). This is pretty commonly used all over the kernel, especially for debugfs/sysfs cleanup paths. Signed-off-by: David Herrmann Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 0f6cd33..3f66cb0 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -156,7 +156,7 @@ err_out: */ void drm_sysfs_destroy(void) { - if ((drm_class == NULL) || (IS_ERR(drm_class))) + if (IS_ERR_OR_NULL(drm_class)) return; class_remove_file(drm_class, &class_attr_version.attr); class_destroy(drm_class); -- cgit v0.10.2 From fcc9021343212f6a4a52a085b3d383ab29a9ac0a Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Wed, 9 Sep 2015 14:21:30 +0200 Subject: drm: move drm_class into drm_sysfs.c Right now, drm_sysfs_create() returns the newly allocated "struct class" to the caller (which is drm_core_init()), which then has to set the global variable 'drm_class'. During cleanup, though, we call drm_sysfs_destroy() which implicitly uses the global 'drm_class'. This is confusing, as ownership of the global 'drm_class' is non-obvious. This patch changes drm_sysfs_create() to drm_sysfs_init() and makes it initialize the 'drm_class' object directly, rather than returning it. This way, both drm_sysfs_init() and drm_sysfs_destroy() work in a similar fashion and manage the global drm class. Signed-off-by: David Herrmann Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index dc93c88..9ad823f 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -55,7 +55,6 @@ module_param_named(debug, drm_debug, int, 0600); static DEFINE_SPINLOCK(drm_minor_lock); static struct idr drm_minors_idr; -struct class *drm_class; static struct dentry *drm_debugfs_root; void drm_err(const char *format, ...) @@ -841,10 +840,9 @@ static int __init drm_core_init(void) if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops)) goto err_p1; - drm_class = drm_sysfs_create(THIS_MODULE, "drm"); - if (IS_ERR(drm_class)) { + ret = drm_sysfs_init(); + if (ret < 0) { printk(KERN_ERR "DRM: Error creating drm class.\n"); - ret = PTR_ERR(drm_class); goto err_p2; } diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 059af01..43cbda3 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -73,7 +73,7 @@ int drm_authmagic(struct drm_device *dev, void *data, /* drm_sysfs.c */ extern struct class *drm_class; -struct class *drm_sysfs_create(struct module *owner, char *name); +int drm_sysfs_init(void); void drm_sysfs_destroy(void); struct device *drm_sysfs_minor_alloc(struct drm_minor *minor); int drm_sysfs_connector_add(struct drm_connector *connector); diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 3f66cb0..f08873f 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -30,6 +30,8 @@ static struct device_type drm_sysfs_device_minor = { .name = "drm_minor" }; +struct class *drm_class; + /** * __drm_class_suspend - internal DRM class suspend routine * @dev: Linux device to suspend @@ -112,41 +114,34 @@ static CLASS_ATTR_STRING(version, S_IRUGO, CORE_DATE); /** - * drm_sysfs_create - create a struct drm_sysfs_class structure - * @owner: pointer to the module that is to "own" this struct drm_sysfs_class - * @name: pointer to a string for the name of this class. + * drm_sysfs_init - initialize sysfs helpers + * + * This is used to create the DRM class, which is the implicit parent of any + * other top-level DRM sysfs objects. * - * This is used to create DRM class pointer that can then be used - * in calls to drm_sysfs_device_add(). + * You must call drm_sysfs_destroy() to release the allocated resources. * - * Note, the pointer created here is to be destroyed when finished by making a - * call to drm_sysfs_destroy(). + * Return: 0 on success, negative error code on failure. */ -struct class *drm_sysfs_create(struct module *owner, char *name) +int drm_sysfs_init(void) { - struct class *class; int err; - class = class_create(owner, name); - if (IS_ERR(class)) { - err = PTR_ERR(class); - goto err_out; - } - - class->pm = &drm_class_dev_pm_ops; + drm_class = class_create(THIS_MODULE, "drm"); + if (IS_ERR(drm_class)) + return PTR_ERR(drm_class); - err = class_create_file(class, &class_attr_version.attr); - if (err) - goto err_out_class; + drm_class->pm = &drm_class_dev_pm_ops; - class->devnode = drm_devnode; - - return class; + err = class_create_file(drm_class, &class_attr_version.attr); + if (err) { + class_destroy(drm_class); + drm_class = NULL; + return err; + } -err_out_class: - class_destroy(class); -err_out: - return ERR_PTR(err); + drm_class->devnode = drm_devnode; + return 0; } /** -- cgit v0.10.2 From c099b55a6fa6f9ec2f26105c76df462d7c7c7d5b Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 9 Sep 2015 13:46:21 +0200 Subject: drm/core: Do not call drm_framebuffer_remove internally during teardown. This may cause issues because encoders are already destroyed so removing active primaries may use freed memory. Instead free the fb directly, ignoring refcount. Signed-off-by: Maarten Lankhorst Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 474f328..9b9c4b4 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -5742,7 +5742,7 @@ void drm_mode_config_cleanup(struct drm_device *dev) */ WARN_ON(!list_empty(&dev->mode_config.fb_list)); list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { - drm_framebuffer_remove(fb); + drm_framebuffer_free(&fb->refcount); } list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list, -- cgit v0.10.2 From e848f754257d7dec2b9a395a15dce22758492d84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 14 Mar 2014 15:53:52 +0100 Subject: ARM: efm32: switch to properly namespaced location property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commits: 281ec367bff4 (i2c: efm32: correct namespacing of location property) d36f47fa8419 (serial: efm32: correct namespacing of location property) 10ed7e9847b6 (spi: efm32: correct namespacing of location property) (contained in 3.17-rc1) all drivers support the correctly namespaced location property. So use the better names now. Signed-off-by: Uwe Kleine-König diff --git a/arch/arm/boot/dts/efm32gg-dk3750.dts b/arch/arm/boot/dts/efm32gg-dk3750.dts index b4031fa..504cf45 100644 --- a/arch/arm/boot/dts/efm32gg-dk3750.dts +++ b/arch/arm/boot/dts/efm32gg-dk3750.dts @@ -26,7 +26,7 @@ }; i2c@4000a000 { - efm32,location = <3>; + energymicro,location = <3>; status = "ok"; temp@48 { @@ -43,7 +43,7 @@ spi0: spi@4000c000 { /* USART0 */ cs-gpios = <&gpio 68 1>; // E4 - location = <1>; + energymicro,location = <1>; status = "ok"; microsd@0 { @@ -57,7 +57,7 @@ spi1: spi@4000c400 { /* USART1 */ cs-gpios = <&gpio 51 1>; // D3 - location = <1>; + energymicro,location = <1>; status = "ok"; ks8851@0 { @@ -70,7 +70,7 @@ }; uart4: uart@4000e400 { /* UART1 */ - location = <2>; + energymicro,location = <2>; status = "ok"; }; -- cgit v0.10.2 From f719a0d6a8541b383c506aaa4b4fa6b4109669f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 25 Mar 2014 11:27:25 +0100 Subject: ARM: efm32: switch to vendor,device compatible strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The mainline drivers were fixed in commits - 4ea8dafd2475 (serial: efm32: use $vendor,$device scheme for compatible string) - 12f6dd860cf8 (spi: efm32: use $vendor,$device scheme for compatible string) - 63cc122381bd (clocksource: efm32: use $vendor,$device scheme for compatible string) which are all in 3.16-rc1 to also support these compatible strings. For the other affected peripherals (adc and gpio) there are no drivers in mainline yet. Signed-off-by: Uwe Kleine-König diff --git a/arch/arm/boot/dts/efm32gg.dtsi b/arch/arm/boot/dts/efm32gg.dtsi index 106d505..c747983 100644 --- a/arch/arm/boot/dts/efm32gg.dtsi +++ b/arch/arm/boot/dts/efm32gg.dtsi @@ -23,7 +23,7 @@ soc { adc: adc@40002000 { - compatible = "efm32,adc"; + compatible = "energymicro,efm32-adc"; reg = <0x40002000 0x400>; interrupts = <7>; clocks = <&cmu clk_HFPERCLKADC0>; @@ -31,7 +31,7 @@ }; gpio: gpio@40006000 { - compatible = "efm32,gpio"; + compatible = "energymicro,efm32-gpio"; reg = <0x40006000 0x1000>; interrupts = <1 11>; gpio-controller; @@ -45,7 +45,7 @@ i2c0: i2c@4000a000 { #address-cells = <1>; #size-cells = <0>; - compatible = "efm32,i2c"; + compatible = "energymicro,efm32-i2c"; reg = <0x4000a000 0x400>; interrupts = <9>; clocks = <&cmu clk_HFPERCLKI2C0>; @@ -56,7 +56,7 @@ i2c1: i2c@4000a400 { #address-cells = <1>; #size-cells = <0>; - compatible = "efm32,i2c"; + compatible = "energymicro,efm32-i2c"; reg = <0x4000a400 0x400>; interrupts = <10>; clocks = <&cmu clk_HFPERCLKI2C1>; @@ -67,7 +67,7 @@ spi0: spi@4000c000 { /* USART0 */ #address-cells = <1>; #size-cells = <0>; - compatible = "efm32,spi"; + compatible = "energymicro,efm32-spi"; reg = <0x4000c000 0x400>; interrupts = <3 4>; clocks = <&cmu clk_HFPERCLKUSART0>; @@ -77,7 +77,7 @@ spi1: spi@4000c400 { /* USART1 */ #address-cells = <1>; #size-cells = <0>; - compatible = "efm32,spi"; + compatible = "energymicro,efm32-spi"; reg = <0x4000c400 0x400>; interrupts = <15 16>; clocks = <&cmu clk_HFPERCLKUSART1>; @@ -87,7 +87,7 @@ spi2: spi@4000c800 { /* USART2 */ #address-cells = <1>; #size-cells = <0>; - compatible = "efm32,spi"; + compatible = "energymicro,efm32-spi"; reg = <0x4000c800 0x400>; interrupts = <18 19>; clocks = <&cmu clk_HFPERCLKUSART2>; @@ -95,7 +95,7 @@ }; uart0: uart@4000c000 { /* USART0 */ - compatible = "efm32,uart"; + compatible = "energymicro,efm32-uart"; reg = <0x4000c000 0x400>; interrupts = <3 4>; clocks = <&cmu clk_HFPERCLKUSART0>; @@ -103,7 +103,7 @@ }; uart1: uart@4000c400 { /* USART1 */ - compatible = "efm32,uart"; + compatible = "energymicro,efm32-uart"; reg = <0x4000c400 0x400>; interrupts = <15 16>; clocks = <&cmu clk_HFPERCLKUSART1>; @@ -111,7 +111,7 @@ }; uart2: uart@4000c800 { /* USART2 */ - compatible = "efm32,uart"; + compatible = "energymicro,efm32-uart"; reg = <0x4000c800 0x400>; interrupts = <18 19>; clocks = <&cmu clk_HFPERCLKUSART2>; @@ -119,7 +119,7 @@ }; uart3: uart@4000e000 { /* UART0 */ - compatible = "efm32,uart"; + compatible = "energymicro,efm32-uart"; reg = <0x4000e000 0x400>; interrupts = <20 21>; clocks = <&cmu clk_HFPERCLKUART0>; @@ -127,7 +127,7 @@ }; uart4: uart@4000e400 { /* UART1 */ - compatible = "efm32,uart"; + compatible = "energymicro,efm32-uart"; reg = <0x4000e400 0x400>; interrupts = <22 23>; clocks = <&cmu clk_HFPERCLKUART1>; @@ -135,28 +135,28 @@ }; timer0: timer@40010000 { - compatible = "efm32,timer"; + compatible = "energymicro,efm32-timer"; reg = <0x40010000 0x400>; interrupts = <2>; clocks = <&cmu clk_HFPERCLKTIMER0>; }; timer1: timer@40010400 { - compatible = "efm32,timer"; + compatible = "energymicro,efm32-timer"; reg = <0x40010400 0x400>; interrupts = <12>; clocks = <&cmu clk_HFPERCLKTIMER1>; }; timer2: timer@40010800 { - compatible = "efm32,timer"; + compatible = "energymicro,efm32-timer"; reg = <0x40010800 0x400>; interrupts = <13>; clocks = <&cmu clk_HFPERCLKTIMER2>; }; timer3: timer@40010c00 { - compatible = "efm32,timer"; + compatible = "energymicro,efm32-timer"; reg = <0x40010c00 0x400>; interrupts = <14>; clocks = <&cmu clk_HFPERCLKTIMER3>; -- cgit v0.10.2 From d8b4c43a4baccecee7106c1432baa986fab9593a Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Fri, 4 Sep 2015 18:56:11 +0530 Subject: drm/i915: add attached connector to hdmi container This patch adds the intel_connector initialized to intel_hdmi display, during the init phase, just like the other encoders do. This attachment is very useful when we need to extract the connector pointer during the hotplug handler function Signed-off-by: Shashank Sharma Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 2bdd544..129d99e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -669,6 +669,7 @@ struct intel_hdmi { enum hdmi_force_audio force_audio; bool rgb_quant_range_selectable; enum hdmi_picture_aspect aspect_ratio; + struct intel_connector *attached_connector; void (*write_infoframe)(struct drm_encoder *encoder, enum hdmi_infoframe_type type, const void *frame, ssize_t len); diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index feb31d8..e978c59 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -2120,6 +2120,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, intel_connector_attach_encoder(intel_connector, intel_encoder); drm_connector_register(connector); + intel_hdmi->attached_connector = intel_connector; /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written * 0xd. Failure to do so will result in spurious interrupts being -- cgit v0.10.2 From d4b08630fb6e3fe9948456b09feb223fba2b48a6 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 10 Sep 2015 16:07:56 +0200 Subject: drm/i915: Use atomic plane state in the primary plane update. Signed-off-by: Maarten Lankhorst Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 110b8dc..0f5df11 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13427,7 +13427,9 @@ intel_commit_primary_plane(struct drm_plane *plane, /* FIXME: kill this fastboot hack */ intel_update_pipe_size(intel_crtc); - dev_priv->display.update_primary_plane(crtc, fb, crtc->x, crtc->y); + dev_priv->display.update_primary_plane(crtc, fb, + state->src.x1 >> 16, + state->src.y1 >> 16); } static void -- cgit v0.10.2 From 23a48d5323bc488f0e350467996e7226f902e0a7 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 10 Sep 2015 16:07:57 +0200 Subject: drm/i915: Use the plane state in intel_crtc_info. Legacy state might not be updated any more. Signed-off-by: Maarten Lankhorst Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 41629fa..72ae347 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2817,11 +2817,13 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *intel_crtc) struct drm_device *dev = node->minor->dev; struct drm_crtc *crtc = &intel_crtc->base; struct intel_encoder *intel_encoder; + struct drm_plane_state *plane_state = crtc->primary->state; + struct drm_framebuffer *fb = plane_state->fb; - if (crtc->primary->fb) + if (fb) seq_printf(m, "\tfb: %d, pos: %dx%d, size: %dx%d\n", - crtc->primary->fb->base.id, crtc->x, crtc->y, - crtc->primary->fb->width, crtc->primary->fb->height); + fb->base.id, plane_state->src_x >> 16, + plane_state->src_y >> 16, fb->width, fb->height); else seq_puts(m, "\tprimary plane disabled\n"); for_each_encoder_on_crtc(dev, crtc, intel_encoder) -- cgit v0.10.2 From 11c22da619101a5a4332df718268e6214e3919f3 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 10 Sep 2015 16:07:58 +0200 Subject: drm/i915: Use the atomic state in intel_update_primary_planes. This function was still using the legacy state, convert it to atomic. While we're at it, fix the FIXME too and disable the primary plane. v2 (Daniel): - Add FIXME explaining that update_primary_planes should soon get removed anyway. - Don't call ->disable_plane since we can't disable the primary plane with a CS flip (noticed by Ville). Signed-off-by: Maarten Lankhorst (v1) Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0f5df11..b7e6158 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3135,24 +3135,20 @@ static void intel_complete_page_flips(struct drm_device *dev) static void intel_update_primary_planes(struct drm_device *dev) { - struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc; for_each_crtc(dev, crtc) { - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_plane *plane = to_intel_plane(crtc->primary); + struct intel_plane_state *plane_state; - drm_modeset_lock(&crtc->mutex, NULL); - /* - * FIXME: Once we have proper support for primary planes (and - * disabling them without disabling the entire crtc) allow again - * a NULL crtc->primary->fb. - */ - if (intel_crtc->active && crtc->primary->fb) - dev_priv->display.update_primary_plane(crtc, - crtc->primary->fb, - crtc->x, - crtc->y); - drm_modeset_unlock(&crtc->mutex); + drm_modeset_lock_crtc(crtc, &plane->base); + + plane_state = to_intel_plane_state(plane->base.state); + + if (plane_state->base.fb) + plane->commit_plane(&plane->base, plane_state); + + drm_modeset_unlock_crtc(crtc); } } @@ -3196,6 +3192,9 @@ void intel_finish_reset(struct drm_device *dev) * so update the base address of all primary * planes to the the last fb to make sure we're * showing the correct fb after a reset. + * + * FIXME: Atomic will make this obsolete since we won't schedule + * CS-based flips (which might get lost in gpu resets) any more. */ intel_update_primary_planes(dev); return; -- cgit v0.10.2 From 9b4101be5bb165484d143629d17d084d76fdd77c Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 10 Sep 2015 16:07:59 +0200 Subject: drm/i915: Use atomic state when changing cursor visibility. Signed-off-by: Maarten Lankhorst Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b7e6158..ea3a4a5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9916,8 +9916,9 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; - int x = crtc->cursor_x; - int y = crtc->cursor_y; + struct drm_plane_state *cursor_state = crtc->cursor->state; + int x = cursor_state->crtc_x; + int y = cursor_state->crtc_y; u32 base = 0, pos = 0; if (on) @@ -9930,7 +9931,7 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, base = 0; if (x < 0) { - if (x + intel_crtc->base.cursor->state->crtc_w <= 0) + if (x + cursor_state->crtc_w <= 0) base = 0; pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT; @@ -9939,7 +9940,7 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, pos |= x << CURSOR_X_SHIFT; if (y < 0) { - if (y + intel_crtc->base.cursor->state->crtc_h <= 0) + if (y + cursor_state->crtc_h <= 0) base = 0; pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT; @@ -9955,8 +9956,8 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, /* ILK+ do this automagically */ if (HAS_GMCH_DISPLAY(dev) && crtc->cursor->state->rotation == BIT(DRM_ROTATE_180)) { - base += (intel_crtc->base.cursor->state->crtc_h * - intel_crtc->base.cursor->state->crtc_w - 1) * 4; + base += (cursor_state->crtc_h * + cursor_state->crtc_w - 1) * 4; } if (IS_845G(dev) || IS_I865G(dev)) -- cgit v0.10.2 From 8e0e9ceaa05317c6644635f8816705b609f2c274 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 10 Sep 2015 16:08:00 +0200 Subject: drm/i915: Remove legacy plane updates for cursor and sprite planes. Unfortunately fbc still depends on legacy primary state, so it can't be killed off completely yet. Signed-off-by: Maarten Lankhorst Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ea3a4a5..62573d5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13634,10 +13634,6 @@ intel_commit_cursor_plane(struct drm_plane *plane, crtc = crtc ? crtc : plane->crtc; intel_crtc = to_intel_crtc(crtc); - plane->fb = state->base.fb; - crtc->cursor_x = state->base.crtc_x; - crtc->cursor_y = state->base.crtc_y; - if (intel_crtc->cursor_bo == obj) goto update; diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index ca7e264..9553859 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -927,8 +927,6 @@ intel_commit_sprite_plane(struct drm_plane *plane, crtc = crtc ? crtc : plane->crtc; - plane->fb = fb; - if (!crtc->state->active) return; -- cgit v0.10.2 From bca8013ec24210087bfed49678ec821c811982b1 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 10 Sep 2015 16:08:02 +0200 Subject: drm/i915: Do not handle a null plane state. With the conversion to atomic this cannot happen any more. Signed-off-by: Maarten Lankhorst Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index f1ab8e4..a119806 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -76,11 +76,7 @@ intel_plane_duplicate_state(struct drm_plane *plane) struct drm_plane_state *state; struct intel_plane_state *intel_state; - if (WARN_ON(!plane->state)) - intel_state = intel_create_plane_state(plane); - else - intel_state = kmemdup(plane->state, sizeof(*intel_state), - GFP_KERNEL); + intel_state = kmemdup(plane->state, sizeof(*intel_state), GFP_KERNEL); if (!intel_state) return NULL; -- cgit v0.10.2 From f2a066f3dee8a0e37015d15298e14e9ad6c0a53d Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 10 Sep 2015 16:08:03 +0200 Subject: drm/i915: Use crtc->state for duplication. In async mode crtc->config can be updated after the locks are released, resulting in the wrong state being duplicated. Note that this also removes a spurious assignment of crtc_state->crtc introduced in commit f0c60574eb1216b0904c0d696c64d5096d6e4913 Author: Ander Conselvan de Oliveira Date: Tue Apr 21 17:12:58 2015 +0300 drm/i915: Call drm helpers when duplicating crtc and plane states Signed-off-by: Maarten Lankhorst Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 9336e80..2c4b1c4 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -85,22 +85,14 @@ intel_connector_atomic_get_property(struct drm_connector *connector, struct drm_crtc_state * intel_crtc_duplicate_state(struct drm_crtc *crtc) { - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc_state *crtc_state; - if (WARN_ON(!intel_crtc->config)) - crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL); - else - crtc_state = kmemdup(intel_crtc->config, - sizeof(*intel_crtc->config), GFP_KERNEL); - + crtc_state = kmemdup(crtc->state, sizeof(*crtc_state), GFP_KERNEL); if (!crtc_state) return NULL; __drm_atomic_helper_crtc_duplicate_state(crtc, &crtc_state->base); - crtc_state->base.crtc = crtc; - return &crtc_state->base; } -- cgit v0.10.2 From f0fea8dd362c77a06e7b8744d63f429fe065c6b4 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 8 Sep 2015 12:52:48 +0100 Subject: drm/i915: Remove one very outdated comment Comment disagrees with the code which has changed a lot since it was documented. Note that the logic to remove -EIO handling was dropped in commit 1488fc08c1706288616c602416654fd38c773deb Author: Chris Wilson Date: Tue Apr 24 15:47:31 2012 +0100 drm/i915: Remove the deferred-free list Signed-off-by: Tvrtko Ursulin Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 41263cd..760cfba 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3230,10 +3230,6 @@ int i915_vma_unbind(struct i915_vma *vma) ret = i915_gem_object_wait_rendering(obj, false); if (ret) return ret; - /* Continue on if we fail due to EIO, the GPU is hung so we - * should be safe and we need to cleanup or else we might - * cause memory corruption through use-after-free. - */ if (i915_is_ggtt(vma->vm) && vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL) { -- cgit v0.10.2 From c86fb9d997428e0d55ab5a47488b6ba3bc4b5c5b Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 10 Sep 2015 22:39:22 +0200 Subject: drm: Nuke drm_framebuffer->helper_private It's completely unused and there's really no reason for this: - drm_framebuffer structures are invariant after creation, no need for helpers to manipulate them. - drm_framebuffer structures should just be embedded (and that's what all the drivers do). Stumbled over this since some folks are apparently concerned with the overhead of struct drm_framebuffer and this is an easy 8 byte saving. More could be gained by ditching the legacy fields and recomputing stuff from the fourcc value. But that would require some drm-wide cocci and real justification. Cc: gary.k.smith@intel.com Reviewed-by: David Herrmann Signed-off-by: Daniel Vetter diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 75f49c1..c0366e9 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -210,8 +210,6 @@ struct drm_framebuffer { int flags; uint32_t pixel_format; /* fourcc format */ struct list_head filp_head; - /* if you are using the helper */ - void *helper_private; }; struct drm_property_blob { -- cgit v0.10.2 From fd1ee4cc9326c97b52154ee2ef8cdd23ac6aae1c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 11 Sep 2015 21:57:24 +0200 Subject: drm/i915: Update DRIVER_DATE to 20150911 Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3e46187..da0f264 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -57,7 +57,7 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20150828" +#define DRIVER_DATE "20150911" #undef WARN_ON /* Many gcc seem to no see through this and fall over :( */ -- cgit v0.10.2 From 22374fbedb2ce03ef81323b3f7ceb3fa29344aa6 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Mon, 29 Jun 2015 15:22:34 +0200 Subject: ARM: dts: Add DMA support for serial ports in exynos4 Enable DMA transfers for serial ports. Signed-off-by: Robert Baldyga Signed-off-by: Krzysztof Kozlowski diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi index 98c0a36..3184e10 100644 --- a/arch/arm/boot/dts/exynos4.dtsi +++ b/arch/arm/boot/dts/exynos4.dtsi @@ -431,6 +431,8 @@ interrupts = <0 52 0>; clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>; clock-names = "uart", "clk_uart_baud0"; + dmas = <&pdma0 15>, <&pdma0 16>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -440,6 +442,8 @@ interrupts = <0 53 0>; clocks = <&clock CLK_UART1>, <&clock CLK_SCLK_UART1>; clock-names = "uart", "clk_uart_baud0"; + dmas = <&pdma1 15>, <&pdma1 16>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -449,6 +453,8 @@ interrupts = <0 54 0>; clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>; clock-names = "uart", "clk_uart_baud0"; + dmas = <&pdma0 17>, <&pdma0 18>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -458,6 +464,8 @@ interrupts = <0 55 0>; clocks = <&clock CLK_UART3>, <&clock CLK_SCLK_UART3>; clock-names = "uart", "clk_uart_baud0"; + dmas = <&pdma1 17>, <&pdma1 18>; + dma-names = "rx", "tx"; status = "disabled"; }; -- cgit v0.10.2 From fec794c7717eaf724542c56fda5f7090f23cefab Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 4 Aug 2015 23:30:09 +0200 Subject: ARM: dts: sun4i: Enable otg in host only mode on Jesurun Q5 The Jesurun Q5 has the musb hooked up to an usb-a receptacle, enable it in host-only mode. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts b/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts index dc2f2ae..7afc7a6 100644 --- a/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts +++ b/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts @@ -156,6 +156,10 @@ status = "okay"; }; +&otg_sram { + status = "okay"; +}; + &pio { emac_power_pin_q5: emac_power_pin@0 { allwinner,pins = "PH19"; @@ -172,6 +176,11 @@ }; }; +®_usb0_vbus { + regulator-boot-on; + status = "okay"; +}; + ®_usb1_vbus { status = "okay"; }; @@ -186,7 +195,13 @@ status = "okay"; }; +&usb_otg { + dr_mode = "host"; + status = "okay"; +}; + &usbphy { + usb0_vbus-supply = <®_usb0_vbus>; usb1_vbus-supply = <®_usb1_vbus>; usb2_vbus-supply = <®_usb2_vbus>; status = "okay"; -- cgit v0.10.2 From bcbf506d777d2627cb8f68755816fab04eb8b852 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 8 Aug 2015 17:38:54 +0200 Subject: ARM: dts: sun4i: Enable i2c1 and i2c2 on the Chuwi V7-CW0825 tablet i2c1 has a freescale mma7660 accelerometer connected to it at addr 0x4c, i2c2 has a ft5x touchscreen connected to it at addr 0x38. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun4i-a10-chuwi-v7-cw0825.dts b/arch/arm/boot/dts/sun4i-a10-chuwi-v7-cw0825.dts index 1430568..5366089 100644 --- a/arch/arm/boot/dts/sun4i-a10-chuwi-v7-cw0825.dts +++ b/arch/arm/boot/dts/sun4i-a10-chuwi-v7-cw0825.dts @@ -78,6 +78,18 @@ }; }; +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; +}; + &lradc { vref-supply = <®_vcc3v0>; status = "okay"; -- cgit v0.10.2 From 9ff5052f7561068207c2b0e7590ad8ca5765f2cc Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Sun, 9 Aug 2015 20:22:58 +0200 Subject: ARM: dts: sunxi: enable otg port on the sun7i-a20-olinuxino-lime2 This patch enables the musb-otg USB controller on the Lime2. The Lime2 differs from the Lime1 series in pins used for usb0 power. Tested on a OlinuXino Lime2-4GB. Signed-off-by: Olliver Schinagl Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts index 8acff78..913032f 100644 --- a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts @@ -190,6 +190,10 @@ status = "okay"; }; +&otg_sram { + status = "okay"; +}; + &pio { ahci_pwr_pin_olinuxinolime: ahci_pwr_pin@1 { allwinner,pins = "PC3"; @@ -204,6 +208,27 @@ allwinner,drive = ; allwinner,pull = ; }; + + usb0_id_detect_pin: usb0_id_detect_pin@0 { + allwinner,pins = "PH4"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb0_vbus_detect_pin: usb0_vbus_detect_pin@0 { + allwinner,pins = "PH5"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb0_vbus_pin_lime2: usb0_vbus_pin@0 { + allwinner,pins = "PC17"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; }; ®_ahci_5v { @@ -212,6 +237,12 @@ status = "okay"; }; +®_usb0_vbus { + pinctrl-0 = <&usb0_vbus_pin_lime2>; + gpio = <&pio 2 17 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + ®_usb1_vbus { status = "okay"; }; @@ -226,7 +257,17 @@ status = "okay"; }; +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + &usbphy { + pinctrl-names = "default"; + pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>; + usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */ + usb0_vbus_det-gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */ + usb0_vbus-supply = <®_usb0_vbus>; usb1_vbus-supply = <®_usb1_vbus>; usb2_vbus-supply = <®_usb2_vbus>; status = "okay"; -- cgit v0.10.2 From 216c59d65f99aa1ef1a92e1ae64f1f1c2590dddc Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 11 Sep 2015 00:07:19 +0300 Subject: drm/atomic-helper: Don't skip plane disabling on active CRTC Since commit "drm/atomic-helper: Add option to update planes only on active crtc" the drm_atomic_helper_commit_planes() function accepts an active_only argument to skip updating planes when the associated CRTC is inactive. Planes being disabled on an active CRTC are incorrectly considered as associated with an inactive CRTC and are thus skipped, preventing any plane disabling update from reaching drivers. Fix it by checking the state of the CRTC stored in the old plane state for planes being disabled. Signed-off-by: Laurent Pinchart Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 9941167..94d6c8e 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1227,23 +1227,35 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, for_each_plane_in_state(old_state, plane, old_plane_state, i) { const struct drm_plane_helper_funcs *funcs; + bool disabling; funcs = plane->helper_private; if (!funcs) continue; - if (active_only && !plane_crtc_active(plane->state)) - continue; + disabling = drm_atomic_plane_disabling(plane, old_plane_state); + + if (active_only) { + /* + * Skip planes related to inactive CRTCs. If the plane + * is enabled use the state of the current CRTC. If the + * plane is being disabled use the state of the old + * CRTC to avoid skipping planes being disabled on an + * active CRTC. + */ + if (!disabling && !plane_crtc_active(plane->state)) + continue; + if (disabling && !plane_crtc_active(old_plane_state)) + continue; + } /* * Special-case disabling the plane if drivers support it. */ - if (drm_atomic_plane_disabling(plane, old_plane_state) && - funcs->atomic_disable) + if (disabling && funcs->atomic_disable) funcs->atomic_disable(plane, old_plane_state); - else if (plane->state->crtc || - drm_atomic_plane_disabling(plane, old_plane_state)) + else if (plane->state->crtc || disabling) funcs->atomic_update(plane, old_plane_state); } -- cgit v0.10.2 From 08a0a2409fd0684a1184bf90486b0286a2ba1194 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 4 Aug 2015 20:03:06 +0200 Subject: ARM: shmobile: Remove unused declaration of r8a7778_add_standard_devices_dt() The actual implementation was removed by commit 40216263d3d0b9b4 ("ARM: shmobile: Remove unused r8a7778 auxdata and callback") in v3.12. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/mach-shmobile/r8a7778.h b/arch/arm/mach-shmobile/r8a7778.h index f64fedb..0e77f3f 100644 --- a/arch/arm/mach-shmobile/r8a7778.h +++ b/arch/arm/mach-shmobile/r8a7778.h @@ -63,7 +63,6 @@ enum { }; extern void r8a7778_add_standard_devices(void); -extern void r8a7778_add_standard_devices_dt(void); extern void r8a7778_add_dt_devices(void); extern void r8a7778_init_late(void); -- cgit v0.10.2 From 26449ecc21dd690f5bc686fbee8037587c77ac5e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 4 Aug 2015 20:03:07 +0200 Subject: ARM: shmobile: Remove obsolete sh-gpio.h The last user of "sh-gpio.h" was removed in commit 1fa59bda21c7fa36 ("ARM: shmobile: Remove legacy board code for Armadillo-800 EVA"). Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/mach-shmobile/sh-gpio.h b/arch/arm/mach-shmobile/sh-gpio.h deleted file mode 100644 index 2c41414..0000000 --- a/arch/arm/mach-shmobile/sh-gpio.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Generic GPIO API and pinmux table support - * - * Copyright (c) 2008 Magnus Damm - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#ifndef __ASM_ARCH_GPIO_H -#define __ASM_ARCH_GPIO_H - -#include -#include -#include - -/* - * FIXME !! - * - * current gpio frame work doesn't have - * the method to control only pull up/down/free. - * this function should be replaced by correct gpio function - */ -static inline void __init gpio_direction_none(void __iomem * addr) -{ - __raw_writeb(0x00, addr); -} - -#endif /* __ASM_ARCH_GPIO_H */ -- cgit v0.10.2 From 815fc8c06b57f283f942c6c25e3c58d6e4cb8fd7 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 4 Aug 2015 20:03:08 +0200 Subject: ARM: shmobile: Remove obsolete custom earlyprintk code The last caller of shmobile_setup_console() was removed in commit 44d88c754e57a6d9 ("ARM: shmobile: Remove legacy SoC code for R-Mobile A1"). Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index 476de30..b028415 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -3,7 +3,7 @@ # # Common objects -obj-y := timer.o console.o +obj-y := timer.o # CPU objects obj-$(CONFIG_ARCH_SH73A0) += setup-sh73a0.o diff --git a/arch/arm/mach-shmobile/common.h b/arch/arm/mach-shmobile/common.h index 8d27ec5..ee8fe9e 100644 --- a/arch/arm/mach-shmobile/common.h +++ b/arch/arm/mach-shmobile/common.h @@ -4,7 +4,6 @@ extern void shmobile_earlytimer_init(void); extern void shmobile_init_delay(void); struct twd_local_timer; -extern void shmobile_setup_console(void); extern void shmobile_boot_vector(void); extern unsigned long shmobile_boot_fn; extern unsigned long shmobile_boot_arg; diff --git a/arch/arm/mach-shmobile/console.c b/arch/arm/mach-shmobile/console.c deleted file mode 100644 index e329ccb..0000000 --- a/arch/arm/mach-shmobile/console.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * SH-Mobile Console - * - * Copyright (C) 2010 Magnus Damm - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#include -#include -#include -#include -#include "common.h" - -void __init shmobile_setup_console(void) -{ - parse_early_param(); - - /* Let earlyprintk output early console messages */ - early_platform_driver_probe("earlyprintk", 1, 1); -} -- cgit v0.10.2 From 49611d482910b654ba6ce09fa44aa665359620b4 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 4 Aug 2015 20:03:09 +0200 Subject: ARM: shmobile: Remove obsolete intc.h The last user of "intc.h" was removed in commit 9a9863987bf7307f ("ARM: shmobile: Remove legacy SoC code for SH-Mobile AG5"). Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/mach-shmobile/intc.h b/arch/arm/mach-shmobile/intc.h deleted file mode 100644 index 40b2ad4..0000000 --- a/arch/arm/mach-shmobile/intc.h +++ /dev/null @@ -1,295 +0,0 @@ -#ifndef __ASM_MACH_INTC_H -#define __ASM_MACH_INTC_H -#include - -#define INTC_IRQ_PINS_ENUM_16L(p) \ - p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3, \ - p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7, \ - p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11, \ - p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 - -#define INTC_IRQ_PINS_ENUM_16H(p) \ - p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19, \ - p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23, \ - p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27, \ - p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 - -#define INTC_IRQ_PINS_VECT_16L(p, vect) \ - vect(p ## _IRQ0, 0x0200), vect(p ## _IRQ1, 0x0220), \ - vect(p ## _IRQ2, 0x0240), vect(p ## _IRQ3, 0x0260), \ - vect(p ## _IRQ4, 0x0280), vect(p ## _IRQ5, 0x02a0), \ - vect(p ## _IRQ6, 0x02c0), vect(p ## _IRQ7, 0x02e0), \ - vect(p ## _IRQ8, 0x0300), vect(p ## _IRQ9, 0x0320), \ - vect(p ## _IRQ10, 0x0340), vect(p ## _IRQ11, 0x0360), \ - vect(p ## _IRQ12, 0x0380), vect(p ## _IRQ13, 0x03a0), \ - vect(p ## _IRQ14, 0x03c0), vect(p ## _IRQ15, 0x03e0) - -#define INTC_IRQ_PINS_VECT_16H(p, vect) \ - vect(p ## _IRQ16, 0x3200), vect(p ## _IRQ17, 0x3220), \ - vect(p ## _IRQ18, 0x3240), vect(p ## _IRQ19, 0x3260), \ - vect(p ## _IRQ20, 0x3280), vect(p ## _IRQ21, 0x32a0), \ - vect(p ## _IRQ22, 0x32c0), vect(p ## _IRQ23, 0x32e0), \ - vect(p ## _IRQ24, 0x3300), vect(p ## _IRQ25, 0x3320), \ - vect(p ## _IRQ26, 0x3340), vect(p ## _IRQ27, 0x3360), \ - vect(p ## _IRQ28, 0x3380), vect(p ## _IRQ29, 0x33a0), \ - vect(p ## _IRQ30, 0x33c0), vect(p ## _IRQ31, 0x33e0) - -#define INTC_IRQ_PINS_MASK_16L(p, base) \ - { base + 0x40, base + 0x60, 8, /* INTMSK00A / INTMSKCLR00A */ \ - { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3, \ - p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } }, \ - { base + 0x44, base + 0x64, 8, /* INTMSK10A / INTMSKCLR10A */ \ - { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11, \ - p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } } - -#define INTC_IRQ_PINS_MASK_16H(p, base) \ - { base + 0x48, base + 0x68, 8, /* INTMSK20A / INTMSKCLR20A */ \ - { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19, \ - p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } }, \ - { base + 0x4c, base + 0x6c, 8, /* INTMSK30A / INTMSKCLR30A */ \ - { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27, \ - p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } } - -#define INTC_IRQ_PINS_PRIO_16L(p, base) \ - { base + 0x10, 0, 32, 4, /* INTPRI00A */ \ - { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3, \ - p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } }, \ - { base + 0x14, 0, 32, 4, /* INTPRI10A */ \ - { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11, \ - p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } } - -#define INTC_IRQ_PINS_PRIO_16H(p, base) \ - { base + 0x18, 0, 32, 4, /* INTPRI20A */ \ - { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19, \ - p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } }, \ - { base + 0x1c, 0, 32, 4, /* INTPRI30A */ \ - { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27, \ - p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } } - -#define INTC_IRQ_PINS_SENSE_16L(p, base) \ - { base + 0x00, 32, 4, /* ICR1A */ \ - { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3, \ - p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } }, \ - { base + 0x04, 32, 4, /* ICR2A */ \ - { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11, \ - p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } } - -#define INTC_IRQ_PINS_SENSE_16H(p, base) \ - { base + 0x08, 32, 4, /* ICR3A */ \ - { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19, \ - p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } }, \ - { base + 0x0c, 32, 4, /* ICR4A */ \ - { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27, \ - p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } } - -#define INTC_IRQ_PINS_ACK_16L(p, base) \ - { base + 0x20, 0, 8, /* INTREQ00A */ \ - { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3, \ - p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } }, \ - { base + 0x24, 0, 8, /* INTREQ10A */ \ - { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11, \ - p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } } - -#define INTC_IRQ_PINS_ACK_16H(p, base) \ - { base + 0x28, 0, 8, /* INTREQ20A */ \ - { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19, \ - p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } }, \ - { base + 0x2c, 0, 8, /* INTREQ30A */ \ - { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27, \ - p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } } - -#define INTC_IRQ_PINS_16(p, base, vect, str) \ - \ -static struct resource p ## _resources[] __initdata = { \ - [0] = { \ - .start = base, \ - .end = base + 0x64, \ - .flags = IORESOURCE_MEM, \ - }, \ -}; \ - \ -enum { \ - p ## _UNUSED = 0, \ - INTC_IRQ_PINS_ENUM_16L(p), \ -}; \ - \ -static struct intc_vect p ## _vectors[] __initdata = { \ - INTC_IRQ_PINS_VECT_16L(p, vect), \ -}; \ - \ -static struct intc_mask_reg p ## _mask_registers[] __initdata = { \ - INTC_IRQ_PINS_MASK_16L(p, base), \ -}; \ - \ -static struct intc_prio_reg p ## _prio_registers[] __initdata = { \ - INTC_IRQ_PINS_PRIO_16L(p, base), \ -}; \ - \ -static struct intc_sense_reg p ## _sense_registers[] __initdata = { \ - INTC_IRQ_PINS_SENSE_16L(p, base), \ -}; \ - \ -static struct intc_mask_reg p ## _ack_registers[] __initdata = { \ - INTC_IRQ_PINS_ACK_16L(p, base), \ -}; \ - \ -static struct intc_desc p ## _desc __initdata = { \ - .name = str, \ - .resource = p ## _resources, \ - .num_resources = ARRAY_SIZE(p ## _resources), \ - .hw = INTC_HW_DESC(p ## _vectors, NULL, \ - p ## _mask_registers, p ## _prio_registers, \ - p ## _sense_registers, p ## _ack_registers) \ -} - -#define INTC_IRQ_PINS_16H(p, base, vect, str) \ - \ -static struct resource p ## _resources[] __initdata = { \ - [0] = { \ - .start = base, \ - .end = base + 0x64, \ - .flags = IORESOURCE_MEM, \ - }, \ -}; \ - \ -enum { \ - p ## _UNUSED = 0, \ - INTC_IRQ_PINS_ENUM_16H(p), \ -}; \ - \ -static struct intc_vect p ## _vectors[] __initdata = { \ - INTC_IRQ_PINS_VECT_16H(p, vect), \ -}; \ - \ -static struct intc_mask_reg p ## _mask_registers[] __initdata = { \ - INTC_IRQ_PINS_MASK_16H(p, base), \ -}; \ - \ -static struct intc_prio_reg p ## _prio_registers[] __initdata = { \ - INTC_IRQ_PINS_PRIO_16H(p, base), \ -}; \ - \ -static struct intc_sense_reg p ## _sense_registers[] __initdata = { \ - INTC_IRQ_PINS_SENSE_16H(p, base), \ -}; \ - \ -static struct intc_mask_reg p ## _ack_registers[] __initdata = { \ - INTC_IRQ_PINS_ACK_16H(p, base), \ -}; \ - \ -static struct intc_desc p ## _desc __initdata = { \ - .name = str, \ - .resource = p ## _resources, \ - .num_resources = ARRAY_SIZE(p ## _resources), \ - .hw = INTC_HW_DESC(p ## _vectors, NULL, \ - p ## _mask_registers, p ## _prio_registers, \ - p ## _sense_registers, p ## _ack_registers) \ -} - -#define INTC_IRQ_PINS_32(p, base, vect, str) \ - \ -static struct resource p ## _resources[] __initdata = { \ - [0] = { \ - .start = base, \ - .end = base + 0x6c, \ - .flags = IORESOURCE_MEM, \ - }, \ -}; \ - \ -enum { \ - p ## _UNUSED = 0, \ - INTC_IRQ_PINS_ENUM_16L(p), \ - INTC_IRQ_PINS_ENUM_16H(p), \ -}; \ - \ -static struct intc_vect p ## _vectors[] __initdata = { \ - INTC_IRQ_PINS_VECT_16L(p, vect), \ - INTC_IRQ_PINS_VECT_16H(p, vect), \ -}; \ - \ -static struct intc_mask_reg p ## _mask_registers[] __initdata = { \ - INTC_IRQ_PINS_MASK_16L(p, base), \ - INTC_IRQ_PINS_MASK_16H(p, base), \ -}; \ - \ -static struct intc_prio_reg p ## _prio_registers[] __initdata = { \ - INTC_IRQ_PINS_PRIO_16L(p, base), \ - INTC_IRQ_PINS_PRIO_16H(p, base), \ -}; \ - \ -static struct intc_sense_reg p ## _sense_registers[] __initdata = { \ - INTC_IRQ_PINS_SENSE_16L(p, base), \ - INTC_IRQ_PINS_SENSE_16H(p, base), \ -}; \ - \ -static struct intc_mask_reg p ## _ack_registers[] __initdata = { \ - INTC_IRQ_PINS_ACK_16L(p, base), \ - INTC_IRQ_PINS_ACK_16H(p, base), \ -}; \ - \ -static struct intc_desc p ## _desc __initdata = { \ - .name = str, \ - .resource = p ## _resources, \ - .num_resources = ARRAY_SIZE(p ## _resources), \ - .hw = INTC_HW_DESC(p ## _vectors, NULL, \ - p ## _mask_registers, p ## _prio_registers, \ - p ## _sense_registers, p ## _ack_registers) \ -} - -#define INTC_PINT_E_EMPTY -#define INTC_PINT_E_NONE 0, 0, 0, 0, 0, 0, 0, 0, -#define INTC_PINT_E(p) \ - PINT ## p ## 0, PINT ## p ## 1, PINT ## p ## 2, PINT ## p ## 3, \ - PINT ## p ## 4, PINT ## p ## 5, PINT ## p ## 6, PINT ## p ## 7, - -#define INTC_PINT_V_NONE -#define INTC_PINT_V(p, vect) \ - vect(PINT ## p ## 0, 0), vect(PINT ## p ## 1, 1), \ - vect(PINT ## p ## 2, 2), vect(PINT ## p ## 3, 3), \ - vect(PINT ## p ## 4, 4), vect(PINT ## p ## 5, 5), \ - vect(PINT ## p ## 6, 6), vect(PINT ## p ## 7, 7), - -#define INTC_PINT(p, mask_reg, sense_base, str, \ - enums_1, enums_2, enums_3, enums_4, \ - vect_1, vect_2, vect_3, vect_4, \ - mask_a, mask_b, mask_c, mask_d, \ - sense_a, sense_b, sense_c, sense_d) \ - \ -enum { \ - PINT ## p ## _UNUSED = 0, \ - enums_1 enums_2 enums_3 enums_4 \ -}; \ - \ -static struct intc_vect p ## _vectors[] __initdata = { \ - vect_1 vect_2 vect_3 vect_4 \ -}; \ - \ -static struct intc_mask_reg p ## _mask_registers[] __initdata = { \ - { mask_reg, 0, 32, /* PINTER */ \ - { mask_a mask_b mask_c mask_d } } \ -}; \ - \ -static struct intc_sense_reg p ## _sense_registers[] __initdata = { \ - { sense_base + 0x00, 16, 2, /* PINTCR */ \ - { sense_a } }, \ - { sense_base + 0x04, 16, 2, /* PINTCR */ \ - { sense_b } }, \ - { sense_base + 0x08, 16, 2, /* PINTCR */ \ - { sense_c } }, \ - { sense_base + 0x0c, 16, 2, /* PINTCR */ \ - { sense_d } }, \ -}; \ - \ -static struct intc_desc p ## _desc __initdata = { \ - .name = str, \ - .hw = INTC_HW_DESC(p ## _vectors, NULL, \ - p ## _mask_registers, NULL, \ - p ## _sense_registers, NULL), \ -} - -/* INTCS */ -#define INTCS_VECT_BASE 0x3400 -#define INTCS_VECT(n, vect) INTC_VECT((n), INTCS_VECT_BASE + (vect)) -#define intcs_evt2irq(evt) evt2irq(INTCS_VECT_BASE + (evt)) - -#endif /* __ASM_MACH_INTC_H */ -- cgit v0.10.2 From edc77c65df148548bd168fde9607707d81de39ff Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 4 Aug 2015 20:03:10 +0200 Subject: ARM: shmobile: Remove obsolete legacy PM Domain leftovers The last users were removed in commit b587288001f05c0e ("ARM: shmobile: R-Mobile: Remove legacy PM Domain code"). Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/mach-shmobile/pm-rmobile.h b/arch/arm/mach-shmobile/pm-rmobile.h index 30a4a42..8146bb6 100644 --- a/arch/arm/mach-shmobile/pm-rmobile.h +++ b/arch/arm/mach-shmobile/pm-rmobile.h @@ -12,10 +12,6 @@ #include -#define DEFAULT_DEV_LATENCY_NS 250000 - -struct platform_device; - struct rmobile_pm_domain { struct generic_pm_domain genpd; struct dev_power_governor *gov; @@ -26,9 +22,4 @@ struct rmobile_pm_domain { bool no_debug; }; -struct pm_domain_device { - const char *domain_name; - struct platform_device *pdev; -}; - #endif /* PM_RMOBILE_H */ -- cgit v0.10.2 From 93161cb4c3c27517f1b4516a880adaf7df4112e2 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 4 Aug 2015 20:03:11 +0200 Subject: ARM: shmobile: Remove obsolete earlytimer registration The last caller of shmobile_earlytimer_init() was removed in commit c99cd90d98a98aa1 ("ARM: shmobile: r8a7779: Remove legacy SoC code"). Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/mach-shmobile/common.h b/arch/arm/mach-shmobile/common.h index ee8fe9e..2a350b4 100644 --- a/arch/arm/mach-shmobile/common.h +++ b/arch/arm/mach-shmobile/common.h @@ -1,7 +1,6 @@ #ifndef __ARCH_MACH_COMMON_H #define __ARCH_MACH_COMMON_H -extern void shmobile_earlytimer_init(void); extern void shmobile_init_delay(void); struct twd_local_timer; extern void shmobile_boot_vector(void); diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c index f1d027a..c17d4d3 100644 --- a/arch/arm/mach-shmobile/timer.c +++ b/arch/arm/mach-shmobile/timer.c @@ -77,24 +77,3 @@ void __init shmobile_init_delay(void) shmobile_setup_delay_hz(max_freq, 2, 4); } } - -static void __init shmobile_late_time_init(void) -{ - /* - * Make sure all compiled-in early timers register themselves. - * - * Run probe() for two "earlytimer" devices, these will be the - * clockevents and clocksource devices respectively. In the event - * that only a clockevents device is available, we -ENODEV on the - * clocksource and the jiffies clocksource is used transparently - * instead. No error handling is necessary here. - */ - early_platform_driver_register_all("earlytimer"); - early_platform_driver_probe("earlytimer", 2, 0); -} - -void __init shmobile_earlytimer_init(void) -{ - late_time_init = shmobile_late_time_init; -} - -- cgit v0.10.2 From b62708ac3f5ebfd3a15bd65fd48ed013c5f166bf Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 4 Aug 2015 20:03:12 +0200 Subject: ARM: shmobile: Remove obsolete twd_local_timer declaration The last user of twd_local_timer was removed in commit c99cd90d98a98aa1 ("ARM: shmobile: r8a7779: Remove legacy SoC code"). Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/mach-shmobile/common.h b/arch/arm/mach-shmobile/common.h index 2a350b4..0833a6e 100644 --- a/arch/arm/mach-shmobile/common.h +++ b/arch/arm/mach-shmobile/common.h @@ -2,7 +2,6 @@ #define __ARCH_MACH_COMMON_H extern void shmobile_init_delay(void); -struct twd_local_timer; extern void shmobile_boot_vector(void); extern unsigned long shmobile_boot_fn; extern unsigned long shmobile_boot_arg; -- cgit v0.10.2 From 2c0a876680c2c90442a8d6bb3cde07bd8b663dca Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Fri, 7 Aug 2015 18:34:56 +0200 Subject: ARM: shmobile: bockw: remove "reference" device tree Replaced by multi-platform. Signed-off-by: Ulrich Hecht Signed-off-by: Simon Horman diff --git a/Documentation/devicetree/bindings/arm/shmobile.txt b/Documentation/devicetree/bindings/arm/shmobile.txt index c4f19b2..eed7eb7 100644 --- a/Documentation/devicetree/bindings/arm/shmobile.txt +++ b/Documentation/devicetree/bindings/arm/shmobile.txt @@ -39,8 +39,6 @@ Boards: compatible = "renesas,armadillo800eva" - BOCK-W compatible = "renesas,bockw", "renesas,r8a7778" - - BOCK-W - Reference Device Tree Implementation - compatible = "renesas,bockw-reference", "renesas,r8a7778" - Genmai (RTK772100BC00000BR) compatible = "renesas,genmai", "renesas,r7s72100" - Gose diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 233159d..ad74cf9 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -523,8 +523,7 @@ dtb-$(CONFIG_ARCH_S5PV210) += \ s5pv210-smdkv210.dtb \ s5pv210-torbreck.dtb dtb-$(CONFIG_ARCH_SHMOBILE_LEGACY) += \ - r8a7778-bockw.dtb \ - r8a7778-bockw-reference.dtb + r8a7778-bockw.dtb dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += \ emev2-kzm9d.dtb \ r7s72100-genmai.dtb \ diff --git a/arch/arm/boot/dts/r8a7778-bockw-reference.dts b/arch/arm/boot/dts/r8a7778-bockw-reference.dts deleted file mode 100644 index dffa6ff..0000000 --- a/arch/arm/boot/dts/r8a7778-bockw-reference.dts +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Reference Device Tree Source for the Bock-W board - * - * Copyright (C) 2013 Renesas Solutions Corp. - * Copyright (C) 2013 Kuninori Morimoto - * - * based on r8a7779 - * - * Copyright (C) 2013 Renesas Solutions Corp. - * Copyright (C) 2013 Simon Horman - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -/dts-v1/; -#include "r8a7778.dtsi" -#include -#include - -/ { - model = "bockw"; - compatible = "renesas,bockw-reference", "renesas,r8a7778"; - - aliases { - serial0 = &scif0; - }; - - chosen { - bootargs = "ignore_loglevel root=/dev/nfs ip=dhcp rw"; - stdout-path = &scif0; - }; - - memory { - device_type = "memory"; - reg = <0x60000000 0x10000000>; - }; - - fixedregulator3v3: fixedregulator@0 { - compatible = "regulator-fixed"; - regulator-name = "fixed-3.3V"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - regulator-always-on; - }; - - ethernet@18300000 { - compatible = "smsc,lan9220", "smsc,lan9115"; - reg = <0x18300000 0x1000>; - - phy-mode = "mii"; - interrupt-parent = <&irqpin>; - interrupts = <0 IRQ_TYPE_EDGE_FALLING>; - reg-io-width = <4>; - vddvario-supply = <&fixedregulator3v3>; - vdd33a-supply = <&fixedregulator3v3>; - }; - -}; - -&mmcif { - pinctrl-0 = <&mmc_pins>; - pinctrl-names = "default"; - - vmmc-supply = <&fixedregulator3v3>; - bus-width = <8>; - broken-cd; - status = "okay"; -}; - -&irqpin { - status = "okay"; -}; - -&tmu0 { - status = "okay"; -}; - -&pfc { - scif0_pins: serial0 { - renesas,groups = "scif0_data_a", "scif0_ctrl"; - renesas,function = "scif0"; - }; - - mmc_pins: mmc { - renesas,groups = "mmc_data8", "mmc_ctrl"; - renesas,function = "mmc"; - }; - - sdhi0_pins: sd0 { - renesas,groups = "sdhi0_data4", "sdhi0_ctrl", - "sdhi0_cd"; - renesas,function = "sdhi0"; - }; - - hspi0_pins: hspi0 { - renesas,groups = "hspi0_a"; - renesas,function = "hspi0"; - }; -}; - -&sdhi0 { - pinctrl-0 = <&sdhi0_pins>; - pinctrl-names = "default"; - - vmmc-supply = <&fixedregulator3v3>; - bus-width = <4>; - status = "okay"; - wp-gpios = <&gpio3 18 GPIO_ACTIVE_HIGH>; -}; - -&hspi0 { - pinctrl-0 = <&hspi0_pins>; - pinctrl-names = "default"; - status = "okay"; - - flash: flash@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "spansion,s25fl008k", "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <104000000>; - m25p,fast-read; - - partition@0 { - label = "data(spi)"; - reg = <0x00000000 0x00100000>; - }; - }; -}; - -&scif0 { - pinctrl-0 = <&scif0_pins>; - pinctrl-names = "default"; - - status = "okay"; -}; -- cgit v0.10.2 From 892b19fe503f5478f14c77d5f14df9f954292baf Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Fri, 7 Aug 2015 18:34:57 +0200 Subject: ARM: shmobile: bockw: remove "reference" board file and config Replaced by multi-platform. Signed-off-by: Ulrich Hecht Signed-off-by: Simon Horman diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 926e336..670dce3 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -126,19 +126,6 @@ config MACH_BOCKW select SND_SOC_AK4642 if SND_SIMPLE_CARD && I2C select USE_OF -config MACH_BOCKW_REFERENCE - bool "BOCK-W - Reference Device Tree Implementation" - depends on ARCH_R8A7778 - select ARCH_REQUIRE_GPIOLIB - select REGULATOR_FIXED_VOLTAGE if REGULATOR - select USE_OF - ---help--- - Use reference implementation of BockW board support - which makes use of device tree at the expense - of not supporting a number of devices. - - This is intended to aid developers - comment "Renesas ARM SoCs System Configuration" config CPU_HAS_INTEVT diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index b028415..8f235c5 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -52,7 +52,6 @@ obj-$(CONFIG_ARCH_RCAR_GEN2) += pm-rcar-gen2.o # Board objects ifndef CONFIG_ARCH_SHMOBILE_MULTI obj-$(CONFIG_MACH_BOCKW) += board-bockw.o -obj-$(CONFIG_MACH_BOCKW_REFERENCE) += board-bockw-reference.o endif # Framework support diff --git a/arch/arm/mach-shmobile/Makefile.boot b/arch/arm/mach-shmobile/Makefile.boot index a489fe9..1a4ab16 100644 --- a/arch/arm/mach-shmobile/Makefile.boot +++ b/arch/arm/mach-shmobile/Makefile.boot @@ -1,7 +1,6 @@ # per-board load address for uImage loadaddr-y := loadaddr-$(CONFIG_MACH_BOCKW) += 0x60008000 -loadaddr-$(CONFIG_MACH_BOCKW_REFERENCE) += 0x60008000 __ZRELADDR := $(sort $(loadaddr-y)) zreladdr-y += $(__ZRELADDR) diff --git a/arch/arm/mach-shmobile/board-bockw-reference.c b/arch/arm/mach-shmobile/board-bockw-reference.c deleted file mode 100644 index 4f78296..0000000 --- a/arch/arm/mach-shmobile/board-bockw-reference.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Bock-W board support - * - * Copyright (C) 2013 Renesas Solutions Corp. - * Copyright (C) 2013 Kuninori Morimoto - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include - -#include - -#include "common.h" -#include "r8a7778.h" - -/* - * see board-bock.c for checking detail of dip-switch - */ - -#define FPGA 0x18200000 -#define IRQ0MR 0x30 -#define COMCTLR 0x101c - -#define PFC 0xfffc0000 -#define PUPR4 0x110 -static void __init bockw_init(void) -{ - void __iomem *fpga; - void __iomem *pfc; - -#ifndef CONFIG_COMMON_CLK - r8a7778_clock_init(); -#endif - r8a7778_init_irq_extpin_dt(1); - r8a7778_add_dt_devices(); - - fpga = ioremap_nocache(FPGA, SZ_1M); - if (fpga) { - /* - * CAUTION - * - * IRQ0/1 is cascaded interrupt from FPGA. - * it should be cared in the future - * Now, it is assuming IRQ0 was used only from SMSC. - */ - u16 val = ioread16(fpga + IRQ0MR); - val &= ~(1 << 4); /* enable SMSC911x */ - iowrite16(val, fpga + IRQ0MR); - - iounmap(fpga); - } - - pfc = ioremap_nocache(PFC, 0x200); - if (pfc) { - /* - * FIXME - * - * SDHI CD/WP pin needs pull-up - */ - iowrite32(ioread32(pfc + PUPR4) | (3 << 26), pfc + PUPR4); - iounmap(pfc); - } - - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); -} - -static const char *const bockw_boards_compat_dt[] __initconst = { - "renesas,bockw-reference", - NULL, -}; - -DT_MACHINE_START(BOCKW_DT, "bockw") - .init_early = shmobile_init_delay, - .init_irq = r8a7778_init_irq_dt, - .init_machine = bockw_init, - .init_late = shmobile_init_late, - .dt_compat = bockw_boards_compat_dt, -MACHINE_END -- cgit v0.10.2 From c2c7375ba2dfcce3dfc9ecf4b3e44b975fb139fc Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Fri, 14 Aug 2015 15:54:04 +0200 Subject: ARM: shmobile: remove paragraph on DT reference platforms They have all been eliminated now. Signed-off-by: Ulrich Hecht Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/Documentation/devicetree/bindings/arm/shmobile.txt b/Documentation/devicetree/bindings/arm/shmobile.txt index eed7eb7..2b9cb62 100644 --- a/Documentation/devicetree/bindings/arm/shmobile.txt +++ b/Documentation/devicetree/bindings/arm/shmobile.txt @@ -55,7 +55,3 @@ Boards: compatible = "renesas,lager", "renesas,r8a7790" - Marzen compatible = "renesas,marzen", "renesas,r8a7779" - -Note: Reference Device Tree Implementations are temporary implementations - to ease the migration from platform devices to Device Tree, and are - intended to be removed in the future. -- cgit v0.10.2 From 3d7608e4c169af0361a4ebcb6294e7530b0e2c31 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Fri, 14 Aug 2015 15:51:02 +0200 Subject: ARM: shmobile: bockw: remove legacy board file and config Replaced by multi-platform. Signed-off-by: Ulrich Hecht Acked-by: by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 670dce3..6e07e98 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -115,17 +115,6 @@ config ARCH_R8A7779 select ARCH_WANT_OPTIONAL_GPIOLIB select ARM_GIC -comment "Renesas ARM SoCs Board Type" - -config MACH_BOCKW - bool "BOCK-W platform" - depends on ARCH_R8A7778 - select ARCH_REQUIRE_GPIOLIB - select REGULATOR_FIXED_VOLTAGE if REGULATOR - select SND_SOC_AK4554 if SND_SIMPLE_CARD - select SND_SOC_AK4642 if SND_SIMPLE_CARD && I2C - select USE_OF - comment "Renesas ARM SoCs System Configuration" config CPU_HAS_INTEVT diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index 8f235c5..5392925 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -49,10 +49,5 @@ obj-$(CONFIG_PM_RCAR) += pm-rcar.o obj-$(CONFIG_PM_RMOBILE) += pm-rmobile.o obj-$(CONFIG_ARCH_RCAR_GEN2) += pm-rcar-gen2.o -# Board objects -ifndef CONFIG_ARCH_SHMOBILE_MULTI -obj-$(CONFIG_MACH_BOCKW) += board-bockw.o -endif - # Framework support obj-$(CONFIG_SMP) += $(smp-y) diff --git a/arch/arm/mach-shmobile/Makefile.boot b/arch/arm/mach-shmobile/Makefile.boot index 1a4ab16..e69de29 100644 --- a/arch/arm/mach-shmobile/Makefile.boot +++ b/arch/arm/mach-shmobile/Makefile.boot @@ -1,11 +0,0 @@ -# per-board load address for uImage -loadaddr-y := -loadaddr-$(CONFIG_MACH_BOCKW) += 0x60008000 - -__ZRELADDR := $(sort $(loadaddr-y)) - zreladdr-y += $(__ZRELADDR) - -# Unsupported legacy stuff -# -#params_phys-y (Instead: Pass atags pointer in r2) -#initrd_phys-y (Instead: Use compiled-in initramfs) diff --git a/arch/arm/mach-shmobile/board-bockw.c b/arch/arm/mach-shmobile/board-bockw.c deleted file mode 100644 index 25a0e72..0000000 --- a/arch/arm/mach-shmobile/board-bockw.c +++ /dev/null @@ -1,737 +0,0 @@ -/* - * Bock-W board support - * - * Copyright (C) 2013-2014 Renesas Solutions Corp. - * Copyright (C) 2013 Kuninori Morimoto - * Copyright (C) 2013-2014 Cogent Embedded, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "common.h" -#include "irqs.h" -#include "r8a7778.h" - -#define FPGA 0x18200000 -#define IRQ0MR 0x30 -#define COMCTLR 0x101c -static void __iomem *fpga; - -/* - * CN9(Upper side) SCIF/RCAN selection - * - * 1,4 3,6 - * SW40 SCIF RCAN - * SW41 SCIF RCAN - */ - -/* - * MMC (CN26) pin - * - * SW6 (D2) 3 pin - * SW7 (D5) ON - * SW8 (D3) 3 pin - * SW10 (D4) 1 pin - * SW12 (CLK) 1 pin - * SW13 (D6) 3 pin - * SW14 (CMD) ON - * SW15 (D6) 1 pin - * SW16 (D0) ON - * SW17 (D1) ON - * SW18 (D7) 3 pin - * SW19 (MMC) 1 pin - */ - -/* - * SSI settings - * - * SW45: 1-4 side (SSI5 out, ROUT/LOUT CN19 Mid) - * SW46: 1101 (SSI6 Recorde) - * SW47: 1110 (SSI5 Playback) - * SW48: 11 (Recorde power) - * SW49: 1 (SSI slave mode) - * SW50: 1111 (SSI7, SSI8) - * SW51: 1111 (SSI3, SSI4) - * SW54: 1pin (ak4554 FPGA control) - * SW55: 1 (CLKB is 24.5760MHz) - * SW60: 1pin (ak4554 FPGA control) - * SW61: 3pin (use X11 clock) - * SW78: 3-6 (ak4642 connects I2C0) - * - * You can use sound as - * - * hw0: CN19: SSI56-AK4643 - * hw1: CN21: SSI3-AK4554(playback) - * hw2: CN21: SSI4-AK4554(capture) - * hw3: CN20: SSI7-AK4554(playback) - * hw4: CN20: SSI8-AK4554(capture) - * - * this command is required when playback on hw0. - * - * # amixer set "LINEOUT Mixer DACL" on - */ - -/* - * USB - * - * USB1 (CN29) can be Host/Function - * - * Host Func - * SW98 1 2 - * SW99 1 3 - */ - -/* Dummy supplies, where voltage doesn't matter */ -static struct regulator_consumer_supply dummy_supplies[] = { - REGULATOR_SUPPLY("vddvario", "smsc911x"), - REGULATOR_SUPPLY("vdd33a", "smsc911x"), -}; - -static struct regulator_consumer_supply fixed3v3_power_consumers[] = { - REGULATOR_SUPPLY("vmmc", "sh_mmcif"), - REGULATOR_SUPPLY("vqmmc", "sh_mmcif"), -}; - -static struct smsc911x_platform_config smsc911x_data __initdata = { - .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, - .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, - .flags = SMSC911X_USE_32BIT, - .phy_interface = PHY_INTERFACE_MODE_MII, -}; - -static struct resource smsc911x_resources[] __initdata = { - DEFINE_RES_MEM(0x18300000, 0x1000), - DEFINE_RES_IRQ(irq_pin(0)), /* IRQ 0 */ -}; - -#if IS_ENABLED(CONFIG_USB_RENESAS_USBHS_UDC) -/* - * When USB1 is Func - */ -static int usbhsf_get_id(struct platform_device *pdev) -{ - return USBHS_GADGET; -} - -#define SUSPMODE 0x102 -static int usbhsf_power_ctrl(struct platform_device *pdev, - void __iomem *base, int enable) -{ - enable = !!enable; - - r8a7778_usb_phy_power(enable); - - iowrite16(enable << 14, base + SUSPMODE); - - return 0; -} - -static struct resource usbhsf_resources[] __initdata = { - DEFINE_RES_MEM(0xffe60000, 0x110), - DEFINE_RES_IRQ(gic_iid(0x4f)), -}; - -static struct renesas_usbhs_platform_info usbhs_info __initdata = { - .platform_callback = { - .get_id = usbhsf_get_id, - .power_ctrl = usbhsf_power_ctrl, - }, - .driver_param = { - .buswait_bwait = 4, - .d0_tx_id = HPBDMA_SLAVE_USBFUNC_TX, - .d1_rx_id = HPBDMA_SLAVE_USBFUNC_RX, - }, -}; - -#define USB_PHY_SETTING {.port1_func = 1, .ovc_pin[1].active_high = 1,} -#define USB1_DEVICE "renesas_usbhs" -#define ADD_USB_FUNC_DEVICE_IF_POSSIBLE() \ - platform_device_register_resndata( \ - NULL, "renesas_usbhs", -1, \ - usbhsf_resources, \ - ARRAY_SIZE(usbhsf_resources), \ - &usbhs_info, sizeof(struct renesas_usbhs_platform_info)) - -#else -/* - * When USB1 is Host - */ -#define USB_PHY_SETTING { } -#define USB1_DEVICE "ehci-platform" -#define ADD_USB_FUNC_DEVICE_IF_POSSIBLE() - -#endif - -/* USB */ -static struct resource usb_phy_resources[] __initdata = { - DEFINE_RES_MEM(0xffe70800, 0x100), - DEFINE_RES_MEM(0xffe76000, 0x100), -}; - -static struct rcar_phy_platform_data usb_phy_platform_data __initdata = - USB_PHY_SETTING; - - -/* SDHI */ -static struct tmio_mmc_data sdhi0_info __initdata = { - .chan_priv_tx = (void *)HPBDMA_SLAVE_SDHI0_TX, - .chan_priv_rx = (void *)HPBDMA_SLAVE_SDHI0_RX, - .capabilities = MMC_CAP_SD_HIGHSPEED, - .ocr_mask = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34, - .flags = TMIO_MMC_HAS_IDLE_WAIT, -}; - -static struct resource sdhi0_resources[] __initdata = { - DEFINE_RES_MEM(0xFFE4C000, 0x100), - DEFINE_RES_IRQ(gic_iid(0x77)), -}; - -/* Ether */ -static struct resource ether_resources[] __initdata = { - DEFINE_RES_MEM(0xfde00000, 0x400), - DEFINE_RES_IRQ(gic_iid(0x89)), -}; - -static struct sh_eth_plat_data ether_platform_data __initdata = { - .phy = 0x01, - .edmac_endian = EDMAC_LITTLE_ENDIAN, - .phy_interface = PHY_INTERFACE_MODE_RMII, - /* - * Although the LINK signal is available on the board, it's connected to - * the link/activity LED output of the PHY, thus the link disappears and - * reappears after each packet. We'd be better off ignoring such signal - * and getting the link state from the PHY indirectly. - */ - .no_ether_link = 1, -}; - -static struct platform_device_info ether_info __initdata = { - .name = "r8a777x-ether", - .id = -1, - .res = ether_resources, - .num_res = ARRAY_SIZE(ether_resources), - .data = ðer_platform_data, - .size_data = sizeof(ether_platform_data), - .dma_mask = DMA_BIT_MASK(32), -}; - -/* I2C */ -static struct i2c_board_info i2c0_devices[] = { - { - I2C_BOARD_INFO("rx8581", 0x51), - }, { - I2C_BOARD_INFO("ak4643", 0x12), - } -}; - -/* HSPI*/ -static struct mtd_partition m25p80_spi_flash_partitions[] = { - { - .name = "data(spi)", - .size = 0x0100000, - .offset = 0, - }, -}; - -static struct flash_platform_data spi_flash_data = { - .name = "m25p80", - .type = "s25fl008k", - .parts = m25p80_spi_flash_partitions, - .nr_parts = ARRAY_SIZE(m25p80_spi_flash_partitions), -}; - -static struct spi_board_info spi_board_info[] __initdata = { - { - .modalias = "m25p80", - .max_speed_hz = 104000000, - .chip_select = 0, - .bus_num = 0, - .mode = SPI_MODE_0, - .platform_data = &spi_flash_data, - }, -}; - -/* MMC */ -static struct resource mmc_resources[] __initdata = { - DEFINE_RES_MEM(0xffe4e000, 0x100), - DEFINE_RES_IRQ(gic_iid(0x5d)), -}; - -static struct sh_mmcif_plat_data sh_mmcif_plat __initdata = { - .sup_pclk = 0, - .caps = MMC_CAP_4_BIT_DATA | - MMC_CAP_8_BIT_DATA | - MMC_CAP_NEEDS_POLL, -}; - -/* In the default configuration both decoders reside on I2C bus 0 */ -#define BOCKW_CAMERA(idx) \ -static struct i2c_board_info camera##idx##_info = { \ - I2C_BOARD_INFO("ml86v7667", 0x41 + 2 * (idx)), \ -}; \ - \ -static struct soc_camera_link iclink##idx##_ml86v7667 __initdata = { \ - .bus_id = idx, \ - .i2c_adapter_id = 0, \ - .board_info = &camera##idx##_info, \ -} - -BOCKW_CAMERA(0); -BOCKW_CAMERA(1); - -/* VIN */ -static struct rcar_vin_platform_data vin_platform_data __initdata = { - .flags = RCAR_VIN_BT656, -}; - -#define R8A7778_VIN(idx) \ -static struct resource vin##idx##_resources[] __initdata = { \ - DEFINE_RES_MEM(0xffc50000 + 0x1000 * (idx), 0x1000), \ - DEFINE_RES_IRQ(gic_iid(0x5a)), \ -}; \ - \ -static struct platform_device_info vin##idx##_info __initdata = { \ - .name = "r8a7778-vin", \ - .id = idx, \ - .res = vin##idx##_resources, \ - .num_res = ARRAY_SIZE(vin##idx##_resources), \ - .dma_mask = DMA_BIT_MASK(32), \ - .data = &vin_platform_data, \ - .size_data = sizeof(vin_platform_data), \ -} -R8A7778_VIN(0); -R8A7778_VIN(1); - -/* Sound */ -static struct resource rsnd_resources[] __initdata = { - [RSND_GEN1_SRU] = DEFINE_RES_MEM(0xffd90000, 0x1000), - [RSND_GEN1_SSI] = DEFINE_RES_MEM(0xffd91000, 0x1240), - [RSND_GEN1_ADG] = DEFINE_RES_MEM(0xfffe0000, 0x24), -}; - -static struct rsnd_ssi_platform_info rsnd_ssi[] = { - RSND_SSI_UNUSED, /* SSI 0 */ - RSND_SSI_UNUSED, /* SSI 1 */ - RSND_SSI_UNUSED, /* SSI 2 */ - RSND_SSI(HPBDMA_SLAVE_HPBIF3_TX, gic_iid(0x85), 0), - RSND_SSI(HPBDMA_SLAVE_HPBIF4_RX, gic_iid(0x85), RSND_SSI_CLK_PIN_SHARE), - RSND_SSI(HPBDMA_SLAVE_HPBIF5_TX, gic_iid(0x86), 0), - RSND_SSI(HPBDMA_SLAVE_HPBIF6_RX, gic_iid(0x86), 0), - RSND_SSI(HPBDMA_SLAVE_HPBIF7_TX, gic_iid(0x86), 0), - RSND_SSI(HPBDMA_SLAVE_HPBIF8_RX, gic_iid(0x86), RSND_SSI_CLK_PIN_SHARE), -}; - -static struct rsnd_src_platform_info rsnd_src[9] = { - RSND_SRC_UNUSED, /* SRU 0 */ - RSND_SRC_UNUSED, /* SRU 1 */ - RSND_SRC_UNUSED, /* SRU 2 */ - RSND_SRC(0, 0), - RSND_SRC(0, 0), - RSND_SRC(0, 0), - RSND_SRC(0, 0), - RSND_SRC(0, 0), - RSND_SRC(0, 0), -}; - -static struct rsnd_dai_platform_info rsnd_dai[] = { - { - .playback = { .ssi = &rsnd_ssi[5], .src = &rsnd_src[5] }, - .capture = { .ssi = &rsnd_ssi[6], .src = &rsnd_src[6] }, - }, { - .playback = { .ssi = &rsnd_ssi[3], .src = &rsnd_src[3] }, - }, { - .capture = { .ssi = &rsnd_ssi[4], .src = &rsnd_src[4] }, - }, { - .playback = { .ssi = &rsnd_ssi[7], .src = &rsnd_src[7] }, - }, { - .capture = { .ssi = &rsnd_ssi[8], .src = &rsnd_src[8] }, - }, -}; - -enum { - AK4554_34 = 0, - AK4643_56, - AK4554_78, - SOUND_MAX, -}; - -static int rsnd_codec_power(int id, int enable) -{ - static int sound_user[SOUND_MAX] = {0, 0, 0}; - int *usr = NULL; - u32 bit; - - switch (id) { - case 3: - case 4: - usr = sound_user + AK4554_34; - bit = (1 << 10); - break; - case 5: - case 6: - usr = sound_user + AK4643_56; - bit = (1 << 6); - break; - case 7: - case 8: - usr = sound_user + AK4554_78; - bit = (1 << 7); - break; - } - - if (!usr) - return -EIO; - - if (enable) { - if (*usr == 0) { - u32 val = ioread16(fpga + COMCTLR); - val &= ~bit; - iowrite16(val, fpga + COMCTLR); - } - - (*usr)++; - } else { - if (*usr == 0) - return 0; - - (*usr)--; - - if (*usr == 0) { - u32 val = ioread16(fpga + COMCTLR); - val |= bit; - iowrite16(val, fpga + COMCTLR); - } - } - - return 0; -} - -static int rsnd_start(int id) -{ - return rsnd_codec_power(id, 1); -} - -static int rsnd_stop(int id) -{ - return rsnd_codec_power(id, 0); -} - -static struct rcar_snd_info rsnd_info = { - .flags = RSND_GEN1, - .ssi_info = rsnd_ssi, - .ssi_info_nr = ARRAY_SIZE(rsnd_ssi), - .src_info = rsnd_src, - .src_info_nr = ARRAY_SIZE(rsnd_src), - .dai_info = rsnd_dai, - .dai_info_nr = ARRAY_SIZE(rsnd_dai), - .start = rsnd_start, - .stop = rsnd_stop, -}; - -static struct asoc_simple_card_info rsnd_card_info[] = { - /* SSI5, SSI6 */ - { - .name = "AK4643", - .card = "SSI56-AK4643", - .codec = "ak4642-codec.0-0012", - .platform = "rcar_sound", - .daifmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM, - .cpu_dai = { - .name = "rsnd-dai.0", - }, - .codec_dai = { - .name = "ak4642-hifi", - .sysclk = 11289600, - }, - }, - /* SSI3 */ - { - .name = "AK4554", - .card = "SSI3-AK4554(playback)", - .codec = "ak4554-adc-dac.0", - .platform = "rcar_sound", - .daifmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_RIGHT_J, - .cpu_dai = { - .name = "rsnd-dai.1", - }, - .codec_dai = { - .name = "ak4554-hifi", - }, - }, - /* SSI4 */ - { - .name = "AK4554", - .card = "SSI4-AK4554(capture)", - .codec = "ak4554-adc-dac.0", - .platform = "rcar_sound", - .daifmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_LEFT_J, - .cpu_dai = { - .name = "rsnd-dai.2", - }, - .codec_dai = { - .name = "ak4554-hifi", - }, - }, - /* SSI7 */ - { - .name = "AK4554", - .card = "SSI7-AK4554(playback)", - .codec = "ak4554-adc-dac.1", - .platform = "rcar_sound", - .daifmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_RIGHT_J, - .cpu_dai = { - .name = "rsnd-dai.3", - }, - .codec_dai = { - .name = "ak4554-hifi", - }, - }, - /* SSI8 */ - { - .name = "AK4554", - .card = "SSI8-AK4554(capture)", - .codec = "ak4554-adc-dac.1", - .platform = "rcar_sound", - .daifmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_LEFT_J, - .cpu_dai = { - .name = "rsnd-dai.4", - }, - .codec_dai = { - .name = "ak4554-hifi", - }, - } -}; - -static const struct pinctrl_map bockw_pinctrl_map[] = { - /* AUDIO */ - PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", - "audio_clk_a", "audio_clk"), - PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", - "audio_clk_b", "audio_clk"), - PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", - "ssi34_ctrl", "ssi"), - PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", - "ssi3_data", "ssi"), - PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", - "ssi4_data", "ssi"), - PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", - "ssi5_ctrl", "ssi"), - PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", - "ssi5_data", "ssi"), - PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", - "ssi6_ctrl", "ssi"), - PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", - "ssi6_data", "ssi"), - PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", - "ssi78_ctrl", "ssi"), - PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", - "ssi7_data", "ssi"), - PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778", - "ssi8_data", "ssi"), - /* Ether */ - PIN_MAP_MUX_GROUP_DEFAULT("r8a777x-ether", "pfc-r8a7778", - "ether_rmii", "ether"), - /* HSPI0 */ - PIN_MAP_MUX_GROUP_DEFAULT("sh-hspi.0", "pfc-r8a7778", - "hspi0_a", "hspi0"), - /* MMC */ - PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif", "pfc-r8a7778", - "mmc_data8", "mmc"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif", "pfc-r8a7778", - "mmc_ctrl", "mmc"), - /* SCIF0 */ - PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.0", "pfc-r8a7778", - "scif0_data_a", "scif0"), - PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.0", "pfc-r8a7778", - "scif0_ctrl", "scif0"), - /* USB */ - PIN_MAP_MUX_GROUP_DEFAULT("ehci-platform", "pfc-r8a7778", - "usb0", "usb0"), - PIN_MAP_MUX_GROUP_DEFAULT(USB1_DEVICE, "pfc-r8a7778", - "usb1", "usb1"), - /* SDHI0 */ - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778", - "sdhi0_data4", "sdhi0"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778", - "sdhi0_ctrl", "sdhi0"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778", - "sdhi0_cd", "sdhi0"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778", - "sdhi0_wp", "sdhi0"), - /* VIN0 */ - PIN_MAP_MUX_GROUP_DEFAULT("r8a7778-vin.0", "pfc-r8a7778", - "vin0_clk", "vin0"), - PIN_MAP_MUX_GROUP_DEFAULT("r8a7778-vin.0", "pfc-r8a7778", - "vin0_data8", "vin0"), - /* VIN1 */ - PIN_MAP_MUX_GROUP_DEFAULT("r8a7778-vin.1", "pfc-r8a7778", - "vin1_clk", "vin1"), - PIN_MAP_MUX_GROUP_DEFAULT("r8a7778-vin.1", "pfc-r8a7778", - "vin1_data8", "vin1"), -}; - -#define PFC 0xfffc0000 -#define PUPR4 0x110 -static void __init bockw_init(void) -{ - void __iomem *base; - struct clk *clk; - struct platform_device *pdev; - int i; - - r8a7778_clock_init(); - r8a7778_init_irq_extpin(1); - r8a7778_add_standard_devices(); - - platform_device_register_full(ðer_info); - - platform_device_register_full(&vin0_info); - /* VIN1 has a pin conflict with Ether */ - if (!IS_ENABLED(CONFIG_SH_ETH)) - platform_device_register_full(&vin1_info); - platform_device_register_data(NULL, "soc-camera-pdrv", 0, - &iclink0_ml86v7667, - sizeof(iclink0_ml86v7667)); - platform_device_register_data(NULL, "soc-camera-pdrv", 1, - &iclink1_ml86v7667, - sizeof(iclink1_ml86v7667)); - - i2c_register_board_info(0, i2c0_devices, - ARRAY_SIZE(i2c0_devices)); - spi_register_board_info(spi_board_info, - ARRAY_SIZE(spi_board_info)); - pinctrl_register_mappings(bockw_pinctrl_map, - ARRAY_SIZE(bockw_pinctrl_map)); - r8a7778_pinmux_init(); - - platform_device_register_resndata( - NULL, "sh_mmcif", -1, - mmc_resources, ARRAY_SIZE(mmc_resources), - &sh_mmcif_plat, sizeof(struct sh_mmcif_plat_data)); - - platform_device_register_resndata( - NULL, "rcar_usb_phy", -1, - usb_phy_resources, - ARRAY_SIZE(usb_phy_resources), - &usb_phy_platform_data, - sizeof(struct rcar_phy_platform_data)); - - regulator_register_fixed(0, dummy_supplies, - ARRAY_SIZE(dummy_supplies)); - regulator_register_always_on(1, "fixed-3.3V", fixed3v3_power_consumers, - ARRAY_SIZE(fixed3v3_power_consumers), 3300000); - - /* for SMSC */ - fpga = ioremap_nocache(FPGA, SZ_1M); - if (fpga) { - /* - * CAUTION - * - * IRQ0/1 is cascaded interrupt from FPGA. - * it should be cared in the future - * Now, it is assuming IRQ0 was used only from SMSC. - */ - u16 val = ioread16(fpga + IRQ0MR); - val &= ~(1 << 4); /* enable SMSC911x */ - iowrite16(val, fpga + IRQ0MR); - - platform_device_register_resndata( - NULL, "smsc911x", -1, - smsc911x_resources, ARRAY_SIZE(smsc911x_resources), - &smsc911x_data, sizeof(smsc911x_data)); - } - - /* for SDHI */ - base = ioremap_nocache(PFC, 0x200); - if (base) { - /* - * FIXME - * - * SDHI CD/WP pin needs pull-up - */ - iowrite32(ioread32(base + PUPR4) | (3 << 26), base + PUPR4); - iounmap(base); - - platform_device_register_resndata( - NULL, "sh_mobile_sdhi", 0, - sdhi0_resources, ARRAY_SIZE(sdhi0_resources), - &sdhi0_info, sizeof(struct tmio_mmc_data)); - } - - /* for Audio */ - rsnd_codec_power(5, 1); /* enable ak4642 */ - - platform_device_register_simple( - "ak4554-adc-dac", 0, NULL, 0); - - platform_device_register_simple( - "ak4554-adc-dac", 1, NULL, 0); - - pdev = platform_device_register_resndata( - NULL, "rcar_sound", -1, - rsnd_resources, ARRAY_SIZE(rsnd_resources), - &rsnd_info, sizeof(rsnd_info)); - - clk = clk_get(&pdev->dev, "clk_b"); - clk_set_rate(clk, 24576000); - clk_put(clk); - - for (i = 0; i < ARRAY_SIZE(rsnd_card_info); i++) { - struct platform_device_info cardinfo = { - .name = "asoc-simple-card", - .id = i, - .data = &rsnd_card_info[i], - .size_data = sizeof(struct asoc_simple_card_info), - .dma_mask = DMA_BIT_MASK(32), - }; - - platform_device_register_full(&cardinfo); - } -} - -static void __init bockw_init_late(void) -{ - r8a7778_init_late(); - ADD_USB_FUNC_DEVICE_IF_POSSIBLE(); -} - -static const char *const bockw_boards_compat_dt[] __initconst = { - "renesas,bockw", - NULL, -}; - -DT_MACHINE_START(BOCKW_DT, "bockw") - .init_early = shmobile_init_delay, - .init_irq = r8a7778_init_irq_dt, - .init_machine = bockw_init, - .dt_compat = bockw_boards_compat_dt, - .init_late = bockw_init_late, -MACHINE_END -- cgit v0.10.2 From 4baadb9e05c68962362b7e1f52f32f50b4062593 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Fri, 14 Aug 2015 15:51:03 +0200 Subject: ARM: shmobile: r8a7778: remove obsolete setup code Removal of the legacy Bock-W platform obsoletes most setup code. Signed-off-by: Ulrich Hecht Acked-by: by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/mach-shmobile/r8a7778.h b/arch/arm/mach-shmobile/r8a7778.h deleted file mode 100644 index 0e77f3f..0000000 --- a/arch/arm/mach-shmobile/r8a7778.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2013 Renesas Solutions Corp. - * Copyright (C) 2013 Kuninori Morimoto - * Copyright (C) 2013 Cogent Embedded, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#ifndef __ASM_R8A7778_H__ -#define __ASM_R8A7778_H__ - -#include - -/* HPB-DMA slave IDs */ -enum { - HPBDMA_SLAVE_DUMMY, - HPBDMA_SLAVE_SDHI0_TX, - HPBDMA_SLAVE_SDHI0_RX, - HPBDMA_SLAVE_SSI0_TX, - HPBDMA_SLAVE_SSI0_RX, - HPBDMA_SLAVE_SSI1_TX, - HPBDMA_SLAVE_SSI1_RX, - HPBDMA_SLAVE_SSI2_TX, - HPBDMA_SLAVE_SSI2_RX, - HPBDMA_SLAVE_SSI3_TX, - HPBDMA_SLAVE_SSI3_RX, - HPBDMA_SLAVE_SSI4_TX, - HPBDMA_SLAVE_SSI4_RX, - HPBDMA_SLAVE_SSI5_TX, - HPBDMA_SLAVE_SSI5_RX, - HPBDMA_SLAVE_SSI6_TX, - HPBDMA_SLAVE_SSI6_RX, - HPBDMA_SLAVE_SSI7_TX, - HPBDMA_SLAVE_SSI7_RX, - HPBDMA_SLAVE_SSI8_TX, - HPBDMA_SLAVE_SSI8_RX, - HPBDMA_SLAVE_HPBIF0_TX, - HPBDMA_SLAVE_HPBIF0_RX, - HPBDMA_SLAVE_HPBIF1_TX, - HPBDMA_SLAVE_HPBIF1_RX, - HPBDMA_SLAVE_HPBIF2_TX, - HPBDMA_SLAVE_HPBIF2_RX, - HPBDMA_SLAVE_HPBIF3_TX, - HPBDMA_SLAVE_HPBIF3_RX, - HPBDMA_SLAVE_HPBIF4_TX, - HPBDMA_SLAVE_HPBIF4_RX, - HPBDMA_SLAVE_HPBIF5_TX, - HPBDMA_SLAVE_HPBIF5_RX, - HPBDMA_SLAVE_HPBIF6_TX, - HPBDMA_SLAVE_HPBIF6_RX, - HPBDMA_SLAVE_HPBIF7_TX, - HPBDMA_SLAVE_HPBIF7_RX, - HPBDMA_SLAVE_HPBIF8_TX, - HPBDMA_SLAVE_HPBIF8_RX, - HPBDMA_SLAVE_USBFUNC_TX, - HPBDMA_SLAVE_USBFUNC_RX, -}; - -extern void r8a7778_add_standard_devices(void); -extern void r8a7778_add_dt_devices(void); - -extern void r8a7778_init_late(void); -extern void r8a7778_init_irq_dt(void); -extern void r8a7778_clock_init(void); -extern void r8a7778_init_irq_extpin(int irlm); -extern void r8a7778_init_irq_extpin_dt(int irlm); -extern void r8a7778_pinmux_init(void); - -extern int r8a7778_usb_phy_power(bool enable); - -#endif /* __ASM_R8A7778_H__ */ diff --git a/arch/arm/mach-shmobile/setup-r8a7778.c b/arch/arm/mach-shmobile/setup-r8a7778.c index b9116c8..b0c9986 100644 --- a/arch/arm/mach-shmobile/setup-r8a7778.c +++ b/arch/arm/mach-shmobile/setup-r8a7778.c @@ -16,35 +16,16 @@ */ #include -#include #include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include #include "common.h" #include "irqs.h" -#include "r8a7778.h" #define MODEMR 0xffcc0020 -#ifdef CONFIG_COMMON_CLK static void __init r8a7778_timer_init(void) { u32 mode; @@ -55,535 +36,7 @@ static void __init r8a7778_timer_init(void) iounmap(modemr); r8a7778_clocks_init(mode); } -#endif -/* SCIF */ -#define R8A7778_SCIF(index, baseaddr, irq) \ -static struct plat_sci_port scif##index##_platform_data = { \ - .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, \ - .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, \ - .type = PORT_SCIF, \ -}; \ - \ -static struct resource scif##index##_resources[] = { \ - DEFINE_RES_MEM(baseaddr, 0x100), \ - DEFINE_RES_IRQ(irq), \ -} - -R8A7778_SCIF(0, 0xffe40000, gic_iid(0x66)); -R8A7778_SCIF(1, 0xffe41000, gic_iid(0x67)); -R8A7778_SCIF(2, 0xffe42000, gic_iid(0x68)); -R8A7778_SCIF(3, 0xffe43000, gic_iid(0x69)); -R8A7778_SCIF(4, 0xffe44000, gic_iid(0x6a)); -R8A7778_SCIF(5, 0xffe45000, gic_iid(0x6b)); - -#define r8a7778_register_scif(index) \ - platform_device_register_resndata(NULL, "sh-sci", index, \ - scif##index##_resources, \ - ARRAY_SIZE(scif##index##_resources), \ - &scif##index##_platform_data, \ - sizeof(scif##index##_platform_data)) - -/* TMU */ -static struct sh_timer_config sh_tmu0_platform_data = { - .channels_mask = 7, -}; - -static struct resource sh_tmu0_resources[] = { - DEFINE_RES_MEM(0xffd80000, 0x30), - DEFINE_RES_IRQ(gic_iid(0x40)), - DEFINE_RES_IRQ(gic_iid(0x41)), - DEFINE_RES_IRQ(gic_iid(0x42)), -}; - -#define r8a7778_register_tmu(idx) \ - platform_device_register_resndata( \ - NULL, "sh-tmu", idx, \ - sh_tmu##idx##_resources, \ - ARRAY_SIZE(sh_tmu##idx##_resources), \ - &sh_tmu##idx##_platform_data, \ - sizeof(sh_tmu##idx##_platform_data)) - -int r8a7778_usb_phy_power(bool enable) -{ - static struct usb_phy *phy = NULL; - int ret = 0; - - if (!phy) - phy = usb_get_phy(USB_PHY_TYPE_USB2); - - if (IS_ERR(phy)) { - pr_err("kernel doesn't have usb phy driver\n"); - return PTR_ERR(phy); - } - - if (enable) - ret = usb_phy_init(phy); - else - usb_phy_shutdown(phy); - - return ret; -} - -/* USB */ -static int usb_power_on(struct platform_device *pdev) -{ - int ret = r8a7778_usb_phy_power(true); - - if (ret) - return ret; - - pm_runtime_enable(&pdev->dev); - pm_runtime_get_sync(&pdev->dev); - - return 0; -} - -static void usb_power_off(struct platform_device *pdev) -{ - if (r8a7778_usb_phy_power(false)) - return; - - pm_runtime_put_sync(&pdev->dev); - pm_runtime_disable(&pdev->dev); -} - -static int ehci_init_internal_buffer(struct usb_hcd *hcd) -{ - /* - * Below are recommended values from the datasheet; - * see [USB :: Setting of EHCI Internal Buffer]. - */ - /* EHCI IP internal buffer setting */ - iowrite32(0x00ff0040, hcd->regs + 0x0094); - /* EHCI IP internal buffer enable */ - iowrite32(0x00000001, hcd->regs + 0x009C); - - return 0; -} - -static struct usb_ehci_pdata ehci_pdata __initdata = { - .power_on = usb_power_on, - .power_off = usb_power_off, - .power_suspend = usb_power_off, - .pre_setup = ehci_init_internal_buffer, -}; - -static struct resource ehci_resources[] __initdata = { - DEFINE_RES_MEM(0xffe70000, 0x400), - DEFINE_RES_IRQ(gic_iid(0x4c)), -}; - -static struct usb_ohci_pdata ohci_pdata __initdata = { - .power_on = usb_power_on, - .power_off = usb_power_off, - .power_suspend = usb_power_off, -}; - -static struct resource ohci_resources[] __initdata = { - DEFINE_RES_MEM(0xffe70400, 0x400), - DEFINE_RES_IRQ(gic_iid(0x4c)), -}; - -#define USB_PLATFORM_INFO(hci) \ -static struct platform_device_info hci##_info __initdata = { \ - .name = #hci "-platform", \ - .id = -1, \ - .res = hci##_resources, \ - .num_res = ARRAY_SIZE(hci##_resources), \ - .data = &hci##_pdata, \ - .size_data = sizeof(hci##_pdata), \ - .dma_mask = DMA_BIT_MASK(32), \ -} - -USB_PLATFORM_INFO(ehci); -USB_PLATFORM_INFO(ohci); - -/* PFC/GPIO */ -static struct resource pfc_resources[] __initdata = { - DEFINE_RES_MEM(0xfffc0000, 0x118), -}; - -#define R8A7778_GPIO(idx) \ -static struct resource r8a7778_gpio##idx##_resources[] __initdata = { \ - DEFINE_RES_MEM(0xffc40000 + 0x1000 * (idx), 0x30), \ - DEFINE_RES_IRQ(gic_iid(0x87)), \ -}; \ - \ -static struct gpio_rcar_config r8a7778_gpio##idx##_platform_data __initdata = { \ - .gpio_base = 32 * (idx), \ - .irq_base = GPIO_IRQ_BASE(idx), \ - .number_of_pins = 32, \ - .pctl_name = "pfc-r8a7778", \ -} - -R8A7778_GPIO(0); -R8A7778_GPIO(1); -R8A7778_GPIO(2); -R8A7778_GPIO(3); -R8A7778_GPIO(4); - -#define r8a7778_register_gpio(idx) \ - platform_device_register_resndata( \ - NULL, "gpio_rcar", idx, \ - r8a7778_gpio##idx##_resources, \ - ARRAY_SIZE(r8a7778_gpio##idx##_resources), \ - &r8a7778_gpio##idx##_platform_data, \ - sizeof(r8a7778_gpio##idx##_platform_data)) - -void __init r8a7778_pinmux_init(void) -{ - platform_device_register_simple( - "pfc-r8a7778", -1, - pfc_resources, - ARRAY_SIZE(pfc_resources)); - - r8a7778_register_gpio(0); - r8a7778_register_gpio(1); - r8a7778_register_gpio(2); - r8a7778_register_gpio(3); - r8a7778_register_gpio(4); -}; - -/* I2C */ -static struct resource i2c_resources[] __initdata = { - /* I2C0 */ - DEFINE_RES_MEM(0xffc70000, 0x1000), - DEFINE_RES_IRQ(gic_iid(0x63)), - /* I2C1 */ - DEFINE_RES_MEM(0xffc71000, 0x1000), - DEFINE_RES_IRQ(gic_iid(0x6e)), - /* I2C2 */ - DEFINE_RES_MEM(0xffc72000, 0x1000), - DEFINE_RES_IRQ(gic_iid(0x6c)), - /* I2C3 */ - DEFINE_RES_MEM(0xffc73000, 0x1000), - DEFINE_RES_IRQ(gic_iid(0x6d)), -}; - -static void __init r8a7778_register_i2c(int id) -{ - BUG_ON(id < 0 || id > 3); - - platform_device_register_simple( - "i2c-rcar", id, - i2c_resources + (2 * id), 2); -} - -/* HSPI */ -static struct resource hspi_resources[] __initdata = { - /* HSPI0 */ - DEFINE_RES_MEM(0xfffc7000, 0x18), - DEFINE_RES_IRQ(gic_iid(0x5f)), - /* HSPI1 */ - DEFINE_RES_MEM(0xfffc8000, 0x18), - DEFINE_RES_IRQ(gic_iid(0x74)), - /* HSPI2 */ - DEFINE_RES_MEM(0xfffc6000, 0x18), - DEFINE_RES_IRQ(gic_iid(0x75)), -}; - -static void __init r8a7778_register_hspi(int id) -{ - BUG_ON(id < 0 || id > 2); - - platform_device_register_simple( - "sh-hspi", id, - hspi_resources + (2 * id), 2); -} - -void __init r8a7778_add_dt_devices(void) -{ -#ifdef CONFIG_CACHE_L2X0 - void __iomem *base = ioremap_nocache(0xf0100000, 0x1000); - if (base) { - /* - * Shared attribute override enable, 64K*16way - * don't call iounmap(base) - */ - l2x0_init(base, 0x00400000, 0xc20f0fff); - } -#endif -} - -/* HPB-DMA */ - -/* Asynchronous mode register (ASYNCMDR) bits */ -#define HPB_DMAE_ASYNCMDR_ASMD22_MASK BIT(2) /* SDHI0 */ -#define HPB_DMAE_ASYNCMDR_ASMD22_SINGLE BIT(2) /* SDHI0 */ -#define HPB_DMAE_ASYNCMDR_ASMD22_MULTI 0 /* SDHI0 */ -#define HPB_DMAE_ASYNCMDR_ASMD21_MASK BIT(1) /* SDHI0 */ -#define HPB_DMAE_ASYNCMDR_ASMD21_SINGLE BIT(1) /* SDHI0 */ -#define HPB_DMAE_ASYNCMDR_ASMD21_MULTI 0 /* SDHI0 */ - -#define HPBDMA_SSI(_id) \ -{ \ - .id = HPBDMA_SLAVE_SSI## _id ##_TX, \ - .addr = 0xffd91008 + (_id * 0x40), \ - .dcr = HPB_DMAE_DCR_CT | \ - HPB_DMAE_DCR_DIP | \ - HPB_DMAE_DCR_SPDS_32BIT | \ - HPB_DMAE_DCR_DMDL | \ - HPB_DMAE_DCR_DPDS_32BIT, \ - .port = _id + (_id << 8), \ - .dma_ch = (28 + _id), \ -}, { \ - .id = HPBDMA_SLAVE_SSI## _id ##_RX, \ - .addr = 0xffd9100c + (_id * 0x40), \ - .dcr = HPB_DMAE_DCR_CT | \ - HPB_DMAE_DCR_DIP | \ - HPB_DMAE_DCR_SMDL | \ - HPB_DMAE_DCR_SPDS_32BIT | \ - HPB_DMAE_DCR_DPDS_32BIT, \ - .port = _id + (_id << 8), \ - .dma_ch = (28 + _id), \ -} - -#define HPBDMA_HPBIF(_id) \ -{ \ - .id = HPBDMA_SLAVE_HPBIF## _id ##_TX, \ - .addr = 0xffda0000 + (_id * 0x1000), \ - .dcr = HPB_DMAE_DCR_CT | \ - HPB_DMAE_DCR_DIP | \ - HPB_DMAE_DCR_SPDS_32BIT | \ - HPB_DMAE_DCR_DMDL | \ - HPB_DMAE_DCR_DPDS_32BIT, \ - .port = 0x1111, \ - .dma_ch = (28 + _id), \ -}, { \ - .id = HPBDMA_SLAVE_HPBIF## _id ##_RX, \ - .addr = 0xffda0000 + (_id * 0x1000), \ - .dcr = HPB_DMAE_DCR_CT | \ - HPB_DMAE_DCR_DIP | \ - HPB_DMAE_DCR_SMDL | \ - HPB_DMAE_DCR_SPDS_32BIT | \ - HPB_DMAE_DCR_DPDS_32BIT, \ - .port = 0x1111, \ - .dma_ch = (28 + _id), \ -} - -static const struct hpb_dmae_slave_config hpb_dmae_slaves[] = { - { - .id = HPBDMA_SLAVE_SDHI0_TX, - .addr = 0xffe4c000 + 0x30, - .dcr = HPB_DMAE_DCR_SPDS_16BIT | - HPB_DMAE_DCR_DMDL | - HPB_DMAE_DCR_DPDS_16BIT, - .rstr = HPB_DMAE_ASYNCRSTR_ASRST21 | - HPB_DMAE_ASYNCRSTR_ASRST22 | - HPB_DMAE_ASYNCRSTR_ASRST23, - .mdr = HPB_DMAE_ASYNCMDR_ASMD21_MULTI, - .mdm = HPB_DMAE_ASYNCMDR_ASMD21_MASK, - .port = 0x0D0C, - .flags = HPB_DMAE_SET_ASYNC_RESET | HPB_DMAE_SET_ASYNC_MODE, - .dma_ch = 21, - }, { - .id = HPBDMA_SLAVE_SDHI0_RX, - .addr = 0xffe4c000 + 0x30, - .dcr = HPB_DMAE_DCR_SMDL | - HPB_DMAE_DCR_SPDS_16BIT | - HPB_DMAE_DCR_DPDS_16BIT, - .rstr = HPB_DMAE_ASYNCRSTR_ASRST21 | - HPB_DMAE_ASYNCRSTR_ASRST22 | - HPB_DMAE_ASYNCRSTR_ASRST23, - .mdr = HPB_DMAE_ASYNCMDR_ASMD22_MULTI, - .mdm = HPB_DMAE_ASYNCMDR_ASMD22_MASK, - .port = 0x0D0C, - .flags = HPB_DMAE_SET_ASYNC_RESET | HPB_DMAE_SET_ASYNC_MODE, - .dma_ch = 22, - }, { - .id = HPBDMA_SLAVE_USBFUNC_TX, /* for D0 */ - .addr = 0xffe60018, - .dcr = HPB_DMAE_DCR_SPDS_32BIT | - HPB_DMAE_DCR_DMDL | - HPB_DMAE_DCR_DPDS_32BIT, - .port = 0x0000, - .dma_ch = 14, - }, { - .id = HPBDMA_SLAVE_USBFUNC_RX, /* for D1 */ - .addr = 0xffe6001c, - .dcr = HPB_DMAE_DCR_SMDL | - HPB_DMAE_DCR_SPDS_32BIT | - HPB_DMAE_DCR_DPDS_32BIT, - .port = 0x0101, - .dma_ch = 15, - }, - - HPBDMA_SSI(0), - HPBDMA_SSI(1), - HPBDMA_SSI(2), - HPBDMA_SSI(3), - HPBDMA_SSI(4), - HPBDMA_SSI(5), - HPBDMA_SSI(6), - HPBDMA_SSI(7), - HPBDMA_SSI(8), - - HPBDMA_HPBIF(0), - HPBDMA_HPBIF(1), - HPBDMA_HPBIF(2), - HPBDMA_HPBIF(3), - HPBDMA_HPBIF(4), - HPBDMA_HPBIF(5), - HPBDMA_HPBIF(6), - HPBDMA_HPBIF(7), - HPBDMA_HPBIF(8), -}; - -static const struct hpb_dmae_channel hpb_dmae_channels[] = { - HPB_DMAE_CHANNEL(0x7c, HPBDMA_SLAVE_USBFUNC_TX), /* ch. 14 */ - HPB_DMAE_CHANNEL(0x7c, HPBDMA_SLAVE_USBFUNC_RX), /* ch. 15 */ - HPB_DMAE_CHANNEL(0x7e, HPBDMA_SLAVE_SDHI0_TX), /* ch. 21 */ - HPB_DMAE_CHANNEL(0x7e, HPBDMA_SLAVE_SDHI0_RX), /* ch. 22 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI0_TX), /* ch. 28 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI0_RX), /* ch. 28 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF0_TX), /* ch. 28 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF0_RX), /* ch. 28 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI1_TX), /* ch. 29 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI1_RX), /* ch. 29 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF1_TX), /* ch. 29 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF1_RX), /* ch. 29 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI2_TX), /* ch. 30 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI2_RX), /* ch. 30 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF2_TX), /* ch. 30 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF2_RX), /* ch. 30 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI3_TX), /* ch. 31 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI3_RX), /* ch. 31 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF3_TX), /* ch. 31 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF3_RX), /* ch. 31 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI4_TX), /* ch. 32 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI4_RX), /* ch. 32 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF4_TX), /* ch. 32 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF4_RX), /* ch. 32 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI5_TX), /* ch. 33 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI5_RX), /* ch. 33 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF5_TX), /* ch. 33 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF5_RX), /* ch. 33 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI6_TX), /* ch. 34 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI6_RX), /* ch. 34 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF6_TX), /* ch. 34 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF6_RX), /* ch. 34 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI7_TX), /* ch. 35 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI7_RX), /* ch. 35 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF7_TX), /* ch. 35 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF7_RX), /* ch. 35 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI8_TX), /* ch. 36 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI8_RX), /* ch. 36 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF8_TX), /* ch. 36 */ - HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF8_RX), /* ch. 36 */ -}; - -static struct hpb_dmae_pdata dma_platform_data __initdata = { - .slaves = hpb_dmae_slaves, - .num_slaves = ARRAY_SIZE(hpb_dmae_slaves), - .channels = hpb_dmae_channels, - .num_channels = ARRAY_SIZE(hpb_dmae_channels), - .ts_shift = { - [XMIT_SZ_8BIT] = 0, - [XMIT_SZ_16BIT] = 1, - [XMIT_SZ_32BIT] = 2, - }, - .num_hw_channels = 39, -}; - -static struct resource hpb_dmae_resources[] __initdata = { - /* Channel registers */ - DEFINE_RES_MEM(0xffc08000, 0x1000), - /* Common registers */ - DEFINE_RES_MEM(0xffc09000, 0x170), - /* Asynchronous reset registers */ - DEFINE_RES_MEM(0xffc00300, 4), - /* Asynchronous mode registers */ - DEFINE_RES_MEM(0xffc00400, 4), - /* IRQ for DMA channels */ - DEFINE_RES_NAMED(gic_iid(0x7b), 5, NULL, IORESOURCE_IRQ), -}; - -static void __init r8a7778_register_hpb_dmae(void) -{ - platform_device_register_resndata(NULL, "hpb-dma-engine", - -1, hpb_dmae_resources, - ARRAY_SIZE(hpb_dmae_resources), - &dma_platform_data, - sizeof(dma_platform_data)); -} - -void __init r8a7778_add_standard_devices(void) -{ - r8a7778_add_dt_devices(); - r8a7778_register_tmu(0); - r8a7778_register_scif(0); - r8a7778_register_scif(1); - r8a7778_register_scif(2); - r8a7778_register_scif(3); - r8a7778_register_scif(4); - r8a7778_register_scif(5); - r8a7778_register_i2c(0); - r8a7778_register_i2c(1); - r8a7778_register_i2c(2); - r8a7778_register_i2c(3); - r8a7778_register_hspi(0); - r8a7778_register_hspi(1); - r8a7778_register_hspi(2); - - r8a7778_register_hpb_dmae(); -} - -void __init r8a7778_init_late(void) -{ - shmobile_init_late(); - platform_device_register_full(&ehci_info); - platform_device_register_full(&ohci_info); -} - -static struct renesas_intc_irqpin_config irqpin_platform_data __initdata = { - .irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */ - .sense_bitfield_width = 2, -}; - -static struct resource irqpin_resources[] __initdata = { - DEFINE_RES_MEM(0xfe78001c, 4), /* ICR1 */ - DEFINE_RES_MEM(0xfe780010, 4), /* INTPRI */ - DEFINE_RES_MEM(0xfe780024, 4), /* INTREQ */ - DEFINE_RES_MEM(0xfe780044, 4), /* INTMSK0 */ - DEFINE_RES_MEM(0xfe780064, 4), /* INTMSKCLR0 */ - DEFINE_RES_IRQ(gic_iid(0x3b)), /* IRQ0 */ - DEFINE_RES_IRQ(gic_iid(0x3c)), /* IRQ1 */ - DEFINE_RES_IRQ(gic_iid(0x3d)), /* IRQ2 */ - DEFINE_RES_IRQ(gic_iid(0x3e)), /* IRQ3 */ -}; - -void __init r8a7778_init_irq_extpin_dt(int irlm) -{ - void __iomem *icr0 = ioremap_nocache(0xfe780000, PAGE_SIZE); - unsigned long tmp; - - if (!icr0) { - pr_warn("r8a7778: unable to setup external irq pin mode\n"); - return; - } - - tmp = ioread32(icr0); - if (irlm) - tmp |= 1 << 23; /* IRQ0 -> IRQ3 as individual pins */ - else - tmp &= ~(1 << 23); /* IRL mode - not supported */ - tmp |= (1 << 21); /* LVLMODE = 1 */ - iowrite32(tmp, icr0); - iounmap(icr0); -} - -void __init r8a7778_init_irq_extpin(int irlm) -{ - r8a7778_init_irq_extpin_dt(irlm); - if (irlm) - platform_device_register_resndata( - NULL, "renesas_intc_irqpin", -1, - irqpin_resources, ARRAY_SIZE(irqpin_resources), - &irqpin_platform_data, sizeof(irqpin_platform_data)); -} - -#ifdef CONFIG_USE_OF #define INT2SMSKCR0 0x82288 /* 0xfe782288 */ #define INT2SMSKCR1 0x8228c /* 0xfe78228c */ @@ -592,18 +45,11 @@ void __init r8a7778_init_irq_extpin(int irlm) void __init r8a7778_init_irq_dt(void) { void __iomem *base = ioremap_nocache(0xfe700000, 0x00100000); -#ifdef CONFIG_ARCH_SHMOBILE_LEGACY - void __iomem *gic_dist_base = ioremap_nocache(0xfe438000, 0x1000); - void __iomem *gic_cpu_base = ioremap_nocache(0xfe430000, 0x1000); -#endif BUG_ON(!base); -#ifdef CONFIG_ARCH_SHMOBILE_LEGACY - gic_init(0, 29, gic_dist_base, gic_cpu_base); -#else irqchip_init(); -#endif + /* route all interrupts to ARM */ __raw_writel(0x73ffffff, base + INT2NTSR0); __raw_writel(0xffffffff, base + INT2NTSR1); @@ -624,10 +70,6 @@ DT_MACHINE_START(R8A7778_DT, "Generic R8A7778 (Flattened Device Tree)") .init_early = shmobile_init_delay, .init_irq = r8a7778_init_irq_dt, .init_late = shmobile_init_late, -#ifdef CONFIG_COMMON_CLK .init_time = r8a7778_timer_init, -#endif .dt_compat = r8a7778_compat_dt, MACHINE_END - -#endif /* CONFIG_USE_OF */ -- cgit v0.10.2 From 993f58c32c613b7155f3cab75ed4e2e6e6b3ec64 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Fri, 14 Aug 2015 15:51:04 +0200 Subject: ARM: shmobile: Kconfig: remove obsolete option ARCH_R8A7778 Obsoleted by removal of r8a7778 legacy platform. Signed-off-by: Ulrich Hecht Acked-by: by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 6e07e98..61a59b1 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -103,12 +103,6 @@ if ARCH_SHMOBILE_LEGACY comment "Renesas ARM SoCs System Type" -config ARCH_R8A7778 - bool "R-Car M1A (R8A77781)" - select ARCH_RCAR_GEN1 - select ARCH_WANT_OPTIONAL_GPIOLIB - select ARM_GIC - config ARCH_R8A7779 bool "R-Car H1 (R8A77790)" select ARCH_RCAR_GEN1 -- cgit v0.10.2 From 51e47a386f3ac1c3efd10505a7b190667bd4b731 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Fri, 14 Aug 2015 15:51:05 +0200 Subject: ARM: shmobile: r8a7778: remove legacy clock implementation Bock-W was the last legacy clock platform, so this also removes the common legacy clock code. Signed-off-by: Ulrich Hecht Acked-by: by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index 5392925..a65c80ac 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -18,12 +18,6 @@ obj-$(CONFIG_ARCH_R8A7794) += setup-r8a7794.o obj-$(CONFIG_ARCH_EMEV2) += setup-emev2.o obj-$(CONFIG_ARCH_R7S72100) += setup-r7s72100.o -# Clock objects -ifndef CONFIG_COMMON_CLK -obj-y += clock.o -obj-$(CONFIG_ARCH_R8A7778) += clock-r8a7778.o -endif - # CPU reset vector handling objects cpu-y := platsmp.o headsmp.o diff --git a/arch/arm/mach-shmobile/clock-r8a7778.c b/arch/arm/mach-shmobile/clock-r8a7778.c deleted file mode 100644 index e8510c3..0000000 --- a/arch/arm/mach-shmobile/clock-r8a7778.c +++ /dev/null @@ -1,342 +0,0 @@ -/* - * r8a7778 clock framework support - * - * Copyright (C) 2013 Renesas Solutions Corp. - * Copyright (C) 2013 Kuninori Morimoto - * - * based on r8a7779 - * - * Copyright (C) 2011 Renesas Solutions Corp. - * Copyright (C) 2011 Magnus Damm - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -/* - * MD MD MD MD PLLA PLLB EXTAL clki clkz - * 19 18 12 11 (HMz) (MHz) (MHz) - *---------------------------------------------------------------------------- - * 1 0 0 0 x21 x21 38.00 800 800 - * 1 0 0 1 x24 x24 33.33 800 800 - * 1 0 1 0 x28 x28 28.50 800 800 - * 1 0 1 1 x32 x32 25.00 800 800 - * 1 1 0 1 x24 x21 33.33 800 700 - * 1 1 1 0 x28 x21 28.50 800 600 - * 1 1 1 1 x32 x24 25.00 800 600 - */ - -#include -#include -#include -#include "clock.h" -#include "common.h" - -#define MSTPCR0 IOMEM(0xffc80030) -#define MSTPCR1 IOMEM(0xffc80034) -#define MSTPCR3 IOMEM(0xffc8003c) -#define MSTPSR1 IOMEM(0xffc80044) -#define MSTPSR4 IOMEM(0xffc80048) -#define MSTPSR6 IOMEM(0xffc8004c) -#define MSTPCR4 IOMEM(0xffc80050) -#define MSTPCR5 IOMEM(0xffc80054) -#define MSTPCR6 IOMEM(0xffc80058) -#define MODEMR 0xFFCC0020 - -#define MD(nr) BIT(nr) - -/* ioremap() through clock mapping mandatory to avoid - * collision with ARM coherent DMA virtual memory range. - */ - -static struct clk_mapping cpg_mapping = { - .phys = 0xffc80000, - .len = 0x80, -}; - -static struct clk extal_clk = { - /* .rate will be updated on r8a7778_clock_init() */ - .mapping = &cpg_mapping, -}; - -static struct clk audio_clk_a = { -}; - -static struct clk audio_clk_b = { -}; - -static struct clk audio_clk_c = { -}; - -/* - * clock ratio of these clock will be updated - * on r8a7778_clock_init() - */ -SH_FIXED_RATIO_CLK_SET(plla_clk, extal_clk, 1, 1); -SH_FIXED_RATIO_CLK_SET(pllb_clk, extal_clk, 1, 1); -SH_FIXED_RATIO_CLK_SET(i_clk, plla_clk, 1, 1); -SH_FIXED_RATIO_CLK_SET(s_clk, plla_clk, 1, 1); -SH_FIXED_RATIO_CLK_SET(s1_clk, plla_clk, 1, 1); -SH_FIXED_RATIO_CLK_SET(s3_clk, plla_clk, 1, 1); -SH_FIXED_RATIO_CLK_SET(s4_clk, plla_clk, 1, 1); -SH_FIXED_RATIO_CLK_SET(b_clk, plla_clk, 1, 1); -SH_FIXED_RATIO_CLK_SET(out_clk, plla_clk, 1, 1); -SH_FIXED_RATIO_CLK_SET(p_clk, plla_clk, 1, 1); -SH_FIXED_RATIO_CLK_SET(g_clk, plla_clk, 1, 1); -SH_FIXED_RATIO_CLK_SET(z_clk, pllb_clk, 1, 1); - -static struct clk *main_clks[] = { - &extal_clk, - &plla_clk, - &pllb_clk, - &i_clk, - &s_clk, - &s1_clk, - &s3_clk, - &s4_clk, - &b_clk, - &out_clk, - &p_clk, - &g_clk, - &z_clk, - &audio_clk_a, - &audio_clk_b, - &audio_clk_c, -}; - -enum { - MSTP531, MSTP530, - MSTP529, MSTP528, MSTP527, MSTP526, MSTP525, MSTP524, MSTP523, - MSTP331, - MSTP323, MSTP322, MSTP321, - MSTP311, MSTP310, - MSTP309, MSTP308, MSTP307, - MSTP114, - MSTP110, MSTP109, - MSTP100, - MSTP030, - MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021, - MSTP016, MSTP015, MSTP012, MSTP011, MSTP010, - MSTP009, MSTP008, MSTP007, - MSTP_NR }; - -static struct clk mstp_clks[MSTP_NR] = { - [MSTP531] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 31, 0), /* SCU0 */ - [MSTP530] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 30, 0), /* SCU1 */ - [MSTP529] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 29, 0), /* SCU2 */ - [MSTP528] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 28, 0), /* SCU3 */ - [MSTP527] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 27, 0), /* SCU4 */ - [MSTP526] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 26, 0), /* SCU5 */ - [MSTP525] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 25, 0), /* SCU6 */ - [MSTP524] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 24, 0), /* SCU7 */ - [MSTP523] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 23, 0), /* SCU8 */ - [MSTP331] = SH_CLK_MSTP32(&s4_clk, MSTPCR3, 31, 0), /* MMC */ - [MSTP323] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 23, 0), /* SDHI0 */ - [MSTP322] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 22, 0), /* SDHI1 */ - [MSTP321] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 21, 0), /* SDHI2 */ - [MSTP311] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 11, 0), /* SSI4 */ - [MSTP310] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 10, 0), /* SSI5 */ - [MSTP309] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 9, 0), /* SSI6 */ - [MSTP308] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 8, 0), /* SSI7 */ - [MSTP307] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 7, 0), /* SSI8 */ - [MSTP114] = SH_CLK_MSTP32(&p_clk, MSTPCR1, 14, 0), /* Ether */ - [MSTP110] = SH_CLK_MSTP32(&s_clk, MSTPCR1, 10, 0), /* VIN0 */ - [MSTP109] = SH_CLK_MSTP32(&s_clk, MSTPCR1, 9, 0), /* VIN1 */ - [MSTP100] = SH_CLK_MSTP32(&p_clk, MSTPCR1, 0, 0), /* USB0/1 */ - [MSTP030] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 30, 0), /* I2C0 */ - [MSTP029] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 29, 0), /* I2C1 */ - [MSTP028] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 28, 0), /* I2C2 */ - [MSTP027] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 27, 0), /* I2C3 */ - [MSTP026] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 26, 0), /* SCIF0 */ - [MSTP025] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 25, 0), /* SCIF1 */ - [MSTP024] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 24, 0), /* SCIF2 */ - [MSTP023] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 23, 0), /* SCIF3 */ - [MSTP022] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 22, 0), /* SCIF4 */ - [MSTP021] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 21, 0), /* SCIF5 */ - [MSTP016] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 16, 0), /* TMU0 */ - [MSTP015] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 15, 0), /* TMU1 */ - [MSTP012] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 12, 0), /* SSI0 */ - [MSTP011] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 11, 0), /* SSI1 */ - [MSTP010] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 10, 0), /* SSI2 */ - [MSTP009] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 9, 0), /* SSI3 */ - [MSTP008] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 8, 0), /* SRU */ - [MSTP007] = SH_CLK_MSTP32(&s_clk, MSTPCR0, 7, 0), /* HSPI */ -}; - -static struct clk_lookup lookups[] = { - /* main */ - CLKDEV_CON_ID("shyway_clk", &s_clk), - CLKDEV_CON_ID("peripheral_clk", &p_clk), - - /* MSTP32 clocks */ - CLKDEV_DEV_ID("sh_mmcif", &mstp_clks[MSTP331]), /* MMC */ - CLKDEV_DEV_ID("ffe4e000.mmc", &mstp_clks[MSTP331]), /* MMC */ - CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP323]), /* SDHI0 */ - CLKDEV_DEV_ID("ffe4c000.sd", &mstp_clks[MSTP323]), /* SDHI0 */ - CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */ - CLKDEV_DEV_ID("ffe4d000.sd", &mstp_clks[MSTP322]), /* SDHI1 */ - CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */ - CLKDEV_DEV_ID("ffe4f000.sd", &mstp_clks[MSTP321]), /* SDHI2 */ - CLKDEV_DEV_ID("r8a777x-ether", &mstp_clks[MSTP114]), /* Ether */ - CLKDEV_DEV_ID("r8a7778-vin.0", &mstp_clks[MSTP110]), /* VIN0 */ - CLKDEV_DEV_ID("r8a7778-vin.1", &mstp_clks[MSTP109]), /* VIN1 */ - CLKDEV_DEV_ID("ehci-platform", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */ - CLKDEV_DEV_ID("ohci-platform", &mstp_clks[MSTP100]), /* USB OHCI port0/1 */ - CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP100]), /* USB FUNC */ - CLKDEV_DEV_ID("i2c-rcar.0", &mstp_clks[MSTP030]), /* I2C0 */ - CLKDEV_DEV_ID("ffc70000.i2c", &mstp_clks[MSTP030]), /* I2C0 */ - CLKDEV_DEV_ID("i2c-rcar.1", &mstp_clks[MSTP029]), /* I2C1 */ - CLKDEV_DEV_ID("ffc71000.i2c", &mstp_clks[MSTP029]), /* I2C1 */ - CLKDEV_DEV_ID("i2c-rcar.2", &mstp_clks[MSTP028]), /* I2C2 */ - CLKDEV_DEV_ID("ffc72000.i2c", &mstp_clks[MSTP028]), /* I2C2 */ - CLKDEV_DEV_ID("i2c-rcar.3", &mstp_clks[MSTP027]), /* I2C3 */ - CLKDEV_DEV_ID("ffc73000.i2c", &mstp_clks[MSTP027]), /* I2C3 */ - CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */ - CLKDEV_DEV_ID("ffe40000.serial", &mstp_clks[MSTP026]), /* SCIF0 */ - CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */ - CLKDEV_DEV_ID("ffe41000.serial", &mstp_clks[MSTP025]), /* SCIF1 */ - CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP024]), /* SCIF2 */ - CLKDEV_DEV_ID("ffe42000.serial", &mstp_clks[MSTP024]), /* SCIF2 */ - CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP023]), /* SCIF3 */ - CLKDEV_DEV_ID("ffe43000.serial", &mstp_clks[MSTP023]), /* SCIF3 */ - CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP022]), /* SCIF4 */ - CLKDEV_DEV_ID("ffe44000.serial", &mstp_clks[MSTP022]), /* SCIF4 */ - CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP021]), /* SCIF6 */ - CLKDEV_DEV_ID("ffe45000.serial", &mstp_clks[MSTP021]), /* SCIF5 */ - CLKDEV_DEV_ID("sh-hspi.0", &mstp_clks[MSTP007]), /* HSPI0 */ - CLKDEV_DEV_ID("fffc7000.spi", &mstp_clks[MSTP007]), /* HSPI0 */ - CLKDEV_DEV_ID("sh-hspi.1", &mstp_clks[MSTP007]), /* HSPI1 */ - CLKDEV_DEV_ID("fffc8000.spi", &mstp_clks[MSTP007]), /* HSPI1 */ - CLKDEV_DEV_ID("sh-hspi.2", &mstp_clks[MSTP007]), /* HSPI2 */ - CLKDEV_DEV_ID("fffc6000.spi", &mstp_clks[MSTP007]), /* HSPI2 */ - CLKDEV_DEV_ID("rcar_sound", &mstp_clks[MSTP008]), /* SRU */ - - CLKDEV_ICK_ID("clk_a", "rcar_sound", &audio_clk_a), - CLKDEV_ICK_ID("clk_b", "rcar_sound", &audio_clk_b), - CLKDEV_ICK_ID("clk_c", "rcar_sound", &audio_clk_c), - CLKDEV_ICK_ID("clk_i", "rcar_sound", &s1_clk), - CLKDEV_ICK_ID("ssi.0", "rcar_sound", &mstp_clks[MSTP012]), - CLKDEV_ICK_ID("ssi.1", "rcar_sound", &mstp_clks[MSTP011]), - CLKDEV_ICK_ID("ssi.2", "rcar_sound", &mstp_clks[MSTP010]), - CLKDEV_ICK_ID("ssi.3", "rcar_sound", &mstp_clks[MSTP009]), - CLKDEV_ICK_ID("ssi.4", "rcar_sound", &mstp_clks[MSTP311]), - CLKDEV_ICK_ID("ssi.5", "rcar_sound", &mstp_clks[MSTP310]), - CLKDEV_ICK_ID("ssi.6", "rcar_sound", &mstp_clks[MSTP309]), - CLKDEV_ICK_ID("ssi.7", "rcar_sound", &mstp_clks[MSTP308]), - CLKDEV_ICK_ID("ssi.8", "rcar_sound", &mstp_clks[MSTP307]), - CLKDEV_ICK_ID("src.0", "rcar_sound", &mstp_clks[MSTP531]), - CLKDEV_ICK_ID("src.1", "rcar_sound", &mstp_clks[MSTP530]), - CLKDEV_ICK_ID("src.2", "rcar_sound", &mstp_clks[MSTP529]), - CLKDEV_ICK_ID("src.3", "rcar_sound", &mstp_clks[MSTP528]), - CLKDEV_ICK_ID("src.4", "rcar_sound", &mstp_clks[MSTP527]), - CLKDEV_ICK_ID("src.5", "rcar_sound", &mstp_clks[MSTP526]), - CLKDEV_ICK_ID("src.6", "rcar_sound", &mstp_clks[MSTP525]), - CLKDEV_ICK_ID("src.7", "rcar_sound", &mstp_clks[MSTP524]), - CLKDEV_ICK_ID("src.8", "rcar_sound", &mstp_clks[MSTP523]), - CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP016]), - CLKDEV_ICK_ID("fck", "ffd80000.timer", &mstp_clks[MSTP016]), - CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[MSTP015]), - CLKDEV_ICK_ID("fck", "ffd81000.timer", &mstp_clks[MSTP015]), -}; - -void __init r8a7778_clock_init(void) -{ - void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE); - u32 mode; - int k, ret = 0; - - BUG_ON(!modemr); - mode = ioread32(modemr); - iounmap(modemr); - - switch (mode & (MD(19) | MD(18) | MD(12) | MD(11))) { - case MD(19): - extal_clk.rate = 38000000; - SH_CLK_SET_RATIO(&plla_clk_ratio, 21, 1); - SH_CLK_SET_RATIO(&pllb_clk_ratio, 21, 1); - break; - case MD(19) | MD(11): - extal_clk.rate = 33333333; - SH_CLK_SET_RATIO(&plla_clk_ratio, 24, 1); - SH_CLK_SET_RATIO(&pllb_clk_ratio, 24, 1); - break; - case MD(19) | MD(12): - extal_clk.rate = 28500000; - SH_CLK_SET_RATIO(&plla_clk_ratio, 28, 1); - SH_CLK_SET_RATIO(&pllb_clk_ratio, 28, 1); - break; - case MD(19) | MD(12) | MD(11): - extal_clk.rate = 25000000; - SH_CLK_SET_RATIO(&plla_clk_ratio, 32, 1); - SH_CLK_SET_RATIO(&pllb_clk_ratio, 32, 1); - break; - case MD(19) | MD(18) | MD(11): - extal_clk.rate = 33333333; - SH_CLK_SET_RATIO(&plla_clk_ratio, 24, 1); - SH_CLK_SET_RATIO(&pllb_clk_ratio, 21, 1); - break; - case MD(19) | MD(18) | MD(12): - extal_clk.rate = 28500000; - SH_CLK_SET_RATIO(&plla_clk_ratio, 28, 1); - SH_CLK_SET_RATIO(&pllb_clk_ratio, 21, 1); - break; - case MD(19) | MD(18) | MD(12) | MD(11): - extal_clk.rate = 25000000; - SH_CLK_SET_RATIO(&plla_clk_ratio, 32, 1); - SH_CLK_SET_RATIO(&pllb_clk_ratio, 24, 1); - break; - default: - BUG(); - } - - if (mode & MD(1)) { - SH_CLK_SET_RATIO(&i_clk_ratio, 1, 1); - SH_CLK_SET_RATIO(&s_clk_ratio, 1, 3); - SH_CLK_SET_RATIO(&s1_clk_ratio, 1, 6); - SH_CLK_SET_RATIO(&s3_clk_ratio, 1, 4); - SH_CLK_SET_RATIO(&s4_clk_ratio, 1, 8); - SH_CLK_SET_RATIO(&p_clk_ratio, 1, 12); - SH_CLK_SET_RATIO(&g_clk_ratio, 1, 12); - if (mode & MD(2)) { - SH_CLK_SET_RATIO(&b_clk_ratio, 1, 18); - SH_CLK_SET_RATIO(&out_clk_ratio, 1, 18); - } else { - SH_CLK_SET_RATIO(&b_clk_ratio, 1, 12); - SH_CLK_SET_RATIO(&out_clk_ratio, 1, 12); - } - } else { - SH_CLK_SET_RATIO(&i_clk_ratio, 1, 1); - SH_CLK_SET_RATIO(&s_clk_ratio, 1, 4); - SH_CLK_SET_RATIO(&s1_clk_ratio, 1, 8); - SH_CLK_SET_RATIO(&s3_clk_ratio, 1, 4); - SH_CLK_SET_RATIO(&s4_clk_ratio, 1, 8); - SH_CLK_SET_RATIO(&p_clk_ratio, 1, 16); - SH_CLK_SET_RATIO(&g_clk_ratio, 1, 12); - if (mode & MD(2)) { - SH_CLK_SET_RATIO(&b_clk_ratio, 1, 16); - SH_CLK_SET_RATIO(&out_clk_ratio, 1, 16); - } else { - SH_CLK_SET_RATIO(&b_clk_ratio, 1, 12); - SH_CLK_SET_RATIO(&out_clk_ratio, 1, 12); - } - } - - for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) - ret = clk_register(main_clks[k]); - - if (!ret) - ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); - - clkdev_add_table(lookups, ARRAY_SIZE(lookups)); - - if (!ret) - shmobile_clk_init(); - else - panic("failed to setup r8a7778 clocks\n"); -} diff --git a/arch/arm/mach-shmobile/clock.c b/arch/arm/mach-shmobile/clock.c deleted file mode 100644 index 68c2d06..0000000 --- a/arch/arm/mach-shmobile/clock.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SH-Mobile Clock Framework - * - * Copyright (C) 2010 Magnus Damm - * - * Used together with arch/arm/common/clkdev.c and drivers/sh/clk.c. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include -#include -#include -#include - -#include "clock.h" -#include "common.h" - -unsigned long shmobile_fixed_ratio_clk_recalc(struct clk *clk) -{ - struct clk_ratio *p = clk->priv; - - return clk->parent->rate / p->div * p->mul; -}; - -struct sh_clk_ops shmobile_fixed_ratio_clk_ops = { - .recalc = shmobile_fixed_ratio_clk_recalc, -}; - -int __init shmobile_clk_init(void) -{ - /* Kick the child clocks.. */ - recalculate_root_clocks(); - - /* Enable the necessary init clocks */ - clk_enable_init_clocks(); - - return 0; -} diff --git a/arch/arm/mach-shmobile/clock.h b/arch/arm/mach-shmobile/clock.h deleted file mode 100644 index cf3552e..0000000 --- a/arch/arm/mach-shmobile/clock.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef CLOCK_H -#define CLOCK_H - -/* legacy clock implementation */ - -struct clk; -unsigned long shmobile_fixed_ratio_clk_recalc(struct clk *clk); -extern struct sh_clk_ops shmobile_fixed_ratio_clk_ops; - -/* clock ratio */ -struct clk_ratio { - int mul; - int div; -}; - -#define SH_CLK_RATIO(name, m, d) \ -static struct clk_ratio name ##_ratio = { \ - .mul = m, \ - .div = d, \ -} - -#define SH_FIXED_RATIO_CLKg(name, p, r) \ -struct clk name = { \ - .parent = &p, \ - .ops = &shmobile_fixed_ratio_clk_ops,\ - .priv = &r ## _ratio, \ -} - -#define SH_FIXED_RATIO_CLK(name, p, r) \ -static SH_FIXED_RATIO_CLKg(name, p, r) - -#define SH_FIXED_RATIO_CLK_SET(name, p, m, d) \ - SH_CLK_RATIO(name, m, d); \ - SH_FIXED_RATIO_CLK(name, p, name) - -#define SH_CLK_SET_RATIO(p, m, d) \ -do { \ - (p)->mul = m; \ - (p)->div = d; \ -} while (0) - -#endif -- cgit v0.10.2 From 36d6c9280b7f7c895c124ecf918ee5bda3c52ccd Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Fri, 14 Aug 2015 15:51:06 +0200 Subject: ARM: shmobile: remove ARCH_SHMOBILE_LEGACY option With Bock-W, the last legacy platform has been removed. Signed-off-by: Ulrich Hecht Acked-by: by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 72ad724..471a3670 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -621,28 +621,6 @@ config ARCH_PXA help Support for Intel/Marvell's PXA2xx/PXA3xx processor line. -config ARCH_SHMOBILE_LEGACY - bool "Renesas ARM SoCs (non-multiplatform)" - select ARCH_SHMOBILE - select ARM_PATCH_PHYS_VIRT if MMU - select CLKDEV_LOOKUP - select CPU_V7 - select GENERIC_CLOCKEVENTS - select HAVE_ARM_SCU if SMP - select HAVE_ARM_TWD if SMP - select HAVE_SMP - select MIGHT_HAVE_CACHE_L2X0 - select MULTI_IRQ_HANDLER - select NO_IOPORT_MAP - select PINCTRL - select PM_GENERIC_DOMAINS if PM - select SH_CLK_CPG - select SPARSE_IRQ - help - Support for Renesas ARM SoC platforms using a non-multiplatform - kernel. This includes the SH-Mobile, R-Mobile, EMMA-Mobile, R-Car - and RZ families. - config ARCH_RPC bool "RiscPC" select ARCH_ACORN @@ -1534,7 +1512,6 @@ config HZ_FIXED default 200 if ARCH_EBSA110 || ARCH_S3C24XX || \ ARCH_S5PV210 || ARCH_EXYNOS4 default 128 if SOC_AT91RM9200 - default SHMOBILE_TIMER_HZ if ARCH_SHMOBILE_LEGACY default 0 choice @@ -1752,8 +1729,7 @@ config ARM_MODULE_PLTS source "mm/Kconfig" config FORCE_MAX_ZONEORDER - int "Maximum zone order" if ARCH_SHMOBILE_LEGACY - range 11 64 if ARCH_SHMOBILE_LEGACY + int "Maximum zone order" default "12" if SOC_AM33XX default "9" if SA1111 || ARCH_EFM32 default "11" diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 0cfd7f9..40a3c25 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -1621,8 +1621,7 @@ config DEBUG_UNCOMPRESS config UNCOMPRESS_INCLUDE string default "debug/uncompress.h" if ARCH_MULTIPLATFORM || ARCH_MSM || \ - PLAT_SAMSUNG || ARM_SINGLE_ARMV7M || \ - ARCH_SHMOBILE_LEGACY + PLAT_SAMSUNG || ARM_SINGLE_ARMV7M default "mach/uncompress.h" config EARLY_PRINTK diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 61a59b1..7f2e053 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -99,29 +99,6 @@ config ARCH_SH73A0 comment "Renesas ARM SoCs System Configuration" endif -if ARCH_SHMOBILE_LEGACY - -comment "Renesas ARM SoCs System Type" - -config ARCH_R8A7779 - bool "R-Car H1 (R8A77790)" - select ARCH_RCAR_GEN1 - select ARCH_WANT_OPTIONAL_GPIOLIB - select ARM_GIC - -comment "Renesas ARM SoCs System Configuration" - -config CPU_HAS_INTEVT - bool - default y - -config SH_CLK_CPG - bool - -source "drivers/sh/Kconfig" - -endif - if ARCH_SHMOBILE menu "Timer and clock configuration" -- cgit v0.10.2 From e12cc06150094d936c955d5fbe8681a0a44b23f8 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Fri, 14 Aug 2015 15:51:07 +0200 Subject: ARM: shmobile: bockw: remove legacy defconfig Obsoleted by removal of legacy platform. Signed-off-by: Ulrich Hecht Acked-by: by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/configs/bockw_defconfig b/arch/arm/configs/bockw_defconfig deleted file mode 100644 index 3125e00..0000000 --- a/arch/arm/configs/bockw_defconfig +++ /dev/null @@ -1,133 +0,0 @@ -# CONFIG_ARM_PATCH_PHYS_VIRT is not set -CONFIG_KERNEL_LZMA=y -CONFIG_NO_HZ=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=16 -CONFIG_SYSCTL_SYSCALL=y -CONFIG_EMBEDDED=y -CONFIG_SLAB=y -# CONFIG_IOSCHED_CFQ is not set -CONFIG_ARCH_SHMOBILE_LEGACY=y -CONFIG_ARCH_R8A7778=y -CONFIG_MACH_BOCKW=y -CONFIG_MEMORY_START=0x60000000 -CONFIG_MEMORY_SIZE=0x10000000 -CONFIG_SHMOBILE_TIMER_HZ=1024 -# CONFIG_SH_TIMER_CMT is not set -# CONFIG_EM_TIMER_STI is not set -CONFIG_ARM_ERRATA_430973=y -CONFIG_ARM_ERRATA_458693=y -CONFIG_ARM_ERRATA_460075=y -CONFIG_ARM_ERRATA_743622=y -CONFIG_ARM_ERRATA_754322=y -CONFIG_AEABI=y -# CONFIG_OABI_COMPAT is not set -CONFIG_HIGHMEM=y -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_ARM_APPENDED_DTB=y -CONFIG_VFP=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_PM=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set -# CONFIG_INET_DIAG is not set -# CONFIG_IPV6 is not set -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_DEVTMPFS=y -CONFIG_DEVTMPFS_MOUNT=y -# CONFIG_STANDALONE is not set -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_FW_LOADER is not set -CONFIG_MTD=y -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_CFI=y -CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_M25P80=y -CONFIG_MTD_SPI_NOR=y -CONFIG_SCSI=y -CONFIG_BLK_DEV_SD=y -CONFIG_NETDEVICES=y -# CONFIG_NET_CADENCE is not set -# CONFIG_NET_VENDOR_BROADCOM is not set -# CONFIG_NET_VENDOR_CIRRUS is not set -# CONFIG_NET_VENDOR_FARADAY is not set -# CONFIG_NET_VENDOR_INTEL is not set -# CONFIG_NET_VENDOR_MARVELL is not set -# CONFIG_NET_VENDOR_MICREL is not set -# CONFIG_NET_VENDOR_NATSEMI is not set -# CONFIG_NET_VENDOR_SEEQ is not set -CONFIG_SMSC911X=y -# CONFIG_NET_VENDOR_STMICRO is not set -# CONFIG_NET_VENDOR_WIZNET is not set -# CONFIG_INPUT is not set -# CONFIG_SERIO is not set -# CONFIG_VT is not set -# CONFIG_LEGACY_PTYS is not set -# CONFIG_DEVKMEM is not set -CONFIG_SERIAL_SH_SCI=y -CONFIG_SERIAL_SH_SCI_NR_UARTS=6 -CONFIG_SERIAL_SH_SCI_CONSOLE=y -# CONFIG_HW_RANDOM is not set -# CONFIG_HWMON is not set -CONFIG_I2C=y -CONFIG_I2C_RCAR=y -CONFIG_GPIO_RCAR=y -CONFIG_REGULATOR=y -CONFIG_MEDIA_SUPPORT=y -CONFIG_MEDIA_CAMERA_SUPPORT=y -CONFIG_V4L_PLATFORM_DRIVERS=y -CONFIG_SOC_CAMERA=y -CONFIG_VIDEO_RCAR_VIN=y -# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set -CONFIG_VIDEO_ML86V7667=y -CONFIG_SPI=y -CONFIG_SPI_SH_HSPI=y -CONFIG_SOUND=y -CONFIG_SND=y -CONFIG_SND_SOC=y -CONFIG_SND_SOC_RCAR=y -CONFIG_USB=y -CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_OHCI_HCD=y -CONFIG_USB_OHCI_HCD_PLATFORM=y -CONFIG_USB_EHCI_HCD_PLATFORM=y -CONFIG_USB_STORAGE=y -CONFIG_USB_RCAR_PHY=y -CONFIG_MMC=y -CONFIG_MMC_SDHI=y -CONFIG_MMC_SH_MMCIF=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_RX8581=y -CONFIG_DMADEVICES=y -CONFIG_RCAR_HPB_DMAE=y -CONFIG_UIO=y -CONFIG_UIO_PDRV_GENIRQ=y -# CONFIG_IOMMU_SUPPORT is not set -# CONFIG_DNOTIFY is not set -CONFIG_TMPFS=y -# CONFIG_MISC_FILESYSTEMS is not set -CONFIG_NFS_FS=y -CONFIG_NFS_V3_ACL=y -CONFIG_NFS_V4=y -CONFIG_NFS_SWAP=y -CONFIG_NFS_V4_1=y -CONFIG_ROOT_NFS=y -# CONFIG_ENABLE_WARN_DEPRECATED is not set -# CONFIG_ENABLE_MUST_CHECK is not set -# CONFIG_SCHED_DEBUG is not set -# CONFIG_DEBUG_BUGVERBOSE is not set -# CONFIG_FTRACE is not set -# CONFIG_ARM_UNWIND is not set -CONFIG_AVERAGE=y -- cgit v0.10.2 From 8d4f9480f6e7882acf4c320833457f879d2bbd10 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Fri, 14 Aug 2015 15:51:08 +0200 Subject: MAINTAINERS: remove references to dropped marzen and bockw defconfigs Signed-off-by: Ulrich Hecht Acked-by: by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/MAINTAINERS b/MAINTAINERS index 7ba7ab7..803c91ed 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1485,8 +1485,6 @@ F: arch/arm/boot/dts/emev2* F: arch/arm/boot/dts/r7s* F: arch/arm/boot/dts/r8a* F: arch/arm/boot/dts/sh* -F: arch/arm/configs/bockw_defconfig -F: arch/arm/configs/marzen_defconfig F: arch/arm/configs/shmobile_defconfig F: arch/arm/include/debug/renesas-scif.S F: arch/arm/mach-shmobile/ -- cgit v0.10.2 From 6263ef7c25d3e081642c22d2e6d0dc1e9cb7c015 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Tue, 18 Aug 2015 15:12:17 +0200 Subject: ARM: shmobile: bockw: remove legacy DTB build target Obsoleted by removal of legacy platform. Signed-off-by: Ulrich Hecht Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index ad74cf9..08f85bc 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -522,8 +522,6 @@ dtb-$(CONFIG_ARCH_S5PV210) += \ s5pv210-smdkc110.dtb \ s5pv210-smdkv210.dtb \ s5pv210-torbreck.dtb -dtb-$(CONFIG_ARCH_SHMOBILE_LEGACY) += \ - r8a7778-bockw.dtb dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += \ emev2-kzm9d.dtb \ r7s72100-genmai.dtb \ -- cgit v0.10.2 From 7463c876331d01aafb420f3637c2f69409eb0447 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Tue, 18 Aug 2015 15:12:18 +0200 Subject: ARM: shmobile: Kconfig: remove unused SHMOBILE_TIMER_HZ section Obsoleted by removal of legacy platforms. Signed-off-by: Ulrich Hecht Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 7f2e053..88734a5 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -98,23 +98,3 @@ config ARCH_SH73A0 comment "Renesas ARM SoCs System Configuration" endif - -if ARCH_SHMOBILE - -menu "Timer and clock configuration" - -config SHMOBILE_TIMER_HZ - int "Kernel HZ (jiffies per second)" - range 32 1024 - default "128" - help - Allows the configuration of the timer frequency. It is customary - to have the timer interrupt run at 1000 Hz or 100 Hz, but in the - case of low timer frequencies other values may be more suitable. - Renesas ARM SoC systems using a 32768 Hz RCLK for clock events may - want to select a HZ value such as 128 that can evenly divide RCLK. - A HZ value that does not divide evenly may cause timer drift. - -endmenu - -endif -- cgit v0.10.2 From fc22a4d484fafb373c51bb6792bb5a4ef4caae71 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Thu, 20 Aug 2015 16:27:44 -0700 Subject: ARM: shmobile: remove Makefile.boot Now that the only multiplatform boot is supported for all shmobile platforms Makefile.boot may be removed. This seems correct to me given: * Setting MACHINE to no value in arch/arm/Makefile if CONFIG_ARCH_MULTIPLATFORM is set * Not including Makefile.boot in arch/arm/boot/Makefile if MACHINE has no value Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven diff --git a/arch/arm/mach-shmobile/Makefile.boot b/arch/arm/mach-shmobile/Makefile.boot deleted file mode 100644 index e69de29..0000000 -- cgit v0.10.2 From 04418c23a9411b85b8789eab5f4397bcbd62b7b4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 29 Aug 2015 00:37:17 +0300 Subject: ARM: shmobile: Remove legacy clock support leftovers The shmobile_clk_init() function has been removed and the linux/sh_clk.h header doesn't need to be included anymore. Signed-off-by: Laurent Pinchart Signed-off-by: Simon Horman diff --git a/arch/arm/mach-shmobile/common.h b/arch/arm/mach-shmobile/common.h index 0833a6e..9cb1121 100644 --- a/arch/arm/mach-shmobile/common.h +++ b/arch/arm/mach-shmobile/common.h @@ -15,8 +15,6 @@ extern void shmobile_boot_scu(void); extern void shmobile_smp_scu_prepare_cpus(unsigned int max_cpus); extern void shmobile_smp_scu_cpu_die(unsigned int cpu); extern int shmobile_smp_scu_cpu_kill(unsigned int cpu); -struct clk; -extern int shmobile_clk_init(void); extern struct platform_suspend_ops shmobile_suspend_ops; #ifdef CONFIG_SUSPEND diff --git a/arch/arm/mach-shmobile/r8a7779.h b/arch/arm/mach-shmobile/r8a7779.h index db303f7..aad833a 100644 --- a/arch/arm/mach-shmobile/r8a7779.h +++ b/arch/arm/mach-shmobile/r8a7779.h @@ -1,8 +1,6 @@ #ifndef __ASM_R8A7779_H__ #define __ASM_R8A7779_H__ -#include - extern void r8a7779_pm_init(void); #ifdef CONFIG_PM -- cgit v0.10.2 From ea3e4a2b3945f62457fa377c2bd0f49c32192194 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 13 Jul 2015 15:15:23 +0900 Subject: ARM: shmobile: Remove Marzen from shmobile_defconfig Kill of the defconfig bits now when the marzen-reference board code is gone. Signed-off-by: Magnus Damm Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig index 89bf31c..0bdeb49 100644 --- a/arch/arm/configs/shmobile_defconfig +++ b/arch/arm/configs/shmobile_defconfig @@ -21,7 +21,6 @@ CONFIG_ARCH_R8A7791=y CONFIG_ARCH_R8A7793=y CONFIG_ARCH_R8A7794=y CONFIG_ARCH_SH73A0=y -CONFIG_MACH_MARZEN=y CONFIG_CPU_BPREDICT_DISABLE=y CONFIG_PL310_ERRATA_588369=y CONFIG_ARM_ERRATA_754322=y -- cgit v0.10.2 From 0a8b0695f4c490c349ee12956d6946576c44a419 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 15 Jul 2015 15:45:23 +0900 Subject: ARM: multi_v7_defconfig: Remove Marzen Kill of the defconfig bits now when the marzen-reference board code is gone. Based on work by Magnus Damm. Acked-by: Magnus Damm Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 03deb7f..e682da3 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -85,7 +85,6 @@ CONFIG_ARCH_R8A7791=y CONFIG_ARCH_R8A7793=y CONFIG_ARCH_R8A7794=y CONFIG_ARCH_SH73A0=y -CONFIG_MACH_MARZEN=y CONFIG_ARCH_SUNXI=y CONFIG_ARCH_SIRF=y CONFIG_ARCH_TEGRA=y -- cgit v0.10.2 From e5923ad92d0177202b85fc4c2f1ae1a3a01f5a76 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 5 Aug 2015 06:30:48 +0900 Subject: ARM: shmobile: Add silk device tree bindings documentation Add Silk Device tree bindings Documentation, listing it as a supported board. This allows to use checkpatch to validate DTSes referring to the Silk board. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven diff --git a/Documentation/devicetree/bindings/arm/shmobile.txt b/Documentation/devicetree/bindings/arm/shmobile.txt index 2b9cb62..1d70e78e 100644 --- a/Documentation/devicetree/bindings/arm/shmobile.txt +++ b/Documentation/devicetree/bindings/arm/shmobile.txt @@ -55,3 +55,5 @@ Boards: compatible = "renesas,lager", "renesas,r8a7790" - Marzen compatible = "renesas,marzen", "renesas,r8a7779" + - Silk + compatible = "renesas,silk", "renesas,r8a7794"; -- cgit v0.10.2 From 3f37e01852a06faf1d5fed30eaee5cae942fc9d5 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sun, 9 Aug 2015 01:08:21 +0300 Subject: ARM: shmobile: r8a7794: add GPIO clocks Describe the GPIO clocks in the R8A7794 device tree. Based on the original patch by Koji Matsuoka . Signed-off-by: Sergei Shtylyov Acked-by: Geert Uytterhoeven Acked-by: Laurent Pinchart Signed-off-by: Simon Horman diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index 97c8e9a..b6db773 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -749,16 +749,22 @@ mstp9_clks: mstp9_clks@e6150994 { compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe6150994 0 4>, <0 0xe61509a4 0 4>; - clocks = <&cpg_clocks R8A7794_CLK_QSPI>, <&hp_clk>, <&hp_clk>, - <&hp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>; + clocks = <&cp_clk>, <&cp_clk>, <&cp_clk>, <&cp_clk>, + <&cp_clk>, <&cp_clk>, <&cp_clk>, + <&cpg_clocks R8A7794_CLK_QSPI>, <&hp_clk>, <&hp_clk>, + <&hp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>; #clock-cells = <1>; - clock-indices = < - R8A7794_CLK_QSPI_MOD R8A7794_CLK_I2C5 R8A7794_CLK_I2C4 - R8A7794_CLK_I2C3 R8A7794_CLK_I2C2 R8A7794_CLK_I2C1 - R8A7794_CLK_I2C0 - >; + clock-indices = ; clock-output-names = - "qspi_mod", "i2c5", "i2c4", "i2c3", "i2c2", "i2c1", "i2c0"; + "gpio6", "gpio5", "gpio4", "gpio3", "gpio2", + "gpio1", "gpio0", "qspi_mod", + "i2c5", "i2c4", "i2c3", "i2c2", "i2c1", "i2c0"; }; mstp11_clks: mstp11_clks@e615099c { compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; -- cgit v0.10.2 From e8f5de3bea9e01fd1390d64bc915a11df919b3fe Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sun, 9 Aug 2015 01:09:31 +0300 Subject: ARM: shmobile: r8a7794: add GPIO DT support Describe GPIO[0-6] controllers in the R8A7794 device tree. Based on original patch by Hisashi Nakamura . Signed-off-by: Sergei Shtylyov Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index b6db773..e9fab31 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -50,6 +50,97 @@ interrupts = <1 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>; }; + gpio0: gpio@e6050000 { + compatible = "renesas,gpio-r8a7794", "renesas,gpio-rcar"; + reg = <0 0xe6050000 0 0x50>; + interrupts = <0 4 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 0 32>; + #interrupt-cells = <2>; + interrupt-controller; + clocks = <&mstp9_clks R8A7794_CLK_GPIO0>; + power-domains = <&cpg_clocks>; + }; + + gpio1: gpio@e6051000 { + compatible = "renesas,gpio-r8a7794", "renesas,gpio-rcar"; + reg = <0 0xe6051000 0 0x50>; + interrupts = <0 5 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 32 26>; + #interrupt-cells = <2>; + interrupt-controller; + clocks = <&mstp9_clks R8A7794_CLK_GPIO1>; + power-domains = <&cpg_clocks>; + }; + + gpio2: gpio@e6052000 { + compatible = "renesas,gpio-r8a7794", "renesas,gpio-rcar"; + reg = <0 0xe6052000 0 0x50>; + interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 64 32>; + #interrupt-cells = <2>; + interrupt-controller; + clocks = <&mstp9_clks R8A7794_CLK_GPIO2>; + power-domains = <&cpg_clocks>; + }; + + gpio3: gpio@e6053000 { + compatible = "renesas,gpio-r8a7794", "renesas,gpio-rcar"; + reg = <0 0xe6053000 0 0x50>; + interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 96 32>; + #interrupt-cells = <2>; + interrupt-controller; + clocks = <&mstp9_clks R8A7794_CLK_GPIO3>; + power-domains = <&cpg_clocks>; + }; + + gpio4: gpio@e6054000 { + compatible = "renesas,gpio-r8a7794", "renesas,gpio-rcar"; + reg = <0 0xe6054000 0 0x50>; + interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 128 32>; + #interrupt-cells = <2>; + interrupt-controller; + clocks = <&mstp9_clks R8A7794_CLK_GPIO4>; + power-domains = <&cpg_clocks>; + }; + + gpio5: gpio@e6055000 { + compatible = "renesas,gpio-r8a7794", "renesas,gpio-rcar"; + reg = <0 0xe6055000 0 0x50>; + interrupts = <0 9 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 160 28>; + #interrupt-cells = <2>; + interrupt-controller; + clocks = <&mstp9_clks R8A7794_CLK_GPIO5>; + power-domains = <&cpg_clocks>; + }; + + gpio6: gpio@e6055400 { + compatible = "renesas,gpio-r8a7794", "renesas,gpio-rcar"; + reg = <0 0xe6055400 0 0x50>; + interrupts = <0 10 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 192 26>; + #interrupt-cells = <2>; + interrupt-controller; + clocks = <&mstp9_clks R8A7794_CLK_GPIO6>; + power-domains = <&cpg_clocks>; + }; + cmt0: timer@ffca0000 { compatible = "renesas,cmt-48-gen2"; reg = <0 0xffca0000 0 0x1004>; -- cgit v0.10.2 From 740b4a9f07fe73b5ccd2bc3dc365dc359e1a332d Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Tue, 11 Aug 2015 00:59:24 +0300 Subject: ARM: shmobile: r8a7794: add QSPI DT support Define the generic R8A7794 part of the QSPI device node. Based on original patch by Hisashi Nakamura . Signed-off-by: Sergei Shtylyov Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index e9fab31..e0f32ed 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -19,6 +19,10 @@ #address-cells = <2>; #size-cells = <2>; + aliases { + spi0 = &qspi; + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -537,6 +541,20 @@ status = "disabled"; }; + qspi: spi@e6b10000 { + compatible = "renesas,qspi-r8a7794", "renesas,qspi"; + reg = <0 0xe6b10000 0 0x2c>; + interrupts = <0 184 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp9_clks R8A7794_CLK_QSPI_MOD>; + dmas = <&dmac0 0x17>, <&dmac0 0x18>; + dma-names = "tx", "rx"; + power-domains = <&cpg_clocks>; + num-cs = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + clocks { #address-cells = <2>; #size-cells = <2>; -- cgit v0.10.2 From 0ebdbc505b620ab4397c3105d36a5383fb16b151 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Tue, 11 Aug 2015 01:00:35 +0300 Subject: ARM: shmobile: silk: add QSPI DT support Define the SILK board dependent part of the QSPI device node. Add device nodes for Spansion S25FL512S SPI flash and MTD partitions on it. Based on the original patch by Vladimir Barinov . Signed-off-by: Sergei Shtylyov Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/boot/dts/r8a7794-silk.dts b/arch/arm/boot/dts/r8a7794-silk.dts index d4dd5a3..f49bc00 100644 --- a/arch/arm/boot/dts/r8a7794-silk.dts +++ b/arch/arm/boot/dts/r8a7794-silk.dts @@ -65,6 +65,11 @@ renesas,groups = "mmc_data8", "mmc_ctrl"; renesas,function = "mmc"; }; + + qspi_pins: spi0 { + renesas,groups = "qspi_ctrl", "qspi_data4"; + renesas,function = "qspi"; + }; }; &scif2 { @@ -100,3 +105,38 @@ non-removable; status = "okay"; }; + +&qspi { + pinctrl-0 = <&qspi_pins>; + pinctrl-names = "default"; + + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spansion,s25fl512s", "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <30000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + spi-cpol; + spi-cpha; + m25p,fast-read; + + partition@0 { + label = "loader"; + reg = <0x00000000 0x00040000>; + read-only; + }; + partition@40000 { + label = "user"; + reg = <0x00040000 0x00400000>; + read-only; + }; + partition@440000 { + label = "flash"; + reg = <0x00440000 0x03bc0000>; + }; + }; +}; -- cgit v0.10.2 From 8025e3ff4ca972a0ca2aa898562670a767f79889 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 7 Aug 2015 11:45:33 +0900 Subject: ARM: shmobile: marzen: Board specific serial port order Convert Marzen to use board-specific serial0 and serial1 instead of the older shared SoC-specific SCIF index. Signed-off-by: Magnus Damm Acked-by: Geert Uytterhoeven Acked-by: Laurent Pinchart Signed-off-by: Simon Horman diff --git a/arch/arm/boot/dts/r8a7779-marzen.dts b/arch/arm/boot/dts/r8a7779-marzen.dts index 20afea6..fe396c8 100644 --- a/arch/arm/boot/dts/r8a7779-marzen.dts +++ b/arch/arm/boot/dts/r8a7779-marzen.dts @@ -19,12 +19,12 @@ compatible = "renesas,marzen", "renesas,r8a7779"; aliases { - serial2 = &scif2; - serial4 = &scif4; + serial0 = &scif2; + serial1 = &scif4; }; chosen { - bootargs = "console=ttySC2,115200 ignore_loglevel root=/dev/nfs ip=on"; + bootargs = "ignore_loglevel root=/dev/nfs ip=on"; stdout-path = &scif2; }; -- cgit v0.10.2 From 755252d0e502627df6ddabbb2d628705bc256497 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 6 Jul 2015 12:55:32 +0200 Subject: ARM: shmobile: kzm9g dts: Use adxl345-specific compatible property Replace the deprecated generic "adi,adxl34x" compatible value by the adxl345-specific "adi,adxl345" value, cfr. commit e465bf6fc55d5ce2 ("DT: i2c: Deprecate adi,adxl34x compatible string"). Signed-off-by: Geert Uytterhoeven Acked-by: Laurent Pinchart Signed-off-by: Simon Horman diff --git a/arch/arm/boot/dts/sh73a0-kzm9g.dts b/arch/arm/boot/dts/sh73a0-kzm9g.dts index 24b4cd2..7fc5602 100644 --- a/arch/arm/boot/dts/sh73a0-kzm9g.dts +++ b/arch/arm/boot/dts/sh73a0-kzm9g.dts @@ -206,7 +206,7 @@ }; accelerometer@1d { - compatible = "adi,adxl34x"; + compatible = "adi,adxl345"; reg = <0x1d>; interrupt-parent = <&irqpin3>; interrupts = <2 IRQ_TYPE_LEVEL_HIGH>, -- cgit v0.10.2 From 5428521ba123dddda4d2ac9ab19d173b692a8acb Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Thu, 20 Aug 2015 01:00:09 +0300 Subject: ARM: shmobile: r8a7794: add I2C DT support Define the generic R8A7794 parts of the I2C[0-5] device nodes. Based on the original patch by Koji Matsuoka . Signed-off-by: Sergei Shtylyov Signed-off-by: Simon Horman diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index e0f32ed..7384db2 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -20,6 +20,12 @@ #size-cells = <2>; aliases { + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c4; + i2c5 = &i2c5; spi0 = &qspi; }; @@ -502,6 +508,73 @@ status = "disabled"; }; + /* The memory map in the User's Manual maps the cores to bus numbers */ + i2c0: i2c@e6508000 { + compatible = "renesas,i2c-r8a7794"; + reg = <0 0xe6508000 0 0x40>; + interrupts = <0 287 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp9_clks R8A7794_CLK_I2C0>; + power-domains = <&cpg_clocks>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c1: i2c@e6518000 { + compatible = "renesas,i2c-r8a7794"; + reg = <0 0xe6518000 0 0x40>; + interrupts = <0 288 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp9_clks R8A7794_CLK_I2C1>; + power-domains = <&cpg_clocks>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c2: i2c@e6530000 { + compatible = "renesas,i2c-r8a7794"; + reg = <0 0xe6530000 0 0x40>; + interrupts = <0 286 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp9_clks R8A7794_CLK_I2C2>; + power-domains = <&cpg_clocks>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c3: i2c@e6540000 { + compatible = "renesas,i2c-r8a7794"; + reg = <0 0xe6540000 0 0x40>; + interrupts = <0 290 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp9_clks R8A7794_CLK_I2C3>; + power-domains = <&cpg_clocks>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c4: i2c@e6520000 { + compatible = "renesas,i2c-r8a7794"; + reg = <0 0xe6520000 0 0x40>; + interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp9_clks R8A7794_CLK_I2C4>; + power-domains = <&cpg_clocks>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c5: i2c@e6528000 { + compatible = "renesas,i2c-r8a7794"; + reg = <0 0xe6528000 0 0x40>; + interrupts = <0 20 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp9_clks R8A7794_CLK_I2C5>; + power-domains = <&cpg_clocks>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + mmcif0: mmc@ee200000 { compatible = "renesas,mmcif-r8a7794", "renesas,sh-mmcif"; reg = <0 0xee200000 0 0x80>; -- cgit v0.10.2 From fa070791c1e7df91ca07fc7c9a431fac0d7d2832 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Thu, 20 Aug 2015 01:05:02 +0300 Subject: ARM: shmobile: silk: add I2C1 DT support Define the SILK board dependent part of the I2C1 device node. Signed-off-by: Sergei Shtylyov Signed-off-by: Simon Horman diff --git a/arch/arm/boot/dts/r8a7794-silk.dts b/arch/arm/boot/dts/r8a7794-silk.dts index f49bc00..3f80872 100644 --- a/arch/arm/boot/dts/r8a7794-silk.dts +++ b/arch/arm/boot/dts/r8a7794-silk.dts @@ -61,6 +61,11 @@ renesas,function = "intc"; }; + i2c1_pins: i2c1 { + renesas,groups = "i2c1"; + renesas,function = "i2c1"; + }; + mmcif0_pins: mmcif0 { renesas,groups = "mmc_data8", "mmc_ctrl"; renesas,function = "mmc"; @@ -95,6 +100,14 @@ }; }; +&i2c1 { + pinctrl-0 = <&i2c1_pins>; + pinctrl-names = "default"; + + status = "okay"; + clock-frequency = <400000>; +}; + &mmcif0 { pinctrl-0 = <&mmcif0_pins>; pinctrl-names = "default"; -- cgit v0.10.2 From 1afe77ca7846489fff3d1675b82bd2116a56474a Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Thu, 20 Aug 2015 01:22:24 +0300 Subject: ARM: shmobile: r8a7794: add VIN DT support Define the generic R8A7794 part of the VIN[01] device nodes. Add aliases for the VIN[01] device nodes. Signed-off-by: Sergei Shtylyov Signed-off-by: Simon Horman diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index 7384db2..e54f3de 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -27,6 +27,8 @@ i2c4 = &i2c4; i2c5 = &i2c5; spi0 = &qspi; + vin0 = &vin0; + vin1 = &vin1; }; cpus { @@ -628,6 +630,24 @@ status = "disabled"; }; + vin0: video@e6ef0000 { + compatible = "renesas,vin-r8a7794"; + reg = <0 0xe6ef0000 0 0x1000>; + interrupts = <0 188 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp8_clks R8A7794_CLK_VIN0>; + power-domains = <&cpg_clocks>; + status = "disabled"; + }; + + vin1: video@e6ef1000 { + compatible = "renesas,vin-r8a7794"; + reg = <0 0xe6ef1000 0 0x1000>; + interrupts = <0 189 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp8_clks R8A7794_CLK_VIN1>; + power-domains = <&cpg_clocks>; + status = "disabled"; + }; + clocks { #address-cells = <2>; #size-cells = <2>; -- cgit v0.10.2 From 8614daf299cbab2bcada922e727fdc9ad45b2412 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Thu, 20 Aug 2015 01:24:47 +0300 Subject: ARM: shmobile: silk: add VIN0/ADV7180 DT support Define the SILK board dependent part of the VIN0 device node. Add the device node for Analog Devices ADV7180 video decoder to I2C1 bus. Add the necessary subnodes to interconnect VIN0 and ADV7180 devices. Based on the Henninger VIN0/ADV8170 device tree patch by myself. Signed-off-by: Sergei Shtylyov Signed-off-by: Simon Horman diff --git a/arch/arm/boot/dts/r8a7794-silk.dts b/arch/arm/boot/dts/r8a7794-silk.dts index 3f80872..bb0a224 100644 --- a/arch/arm/boot/dts/r8a7794-silk.dts +++ b/arch/arm/boot/dts/r8a7794-silk.dts @@ -75,6 +75,11 @@ renesas,groups = "qspi_ctrl", "qspi_data4"; renesas,function = "qspi"; }; + + vin0_pins: vin0 { + renesas,groups = "vin0_data8", "vin0_clk"; + renesas,function = "vin0"; + }; }; &scif2 { @@ -106,6 +111,19 @@ status = "okay"; clock-frequency = <400000>; + + composite-in@20 { + compatible = "adi,adv7180"; + reg = <0x20>; + remote = <&vin0>; + + port { + adv7180: endpoint { + bus-width = <8>; + remote-endpoint = <&vin0ep>; + }; + }; + }; }; &mmcif0 { @@ -153,3 +171,20 @@ }; }; }; + +/* composite video input */ +&vin0 { + status = "okay"; + pinctrl-0 = <&vin0_pins>; + pinctrl-names = "default"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + vin0ep: endpoint { + remote-endpoint = <&adv7180>; + bus-width = <8>; + }; + }; +}; -- cgit v0.10.2 From c19c84ff3ab1280894bb2cdd99027f751922e2ba Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 20 Aug 2015 03:09:30 +0000 Subject: ARM: shmobile: koelsch: use CCF for audio clock Because of historical reason, audio clock didn't use CCF. Let's use it now. Signed-off-by: Kuninori Morimoto Signed-off-by: Simon Horman diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts index dc15884..fc44ea3 100644 --- a/arch/arm/boot/dts/r8a7791-koelsch.dts +++ b/arch/arm/boot/dts/r8a7791-koelsch.dts @@ -242,6 +242,13 @@ 1800000 0>; }; + audio_clock: clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <11289600>; + clock-output-names = "audio_clock"; + }; + rsnd_ak4643: sound { compatible = "simple-audio-card"; @@ -255,7 +262,7 @@ sndcodec: simple-audio-card,codec { sound-dai = <&ak4643>; - system-clock-frequency = <11289600>; + clocks = <&audio_clock>; }; }; -- cgit v0.10.2 From 6bc651afec2dba4d3e40901a2c5cfc88ad35d97a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 20 Aug 2015 03:09:52 +0000 Subject: ARM: shmobile: lager: use CCF for audio clock Because of historical reason, audio clock didn't use CCF. Let's use it now. Signed-off-by: Kuninori Morimoto Signed-off-by: Simon Horman diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts index 37dec52..6f5d7f5 100644 --- a/arch/arm/boot/dts/r8a7790-lager.dts +++ b/arch/arm/boot/dts/r8a7790-lager.dts @@ -174,6 +174,13 @@ 1800000 0>; }; + audio_clock: clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <11289600>; + clock-output-names = "audio_clock"; + }; + rsnd_ak4643: sound { compatible = "simple-audio-card"; @@ -187,7 +194,7 @@ sndcodec: simple-audio-card,codec { sound-dai = <&ak4643>; - system-clock-frequency = <11289600>; + clocks = <&audio_clock>; }; }; -- cgit v0.10.2 From 4bc4a2051abe12e6e7521cbabac0048096243094 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 24 Aug 2015 08:27:56 +0000 Subject: ARM: shmobile: r8a7790: tidyup SSI resource region Signed-off-by: Kuninori Morimoto Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index a0b2a79..ae5eb28 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -1599,7 +1599,7 @@ reg = <0 0xec500000 0 0x1000>, /* SCU */ <0 0xec5a0000 0 0x100>, /* ADG */ <0 0xec540000 0 0x1000>, /* SSIU */ - <0 0xec541000 0 0x1280>, /* SSI */ + <0 0xec541000 0 0x280>, /* SSI */ <0 0xec740000 0 0x200>; /* Audio DMAC peri peri*/ reg-names = "scu", "adg", "ssiu", "ssi", "audmapp"; -- cgit v0.10.2 From 8c3f903bd362328aac997aba1adfea59e337918a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 24 Aug 2015 08:28:17 +0000 Subject: ARM: shmobile: r8a7791: tidyup SSI resource region Signed-off-by: Kuninori Morimoto Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index 831525d..3b8e26d 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -1649,7 +1649,7 @@ reg = <0 0xec500000 0 0x1000>, /* SCU */ <0 0xec5a0000 0 0x100>, /* ADG */ <0 0xec540000 0 0x1000>, /* SSIU */ - <0 0xec541000 0 0x1280>, /* SSI */ + <0 0xec541000 0 0x280>, /* SSI */ <0 0xec740000 0 0x200>; /* Audio DMAC peri peri*/ reg-names = "scu", "adg", "ssiu", "ssi", "audmapp"; -- cgit v0.10.2 From 23640ff2eff0dec2016dd097b1b04c817a4ffd3f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 25 Aug 2015 07:14:50 +0000 Subject: ARM: shmobile: r8a7778: tidyup SSI resource region Signed-off-by: Kuninori Morimoto Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman diff --git a/arch/arm/boot/dts/r8a7778.dtsi b/arch/arm/boot/dts/r8a7778.dtsi index 4b1fa9f..4f8e078 100644 --- a/arch/arm/boot/dts/r8a7778.dtsi +++ b/arch/arm/boot/dts/r8a7778.dtsi @@ -239,7 +239,7 @@ #sound-dai-cells = <1>; compatible = "renesas,rcar_sound-r8a7778", "renesas,rcar_sound-gen1"; reg = <0xffd90000 0x1000>, /* SRU */ - <0xffd91000 0x1240>, /* SSI */ + <0xffd91000 0x240>, /* SSI */ <0xfffe0000 0x24>; /* ADG */ clocks = <&mstp3_clks R8A7778_CLK_SSI8>, <&mstp3_clks R8A7778_CLK_SSI7>, -- cgit v0.10.2 From 535118cac9e0705bf58de0604060f644bee7472d Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 9 Sep 2015 19:48:19 +0200 Subject: ARM: shmobile: r8a7790: lager: add pinmux for iic0 It seems we used to rely on the default pinmux setting of this HW, but currently we need to explicitly set the pinmux to access this bus. It is better style, too. Signed-off-by: Wolfram Sang Signed-off-by: Simon Horman diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts index 6f5d7f5..c553abd 100644 --- a/arch/arm/boot/dts/r8a7790-lager.dts +++ b/arch/arm/boot/dts/r8a7790-lager.dts @@ -342,6 +342,11 @@ renesas,function = "msiof1"; }; + iic0_pins: iic0 { + renesas,groups = "iic0"; + renesas,function = "iic0"; + }; + iic1_pins: iic1 { renesas,groups = "iic1"; renesas,function = "iic1"; @@ -517,6 +522,8 @@ &iic0 { status = "okay"; + pinctrl-0 = <&iic0_pins>; + pinctrl-names = "default"; }; &iic1 { -- cgit v0.10.2 From 44522d852f1979ec0e6807eb4dc58bd7ecc8af08 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 27 Aug 2015 15:44:02 +0200 Subject: drm/i915: Set csc coefficients in update_pipe_size. This might not have been set during boot, and when we preserve the initial mode this can result in a black screen. Cc: Daniel Stone Signed-off-by: Maarten Lankhorst Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 62573d5..1904919 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3274,6 +3274,9 @@ static void intel_update_pipe_size(struct intel_crtc *crtc) if (!i915.fastboot) return; + if (HAS_DDI(dev)) + intel_set_pipe_csc(&crtc->base); + /* * Update pipe size and adjust fitter if needed: the reason for this is * that in compute_mode_changes we check the native mode (not the pfit -- cgit v0.10.2 From d551599181769571f4f68dd93e5d8b15868889af Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 27 Aug 2015 15:44:03 +0200 Subject: drm/i915: Remove references to crtc->active from intel_fbdev.c It should really use the atomic state. Signed-off-by: Maarten Lankhorst Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 96476d7..0c9291d 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -550,7 +550,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev, intel_fb_obj(crtc->primary->state->fb); intel_crtc = to_intel_crtc(crtc); - if (!intel_crtc->active || !obj) { + if (!crtc->state->active || !obj) { DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n", pipe_name(intel_crtc->pipe)); continue; @@ -575,7 +575,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev, intel_crtc = to_intel_crtc(crtc); - if (!intel_crtc->active) { + if (!crtc->state->active) { DRM_DEBUG_KMS("pipe %c not active, skipping\n", pipe_name(intel_crtc->pipe)); continue; @@ -638,7 +638,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev, for_each_crtc(dev, crtc) { intel_crtc = to_intel_crtc(crtc); - if (!intel_crtc->active) + if (!crtc->state->active) continue; WARN(!crtc->primary->fb, -- cgit v0.10.2 From f4502c25ebd04691f284fdafff4a5613299c36dc Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 27 Aug 2015 15:44:04 +0200 Subject: drm/i915: Always try to inherit the initial fb. The initial state is read out correctly and the state is atomic, so it's safe to preserve the fb without any hacks if it's suitable. Signed-off-by: Maarten Lankhorst Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 0c9291d..73a14e8 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -541,9 +541,6 @@ static bool intel_fbdev_init_bios(struct drm_device *dev, struct intel_crtc *intel_crtc; unsigned int max_size = 0; - if (!i915.fastboot) - return false; - /* Find the largest fb */ for_each_crtc(dev, crtc) { struct drm_i915_gem_object *obj = -- cgit v0.10.2 From bfd16b2a23dc99f2af3f5c4f54aa153347f2dc3c Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 27 Aug 2015 15:44:05 +0200 Subject: drm/i915: Make updating pipe without modeset atomic. Instead of doing a hack during primary plane commit the state is updated during atomic evasion. It handles differences in pipe size and the panel fitter. This is continuing on top of Daniel's work to make faster modesets atomic, and not yet enabled by default. Signed-off-by: Maarten Lankhorst Reviewed-by: Jesse Barnes [danvet: - simplify/future-proof if ladder that Jesse spotted - resolve conflict in pipe_config_check and don't spuriously move the code.] Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 2c4b1c4..f1975f2 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -93,6 +93,8 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc) __drm_atomic_helper_crtc_duplicate_state(crtc, &crtc_state->base); + crtc_state->update_pipe = false; + return &crtc_state->base; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1904919..1691ec2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -112,6 +112,9 @@ static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_cr struct intel_crtc_state *crtc_state); static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state, int num_connectors); +static void skylake_pfit_enable(struct intel_crtc *crtc); +static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force); +static void ironlake_pfit_enable(struct intel_crtc *crtc); static void intel_modeset_setup_hw_state(struct drm_device *dev); typedef struct { @@ -3265,14 +3268,20 @@ static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc) return pending; } -static void intel_update_pipe_size(struct intel_crtc *crtc) +static void intel_update_pipe_config(struct intel_crtc *crtc, + struct intel_crtc_state *old_crtc_state) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - const struct drm_display_mode *adjusted_mode; + struct intel_crtc_state *pipe_config = + to_intel_crtc_state(crtc->base.state); - if (!i915.fastboot) - return; + /* drm_atomic_helper_update_legacy_modeset_state might not be called. */ + crtc->base.mode = crtc->base.state->mode; + + DRM_DEBUG_KMS("Updating pipe size %ix%i -> %ix%i\n", + old_crtc_state->pipe_src_w, old_crtc_state->pipe_src_h, + pipe_config->pipe_src_w, pipe_config->pipe_src_h); if (HAS_DDI(dev)) intel_set_pipe_csc(&crtc->base); @@ -3284,27 +3293,24 @@ static void intel_update_pipe_size(struct intel_crtc *crtc) * fastboot case, we'll flip, but if we don't update the pipesrc and * pfit state, we'll end up with a big fb scanned out into the wrong * sized surface. - * - * To fix this properly, we need to hoist the checks up into - * compute_mode_changes (or above), check the actual pfit state and - * whether the platform allows pfit disable with pipe active, and only - * then update the pipesrc and pfit state, even on the flip path. */ - adjusted_mode = &crtc->config->base.adjusted_mode; - I915_WRITE(PIPESRC(crtc->pipe), - ((adjusted_mode->crtc_hdisplay - 1) << 16) | - (adjusted_mode->crtc_vdisplay - 1)); - if (!crtc->config->pch_pfit.enabled && - (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) || - intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) { - I915_WRITE(PF_CTL(crtc->pipe), 0); - I915_WRITE(PF_WIN_POS(crtc->pipe), 0); - I915_WRITE(PF_WIN_SZ(crtc->pipe), 0); + ((pipe_config->pipe_src_w - 1) << 16) | + (pipe_config->pipe_src_h - 1)); + + /* on skylake this is done by detaching scalers */ + if (INTEL_INFO(dev)->gen >= 9) { + skl_detach_scalers(crtc); + + if (pipe_config->pch_pfit.enabled) + skylake_pfit_enable(crtc); + } else if (HAS_PCH_SPLIT(dev)) { + if (pipe_config->pch_pfit.enabled) + ironlake_pfit_enable(crtc); + else if (old_crtc_state->pch_pfit.enabled) + ironlake_pfit_disable(crtc, true); } - crtc->config->pipe_src_w = adjusted_mode->crtc_hdisplay; - crtc->config->pipe_src_h = adjusted_mode->crtc_vdisplay; } static void intel_fdi_normal_train(struct drm_crtc *crtc) @@ -4961,7 +4967,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) } } -static void ironlake_pfit_disable(struct intel_crtc *crtc) +static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -4969,7 +4975,7 @@ static void ironlake_pfit_disable(struct intel_crtc *crtc) /* To avoid upsetting the power well on haswell only disable the pfit if * it's in use. The hw state code will make sure we get this right. */ - if (crtc->config->pch_pfit.enabled) { + if (force || crtc->config->pch_pfit.enabled) { I915_WRITE(PF_CTL(pipe), 0); I915_WRITE(PF_WIN_POS(pipe), 0); I915_WRITE(PF_WIN_SZ(pipe), 0); @@ -4996,7 +5002,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) intel_disable_pipe(intel_crtc); - ironlake_pfit_disable(intel_crtc); + ironlake_pfit_disable(intel_crtc, false); if (intel_crtc->config->has_pch_encoder) ironlake_fdi_disable(crtc); @@ -5059,7 +5065,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) if (INTEL_INFO(dev)->gen >= 9) skylake_scaler_disable(intel_crtc); else - ironlake_pfit_disable(intel_crtc); + ironlake_pfit_disable(intel_crtc, false); intel_ddi_disable_pipe_clock(intel_crtc); @@ -12218,7 +12224,6 @@ static bool intel_fuzzy_clock_check(int clock1, int clock2) base.head) \ if (mask & (1 <<(intel_crtc)->pipe)) - static bool intel_compare_m_n(unsigned int m, unsigned int n, unsigned int m2, unsigned int n2, @@ -12439,19 +12444,21 @@ intel_pipe_config_compare(struct drm_device *dev, DRM_MODE_FLAG_NVSYNC); } - PIPE_CONF_CHECK_I(pipe_src_w); - PIPE_CONF_CHECK_I(pipe_src_h); - PIPE_CONF_CHECK_X(gmch_pfit.control); /* pfit ratios are autocomputed by the hw on gen4+ */ if (INTEL_INFO(dev)->gen < 4) PIPE_CONF_CHECK_I(gmch_pfit.pgm_ratios); PIPE_CONF_CHECK_X(gmch_pfit.lvds_border_bits); - PIPE_CONF_CHECK_I(pch_pfit.enabled); - if (current_config->pch_pfit.enabled) { - PIPE_CONF_CHECK_X(pch_pfit.pos); - PIPE_CONF_CHECK_X(pch_pfit.size); + if (!adjust) { + PIPE_CONF_CHECK_I(pipe_src_w); + PIPE_CONF_CHECK_I(pipe_src_h); + + PIPE_CONF_CHECK_I(pch_pfit.enabled); + if (current_config->pch_pfit.enabled) { + PIPE_CONF_CHECK_X(pch_pfit.pos); + PIPE_CONF_CHECK_X(pch_pfit.size); + } } PIPE_CONF_CHECK_I(scaler_state.scaler_id); @@ -12616,7 +12623,8 @@ check_crtc_state(struct drm_device *dev, struct drm_atomic_state *old_state) struct intel_crtc_state *pipe_config, *sw_config; bool active; - if (!needs_modeset(crtc->state)) + if (!needs_modeset(crtc->state) && + !to_intel_crtc_state(crtc->state)->update_pipe) continue; __drm_atomic_helper_crtc_destroy_state(crtc, old_crtc_state); @@ -12912,7 +12920,6 @@ static int intel_modeset_all_pipes(struct drm_atomic_state *state) return ret; } - static int intel_modeset_checks(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; @@ -13003,6 +13010,7 @@ static int intel_atomic_check(struct drm_device *dev, to_intel_crtc_state(crtc->state), pipe_config, true)) { crtc_state->mode_changed = false; + to_intel_crtc_state(crtc_state)->update_pipe = true; } if (needs_modeset(crtc_state)) { @@ -13100,16 +13108,30 @@ static int intel_atomic_commit(struct drm_device *dev, for_each_crtc_in_state(state, crtc, crtc_state, i) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); bool modeset = needs_modeset(crtc->state); + bool update_pipe = !modeset && + to_intel_crtc_state(crtc->state)->update_pipe; + unsigned long put_domains = 0; if (modeset && crtc->state->active) { update_scanline_offset(to_intel_crtc(crtc)); dev_priv->display.crtc_enable(crtc); } + if (update_pipe) { + put_domains = modeset_get_crtc_power_domains(crtc); + + /* make sure intel_modeset_check_state runs */ + any_ms = true; + } + if (!modeset) intel_pre_plane_update(intel_crtc); drm_atomic_helper_commit_planes_on_crtc(crtc_state); + + if (put_domains) + modeset_put_power_domains(dev_priv, put_domains); + intel_post_plane_update(intel_crtc); } @@ -13426,10 +13448,6 @@ intel_commit_primary_plane(struct drm_plane *plane, if (!crtc->state->active) return; - if (state->visible) - /* FIXME: kill this fastboot hack */ - intel_update_pipe_size(intel_crtc); - dev_priv->display.update_primary_plane(crtc, fb, state->src.x1 >> 16, state->src.y1 >> 16); @@ -13450,6 +13468,9 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc_state *old_intel_state = + to_intel_crtc_state(old_crtc_state); + bool modeset = needs_modeset(crtc->state); if (intel_crtc->atomic.update_wm_pre) intel_update_watermarks(crtc); @@ -13458,7 +13479,12 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc, if (crtc->state->active) intel_pipe_update_start(intel_crtc); - if (!needs_modeset(crtc->state) && INTEL_INFO(dev)->gen >= 9) + if (modeset) + return; + + if (to_intel_crtc_state(crtc->state)->update_pipe) + intel_update_pipe_config(intel_crtc, old_intel_state); + else if (INTEL_INFO(dev)->gen >= 9) skl_detach_scalers(intel_crtc); } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 129d99e..e9e5cfd 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -338,6 +338,8 @@ struct intel_crtc_state { #define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS (1<<0) /* unreliable sync mode.flags */ unsigned long quirks; + bool update_pipe; + /* Pipe source size (ie. panel fitter input size) * All planes will be positioned inside this space, * and get clipped at the edges. */ -- cgit v0.10.2 From 6764e9f8724f1231b4deac53b9a82286ac0830e7 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 27 Aug 2015 15:44:06 +0200 Subject: drm/i915: skip modeset if compatible for everyone. This is done as a separate commit, to make it easier to revert when things break. Signed-off-by: Maarten Lankhorst Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index da0f264..2994ce5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2644,7 +2644,6 @@ struct i915_params { int enable_cmd_parser; /* leave bools at the end to not create holes */ bool enable_hangcheck; - bool fastboot; bool prefault_disable; bool load_detect_test; bool reset; diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 05053e2..ca060d5 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -40,7 +40,6 @@ struct i915_params i915 __read_mostly = { .preliminary_hw_support = IS_ENABLED(CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT), .disable_power_well = 1, .enable_ips = 1, - .fastboot = 0, .prefault_disable = 0, .load_detect_test = 0, .reset = true, @@ -133,10 +132,6 @@ MODULE_PARM_DESC(disable_power_well, module_param_named(enable_ips, i915.enable_ips, int, 0600); MODULE_PARM_DESC(enable_ips, "Enable IPS (default: true)"); -module_param_named(fastboot, i915.fastboot, bool, 0600); -MODULE_PARM_DESC(fastboot, - "Try to skip unnecessary mode sets at boot time (default: false)"); - module_param_named_unsafe(prefault_disable, i915.prefault_disable, bool, 0600); MODULE_PARM_DESC(prefault_disable, "Disable page prefaulting for pread/pwrite/reloc (default:false). " diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1691ec2..a001cbb 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13005,8 +13005,7 @@ static int intel_atomic_check(struct drm_device *dev, if (ret) return ret; - if (i915.fastboot && - intel_pipe_config_compare(state->dev, + if (intel_pipe_config_compare(state->dev, to_intel_crtc_state(crtc->state), pipe_config, true)) { crtc_state->mode_changed = false; -- cgit v0.10.2 From ec72d5884c6a3cf4f27b52da51654a472b919545 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Fri, 4 Sep 2015 12:59:14 +0100 Subject: drm/i915: WaEnableForceRestoreInCtxtDescForVCS is for video engines only Also check for correct revision id in each Gen9 platform (SKL until B0 and BXT until A0). Cc: Nick Hoath Signed-off-by: Michel Thierry Reviewed-by: Arun Siluvery Tested-by: Daniele Ceraolo Spurio Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 28a712e..d8b605f 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -301,10 +301,10 @@ uint64_t intel_lr_context_descriptor(struct intel_context *ctx, /* desc |= GEN8_CTX_FORCE_RESTORE; */ /* WaEnableForceRestoreInCtxtDescForVCS:skl */ - if (IS_GEN9(dev) && - INTEL_REVID(dev) <= SKL_REVID_B0 && - (ring->id == BCS || ring->id == VCS || - ring->id == VECS || ring->id == VCS2)) + /* WaEnableForceRestoreInCtxtDescForVCS:bxt */ + if (((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0) || + (IS_BROXTON(dev) && INTEL_REVID(dev) == BXT_REVID_A0)) && + (ring->id == VCS || ring->id == VCS2)) desc |= GEN8_CTX_FORCE_RESTORE; return desc; -- cgit v0.10.2 From 5af05fefb5be51d42effc4f802b6d806fbda34eb Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Fri, 4 Sep 2015 12:59:15 +0100 Subject: drm/i915/lrc: Prevent preemption when lite-restore is disabled When WaEnableForceRestoreInCtxtDescForVCS is required, it is only safe to send new contexts if the last reported event is "active to idle". Otherwise the same context can fully preempt itself because lite-restore is disabled. Testcase: igt/gem_concurrent_blit Reported-by: Daniele Ceraolo Spurio Signed-off-by: Michel Thierry Reviewed-by: Arun Siluvery Tested-by: Daniele Ceraolo Spurio Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index d8b605f..c3fca4b 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -277,10 +277,18 @@ u32 intel_execlists_ctx_id(struct drm_i915_gem_object *ctx_obj) return lrca >> 12; } +static bool disable_lite_restore_wa(struct intel_engine_cs *ring) +{ + struct drm_device *dev = ring->dev; + + return ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0) || + (IS_BROXTON(dev) && INTEL_REVID(dev) == BXT_REVID_A0)) && + (ring->id == VCS || ring->id == VCS2); +} + uint64_t intel_lr_context_descriptor(struct intel_context *ctx, struct intel_engine_cs *ring) { - struct drm_device *dev = ring->dev; struct drm_i915_gem_object *ctx_obj = ctx->engine[ring->id].state; uint64_t desc; uint64_t lrca = i915_gem_obj_ggtt_offset(ctx_obj) + @@ -302,9 +310,7 @@ uint64_t intel_lr_context_descriptor(struct intel_context *ctx, /* WaEnableForceRestoreInCtxtDescForVCS:skl */ /* WaEnableForceRestoreInCtxtDescForVCS:bxt */ - if (((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0) || - (IS_BROXTON(dev) && INTEL_REVID(dev) == BXT_REVID_A0)) && - (ring->id == VCS || ring->id == VCS2)) + if (disable_lite_restore_wa(ring)) desc |= GEN8_CTX_FORCE_RESTORE; return desc; @@ -495,7 +501,7 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring) u32 status_pointer; u8 read_pointer; u8 write_pointer; - u32 status; + u32 status = 0; u32 status_id; u32 submit_contexts = 0; @@ -533,8 +539,14 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring) } } - if (submit_contexts != 0) + if (disable_lite_restore_wa(ring)) { + /* Prevent a ctx to preempt itself */ + if ((status & GEN8_CTX_STATUS_ACTIVE_IDLE) && + (submit_contexts != 0)) + execlists_context_unqueue(ring); + } else if (submit_contexts != 0) { execlists_context_unqueue(ring); + } spin_unlock(&ring->execlist_lock); -- cgit v0.10.2 From e2ec35a58b3c9cdadbb7d913e8262ad9ddcb00f7 Mon Sep 17 00:00:00 2001 From: Sonika Jindal Date: Fri, 11 Sep 2015 16:58:32 +0530 Subject: drm/i915/bxt: Use intel_encoder->hpd_pin to check live status Using intel_encoder's hpd_pin to check the live status because of BXT A0/A1 WA for HPD pins and hpd_pin contains the updated pin for the corresponding port. Signed-off-by: Sonika Jindal Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 45ab25e..b8c4fc5 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4637,11 +4637,14 @@ static bool vlv_digital_port_connected(struct drm_i915_private *dev_priv, } static bool bxt_digital_port_connected(struct drm_i915_private *dev_priv, - struct intel_digital_port *port) + struct intel_digital_port *intel_dig_port) { + struct intel_encoder *intel_encoder = &intel_dig_port->base; + enum port port; u32 bit; - switch (port->port) { + intel_hpd_pin_to_port(intel_encoder->hpd_pin, &port); + switch (port) { case PORT_A: bit = BXT_DE_PORT_HP_DDIA; break; @@ -4652,7 +4655,7 @@ static bool bxt_digital_port_connected(struct drm_i915_private *dev_priv, bit = BXT_DE_PORT_HP_DDIC; break; default: - MISSING_CASE(port->port); + MISSING_CASE(port); return false; } -- cgit v0.10.2 From 8c761609ec3beca88819e28d4fcf333b579d29b4 Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Tue, 8 Sep 2015 10:31:48 +0100 Subject: drm/i915/gen9: Add WaDisableSamplerPowerBypassForSOPingPong Signed-off-by: Arun Siluvery Reviewed-by: Sagar Arun Kamble Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 20a75bb..684e069 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -983,6 +983,13 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring) tmp |= HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE; WA_SET_BIT_MASKED(HDC_CHICKEN0, tmp); + /* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt */ + if (IS_SKYLAKE(dev) || + (IS_BROXTON(dev) && INTEL_REVID(dev) <= BXT_REVID_B0)) { + WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, + GEN8_SAMPLER_POWER_BYPASS_DIS); + } + return 0; } -- cgit v0.10.2 From 5b88abacd4820c66bc347a6beeb3d6ad1144544b Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Tue, 8 Sep 2015 10:31:49 +0100 Subject: drm/i915/bxt: Add WaSetClckGatingDisableMedia Signed-off-by: Arun Siluvery Reviewed-by: Sagar Arun Kamble Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 65b5682..495ac17 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6897,6 +6897,7 @@ enum skl_disp_power_wells { #define GEN7_DOP_CLOCK_GATE_ENABLE (1<<0) #define GEN8_DOP_CLOCK_GATE_CFCLK_ENABLE (1<<2) #define GEN8_DOP_CLOCK_GATE_GUC_ENABLE (1<<4) +#define GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE (1<<6) #define GEN8_GARBCNTL 0xB004 #define GEN9_GAPS_TSV_CREDIT_DISABLE (1<<7) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 64bc77e..920872a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -134,6 +134,12 @@ static void bxt_init_clock_gating(struct drm_device *dev) */ I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF); } + + /* WaSetClckGatingDisableMedia:bxt */ + if (INTEL_REVID(dev) == BXT_REVID_A0) { + I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) & + ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE)); + } } static void i915_pineview_get_mem_freq(struct drm_device *dev) -- cgit v0.10.2 From b970b48685a7ae2953e659f7e657cde2949b12ae Mon Sep 17 00:00:00 2001 From: Nick Hoath Date: Tue, 8 Sep 2015 10:31:53 +0100 Subject: drm/i915/gen9: Add WaDisableMinuteIaClockGating Signed-off-by: Nick Hoath Signed-off-by: Arun Siluvery Reviewed-by: Sagar Arun Kamble Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 5eafd31..e0601cc 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -330,6 +330,13 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv) /* Enable MIA caching. GuC clock gating is disabled. */ I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE); + /* WaDisableMinuteIaClockGating:skl,bxt */ + if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0) || + (IS_BROXTON(dev) && INTEL_REVID(dev) == BXT_REVID_A0)) { + I915_WRITE(GUC_SHIM_CONTROL, (I915_READ(GUC_SHIM_CONTROL) & + ~GUC_ENABLE_MIA_CLOCK_GATING)); + } + /* WaC6DisallowByGfxPause*/ I915_WRITE(GEN6_GFXPAUSE, 0x30FFF); -- cgit v0.10.2 From 6ff8ab0d0fab914755cb79b1e0469dd7123cc471 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 10 Sep 2015 08:20:28 -0700 Subject: drm/i915: make CSR firmware messages less verbose Use WARN_ONCE in a bunch of places and demote a message that would continually spam us. Signed-off-by: Jesse Barnes Acked-by: Damien Lespiau Acked-by: Chris Wilson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index ba1ae03..765dfcd 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -454,10 +454,10 @@ void intel_csr_ucode_fini(struct drm_device *dev) void assert_csr_loaded(struct drm_i915_private *dev_priv) { - WARN(intel_csr_load_status_get(dev_priv) != FW_LOADED, - "CSR is not loaded.\n"); - WARN(!I915_READ(CSR_PROGRAM_BASE), - "CSR program storage start is NULL\n"); - WARN(!I915_READ(CSR_SSP_BASE), "CSR SSP Base Not fine\n"); - WARN(!I915_READ(CSR_HTP_SKL), "CSR HTP Not fine\n"); + WARN_ONCE(intel_csr_load_status_get(dev_priv) != FW_LOADED, + "CSR is not loaded.\n"); + WARN_ONCE(!I915_READ(CSR_PROGRAM_BASE), + "CSR program storage start is NULL\n"); + WARN_ONCE(!I915_READ(CSR_SSP_BASE), "CSR SSP Base Not fine\n"); + WARN_ONCE(!I915_READ(CSR_HTP_SKL), "CSR HTP Not fine\n"); } diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 3f682a1..85c35fd 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -463,14 +463,14 @@ static void assert_can_enable_dc5(struct drm_i915_private *dev_priv) bool pg2_enabled = intel_display_power_well_is_enabled(dev_priv, SKL_DISP_PW_2); - WARN(!IS_SKYLAKE(dev), "Platform doesn't support DC5.\n"); - WARN(!HAS_RUNTIME_PM(dev), "Runtime PM not enabled.\n"); - WARN(pg2_enabled, "PG2 not disabled to enable DC5.\n"); + WARN_ONCE(!IS_SKYLAKE(dev), "Platform doesn't support DC5.\n"); + WARN_ONCE(!HAS_RUNTIME_PM(dev), "Runtime PM not enabled.\n"); + WARN_ONCE(pg2_enabled, "PG2 not disabled to enable DC5.\n"); - WARN((I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5), - "DC5 already programmed to be enabled.\n"); - WARN(dev_priv->pm.suspended, - "DC5 cannot be enabled, if platform is runtime-suspended.\n"); + WARN_ONCE((I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5), + "DC5 already programmed to be enabled.\n"); + WARN_ONCE(dev_priv->pm.suspended, + "DC5 cannot be enabled, if platform is runtime-suspended.\n"); assert_csr_loaded(dev_priv); } @@ -486,8 +486,8 @@ static void assert_can_disable_dc5(struct drm_i915_private *dev_priv) if (dev_priv->power_domains.initializing) return; - WARN(!pg2_enabled, "PG2 not enabled to disable DC5.\n"); - WARN(dev_priv->pm.suspended, + WARN_ONCE(!pg2_enabled, "PG2 not enabled to disable DC5.\n"); + WARN_ONCE(dev_priv->pm.suspended, "Disabling of DC5 while platform is runtime-suspended should never happen.\n"); } @@ -526,12 +526,12 @@ static void assert_can_enable_dc6(struct drm_i915_private *dev_priv) { struct drm_device *dev = dev_priv->dev; - WARN(!IS_SKYLAKE(dev), "Platform doesn't support DC6.\n"); - WARN(!HAS_RUNTIME_PM(dev), "Runtime PM not enabled.\n"); - WARN(I915_READ(UTIL_PIN_CTL) & UTIL_PIN_ENABLE, - "Backlight is not disabled.\n"); - WARN((I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC6), - "DC6 already programmed to be enabled.\n"); + WARN_ONCE(!IS_SKYLAKE(dev), "Platform doesn't support DC6.\n"); + WARN_ONCE(!HAS_RUNTIME_PM(dev), "Runtime PM not enabled.\n"); + WARN_ONCE(I915_READ(UTIL_PIN_CTL) & UTIL_PIN_ENABLE, + "Backlight is not disabled.\n"); + WARN_ONCE((I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC6), + "DC6 already programmed to be enabled.\n"); assert_csr_loaded(dev_priv); } @@ -546,8 +546,8 @@ static void assert_can_disable_dc6(struct drm_i915_private *dev_priv) return; assert_csr_loaded(dev_priv); - WARN(!(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC6), - "DC6 already programmed to be disabled.\n"); + WARN_ONCE(!(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC6), + "DC6 already programmed to be disabled.\n"); } static void skl_enable_dc6(struct drm_i915_private *dev_priv) @@ -670,7 +670,7 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv, wait_for((state = intel_csr_load_status_get(dev_priv)) != FW_UNINITIALIZED, 1000); if (state != FW_LOADED) - DRM_ERROR("CSR firmware not ready (%d)\n", + DRM_DEBUG("CSR firmware not ready (%d)\n", state); else if (SKL_ENABLE_DC6(dev)) -- cgit v0.10.2 From 87bcdd2e275d75e374434a4ad7da66bbb6da1d17 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 10 Sep 2015 14:55:00 -0700 Subject: drm/i915: don't try to load GuC fw on pre-gen9 This avoids some bad register writes and generally feels more correct than unconditionally trying to redirect interrupts and such. References: https://bugs.freedesktop.org/show_bug.cgi?id=91777 Signed-off-by: Jesse Barnes Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 760cfba..acb1f23 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4687,19 +4687,22 @@ i915_gem_init_hw(struct drm_device *dev) } /* We can't enable contexts until all firmware is loaded */ - ret = intel_guc_ucode_load(dev); - if (ret) { - /* - * If we got an error and GuC submission is enabled, map - * the error to -EIO so the GPU will be declared wedged. - * OTOH, if we didn't intend to use the GuC anyway, just - * discard the error and carry on. - */ - DRM_ERROR("Failed to initialize GuC, error %d%s\n", ret, - i915.enable_guc_submission ? "" : " (ignored)"); - ret = i915.enable_guc_submission ? -EIO : 0; - if (ret) - goto out; + if (HAS_GUC_UCODE(dev)) { + ret = intel_guc_ucode_load(dev); + if (ret) { + /* + * If we got an error and GuC submission is enabled, map + * the error to -EIO so the GPU will be declared wedged. + * OTOH, if we didn't intend to use the GuC anyway, just + * discard the error and carry on. + */ + DRM_ERROR("Failed to initialize GuC, error %d%s\n", ret, + i915.enable_guc_submission ? "" : + " (ignored)"); + ret = i915.enable_guc_submission ? -EIO : 0; + if (ret) + goto out; + } } /* Now it is safe to go back round and do everything else: */ -- cgit v0.10.2 From e84fe80337dc85cca07d0417ea97edbec4789d8b Mon Sep 17 00:00:00 2001 From: Nick Hoath Date: Fri, 11 Sep 2015 12:53:46 +0100 Subject: drm/i915: Split alloc from init for lrc Extend init/init_hw split to context init. - Move context initialisation in to i915_gem_init_hw - Move one off initialisation for render ring to i915_gem_validate_context - Move default context initialisation to logical_ring_init Rename intel_lr_context_deferred_create to intel_lr_context_deferred_alloc, to reflect reduced functionality & alloc/init split. This patch is intended to split out the allocation of resources & initialisation to allow easier reuse of code for resume/gpu reset. v2: Removed function ptr wrapping of do_switch_context (Daniel Vetter) Left ->init_context int intel_lr_context_deferred_alloc (Daniel Vetter) Remove unnecessary init flag & ring type test. (Daniel Vetter) Improve commit message (Daniel Vetter) v3: On init/reinit, set the hw next sequence number to the sw next sequence number. This is set to 1 at driver load time. This prevents the seqno being reset on reinit (Chris Wilson) v4: Set seqno back to ~0 - 0x1000 at start-of-day, and increment by 0x100 on reset. This makes it obvious which bbs are which after a reset. (David Gordon & John Harrison) Rebase. v5: Rebase. Fixed rebase breakage. Put context pinning in separate function. Removed code churn. (Thomas Daniel) v6: Cleanup up issues introduced in v2 & v5 (Thomas Daniel) Issue: VIZ-4798 Signed-off-by: Nick Hoath Cc: Daniel Vetter Cc: Chris Wilson Cc: John Harrison Cc: David Gordon Cc: Thomas Daniel Reviewed-by: Thomas Daniel Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2994ce5..7ddf17b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -890,7 +890,6 @@ struct intel_context { } legacy_hw_ctx; /* Execlists */ - bool rcs_initialized; struct { struct drm_i915_gem_object *state; struct intel_ringbuffer *ringbuf; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index acb1f23..cb0df7e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4609,14 +4609,8 @@ int i915_gem_init_rings(struct drm_device *dev) goto cleanup_vebox_ring; } - ret = i915_gem_set_seqno(dev, ((u32)~0 - 0x1000)); - if (ret) - goto cleanup_bsd2_ring; - return 0; -cleanup_bsd2_ring: - intel_cleanup_ring_buffer(&dev_priv->ring[VCS2]); cleanup_vebox_ring: intel_cleanup_ring_buffer(&dev_priv->ring[VECS]); cleanup_blt_ring: @@ -4705,6 +4699,14 @@ i915_gem_init_hw(struct drm_device *dev) } } + /* + * Increment the next seqno by 0x100 so we have a visible break + * on re-initialisation + */ + ret = i915_gem_set_seqno(dev, dev_priv->next_seqno+0x100); + if (ret) + goto out; + /* Now it is safe to go back round and do everything else: */ for_each_ring(ring, dev_priv, i) { struct drm_i915_gem_request *req; @@ -4906,6 +4908,14 @@ i915_gem_load(struct drm_device *dev) dev_priv->num_fence_regs = I915_READ(vgtif_reg(avail_rs.fence_num)); + /* + * Set initial sequence number for requests. + * Using this number allows the wraparound to happen early, + * catching any obvious problems. + */ + dev_priv->next_seqno = ((u32)~0 - 0x1100); + dev_priv->last_seqno = ((u32)~0 - 0x1101); + /* Initialize fence registers to zero */ INIT_LIST_HEAD(&dev_priv->mm.fence_list); i915_gem_restore_fences(dev); diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 923a3c4..98952b4 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1009,7 +1009,7 @@ i915_gem_validate_context(struct drm_device *dev, struct drm_file *file, } if (i915.enable_execlists && !ctx->engine[ring->id].state) { - int ret = intel_lr_context_deferred_create(ctx, ring); + int ret = intel_lr_context_deferred_alloc(ctx, ring); if (ret) { DRM_DEBUG("Could not create LRC %u: %d\n", ctx_id, ret); return ERR_PTR(ret); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index c3fca4b..0a53c96 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -221,6 +221,9 @@ enum { #define CTX_RCS_INDIRECT_CTX_OFFSET_DEFAULT 0x17 static int intel_lr_context_pin(struct drm_i915_gem_request *rq); +static void lrc_setup_hardware_status_page(struct intel_engine_cs *ring, + struct drm_i915_gem_object *default_ctx_obj); + /** * intel_sanitize_enable_execlists() - sanitize i915.enable_execlists @@ -1020,39 +1023,54 @@ int logical_ring_flush_all_caches(struct drm_i915_gem_request *req) return 0; } -static int intel_lr_context_pin(struct drm_i915_gem_request *rq) +static int intel_lr_context_do_pin(struct intel_engine_cs *ring, + struct drm_i915_gem_object *ctx_obj, + struct intel_ringbuffer *ringbuf) { - struct drm_i915_private *dev_priv = rq->i915; - struct intel_engine_cs *ring = rq->ring; - struct drm_i915_gem_object *ctx_obj = rq->ctx->engine[ring->id].state; - struct intel_ringbuffer *ringbuf = rq->ringbuf; + struct drm_device *dev = ring->dev; + struct drm_i915_private *dev_priv = dev->dev_private; int ret = 0; WARN_ON(!mutex_is_locked(&ring->dev->struct_mutex)); - if (rq->ctx->engine[ring->id].pin_count++ == 0) { - ret = i915_gem_obj_ggtt_pin(ctx_obj, GEN8_LR_CONTEXT_ALIGN, - PIN_OFFSET_BIAS | GUC_WOPCM_TOP); - if (ret) - goto reset_pin_count; + ret = i915_gem_obj_ggtt_pin(ctx_obj, GEN8_LR_CONTEXT_ALIGN, + PIN_OFFSET_BIAS | GUC_WOPCM_TOP); + if (ret) + return ret; - ret = intel_pin_and_map_ringbuffer_obj(ring->dev, ringbuf); - if (ret) - goto unpin_ctx_obj; + ret = intel_pin_and_map_ringbuffer_obj(ring->dev, ringbuf); + if (ret) + goto unpin_ctx_obj; - ctx_obj->dirty = true; + ctx_obj->dirty = true; - /* Invalidate GuC TLB. */ - if (i915.enable_guc_submission) - I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE); - } + /* Invalidate GuC TLB. */ + if (i915.enable_guc_submission) + I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE); return ret; unpin_ctx_obj: i915_gem_object_ggtt_unpin(ctx_obj); + + return ret; +} + +static int intel_lr_context_pin(struct drm_i915_gem_request *rq) +{ + int ret = 0; + struct intel_engine_cs *ring = rq->ring; + struct drm_i915_gem_object *ctx_obj = rq->ctx->engine[ring->id].state; + struct intel_ringbuffer *ringbuf = rq->ringbuf; + + if (rq->ctx->engine[ring->id].pin_count++ == 0) { + ret = intel_lr_context_do_pin(ring, ctx_obj, ringbuf); + if (ret) + goto reset_pin_count; + } + return ret; + reset_pin_count: rq->ctx->engine[ring->id].pin_count = 0; - return ret; } @@ -1462,6 +1480,9 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring) struct drm_device *dev = ring->dev; struct drm_i915_private *dev_priv = dev->dev_private; + lrc_setup_hardware_status_page(ring, + ring->default_context->engine[ring->id].state); + I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask)); I915_WRITE(RING_HWSTAM(ring->mmio_base), 0xffffffff); @@ -1901,7 +1922,21 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rin if (ret) return ret; - ret = intel_lr_context_deferred_create(ring->default_context, ring); + ret = intel_lr_context_deferred_alloc(ring->default_context, ring); + if (ret) + return ret; + + /* As this is the default context, always pin it */ + ret = intel_lr_context_do_pin( + ring, + ring->default_context->engine[ring->id].state, + ring->default_context->engine[ring->id].ringbuf); + if (ret) { + DRM_ERROR( + "Failed to pin and map ringbuffer %s: %d\n", + ring->name, ret); + return ret; + } return ret; } @@ -2124,14 +2159,8 @@ int intel_logical_rings_init(struct drm_device *dev) goto cleanup_vebox_ring; } - ret = i915_gem_set_seqno(dev, ((u32)~0 - 0x1000)); - if (ret) - goto cleanup_bsd2_ring; - return 0; -cleanup_bsd2_ring: - intel_logical_ring_cleanup(&dev_priv->ring[VCS2]); cleanup_vebox_ring: intel_logical_ring_cleanup(&dev_priv->ring[VECS]); cleanup_blt_ring: @@ -2401,7 +2430,7 @@ static void lrc_setup_hardware_status_page(struct intel_engine_cs *ring, } /** - * intel_lr_context_deferred_create() - create the LRC specific bits of a context + * intel_lr_context_deferred_alloc() - create the LRC specific bits of a context * @ctx: LR context to create. * @ring: engine to be used with the context. * @@ -2413,12 +2442,11 @@ static void lrc_setup_hardware_status_page(struct intel_engine_cs *ring, * * Return: non-zero on error. */ -int intel_lr_context_deferred_create(struct intel_context *ctx, + +int intel_lr_context_deferred_alloc(struct intel_context *ctx, struct intel_engine_cs *ring) { - const bool is_global_default_ctx = (ctx == ring->default_context); struct drm_device *dev = ring->dev; - struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_object *ctx_obj; uint32_t context_size; struct intel_ringbuffer *ringbuf; @@ -2438,82 +2466,50 @@ int intel_lr_context_deferred_create(struct intel_context *ctx, return -ENOMEM; } - if (is_global_default_ctx) { - ret = i915_gem_obj_ggtt_pin(ctx_obj, GEN8_LR_CONTEXT_ALIGN, - PIN_OFFSET_BIAS | GUC_WOPCM_TOP); - if (ret) { - DRM_DEBUG_DRIVER("Pin LRC backing obj failed: %d\n", - ret); - drm_gem_object_unreference(&ctx_obj->base); - return ret; - } - - /* Invalidate GuC TLB. */ - if (i915.enable_guc_submission) - I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE); - } - ringbuf = intel_engine_create_ringbuffer(ring, 4 * PAGE_SIZE); if (IS_ERR(ringbuf)) { ret = PTR_ERR(ringbuf); - goto error_unpin_ctx; - } - - if (is_global_default_ctx) { - ret = intel_pin_and_map_ringbuffer_obj(dev, ringbuf); - if (ret) { - DRM_ERROR( - "Failed to pin and map ringbuffer %s: %d\n", - ring->name, ret); - goto error_ringbuf; - } + goto error_deref_obj; } ret = populate_lr_context(ctx, ctx_obj, ring, ringbuf); if (ret) { DRM_DEBUG_DRIVER("Failed to populate LRC: %d\n", ret); - goto error; + goto error_ringbuf; } ctx->engine[ring->id].ringbuf = ringbuf; ctx->engine[ring->id].state = ctx_obj; - if (ctx == ring->default_context) - lrc_setup_hardware_status_page(ring, ctx_obj); - else if (ring->id == RCS && !ctx->rcs_initialized) { - if (ring->init_context) { - struct drm_i915_gem_request *req; - - ret = i915_gem_request_alloc(ring, ctx, &req); - if (ret) - return ret; + if (ctx != ring->default_context && ring->init_context) { + struct drm_i915_gem_request *req; - ret = ring->init_context(req); - if (ret) { - DRM_ERROR("ring init context: %d\n", ret); - i915_gem_request_cancel(req); - ctx->engine[ring->id].ringbuf = NULL; - ctx->engine[ring->id].state = NULL; - goto error; - } - - i915_add_request_no_flush(req); + ret = i915_gem_request_alloc(ring, + ctx, &req); + if (ret) { + DRM_ERROR("ring create req: %d\n", + ret); + i915_gem_request_cancel(req); + goto error_ringbuf; } - ctx->rcs_initialized = true; + ret = ring->init_context(req); + if (ret) { + DRM_ERROR("ring init context: %d\n", + ret); + i915_gem_request_cancel(req); + goto error_ringbuf; + } + i915_add_request_no_flush(req); } - return 0; -error: - if (is_global_default_ctx) - intel_unpin_ringbuffer_obj(ringbuf); error_ringbuf: intel_ringbuffer_free(ringbuf); -error_unpin_ctx: - if (is_global_default_ctx) - i915_gem_object_ggtt_unpin(ctx_obj); +error_deref_obj: drm_gem_object_unreference(&ctx_obj->base); + ctx->engine[ring->id].ringbuf = NULL; + ctx->engine[ring->id].state = NULL; return ret; } diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index 4cc54b3..69d99f0 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -75,8 +75,8 @@ static inline void intel_logical_ring_emit(struct intel_ringbuffer *ringbuf, #define LRC_STATE_PN (LRC_PPHWSP_PN + 1) void intel_lr_context_free(struct intel_context *ctx); -int intel_lr_context_deferred_create(struct intel_context *ctx, - struct intel_engine_cs *ring); +int intel_lr_context_deferred_alloc(struct intel_context *ctx, + struct intel_engine_cs *ring); void intel_lr_context_unpin(struct drm_i915_gem_request *req); void intel_lr_context_reset(struct drm_device *dev, struct intel_context *ctx); -- cgit v0.10.2 From 374887bae861be2e691381f704b3d6068a54457c Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Sun, 13 Sep 2015 21:08:31 +0900 Subject: drm/i915: Fix warnings while make xmldocs caused by intel_lrc.c This patch fix following warnings while "make xmldocs". .//drivers/gpu/drm/i915/intel_lrc.c:780: warning: No description found for parameter 'req' .//drivers/gpu/drm/i915/intel_lrc.c:780: warning: Excess function parameter 'request' description in 'intel_logical_ring_begin' .//drivers/gpu/drm/i915/intel_lrc.c:780: warning: Excess function parameter 'ctx' description in 'intel_logical_ring_begin' Signed-off-by: Masanari Iida Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 0a53c96..fe06accb0 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -802,8 +802,7 @@ static int logical_ring_prepare(struct drm_i915_gem_request *req, int bytes) /** * intel_logical_ring_begin() - prepare the logical ringbuffer to accept some commands * - * @request: The request to start some new work for - * @ctx: Logical ring context whose ringbuffer is being prepared. + * @req: The request to start some new work for * @num_dwords: number of DWORDs that we plan to write to the ringbuffer. * * The ringbuffer might not be ready to accept the commands right away (maybe it needs to -- cgit v0.10.2 From d7884d69a524b92d9770bcdc03df3c5a6120c2d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Sep 2015 21:14:29 +0300 Subject: drm/i915: Set stolen reserved to 0 for pre-g4x platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This stolen reserved stuff was introduced on g4x, so no need to waste stolen on older platforms. Unfortunately configdb is no more so I can't look up the right way to detect this stuff. I do have one hint as to where the register might be on ctg, but I don't have a ctg to test it, and on the elk I have here it doesn't contain sensible looking data. For ilk grits suggegsts it might be in the same place as on snb (the original PCI reg, not the mirror) but I can't be entirely sure about it The register shows a round zero on my ilk. So when there's no really good data for any of these platforms leave the current "assume 1MiB" approach in place. Cc: Paulo Zanoni Cc: Chris Wilson Signed-off-by: Ville Syrjälä Acked-by: Chris Wilson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index f361c4a..bf26ecc 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -281,7 +281,7 @@ static void bdw_get_stolen_reserved(struct drm_i915_private *dev_priv, int i915_gem_init_stolen(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - unsigned long reserved_total, reserved_base, reserved_size; + unsigned long reserved_total, reserved_base = 0, reserved_size; unsigned long stolen_top; mutex_init(&dev_priv->mm.stolen_lock); @@ -306,6 +306,9 @@ int i915_gem_init_stolen(struct drm_device *dev) case 2: case 3: case 4: + if (!IS_G4X(dev)) + break; + /* fall through */ case 5: /* Assume the gen6 maximum for the older platforms. */ reserved_size = 1024 * 1024; -- cgit v0.10.2 From 6b6d5626750d72a22180a6e094cf95acd1d85c9b Mon Sep 17 00:00:00 2001 From: Robert Beckett Date: Tue, 8 Sep 2015 10:31:52 +0100 Subject: drm/i915/gen9: WA ST Unit Power Optimization Disable WaDisableSTUnitPowerOptimization:skl,bxt Signed-off-by: Robert Beckett Signed-off-by: Arun Siluvery Reviewed-by: Sagar Arun Kamble Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 495ac17..dd3d235 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6943,6 +6943,9 @@ enum skl_disp_power_wells { #define HSW_ROW_CHICKEN3 0xe49c #define HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE (1 << 6) +#define HALF_SLICE_CHICKEN2 0xe180 +#define GEN8_ST_PO_DISABLE (1<<13) + #define HALF_SLICE_CHICKEN3 0xe184 #define HSW_SAMPLE_C_PERFORMANCE (1<<9) #define GEN8_CENTROID_PIXEL_OPT_DIS (1<<8) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 684e069..16a4ead 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -990,6 +990,9 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring) GEN8_SAMPLER_POWER_BYPASS_DIS); } + /* WaDisableSTUnitPowerOptimization:skl,bxt */ + WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE); + return 0; } -- cgit v0.10.2 From d1b9d039de79a1cdd789d1547251d5ba0fad573b Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Mon, 14 Sep 2015 21:35:42 +0530 Subject: drm/i915: Fix fb object's frontbuffer-bits Shared frontbuffer bits are causing warnings when same FB is displayed in another plane without clearing the bits from previous plane. v2: Removing coversion of fb bits to 64 bit as it is not needed for now. (Daniel) Change-Id: Ic2df80747f314b82afd22f8326297c57d1e652c6 Signed-off-by: Sagar Arun Kamble Signed-off-by: Kumar, Mahesh [danvet: Drop INTEL_FRONTBUFFER_SPRITE_MASK since unused.] Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7ddf17b..677faa8 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2011,25 +2011,26 @@ struct drm_i915_gem_object_ops { /* * Frontbuffer tracking bits. Set in obj->frontbuffer_bits while a gem bo is - * considered to be the frontbuffer for the given plane interface-vise. This + * considered to be the frontbuffer for the given plane interface-wise. This * doesn't mean that the hw necessarily already scans it out, but that any * rendering (by the cpu or gpu) will land in the frontbuffer eventually. * * We have one bit per pipe and per scanout plane type. */ -#define INTEL_FRONTBUFFER_BITS_PER_PIPE 4 +#define INTEL_MAX_SPRITE_BITS_PER_PIPE 5 +#define INTEL_FRONTBUFFER_BITS_PER_PIPE 8 #define INTEL_FRONTBUFFER_BITS \ (INTEL_FRONTBUFFER_BITS_PER_PIPE * I915_MAX_PIPES) #define INTEL_FRONTBUFFER_PRIMARY(pipe) \ (1 << (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))) #define INTEL_FRONTBUFFER_CURSOR(pipe) \ - (1 << (1 +(INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))) -#define INTEL_FRONTBUFFER_SPRITE(pipe) \ - (1 << (2 +(INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))) + (1 << (1 + (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))) +#define INTEL_FRONTBUFFER_SPRITE(pipe, plane) \ + (1 << (2 + plane + (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))) #define INTEL_FRONTBUFFER_OVERLAY(pipe) \ - (1 << (3 +(INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))) + (1 << (2 + INTEL_MAX_SPRITE_BITS_PER_PIPE + (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))) #define INTEL_FRONTBUFFER_ALL_MASK(pipe) \ - (0xf << (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))) + (0xff << (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))) struct drm_i915_gem_object { struct drm_gem_object base; diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 9553859..4d27243 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1123,7 +1123,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) intel_plane->pipe = pipe; intel_plane->plane = plane; - intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER_SPRITE(pipe); + intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER_SPRITE(pipe, plane); intel_plane->check_plane = intel_check_sprite_plane; intel_plane->commit_plane = intel_commit_sprite_plane; possible_crtcs = (1 << pipe); -- cgit v0.10.2 From 1f3e9a6edae4f1168a4baaeb4c55d4eb5a8f7501 Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Wed, 26 Aug 2015 18:35:28 -0400 Subject: ARM: NSP: Add basic support for Broadcom Northstar Plus SoC Broadcom Northstar Plus family of SoCs are used for switching control and management applications as well as residential router/gateway applications. The SoC features dual core Cortex A9 ARM CPUs, integrating several peripheral interfaces including multiple Gigabit Ethernet PHYs, DDR3 memory, PCIE Gen-2, USB 2.0 and USB 3.0, serial and NAND flash, SATA and several other IO controllers. Signed-off-by: Kapil Hali Signed-off-by: Jon Mason Acked-by: Scott Branden Signed-off-by: Florian Fainelli diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig index 1319c3c..1679fa4 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -35,6 +35,20 @@ config ARCH_BCM_CYGNUS BCM11300, BCM11320, BCM11350, BCM11360, BCM58300, BCM58302, BCM58303, BCM58305. +config ARCH_BCM_NSP + bool "Broadcom Northstar Plus SoC Support" if ARCH_MULTI_V7 + select ARCH_BCM_IPROC + select ARM_ERRATA_754322 + select ARM_ERRATA_775420 + help + Support for Broadcom Northstar Plus SoC. + Broadcom Northstar Plus family of SoCs are used for switching control + and management applications as well as residential router/gateway + applications. The SoC features dual core Cortex A9 ARM CPUs, + integrating several peripheral interfaces including multiple Gigabit + Ethernet PHYs, DDR3 memory, PCIE Gen-2, USB 2.0 and USB 3.0, serial and + NAND flash, SATA and several other IO controllers. + config ARCH_BCM_5301X bool "Broadcom BCM470X / BCM5301X ARM SoC" if ARCH_MULTI_V7 select ARCH_BCM_IPROC diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile index 1780a3f..892261f 100644 --- a/arch/arm/mach-bcm/Makefile +++ b/arch/arm/mach-bcm/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2012-2014 Broadcom Corporation +# Copyright (C) 2012-2015 Broadcom Corporation # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as @@ -13,6 +13,9 @@ # Cygnus obj-$(CONFIG_ARCH_BCM_CYGNUS) += bcm_cygnus.o +# Northstar Plus +obj-$(CONFIG_ARCH_BCM_NSP) += bcm_nsp.o + # BCM281XX obj-$(CONFIG_ARCH_BCM_281XX) += board_bcm281xx.o diff --git a/arch/arm/mach-bcm/bcm_nsp.c b/arch/arm/mach-bcm/bcm_nsp.c new file mode 100644 index 0000000..a1101a3 --- /dev/null +++ b/arch/arm/mach-bcm/bcm_nsp.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2015 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +static const char *const bcm_nsp_dt_compat[] __initconst = { + "brcm,nsp", + NULL, +}; + +DT_MACHINE_START(NSP_DT, "Broadcom Northstar Plus SoC") + .l2c_aux_val = 0, + .l2c_aux_mask = ~0, + .dt_compat = bcm_nsp_dt_compat, +MACHINE_END -- cgit v0.10.2 From d52fad262041217be0a0e7049253186ec9cfb2a6 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Thu, 18 Jun 2015 17:11:32 -0700 Subject: soc: add stubs for brcmstb SoC's Used on BCM7xxx Set-Top Box chips (e.g., BCM7445). Signed-off-by: Brian Norris Signed-off-by: Florian Fainelli diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig index 1679fa4..0be09af 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -161,6 +161,7 @@ config ARCH_BRCMSTB select BCM7120_L2_IRQ select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE select ARCH_WANT_OPTIONAL_GPIOLIB + select SOC_BRCMSTB help Say Y if you intend to run the kernel on a Broadcom ARM-based STB chipset. diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig index 96ddecb..c9c0fcc 100644 --- a/drivers/soc/Kconfig +++ b/drivers/soc/Kconfig @@ -1,5 +1,6 @@ menu "SOC (System On Chip) specific Drivers" +source "drivers/soc/brcmstb/Kconfig" source "drivers/soc/mediatek/Kconfig" source "drivers/soc/qcom/Kconfig" source "drivers/soc/sunxi/Kconfig" diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index 0b12d77..4e27f10 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -2,6 +2,7 @@ # Makefile for the Linux Kernel SOC specific device drivers. # +obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/ obj-$(CONFIG_MACH_DOVE) += dove/ obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ obj-$(CONFIG_ARCH_QCOM) += qcom/ diff --git a/drivers/soc/brcmstb/Kconfig b/drivers/soc/brcmstb/Kconfig new file mode 100644 index 0000000..39cab3b --- /dev/null +++ b/drivers/soc/brcmstb/Kconfig @@ -0,0 +1,9 @@ +menuconfig SOC_BRCMSTB + bool "Broadcom STB SoC drivers" + depends on ARM + help + Enables drivers for the Broadcom Set-Top Box (STB) series of chips. + This option alone enables only some support code, while the drivers + can be enabled individually within this menu. + + If unsure, say N. diff --git a/drivers/soc/brcmstb/Makefile b/drivers/soc/brcmstb/Makefile new file mode 100644 index 0000000..183280e --- /dev/null +++ b/drivers/soc/brcmstb/Makefile @@ -0,0 +1 @@ +obj-y += common.o diff --git a/drivers/soc/brcmstb/common.c b/drivers/soc/brcmstb/common.c new file mode 100644 index 0000000..c262c02 --- /dev/null +++ b/drivers/soc/brcmstb/common.c @@ -0,0 +1,33 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * Copyright © 2015 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +#include + +static const struct of_device_id brcmstb_machine_match[] = { + { .compatible = "brcm,brcmstb", }, + { } +}; + +bool soc_is_brcmstb(void) +{ + struct device_node *root; + + root = of_find_node_by_path("/"); + if (!root) + return false; + + return of_match_node(brcmstb_machine_match, root) != NULL; +} diff --git a/include/soc/brcmstb/common.h b/include/soc/brcmstb/common.h new file mode 100644 index 0000000..cfb5335 --- /dev/null +++ b/include/soc/brcmstb/common.h @@ -0,0 +1,15 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * Copyright © 2015 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __SOC_BRCMSTB_COMMON_H__ +#define __SOC_BRCMSTB_COMMON_H__ + +bool soc_is_brcmstb(void); + +#endif /* __SOC_BRCMSTB_COMMON_H__ */ -- cgit v0.10.2 From 40b43419e61cbeb3946953df46d4a18d47f8e09c Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Wed, 26 Aug 2015 18:35:26 -0400 Subject: dt-bindings: Create Documentation for NSP DT bindings Add the documentation for the Broadcom Northstar Plus device tree bindings. Signed-off-by: Jon Mason Acked-by: Scott Branden Signed-off-by: Florian Fainelli diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,nsp.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,nsp.txt new file mode 100644 index 0000000..eae53e4 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,nsp.txt @@ -0,0 +1,34 @@ +Broadcom Northstar Plus device tree bindings +-------------------------------------------- + +Broadcom Northstar Plus family of SoCs are used for switching control +and management applications as well as residential router/gateway +applications. The SoC features dual core Cortex A9 ARM CPUs, integrating +several peripheral interfaces including multiple Gigabit Ethernet PHYs, +DDR3 memory, PCIE Gen-2, USB 2.0 and USB 3.0, serial and NAND flash, +SATA and several other IO controllers. + +Boards with Northstar Plus SoCs shall have the following properties: + +Required root node property: + +BCM58522 +compatible = "brcm,bcm58522", "brcm,nsp"; + +BCM58525 +compatible = "brcm,bcm58525", "brcm,nsp"; + +BCM58535 +compatible = "brcm,bcm58535", "brcm,nsp"; + +BCM58622 +compatible = "brcm,bcm58622", "brcm,nsp"; + +BCM58623 +compatible = "brcm,bcm58623", "brcm,nsp"; + +BCM58625 +compatible = "brcm,bcm58625", "brcm,nsp"; + +BCM88312 +compatible = "brcm,bcm88312", "brcm,nsp"; -- cgit v0.10.2 From 7b2e987de20781ce74c160a59dbf6a2c06983794 Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Mon, 31 Aug 2015 19:48:53 -0400 Subject: ARM: NSP: add minimal Northstar Plus device tree Add a very minimalistic set of Northstar Plus Device Tree files which describes the SoC and the BCM958625 implementation. The perpherials described are: ARM Cortex A9 CPU 2 8250 UARTs ARM GIC PL310 L2 Cache ARM A9 Global timer Signed-off-by: Kapil Hali Signed-off-by: Jon Mason Reviewed-by: Ray Jui Signed-off-by: Florian Fainelli diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 233159d..7b94c49 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -83,6 +83,8 @@ dtb-$(CONFIG_ARCH_BCM_CYGNUS) += \ dtb-$(CONFIG_ARCH_BCM_MOBILE) += \ bcm28155-ap.dtb \ bcm21664-garnet.dtb +dtb-$(CONFIG_ARCH_BCM_NSP) += \ + bcm958625k.dtb dtb-$(CONFIG_ARCH_BERLIN) += \ berlin2-sony-nsz-gs7.dtb \ berlin2cd-google-chromecast.dtb \ diff --git a/arch/arm/boot/dts/bcm-nsp.dtsi b/arch/arm/boot/dts/bcm-nsp.dtsi new file mode 100644 index 0000000..58aca27 --- /dev/null +++ b/arch/arm/boot/dts/bcm-nsp.dtsi @@ -0,0 +1,119 @@ +/* + * BSD LICENSE + * + * Copyright(c) 2015 Broadcom Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Broadcom Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "skeleton.dtsi" + +/ { + compatible = "brcm,nsp"; + model = "Broadcom Northstar Plus SoC"; + interrupt-parent = <&gic>; + + mpcore { + compatible = "simple-bus"; + ranges = <0x00000000 0x19020000 0x00003000>; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + next-level-cache = <&L2>; + reg = <0x0>; + }; + }; + + L2: l2-cache { + compatible = "arm,pl310-cache"; + reg = <0x2000 0x1000>; + cache-unified; + cache-level = <2>; + }; + + gic: interrupt-controller@19021000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x1000 0x1000>, + <0x0100 0x100>; + }; + + timer@19020200 { + compatible = "arm,cortex-a9-global-timer"; + reg = <0x0200 0x100>; + interrupts = ; + clocks = <&periph_clk>; + }; + }; + + clocks { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + periph_clk: periph_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <500000000>; + }; + }; + + axi { + compatible = "simple-bus"; + ranges = <0x00000000 0x18000000 0x00001000>; + #address-cells = <1>; + #size-cells = <1>; + + uart0: serial@18000300 { + compatible = "ns16550a"; + reg = <0x0300 0x100>; + interrupts = ; + clock-frequency = <62499840>; + status = "disabled"; + }; + + uart1: serial@18000400 { + compatible = "ns16550a"; + reg = <0x0400 0x100>; + interrupts = ; + clock-frequency = <62499840>; + status = "disabled"; + }; + }; +}; diff --git a/arch/arm/boot/dts/bcm958625k.dts b/arch/arm/boot/dts/bcm958625k.dts new file mode 100644 index 0000000..16303db --- /dev/null +++ b/arch/arm/boot/dts/bcm958625k.dts @@ -0,0 +1,57 @@ +/* + * BSD LICENSE + * + * Copyright(c) 2015 Broadcom Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Broadcom Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/dts-v1/; + +#include "bcm-nsp.dtsi" + +/ { + model = "NorthStar Plus SVK (BCM958625K)"; + compatible = "brcm,bcm58625", "brcm,nsp"; + + aliases { + serial0 = &uart0; + serial1 = &uart1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + status = "okay"; +}; -- cgit v0.10.2 From bfae737540fd2647afb55dfb480964042819b751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 26 Aug 2015 16:13:22 +0200 Subject: ARM: BCM5301X: Add DT for Netgear R7000 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: Florian Fainelli diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 7b94c49..1e9eecf 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -72,6 +72,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ bcm47081-buffalo-wzr-900dhp.dtb \ bcm4709-asus-rt-ac87u.dtb \ bcm4709-buffalo-wxr-1900dhp.dtb \ + bcm4709-netgear-r7000.dtb \ bcm4709-netgear-r8000.dtb dtb-$(CONFIG_ARCH_BCM_63XX) += \ bcm963138dvt.dtb diff --git a/arch/arm/boot/dts/bcm4709-netgear-r7000.dts b/arch/arm/boot/dts/bcm4709-netgear-r7000.dts new file mode 100644 index 0000000..a22ed14 --- /dev/null +++ b/arch/arm/boot/dts/bcm4709-netgear-r7000.dts @@ -0,0 +1,106 @@ +/* + * Broadcom BCM470X / BCM5301X ARM platform code. + * DTS for Netgear R7000 + * + * Copyright (C) 2015 Rafał Miłecki + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +/dts-v1/; + +#include "bcm4708.dtsi" +#include "bcm5301x-nand-cs0-bch8.dtsi" + +/ { + compatible = "netgear,r7000", "brcm,bcm4709", "brcm,bcm4708"; + model = "Netgear R7000"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + memory { + reg = <0x00000000 0x08000000>; + }; + + leds { + compatible = "gpio-leds"; + + power-white { + label = "bcm53xx:white:power"; + gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>; + linux,default-trigger = "default-on"; + }; + + power-amber { + label = "bcm53xx:amber:power"; + gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>; + linux,default-trigger = "default-off"; + }; + + 5ghz { + label = "bcm53xx:white:5ghz"; + gpios = <&chipcommon 12 GPIO_ACTIVE_LOW>; + linux,default-trigger = "default-off"; + }; + + 2ghz { + label = "bcm53xx:white:2ghz"; + gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>; + linux,default-trigger = "default-off"; + }; + + wps { + label = "bcm53xx:white:wps"; + gpios = <&chipcommon 14 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "default-off"; + }; + + wireless { + label = "bcm53xx:white:wireless"; + gpios = <&chipcommon 15 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "default-off"; + }; + + usb3 { + label = "bcm53xx:white:usb3"; + gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>; + linux,default-trigger = "default-off"; + }; + + usb2 { + label = "bcm53xx:white:usb2"; + gpios = <&chipcommon 18 GPIO_ACTIVE_LOW>; + linux,default-trigger = "default-off"; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; + + wps { + label = "WPS"; + linux,code = ; + gpios = <&chipcommon 4 GPIO_ACTIVE_LOW>; + }; + + rfkill { + label = "WiFi"; + linux,code = ; + gpios = <&chipcommon 5 GPIO_ACTIVE_LOW>; + }; + + restart { + label = "Reset"; + linux,code = ; + gpios = <&chipcommon 6 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&uart0 { + status = "okay"; +}; -- cgit v0.10.2 From bb1d8fba19654be3a92cf40a4c67e64ec7d4fc8f Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 12 Sep 2015 13:17:36 +0200 Subject: ARM: BCM5301X: add NAND flash chip description for Asus RT-AC87U The NAND flash chip description were not imported for the Asus RT-AC87U dts file when this was done for all the other dts files, because these patches were send in parallel. This adds a missing NAND flash chip description to this patch: commit 9faa5960eef3204cae6637b530f5e23e53b5a9ef Author: Hauke Mehrtens Date: Fri May 29 23:39:47 2015 +0200 ARM: BCM5301X: add NAND flash chip description Signed-off-by: Hauke Mehrtens Signed-off-by: Florian Fainelli diff --git a/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts b/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts index aedf3c4..8ade7de 100644 --- a/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts +++ b/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts @@ -10,6 +10,7 @@ /dts-v1/; #include "bcm4708.dtsi" +#include "bcm5301x-nand-cs0-bch8.dtsi" / { compatible = "asus,rt-ac87u", "brcm,bcm4709", "brcm,bcm4708"; -- cgit v0.10.2 From 9c07d61f1bbb96beb01dcc2b109cf56e61f9b819 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Thu, 18 Jun 2015 17:11:30 -0700 Subject: Documentation: dt: brcmstb: add system PM bindings Signed-off-by: Brian Norris Signed-off-by: Florian Fainelli diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,brcmstb.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,brcmstb.txt index 430608e..9442964 100644 --- a/Documentation/devicetree/bindings/arm/bcm/brcm,brcmstb.txt +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,brcmstb.txt @@ -43,8 +43,7 @@ example: }; }; -Lastly, nodes that allow for support of SMP initialization and reboot are -required: +Nodes that allow for support of SMP initialization and reboot are required: smpboot ------- @@ -95,3 +94,142 @@ example: compatible = "brcm,brcmstb-reboot"; syscon = <&sun_top_ctrl 0x304 0x308>; }; + + + +Power management +---------------- + +For power management (particularly, S2/S3/S5 system suspend), the following SoC +components are needed: + += Always-On control block (AON CTRL) + +This hardware provides control registers for the "always-on" (even in low-power +modes) hardware, such as the Power Management State Machine (PMSM). + +Required properties: +- compatible : should contain "brcm,brcmstb-aon-ctrl" +- reg : the register start and length for the AON CTRL block + +Example: + +aon-ctrl@410000 { + compatible = "brcm,brcmstb-aon-ctrl"; + reg = <0x410000 0x400>; +}; + += Memory controllers + +A Broadcom STB SoC typically has a number of independent memory controllers, +each of which may have several associated hardware blocks, which are versioned +independently (control registers, DDR PHYs, etc.). One might consider +describing these controllers as a parent "memory controllers" block, which +contains N sub-nodes (one for each controller in the system), each of which is +associated with a number of hardware register resources (e.g., its PHY). See +the example device tree snippet below. + +== MEMC (MEMory Controller) + +Represents a single memory controller instance. + +Required properties: +- compatible : should contain "brcm,brcmstb-memc" and "simple-bus" + +Should contain subnodes for any of the following relevant hardware resources: + +== DDR PHY control + +Control registers for this memory controller's DDR PHY. + +Required properties: +- compatible : should contain one of these + "brcm,brcmstb-ddr-phy-v225.1" + "brcm,brcmstb-ddr-phy-v240.1" + "brcm,brcmstb-ddr-phy-v240.2" + +- reg : the DDR PHY register range + +== DDR SHIMPHY + +Control registers for this memory controller's DDR SHIMPHY. + +Required properties: +- compatible : should contain "brcm,brcmstb-ddr-shimphy-v1.0" +- reg : the DDR SHIMPHY register range + +== MEMC DDR control + +Sequencer DRAM parameters and control registers. Used for Self-Refresh +Power-Down (SRPD), among other things. + +Required properties: +- compatible : should contain "brcm,brcmstb-memc-ddr" +- reg : the MEMC DDR register range + +Example: + +memory_controllers { + ranges; + compatible = "simple-bus"; + + memc@0 { + compatible = "brcm,brcmstb-memc", "simple-bus"; + ranges; + + ddr-phy@f1106000 { + compatible = "brcm,brcmstb-ddr-phy-v240.1"; + reg = <0xf1106000 0x21c>; + }; + + shimphy@f1108000 { + compatible = "brcm,brcmstb-ddr-shimphy-v1.0"; + reg = <0xf1108000 0xe4>; + }; + + memc-ddr@f1102000 { + reg = <0xf1102000 0x800>; + compatible = "brcm,brcmstb-memc-ddr"; + }; + }; + + memc@1 { + compatible = "brcm,brcmstb-memc", "simple-bus"; + ranges; + + ddr-phy@f1186000 { + compatible = "brcm,brcmstb-ddr-phy-v240.1"; + reg = <0xf1186000 0x21c>; + }; + + shimphy@f1188000 { + compatible = "brcm,brcmstb-ddr-shimphy-v1.0"; + reg = <0xf1188000 0xe4>; + }; + + memc-ddr@f1182000 { + reg = <0xf1182000 0x800>; + compatible = "brcm,brcmstb-memc-ddr"; + }; + }; + + memc@2 { + compatible = "brcm,brcmstb-memc", "simple-bus"; + ranges; + + ddr-phy@f1206000 { + compatible = "brcm,brcmstb-ddr-phy-v240.1"; + reg = <0xf1206000 0x21c>; + }; + + shimphy@f1208000 { + compatible = "brcm,brcmstb-ddr-shimphy-v1.0"; + reg = <0xf1208000 0xe4>; + }; + + memc-ddr@f1202000 { + reg = <0xf1202000 0x800>; + compatible = "brcm,brcmstb-memc-ddr"; + }; + }; +}; -- cgit v0.10.2 From aca770fb4f9a88434e77b922743e5010a43f73d1 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Thu, 18 Jun 2015 17:11:36 -0700 Subject: ARM: dts: brcmstb: add BCM7445 system PM DT nodes Need the aon-ctrl, boot SRAM, and memory_controller descriptions. Signed-off-by: Brian Norris [florian: remove wake-timer, aon-pm-l2-intc duplicate] Signed-off-by: Florian Fainelli diff --git a/arch/arm/boot/dts/bcm7445.dtsi b/arch/arm/boot/dts/bcm7445.dtsi index 3b6b175..4791321 100644 --- a/arch/arm/boot/dts/bcm7445.dtsi +++ b/arch/arm/boot/dts/bcm7445.dtsi @@ -143,6 +143,12 @@ brcm,irq-can-wake; }; + aon-ctrl@410000 { + compatible = "brcm,brcmstb-aon-ctrl"; + reg = <0x410000 0x200>, <0x410200 0x400>; + reg-names = "aon-ctrl", "aon-sram"; + }; + nand: nand@3e2800 { status = "disabled"; #address-cells = <1>; @@ -219,6 +225,84 @@ }; + memory_controllers { + compatible = "simple-bus"; + ranges = <0x0 0x0 0xf1100000 0x200000>; + #address-cells = <1>; + #size-cells = <1>; + + memc@0 { + compatible = "brcm,brcmstb-memc", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x0 0x80000>; + + memc-ddr@2000 { + compatible = "brcm,brcmstb-memc-ddr"; + reg = <0x2000 0x800>; + }; + + ddr-phy@6000 { + compatible = "brcm,brcmstb-ddr-phy-v240.1"; + reg = <0x6000 0x21c>; + }; + + shimphy@8000 { + compatible = "brcm,brcmstb-ddr-shimphy-v1.0"; + reg = <0x8000 0xe4>; + }; + }; + + memc@1 { + compatible = "brcm,brcmstb-memc", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x80000 0x80000>; + + memc-ddr@2000 { + compatible = "brcm,brcmstb-memc-ddr"; + reg = <0x2000 0x800>; + }; + + ddr-phy@6000 { + compatible = "brcm,brcmstb-ddr-phy-v240.1"; + reg = <0x6000 0x21c>; + }; + + shimphy@8000 { + compatible = "brcm,brcmstb-ddr-shimphy-v1.0"; + reg = <0x8000 0xe4>; + }; + }; + + memc@2 { + compatible = "brcm,brcmstb-memc", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x100000 0x80000>; + + memc-ddr@2000 { + compatible = "brcm,brcmstb-memc-ddr"; + reg = <0x2000 0x800>; + }; + + ddr-phy@6000 { + compatible = "brcm,brcmstb-ddr-phy-v240.1"; + reg = <0x6000 0x21c>; + }; + + shimphy@8000 { + compatible = "brcm,brcmstb-ddr-shimphy-v1.0"; + reg = <0x8000 0xe4>; + }; + }; + }; + + sram@ffe00000 { + compatible = "brcm,boot-sram", "mmio-sram"; + reg = <0x0 0xffe00000 0x0 0x10000>; + }; + smpboot { compatible = "brcm,brcmstb-smpboot"; syscon-cpu = <&hif_cpubiuctrl 0x88 0x178>; -- cgit v0.10.2 From 63f37ddf5c221c5a86ea9e45625bd0381feabc13 Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Wed, 26 Aug 2015 18:35:30 -0400 Subject: MAINTAINERS: add entry for the Broadcom Northstar Plus SoCs Modify the iProc MAINTAINER to cover the Nortstar Plus SoCs, and add me to the list of people responsible for it. Since iProc is a family of SoCs that includes more than just Cygnus (i.e., Northstar (BCM5301X), Northstar Plus, Northstar 2, and a number of other platforms), remove it from the title to avoid any future confusion. Signed-off-by: Jon Mason Acked-by: Scott Branden Signed-off-by: Florian Fainelli diff --git a/MAINTAINERS b/MAINTAINERS index 7ba7ab7..84e306b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2354,19 +2354,27 @@ L: linux-scsi@vger.kernel.org S: Supported F: drivers/scsi/bnx2i/ -BROADCOM CYGNUS/IPROC ARM ARCHITECTURE +BROADCOM IPROC ARM ARCHITECTURE M: Ray Jui M: Scott Branden +M: Jon Mason L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: bcm-kernel-feedback-list@broadcom.com T: git git://github.com/broadcom/cygnus-linux.git S: Maintained N: iproc N: cygnus +N: nsp N: bcm9113* N: bcm9583* -N: bcm583* +N: bcm9585* +N: bcm9586* +N: bcm988312 N: bcm113* +N: bcm583* +N: bcm585* +N: bcm586* +N: bcm88312 BROADCOM BRCMSTB GPIO DRIVER M: Gregory Fong -- cgit v0.10.2 From de0d542338bc507d2fc21bfca2be540f17fc874a Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Wed, 26 Aug 2015 18:35:29 -0400 Subject: ARM: multi_v7_defconfig: Add NSP to defconfig Add the Broadcom Northstar Plus SoC to the multi_v7_defconfig Signed-off-by: Jon Mason Acked-by: Scott Branden Signed-off-by: Florian Fainelli diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 03deb7f..f84a42e 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -25,6 +25,7 @@ CONFIG_SOC_SAMA5D3=y CONFIG_SOC_SAMA5D4=y CONFIG_ARCH_BCM=y CONFIG_ARCH_BCM_CYGNUS=y +CONFIG_ARCH_BCM_NSP=y CONFIG_ARCH_BCM_21664=y CONFIG_ARCH_BCM_281XX=y CONFIG_ARCH_BCM_5301X=y -- cgit v0.10.2 From 241e077b560ce3a67bb3ba681d9e5494a6c1042d Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 15 Sep 2015 11:10:48 +0200 Subject: ARM: tegra: Rebuild default configuration on v4.3-rc1 As a result of rebuilding the configuration the following symbols are removed: - EXT4_FS: ext3 has finally been removed from the kernel. ext4 provides feature parity and can be used to mount ext3 filesystems. EXT3_FS selects EXT4_FS. - EXT3_DEFAULTS_TO_ORDERED: Removed as part of the ext3 filesystem removal. - IPV6: IPv6 is now built-in by default Signed-off-by: Thierry Reding diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig index 9808581..48af636 100644 --- a/arch/arm/configs/tegra_defconfig +++ b/arch/arm/configs/tegra_defconfig @@ -60,7 +60,6 @@ CONFIG_INET_ESP=y # CONFIG_INET_XFRM_MODE_BEET is not set # CONFIG_INET_LRO is not set # CONFIG_INET_DIAG is not set -CONFIG_IPV6=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_OPTIMISTIC_DAD=y CONFIG_INET6_AH=y @@ -266,10 +265,8 @@ CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y CONFIG_EXT2_FS_SECURITY=y CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set CONFIG_EXT3_FS_POSIX_ACL=y CONFIG_EXT3_FS_SECURITY=y -CONFIG_EXT4_FS=y # CONFIG_DNOTIFY is not set CONFIG_VFAT_FS=y CONFIG_TMPFS=y -- cgit v0.10.2 From 716d81e3508cad4f8c2fa4e48088646c0a9bbe7d Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 28 Aug 2015 23:08:15 +0200 Subject: ARM: tegra: Update default configuration Update the Tegra default configuration for the following features: - expose hardware/virtual IRQ mapping via debugfs - WM9712 audio/touch controller as found on Colibri T20 - sysfs interface for GPIOs - NFS client support for NFS version 4 Signed-off-by: Marcel Ziswiler Signed-off-by: Thierry Reding diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig index 48af636..3a36244 100644 --- a/arch/arm/configs/tegra_defconfig +++ b/arch/arm/configs/tegra_defconfig @@ -1,5 +1,6 @@ CONFIG_SYSVIPC=y CONFIG_FHANDLE=y +CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_IKCONFIG=y @@ -120,6 +121,9 @@ CONFIG_KEYBOARD_CROS_EC=y CONFIG_MOUSE_PS2_ELANTECH=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_ATMEL_MXT=y +CONFIG_TOUCHSCREEN_WM97XX=y +# CONFIG_TOUCHSCREEN_WM9705 is not set +# CONFIG_TOUCHSCREEN_WM9713 is not set CONFIG_TOUCHSCREEN_STMPE=y CONFIG_INPUT_MISC=y CONFIG_INPUT_MPU3050=y @@ -141,6 +145,7 @@ CONFIG_SPI_TEGRA20_SFLASH=y CONFIG_SPI_TEGRA20_SLINK=y CONFIG_PINCTRL_AS3722=y CONFIG_PINCTRL_PALMAS=y +CONFIG_GPIO_SYSFS=y CONFIG_GPIO_PCA953X=y CONFIG_GPIO_PCA953X_IRQ=y CONFIG_GPIO_PALMAS=y @@ -207,6 +212,7 @@ CONFIG_SND_SOC_TEGRA=y CONFIG_SND_SOC_TEGRA_RT5640=y CONFIG_SND_SOC_TEGRA_WM8753=y CONFIG_SND_SOC_TEGRA_WM8903=y +CONFIG_SND_SOC_TEGRA_WM9712=y CONFIG_SND_SOC_TEGRA_TRIMSLICE=y CONFIG_SND_SOC_TEGRA_ALC5632=y CONFIG_SND_SOC_TEGRA_MAX98090=y @@ -275,6 +281,7 @@ CONFIG_SQUASHFS=y CONFIG_SQUASHFS_LZO=y CONFIG_SQUASHFS_XZ=y CONFIG_NFS_FS=y +CONFIG_NFS_V4=y CONFIG_ROOT_NFS=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y -- cgit v0.10.2 From 9a0baee960a718b2fde249b7d9197641fb8eb08d Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 3 Jun 2015 12:43:41 +0100 Subject: ARM: tegra: Enable CPUFreq support for Tegra124 Chromebooks Add the device-tree DFLL clock node and CPU regulator phandle for Tegra124 Chromebooks to enable CPUFreq support on these boards. Signed-off-by: Jon Hunter Reviewed-by: Tomeu Vizoso Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra124-nyan.dtsi b/arch/arm/boot/dts/tegra124-nyan.dtsi index a9aec23..40c23a0 100644 --- a/arch/arm/boot/dts/tegra124-nyan.dtsi +++ b/arch/arm/boot/dts/tegra124-nyan.dtsi @@ -159,7 +159,7 @@ vin-ldo9-10-supply = <&vdd_5v0_sys>; vin-ldo11-supply = <&vdd_3v3_run>; - sd0 { + vdd_cpu: sd0 { regulator-name = "+VDD_CPU_AP"; regulator-min-microvolt = <700000>; regulator-max-microvolt = <1350000>; @@ -397,6 +397,13 @@ non-removable; }; + /* CPU DFLL clock */ + clock@0,70110000 { + status = "okay"; + vdd-cpu-supply = <&vdd_cpu>; + nvidia,i2c-fs-rate = <400000>; + }; + ahub@0,70300000 { i2s@0,70301100 { status = "okay"; @@ -487,6 +494,12 @@ }; }; + cpus { + cpu@0 { + vdd-cpu-supply = <&vdd_cpu>; + }; + }; + gpio-keys { compatible = "gpio-keys"; -- cgit v0.10.2 From d8b316b2509f224308e851036653364c22222c61 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Thu, 27 Aug 2015 11:44:48 +0200 Subject: ARM: tegra: Whitespace clean-up for Tegra20/30/124 There were a few cases of eight spaces being used instead of a tab character plus one case of using two spaces after an equal sign instead of just one which this patch fixes. Signed-off-by: Marcel Ziswiler Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi index 1e204a6..a5c878e 100644 --- a/arch/arm/boot/dts/tegra124.dtsi +++ b/arch/arm/boot/dts/tegra124.dtsi @@ -636,7 +636,7 @@ reg = <0x0 0x70030000 0x0 0x10000>; interrupts = ; clocks = <&tegra_car TEGRA124_CLK_HDA>, - <&tegra_car TEGRA124_CLK_HDA2HDMI>, + <&tegra_car TEGRA124_CLK_HDA2HDMI>, <&tegra_car TEGRA124_CLK_HDA2CODEC_2X>; clock-names = "hda", "hda2hdmi", "hda2codec_2x"; resets = <&tegra_car 125>, /* hda */ diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index e058709..0a8d1a6 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi @@ -601,8 +601,8 @@ <&tegra_car TEGRA20_CLK_PLL_E>; clock-names = "pex", "afi", "pll_e"; resets = <&tegra_car 70>, - <&tegra_car 72>, - <&tegra_car 74>; + <&tegra_car 72>, + <&tegra_car 74>; reset-names = "pex", "afi", "pcie_x"; status = "disabled"; diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi index fe04fb5..38e1e27 100644 --- a/arch/arm/boot/dts/tegra30.dtsi +++ b/arch/arm/boot/dts/tegra30.dtsi @@ -42,8 +42,8 @@ <&tegra_car TEGRA30_CLK_CML0>; clock-names = "pex", "afi", "pll_e", "cml"; resets = <&tegra_car 70>, - <&tegra_car 72>, - <&tegra_car 74>; + <&tegra_car 72>, + <&tegra_car 74>; reset-names = "pex", "afi", "pcie_x"; status = "disabled"; @@ -153,7 +153,7 @@ &tegra_car TEGRA30_CLK_GR3D2>; clock-names = "3d", "3d2"; resets = <&tegra_car 24>, - <&tegra_car 98>; + <&tegra_car 98>; reset-names = "3d", "3d2"; }; @@ -455,7 +455,7 @@ }; i2c@7000c000 { - compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c"; + compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c"; reg = <0x7000c000 0x100>; interrupts = ; #address-cells = <1>; @@ -660,7 +660,7 @@ reg = <0x70030000 0x10000>; interrupts = ; clocks = <&tegra_car TEGRA30_CLK_HDA>, - <&tegra_car TEGRA30_CLK_HDA2HDMI>, + <&tegra_car TEGRA30_CLK_HDA2HDMI>, <&tegra_car TEGRA30_CLK_HDA2CODEC_2X>; clock-names = "hda", "hda2hdmi", "hda2codec_2x"; resets = <&tegra_car 125>, /* hda */ -- cgit v0.10.2 From a5e27206b3b560f91aa421e166029db02b15a7dd Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 28 Aug 2015 14:42:28 +0200 Subject: ARM: tegra: apalis: Update hardware revisions compatibility comment Update introductory comment about what exact hardware revisions this device tree is compatible with as a hint for our customers. Signed-off-by: Marcel Ziswiler Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra30-apalis.dtsi b/arch/arm/boot/dts/tegra30-apalis.dtsi index a5446cb..3bff4d7 100644 --- a/arch/arm/boot/dts/tegra30-apalis.dtsi +++ b/arch/arm/boot/dts/tegra30-apalis.dtsi @@ -1,8 +1,9 @@ #include "tegra30.dtsi" /* - * Toradex Apalis T30 Device Tree - * Compatible for Revisions 1GB: V1.0A; 2GB: V1.0B, V1.0C + * Toradex Apalis T30 Module Device Tree + * Compatible for Revisions 1GB: V1.0A, V1.1A; 1GB IT: V1.1A; + * 2GB: V1.0B, V1.0C, V1.0E, V1.1A */ / { model = "Toradex Apalis T30"; -- cgit v0.10.2 From 654b7d6aec9e55ca5e67adb3bdf0fefd9533c900 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 28 Aug 2015 14:42:29 +0200 Subject: ARM: tegra: apalis: Fix HDMI power supplies Fix HDMI supplies (both regular VDD as well as PLL ones) being switched by the TPS65911 PMIC's GPIO6 aka EN_VDD_HDMI by introducing two new GPIO switched fixed regulators avdd_hdmi_pll_1v8_reg and avdd_hdmi_3v3_reg. Signed-off-by: Marcel Ziswiler Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra30-apalis.dtsi b/arch/arm/boot/dts/tegra30-apalis.dtsi index 3bff4d7..fd6c94e 100644 --- a/arch/arm/boot/dts/tegra30-apalis.dtsi +++ b/arch/arm/boot/dts/tegra30-apalis.dtsi @@ -34,8 +34,8 @@ host1x@50000000 { hdmi@54280000 { - vdd-supply = <&sys_3v3_reg>; - pll-supply = <&vio_reg>; + vdd-supply = <&avdd_hdmi_3v3_reg>; + pll-supply = <&avdd_hdmi_pll_1v8_reg>; nvidia,hpd-gpio = <&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>; @@ -667,18 +667,40 @@ #address-cells = <1>; #size-cells = <0>; - sys_3v3_reg: regulator@100 { + avdd_hdmi_pll_1v8_reg: regulator@100 { compatible = "regulator-fixed"; reg = <100>; + regulator-name = "+V1.8_AVDD_HDMI_PLL"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + enable-active-high; + gpio = <&pmic 6 GPIO_ACTIVE_HIGH>; + vin-supply = <&vio_reg>; + }; + + sys_3v3_reg: regulator@101 { + compatible = "regulator-fixed"; + reg = <101>; regulator-name = "3v3"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; }; - charge_pump_5v0_reg: regulator@101 { + avdd_hdmi_3v3_reg: regulator@102 { compatible = "regulator-fixed"; - reg = <101>; + reg = <102>; + regulator-name = "+V3.3_AVDD_HDMI"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + gpio = <&pmic 6 GPIO_ACTIVE_HIGH>; + vin-supply = <&sys_3v3_reg>; + }; + + charge_pump_5v0_reg: regulator@103 { + compatible = "regulator-fixed"; + reg = <103>; regulator-name = "5v0"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; -- cgit v0.10.2 From 0f44de6cb8904e9a686188aaa51323280d37e127 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 28 Aug 2015 14:42:30 +0200 Subject: ARM: tegra: apalis: Fix pin muxing Fix pin muxing which got broken due to certain stuff having been fixed or renamed since. Signed-off-by: Marcel Ziswiler Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra30-apalis.dtsi b/arch/arm/boot/dts/tegra30-apalis.dtsi index fd6c94e..84744dc 100644 --- a/arch/arm/boot/dts/tegra30-apalis.dtsi +++ b/arch/arm/boot/dts/tegra30-apalis.dtsi @@ -66,7 +66,7 @@ /* BKL1_PWM_EN#, disable TPS65911 PMIC PWM backlight */ uart3_cts_n_pa1 { nvidia,pins = "uart3_cts_n_pa1"; - nvidia,function = "rsvd1"; + nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; }; @@ -152,32 +152,32 @@ }; /* Apalis PWM1 */ - gpio_pu6 { - nvidia,pins = "gpio_pu6"; + pu6 { + nvidia,pins = "pu6"; nvidia,function = "pwm3"; nvidia,pull = ; nvidia,tristate = ; }; /* Apalis PWM2 */ - gpio_pu5 { - nvidia,pins = "gpio_pu5"; + pu5 { + nvidia,pins = "pu5"; nvidia,function = "pwm2"; nvidia,pull = ; nvidia,tristate = ; }; /* Apalis PWM3 */ - gpio_pu4 { - nvidia,pins = "gpio_pu4"; + pu4 { + nvidia,pins = "pu4"; nvidia,function = "pwm1"; nvidia,pull = ; nvidia,tristate = ; }; /* Apalis PWM4 */ - gpio_pu3 { - nvidia,pins = "gpio_pu3"; + pu3 { + nvidia,pins = "pu3"; nvidia,function = "pwm0"; nvidia,pull = ; nvidia,tristate = ; -- cgit v0.10.2 From 7be74b0594a51a1b0fb1eba1001e7beda6a4b9de Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 28 Aug 2015 14:42:31 +0200 Subject: ARM: tegra: apalis: Add comment concerning eMMC Instead of adding an otherwise unused emmc label just add a comment describing what the SDHCI is routed to. Signed-off-by: Marcel Ziswiler Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra30-apalis.dtsi b/arch/arm/boot/dts/tegra30-apalis.dtsi index 84744dc..d1b24b1 100644 --- a/arch/arm/boot/dts/tegra30-apalis.dtsi +++ b/arch/arm/boot/dts/tegra30-apalis.dtsi @@ -636,6 +636,7 @@ nvidia,sys-clock-req-active-high; }; + /* eMMC */ sdhci@78000600 { status = "okay"; bus-width = <8>; -- cgit v0.10.2 From 4399f40b2bebde152171112253990f1a88abd912 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 28 Aug 2015 14:42:32 +0200 Subject: ARM: tegra: apalis: Add digital audio pin muxing Add Apalis digital audio pin muxing which is e.g. used for HDA operation together with the Realtek HDA codec as found on the Apalis Evaluation board. Signed-off-by: Marcel Ziswiler Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra30-apalis.dtsi b/arch/arm/boot/dts/tegra30-apalis.dtsi index d1b24b1..4a6ca38 100644 --- a/arch/arm/boot/dts/tegra30-apalis.dtsi +++ b/arch/arm/boot/dts/tegra30-apalis.dtsi @@ -109,6 +109,30 @@ nvidia,enable-input = ; }; + /* Apalis Digital Audio */ + clk1_req_pee2 { + nvidia,pins = "clk1_req_pee2"; + nvidia,function = "hda"; + nvidia,pull = ; + nvidia,tristate = ; + }; + clk2_out_pw5 { + nvidia,pins = "clk2_out_pw5"; + nvidia,function = "extperiph2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + dap1_fs_pn0 { + nvidia,pins = "dap1_fs_pn0", + "dap1_din_pn1", + "dap1_dout_pn2", + "dap1_sclk_pn3"; + nvidia,function = "hda"; + nvidia,pull = ; + nvidia,tristate = ; + }; + /* Apalis I2C3 */ cam_i2c_scl_pbb1 { nvidia,pins = "cam_i2c_scl_pbb1", -- cgit v0.10.2 From 40699b926df77ccfe2a85c14ede6ac61e515bb40 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 15 Sep 2015 10:29:57 +0200 Subject: ARM: tegra: apalis: Properly align pin names Align pin names on subsequent lines with the first the name of the first pin in the first line. Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra30-apalis.dtsi b/arch/arm/boot/dts/tegra30-apalis.dtsi index 4a6ca38..bf36127 100644 --- a/arch/arm/boot/dts/tegra30-apalis.dtsi +++ b/arch/arm/boot/dts/tegra30-apalis.dtsi @@ -58,14 +58,14 @@ /* Apalis BKL1_PWM */ uart3_rts_n_pc0 { - nvidia,pins = "uart3_rts_n_pc0"; + nvidia,pins = "uart3_rts_n_pc0"; nvidia,function = "pwm0"; nvidia,pull = ; nvidia,tristate = ; }; /* BKL1_PWM_EN#, disable TPS65911 PMIC PWM backlight */ uart3_cts_n_pa1 { - nvidia,pins = "uart3_cts_n_pa1"; + nvidia,pins = "uart3_cts_n_pa1"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; @@ -73,10 +73,10 @@ /* Apalis CAN1 on SPI6 */ spi2_cs0_n_px3 { - nvidia,pins = "spi2_cs0_n_px3", - "spi2_miso_px1", - "spi2_mosi_px0", - "spi2_sck_px2"; + nvidia,pins = "spi2_cs0_n_px3", + "spi2_miso_px1", + "spi2_mosi_px0", + "spi2_sck_px2"; nvidia,function = "spi6"; nvidia,pull = ; nvidia,tristate = ; @@ -92,10 +92,10 @@ /* Apalis CAN2 on SPI4 */ gmi_a16_pj7 { - nvidia,pins = "gmi_a16_pj7", - "gmi_a17_pb0", - "gmi_a18_pb1", - "gmi_a19_pk7"; + nvidia,pins = "gmi_a16_pj7", + "gmi_a17_pb0", + "gmi_a18_pb1", + "gmi_a19_pk7"; nvidia,function = "spi4"; nvidia,pull = ; nvidia,tristate = ; @@ -111,7 +111,7 @@ /* Apalis Digital Audio */ clk1_req_pee2 { - nvidia,pins = "clk1_req_pee2"; + nvidia,pins = "clk1_req_pee2"; nvidia,function = "hda"; nvidia,pull = ; nvidia,tristate = ; @@ -124,10 +124,10 @@ nvidia,enable-input = ; }; dap1_fs_pn0 { - nvidia,pins = "dap1_fs_pn0", - "dap1_din_pn1", - "dap1_dout_pn2", - "dap1_sclk_pn3"; + nvidia,pins = "dap1_fs_pn0", + "dap1_din_pn1", + "dap1_dout_pn2", + "dap1_sclk_pn3"; nvidia,function = "hda"; nvidia,pull = ; nvidia,tristate = ; @@ -147,21 +147,21 @@ /* Apalis MMC1 */ sdmmc3_clk_pa6 { - nvidia,pins = "sdmmc3_clk_pa6", - "sdmmc3_cmd_pa7"; + nvidia,pins = "sdmmc3_clk_pa6", + "sdmmc3_cmd_pa7"; nvidia,function = "sdmmc3"; nvidia,pull = ; nvidia,tristate = ; }; sdmmc3_dat0_pb7 { - nvidia,pins = "sdmmc3_dat0_pb7", - "sdmmc3_dat1_pb6", - "sdmmc3_dat2_pb5", - "sdmmc3_dat3_pb4", - "sdmmc3_dat4_pd1", - "sdmmc3_dat5_pd0", - "sdmmc3_dat6_pd3", - "sdmmc3_dat7_pd4"; + nvidia,pins = "sdmmc3_dat0_pb7", + "sdmmc3_dat1_pb6", + "sdmmc3_dat2_pb5", + "sdmmc3_dat3_pb4", + "sdmmc3_dat4_pd1", + "sdmmc3_dat5_pd0", + "sdmmc3_dat6_pd3", + "sdmmc3_dat7_pd4"; nvidia,function = "sdmmc3"; nvidia,pull = ; nvidia,tristate = ; @@ -177,7 +177,7 @@ /* Apalis PWM1 */ pu6 { - nvidia,pins = "pu6"; + nvidia,pins = "pu6"; nvidia,function = "pwm3"; nvidia,pull = ; nvidia,tristate = ; @@ -185,7 +185,7 @@ /* Apalis PWM2 */ pu5 { - nvidia,pins = "pu5"; + nvidia,pins = "pu5"; nvidia,function = "pwm2"; nvidia,pull = ; nvidia,tristate = ; @@ -193,7 +193,7 @@ /* Apalis PWM3 */ pu4 { - nvidia,pins = "pu4"; + nvidia,pins = "pu4"; nvidia,function = "pwm1"; nvidia,pull = ; nvidia,tristate = ; @@ -201,7 +201,7 @@ /* Apalis PWM4 */ pu3 { - nvidia,pins = "pu3"; + nvidia,pins = "pu3"; nvidia,function = "pwm0"; nvidia,pull = ; nvidia,tristate = ; @@ -223,11 +223,11 @@ nvidia,tristate = ; }; sdmmc1_cmd_pz1 { - nvidia,pins = "sdmmc1_cmd_pz1", - "sdmmc1_dat0_py7", - "sdmmc1_dat1_py6", - "sdmmc1_dat2_py5", - "sdmmc1_dat3_py4"; + nvidia,pins = "sdmmc1_cmd_pz1", + "sdmmc1_dat0_py7", + "sdmmc1_dat1_py6", + "sdmmc1_dat2_py5", + "sdmmc1_dat3_py4"; nvidia,function = "sdmmc1"; nvidia,pull = ; nvidia,tristate = ; @@ -243,10 +243,10 @@ /* Apalis SPI1 */ spi1_sck_px5 { - nvidia,pins = "spi1_sck_px5", - "spi1_mosi_px4", - "spi1_miso_px7", - "spi1_cs0_n_px6"; + nvidia,pins = "spi1_sck_px5", + "spi1_mosi_px4", + "spi1_miso_px7", + "spi1_cs0_n_px6"; nvidia,function = "spi1"; nvidia,pull = ; nvidia,tristate = ; @@ -254,10 +254,10 @@ /* Apalis SPI2 */ lcd_sck_pz4 { - nvidia,pins = "lcd_sck_pz4", - "lcd_sdout_pn5", - "lcd_sdin_pz2", - "lcd_cs0_n_pn4"; + nvidia,pins = "lcd_sck_pz4", + "lcd_sdout_pn5", + "lcd_sdin_pz2", + "lcd_cs0_n_pn4"; nvidia,function = "spi5"; nvidia,pull = ; nvidia,tristate = ; @@ -265,14 +265,14 @@ /* Apalis UART1 */ ulpi_data0 { - nvidia,pins = "ulpi_data0_po1", - "ulpi_data1_po2", - "ulpi_data2_po3", - "ulpi_data3_po4", - "ulpi_data4_po5", - "ulpi_data5_po6", - "ulpi_data6_po7", - "ulpi_data7_po0"; + nvidia,pins = "ulpi_data0_po1", + "ulpi_data1_po2", + "ulpi_data2_po3", + "ulpi_data3_po4", + "ulpi_data4_po5", + "ulpi_data5_po6", + "ulpi_data6_po7", + "ulpi_data7_po0"; nvidia,function = "uarta"; nvidia,pull = ; nvidia,tristate = ; @@ -280,10 +280,10 @@ /* Apalis UART2 */ ulpi_clk_py0 { - nvidia,pins = "ulpi_clk_py0", - "ulpi_dir_py1", - "ulpi_nxt_py2", - "ulpi_stp_py3"; + nvidia,pins = "ulpi_clk_py0", + "ulpi_dir_py1", + "ulpi_nxt_py2", + "ulpi_stp_py3"; nvidia,function = "uartd"; nvidia,pull = ; nvidia,tristate = ; @@ -291,8 +291,8 @@ /* Apalis UART3 */ uart2_rxd_pc3 { - nvidia,pins = "uart2_rxd_pc3", - "uart2_txd_pc2"; + nvidia,pins = "uart2_rxd_pc3", + "uart2_txd_pc2"; nvidia,function = "uartb"; nvidia,pull = ; nvidia,tristate = ; @@ -300,8 +300,8 @@ /* Apalis UART4 */ uart3_rxd_pw7 { - nvidia,pins = "uart3_rxd_pw7", - "uart3_txd_pw6"; + nvidia,pins = "uart3_rxd_pw7", + "uart3_txd_pw6"; nvidia,function = "uartc"; nvidia,pull = ; nvidia,tristate = ; @@ -337,21 +337,21 @@ /* eMMC (On-module) */ sdmmc4_clk_pcc4 { - nvidia,pins = "sdmmc4_clk_pcc4", - "sdmmc4_rst_n_pcc3"; + nvidia,pins = "sdmmc4_clk_pcc4", + "sdmmc4_rst_n_pcc3"; nvidia,function = "sdmmc4"; nvidia,pull = ; nvidia,tristate = ; }; sdmmc4_dat0_paa0 { - nvidia,pins = "sdmmc4_dat0_paa0", - "sdmmc4_dat1_paa1", - "sdmmc4_dat2_paa2", - "sdmmc4_dat3_paa3", - "sdmmc4_dat4_paa4", - "sdmmc4_dat5_paa5", - "sdmmc4_dat6_paa6", - "sdmmc4_dat7_paa7"; + nvidia,pins = "sdmmc4_dat0_paa0", + "sdmmc4_dat1_paa1", + "sdmmc4_dat2_paa2", + "sdmmc4_dat3_paa3", + "sdmmc4_dat4_paa4", + "sdmmc4_dat5_paa5", + "sdmmc4_dat6_paa6", + "sdmmc4_dat7_paa7"; nvidia,function = "sdmmc4"; nvidia,pull = ; nvidia,tristate = ; @@ -359,10 +359,10 @@ /* LVDS Transceiver Configuration */ pbb0 { - nvidia,pins = "pbb0", - "pbb7", - "pcc1", - "pcc2"; + nvidia,pins = "pbb0", + "pbb7", + "pcc1", + "pcc2"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; @@ -370,10 +370,10 @@ nvidia,lock = ; }; pbb3 { - nvidia,pins = "pbb3", - "pbb4", - "pbb5", - "pbb6"; + nvidia,pins = "pbb3", + "pbb4", + "pbb5", + "pbb6"; nvidia,function = "displayb"; nvidia,pull = ; nvidia,tristate = ; -- cgit v0.10.2 From 26f660d9db98582e28b85a95cd2318ba2dc9df8a Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 28 Aug 2015 14:42:33 +0200 Subject: ARM: tegra: apalis-eval: Enable HDA controller Actually enable HDA now that it should otherwise be supported by the driver and the device tree. Signed-off-by: Marcel Ziswiler Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra30-apalis-eval.dts b/arch/arm/boot/dts/tegra30-apalis-eval.dts index 6236bde..5a49f03 100644 --- a/arch/arm/boot/dts/tegra30-apalis-eval.dts +++ b/arch/arm/boot/dts/tegra30-apalis-eval.dts @@ -126,6 +126,10 @@ }; }; + hda@70030000 { + status = "okay"; + }; + sd1: sdhci@78000000 { status = "okay"; bus-width = <4>; -- cgit v0.10.2 From ea147c8f0e8e5265143f43e602b978ff1859a1b1 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 28 Aug 2015 14:42:34 +0200 Subject: ARM: tegra: apalis-eval: Set OTG dr_mode This has currently no functional effect as neither USB device nor OTG is currently supported on any Tegras in mainline as of yet. However once we use the same device tree on U-Boot this will actually make it work properly there. Signed-off-by: Marcel Ziswiler Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra30-apalis-eval.dts b/arch/arm/boot/dts/tegra30-apalis-eval.dts index 5a49f03..37437c6 100644 --- a/arch/arm/boot/dts/tegra30-apalis-eval.dts +++ b/arch/arm/boot/dts/tegra30-apalis-eval.dts @@ -153,6 +153,7 @@ usb-phy@7d000000 { status = "okay"; + dr_mode = "otg"; vbus-supply = <&usbo1_vbus_reg>; }; -- cgit v0.10.2 From 9ecf78c277ab721f793cccc84312d7f55011b40c Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 28 Aug 2015 14:42:35 +0200 Subject: ARM: tegra: apalis-eval: Fix backlight PWM comment Fix the backlight PWM comment as it is actually called PWM_BKL1 rather than just PWM0. Signed-off-by: Marcel Ziswiler Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra30-apalis-eval.dts b/arch/arm/boot/dts/tegra30-apalis-eval.dts index 37437c6..c832c15 100644 --- a/arch/arm/boot/dts/tegra30-apalis-eval.dts +++ b/arch/arm/boot/dts/tegra30-apalis-eval.dts @@ -180,7 +180,7 @@ backlight: backlight { compatible = "pwm-backlight"; - /* PWM0 */ + /* PWM_BKL1 */ pwms = <&pwm 0 5000000>; brightness-levels = <255 231 223 207 191 159 127 0>; default-brightness-level = <6>; -- cgit v0.10.2 From 21db15df49e9095326ce672209ec47c022105422 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 28 Aug 2015 14:42:36 +0200 Subject: ARM: tegra: apalis-eval: Fix power/wakeup key Rather than a power key, WAKE1_MICO is actually a standard Apalis MXM3 pin used for wake-up purposes which this patch fixes. Signed-off-by: Marcel Ziswiler Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra30-apalis-eval.dts b/arch/arm/boot/dts/tegra30-apalis-eval.dts index c832c15..f2879cf 100644 --- a/arch/arm/boot/dts/tegra30-apalis-eval.dts +++ b/arch/arm/boot/dts/tegra30-apalis-eval.dts @@ -191,10 +191,10 @@ gpio-keys { compatible = "gpio-keys"; - power { - label = "Power"; + wakeup { + label = "WAKE1_MICO"; gpios = <&gpio TEGRA_GPIO(V, 1) GPIO_ACTIVE_LOW>; - linux,code = ; + linux,code = ; debounce-interval = <10>; gpio-key,wakeup; }; -- cgit v0.10.2 From 39ebbf61d4a71dc0f47ac443c9d3fb433b057283 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 28 Aug 2015 17:59:36 +0200 Subject: ARM: tegra: colibri: Update hardware revisions compatibility Update introductory comment about what exact hardware revisions this device tree is compatible with as a hint for our customers. Signed-off-by: Marcel Ziswiler Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra30-colibri.dtsi b/arch/arm/boot/dts/tegra30-colibri.dtsi index c4ed1be..83ba3f2 100644 --- a/arch/arm/boot/dts/tegra30-colibri.dtsi +++ b/arch/arm/boot/dts/tegra30-colibri.dtsi @@ -2,8 +2,8 @@ #include "tegra30.dtsi" /* - * Toradex Colibri T30 Device Tree - * Compatible for Revisions 1.1B/1.1C/1.1D + * Toradex Colibri T30 Module Device Tree + * Compatible for Revisions V1.1B, V1.1C, V1.1D, V1.1E; IT: V1.1A */ / { model = "Toradex Colibri T30"; -- cgit v0.10.2 From 312d373225fb9f05a9b45207087378d236026b4e Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 28 Aug 2015 17:59:37 +0200 Subject: ARM: tegra: colibri: Fix HDMI supplies Fix HDMI supplies (both regular VDD as well as PLL ones) being switched by the TPS65911 PMIC's GPIO6 aka EN_VDD_HDMI by introducing two new GPIO witched fixed regulators avdd_hdmi_pll_1v8_reg and avdd_hdmi_3v3_reg. Signed-off-by: Marcel Ziswiler Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra30-colibri.dtsi b/arch/arm/boot/dts/tegra30-colibri.dtsi index 83ba3f2..5e6a47e 100644 --- a/arch/arm/boot/dts/tegra30-colibri.dtsi +++ b/arch/arm/boot/dts/tegra30-colibri.dtsi @@ -15,8 +15,8 @@ host1x@50000000 { hdmi@54280000 { - vdd-supply = <&sys_3v3_reg>; - pll-supply = <&vio_reg>; + vdd-supply = <&avdd_hdmi_3v3_reg>; + pll-supply = <&avdd_hdmi_pll_1v8_reg>; nvidia,hpd-gpio = <&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>; @@ -365,18 +365,40 @@ #address-cells = <1>; #size-cells = <0>; - sys_3v3_reg: regulator@100 { + avdd_hdmi_pll_1v8_reg: regulator@100 { compatible = "regulator-fixed"; reg = <100>; + regulator-name = "+V1.8_AVDD_HDMI_PLL"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + enable-active-high; + gpio = <&pmic 6 GPIO_ACTIVE_HIGH>; + vin-supply = <&vio_reg>; + }; + + sys_3v3_reg: regulator@101 { + compatible = "regulator-fixed"; + reg = <101>; regulator-name = "3v3"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; }; - charge_pump_5v0_reg: regulator@101 { + avdd_hdmi_3v3_reg: regulator@102 { compatible = "regulator-fixed"; - reg = <101>; + reg = <102>; + regulator-name = "+V3.3_AVDD_HDMI"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + gpio = <&pmic 6 GPIO_ACTIVE_HIGH>; + vin-supply = <&sys_3v3_reg>; + }; + + charge_pump_5v0_reg: regulator@103 { + compatible = "regulator-fixed"; + reg = <103>; regulator-name = "5v0"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; -- cgit v0.10.2 From 62bcaba1ab2fb1a9ce5e6d7540ca5efa609fe480 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 28 Aug 2015 17:59:38 +0200 Subject: ARM: tegra: colibri: Improve comment about thermal alert pin Improve the comment about the THERMD_ALERT# pin which is the unlatched I2C address pin of the LM95245 temperature sensor and therefore requires disabling for now otherwise it won't get detected properly. While at it also move that pin further down to have it alphabetically sorted again. Signed-off-by: Marcel Ziswiler Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra30-colibri.dtsi b/arch/arm/boot/dts/tegra30-colibri.dtsi index 5e6a47e..074123f 100644 --- a/arch/arm/boot/dts/tegra30-colibri.dtsi +++ b/arch/arm/boot/dts/tegra30-colibri.dtsi @@ -66,15 +66,6 @@ nvidia,enable-input = ; }; - /* Thermal alert, need to be disabled */ - lcd_dc1_pd2 { - nvidia,pins = "lcd_dc1_pd2"; - nvidia,function = "rsvd3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - /* Colibri MMC */ kb_row10_ps2 { nvidia,pins = "kb_row10_ps2"; @@ -167,6 +158,19 @@ nvidia,pull = ; nvidia,tristate = ; }; + + /* + * THERMD_ALERT#, unlatched I2C address pin of LM95245 + * temperature sensor therefore requires disabling for + * now + */ + lcd_dc1_pd2 { + nvidia,pins = "lcd_dc1_pd2"; + nvidia,function = "rsvd3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; }; }; -- cgit v0.10.2 From e48f6c0eaac087519f9343297eedc6dc117bb153 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 28 Aug 2015 17:59:39 +0200 Subject: ARM: tegra: colibri: Add pin muxing for on-module power I2C Add pin muxing for the on-module power I2C bus which connects to the PMICs, temperature sensor and touch screen controller. Signed-off-by: Marcel Ziswiler Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra30-colibri.dtsi b/arch/arm/boot/dts/tegra30-colibri.dtsi index 074123f..4ddccfa 100644 --- a/arch/arm/boot/dts/tegra30-colibri.dtsi +++ b/arch/arm/boot/dts/tegra30-colibri.dtsi @@ -159,6 +159,18 @@ nvidia,tristate = ; }; + /* Power I2C (On-module) */ + pwr_i2c_scl_pz6 { + nvidia,pins = "pwr_i2c_scl_pz6", + "pwr_i2c_sda_pz7"; + nvidia,function = "i2cpwr"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,lock = ; + nvidia,open-drain = ; + }; + /* * THERMD_ALERT#, unlatched I2C address pin of LM95245 * temperature sensor therefore requires disabling for -- cgit v0.10.2 From b038e3b916cf5c6f4f27f1fbaa10b657a941be54 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 28 Aug 2015 17:59:40 +0200 Subject: ARM: tegra: colibri: Fix comment about 3v3 fixed supply Fix the comment about the 3v3 fixed supply as the previous v3_3 was bogus. Signed-off-by: Marcel Ziswiler Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra30-colibri.dtsi b/arch/arm/boot/dts/tegra30-colibri.dtsi index 4ddccfa..57335c3 100644 --- a/arch/arm/boot/dts/tegra30-colibri.dtsi +++ b/arch/arm/boot/dts/tegra30-colibri.dtsi @@ -252,7 +252,7 @@ /* * EN_+V3.3 switching via FET: * +V3.3_AUDIO_AVDD_S, +V3.3 and +V1.8_VDD_LAN - * see also v3_3 fixed supply + * see also 3v3 fixed supply */ ldo2_reg: ldo2 { regulator-name = "en_3v3"; -- cgit v0.10.2 From 6456e9c5a27fad0345d2b24ea35ce5562917a352 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 28 Aug 2015 17:59:41 +0200 Subject: ARM: tegra: colibri: Add touch pen interrupt pin muxing Add TOUCH_PEN_INT# pin muxing required for proper STMPE811 touch screen controller operation. Signed-off-by: Marcel Ziswiler Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra30-colibri.dtsi b/arch/arm/boot/dts/tegra30-colibri.dtsi index 57335c3..fba3d2a 100644 --- a/arch/arm/boot/dts/tegra30-colibri.dtsi +++ b/arch/arm/boot/dts/tegra30-colibri.dtsi @@ -183,6 +183,15 @@ nvidia,tristate = ; nvidia,enable-input = ; }; + + /* TOUCH_PEN_INT# */ + pv0 { + nvidia,pins = "pv0"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; }; }; -- cgit v0.10.2 From 737a7c26a8917f4789884f728e66856a5d526556 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 28 Aug 2015 17:59:42 +0200 Subject: ARM: tegra: colibri: Activate STMPE811 touch controller Activate STMPE811 touch controller as found on Colibri T30 modules. Signed-off-by: Marcel Ziswiler Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra30-colibri.dtsi b/arch/arm/boot/dts/tegra30-colibri.dtsi index fba3d2a..5f8ec5c 100644 --- a/arch/arm/boot/dts/tegra30-colibri.dtsi +++ b/arch/arm/boot/dts/tegra30-colibri.dtsi @@ -320,6 +320,46 @@ }; }; + /* STMPE811 touch screen controller */ + stmpe811@41 { + compatible = "st,stmpe811"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x41>; + interrupts = ; + interrupt-parent = <&gpio>; + interrupt-controller; + id = <0>; + blocks = <0x5>; + irq-trigger = <0x1>; + + stmpe_touchscreen { + compatible = "st,stmpe-ts"; + reg = <0>; + /* 3.25 MHz ADC clock speed */ + st,adc-freq = <1>; + /* 8 sample average control */ + st,ave-ctrl = <3>; + /* 7 length fractional part in z */ + st,fraction-z = <7>; + /* + * 50 mA typical 80 mA max touchscreen drivers + * current limit value + */ + st,i-drive = <1>; + /* 12-bit ADC */ + st,mod-12b = <1>; + /* internal ADC reference */ + st,ref-sel = <0>; + /* ADC converstion time: 80 clocks */ + st,sample-time = <4>; + /* 1 ms panel driver settling time */ + st,settling = <3>; + /* 5 ms touch detect interrupt delay */ + st,touch-det-delay = <5>; + }; + }; + /* * LM95245 temperature sensor * Note: OVERT_N directly connected to PMIC PWRDN -- cgit v0.10.2 From 3791d1cc4bb1aa78c1032873a637ceeaf304a704 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 28 Aug 2015 17:59:43 +0200 Subject: ARM: tegra: colibri: Replace eMMC label by comment Rather than a bogus label just add a comment identifying the SDHCI instance connected to the on-module eMMC. Signed-off-by: Marcel Ziswiler Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra30-colibri.dtsi b/arch/arm/boot/dts/tegra30-colibri.dtsi index 5f8ec5c..67ba943 100644 --- a/arch/arm/boot/dts/tegra30-colibri.dtsi +++ b/arch/arm/boot/dts/tegra30-colibri.dtsi @@ -396,7 +396,8 @@ nvidia,sys-clock-req-active-high; }; - emmc: sdhci@78000600 { + /* eMMC */ + sdhci@78000600 { status = "okay"; bus-width = <8>; non-removable; -- cgit v0.10.2 From d5edc4ecc84edc6a336592a39946f44543158cf3 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 15 Sep 2015 10:29:57 +0200 Subject: ARM: tegra: colibri: Properly align pin names Align pin names on subsequent lines with the first the name of the first pin in the first line. Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra30-colibri.dtsi b/arch/arm/boot/dts/tegra30-colibri.dtsi index 67ba943..2d8c58f 100644 --- a/arch/arm/boot/dts/tegra30-colibri.dtsi +++ b/arch/arm/boot/dts/tegra30-colibri.dtsi @@ -39,7 +39,7 @@ /* Colibri Backlight PWM */ sdmmc3_dat3_pb4 { - nvidia,pins = "sdmmc3_dat3_pb4"; + nvidia,pins = "sdmmc3_dat3_pb4"; nvidia,function = "pwm0"; nvidia,pull = ; nvidia,tristate = ; @@ -74,11 +74,11 @@ nvidia,tristate = ; }; kb_row11_ps3 { - nvidia,pins = "kb_row11_ps3", - "kb_row12_ps4", - "kb_row13_ps5", - "kb_row14_ps6", - "kb_row15_ps7"; + nvidia,pins = "kb_row11_ps3", + "kb_row12_ps4", + "kb_row13_ps5", + "kb_row14_ps6", + "kb_row15_ps7"; nvidia,function = "sdmmc2"; nvidia,pull = ; nvidia,tristate = ; @@ -86,17 +86,17 @@ /* Colibri SSP */ ulpi_clk_py0 { - nvidia,pins = "ulpi_clk_py0", - "ulpi_dir_py1", - "ulpi_nxt_py2", - "ulpi_stp_py3"; + nvidia,pins = "ulpi_clk_py0", + "ulpi_dir_py1", + "ulpi_nxt_py2", + "ulpi_stp_py3"; nvidia,function = "spi1"; nvidia,pull = ; nvidia,tristate = ; }; sdmmc3_dat6_pd3 { - nvidia,pins = "sdmmc3_dat6_pd3", - "sdmmc3_dat7_pd4"; + nvidia,pins = "sdmmc3_dat6_pd3", + "sdmmc3_dat7_pd4"; nvidia,function = "spdif"; nvidia,pull = ; nvidia,tristate = ; @@ -104,14 +104,14 @@ /* Colibri UART_A */ ulpi_data0 { - nvidia,pins = "ulpi_data0_po1", - "ulpi_data1_po2", - "ulpi_data2_po3", - "ulpi_data3_po4", - "ulpi_data4_po5", - "ulpi_data5_po6", - "ulpi_data6_po7", - "ulpi_data7_po0"; + nvidia,pins = "ulpi_data0_po1", + "ulpi_data1_po2", + "ulpi_data2_po3", + "ulpi_data3_po4", + "ulpi_data4_po5", + "ulpi_data5_po6", + "ulpi_data6_po7", + "ulpi_data7_po0"; nvidia,function = "uarta"; nvidia,pull = ; nvidia,tristate = ; @@ -119,10 +119,10 @@ /* Colibri UART_B */ gmi_a16_pj7 { - nvidia,pins = "gmi_a16_pj7", - "gmi_a17_pb0", - "gmi_a18_pb1", - "gmi_a19_pk7"; + nvidia,pins = "gmi_a16_pj7", + "gmi_a17_pb0", + "gmi_a18_pb1", + "gmi_a19_pk7"; nvidia,function = "uartd"; nvidia,pull = ; nvidia,tristate = ; @@ -130,8 +130,8 @@ /* Colibri UART_C */ uart2_rxd { - nvidia,pins = "uart2_rxd_pc3", - "uart2_txd_pc2"; + nvidia,pins = "uart2_rxd_pc3", + "uart2_txd_pc2"; nvidia,function = "uartb"; nvidia,pull = ; nvidia,tristate = ; @@ -139,21 +139,21 @@ /* eMMC */ sdmmc4_clk_pcc4 { - nvidia,pins = "sdmmc4_clk_pcc4", - "sdmmc4_rst_n_pcc3"; + nvidia,pins = "sdmmc4_clk_pcc4", + "sdmmc4_rst_n_pcc3"; nvidia,function = "sdmmc4"; nvidia,pull = ; nvidia,tristate = ; }; sdmmc4_dat0_paa0 { - nvidia,pins = "sdmmc4_dat0_paa0", - "sdmmc4_dat1_paa1", - "sdmmc4_dat2_paa2", - "sdmmc4_dat3_paa3", - "sdmmc4_dat4_paa4", - "sdmmc4_dat5_paa5", - "sdmmc4_dat6_paa6", - "sdmmc4_dat7_paa7"; + nvidia,pins = "sdmmc4_dat0_paa0", + "sdmmc4_dat1_paa1", + "sdmmc4_dat2_paa2", + "sdmmc4_dat3_paa3", + "sdmmc4_dat4_paa4", + "sdmmc4_dat5_paa5", + "sdmmc4_dat6_paa6", + "sdmmc4_dat7_paa7"; nvidia,function = "sdmmc4"; nvidia,pull = ; nvidia,tristate = ; -- cgit v0.10.2 From e4212ffa41361aae7824844609ea4ac9f78513d8 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 28 Aug 2015 17:59:44 +0200 Subject: ARM: tegra: colibri-eval: Fix vendor string of M41T0M6 RTC Fix compatible vendor string of M41T0M6 real time clock as found on the Colibri Evaluation board. Signed-off-by: Marcel Ziswiler Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts b/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts index 4d3ddc5..46a7c2d 100644 --- a/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts +++ b/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts @@ -55,7 +55,7 @@ /* M41T0M6 real time clock on carrier board */ rtc@68 { - compatible = "stm,m41t00"; + compatible = "st,m41t00"; reg = <0x68>; }; }; -- cgit v0.10.2 From ccb43161b0bde0d22692dbfb34383f2c0228abc3 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 28 Aug 2015 17:59:45 +0200 Subject: ARM: tegra: colibri-eval: Add comment concerning SD/MMC Instead of adding an otherwise unused sdmmc label just add a comment. Signed-off-by: Marcel Ziswiler Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts b/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts index 46a7c2d..a6c98b1 100644 --- a/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts +++ b/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts @@ -84,6 +84,7 @@ }; }; + /* SD/MMC */ sdhci@78000200 { status = "okay"; bus-width = <4>; -- cgit v0.10.2 From 3f5331324f187b3dc7634c4fb4351f7bd36fad21 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 28 Aug 2015 17:59:46 +0200 Subject: ARM: tegra: colibri-eval: Fix power/wakeup key Rather than a power key SODIMM pin 45 is actually used for wake-up purposes which this patch fixes. Signed-off-by: Marcel Ziswiler Signed-off-by: Thierry Reding diff --git a/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts b/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts index a6c98b1..3ff019f 100644 --- a/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts +++ b/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts @@ -137,10 +137,10 @@ gpio-keys { compatible = "gpio-keys"; - power { - label = "Power"; + wakeup { + label = "SODIMM pin 45 wakeup"; gpios = <&gpio TEGRA_GPIO(V, 1) GPIO_ACTIVE_HIGH>; - linux,code = ; + linux,code = ; debounce-interval = <10>; gpio-key,wakeup; }; -- cgit v0.10.2 From 3f3d0d00734de56a0c5996f4e4433046c745592e Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 6 Jun 2015 21:41:09 +0100 Subject: drm/i2c: tda998x: remove useless NULL checks There is no way 'priv' can be NULL in tda998x_irq_thread() - this can only happen if request_threaded_irq() was passed a NULL priv pointer, and we would have crashed long before then if that was the case. We also always ensure that priv->encoder is correctly setup, which must have been initialised prior to the interrupt being claimed, so we can remove this check as well. Signed-off-by: Russell King diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 424228b..d8e9708 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -558,7 +558,7 @@ static void tda998x_hpd(struct work_struct *work) struct tda998x_priv *priv = container_of(dwork, struct tda998x_priv, dwork); - if (priv->encoder && priv->encoder->dev) + if (priv->encoder->dev) drm_kms_helper_hotplug_event(priv->encoder->dev); } @@ -570,8 +570,6 @@ static irqreturn_t tda998x_irq_thread(int irq, void *data) struct tda998x_priv *priv = data; u8 sta, cec, lvl, flag0, flag1, flag2; - if (!priv) - return IRQ_HANDLED; sta = cec_read(priv, REG_CEC_INTSTATUS); cec = cec_read(priv, REG_CEC_RXSHPDINT); lvl = cec_read(priv, REG_CEC_RXSHPDLEV); -- cgit v0.10.2 From f84a97d4804a09240372dc7b195f9d6162152228 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 6 Jun 2015 21:41:09 +0100 Subject: drm/i2c: tda998x: report whether we actually handled the IRQ Rather than always reporting that the interrupt was handled, we should report whether we did handle the interrupt. Arrange to report IRQ_NONE for cases where we found nothing to do. This allows us to (eventually) recover from stuck-IRQ problems, rather than causing the kernel to solidly lock up. Signed-off-by: Russell King diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index d8e9708..ad3ce34 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -569,6 +569,7 @@ static irqreturn_t tda998x_irq_thread(int irq, void *data) { struct tda998x_priv *priv = data; u8 sta, cec, lvl, flag0, flag1, flag2; + bool handled = false; sta = cec_read(priv, REG_CEC_INTSTATUS); cec = cec_read(priv, REG_CEC_RXSHPDINT); @@ -582,10 +583,12 @@ static irqreturn_t tda998x_irq_thread(int irq, void *data) if ((flag2 & INT_FLAGS_2_EDID_BLK_RD) && priv->wq_edid_wait) { priv->wq_edid_wait = 0; wake_up(&priv->wq_edid); + handled = true; } else if (cec != 0) { /* HPD change */ schedule_delayed_work(&priv->dwork, HZ/10); + handled = true; } - return IRQ_HANDLED; + return IRQ_RETVAL(handled); } static uint8_t tda998x_cksum(uint8_t *buf, size_t bytes) -- cgit v0.10.2 From 0fc6f44d9683c61678da4b0eebc89e8fa624de39 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 6 Jun 2015 21:41:09 +0100 Subject: drm/i2c: tda998x: re-implement "Fix EDID read timeout on HDMI connect" Commit 6833d26ef823 ("drm: tda998x: Fix EDID read timeout on HDMI connect") used a weak scheme to try and delay reading EDID on a HDMI connect event. It is weak because delaying the notification of a hotplug event does not stop userspace from trying to read the EDID within the 100ms delay. The solution provided here solves this issue: * When a HDMI connection event is detected, mark a blocking flag for EDID reads, and start a timer for the delay. * If an EDID read is attempted, and the blocking flag is set, wait for the blocking flag to clear. * When the timer expires, clear the blocking flag and wake any thread waiting for the EDID read. Signed-off-by: Russell King diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index ad3ce34..a53696f 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -34,7 +34,6 @@ struct tda998x_priv { struct i2c_client *cec; struct i2c_client *hdmi; struct mutex mutex; - struct delayed_work dwork; uint16_t rev; uint8_t current_page; int dpms; @@ -47,6 +46,11 @@ struct tda998x_priv { wait_queue_head_t wq_edid; volatile int wq_edid_wait; struct drm_encoder *encoder; + + struct work_struct detect_work; + struct timer_list edid_delay_timer; + wait_queue_head_t edid_delay_waitq; + bool edid_delay_active; }; #define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv) @@ -551,15 +555,50 @@ tda998x_reset(struct tda998x_priv *priv) reg_write(priv, REG_MUX_VP_VIP_OUT, 0x24); } -/* handle HDMI connect/disconnect */ -static void tda998x_hpd(struct work_struct *work) +/* + * The TDA998x has a problem when trying to read the EDID close to a + * HPD assertion: it needs a delay of 100ms to avoid timing out while + * trying to read EDID data. + * + * However, tda998x_encoder_get_modes() may be called at any moment + * after tda998x_encoder_detect() indicates that we are connected, so + * we need to delay probing modes in tda998x_encoder_get_modes() after + * we have seen a HPD inactive->active transition. This code implements + * that delay. + */ +static void tda998x_edid_delay_done(unsigned long data) +{ + struct tda998x_priv *priv = (struct tda998x_priv *)data; + + priv->edid_delay_active = false; + wake_up(&priv->edid_delay_waitq); + schedule_work(&priv->detect_work); +} + +static void tda998x_edid_delay_start(struct tda998x_priv *priv) +{ + priv->edid_delay_active = true; + mod_timer(&priv->edid_delay_timer, jiffies + HZ/10); +} + +static int tda998x_edid_delay_wait(struct tda998x_priv *priv) +{ + return wait_event_killable(priv->edid_delay_waitq, !priv->edid_delay_active); +} + +/* + * We need to run the KMS hotplug event helper outside of our threaded + * interrupt routine as this can call back into our get_modes method, + * which will want to make use of interrupts. + */ +static void tda998x_detect_work(struct work_struct *work) { - struct delayed_work *dwork = to_delayed_work(work); struct tda998x_priv *priv = - container_of(dwork, struct tda998x_priv, dwork); + container_of(work, struct tda998x_priv, detect_work); + struct drm_device *dev = priv->encoder->dev; - if (priv->encoder->dev) - drm_kms_helper_hotplug_event(priv->encoder->dev); + if (dev) + drm_kms_helper_hotplug_event(dev); } /* @@ -585,7 +624,11 @@ static irqreturn_t tda998x_irq_thread(int irq, void *data) wake_up(&priv->wq_edid); handled = true; } else if (cec != 0) { /* HPD change */ - schedule_delayed_work(&priv->dwork, HZ/10); + if (lvl & CEC_RXSHPDLEV_HPD) + tda998x_edid_delay_start(priv); + else + schedule_work(&priv->detect_work); + handled = true; } return IRQ_RETVAL(handled); @@ -1103,6 +1146,14 @@ tda998x_encoder_get_modes(struct tda998x_priv *priv, struct edid *edid; int n; + /* + * If we get killed while waiting for the HPD timeout, return + * no modes found: we are not in a restartable path, so we + * can't handle signals gracefully. + */ + if (tda998x_edid_delay_wait(priv)) + return 0; + if (priv->rev == TDA19988) reg_clear(priv, REG_TX4, TX4_PD_RAM); @@ -1149,10 +1200,12 @@ static void tda998x_destroy(struct tda998x_priv *priv) /* disable all IRQs and free the IRQ handler */ cec_write(priv, REG_CEC_RXSHPDINTENA, 0); reg_clear(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD); - if (priv->hdmi->irq) { + + if (priv->hdmi->irq) free_irq(priv->hdmi->irq, priv); - cancel_delayed_work_sync(&priv->dwork); - } + + del_timer_sync(&priv->edid_delay_timer); + cancel_work_sync(&priv->detect_work); i2c_unregister_device(priv->cec); } @@ -1253,6 +1306,10 @@ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv) priv->dpms = DRM_MODE_DPMS_OFF; mutex_init(&priv->mutex); /* protect the page access */ + init_waitqueue_head(&priv->edid_delay_waitq); + setup_timer(&priv->edid_delay_timer, tda998x_edid_delay_done, + (unsigned long)priv); + INIT_WORK(&priv->detect_work, tda998x_detect_work); /* wake up the device: */ cec_write(priv, REG_CEC_ENAMODS, @@ -1311,7 +1368,6 @@ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv) /* init read EDID waitqueue and HDP work */ init_waitqueue_head(&priv->wq_edid); - INIT_DELAYED_WORK(&priv->dwork, tda998x_hpd); /* clear pending interrupts */ reg_read(priv, REG_INT_FLAGS_0); -- cgit v0.10.2 From e66e03abf80f701da60ae085cbb913e67ce6741d Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 6 Jun 2015 21:41:10 +0100 Subject: drm/i2c: tda998x: convert to u8/u16/u32 types C99 types are against the style of the Linux kernel. Convert to using Linus-friendly types. See https://lwn.net/Articles/113367/ for more information. Signed-off-by: Russell King diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index a53696f..6d6aaad 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -34,8 +34,8 @@ struct tda998x_priv { struct i2c_client *cec; struct i2c_client *hdmi; struct mutex mutex; - uint16_t rev; - uint8_t current_page; + u16 rev; + u8 current_page; int dpms; bool is_hdmi_sink; u8 vip_cntrl_0; @@ -349,10 +349,10 @@ struct tda998x_priv { #define TDA19988 0x0301 static void -cec_write(struct tda998x_priv *priv, uint16_t addr, uint8_t val) +cec_write(struct tda998x_priv *priv, u16 addr, u8 val) { struct i2c_client *client = priv->cec; - uint8_t buf[] = {addr, val}; + u8 buf[] = {addr, val}; int ret; ret = i2c_master_send(client, buf, sizeof(buf)); @@ -360,11 +360,11 @@ cec_write(struct tda998x_priv *priv, uint16_t addr, uint8_t val) dev_err(&client->dev, "Error %d writing to cec:0x%x\n", ret, addr); } -static uint8_t -cec_read(struct tda998x_priv *priv, uint8_t addr) +static u8 +cec_read(struct tda998x_priv *priv, u8 addr) { struct i2c_client *client = priv->cec; - uint8_t val; + u8 val; int ret; ret = i2c_master_send(client, &addr, sizeof(addr)); @@ -383,11 +383,11 @@ fail: } static int -set_page(struct tda998x_priv *priv, uint16_t reg) +set_page(struct tda998x_priv *priv, u16 reg) { if (REG2PAGE(reg) != priv->current_page) { struct i2c_client *client = priv->hdmi; - uint8_t buf[] = { + u8 buf[] = { REG_CURPAGE, REG2PAGE(reg) }; int ret = i2c_master_send(client, buf, sizeof(buf)); @@ -403,10 +403,10 @@ set_page(struct tda998x_priv *priv, uint16_t reg) } static int -reg_read_range(struct tda998x_priv *priv, uint16_t reg, char *buf, int cnt) +reg_read_range(struct tda998x_priv *priv, u16 reg, char *buf, int cnt) { struct i2c_client *client = priv->hdmi; - uint8_t addr = REG2ADDR(reg); + u8 addr = REG2ADDR(reg); int ret; mutex_lock(&priv->mutex); @@ -432,10 +432,10 @@ out: } static void -reg_write_range(struct tda998x_priv *priv, uint16_t reg, uint8_t *p, int cnt) +reg_write_range(struct tda998x_priv *priv, u16 reg, u8 *p, int cnt) { struct i2c_client *client = priv->hdmi; - uint8_t buf[cnt+1]; + u8 buf[cnt+1]; int ret; buf[0] = REG2ADDR(reg); @@ -454,9 +454,9 @@ out: } static int -reg_read(struct tda998x_priv *priv, uint16_t reg) +reg_read(struct tda998x_priv *priv, u16 reg) { - uint8_t val = 0; + u8 val = 0; int ret; ret = reg_read_range(priv, reg, &val, sizeof(val)); @@ -466,10 +466,10 @@ reg_read(struct tda998x_priv *priv, uint16_t reg) } static void -reg_write(struct tda998x_priv *priv, uint16_t reg, uint8_t val) +reg_write(struct tda998x_priv *priv, u16 reg, u8 val) { struct i2c_client *client = priv->hdmi; - uint8_t buf[] = {REG2ADDR(reg), val}; + u8 buf[] = {REG2ADDR(reg), val}; int ret; mutex_lock(&priv->mutex); @@ -485,10 +485,10 @@ out: } static void -reg_write16(struct tda998x_priv *priv, uint16_t reg, uint16_t val) +reg_write16(struct tda998x_priv *priv, u16 reg, u16 val) { struct i2c_client *client = priv->hdmi; - uint8_t buf[] = {REG2ADDR(reg), val >> 8, val}; + u8 buf[] = {REG2ADDR(reg), val >> 8, val}; int ret; mutex_lock(&priv->mutex); @@ -504,7 +504,7 @@ out: } static void -reg_set(struct tda998x_priv *priv, uint16_t reg, uint8_t val) +reg_set(struct tda998x_priv *priv, u16 reg, u8 val) { int old_val; @@ -514,7 +514,7 @@ reg_set(struct tda998x_priv *priv, uint16_t reg, uint8_t val) } static void -reg_clear(struct tda998x_priv *priv, uint16_t reg, uint8_t val) +reg_clear(struct tda998x_priv *priv, u16 reg, u8 val) { int old_val; @@ -634,7 +634,7 @@ static irqreturn_t tda998x_irq_thread(int irq, void *data) return IRQ_RETVAL(handled); } -static uint8_t tda998x_cksum(uint8_t *buf, size_t bytes) +static u8 tda998x_cksum(u8 *buf, size_t bytes) { int sum = 0; @@ -647,8 +647,8 @@ static uint8_t tda998x_cksum(uint8_t *buf, size_t bytes) #define PB(x) (HB(2) + 1 + (x)) static void -tda998x_write_if(struct tda998x_priv *priv, uint8_t bit, uint16_t addr, - uint8_t *buf, size_t size) +tda998x_write_if(struct tda998x_priv *priv, u8 bit, u16 addr, + u8 *buf, size_t size) { reg_clear(priv, REG_DIP_IF_FLAGS, bit); reg_write_range(priv, addr, buf, size); @@ -711,8 +711,8 @@ static void tda998x_configure_audio(struct tda998x_priv *priv, struct drm_display_mode *mode, struct tda998x_encoder_params *p) { - uint8_t buf[6], clksel_aip, clksel_fs, cts_n, adiv; - uint32_t n; + u8 buf[6], clksel_aip, clksel_fs, cts_n, adiv; + u32 n; /* Enable audio ports */ reg_write(priv, REG_ENA_AP, p->audio_cfg); @@ -888,14 +888,14 @@ tda998x_encoder_mode_set(struct tda998x_priv *priv, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { - uint16_t ref_pix, ref_line, n_pix, n_line; - uint16_t hs_pix_s, hs_pix_e; - uint16_t vs1_pix_s, vs1_pix_e, vs1_line_s, vs1_line_e; - uint16_t vs2_pix_s, vs2_pix_e, vs2_line_s, vs2_line_e; - uint16_t vwin1_line_s, vwin1_line_e; - uint16_t vwin2_line_s, vwin2_line_e; - uint16_t de_pix_s, de_pix_e; - uint8_t reg, div, rep; + u16 ref_pix, ref_line, n_pix, n_line; + u16 hs_pix_s, hs_pix_e; + u16 vs1_pix_s, vs1_pix_e, vs1_line_s, vs1_line_e; + u16 vs2_pix_s, vs2_pix_e, vs2_line_s, vs2_line_e; + u16 vwin1_line_s, vwin1_line_e; + u16 vwin2_line_s, vwin2_line_e; + u16 de_pix_s, de_pix_e; + u8 reg, div, rep; /* * Internally TDA998x is using ITU-R BT.656 style sync but @@ -1077,7 +1077,7 @@ tda998x_encoder_mode_set(struct tda998x_priv *priv, static enum drm_connector_status tda998x_encoder_detect(struct tda998x_priv *priv) { - uint8_t val = cec_read(priv, REG_CEC_RXSHPDLEV); + u8 val = cec_read(priv, REG_CEC_RXSHPDLEV); return (val & CEC_RXSHPDLEV_HPD) ? connector_status_connected : connector_status_disconnected; @@ -1086,7 +1086,7 @@ tda998x_encoder_detect(struct tda998x_priv *priv) static int read_edid_block(void *data, u8 *buf, unsigned int blk, size_t length) { struct tda998x_priv *priv = data; - uint8_t offset, segptr; + u8 offset, segptr; int ret, i; offset = (blk & 1) ? 128 : 0; @@ -1558,7 +1558,7 @@ static int tda998x_bind(struct device *dev, struct device *master, void *data) struct i2c_client *client = to_i2c_client(dev); struct drm_device *drm = data; struct tda998x_priv2 *priv; - uint32_t crtcs = 0; + u32 crtcs = 0; int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -- cgit v0.10.2 From ec5d3e83d332ac5dfde8e0a1f57393fc91d55030 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 6 Jun 2015 21:41:10 +0100 Subject: drm/i2c: tda998x: handle all outstanding interrupts As reading the interrupt registers clears the outstanding interrupts, we must process all received interrupts to avoid dropping any. Rearrange the code to achieve this, and properly check for a HPD interrupt from the CEC_RXSHPDINT register. Signed-off-by: Russell King diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 6d6aaad..1285fb3 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -330,6 +330,8 @@ struct tda998x_priv { # define CEC_FRO_IM_CLK_CTRL_FRO_DIV (1 << 0) #define REG_CEC_RXSHPDINTENA 0xfc /* read/write */ #define REG_CEC_RXSHPDINT 0xfd /* read */ +# define CEC_RXSHPDINT_RXSENS BIT(0) +# define CEC_RXSHPDINT_HPD BIT(1) #define REG_CEC_RXSHPDLEV 0xfe /* read */ # define CEC_RXSHPDLEV_RXSENS (1 << 0) # define CEC_RXSHPDLEV_HPD (1 << 1) @@ -619,11 +621,8 @@ static irqreturn_t tda998x_irq_thread(int irq, void *data) DRM_DEBUG_DRIVER( "tda irq sta %02x cec %02x lvl %02x f0 %02x f1 %02x f2 %02x\n", sta, cec, lvl, flag0, flag1, flag2); - if ((flag2 & INT_FLAGS_2_EDID_BLK_RD) && priv->wq_edid_wait) { - priv->wq_edid_wait = 0; - wake_up(&priv->wq_edid); - handled = true; - } else if (cec != 0) { /* HPD change */ + + if (cec & CEC_RXSHPDINT_HPD) { if (lvl & CEC_RXSHPDLEV_HPD) tda998x_edid_delay_start(priv); else @@ -631,6 +630,13 @@ static irqreturn_t tda998x_irq_thread(int irq, void *data) handled = true; } + + if ((flag2 & INT_FLAGS_2_EDID_BLK_RD) && priv->wq_edid_wait) { + priv->wq_edid_wait = 0; + wake_up(&priv->wq_edid); + handled = true; + } + return IRQ_RETVAL(handled); } -- cgit v0.10.2 From 96795df15c89ce30261a31289740b4621bcec0fe Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 6 Aug 2015 10:52:05 +0100 Subject: drm/i2c: tda998x: use more HDMI helpers Signed-off-by: Russell King diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 1285fb3..1c6fc24 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -640,66 +640,57 @@ static irqreturn_t tda998x_irq_thread(int irq, void *data) return IRQ_RETVAL(handled); } -static u8 tda998x_cksum(u8 *buf, size_t bytes) -{ - int sum = 0; - - while (bytes--) - sum -= *buf++; - return sum; -} - -#define HB(x) (x) -#define PB(x) (HB(2) + 1 + (x)) - static void tda998x_write_if(struct tda998x_priv *priv, u8 bit, u16 addr, - u8 *buf, size_t size) + union hdmi_infoframe *frame) { + u8 buf[32]; + ssize_t len; + + len = hdmi_infoframe_pack(frame, buf, sizeof(buf)); + if (len < 0) { + dev_err(&priv->hdmi->dev, + "hdmi_infoframe_pack() type=0x%02x failed: %zd\n", + frame->any.type, len); + return; + } + reg_clear(priv, REG_DIP_IF_FLAGS, bit); - reg_write_range(priv, addr, buf, size); + reg_write_range(priv, addr, buf, len); reg_set(priv, REG_DIP_IF_FLAGS, bit); } static void tda998x_write_aif(struct tda998x_priv *priv, struct tda998x_encoder_params *p) { - u8 buf[PB(HDMI_AUDIO_INFOFRAME_SIZE) + 1]; + union hdmi_infoframe frame; + + hdmi_audio_infoframe_init(&frame.audio); - memset(buf, 0, sizeof(buf)); - buf[HB(0)] = HDMI_INFOFRAME_TYPE_AUDIO; - buf[HB(1)] = 0x01; - buf[HB(2)] = HDMI_AUDIO_INFOFRAME_SIZE; - buf[PB(1)] = p->audio_frame[1] & 0x07; /* CC */ - buf[PB(2)] = p->audio_frame[2] & 0x1c; /* SF */ - buf[PB(4)] = p->audio_frame[4]; - buf[PB(5)] = p->audio_frame[5] & 0xf8; /* DM_INH + LSV */ + frame.audio.channels = p->audio_frame[1] & 0x07; + frame.audio.channel_allocation = p->audio_frame[4]; + frame.audio.level_shift_value = (p->audio_frame[5] & 0x78) >> 3; + frame.audio.downmix_inhibit = (p->audio_frame[5] & 0x80) >> 7; - buf[PB(0)] = tda998x_cksum(buf, sizeof(buf)); + /* + * L-PCM and IEC61937 compressed audio shall always set sample + * frequency to "refer to stream". For others, see the HDMI + * specification. + */ + frame.audio.sample_frequency = (p->audio_frame[2] & 0x1c) >> 2; - tda998x_write_if(priv, DIP_IF_FLAGS_IF4, REG_IF4_HB0, buf, - sizeof(buf)); + tda998x_write_if(priv, DIP_IF_FLAGS_IF4, REG_IF4_HB0, &frame); } static void tda998x_write_avi(struct tda998x_priv *priv, struct drm_display_mode *mode) { - struct hdmi_avi_infoframe frame; - u8 buf[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; - ssize_t len; - - drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); + union hdmi_infoframe frame; - frame.quantization_range = HDMI_QUANTIZATION_RANGE_FULL; - - len = hdmi_avi_infoframe_pack(&frame, buf, sizeof(buf)); - if (len < 0) { - dev_err(&priv->hdmi->dev, - "hdmi_avi_infoframe_pack() failed: %zd\n", len); - return; - } + drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode); + frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_FULL; - tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, buf, len); + tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, &frame); } static void tda998x_audio_mute(struct tda998x_priv *priv, bool on) -- cgit v0.10.2 From 0fb2970b4b6bfc26817a731b8bc29a9bf9177c20 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 6 Jun 2015 21:46:53 +0100 Subject: drm/armada: remove non-component support Now that the transition of TDA998x to the component helpers is complete, remove the non-componentised support from the Armada DRM driver. All outputs are expected to use the component helpers from now on. Signed-off-by: Russell King diff --git a/drivers/gpu/drm/armada/Kconfig b/drivers/gpu/drm/armada/Kconfig index 50ae88a..eb773e9 100644 --- a/drivers/gpu/drm/armada/Kconfig +++ b/drivers/gpu/drm/armada/Kconfig @@ -14,12 +14,3 @@ config DRM_ARMADA This driver provides no built-in acceleration; acceleration is performed by other IP found on the SoC. This driver provides kernel mode setting and buffer management to userspace. - -config DRM_ARMADA_TDA1998X - bool "Support TDA1998X HDMI output" - depends on DRM_ARMADA != n - depends on I2C && DRM_I2C_NXP_TDA998X = y - default y - help - Support the TDA1998x HDMI output device found on the Solid-Run - CuBox. diff --git a/drivers/gpu/drm/armada/Makefile b/drivers/gpu/drm/armada/Makefile index d6f43e0..ffd6736 100644 --- a/drivers/gpu/drm/armada/Makefile +++ b/drivers/gpu/drm/armada/Makefile @@ -1,6 +1,5 @@ armada-y := armada_crtc.o armada_drv.o armada_fb.o armada_fbdev.o \ - armada_gem.o armada_output.o armada_overlay.o \ - armada_slave.o + armada_gem.o armada_overlay.o armada-y += armada_510.o armada-$(CONFIG_DEBUG_FS) += armada_debugfs.o diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 01ffe9b..c7374a3 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -1044,7 +1044,7 @@ static int armada_drm_crtc_create_properties(struct drm_device *dev) return 0; } -int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, +static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, struct resource *res, int irq, const struct armada_variant *variant, struct device_node *port) { diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h index 98102a5..a13469f 100644 --- a/drivers/gpu/drm/armada/armada_crtc.h +++ b/drivers/gpu/drm/armada/armada_crtc.h @@ -75,10 +75,6 @@ struct armada_crtc { }; #define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc) -struct device_node; -int armada_drm_crtc_create(struct drm_device *, struct device *, - struct resource *, int, const struct armada_variant *, - struct device_node *); void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int); void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int); void armada_drm_crtc_disable_irq(struct armada_crtc *, u32); diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index 225034b..b373cf9 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -18,47 +18,6 @@ #include #include "armada_ioctlP.h" -#ifdef CONFIG_DRM_ARMADA_TDA1998X -#include -#include "armada_slave.h" - -static struct tda998x_encoder_params params = { - /* With 0x24, there is no translation between vp_out and int_vp - FB LCD out Pins VIP Int Vp - R:23:16 R:7:0 VPC7:0 7:0 7:0[R] - G:15:8 G:15:8 VPB7:0 23:16 23:16[G] - B:7:0 B:23:16 VPA7:0 15:8 15:8[B] - */ - .swap_a = 2, - .swap_b = 3, - .swap_c = 4, - .swap_d = 5, - .swap_e = 0, - .swap_f = 1, - .audio_cfg = BIT(2), - .audio_frame[1] = 1, - .audio_format = AFMT_SPDIF, - .audio_sample_rate = 44100, -}; - -static const struct armada_drm_slave_config tda19988_config = { - .i2c_adapter_id = 0, - .crtcs = 1 << 0, /* Only LCD0 at the moment */ - .polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT, - .interlace_allowed = true, - .info = { - .type = "tda998x", - .addr = 0x70, - .platform_data = ¶ms, - }, -}; -#endif - -static bool is_componentized(struct device *dev) -{ - return dev->of_node || dev->platform_data; -} - static void armada_drm_unref_work(struct work_struct *work) { struct armada_private *priv = @@ -91,16 +50,11 @@ void armada_drm_queue_unref_work(struct drm_device *dev, static int armada_drm_load(struct drm_device *dev, unsigned long flags) { - const struct platform_device_id *id; - const struct armada_variant *variant; struct armada_private *priv; - struct resource *res[ARRAY_SIZE(priv->dcrtc)]; struct resource *mem = NULL; - int ret, n, i; + int ret, n; - memset(res, 0, sizeof(res)); - - for (n = i = 0; ; n++) { + for (n = 0; ; n++) { struct resource *r = platform_get_resource(dev->platformdev, IORESOURCE_MEM, n); if (!r) @@ -109,8 +63,6 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags) /* Resources above 64K are graphics memory */ if (resource_size(r) > SZ_64K) mem = r; - else if (i < ARRAY_SIZE(priv->dcrtc)) - res[i++] = r; else return -EINVAL; } @@ -131,13 +83,6 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags) platform_set_drvdata(dev->platformdev, dev); dev->dev_private = priv; - /* Get the implementation specific driver data. */ - id = platform_get_device_id(dev->platformdev); - if (!id) - return -ENXIO; - - variant = (const struct armada_variant *)id->driver_data; - INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work); INIT_KFIFO(priv->fb_unref); @@ -157,34 +102,9 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags) dev->mode_config.funcs = &armada_drm_mode_config_funcs; drm_mm_init(&priv->linear, mem->start, resource_size(mem)); - /* Create all LCD controllers */ - for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) { - int irq; - - if (!res[n]) - break; - - irq = platform_get_irq(dev->platformdev, n); - if (irq < 0) - goto err_kms; - - ret = armada_drm_crtc_create(dev, dev->dev, res[n], irq, - variant, NULL); - if (ret) - goto err_kms; - } - - if (is_componentized(dev->dev)) { - ret = component_bind_all(dev->dev, dev); - if (ret) - goto err_kms; - } else { -#ifdef CONFIG_DRM_ARMADA_TDA1998X - ret = armada_drm_connector_slave_create(dev, &tda19988_config); - if (ret) - goto err_kms; -#endif - } + ret = component_bind_all(dev->dev, dev); + if (ret) + goto err_kms; ret = drm_vblank_init(dev, dev->mode_config.num_crtc); if (ret) @@ -202,8 +122,7 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags) return 0; err_comp: - if (is_componentized(dev->dev)) - component_unbind_all(dev->dev, dev); + component_unbind_all(dev->dev, dev); err_kms: drm_mode_config_cleanup(dev); drm_mm_takedown(&priv->linear); @@ -219,8 +138,7 @@ static int armada_drm_unload(struct drm_device *dev) drm_kms_helper_poll_fini(dev); armada_fbdev_fini(dev); - if (is_componentized(dev->dev)) - component_unbind_all(dev->dev, dev); + component_unbind_all(dev->dev, dev); drm_mode_config_cleanup(dev); drm_mm_takedown(&priv->linear); @@ -435,37 +353,28 @@ static const struct component_master_ops armada_master_ops = { static int armada_drm_probe(struct platform_device *pdev) { - if (is_componentized(&pdev->dev)) { - struct component_match *match = NULL; - int ret; - - ret = armada_drm_find_components(&pdev->dev, &match); - if (ret < 0) - return ret; - - return component_master_add_with_match(&pdev->dev, - &armada_master_ops, match); - } else { - return drm_platform_init(&armada_drm_driver, pdev); - } + struct component_match *match = NULL; + int ret; + + ret = armada_drm_find_components(&pdev->dev, &match); + if (ret < 0) + return ret; + + return component_master_add_with_match(&pdev->dev, &armada_master_ops, + match); } static int armada_drm_remove(struct platform_device *pdev) { - if (is_componentized(&pdev->dev)) - component_master_del(&pdev->dev, &armada_master_ops); - else - drm_put_dev(platform_get_drvdata(pdev)); + component_master_del(&pdev->dev, &armada_master_ops); return 0; } static const struct platform_device_id armada_drm_platform_ids[] = { { .name = "armada-drm", - .driver_data = (unsigned long)&armada510_ops, }, { .name = "armada-510-drm", - .driver_data = (unsigned long)&armada510_ops, }, { }, }; diff --git a/drivers/gpu/drm/armada/armada_output.c b/drivers/gpu/drm/armada/armada_output.c deleted file mode 100644 index 5a98231..0000000 --- a/drivers/gpu/drm/armada/armada_output.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2012 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include "armada_output.h" -#include "armada_drm.h" - -struct armada_connector { - struct drm_connector conn; - const struct armada_output_type *type; -}; - -#define drm_to_armada_conn(c) container_of(c, struct armada_connector, conn) - -struct drm_encoder *armada_drm_connector_encoder(struct drm_connector *conn) -{ - struct drm_encoder *enc = conn->encoder; - - return enc ? enc : drm_encoder_find(conn->dev, conn->encoder_ids[0]); -} - -static enum drm_connector_status armada_drm_connector_detect( - struct drm_connector *conn, bool force) -{ - struct armada_connector *dconn = drm_to_armada_conn(conn); - enum drm_connector_status status = connector_status_disconnected; - - if (dconn->type->detect) { - status = dconn->type->detect(conn, force); - } else { - struct drm_encoder *enc = armada_drm_connector_encoder(conn); - - if (enc) - status = encoder_helper_funcs(enc)->detect(enc, conn); - } - - return status; -} - -static void armada_drm_connector_destroy(struct drm_connector *conn) -{ - struct armada_connector *dconn = drm_to_armada_conn(conn); - - drm_connector_unregister(conn); - drm_connector_cleanup(conn); - kfree(dconn); -} - -static int armada_drm_connector_set_property(struct drm_connector *conn, - struct drm_property *property, uint64_t value) -{ - struct armada_connector *dconn = drm_to_armada_conn(conn); - - if (!dconn->type->set_property) - return -EINVAL; - - return dconn->type->set_property(conn, property, value); -} - -static const struct drm_connector_funcs armada_drm_conn_funcs = { - .dpms = drm_helper_connector_dpms, - .fill_modes = drm_helper_probe_single_connector_modes, - .detect = armada_drm_connector_detect, - .destroy = armada_drm_connector_destroy, - .set_property = armada_drm_connector_set_property, -}; - -/* Shouldn't this be a generic helper function? */ -int armada_drm_slave_encoder_mode_valid(struct drm_connector *conn, - struct drm_display_mode *mode) -{ - struct drm_encoder *encoder = armada_drm_connector_encoder(conn); - int valid = MODE_BAD; - - if (encoder) { - struct drm_encoder_slave *slave = to_encoder_slave(encoder); - - valid = slave->slave_funcs->mode_valid(encoder, mode); - } - return valid; -} - -int armada_drm_slave_encoder_set_property(struct drm_connector *conn, - struct drm_property *property, uint64_t value) -{ - struct drm_encoder *encoder = armada_drm_connector_encoder(conn); - int rc = -EINVAL; - - if (encoder) { - struct drm_encoder_slave *slave = to_encoder_slave(encoder); - - rc = slave->slave_funcs->set_property(encoder, conn, property, - value); - } - return rc; -} - -int armada_output_create(struct drm_device *dev, - const struct armada_output_type *type, const void *data) -{ - struct armada_connector *dconn; - int ret; - - dconn = kzalloc(sizeof(*dconn), GFP_KERNEL); - if (!dconn) - return -ENOMEM; - - dconn->type = type; - - ret = drm_connector_init(dev, &dconn->conn, &armada_drm_conn_funcs, - type->connector_type); - if (ret) { - DRM_ERROR("unable to init connector\n"); - goto err_destroy_dconn; - } - - ret = type->create(&dconn->conn, data); - if (ret) - goto err_conn; - - ret = drm_connector_register(&dconn->conn); - if (ret) - goto err_sysfs; - - return 0; - - err_sysfs: - if (dconn->conn.encoder) - dconn->conn.encoder->funcs->destroy(dconn->conn.encoder); - err_conn: - drm_connector_cleanup(&dconn->conn); - err_destroy_dconn: - kfree(dconn); - return ret; -} diff --git a/drivers/gpu/drm/armada/armada_output.h b/drivers/gpu/drm/armada/armada_output.h deleted file mode 100644 index f448785..0000000 --- a/drivers/gpu/drm/armada/armada_output.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2012 Russell King - * - * 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. - */ -#ifndef ARMADA_CONNETOR_H -#define ARMADA_CONNETOR_H - -#define encoder_helper_funcs(encoder) \ - ((const struct drm_encoder_helper_funcs *)encoder->helper_private) - -struct armada_output_type { - int connector_type; - enum drm_connector_status (*detect)(struct drm_connector *, bool); - int (*create)(struct drm_connector *, const void *); - int (*set_property)(struct drm_connector *, struct drm_property *, - uint64_t); -}; - -struct drm_encoder *armada_drm_connector_encoder(struct drm_connector *conn); - -int armada_drm_slave_encoder_mode_valid(struct drm_connector *conn, - struct drm_display_mode *mode); - -int armada_drm_slave_encoder_set_property(struct drm_connector *conn, - struct drm_property *property, uint64_t value); - -int armada_output_create(struct drm_device *dev, - const struct armada_output_type *type, const void *data); - -#endif diff --git a/drivers/gpu/drm/armada/armada_slave.c b/drivers/gpu/drm/armada/armada_slave.c deleted file mode 100644 index 00d0fac..0000000 --- a/drivers/gpu/drm/armada/armada_slave.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2012 Russell King - * Rewritten from the dovefb driver, and Armada510 manuals. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include "armada_drm.h" -#include "armada_output.h" -#include "armada_slave.h" - -static int armada_drm_slave_get_modes(struct drm_connector *conn) -{ - struct drm_encoder *enc = armada_drm_connector_encoder(conn); - int count = 0; - - if (enc) { - struct drm_encoder_slave *slave = to_encoder_slave(enc); - - count = slave->slave_funcs->get_modes(enc, conn); - } - - return count; -} - -static void armada_drm_slave_destroy(struct drm_encoder *enc) -{ - struct drm_encoder_slave *slave = to_encoder_slave(enc); - struct i2c_client *client = drm_i2c_encoder_get_client(enc); - - if (slave->slave_funcs) - slave->slave_funcs->destroy(enc); - if (client) - i2c_put_adapter(client->adapter); - - drm_encoder_cleanup(&slave->base); - kfree(slave); -} - -static const struct drm_encoder_funcs armada_drm_slave_encoder_funcs = { - .destroy = armada_drm_slave_destroy, -}; - -static const struct drm_connector_helper_funcs armada_drm_slave_helper_funcs = { - .get_modes = armada_drm_slave_get_modes, - .mode_valid = armada_drm_slave_encoder_mode_valid, - .best_encoder = armada_drm_connector_encoder, -}; - -static const struct drm_encoder_helper_funcs drm_slave_encoder_helpers = { - .dpms = drm_i2c_encoder_dpms, - .save = drm_i2c_encoder_save, - .restore = drm_i2c_encoder_restore, - .mode_fixup = drm_i2c_encoder_mode_fixup, - .prepare = drm_i2c_encoder_prepare, - .commit = drm_i2c_encoder_commit, - .mode_set = drm_i2c_encoder_mode_set, - .detect = drm_i2c_encoder_detect, -}; - -static int -armada_drm_conn_slave_create(struct drm_connector *conn, const void *data) -{ - const struct armada_drm_slave_config *config = data; - struct drm_encoder_slave *slave; - struct i2c_adapter *adap; - int ret; - - conn->interlace_allowed = config->interlace_allowed; - conn->doublescan_allowed = config->doublescan_allowed; - conn->polled = config->polled; - - drm_connector_helper_add(conn, &armada_drm_slave_helper_funcs); - - slave = kzalloc(sizeof(*slave), GFP_KERNEL); - if (!slave) - return -ENOMEM; - - slave->base.possible_crtcs = config->crtcs; - - adap = i2c_get_adapter(config->i2c_adapter_id); - if (!adap) { - kfree(slave); - return -EPROBE_DEFER; - } - - ret = drm_encoder_init(conn->dev, &slave->base, - &armada_drm_slave_encoder_funcs, - DRM_MODE_ENCODER_TMDS); - if (ret) { - DRM_ERROR("unable to init encoder\n"); - i2c_put_adapter(adap); - kfree(slave); - return ret; - } - - ret = drm_i2c_encoder_init(conn->dev, slave, adap, &config->info); - i2c_put_adapter(adap); - if (ret) { - DRM_ERROR("unable to init encoder slave\n"); - armada_drm_slave_destroy(&slave->base); - return ret; - } - - drm_encoder_helper_add(&slave->base, &drm_slave_encoder_helpers); - - ret = slave->slave_funcs->create_resources(&slave->base, conn); - if (ret) { - armada_drm_slave_destroy(&slave->base); - return ret; - } - - ret = drm_mode_connector_attach_encoder(conn, &slave->base); - if (ret) { - armada_drm_slave_destroy(&slave->base); - return ret; - } - - conn->encoder = &slave->base; - - return ret; -} - -static const struct armada_output_type armada_drm_conn_slave = { - .connector_type = DRM_MODE_CONNECTOR_HDMIA, - .create = armada_drm_conn_slave_create, - .set_property = armada_drm_slave_encoder_set_property, -}; - -int armada_drm_connector_slave_create(struct drm_device *dev, - const struct armada_drm_slave_config *config) -{ - return armada_output_create(dev, &armada_drm_conn_slave, config); -} diff --git a/drivers/gpu/drm/armada/armada_slave.h b/drivers/gpu/drm/armada/armada_slave.h deleted file mode 100644 index bf2374c..0000000 --- a/drivers/gpu/drm/armada/armada_slave.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2012 Russell King - * - * 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. - */ -#ifndef ARMADA_SLAVE_H -#define ARMADA_SLAVE_H - -#include -#include - -struct armada_drm_slave_config { - int i2c_adapter_id; - uint32_t crtcs; - uint8_t polled; - bool interlace_allowed; - bool doublescan_allowed; - struct i2c_board_info info; -}; - -int armada_drm_connector_slave_create(struct drm_device *dev, - const struct armada_drm_slave_config *); - -#endif -- cgit v0.10.2 From 7c8f7e1abc75b853adf60d8ee0a589e058bcdb6b Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 29 Jun 2015 17:52:16 +0100 Subject: drm/armada: move vbl code into armada_crtc Our vblank event code belongs in armada_crtc.c rather than the core of the driver. Move it there. Signed-off-by: Russell King diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index c7374a3..418594b 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -173,6 +173,44 @@ static unsigned armada_drm_crtc_calc_fb(struct drm_framebuffer *fb, return i; } +void armada_drm_vbl_event_add(struct armada_crtc *dcrtc, + struct armada_vbl_event *evt) +{ + unsigned long flags; + bool not_on_list; + + WARN_ON(drm_vblank_get(dcrtc->crtc.dev, dcrtc->num)); + + spin_lock_irqsave(&dcrtc->irq_lock, flags); + not_on_list = list_empty(&evt->node); + if (not_on_list) + list_add_tail(&evt->node, &dcrtc->vbl_list); + spin_unlock_irqrestore(&dcrtc->irq_lock, flags); + + if (!not_on_list) + drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); +} + +void armada_drm_vbl_event_remove(struct armada_crtc *dcrtc, + struct armada_vbl_event *evt) +{ + if (!list_empty(&evt->node)) { + list_del_init(&evt->node); + drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); + } +} + +static void armada_drm_vbl_event_run(struct armada_crtc *dcrtc) +{ + struct armada_vbl_event *e, *n; + + list_for_each_entry_safe(e, n, &dcrtc->vbl_list, node) { + list_del_init(&e->node); + drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); + e->fn(dcrtc, e->data); + } +} + static int armada_drm_crtc_queue_frame_work(struct armada_crtc *dcrtc, struct armada_frame_work *work) { @@ -356,7 +394,6 @@ static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc, static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) { - struct armada_vbl_event *e, *n; void __iomem *base = dcrtc->base; if (stat & DMA_FF_UNDERFLOW) @@ -368,12 +405,7 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) drm_handle_vblank(dcrtc->crtc.dev, dcrtc->num); spin_lock(&dcrtc->irq_lock); - - list_for_each_entry_safe(e, n, &dcrtc->vbl_list, node) { - list_del_init(&e->node); - drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); - e->fn(dcrtc, e->data); - } + armada_drm_vbl_event_run(dcrtc); if (stat & GRA_FRAME_IRQ && dcrtc->interlaced) { int i = stat & GRA_FRAME_IRQ0 ? 0 : 1; diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h index a13469f..a86243e 100644 --- a/drivers/gpu/drm/armada/armada_crtc.h +++ b/drivers/gpu/drm/armada/armada_crtc.h @@ -75,6 +75,23 @@ struct armada_crtc { }; #define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc) +struct armada_vbl_event { + struct list_head node; + void *data; + void (*fn)(struct armada_crtc *, void *); +}; + +void armada_drm_vbl_event_add(struct armada_crtc *, + struct armada_vbl_event *); +void armada_drm_vbl_event_remove(struct armada_crtc *, + struct armada_vbl_event *); +#define armada_drm_vbl_event_init(_e, _f, _d) do { \ + struct armada_vbl_event *__e = _e; \ + INIT_LIST_HEAD(&__e->node); \ + __e->data = _d; \ + __e->fn = _f; \ +} while (0) + void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int); void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int); void armada_drm_crtc_disable_irq(struct armada_crtc *, u32); diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h index 5f6aef0..4df6f2a 100644 --- a/drivers/gpu/drm/armada/armada_drm.h +++ b/drivers/gpu/drm/armada/armada_drm.h @@ -37,22 +37,6 @@ static inline uint32_t armada_pitch(uint32_t width, uint32_t bpp) return ALIGN(pitch, 128); } -struct armada_vbl_event { - struct list_head node; - void *data; - void (*fn)(struct armada_crtc *, void *); -}; -void armada_drm_vbl_event_add(struct armada_crtc *, - struct armada_vbl_event *); -void armada_drm_vbl_event_remove(struct armada_crtc *, - struct armada_vbl_event *); -#define armada_drm_vbl_event_init(_e, _f, _d) do { \ - struct armada_vbl_event *__e = _e; \ - INIT_LIST_HEAD(&__e->node); \ - __e->data = _d; \ - __e->fn = _f; \ -} while (0) - struct armada_private; diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index b373cf9..3f1396e 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -148,29 +148,6 @@ static int armada_drm_unload(struct drm_device *dev) return 0; } -void armada_drm_vbl_event_add(struct armada_crtc *dcrtc, - struct armada_vbl_event *evt) -{ - unsigned long flags; - - spin_lock_irqsave(&dcrtc->irq_lock, flags); - if (list_empty(&evt->node)) { - list_add_tail(&evt->node, &dcrtc->vbl_list); - - drm_vblank_get(dcrtc->crtc.dev, dcrtc->num); - } - spin_unlock_irqrestore(&dcrtc->irq_lock, flags); -} - -void armada_drm_vbl_event_remove(struct armada_crtc *dcrtc, - struct armada_vbl_event *evt) -{ - if (!list_empty(&evt->node)) { - list_del_init(&evt->node); - drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); - } -} - /* These are called under the vbl_lock. */ static int armada_drm_enable_vblank(struct drm_device *dev, int crtc) { -- cgit v0.10.2 From f8e140698234dae3a4ea7b971e7bf63a3e0c987a Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 29 Jun 2015 17:52:42 +0100 Subject: drm/armada: use drm_plane_force_disable() to disable the overlay plane Use drm_plane_force_disable() to disable the overlay plane on a mode_set rather than coding this ourselves. Signed-off-by: Russell King diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 418594b..bbf5ff7 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -348,17 +348,11 @@ static void armada_drm_crtc_prepare(struct drm_crtc *crtc) /* * If we have an overlay plane associated with this CRTC, disable * it before the modeset to avoid its coordinates being outside - * the new mode parameters. DRM doesn't provide help with this. + * the new mode parameters. */ plane = dcrtc->plane; - if (plane) { - struct drm_framebuffer *fb = plane->fb; - - plane->funcs->disable_plane(plane); - plane->fb = NULL; - plane->crtc = NULL; - drm_framebuffer_unreference(fb); - } + if (plane) + drm_plane_force_disable(plane); } /* The mode_config.mutex will be held for this call */ -- cgit v0.10.2 From e0ac5e9b4b14ab4be7fbba48d666fc619342fd88 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 29 Jun 2015 18:01:38 +0100 Subject: drm/armada: disable CRTC clock during DPMS When the CRTC is in low power mode, it isn't running, and so there's no point keeping the CRTC clock enabled. Disable the CRTC clock during DPMS. We need to re-enable it in the mode_set callback to ensure that the variant's compute_clock() continues to see its clock in the expected state (enabled). Signed-off-by: Russell King diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index bbf5ff7..8c43ecc 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -325,7 +325,11 @@ static void armada_drm_crtc_dpms(struct drm_crtc *crtc, int dpms) if (dcrtc->dpms != dpms) { dcrtc->dpms = dpms; + if (!IS_ERR(dcrtc->clk) && !dpms_blanked(dpms)) + WARN_ON(clk_prepare_enable(dcrtc->clk)); armada_drm_crtc_update(dcrtc); + if (!IS_ERR(dcrtc->clk) && dpms_blanked(dpms)) + clk_disable_unprepare(dcrtc->clk); if (dpms_blanked(dpms)) armada_drm_vblank_off(dcrtc); else @@ -563,6 +567,13 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc, writel_relaxed(val, dcrtc->base + LCD_SPU_DUMB_CTRL); } + /* + * If we are blanked, we would have disabled the clock. Re-enable + * it so that compute_clock() does the right thing. + */ + if (!IS_ERR(dcrtc->clk) && dpms_blanked(dcrtc->dpms)) + WARN_ON(clk_prepare_enable(dcrtc->clk)); + /* Now compute the divider for real */ dcrtc->variant->compute_clock(dcrtc, adj, &sclk); -- cgit v0.10.2 From 709ffd82fc6ff760dc3a7f71bdf26d78a8e3caf0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 15 Jul 2015 18:09:38 +0100 Subject: drm/armada: redo locking and atomics for armada_drm_crtc_complete_frame_work() We can do better with armada_drm_crtc_complete_frame_work() - we can avoid taking the event lock unless a call to drm_send_vblank_event() is required, and using cmpxchg() and xchg(), we can eliminate the locking around dcrtc->frame_work entirely. Signed-off-by: Russell King diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 8c43ecc..5d62764 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -215,7 +215,6 @@ static int armada_drm_crtc_queue_frame_work(struct armada_crtc *dcrtc, struct armada_frame_work *work) { struct drm_device *dev = dcrtc->crtc.dev; - unsigned long flags; int ret; ret = drm_vblank_get(dev, dcrtc->num); @@ -224,30 +223,29 @@ static int armada_drm_crtc_queue_frame_work(struct armada_crtc *dcrtc, return ret; } - spin_lock_irqsave(&dev->event_lock, flags); - if (!dcrtc->frame_work) - dcrtc->frame_work = work; - else - ret = -EBUSY; - spin_unlock_irqrestore(&dev->event_lock, flags); - - if (ret) + if (cmpxchg(&dcrtc->frame_work, NULL, work)) { drm_vblank_put(dev, dcrtc->num); + ret = -EBUSY; + } return ret; } -static void armada_drm_crtc_complete_frame_work(struct armada_crtc *dcrtc) +static void armada_drm_crtc_complete_frame_work(struct armada_crtc *dcrtc, + struct armada_frame_work *work) { struct drm_device *dev = dcrtc->crtc.dev; - struct armada_frame_work *work = dcrtc->frame_work; - - dcrtc->frame_work = NULL; + unsigned long flags; + spin_lock_irqsave(&dcrtc->irq_lock, flags); armada_drm_crtc_update_regs(dcrtc, work->regs); + spin_unlock_irqrestore(&dcrtc->irq_lock, flags); - if (work->event) + if (work->event) { + spin_lock_irqsave(&dev->event_lock, flags); drm_send_vblank_event(dev, dcrtc->num, work->event); + spin_unlock_irqrestore(&dev->event_lock, flags); + } drm_vblank_put(dev, dcrtc->num); @@ -293,7 +291,7 @@ static void armada_drm_crtc_finish_fb(struct armada_crtc *dcrtc, static void armada_drm_vblank_off(struct armada_crtc *dcrtc) { - struct drm_device *dev = dcrtc->crtc.dev; + struct armada_frame_work *work; /* * Tell the DRM core that vblank IRQs aren't going to happen for @@ -302,10 +300,9 @@ static void armada_drm_vblank_off(struct armada_crtc *dcrtc) drm_crtc_vblank_off(&dcrtc->crtc); /* Handle any pending flip event. */ - spin_lock_irq(&dev->event_lock); - if (dcrtc->frame_work) - armada_drm_crtc_complete_frame_work(dcrtc); - spin_unlock_irq(&dev->event_lock); + work = xchg(&dcrtc->frame_work, NULL); + if (work) + armada_drm_crtc_complete_frame_work(dcrtc, work); } void armada_drm_crtc_gamma_set(struct drm_crtc *crtc, u16 r, u16 g, u16 b, @@ -434,12 +431,10 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) spin_unlock(&dcrtc->irq_lock); if (stat & GRA_FRAME_IRQ) { - struct drm_device *dev = dcrtc->crtc.dev; + struct armada_frame_work *work = xchg(&dcrtc->frame_work, NULL); - spin_lock(&dev->event_lock); - if (dcrtc->frame_work) - armada_drm_crtc_complete_frame_work(dcrtc); - spin_unlock(&dev->event_lock); + if (work) + armada_drm_crtc_complete_frame_work(dcrtc, work); wake_up(&dcrtc->frame_wait); } @@ -957,8 +952,6 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc, { struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); struct armada_frame_work *work; - struct drm_device *dev = crtc->dev; - unsigned long flags; unsigned i; int ret; @@ -1004,10 +997,10 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc, * interrupt, so complete it now. */ if (dpms_blanked(dcrtc->dpms)) { - spin_lock_irqsave(&dev->event_lock, flags); - if (dcrtc->frame_work) - armada_drm_crtc_complete_frame_work(dcrtc); - spin_unlock_irqrestore(&dev->event_lock, flags); + struct armada_frame_work *work = xchg(&dcrtc->frame_work, NULL); + + if (work) + armada_drm_crtc_complete_frame_work(dcrtc, work); } return 0; -- cgit v0.10.2 From 28a2aebed6374c4af5224114e4b4273a3aae649a Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 15 Jul 2015 18:11:23 +0100 Subject: drm/armada: rename overlay identifiers Include an _ovl infix into the overlay identifiers to separate them from the primary plane. Signed-off-by: Russell King diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index e939fab..9393a15 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -16,7 +16,7 @@ #include #include "armada_ioctlP.h" -struct armada_plane_properties { +struct armada_ovl_plane_properties { uint32_t colorkey_yr; uint32_t colorkey_ug; uint32_t colorkey_vb; @@ -29,7 +29,7 @@ struct armada_plane_properties { uint32_t colorkey_mode; }; -struct armada_plane { +struct armada_ovl_plane { struct drm_plane base; spinlock_t lock; struct drm_framebuffer *old_fb; @@ -42,13 +42,13 @@ struct armada_plane { struct armada_regs regs[13]; wait_queue_head_t wait; } vbl; - struct armada_plane_properties prop; + struct armada_ovl_plane_properties prop; }; -#define drm_to_armada_plane(p) container_of(p, struct armada_plane, base) +#define drm_to_armada_ovl_plane(p) container_of(p, struct armada_ovl_plane, base) static void -armada_ovl_update_attr(struct armada_plane_properties *prop, +armada_ovl_update_attr(struct armada_ovl_plane_properties *prop, struct armada_crtc *dcrtc) { writel_relaxed(prop->colorkey_yr, dcrtc->base + LCD_SPU_COLORKEY_Y); @@ -72,9 +72,9 @@ armada_ovl_update_attr(struct armada_plane_properties *prop, } /* === Plane support === */ -static void armada_plane_vbl(struct armada_crtc *dcrtc, void *data) +static void armada_ovl_plane_vbl(struct armada_crtc *dcrtc, void *data) { - struct armada_plane *dplane = data; + struct armada_ovl_plane *dplane = data; struct drm_framebuffer *fb; armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs); @@ -91,12 +91,12 @@ static void armada_plane_vbl(struct armada_crtc *dcrtc, void *data) } static int -armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, +armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, struct drm_framebuffer *fb, int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) { - struct armada_plane *dplane = drm_to_armada_plane(plane); + struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); struct drm_rect src = { .x1 = src_x, @@ -267,9 +267,9 @@ armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, return 0; } -static int armada_plane_disable(struct drm_plane *plane) +static int armada_ovl_plane_disable(struct drm_plane *plane) { - struct armada_plane *dplane = drm_to_armada_plane(plane); + struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); struct drm_framebuffer *fb; struct armada_crtc *dcrtc; @@ -302,20 +302,20 @@ static int armada_plane_disable(struct drm_plane *plane) return 0; } -static void armada_plane_destroy(struct drm_plane *plane) +static void armada_ovl_plane_destroy(struct drm_plane *plane) { - struct armada_plane *dplane = drm_to_armada_plane(plane); + struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); drm_plane_cleanup(plane); kfree(dplane); } -static int armada_plane_set_property(struct drm_plane *plane, +static int armada_ovl_plane_set_property(struct drm_plane *plane, struct drm_property *property, uint64_t val) { struct armada_private *priv = plane->dev->dev_private; - struct armada_plane *dplane = drm_to_armada_plane(plane); + struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); bool update_attr = false; if (property == priv->colorkey_prop) { @@ -379,14 +379,14 @@ static int armada_plane_set_property(struct drm_plane *plane, return 0; } -static const struct drm_plane_funcs armada_plane_funcs = { - .update_plane = armada_plane_update, - .disable_plane = armada_plane_disable, - .destroy = armada_plane_destroy, - .set_property = armada_plane_set_property, +static const struct drm_plane_funcs armada_ovl_plane_funcs = { + .update_plane = armada_ovl_plane_update, + .disable_plane = armada_ovl_plane_disable, + .destroy = armada_ovl_plane_destroy, + .set_property = armada_ovl_plane_set_property, }; -static const uint32_t armada_formats[] = { +static const uint32_t armada_ovl_formats[] = { DRM_FORMAT_UYVY, DRM_FORMAT_YUYV, DRM_FORMAT_YUV420, @@ -456,7 +456,7 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) { struct armada_private *priv = dev->dev_private; struct drm_mode_object *mobj; - struct armada_plane *dplane; + struct armada_ovl_plane *dplane; int ret; ret = armada_overlay_create_properties(dev); @@ -469,11 +469,16 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) spin_lock_init(&dplane->lock); init_waitqueue_head(&dplane->vbl.wait); - armada_drm_vbl_event_init(&dplane->vbl.update, armada_plane_vbl, + armada_drm_vbl_event_init(&dplane->vbl.update, armada_ovl_plane_vbl, dplane); - drm_plane_init(dev, &dplane->base, crtcs, &armada_plane_funcs, - armada_formats, ARRAY_SIZE(armada_formats), false); + drm_plane_init(dev, &dplane->base, crtcs, &armada_ovl_plane_funcs, + armada_ovl_formats, ARRAY_SIZE(armada_ovl_formats), + false); + if (ret) { + kfree(dplane); + return ret; + } dplane->prop.colorkey_yr = 0xfefefe00; dplane->prop.colorkey_ug = 0x01010100; -- cgit v0.10.2 From fecfdb2db8b5fc2e6cb731a714889de5e43c2380 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 15 Jul 2015 18:11:24 +0100 Subject: drm/armada: factor out retirement of old fb We have two identical places in the overlay code which retire the drm framebuffer. Factor these out into a common function. Signed-off-by: Russell King diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 9393a15..093c2d4 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -71,21 +71,27 @@ armada_ovl_update_attr(struct armada_ovl_plane_properties *prop, spin_unlock_irq(&dcrtc->irq_lock); } +static void armada_ovl_retire_fb(struct armada_ovl_plane *dplane, + struct drm_framebuffer *fb) +{ + struct drm_framebuffer *old_fb; + + spin_lock(&dplane->lock); + old_fb = dplane->old_fb; + dplane->old_fb = fb; + spin_unlock(&dplane->lock); + + if (old_fb) + armada_drm_queue_unref_work(dplane->base.dev, old_fb); +} + /* === Plane support === */ static void armada_ovl_plane_vbl(struct armada_crtc *dcrtc, void *data) { struct armada_ovl_plane *dplane = data; - struct drm_framebuffer *fb; armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs); - - spin_lock(&dplane->lock); - fb = dplane->old_fb; - dplane->old_fb = NULL; - spin_unlock(&dplane->lock); - - if (fb) - armada_drm_queue_unref_work(dcrtc->crtc.dev, fb); + armada_ovl_retire_fb(dplane, NULL); wake_up(&dplane->vbl.wait); } @@ -175,17 +181,8 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, */ drm_framebuffer_reference(fb); - if (plane->fb) { - struct drm_framebuffer *older_fb; - - spin_lock_irq(&dplane->lock); - older_fb = dplane->old_fb; - dplane->old_fb = plane->fb; - spin_unlock_irq(&dplane->lock); - if (older_fb) - armada_drm_queue_unref_work(dcrtc->crtc.dev, - older_fb); - } + if (plane->fb) + armada_ovl_retire_fb(dplane, plane->fb); src_y = src.y1 >> 16; src_x = src.x1 >> 16; -- cgit v0.10.2 From 928df02bd46e2fe02cfd3127ba1814796d6d80b0 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 15 Sep 2015 22:19:04 +0100 Subject: metag: SMP: Fix 4KiB stack setup on secondary CPUs Back in early 2008, 4KiB stack support was added to reduce memory consumption on workloads with lots of threads, using a separate IRQ stack per CPU to alleviate stack pressure. However the SMP code added a year and a half later didn't set up the IRQ stack when bringing up secondary CPUs, resulting in a crash when SMP is configured with 4KiB stacks, as soon as the first interrupt arrived on a secondary CPU. Fix with calls to irq_ctx_exit()/irq_ctx_exit() when bringing up/down a CPU. Signed-off-by: James Hogan Cc: linux-metag@vger.kernel.org diff --git a/arch/metag/kernel/smp.c b/arch/metag/kernel/smp.c index ac3a199..c3c6f08 100644 --- a/arch/metag/kernel/smp.c +++ b/arch/metag/kernel/smp.c @@ -312,6 +312,7 @@ void cpu_die(void) { local_irq_disable(); idle_task_exit(); + irq_ctx_exit(smp_processor_id()); (void)cpu_report_death(); @@ -366,6 +367,7 @@ asmlinkage void secondary_start_kernel(void) panic("No TBI found!"); per_cpu_trap_init(cpu); + irq_ctx_init(cpu); preempt_disable(); -- cgit v0.10.2 From 3dce23eb887800e19cc18b389a13290dd12c5905 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 15 Sep 2015 22:50:33 +0100 Subject: metag: Turn irq_ctx_* macros into static inlines The irq_ctx_init()/irq_ctx_exit() functions are only used for 4KiB stacks, otherwise they are implemented as an empty macro. To prevent future bit rottage due to the cpu argument not being type checked, convert the macros to empty static inline functions. Signed-off-by: James Hogan Cc: linux-metag@vger.kernel.org diff --git a/arch/metag/include/asm/irq.h b/arch/metag/include/asm/irq.h index ad6bd0e..6ac6d4a 100644 --- a/arch/metag/include/asm/irq.h +++ b/arch/metag/include/asm/irq.h @@ -6,8 +6,12 @@ extern void irq_ctx_init(int cpu); extern void irq_ctx_exit(int cpu); # define __ARCH_HAS_DO_SOFTIRQ #else -# define irq_ctx_init(cpu) do { } while (0) -# define irq_ctx_exit(cpu) do { } while (0) +static inline void irq_ctx_init(int cpu) +{ +} +static inline void irq_ctx_exit(int cpu) +{ +} #endif void tbi_startup_interrupt(int); -- cgit v0.10.2 From be8becb81bdc6d4c1bb81808e252ed6bc2c7a2f1 Mon Sep 17 00:00:00 2001 From: Priit Laes Date: Wed, 16 Sep 2015 10:55:42 +0300 Subject: ARM: sunxi_defconfig: Enable LRADC keys (KEYBOARD_SUN4I_LRADC) Signed-off-by: Priit Laes Signed-off-by: Maxime Ripard diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig index 51eea22..94c6bd0 100644 --- a/arch/arm/configs/sunxi_defconfig +++ b/arch/arm/configs/sunxi_defconfig @@ -63,6 +63,7 @@ CONFIG_STMMAC_ETH=y CONFIG_INPUT_MISC=y CONFIG_INPUT_AXP20X_PEK=y CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_KEYBOARD_SUN4I_LRADC=y CONFIG_TOUCHSCREEN_SUN4I=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y -- cgit v0.10.2 From 9685cd9df75c1f5686308601c870f5e4ebc809be Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 25 Aug 2015 15:35:57 -0400 Subject: drm/fb-helper: add headerdoc for drm_fb_helper Signed-off-by: Rob Clark Signed-off-by: Daniel Vetter diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 67de1f1..6254136 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -104,6 +104,20 @@ struct drm_fb_helper_connector { struct drm_connector *connector; }; +/** + * struct drm_fb_helper - helper to emulate fbdev on top of kms + * @fb: Scanout framebuffer object + * @dev: DRM device + * @crtc_count: number of possible CRTCs + * @crtc_info: per-CRTC helper state (mode, x/y offset, etc) + * @connector_count: number of connected connectors + * @connector_info_alloc_count: size of connector_info + * @funcs: driver callbacks for fb helper + * @fbdev: emulated fbdev device info struct + * @pseudo_palette: fake palette of 16 colors + * @kernel_fb_list: list_head in kernel_fb_helper_list + * @delayed_hotplug: was there a hotplug while kms master active? + */ struct drm_fb_helper { struct drm_framebuffer *fb; struct drm_device *dev; -- cgit v0.10.2 From bbb1e52402b2a288b09ae37e8182599931c7e9df Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 25 Aug 2015 15:35:58 -0400 Subject: drm/fb-helper: atomic restore_fbdev_mode().. Add support for using atomic code-paths for restore_fbdev_mode(). Signed-off-by: Rob Clark [danvet: Bikeshed comments slightly.] Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 94d6c8e..ee57ecf 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1553,21 +1553,9 @@ retry: goto fail; } - ret = drm_atomic_set_crtc_for_plane(plane_state, NULL); + ret = __drm_atomic_helper_disable_plane(plane, plane_state); if (ret != 0) goto fail; - drm_atomic_set_fb_for_plane(plane_state, NULL); - plane_state->crtc_x = 0; - plane_state->crtc_y = 0; - plane_state->crtc_h = 0; - plane_state->crtc_w = 0; - plane_state->src_x = 0; - plane_state->src_y = 0; - plane_state->src_h = 0; - plane_state->src_w = 0; - - if (plane == plane->crtc->cursor) - state->legacy_cursor_update = true; ret = drm_atomic_commit(state); if (ret != 0) @@ -1597,6 +1585,32 @@ backoff: } EXPORT_SYMBOL(drm_atomic_helper_disable_plane); +/* just used from fb-helper and atomic-helper: */ +int __drm_atomic_helper_disable_plane(struct drm_plane *plane, + struct drm_plane_state *plane_state) +{ + int ret; + + ret = drm_atomic_set_crtc_for_plane(plane_state, NULL); + if (ret != 0) + return ret; + + drm_atomic_set_fb_for_plane(plane_state, NULL); + plane_state->crtc_x = 0; + plane_state->crtc_y = 0; + plane_state->crtc_h = 0; + plane_state->crtc_w = 0; + plane_state->src_x = 0; + plane_state->src_y = 0; + plane_state->src_h = 0; + plane_state->src_w = 0; + + if (plane->crtc && (plane == plane->crtc->cursor)) + plane_state->state->legacy_cursor_update = true; + + return 0; +} + static int update_output_state(struct drm_atomic_state *state, struct drm_mode_set *set) { @@ -1680,8 +1694,6 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set) { struct drm_atomic_state *state; struct drm_crtc *crtc = set->crtc; - struct drm_crtc_state *crtc_state; - struct drm_plane_state *primary_state; int ret = 0; state = drm_atomic_state_alloc(crtc->dev); @@ -1690,17 +1702,54 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set) state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); retry: - crtc_state = drm_atomic_get_crtc_state(state, crtc); - if (IS_ERR(crtc_state)) { - ret = PTR_ERR(crtc_state); + ret = __drm_atomic_helper_set_config(set, state); + if (ret != 0) goto fail; - } - primary_state = drm_atomic_get_plane_state(state, crtc->primary); - if (IS_ERR(primary_state)) { - ret = PTR_ERR(primary_state); + ret = drm_atomic_commit(state); + if (ret != 0) goto fail; - } + + /* Driver takes ownership of state on successful commit. */ + return 0; +fail: + if (ret == -EDEADLK) + goto backoff; + + drm_atomic_state_free(state); + + return ret; +backoff: + drm_atomic_state_clear(state); + drm_atomic_legacy_backoff(state); + + /* + * Someone might have exchanged the framebuffer while we dropped locks + * in the backoff code. We need to fix up the fb refcount tracking the + * core does for us. + */ + crtc->primary->old_fb = crtc->primary->fb; + + goto retry; +} +EXPORT_SYMBOL(drm_atomic_helper_set_config); + +/* just used from fb-helper and atomic-helper: */ +int __drm_atomic_helper_set_config(struct drm_mode_set *set, + struct drm_atomic_state *state) +{ + struct drm_crtc_state *crtc_state; + struct drm_plane_state *primary_state; + struct drm_crtc *crtc = set->crtc; + int ret; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + + primary_state = drm_atomic_get_plane_state(state, crtc->primary); + if (IS_ERR(primary_state)) + return PTR_ERR(primary_state); if (!set->mode) { WARN_ON(set->fb); @@ -1708,13 +1757,13 @@ retry: ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL); if (ret != 0) - goto fail; + return ret; crtc_state->active = false; ret = drm_atomic_set_crtc_for_plane(primary_state, NULL); if (ret != 0) - goto fail; + return ret; drm_atomic_set_fb_for_plane(primary_state, NULL); @@ -1726,13 +1775,14 @@ retry: ret = drm_atomic_set_mode_for_crtc(crtc_state, set->mode); if (ret != 0) - goto fail; + return ret; crtc_state->active = true; ret = drm_atomic_set_crtc_for_plane(primary_state, crtc); if (ret != 0) - goto fail; + return ret; + drm_atomic_set_fb_for_plane(primary_state, set->fb); primary_state->crtc_x = 0; primary_state->crtc_y = 0; @@ -1746,35 +1796,10 @@ retry: commit: ret = update_output_state(state, set); if (ret) - goto fail; - - ret = drm_atomic_commit(state); - if (ret != 0) - goto fail; + return ret; - /* Driver takes ownership of state on successful commit. */ return 0; -fail: - if (ret == -EDEADLK) - goto backoff; - - drm_atomic_state_free(state); - - return ret; -backoff: - drm_atomic_state_clear(state); - drm_atomic_legacy_backoff(state); - - /* - * Someone might have exchanged the framebuffer while we dropped locks - * in the backoff code. We need to fix up the fb refcount tracking the - * core does for us. - */ - crtc->primary->old_fb = crtc->primary->fb; - - goto retry; } -EXPORT_SYMBOL(drm_atomic_helper_set_config); /** * drm_atomic_helper_crtc_set_property - helper for crtc properties diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index ba12f51..0180fdd 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -38,6 +38,8 @@ #include #include #include +#include +#include static bool drm_fbdev_emulation = true; module_param_named(fbdev_emulation, drm_fbdev_emulation, bool, 0600); @@ -334,6 +336,72 @@ int drm_fb_helper_debug_leave(struct fb_info *info) } EXPORT_SYMBOL(drm_fb_helper_debug_leave); +static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper) +{ + struct drm_device *dev = fb_helper->dev; + struct drm_plane *plane; + struct drm_atomic_state *state; + int i, ret; + + state = drm_atomic_state_alloc(dev); + if (!state) + return -ENOMEM; + + state->acquire_ctx = dev->mode_config.acquire_ctx; +retry: + drm_for_each_plane(plane, dev) { + struct drm_plane_state *plane_state; + + plane_state = drm_atomic_get_plane_state(state, plane); + if (IS_ERR(plane_state)) { + ret = PTR_ERR(plane_state); + goto fail; + } + + ret = drm_atomic_plane_set_property(plane, plane_state, + dev->mode_config.rotation_property, + BIT(DRM_ROTATE_0)); + if (ret != 0) + goto fail; + + /* disable non-primary: */ + if (plane->type == DRM_PLANE_TYPE_PRIMARY) + continue; + + ret = __drm_atomic_helper_disable_plane(plane, plane_state); + if (ret != 0) + goto fail; + } + + for(i = 0; i < fb_helper->crtc_count; i++) { + struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; + + ret = __drm_atomic_helper_set_config(mode_set, state); + if (ret != 0) + goto fail; + } + + ret = drm_atomic_commit(state); + if (ret != 0) + goto fail; + + return 0; + +fail: + if (ret == -EDEADLK) + goto backoff; + + drm_atomic_state_free(state); + + return ret; + +backoff: + drm_atomic_state_clear(state); + drm_atomic_legacy_backoff(state); + + goto retry; +} + static int restore_fbdev_mode(struct drm_fb_helper *fb_helper) { struct drm_device *dev = fb_helper->dev; @@ -342,6 +410,9 @@ static int restore_fbdev_mode(struct drm_fb_helper *fb_helper) drm_warn_on_modeset_not_all_locked(dev); + if (fb_helper->atomic) + return restore_fbdev_mode_atomic(fb_helper); + drm_for_each_plane(plane, dev) { if (plane->type != DRM_PLANE_TYPE_PRIMARY) drm_plane_force_disable(plane); @@ -644,6 +715,8 @@ int drm_fb_helper_init(struct drm_device *dev, i++; } + fb_helper->atomic = !!drm_core_check_feature(dev, DRIVER_ATOMIC); + return 0; out_free: drm_fb_helper_crtc_free(fb_helper); diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 1547eb4..8cba54a 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -30,6 +30,8 @@ #include +struct drm_atomic_state; + int drm_atomic_helper_check_modeset(struct drm_device *dev, struct drm_atomic_state *state); int drm_atomic_helper_check_planes(struct drm_device *dev, @@ -73,7 +75,11 @@ int drm_atomic_helper_update_plane(struct drm_plane *plane, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h); int drm_atomic_helper_disable_plane(struct drm_plane *plane); +int __drm_atomic_helper_disable_plane(struct drm_plane *plane, + struct drm_plane_state *plane_state); int drm_atomic_helper_set_config(struct drm_mode_set *set); +int __drm_atomic_helper_set_config(struct drm_mode_set *set, + struct drm_atomic_state *state); int drm_atomic_helper_crtc_set_property(struct drm_crtc *crtc, struct drm_property *property, diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 6254136..87b090c 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -134,6 +134,17 @@ struct drm_fb_helper { /* we got a hotplug but fbdev wasn't running the console delay until next set_par */ bool delayed_hotplug; + + /** + * @atomic: + * + * Use atomic updates for restore_fbdev_mode(), etc. This defaults to + * true if driver has DRIVER_ATOMIC feature flag, but drivers can + * override it to true after drm_fb_helper_init() if they support atomic + * modeset but do not yet advertise DRIVER_ATOMIC (note that fb-helper + * does not require ASYNC commits). + */ + bool atomic; }; #ifdef CONFIG_DRM_FBDEV_EMULATION -- cgit v0.10.2 From 1edf0269f02dc7e295f3ca7bdd698e3dcf7350bf Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 25 Aug 2015 15:35:59 -0400 Subject: drm/fb-helper: atomic pan_display().. Signed-off-by: Rob Clark Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 0180fdd..64fc5ca 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1217,6 +1217,57 @@ int drm_fb_helper_set_par(struct fb_info *info) } EXPORT_SYMBOL(drm_fb_helper_set_par); +static int pan_display_atomic(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct drm_fb_helper *fb_helper = info->par; + struct drm_device *dev = fb_helper->dev; + struct drm_atomic_state *state; + int i, ret; + + state = drm_atomic_state_alloc(dev); + if (!state) + return -ENOMEM; + + state->acquire_ctx = dev->mode_config.acquire_ctx; +retry: + for(i = 0; i < fb_helper->crtc_count; i++) { + struct drm_mode_set *mode_set; + + mode_set = &fb_helper->crtc_info[i].mode_set; + + mode_set->x = var->xoffset; + mode_set->y = var->yoffset; + + ret = __drm_atomic_helper_set_config(mode_set, state); + if (ret != 0) + goto fail; + } + + ret = drm_atomic_commit(state); + if (ret != 0) + goto fail; + + info->var.xoffset = var->xoffset; + info->var.yoffset = var->yoffset; + + return 0; + +fail: + if (ret == -EDEADLK) + goto backoff; + + drm_atomic_state_free(state); + + return ret; + +backoff: + drm_atomic_state_clear(state); + drm_atomic_legacy_backoff(state); + + goto retry; +} + /** * drm_fb_helper_pan_display - implementation for ->fb_pan_display * @var: updated screen information @@ -1240,6 +1291,11 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, return -EBUSY; } + if (fb_helper->atomic) { + ret = pan_display_atomic(var, info); + goto unlock; + } + for (i = 0; i < fb_helper->crtc_count; i++) { modeset = &fb_helper->crtc_info[i].mode_set; @@ -1254,6 +1310,7 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, } } } +unlock: drm_modeset_unlock_all(dev); return ret; } -- cgit v0.10.2 From 28cc504e8d52248962f5b485bdc65f539e3fe21d Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 25 Aug 2015 15:36:00 -0400 Subject: drm/i915: enable atomic fb-helper i915 supports enough atomic to have atomic fb-helper paths, even though it does not yet advertise DRIVER_ATOMIC. Signed-off-by: Rob Clark Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 8c6a6fa..ab2b856 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -689,6 +689,8 @@ int intel_fbdev_init(struct drm_device *dev) return ret; } + ifbdev->helper.atomic = true; + dev_priv->fbdev = ifbdev; INIT_WORK(&dev_priv->fbdev_suspend_work, intel_fbdev_suspend_worker); -- cgit v0.10.2 From 21c75328866deaa17e52bd7982d8e28ba0ce38b5 Mon Sep 17 00:00:00 2001 From: Duc Dang Date: Wed, 12 Aug 2015 17:01:12 -0700 Subject: MAINTAINERS: Add Applied Micro (APM) X-Gene Device Tree maintainer This patch adds information of maintainers for Applied Micro (APM) X-Gene device tree. Signed-off-by: Duc Dang diff --git a/MAINTAINERS b/MAINTAINERS index 7ba7ab7..2805013 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -789,6 +789,11 @@ S: Maintained F: drivers/net/appletalk/ F: net/appletalk/ +APPLIED MICRO (APM) X-GENE DEVICE TREE SUPPORT +M: Duc Dang +S: Supported +F: arch/arm64/boot/dts/apm/ + APPLIED MICRO (APM) X-GENE SOC ETHERNET DRIVER M: Iyappan Subramanian M: Keyur Chudgar -- cgit v0.10.2 From c5251136031e615aafd5b36589a2729ca6589612 Mon Sep 17 00:00:00 2001 From: Feng Kan Date: Thu, 13 Nov 2014 16:19:56 -0800 Subject: Documentation: arm64: add SCU dts binding documentation to linux kernel This add documentation for the SCU system clock unit device tree binding to the kernel. Signed-off-by: Feng Kan diff --git a/Documentation/devicetree/bindings/arm/apm/scu.txt b/Documentation/devicetree/bindings/arm/apm/scu.txt new file mode 100644 index 0000000..b45be06 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/apm/scu.txt @@ -0,0 +1,17 @@ +APM X-GENE SoC series SCU Registers + +This system clock unit contain various register that control block resets, +clock enable/disables, clock divisors and other deepsleep registers. + +Properties: + - compatible : should contain two values. First value must be: + - "apm,xgene-scu" + second value must be always "syscon". + + - reg : offset and length of the register set. + +Example : + scu: system-clk-controller@17000000 { + compatible = "apm,xgene-scu","syscon"; + reg = <0x0 0x17000000 0x0 0x400>; + }; -- cgit v0.10.2 From 5c3a87e363c09242541620a777d5b73e89b6c245 Mon Sep 17 00:00:00 2001 From: Feng Kan Date: Tue, 11 Aug 2015 17:39:36 -0700 Subject: arm64: dts: Add X-Gene reboot driver dts node This patch add dts nodes for X-Gene platforms to use generic SYSCON regmap reset driver for its reset operation. [dhdang: changelog] Signed-off-by: Feng Kan Signed-off-by: Duc Dang diff --git a/arch/arm64/boot/dts/apm/apm-storm.dtsi b/arch/arm64/boot/dts/apm/apm-storm.dtsi index d831bc2..c50a27f 100644 --- a/arch/arm64/boot/dts/apm/apm-storm.dtsi +++ b/arch/arm64/boot/dts/apm/apm-storm.dtsi @@ -396,6 +396,18 @@ 0x0 0x1f 0x4>; }; + scu: system-clk-controller@17000000 { + compatible = "apm,xgene-scu","syscon"; + reg = <0x0 0x17000000 0x0 0x400>; + }; + + reboot: reboot@17000014 { + compatible = "syscon-reboot"; + regmap = <&scu>; + offset = <0x14>; + mask = <0x1>; + }; + csw: csw@7e200000 { compatible = "apm,xgene-csw", "syscon"; reg = <0x0 0x7e200000 0x0 0x1000>; -- cgit v0.10.2 From 94d6ba285f561cd4382b2410fcbf8820056de34e Mon Sep 17 00:00:00 2001 From: Tai Nguyen Date: Wed, 12 Aug 2015 12:32:32 -0700 Subject: power: reset: Add syscon poweroff device node for APM X-Gene platform This patch adds syscon poweroff device node to support poweroff feature on APM X-Gene Mustang platform Signed-off-by: Tai Nguyen Tested-by: dann frazier Acked-by: Moritz Fischer diff --git a/arch/arm64/boot/dts/apm/apm-mustang.dts b/arch/arm64/boot/dts/apm/apm-mustang.dts index 4c55833..01cdeda 100644 --- a/arch/arm64/boot/dts/apm/apm-mustang.dts +++ b/arch/arm64/boot/dts/apm/apm-mustang.dts @@ -33,6 +33,18 @@ interrupts = <0x0 0x2d 0x1>; }; }; + + poweroff_mbox: poweroff_mbox@10548000 { + compatible = "syscon"; + reg = <0x0 0x10548000 0x0 0x30>; + }; + + poweroff: poweroff@10548010 { + compatible = "syscon-poweroff"; + regmap = <&poweroff_mbox>; + offset = <0x10>; + mask = <0x1>; + }; }; &pcie0clk { -- cgit v0.10.2 From e144dc5b8fadb1ca6d4c429aeae51a9f51d88b0e Mon Sep 17 00:00:00 2001 From: Feng Kan Date: Mon, 18 May 2015 17:56:16 -0700 Subject: arm64: dts: add APM Merlin Board device tree This patch adds the support for APM Merlin board. The Merlin board is based on the APM X-Gene Shadowcat SoC. This DTS enables PMU, Ethernet, SATA and Serial. [dhdang: remove pcie0 node] Signed-off-by: Feng Kan Signed-off-by: Duc Dang diff --git a/arch/arm64/boot/dts/apm/Makefile b/arch/arm64/boot/dts/apm/Makefile index a2afabb..c75f17a4 100644 --- a/arch/arm64/boot/dts/apm/Makefile +++ b/arch/arm64/boot/dts/apm/Makefile @@ -1,4 +1,5 @@ dtb-$(CONFIG_ARCH_XGENE) += apm-mustang.dtb +dtb-$(CONFIG_ARCH_XGENE) += apm-merlin.dtb always := $(dtb-y) subdir-y := $(dts-dirs) diff --git a/arch/arm64/boot/dts/apm/apm-merlin.dts b/arch/arm64/boot/dts/apm/apm-merlin.dts new file mode 100644 index 0000000..a20ef5b --- /dev/null +++ b/arch/arm64/boot/dts/apm/apm-merlin.dts @@ -0,0 +1,50 @@ +/* + * dts file for AppliedMicro (APM) Merlin Board + * + * Copyright (C) 2015, Applied Micro Circuits Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +/dts-v1/; + +/include/ "apm-shadowcat.dtsi" + +/ { + model = "APM X-Gene Merlin board"; + compatible = "apm,merlin", "apm,xgene-shadowcat"; + + chosen { }; + + memory { + device_type = "memory"; + reg = < 0x1 0x00000000 0x0 0x80000000 >; + }; +}; + +&serial0 { + status = "ok"; +}; + +&sata1 { + status = "ok"; +}; + +&sata2 { + status = "ok"; +}; + +&sata3 { + status = "ok"; +}; + +&sgenet0 { + status = "ok"; +}; + +&xgenet1 { + status = "ok"; +}; diff --git a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi new file mode 100644 index 0000000..b474aa0 --- /dev/null +++ b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi @@ -0,0 +1,244 @@ +/* + * dts file for AppliedMicro (APM) X-Gene Shadowcat SOC + * + * Copyright (C) 2015, Applied Micro Circuits Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +/ { + compatible = "apm,xgene-shadowcat"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu@000 { + device_type = "cpu"; + compatible = "apm,strega", "arm,armv8"; + reg = <0x0 0x000>; + enable-method = "spin-table"; + cpu-release-addr = <0x1 0x0000fff8>; + }; + cpu@001 { + device_type = "cpu"; + compatible = "apm,strega", "arm,armv8"; + reg = <0x0 0x001>; + enable-method = "spin-table"; + cpu-release-addr = <0x1 0x0000fff8>; + }; + cpu@100 { + device_type = "cpu"; + compatible = "apm,strega", "arm,armv8"; + reg = <0x0 0x100>; + enable-method = "spin-table"; + cpu-release-addr = <0x1 0x0000fff8>; + }; + cpu@101 { + device_type = "cpu"; + compatible = "apm,strega", "arm,armv8"; + reg = <0x0 0x101>; + enable-method = "spin-table"; + cpu-release-addr = <0x1 0x0000fff8>; + }; + cpu@200 { + device_type = "cpu"; + compatible = "apm,strega", "arm,armv8"; + reg = <0x0 0x200>; + enable-method = "spin-table"; + cpu-release-addr = <0x1 0x0000fff8>; + }; + cpu@201 { + device_type = "cpu"; + compatible = "apm,strega", "arm,armv8"; + reg = <0x0 0x201>; + enable-method = "spin-table"; + cpu-release-addr = <0x1 0x0000fff8>; + }; + cpu@300 { + device_type = "cpu"; + compatible = "apm,strega", "arm,armv8"; + reg = <0x0 0x300>; + enable-method = "spin-table"; + cpu-release-addr = <0x1 0x0000fff8>; + }; + cpu@301 { + device_type = "cpu"; + compatible = "apm,strega", "arm,armv8"; + reg = <0x0 0x301>; + enable-method = "spin-table"; + cpu-release-addr = <0x1 0x0000fff8>; + }; + }; + + gic: interrupt-controller@78090000 { + compatible = "arm,cortex-a15-gic"; + #interrupt-cells = <3>; + #address-cells = <2>; + #size-cells = <2>; + interrupt-controller; + interrupts = <1 9 0xf04>; /* GIC Maintenence IRQ */ + ranges = <0 0 0 0x79000000 0x0 0x800000>; /* MSI Range */ + reg = <0x0 0x78090000 0x0 0x10000>, /* GIC Dist */ + <0x0 0x780A0000 0x0 0x20000>, /* GIC CPU */ + <0x0 0x780C0000 0x0 0x10000>, /* GIC VCPU Control */ + <0x0 0x780E0000 0x0 0x20000>; /* GIC VCPU */ + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <1 12 0xff04>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <1 0 0xff04>, /* Secure Phys IRQ */ + <1 13 0xff04>, /* Non-secure Phys IRQ */ + <1 14 0xff04>, /* Virt IRQ */ + <1 15 0xff04>; /* Hyp IRQ */ + clock-frequency = <50000000>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + clocks { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + refclk: refclk { + compatible = "fixed-clock"; + #clock-cells = <1>; + clock-frequency = <100000000>; + clock-output-names = "refclk"; + }; + + socpll: socpll@17000120 { + compatible = "apm,xgene-socpll-clock"; + #clock-cells = <1>; + clocks = <&refclk 0>; + reg = <0x0 0x17000120 0x0 0x1000>; + clock-output-names = "socpll"; + }; + + socplldiv2: socplldiv2 { + compatible = "fixed-factor-clock"; + #clock-cells = <1>; + clocks = <&socpll 0>; + clock-mult = <1>; + clock-div = <2>; + clock-output-names = "socplldiv2"; + }; + + pcie0clk: pcie0clk@1f2bc000 { + compatible = "apm,xgene-device-clock"; + #clock-cells = <1>; + clocks = <&socplldiv2 0>; + reg = <0x0 0x1f2bc000 0x0 0x1000>; + reg-names = "csr-reg"; + clock-output-names = "pcie0clk"; + }; + + xge0clk: xge0clk@1f61c000 { + compatible = "apm,xgene-device-clock"; + #clock-cells = <1>; + clocks = <&socplldiv2 0>; + reg = <0x0 0x1f61c000 0x0 0x1000>; + reg-names = "csr-reg"; + enable-mask = <0x3>; + csr-mask = <0x3>; + clock-output-names = "xge0clk"; + }; + + xge1clk: xge1clk@1f62c000 { + compatible = "apm,xgene-device-clock"; + #clock-cells = <1>; + clocks = <&socplldiv2 0>; + reg = <0x0 0x1f62c000 0x0 0x1000>; + reg-names = "csr-reg"; + enable-mask = <0x3>; + csr-mask = <0x3>; + clock-output-names = "xge1clk"; + }; + }; + + serial0: serial@10600000 { + device_type = "serial"; + compatible = "ns16550"; + reg = <0 0x10600000 0x0 0x1000>; + reg-shift = <2>; + clock-frequency = <10000000>; + interrupt-parent = <&gic>; + interrupts = <0x0 0x4c 0x4>; + }; + + sata1: sata@1a000000 { + compatible = "apm,xgene-ahci"; + reg = <0x0 0x1a000000 0x0 0x1000>, + <0x0 0x1f200000 0x0 0x1000>, + <0x0 0x1f20d000 0x0 0x1000>, + <0x0 0x1f20e000 0x0 0x1000>; + interrupts = <0x0 0x5a 0x4>; + dma-coherent; + }; + + sata2: sata@1a200000 { + compatible = "apm,xgene-ahci"; + reg = <0x0 0x1a200000 0x0 0x1000>, + <0x0 0x1f210000 0x0 0x1000>, + <0x0 0x1f21d000 0x0 0x1000>, + <0x0 0x1f21e000 0x0 0x1000>; + interrupts = <0x0 0x5b 0x4>; + dma-coherent; + }; + + sata3: sata@1a400000 { + compatible = "apm,xgene-ahci"; + reg = <0x0 0x1a400000 0x0 0x1000>, + <0x0 0x1f220000 0x0 0x1000>, + <0x0 0x1f22d000 0x0 0x1000>, + <0x0 0x1f22e000 0x0 0x1000>; + interrupts = <0x0 0x5c 0x4>; + dma-coherent; + }; + + sgenet0: ethernet@1f610000 { + compatible = "apm,xgene2-sgenet"; + status = "disabled"; + reg = <0x0 0x1f610000 0x0 0x10000>, + <0x0 0x1f600000 0x0 0Xd100>, + <0x0 0x20000000 0x0 0X20000>; + interrupts = <0 96 4>, + <0 97 4>; + dma-coherent; + clocks = <&xge0clk 0>; + local-mac-address = [00 01 73 00 00 01]; + phy-connection-type = "sgmii"; + }; + + xgenet1: ethernet@1f620000 { + compatible = "apm,xgene2-xgenet"; + status = "disabled"; + reg = <0x0 0x1f620000 0x0 0x10000>, + <0x0 0x1f600000 0x0 0Xd100>, + <0x0 0x20000000 0x0 0X220000>; + interrupts = <0 108 4>, + <0 109 4>; + port-id = <1>; + dma-coherent; + clocks = <&xge1clk 0>; + local-mac-address = [00 01 73 00 00 02]; + phy-connection-type = "xgmii"; + }; + }; +}; -- cgit v0.10.2 From 991c1292f61261180873be430b9bdd50de36055d Mon Sep 17 00:00:00 2001 From: Duc Dang Date: Wed, 12 Aug 2015 16:37:08 -0700 Subject: arm64: dts: Add X-Gene v2 reboot driver dts node This patch add dts nodes for X-Gene v2 (APM X-Gene Shadowcat SoC) platforms to use generic SYSCON regmap reset driver for its reset operation. Signed-off-by: Duc Dang diff --git a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi index b474aa0..350b82b8 100644 --- a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi +++ b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi @@ -172,6 +172,18 @@ }; }; + scu: system-clk-controller@17000000 { + compatible = "apm,xgene-scu","syscon"; + reg = <0x0 0x17000000 0x0 0x400>; + }; + + reboot: reboot@17000014 { + compatible = "syscon-reboot"; + regmap = <&scu>; + offset = <0x14>; + mask = <0x1>; + }; + serial0: serial@10600000 { device_type = "serial"; compatible = "ns16550"; -- cgit v0.10.2 From 51f1e4a0d4992af29228090825546ffe55ad675c Mon Sep 17 00:00:00 2001 From: Feng Kan Date: Wed, 7 Jan 2015 17:33:37 -0700 Subject: Documentation: arm: pmu: Add Potenza PMU binding This patch documents the compatible string for APM X-Gene Potenza CPU's PMU. Signed-off-by: Vinayak Kale Signed-off-by: Feng Kan diff --git a/Documentation/devicetree/bindings/arm/pmu.txt b/Documentation/devicetree/bindings/arm/pmu.txt index 435251f..80625ae 100644 --- a/Documentation/devicetree/bindings/arm/pmu.txt +++ b/Documentation/devicetree/bindings/arm/pmu.txt @@ -7,6 +7,7 @@ representation in the device tree should be done as under:- Required properties: - compatible : should be one of + "apm,potenza-pmu" "arm,armv8-pmuv3" "arm,cortex-a17-pmu" "arm,cortex-a15-pmu" -- cgit v0.10.2 From 7434f42b8e5ca5d57262ca7ceb856a86e4ade0d4 Mon Sep 17 00:00:00 2001 From: Feng Kan Date: Wed, 7 Jan 2015 17:33:38 -0700 Subject: arm64: dts: Add PMU node for APM X-Gene Storm SOC This patch adds the PMU device tree node for APM X-Gene Storm SOC. Signed-off-by: Vinayak Kale Signed-off-by: Feng Kan diff --git a/arch/arm64/boot/dts/apm/apm-storm.dtsi b/arch/arm64/boot/dts/apm/apm-storm.dtsi index c50a27f..9e65b75 100644 --- a/arch/arm64/boot/dts/apm/apm-storm.dtsi +++ b/arch/arm64/boot/dts/apm/apm-storm.dtsi @@ -97,6 +97,11 @@ clock-frequency = <50000000>; }; + pmu { + compatible = "apm,potenza-pmu", "arm,armv8-pmuv3"; + interrupts = <1 12 0xff04>; + }; + soc { compatible = "simple-bus"; #address-cells = <2>; -- cgit v0.10.2 From 5fc86b513fd3a2f19fb267bc2e9cac49c792294e Mon Sep 17 00:00:00 2001 From: Duc Dang Date: Tue, 1 Sep 2015 13:39:27 -0700 Subject: arm64: dts: Add APM X-Gene 2 standby GPIO controller DTS entries Add standby domain gpio controller for APM X-Gene 2 SoC platforms. Signed-off-by: Duc Dang diff --git a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi index 350b82b8..c804f8f 100644 --- a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi +++ b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi @@ -224,6 +224,21 @@ dma-coherent; }; + sbgpio: sbgpio@17001000{ + compatible = "apm,xgene-gpio-sb"; + reg = <0x0 0x17001000 0x0 0x400>; + #gpio-cells = <2>; + gpio-controller; + interrupts = <0x0 0x28 0x1>, + <0x0 0x29 0x1>, + <0x0 0x2a 0x1>, + <0x0 0x2b 0x1>, + <0x0 0x2c 0x1>, + <0x0 0x2d 0x1>, + <0x0 0x2e 0x1>, + <0x0 0x2f 0x1>; + }; + sgenet0: ethernet@1f610000 { compatible = "apm,xgene2-sgenet"; status = "disabled"; -- cgit v0.10.2 From 1d8d53b62d80dc3a6ae1483891e7d840cd7a51bd Mon Sep 17 00:00:00 2001 From: Duc Dang Date: Tue, 1 Sep 2015 13:42:16 -0700 Subject: arm64: dts: Add poweroff device nodes for APM X-Gene 2 platform This patch adds: + poweroff button device node to support poweroff by power button on APM X-Gene 2 Merlin platform. + syscon poweroff device node to support poweroff feature on APM X-Gene 2 Merlin platform Signed-off-by: Duc Dang diff --git a/arch/arm64/boot/dts/apm/apm-merlin.dts b/arch/arm64/boot/dts/apm/apm-merlin.dts index a20ef5b..119a469 100644 --- a/arch/arm64/boot/dts/apm/apm-merlin.dts +++ b/arch/arm64/boot/dts/apm/apm-merlin.dts @@ -23,6 +23,28 @@ device_type = "memory"; reg = < 0x1 0x00000000 0x0 0x80000000 >; }; + + gpio-keys { + compatible = "gpio-keys"; + button@1 { + label = "POWER"; + linux,code = <116>; + linux,input-type = <0x1>; + interrupts = <0x0 0x28 0x1>; + }; + }; + + poweroff_mbox: poweroff_mbox@10548000 { + compatible = "syscon"; + reg = <0x0 0x10548000 0x0 0x30>; + }; + + poweroff: poweroff@10548010 { + compatible = "syscon-poweroff"; + regmap = <&poweroff_mbox>; + offset = <0x10>; + mask = <0x1>; + }; }; &serial0 { -- cgit v0.10.2 From 41553f267a369f24244867f5d6c8d4df254906b7 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Mon, 17 Aug 2015 08:53:47 +0900 Subject: dt-bindings: Documentation entry to explain how to use PWM FAN as a cooling device Explanation of several properties, which allow PWM fan working as a cooling device, have been embraced in this commit. Signed-off-by: Lukasz Majewski Acked-by: Eduardo Valentin Acked-by: Krzysztof Kozlowski Signed-off-by: Kukjin Kim diff --git a/Documentation/devicetree/bindings/hwmon/pwm-fan.txt b/Documentation/devicetree/bindings/hwmon/pwm-fan.txt index 610757c..c6d5332 100644 --- a/Documentation/devicetree/bindings/hwmon/pwm-fan.txt +++ b/Documentation/devicetree/bindings/hwmon/pwm-fan.txt @@ -3,10 +3,35 @@ Bindings for a fan connected to the PWM lines Required properties: - compatible : "pwm-fan" - pwms : the PWM that is used to control the PWM fan +- cooling-levels : PWM duty cycle values in a range from 0 to 255 + which correspond to thermal cooling states Example: - pwm-fan { + fan0: pwm-fan { compatible = "pwm-fan"; - status = "okay"; + cooling-min-state = <0>; + cooling-max-state = <3>; + #cooling-cells = <2>; pwms = <&pwm 0 10000 0>; + cooling-levels = <0 102 170 230>; }; + + thermal-zones { + cpu_thermal: cpu-thermal { + thermal-sensors = <&tmu 0>; + polling-delay-passive = <0>; + polling-delay = <0>; + trips { + cpu_alert1: cpu-alert1 { + temperature = <100000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + }; + cooling-maps { + map0 { + trip = <&cpu_alert1>; + cooling-device = <&fan0 0 1>; + }; + }; + }; -- cgit v0.10.2 From ee6011f299f3e75458bd6e91db5795e5adedd6fe Mon Sep 17 00:00:00 2001 From: Kamil Debski Date: Mon, 17 Aug 2015 08:53:47 +0900 Subject: ARM: dts: Add pwm-fan node for exynos4412-odroidu3 Add pwm-fan node to the Odroid-U3 board file to enable PWM control of the cooling fan. In addition, add the "pwm" label to the pwm@139D0000 node in the exynos4412.dtsi. Signed-off-by: Kamil Debski Signed-off-by: Lukasz Majewski Reviewed-by: Krzysztof Kozlowski Signed-off-by: Kukjin Kim diff --git a/arch/arm/boot/dts/exynos4412-odroidu3.dts b/arch/arm/boot/dts/exynos4412-odroidu3.dts index 8632f35..54b3bc1 100644 --- a/arch/arm/boot/dts/exynos4412-odroidu3.dts +++ b/arch/arm/boot/dts/exynos4412-odroidu3.dts @@ -32,6 +32,18 @@ linux,default-trigger = "heartbeat"; }; }; + + pwm-fan { + compatible = "pwm-fan"; + pwms = <&pwm 0 10000 0>; + }; +}; + +&pwm { + pinctrl-0 = <&pwm0_out>; + pinctrl-names = "default"; + samsung,pwm-outputs = <0>; + status = "okay"; }; &usb3503 { -- cgit v0.10.2 From d3981d1e0a34bd294d620476a33967452e0298a7 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Mon, 17 Aug 2015 08:53:48 +0900 Subject: ARM: dts: use pwm-fan device as a cooling device for exynos4412-odroidu3 With those bindings it is possible to use pwm-fan device available in Odroid U3 as a cooling device. Signed-off-by: Lukasz Majewski Acked-by: Eduardo Valentin Reviewed-by: Krzysztof Kozlowski Signed-off-by: Kukjin Kim diff --git a/arch/arm/boot/dts/exynos4412-odroidu3.dts b/arch/arm/boot/dts/exynos4412-odroidu3.dts index 54b3bc1..1e6ef99 100644 --- a/arch/arm/boot/dts/exynos4412-odroidu3.dts +++ b/arch/arm/boot/dts/exynos4412-odroidu3.dts @@ -33,9 +33,40 @@ }; }; - pwm-fan { + fan0: pwm-fan { compatible = "pwm-fan"; pwms = <&pwm 0 10000 0>; + cooling-min-state = <0>; + cooling-max-state = <3>; + #cooling-cells = <2>; + cooling-levels = <0 102 170 230>; + }; + + thermal-zones { + cpu_thermal: cpu-thermal { + cooling-maps { + map0 { + trip = <&cpu_alert1>; + cooling-device = <&cpu0 7 7>; + }; + map1 { + trip = <&cpu_alert2>; + cooling-device = <&cpu0 13 13>; + }; + map2 { + trip = <&cpu_alert0>; + cooling-device = <&fan0 0 1>; + }; + map3 { + trip = <&cpu_alert1>; + cooling-device = <&fan0 1 2>; + }; + map4 { + trip = <&cpu_alert2>; + cooling-device = <&fan0 2 3>; + }; + }; + }; }; }; -- cgit v0.10.2 From 6a4479f965430457f301c61dfe7b0dd76f691e9e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 17 Aug 2015 08:55:51 +0900 Subject: dt-bindings: Document grounded ACOKB pin on S2MPS11 Document a new Device Tree property 'samsung,s2mps11-acokb-ground' indicating that ACOKB pin of S2MPS11 PMIC is connected to the ground so the PMIC must manually set PWRHOLD bit in CTRL1 register to turn off the power. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas Acked-by: Lee Jones Signed-off-by: Kukjin Kim diff --git a/Documentation/devicetree/bindings/mfd/s2mps11.txt b/Documentation/devicetree/bindings/mfd/s2mps11.txt index 57a0450..90eaef3 100644 --- a/Documentation/devicetree/bindings/mfd/s2mps11.txt +++ b/Documentation/devicetree/bindings/mfd/s2mps11.txt @@ -15,6 +15,10 @@ Optional properties: - interrupt-parent: Specifies the phandle of the interrupt controller to which the interrupts from s2mps11 are delivered to. - interrupts: Interrupt specifiers for interrupt sources. +- samsung,s2mps11-acokb-ground: Indicates that ACOKB pin of S2MPS11 PMIC is + connected to the ground so the PMIC must manually set PWRHOLD bit in CTRL1 + register to turn off the power. Usually the ACOKB is pulled up to VBATT so + when PWRHOLD pin goes low, the rising ACOKB will trigger power off. Optional nodes: - clocks: s2mps11, s2mps13 and s5m8767 provide three(AP/CP/BT) buffered 32.768 -- cgit v0.10.2 From 0fb033bb3a384fdf1c08bcfaf429ca6431de91c7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 17 Aug 2015 08:55:51 +0900 Subject: ARM: dts: Fix power off method for exynos5422-odroidxu3-common The Odroid XU3 family boards have ACOKB pin of PMIC grounded, instead of pulled up as usual. This means that PMIC must manually set PWRHOLD field in its CTRL1 register to low before initiating power down. This fixes Odroid XU3 powering off: [ 25.966053] reboot: Power down [ 25.967679] Power down. [ 26.070174] Power down failed, please power off system manually. Signed-off-by: Krzysztof Kozlowski Reported-by: Anand Moon Reviewed-by: Javier Martinez Canillas Signed-off-by: Kukjin Kim diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi index 3b43e57..90d298d 100644 --- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi @@ -160,6 +160,7 @@ s2mps11,buck2-ramp-enable = <1>; s2mps11,buck3-ramp-enable = <1>; s2mps11,buck4-ramp-enable = <1>; + samsung,s2mps11-acokb-ground; interrupt-parent = <&gpx0>; interrupts = <4 IRQ_TYPE_EDGE_FALLING>; -- cgit v0.10.2 From 8cec734904f55d5551ac97fa9910752ef521a673 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 16 Sep 2015 08:37:07 +0900 Subject: ARM: dts: Split audio configuration to separate exynos5422-odroidxu3-audio The Odroid XU4 board does not have audio codec so before adding DTS for new board split the audio codec to separate DTSI file. Include the audio codec DTSI in Odroid XU3 and XU3-Lite boards. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas Signed-off-by: Kukjin Kim diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-audio.dtsi b/arch/arm/boot/dts/exynos5422-odroidxu3-audio.dtsi new file mode 100644 index 0000000..9493923 --- /dev/null +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-audio.dtsi @@ -0,0 +1,61 @@ +/* + * Hardkernel Odroid XU3 Audio Codec device tree source + * + * Copyright (c) 2015 Krzysztof Kozlowski + * Copyright (c) 2014 Collabora Ltd. + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/ { + sound: sound { + compatible = "simple-audio-card"; + + simple-audio-card,name = "Odroid-XU3"; + simple-audio-card,widgets = + "Headphone", "Headphone Jack", + "Speakers", "Speakers"; + simple-audio-card,routing = + "Headphone Jack", "HPL", + "Headphone Jack", "HPR", + "Headphone Jack", "MICBIAS", + "IN1", "Headphone Jack", + "Speakers", "SPKL", + "Speakers", "SPKR"; + + simple-audio-card,format = "i2s"; + simple-audio-card,bitclock-master = <&link0_codec>; + simple-audio-card,frame-master = <&link0_codec>; + + simple-audio-card,cpu { + sound-dai = <&i2s0 0>; + system-clock-frequency = <19200000>; + }; + + link0_codec: simple-audio-card,codec { + sound-dai = <&max98090>; + clocks = <&i2s0 CLK_I2S_CDCLK>; + }; + }; +}; + +&hsi2c_5 { + status = "okay"; + max98090: max98090@10 { + compatible = "maxim,max98090"; + reg = <0x10>; + interrupt-parent = <&gpx3>; + interrupts = <2 0>; + clocks = <&i2s0 CLK_I2S_CDCLK>; + clock-names = "mclk"; + #sound-dai-cells = <0>; + }; +}; + +&i2s0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi index 90d298d..2f0fb86 100644 --- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi @@ -80,36 +80,6 @@ }; }; - sound: sound { - compatible = "simple-audio-card"; - - simple-audio-card,name = "Odroid-XU3"; - simple-audio-card,widgets = - "Headphone", "Headphone Jack", - "Speakers", "Speakers"; - simple-audio-card,routing = - "Headphone Jack", "HPL", - "Headphone Jack", "HPR", - "Headphone Jack", "MICBIAS", - "IN1", "Headphone Jack", - "Speakers", "SPKL", - "Speakers", "SPKR"; - - simple-audio-card,format = "i2s"; - simple-audio-card,bitclock-master = <&link0_codec>; - simple-audio-card,frame-master = <&link0_codec>; - - simple-audio-card,cpu { - sound-dai = <&i2s0 0>; - system-clock-frequency = <19200000>; - }; - - link0_codec: simple-audio-card,codec { - sound-dai = <&max98090>; - clocks = <&i2s0 CLK_I2S_CDCLK>; - }; - }; - fan0: pwm-fan { compatible = "pwm-fan"; pwms = <&pwm 0 20972 0>; @@ -376,19 +346,6 @@ }; }; -&hsi2c_5 { - status = "okay"; - max98090: max98090@10 { - compatible = "maxim,max98090"; - reg = <0x10>; - interrupt-parent = <&gpx3>; - interrupts = <2 0>; - clocks = <&i2s0 CLK_I2S_CDCLK>; - clock-names = "mclk"; - #sound-dai-cells = <0>; - }; -}; - &i2c_2 { samsung,i2c-sda-delay = <100>; samsung,i2c-max-bus-freq = <66000>; @@ -400,10 +357,6 @@ }; }; -&i2s0 { - status = "okay"; -}; - &mfc { samsung,mfc-r = <0x43000000 0x800000>; samsung,mfc-l = <0x51000000 0x800000>; diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts b/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts index c06882b..9c0cea9 100644 --- a/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts @@ -13,6 +13,7 @@ /dts-v1/; #include "exynos5422-odroidxu3-common.dtsi" +#include "exynos5422-odroidxu3-audio.dtsi" / { model = "Hardkernel Odroid XU3 Lite"; diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3.dts b/arch/arm/boot/dts/exynos5422-odroidxu3.dts index 78e6a50..d8647a4 100644 --- a/arch/arm/boot/dts/exynos5422-odroidxu3.dts +++ b/arch/arm/boot/dts/exynos5422-odroidxu3.dts @@ -12,6 +12,7 @@ /dts-v1/; #include "exynos5422-odroidxu3-common.dtsi" +#include "exynos5422-odroidxu3-audio.dtsi" / { model = "Hardkernel Odroid XU3"; -- cgit v0.10.2 From 6658356014cbf772c7f11154adc0c46717b3322b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 16 Sep 2015 08:37:11 +0900 Subject: ARM: dts: Add support Odroid XU4 board for exynos5422-odroidxu4 Add Hardkernel Odroid XU4 board Device Tree sources. The board differs from Odroid XU3 and XU3-Lite by: 1. No green and red LEDs (except standard red power LED). 2. Only two PWM outputs are used (fan and blue LED) 3. No audio codec. 4. Two USB3 ports in host mode (no micro USB3 connector for OTG). 5. Realtek RTL8153-CG gigabit network adapter (instead of SMSC9514). 6. Additional connector with IO ports (I2S_0, I2C_5). 7. No DisplayPort (like XU3-Lite). 8. No TI INA231 power measurement sensors (like XU3-Lite). Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas Signed-off-by: Kukjin Kim diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 233159d..3d27fe3 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -123,6 +123,7 @@ dtb-$(CONFIG_ARCH_EXYNOS5) += \ exynos5420-smdk5420.dtb \ exynos5422-odroidxu3.dtb \ exynos5422-odroidxu3-lite.dtb \ + exynos5422-odroidxu4.dtb \ exynos5440-sd5v1.dtb \ exynos5440-ssdk5440.dtb \ exynos5800-peach-pi.dtb diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi index 2f0fb86..a83d569 100644 --- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi @@ -46,40 +46,6 @@ reset-gpios = <&gpd1 0 1>; }; - pwmleds { - compatible = "pwm-leds"; - - greenled { - label = "green:mmc0"; - pwms = <&pwm 1 2000000 0>; - pwm-names = "pwm1"; - /* - * Green LED is much brighter than the others - * so limit its max brightness - */ - max_brightness = <127>; - linux,default-trigger = "mmc0"; - }; - - blueled { - label = "blue:heartbeat"; - pwms = <&pwm 2 2000000 0>; - pwm-names = "pwm2"; - max_brightness = <255>; - linux,default-trigger = "heartbeat"; - }; - }; - - gpioleds { - compatible = "gpio-leds"; - redled { - label = "red:microSD"; - gpios = <&gpx2 3 GPIO_ACTIVE_HIGH>; - default-state = "off"; - linux,default-trigger = "mmc1"; - }; - }; - fan0: pwm-fan { compatible = "pwm-fan"; pwms = <&pwm 0 20972 0>; @@ -417,18 +383,6 @@ }; }; -&pwm { - /* - * PWM 0 -- fan - * PWM 1 -- Green LED - * PWM 2 -- Blue LED - * PWM 3 -- on MIPI connector for backlight - */ - pinctrl-0 = <&pwm0_out &pwm1_out &pwm2_out &pwm3_out>; - pinctrl-names = "default"; - status = "okay"; -}; - &tmu_cpu0 { vtmu-supply = <&ldo7_reg>; status = "okay"; @@ -464,9 +418,7 @@ dr_mode = "host"; }; -&usbdrd_dwc3_1 { - dr_mode = "otg"; -}; +/* usbdrd_dwc3_1 mode customized in each board */ &usbdrd3_0 { vdd33-supply = <&ldo9_reg>; diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts b/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts index 9c0cea9..b1b3608 100644 --- a/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts @@ -18,4 +18,54 @@ / { model = "Hardkernel Odroid XU3 Lite"; compatible = "hardkernel,odroid-xu3-lite", "samsung,exynos5800", "samsung,exynos5"; + + pwmleds { + compatible = "pwm-leds"; + + greenled { + label = "green:mmc0"; + pwms = <&pwm 1 2000000 0>; + pwm-names = "pwm1"; + /* + * Green LED is much brighter than the others + * so limit its max brightness + */ + max_brightness = <127>; + linux,default-trigger = "mmc0"; + }; + + blueled { + label = "blue:heartbeat"; + pwms = <&pwm 2 2000000 0>; + pwm-names = "pwm2"; + max_brightness = <255>; + linux,default-trigger = "heartbeat"; + }; + }; + + gpioleds { + compatible = "gpio-leds"; + redled { + label = "red:microSD"; + gpios = <&gpx2 3 GPIO_ACTIVE_HIGH>; + default-state = "off"; + linux,default-trigger = "mmc1"; + }; + }; +}; + +&pwm { + /* + * PWM 0 -- fan + * PWM 1 -- Green LED + * PWM 2 -- Blue LED + * PWM 3 -- on MIPI connector for backlight + */ + pinctrl-0 = <&pwm0_out &pwm1_out &pwm2_out &pwm3_out>; + pinctrl-names = "default"; + status = "okay"; +}; + +&usbdrd_dwc3_1 { + dr_mode = "otg"; }; diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3.dts b/arch/arm/boot/dts/exynos5422-odroidxu3.dts index d8647a4..0c0bbdb 100644 --- a/arch/arm/boot/dts/exynos5422-odroidxu3.dts +++ b/arch/arm/boot/dts/exynos5422-odroidxu3.dts @@ -17,6 +17,40 @@ / { model = "Hardkernel Odroid XU3"; compatible = "hardkernel,odroid-xu3", "samsung,exynos5800", "samsung,exynos5"; + + pwmleds { + compatible = "pwm-leds"; + + greenled { + label = "green:mmc0"; + pwms = <&pwm 1 2000000 0>; + pwm-names = "pwm1"; + /* + * Green LED is much brighter than the others + * so limit its max brightness + */ + max_brightness = <127>; + linux,default-trigger = "mmc0"; + }; + + blueled { + label = "blue:heartbeat"; + pwms = <&pwm 2 2000000 0>; + pwm-names = "pwm2"; + max_brightness = <255>; + linux,default-trigger = "heartbeat"; + }; + }; + + gpioleds { + compatible = "gpio-leds"; + redled { + label = "red:microSD"; + gpios = <&gpx2 3 GPIO_ACTIVE_HIGH>; + default-state = "off"; + linux,default-trigger = "mmc1"; + }; + }; }; &i2c_0 { @@ -50,3 +84,19 @@ shunt-resistor = <10000>; }; }; + +&pwm { + /* + * PWM 0 -- fan + * PWM 1 -- Green LED + * PWM 2 -- Blue LED + * PWM 3 -- on MIPI connector for backlight + */ + pinctrl-0 = <&pwm0_out &pwm1_out &pwm2_out &pwm3_out>; + pinctrl-names = "default"; + status = "okay"; +}; + +&usbdrd_dwc3_1 { + dr_mode = "otg"; +}; diff --git a/arch/arm/boot/dts/exynos5422-odroidxu4.dts b/arch/arm/boot/dts/exynos5422-odroidxu4.dts new file mode 100644 index 0000000..2faf886 --- /dev/null +++ b/arch/arm/boot/dts/exynos5422-odroidxu4.dts @@ -0,0 +1,48 @@ +/* + * Hardkernel Odroid XU4 board device tree source + * + * Copyright (c) 2015 Krzysztof Kozlowski + * Copyright (c) 2014 Collabora Ltd. + * Copyright (c) 2013-2015 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/dts-v1/; +#include "exynos5422-odroidxu3-common.dtsi" + +/ { + model = "Hardkernel Odroid XU4"; + compatible = "hardkernel,odroid-xu4", "samsung,exynos5800", \ + "samsung,exynos5"; + + pwmleds { + compatible = "pwm-leds"; + + blueled { + label = "blue:heartbeat"; + pwms = <&pwm 2 2000000 0>; + pwm-names = "pwm2"; + max_brightness = <255>; + linux,default-trigger = "heartbeat"; + }; + }; +}; + +&pwm { + /* + * PWM 0 -- fan + * PWM 2 -- Blue LED + */ + pinctrl-0 = <&pwm0_out &pwm2_out>; + pinctrl-names = "default"; + samsung,pwm-outputs = <0>, <2>; + status = "okay"; +}; + +&usbdrd_dwc3_1 { + dr_mode = "host"; +}; -- cgit v0.10.2 From 44103fcfef646b5d6a5a8f8f48a2abdc9e9dbdea Mon Sep 17 00:00:00 2001 From: Haibo Chen Date: Fri, 28 Aug 2015 17:09:34 +0800 Subject: ARM: imx_v6_v7_defconfig: enable imx6ul_tsc Enable imx6ul touchscreen controller Signed-off-by: Haibo Chen Signed-off-by: Shawn Guo diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 79194c6..61d4e02 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -159,6 +159,7 @@ CONFIG_MOUSE_PS2=m CONFIG_MOUSE_PS2_ELANTECH=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_EGALAX=y +CONFIG_TOUCHSCREEN_IMX6UL_TSC=y CONFIG_TOUCHSCREEN_MC13783=y CONFIG_TOUCHSCREEN_TSC2007=y CONFIG_TOUCHSCREEN_STMPE=y -- cgit v0.10.2 From ee4a5f838c8437484c9387e9ef9256332f07f3dd Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 5 Aug 2015 01:48:37 +0800 Subject: ARM: imx: add suspend/resume support for i.mx6ul This patch adds suspend function for i.MX6UL, it supports "standby" and "mem" mode, for "standby" mode, SoC will enter STOP mode only, while for "mem" mode, SoC will enter STOP mode and DDR IO will be set to low power mode. As i.MX6UL contains a "Cortex-A7" ARM core which has no PL310, so we need to avoid any PL310 operations during suspend/resume, also, we need to flush Cortex-A7's inernal L2 cache before suspend. Signed-off-by: Anson Huang diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index 21e4e86..e2d5383 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -131,6 +131,7 @@ void imx6q_pm_init(void); void imx6dl_pm_init(void); void imx6sl_pm_init(void); void imx6sx_pm_init(void); +void imx6ul_pm_init(void); #ifdef CONFIG_PM void imx51_pm_init(void); diff --git a/arch/arm/mach-imx/mach-imx6ul.c b/arch/arm/mach-imx/mach-imx6ul.c index 1b97fe1..be832b9 100644 --- a/arch/arm/mach-imx/mach-imx6ul.c +++ b/arch/arm/mach-imx/mach-imx6ul.c @@ -67,6 +67,7 @@ static void __init imx6ul_init_machine(void) of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); imx6ul_enet_init(); imx_anatop_init(); + imx6ul_pm_init(); } static void __init imx6ul_init_irq(void) @@ -74,6 +75,7 @@ static void __init imx6ul_init_irq(void) imx_init_revision_from_anatop(); imx_src_init(); irqchip_init(); + imx6_pm_ccm_init("fsl,imx6ul-ccm"); } static const char *imx6ul_dt_compat[] __initconst = { diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c index 8ff8fc0..4470376 100644 --- a/arch/arm/mach-imx/pm-imx6.c +++ b/arch/arm/mach-imx/pm-imx6.c @@ -93,6 +93,7 @@ struct imx6_pm_socdata { const char *src_compat; const char *iomuxc_compat; const char *gpc_compat; + const char *pl310_compat; const u32 mmdc_io_num; const u32 *mmdc_io_offset; }; @@ -137,11 +138,19 @@ static const u32 imx6sx_mmdc_io_offset[] __initconst = { 0x330, 0x334, 0x338, 0x33c, /* SDQS0 ~ SDQS3 */ }; +static const u32 imx6ul_mmdc_io_offset[] __initconst = { + 0x244, 0x248, 0x24c, 0x250, /* DQM0, DQM1, RAS, CAS */ + 0x27c, 0x498, 0x4a4, 0x490, /* SDCLK0, GPR_B0DS-B1DS, GPR_ADDS */ + 0x280, 0x284, 0x260, 0x264, /* SDQS0~1, SODT0, SODT1 */ + 0x494, 0x4b0, /* MODE_CTL, MODE, */ +}; + static const struct imx6_pm_socdata imx6q_pm_data __initconst = { .mmdc_compat = "fsl,imx6q-mmdc", .src_compat = "fsl,imx6q-src", .iomuxc_compat = "fsl,imx6q-iomuxc", .gpc_compat = "fsl,imx6q-gpc", + .pl310_compat = "arm,pl310-cache", .mmdc_io_num = ARRAY_SIZE(imx6q_mmdc_io_offset), .mmdc_io_offset = imx6q_mmdc_io_offset, }; @@ -151,6 +160,7 @@ static const struct imx6_pm_socdata imx6dl_pm_data __initconst = { .src_compat = "fsl,imx6q-src", .iomuxc_compat = "fsl,imx6dl-iomuxc", .gpc_compat = "fsl,imx6q-gpc", + .pl310_compat = "arm,pl310-cache", .mmdc_io_num = ARRAY_SIZE(imx6dl_mmdc_io_offset), .mmdc_io_offset = imx6dl_mmdc_io_offset, }; @@ -160,6 +170,7 @@ static const struct imx6_pm_socdata imx6sl_pm_data __initconst = { .src_compat = "fsl,imx6sl-src", .iomuxc_compat = "fsl,imx6sl-iomuxc", .gpc_compat = "fsl,imx6sl-gpc", + .pl310_compat = "arm,pl310-cache", .mmdc_io_num = ARRAY_SIZE(imx6sl_mmdc_io_offset), .mmdc_io_offset = imx6sl_mmdc_io_offset, }; @@ -169,10 +180,21 @@ static const struct imx6_pm_socdata imx6sx_pm_data __initconst = { .src_compat = "fsl,imx6sx-src", .iomuxc_compat = "fsl,imx6sx-iomuxc", .gpc_compat = "fsl,imx6sx-gpc", + .pl310_compat = "arm,pl310-cache", .mmdc_io_num = ARRAY_SIZE(imx6sx_mmdc_io_offset), .mmdc_io_offset = imx6sx_mmdc_io_offset, }; +static const struct imx6_pm_socdata imx6ul_pm_data __initconst = { + .mmdc_compat = "fsl,imx6ul-mmdc", + .src_compat = "fsl,imx6ul-src", + .iomuxc_compat = "fsl,imx6ul-iomuxc", + .gpc_compat = "fsl,imx6ul-gpc", + .pl310_compat = NULL, + .mmdc_io_num = ARRAY_SIZE(imx6ul_mmdc_io_offset), + .mmdc_io_offset = imx6ul_mmdc_io_offset, +}; + /* * This structure is for passing necessary data for low level ocram * suspend code(arch/arm/mach-imx/suspend-imx6.S), if this struct @@ -290,7 +312,7 @@ int imx6_set_lpm(enum mxc_cpu_pwr_mode mode) val |= BM_CLPCR_SBYOS; if (cpu_is_imx6sl()) val |= BM_CLPCR_BYPASS_PMIC_READY; - if (cpu_is_imx6sl() || cpu_is_imx6sx()) + if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul()) val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS; else val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS; @@ -330,6 +352,10 @@ static int imx6q_suspend_finish(unsigned long val) * as we need to float DDR IO. */ local_flush_tlb_all(); + /* check if need to flush internal L2 cache */ + if (!((struct imx6_cpu_pm_info *) + suspend_ocram_base)->l2_base.vbase) + flush_cache_all(); imx6_suspend_in_ocram_fn(suspend_ocram_base); } @@ -470,6 +496,7 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata) suspend_ocram_base = __arm_ioremap_exec(ocram_pbase, MX6Q_SUSPEND_OCRAM_SIZE, false); + memset(suspend_ocram_base, 0, sizeof(*pm_info)); pm_info = suspend_ocram_base; pm_info->pbase = ocram_pbase; pm_info->resume_addr = virt_to_phys(v7_cpu_resume); @@ -505,11 +532,13 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata) goto gpc_map_failed; } - ret = imx6_pm_get_base(&pm_info->l2_base, "arm,pl310-cache"); - if (ret) { - pr_warn("%s: failed to get pl310-cache base %d!\n", - __func__, ret); - goto pl310_cache_map_failed; + if (socdata->pl310_compat) { + ret = imx6_pm_get_base(&pm_info->l2_base, socdata->pl310_compat); + if (ret) { + pr_warn("%s: failed to get pl310-cache base %d!\n", + __func__, ret); + goto pl310_cache_map_failed; + } } pm_info->ddr_type = imx_mmdc_get_ddr_type(); @@ -610,3 +639,8 @@ void __init imx6sx_pm_init(void) { imx6_pm_common_init(&imx6sx_pm_data); } + +void __init imx6ul_pm_init(void) +{ + imx6_pm_common_init(&imx6ul_pm_data); +} diff --git a/arch/arm/mach-imx/suspend-imx6.S b/arch/arm/mach-imx/suspend-imx6.S index b99987b..76ee2ce 100644 --- a/arch/arm/mach-imx/suspend-imx6.S +++ b/arch/arm/mach-imx/suspend-imx6.S @@ -79,12 +79,15 @@ /* sync L2 cache to drain L2's buffers to DRAM. */ #ifdef CONFIG_CACHE_L2X0 ldr r11, [r0, #PM_INFO_MX6Q_L2_V_OFFSET] + teq r11, #0 + beq 6f mov r6, #0x0 str r6, [r11, #L2X0_CACHE_SYNC] 1: ldr r6, [r11, #L2X0_CACHE_SYNC] ands r6, r6, #0x1 bne 1b +6: #endif .endm -- cgit v0.10.2 From d9072a3e80bd0f2e95d6a452987899039ba808ed Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Tue, 15 Sep 2015 05:58:44 -0700 Subject: drm/i915: fix kernel-doc warnings in i915_gem.c Fix the following 'make htmldocs' warnings: .//drivers/gpu/drm/i915/i915_gem.c:1729: warning: No description found for parameter 'vma' .//drivers/gpu/drm/i915/i915_gem.c:1729: warning: No description found for parameter 'vmf' .//drivers/gpu/drm/i915/i915_gem.c:4962: warning: No description found for parameter 'old' .//drivers/gpu/drm/i915/i915_gem.c:4962: warning: No description found for parameter 'new' .//drivers/gpu/drm/i915/i915_gem.c:4962: warning: No description found for parameter 'frontbuffer_bits' Signed-off-by: Geliang Tang Signed-off-by: Jani Nikula diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index cb0df7e..e1b6457 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1713,8 +1713,8 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, /** * i915_gem_fault - fault a page into the GTT - * vma: VMA in question - * vmf: fault info + * @vma: VMA in question + * @vmf: fault info * * The fault handler is set up by drm_gem_mmap() when a object is GTT mapped * from userspace. The fault handler takes care of binding the object to @@ -4985,9 +4985,9 @@ int i915_gem_open(struct drm_device *dev, struct drm_file *file) /** * i915_gem_track_fb - update frontbuffer tracking - * old: current GEM buffer for the frontbuffer slots - * new: new GEM buffer for the frontbuffer slots - * frontbuffer_bits: bitmask of frontbuffer slots + * @old: current GEM buffer for the frontbuffer slots + * @new: new GEM buffer for the frontbuffer slots + * @frontbuffer_bits: bitmask of frontbuffer slots * * This updates the frontbuffer tracking bits @frontbuffer_bits by clearing them * from @old and setting them in @new. Both @old and @new can be NULL. -- cgit v0.10.2 From eb120ef6a3e18780e7464e7de70221d06dfe5845 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 15 Sep 2015 14:19:32 -0700 Subject: drm/i915: add more debug info for when atomic updates fail v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I used these additional fields to track down the issue I saw on HSW. v2: move debug fields into a substruct (Ville) v3: clean up debug code more (Ville) References: https://bugs.freedesktop.org/show_bug.cgi?id=91579 Signed-off-by: Jesse Barnes Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index e9e5cfd..8760814 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -565,8 +565,12 @@ struct intel_crtc { int scanline_offset; - unsigned start_vbl_count; - ktime_t start_vbl_time; + struct { + unsigned start_vbl_count; + ktime_t start_vbl_time; + int min_vbl, max_vbl; + int scanline_start; + } debug; struct intel_crtc_atomic_commit atomic; diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 4d27243..7de121d 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -95,7 +95,6 @@ void intel_pipe_update_start(struct intel_crtc *crtc) max = vblank_start - 1; local_irq_disable(); - crtc->start_vbl_count = 0; if (min <= 0 || max <= 0) return; @@ -134,11 +133,15 @@ void intel_pipe_update_start(struct intel_crtc *crtc) drm_crtc_vblank_put(&crtc->base); - crtc->start_vbl_time = ktime_get(); - crtc->start_vbl_count = dev->driver->get_vblank_counter(dev, pipe); + crtc->debug.min_vbl = min; + crtc->debug.max_vbl = max; + crtc->debug.scanline_start = scanline; + crtc->debug.start_vbl_time = ktime_get(); + crtc->debug.start_vbl_count = + dev->driver->get_vblank_counter(dev, pipe); trace_i915_pipe_update_vblank_evaded(crtc, min, max, - crtc->start_vbl_count); + crtc->debug.start_vbl_count); } /** @@ -154,6 +157,7 @@ void intel_pipe_update_end(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; enum pipe pipe = crtc->pipe; + int scanline_end = intel_get_crtc_scanline(crtc); u32 end_vbl_count = dev->driver->get_vblank_counter(dev, pipe); ktime_t end_vbl_time = ktime_get(); @@ -161,10 +165,15 @@ void intel_pipe_update_end(struct intel_crtc *crtc) local_irq_enable(); - if (crtc->start_vbl_count && crtc->start_vbl_count != end_vbl_count) - DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u) time %lld us\n", - pipe_name(pipe), crtc->start_vbl_count, end_vbl_count, - ktime_us_delta(end_vbl_time, crtc->start_vbl_time)); + if (crtc->debug.start_vbl_count && + crtc->debug.start_vbl_count != end_vbl_count) { + DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u) time %lld us, min %d, max %d, scanline start %d, end %d\n", + pipe_name(pipe), crtc->debug.start_vbl_count, + end_vbl_count, + ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time), + crtc->debug.min_vbl, crtc->debug.max_vbl, + crtc->debug.scanline_start, scanline_end); + } } static void -- cgit v0.10.2 From 1a344e9b7557a819b8143d7d7d4365b9694bb5e3 Mon Sep 17 00:00:00 2001 From: Franklin S Cooper Jr Date: Thu, 17 Sep 2015 09:03:52 -0700 Subject: ARM: dts: keystone: Add ti,keystone-spi for SPI Add ti,keystone-spi to the compatible field for the SPI node. This new entry insures that the proper prescaler limit is used for keystone devices Signed-off-by: Franklin S Cooper Jr Signed-off-by: Santosh Shilimkar diff --git a/arch/arm/boot/dts/keystone.dtsi b/arch/arm/boot/dts/keystone.dtsi index 72816d6..fbc4a8e 100644 --- a/arch/arm/boot/dts/keystone.dtsi +++ b/arch/arm/boot/dts/keystone.dtsi @@ -136,7 +136,7 @@ }; spi0: spi@21000400 { - compatible = "ti,dm6441-spi"; + compatible = "ti,keystone-spi", "ti,dm6441-spi"; reg = <0x21000400 0x200>; num-cs = <4>; ti,davinci-spi-intr-line = <0>; @@ -147,7 +147,7 @@ }; spi1: spi@21000600 { - compatible = "ti,dm6441-spi"; + compatible = "ti,keystone-spi", "ti,dm6441-spi"; reg = <0x21000600 0x200>; num-cs = <4>; ti,davinci-spi-intr-line = <0>; @@ -158,7 +158,7 @@ }; spi2: spi@21000800 { - compatible = "ti,dm6441-spi"; + compatible = "ti,keystone-spi", "ti,dm6441-spi"; reg = <0x21000800 0x200>; num-cs = <4>; ti,davinci-spi-intr-line = <0>; -- cgit v0.10.2 From 82f46c465149137a8d230b6c1e08c43bf6e32cdb Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 14 Sep 2015 12:04:22 -0700 Subject: Documentation: bindings: brcmstb: Document write-pairing Document the hif-cpubiuctrl node a bit more, and add a documentation entry for the optional "brcm,write-pairing" property. Acked-by: Rob Herring Acked-by: Gregory Fong Signed-off-by: Florian Fainelli diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,brcmstb.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,brcmstb.txt index 9442964..0d0c1ae 100644 --- a/Documentation/devicetree/bindings/arm/bcm/brcm,brcmstb.txt +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,brcmstb.txt @@ -20,6 +20,25 @@ system control is required: - compatible: "brcm,bcm-hif-cpubiuctrl", "syscon" - compatible: "brcm,bcm-hif-continuation", "syscon" +hif-cpubiuctrl node +------------------- +SoCs with Broadcom Brahma15 ARM-based CPUs have a specific Bus Interface Unit +(BIU) block which controls and interfaces the CPU complex to the different +Memory Controller Ports (MCP), one per memory controller (MEMC). This BIU block +offers a feature called Write Pairing which consists in collapsing two adjacent +cache lines into a single (bursted) write transaction towards the memory +controller (MEMC) to maximize write bandwidth. + +Required properties: + + - compatible: must be "brcm,bcm7445-hif-cpubiuctrl", "syscon" + +Optional properties: + + - brcm,write-pairing: + Boolean property, which when present indicates that the chip + supports write-pairing. + example: rdb { #address-cells = <1>; @@ -35,6 +54,7 @@ example: hif_cpubiuctrl: syscon@3e2400 { compatible = "brcm,bcm7445-hif-cpubiuctrl", "syscon"; reg = <0x3e2400 0x5b4>; + brcm,write-pairing; }; hif_continuation: syscon@452000 { -- cgit v0.10.2 From a918a7d2e3b14c9b33353bc2ef128ba53786eb40 Mon Sep 17 00:00:00 2001 From: Gerhard Bertelsmann Date: Wed, 16 Sep 2015 13:21:21 +0200 Subject: can: Allwinner A10/A20 CAN Controller support - Defconfig Defconfig sunxi for Allwinner A10/A20 CAN driver Signed-off-by: Gerhard Bertelsmann Signed-off-by: Maxime Ripard diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig index 94c6bd0..f5fa019 100644 --- a/arch/arm/configs/sunxi_defconfig +++ b/arch/arm/configs/sunxi_defconfig @@ -31,6 +31,8 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_LRO is not set # CONFIG_INET_DIAG is not set # CONFIG_IPV6 is not set +CONFIG_CAN=y +CONFIG_CAN_SUN4I=y # CONFIG_WIRELESS is not set CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y -- cgit v0.10.2 From 285547802936247adb77c192d08a1ddb97948bd6 Mon Sep 17 00:00:00 2001 From: Gerhard Bertelsmann Date: Wed, 16 Sep 2015 13:21:20 +0200 Subject: can: Allwinner A10/A20 CAN Controller support - Defconfig Defconfig multi_v7 for Allwinner A10/A20 CAN driver Signed-off-by: Gerhard Bertelsmann Signed-off-by: Maxime Ripard diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 03deb7f..8e4bca4 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -153,6 +153,7 @@ CONFIG_CAN_DEV=y CONFIG_CAN_AT91=m CONFIG_CAN_XILINXCAN=y CONFIG_CAN_MCP251X=y +CONFIG_CAN_SUN4I=y CONFIG_BT=m CONFIG_BT_MRVL=m CONFIG_BT_MRVL_SDIO=m -- cgit v0.10.2 From e233d74c30f48108b7affb4e76bfc8f3c76b68ce Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 4 Aug 2015 15:25:35 +0200 Subject: clk: shmobile: mstp: Consider "zb_clk" suitable for power management Currently the CPG/MSTP Clock Domain code looks for MSTP clocks to power manage a device. Unfortunately, on R-Mobile APE6 (r8a73a4) and SH-Mobile AG5 (sh73a0), the Bus State Controller (BSC) is not power-managed by an MSTP clock, but by a plain CPG clock (zb_clk). Add a special case to handle this, so the clock is properly managed, and devices connected to the BSC work as expected. Signed-off-by: Geert Uytterhoeven Reviewed-by: Ulf Hansson Acked-by: Stephen Boyd Signed-off-by: Simon Horman diff --git a/drivers/clk/shmobile/clk-mstp.c b/drivers/clk/shmobile/clk-mstp.c index b1df7b2..a0a56e9 100644 --- a/drivers/clk/shmobile/clk-mstp.c +++ b/drivers/clk/shmobile/clk-mstp.c @@ -259,6 +259,10 @@ int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev) "renesas,cpg-mstp-clocks")) goto found; + /* BSC on r8a73a4/sh73a0 uses zb_clk instead of an mstp clock */ + if (!strcmp(clkspec.np->name, "zb_clk")) + goto found; + of_node_put(clkspec.np); i++; } -- cgit v0.10.2 From 8b98d74780ab70147d40400c36059c16c1aea4da Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 4 Aug 2015 14:28:17 +0200 Subject: ARM: shmobile: R-Mobile: Use CPG/MSTP Clock Domain attach/detach helpers The R-Mobile PM Domain driver manages both power domains and a clock domain. The clock domain part is very similar to the CPG/MSTP Clock Domain, which is used on shmobile SoCs without device power domains, except for the way how clocks suitable for power management are selected: - The former uses the first clock tied to the device through the NULL con_id, which is a relic from the legacy pm_clk_notifier-based method in drivers/sh/pm_runtime.c, - The latter looks for suitable clocks in DT, which is more future-proof. All platforms using this driver are now supported in DT-based ARM multi-platform builds only, hence switch to using the CPG/MSTP Clock Domain helpers. Signed-off-by: Geert Uytterhoeven Reviewed-by: Ulf Hansson Signed-off-by: Simon Horman diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c index a5b96b9..89068c8 100644 --- a/arch/arm/mach-shmobile/pm-rmobile.c +++ b/arch/arm/mach-shmobile/pm-rmobile.c @@ -12,6 +12,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. */ +#include #include #include #include @@ -124,36 +125,6 @@ static bool rmobile_pd_active_wakeup(struct device *dev) return true; } -static int rmobile_pd_attach_dev(struct generic_pm_domain *domain, - struct device *dev) -{ - int error; - - error = pm_clk_create(dev); - if (error) { - dev_err(dev, "pm_clk_create failed %d\n", error); - return error; - } - - error = pm_clk_add(dev, NULL); - if (error) { - dev_err(dev, "pm_clk_add failed %d\n", error); - goto fail; - } - - return 0; - -fail: - pm_clk_destroy(dev); - return error; -} - -static void rmobile_pd_detach_dev(struct generic_pm_domain *domain, - struct device *dev) -{ - pm_clk_destroy(dev); -} - static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) { struct generic_pm_domain *genpd = &rmobile_pd->genpd; @@ -164,8 +135,8 @@ static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) genpd->dev_ops.active_wakeup = rmobile_pd_active_wakeup; genpd->power_off = rmobile_pd_power_down; genpd->power_on = rmobile_pd_power_up; - genpd->attach_dev = rmobile_pd_attach_dev; - genpd->detach_dev = rmobile_pd_detach_dev; + genpd->attach_dev = cpg_mstp_attach_dev; + genpd->detach_dev = cpg_mstp_detach_dev; __rmobile_pd_power_up(rmobile_pd, false); } -- cgit v0.10.2 From d1a9c24ad16ab2b26f1574bc3f2c165a7beff5df Mon Sep 17 00:00:00 2001 From: Holger Busse Date: Wed, 26 Aug 2015 10:45:45 +0200 Subject: ARM: at91/dt: corrections to i2c1 declaration to sama5d4 Correcting the dma declaration for i2c1 dma. Signed-off-by: Holger Busse Signed-off-by: Nicolas Ferre Fixes: 4cc7cdf35c5f ("ARM: at91/dt: add i2c1 declaration to sama5d4") Cc: stable@vger.kernel.org # v4.1+ diff --git a/arch/arm/boot/dts/sama5d4.dtsi b/arch/arm/boot/dts/sama5d4.dtsi index 8d1de29..fb92481 100644 --- a/arch/arm/boot/dts/sama5d4.dtsi +++ b/arch/arm/boot/dts/sama5d4.dtsi @@ -939,11 +939,11 @@ reg = <0xf8018000 0x4000>; interrupts = <33 IRQ_TYPE_LEVEL_HIGH 6>; dmas = <&dma1 - (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1)) - AT91_XDMAC_DT_PERID(4)>, + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) + | AT91_XDMAC_DT_PERID(4))>, <&dma1 - (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1)) - AT91_XDMAC_DT_PERID(5)>; + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) + | AT91_XDMAC_DT_PERID(5))>; dma-names = "tx", "rx"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c1>; -- cgit v0.10.2 From d637ce3f6dcc0bec950ed4e03e53162500d6b28b Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 17 Sep 2015 08:08:32 -0700 Subject: drm/i915: cleanup pipe_update trace functions with new crtc debug info v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the new debug info in the intel_crtc struct in these functions rather than passing them as args. v2: move min/max assignment back above first trace call (Ville) use scanline from crtc->debug rather than fetching a new one (Ville) v3: fix up trace_i915_pipe_update_end, needs end scanline (Ville) Requested-by: Ville Syrjälä Signed-off-by: Jesse Barnes Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index e6b5c74..d0993bc 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -17,8 +17,8 @@ /* pipe updates */ TRACE_EVENT(i915_pipe_update_start, - TP_PROTO(struct intel_crtc *crtc, u32 min, u32 max), - TP_ARGS(crtc, min, max), + TP_PROTO(struct intel_crtc *crtc), + TP_ARGS(crtc), TP_STRUCT__entry( __field(enum pipe, pipe) @@ -33,8 +33,8 @@ TRACE_EVENT(i915_pipe_update_start, __entry->frame = crtc->base.dev->driver->get_vblank_counter(crtc->base.dev, crtc->pipe); __entry->scanline = intel_get_crtc_scanline(crtc); - __entry->min = min; - __entry->max = max; + __entry->min = crtc->debug.min_vbl; + __entry->max = crtc->debug.max_vbl; ), TP_printk("pipe %c, frame=%u, scanline=%u, min=%u, max=%u", @@ -43,8 +43,8 @@ TRACE_EVENT(i915_pipe_update_start, ); TRACE_EVENT(i915_pipe_update_vblank_evaded, - TP_PROTO(struct intel_crtc *crtc, u32 min, u32 max, u32 frame), - TP_ARGS(crtc, min, max, frame), + TP_PROTO(struct intel_crtc *crtc), + TP_ARGS(crtc), TP_STRUCT__entry( __field(enum pipe, pipe) @@ -56,10 +56,10 @@ TRACE_EVENT(i915_pipe_update_vblank_evaded, TP_fast_assign( __entry->pipe = crtc->pipe; - __entry->frame = frame; - __entry->scanline = intel_get_crtc_scanline(crtc); - __entry->min = min; - __entry->max = max; + __entry->frame = crtc->debug.start_vbl_count; + __entry->scanline = crtc->debug.scanline_start; + __entry->min = crtc->debug.min_vbl; + __entry->max = crtc->debug.max_vbl; ), TP_printk("pipe %c, frame=%u, scanline=%u, min=%u, max=%u", @@ -68,8 +68,8 @@ TRACE_EVENT(i915_pipe_update_vblank_evaded, ); TRACE_EVENT(i915_pipe_update_end, - TP_PROTO(struct intel_crtc *crtc, u32 frame), - TP_ARGS(crtc, frame), + TP_PROTO(struct intel_crtc *crtc, u32 frame, int scanline_end), + TP_ARGS(crtc, frame, scanline_end), TP_STRUCT__entry( __field(enum pipe, pipe) @@ -80,7 +80,7 @@ TRACE_EVENT(i915_pipe_update_end, TP_fast_assign( __entry->pipe = crtc->pipe; __entry->frame = frame; - __entry->scanline = intel_get_crtc_scanline(crtc); + __entry->scanline = scanline_end; ), TP_printk("pipe %c, frame=%u, scanline=%u", diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 7de121d..79f7cc2 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -102,7 +102,9 @@ void intel_pipe_update_start(struct intel_crtc *crtc) if (WARN_ON(drm_crtc_vblank_get(&crtc->base))) return; - trace_i915_pipe_update_start(crtc, min, max); + crtc->debug.min_vbl = min; + crtc->debug.max_vbl = max; + trace_i915_pipe_update_start(crtc); for (;;) { /* @@ -133,15 +135,12 @@ void intel_pipe_update_start(struct intel_crtc *crtc) drm_crtc_vblank_put(&crtc->base); - crtc->debug.min_vbl = min; - crtc->debug.max_vbl = max; crtc->debug.scanline_start = scanline; crtc->debug.start_vbl_time = ktime_get(); crtc->debug.start_vbl_count = dev->driver->get_vblank_counter(dev, pipe); - trace_i915_pipe_update_vblank_evaded(crtc, min, max, - crtc->debug.start_vbl_count); + trace_i915_pipe_update_vblank_evaded(crtc); } /** @@ -161,7 +160,7 @@ void intel_pipe_update_end(struct intel_crtc *crtc) u32 end_vbl_count = dev->driver->get_vblank_counter(dev, pipe); ktime_t end_vbl_time = ktime_get(); - trace_i915_pipe_update_end(crtc, end_vbl_count); + trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end); local_irq_enable(); -- cgit v0.10.2 From 9aa6114253a9d01513796f6b44eda9838dc7bf3b Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Mon, 14 Sep 2015 19:24:18 -0700 Subject: drm/i915: Don't leak VBT mode data We allocate memory for LVDS modes while parsing the VBT at startup, but never free this memory when the driver is unloaded, causing a small leak. Signed-off-by: Matt Roper Signed-off-by: Jani Nikula diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 066a0ef..c069550 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1137,6 +1137,10 @@ int i915_driver_unload(struct drm_device *dev) dev_priv->vbt.child_dev = NULL; dev_priv->vbt.child_dev_num = 0; } + kfree(dev_priv->vbt.sdvo_lvds_vbt_mode); + dev_priv->vbt.sdvo_lvds_vbt_mode = NULL; + kfree(dev_priv->vbt.lfp_lvds_vbt_mode); + dev_priv->vbt.lfp_lvds_vbt_mode = NULL; vga_switcheroo_unregister_client(dev->pdev); vga_client_register(dev->pdev, NULL, NULL, NULL); -- cgit v0.10.2 From b5dada82ad624b69a2229c819d6a30b664a5606f Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Thu, 17 Sep 2015 14:20:32 +0100 Subject: drm/i915/bxt: Fix wrongly placed ')' in I915_READ() Not the first time! not the last time? There is a possibility to use gcc 5's -Wbool-compare to try and compare (reg) in those macros to a constant and gcc will warn that the comparison between a boolean expression and a constant is always either true or false. Maybe. Cc: Imre Deak Signed-off-by: Damien Lespiau Reviewed-by: Imre Deak Signed-off-by: Jani Nikula diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 4823184..5b600bf 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2882,7 +2882,7 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, * here just read out lanes 0/1 and output a note if lanes 2/3 differ. */ hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(port)); - if (I915_READ(BXT_PORT_PCS_DW12_LN23(port) != hw_state->pcsdw12)) + if (I915_READ(BXT_PORT_PCS_DW12_LN23(port)) != hw_state->pcsdw12) DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n", hw_state->pcsdw12, I915_READ(BXT_PORT_PCS_DW12_LN23(port))); -- cgit v0.10.2 From 7b6521f112afcbb6555cf119c2eefb21dee5eae8 Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Mon, 30 Mar 2015 18:40:22 +0800 Subject: ARM: at91/dt: at91sam9n12ek: fix the led labels name Correct the led labels in at91sam9n12ek. Signed-off-by: Josh Wu Signed-off-by: Nicolas Ferre diff --git a/arch/arm/boot/dts/at91sam9n12ek.dts b/arch/arm/boot/dts/at91sam9n12ek.dts index efa7506..186a170 100644 --- a/arch/arm/boot/dts/at91sam9n12ek.dts +++ b/arch/arm/boot/dts/at91sam9n12ek.dts @@ -204,13 +204,13 @@ }; d9 { - label = "d6"; + label = "d9"; gpios = <&pioB 5 GPIO_ACTIVE_LOW>; linux,default-trigger = "nand-disk"; }; d10 { - label = "d7"; + label = "d10"; gpios = <&pioB 6 GPIO_ACTIVE_HIGH>; linux,default-trigger = "heartbeat"; }; -- cgit v0.10.2 From eed7c4e611a7feaacb70fca1c3180af4edef4562 Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Thu, 11 Sep 2014 09:29:12 +0800 Subject: ARM: at91/dt: at91sam9n12ek: disable i2c1 No device connect to i2c1, so remove it to keep it as disabled. Signed-off-by: Bo Shen Signed-off-by: Nicolas Ferre diff --git a/arch/arm/boot/dts/at91sam9n12ek.dts b/arch/arm/boot/dts/at91sam9n12ek.dts index 186a170..acf3451 100644 --- a/arch/arm/boot/dts/at91sam9n12ek.dts +++ b/arch/arm/boot/dts/at91sam9n12ek.dts @@ -71,10 +71,6 @@ }; }; - i2c1: i2c@f8014000 { - status = "okay"; - }; - mmc0: mmc@f0008000 { pinctrl-0 = < &pinctrl_board_mmc0 -- cgit v0.10.2 From 7c08d8cda1dd0fb304e8171dce4300fc92907bd9 Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Fri, 12 Jul 2013 18:17:00 +0800 Subject: ARM: at91/dt: at91sam9x5: enable iio touchscreen for 9x5ek Signed-off-by: Josh Wu Signed-off-by: Nicolas Ferre diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index 747d8f0..9df8ca5 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi @@ -68,7 +68,7 @@ adc_op_clk: adc_op_clk{ compatible = "fixed-clock"; #clock-cells = <0>; - clock-frequency = <5000000>; + clock-frequency = <1000000>; }; }; @@ -1043,6 +1043,7 @@ atmel,adc-channels-used = <0xffff>; atmel,adc-vref = <3300>; atmel,adc-startup-time = <40>; + atmel,adc-sample-hold-time = <11>; atmel,adc-res = <8 10>; atmel,adc-res-names = "lowres", "highres"; atmel,adc-use-res = "highres"; diff --git a/arch/arm/boot/dts/at91sam9x5ek.dtsi b/arch/arm/boot/dts/at91sam9x5ek.dtsi index d237c46..36de329 100644 --- a/arch/arm/boot/dts/at91sam9x5ek.dtsi +++ b/arch/arm/boot/dts/at91sam9x5ek.dtsi @@ -100,6 +100,12 @@ }; }; + adc0: adc@f804c000 { + atmel,adc-ts-wires = <4>; + atmel,adc-ts-pressure-threshold = <10000>; + status = "okay"; + }; + pinctrl@fffff400 { camera_sensor { pinctrl_pck0_as_isi_mck: pck0_as_isi_mck-0 { -- cgit v0.10.2 From 19146e7e91bd1c1d0838c44808bad151dee0d2e6 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Fri, 17 Apr 2015 15:27:19 +0200 Subject: ARM: at91/dt: sama5d3 xplained: disable pmic As PMIC act8865 can disturb communication on i2c1, and as it should be setup correctly then its i2c interface disabled by bootloader, we simply disregard it in DT. Acked-by: Wenyou Yang Signed-off-by: Nicolas Ferre diff --git a/arch/arm/boot/dts/at91-sama5d3_xplained.dts b/arch/arm/boot/dts/at91-sama5d3_xplained.dts index d81474e..8488ac5 100644 --- a/arch/arm/boot/dts/at91-sama5d3_xplained.dts +++ b/arch/arm/boot/dts/at91-sama5d3_xplained.dts @@ -76,7 +76,7 @@ pmic: act8865@5b { compatible = "active-semi,act8865"; reg = <0x5b>; - status = "okay"; + status = "disabled"; regulators { vcc_1v8_reg: DCDC_REG1 { -- cgit v0.10.2 From cb3651d7be288573591e9e21f3ba7e8258efa4c6 Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Wed, 28 Jan 2015 14:39:34 +0100 Subject: ARM: at91/dt: sama5d3: update iio config for touchscreen Signed-off-by: Josh Wu Signed-off-by: Nicolas Ferre diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi index 7fa2765..1832736 100644 --- a/arch/arm/boot/dts/sama5d3.dtsi +++ b/arch/arm/boot/dts/sama5d3.dtsi @@ -75,7 +75,7 @@ adc_op_clk: adc_op_clk{ compatible = "fixed-clock"; #clock-cells = <0>; - clock-frequency = <20000000>; + clock-frequency = <1000000>; }; }; @@ -322,6 +322,7 @@ atmel,adc-use-external-triggers; atmel,adc-vref = <3000>; atmel,adc-res = <10 12>; + atmel,adc-sample-hold-time = <11>; atmel,adc-res-names = "lowres", "highres"; status = "disabled"; -- cgit v0.10.2 From 679f8d92bb015cfe2af4fddbe22a6689609c4ec6 Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Thu, 23 Apr 2015 10:07:18 +0200 Subject: ARM: at91/dt: sama5d4: add pioD pin mux mask and enable pioD Signed-off-by: Josh Wu Signed-off-by: Nicolas Ferre diff --git a/arch/arm/boot/dts/sama5d4.dtsi b/arch/arm/boot/dts/sama5d4.dtsi index fb92481..c367153 100644 --- a/arch/arm/boot/dts/sama5d4.dtsi +++ b/arch/arm/boot/dts/sama5d4.dtsi @@ -1350,7 +1350,7 @@ 0xffffffff 0x3ffcfe7c 0x1c010101 /* pioA */ 0x7fffffff 0xfffccc3a 0x3f00cc3a /* pioB */ 0xffffffff 0x3ff83fff 0xff00ffff /* pioC */ - 0x00000000 0x00000000 0x00000000 /* pioD */ + 0x0003ff00 0x8002a800 0x00000000 /* pioD */ 0xffffffff 0x7fffffff 0x76fff1bf /* pioE */ >; @@ -1396,7 +1396,6 @@ interrupt-controller; #interrupt-cells = <2>; clocks = <&pioD_clk>; - status = "disabled"; }; pioE: gpio@fc06d000 { -- cgit v0.10.2 From 4288ac7b882d2669fe4b795971392aadb7168fa8 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 7 Apr 2015 14:28:53 +0200 Subject: ARM: at91/dt: sama5d4: enable crypto nodes The crypto modules will provide HW AES/TDES/SHA for any sama5d4 board. Enable them by default. Signed-off-by: Nicolas Ferre diff --git a/arch/arm/boot/dts/sama5d4.dtsi b/arch/arm/boot/dts/sama5d4.dtsi index c367153..9760a75 100644 --- a/arch/arm/boot/dts/sama5d4.dtsi +++ b/arch/arm/boot/dts/sama5d4.dtsi @@ -1238,7 +1238,7 @@ dma-names = "tx", "rx"; clocks = <&aes_clk>; clock-names = "aes_clk"; - status = "disabled"; + status = "okay"; }; tdes@fc04c000 { @@ -1252,7 +1252,7 @@ dma-names = "tx", "rx"; clocks = <&tdes_clk>; clock-names = "tdes_clk"; - status = "disabled"; + status = "okay"; }; sha@fc050000 { @@ -1264,7 +1264,7 @@ dma-names = "tx"; clocks = <&sha_clk>; clock-names = "sha_clk"; - status = "disabled"; + status = "okay"; }; rstc@fc068600 { -- cgit v0.10.2 From a21a6c47f53c575082800cd311a9ab0bd3b52809 Mon Sep 17 00:00:00 2001 From: Patrice Vilchez Date: Mon, 12 Jan 2015 11:34:45 +0100 Subject: ARM: at91/dt: sama5d4ek: Add support of QT1070 and Maxtouch As the EK board comes with a PDA 7" screen, add the touch buttons and touchscreen for it. Signed-off-by: Patrice Vilchez [nicolas.ferre@atmel.com: add commit message] Signed-off-by: Nicolas Ferre diff --git a/arch/arm/boot/dts/at91-sama5d4ek.dts b/arch/arm/boot/dts/at91-sama5d4ek.dts index 49a59c7..6d272c0 100644 --- a/arch/arm/boot/dts/at91-sama5d4ek.dts +++ b/arch/arm/boot/dts/at91-sama5d4ek.dts @@ -148,6 +148,25 @@ clocks = <&pck2>; clock-names = "mclk"; }; + + qt1070:keyboard@1b { + compatible = "qt1070"; + reg = <0x1b>; + interrupt-parent = <&pioE>; + interrupts = <25 0x0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_qt1070_irq>; + wakeup-source; + }; + + atmel_mxt_ts@4c { + compatible = "atmel,atmel_mxt_ts"; + reg = <0x4c>; + interrupt-parent = <&pioE>; + interrupts = <24 0x0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mxt_ts>; + }; }; macb0: ethernet@f8020000 { @@ -204,6 +223,14 @@ atmel,pins = ; /* PE13 gpio */ }; + pinctrl_qt1070_irq: qt1070_irq { + atmel,pins = + ; + }; + pinctrl_mxt_ts: mxt_irq { + atmel,pins = + ; + }; }; }; }; -- cgit v0.10.2 From 4a43c3b8d8c085d643786c7b69a75f72770fe04b Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Thu, 23 Apr 2015 10:08:04 +0200 Subject: ARM: at91/dt: sama5d4 xplained: enable the led D8 Enable D8 led as now the pioD is available. D8 is the power led and is on by default. Signed-off-by: Josh Wu [nicolas.ferre@atmel.com: split the patch in 2] Signed-off-by: Nicolas Ferre diff --git a/arch/arm/boot/dts/at91-sama5d4_xplained.dts b/arch/arm/boot/dts/at91-sama5d4_xplained.dts index 07f4696..45371a1 100644 --- a/arch/arm/boot/dts/at91-sama5d4_xplained.dts +++ b/arch/arm/boot/dts/at91-sama5d4_xplained.dts @@ -246,7 +246,7 @@ d8 { label = "d8"; gpios = <&pioD 30 GPIO_ACTIVE_HIGH>; - status = "disabled"; + default-state = "on"; }; d10 { -- cgit v0.10.2 From 8dca5ce893e8d6b7e6b03f0df03375fb26b846ec Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 2 Sep 2015 18:24:21 +0200 Subject: MAINTAINERS: explicitly add Atmel SAMA5 Atmel SAMA5 SoCs are also supported through mach-at91. Signed-off-by: Alexandre Belloni Signed-off-by: Nicolas Ferre diff --git a/MAINTAINERS b/MAINTAINERS index 7ba7ab7..1bec767 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -911,7 +911,7 @@ M: Tsahee Zidenberg S: Maintained F: arch/arm/mach-alpine/ -ARM/ATMEL AT91RM9200 AND AT91SAM ARM ARCHITECTURES +ARM/ATMEL AT91RM9200, AT91SAM9 AND SAMA5 SOC SUPPORT M: Nicolas Ferre M: Alexandre Belloni M: Jean-Christophe Plagniol-Villard -- cgit v0.10.2 From d6157e4f18173ad24441aa9ca04e7e9121a9b4c7 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 10 Aug 2015 16:41:45 +0200 Subject: ARM: at91: remove useless includes in platform_data/atmel.h include/linux/platform_data/atmel.h has a lot of useless includes, remove them. Signed-off-by: Alexandre Belloni Signed-off-by: Nicolas Ferre diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h index 527a85c..4d67a5e 100644 --- a/include/linux/platform_data/atmel.h +++ b/include/linux/platform_data/atmel.h @@ -9,15 +9,7 @@ #include #include -#include -#include -#include -#include -#include -#include -#include #include -#include /* * at91: 6 USARTs and one DBGU port (SAM9260) -- cgit v0.10.2 From 487eacb9fc184eb6e54b299df3faf3ee57ace5df Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Mon, 14 Sep 2015 14:42:12 +0800 Subject: arm: dts: berlin: add aliases for serial This is to prepare for the using stdout-path in next commit. Signed-off-by: Jisheng Zhang Signed-off-by: Sebastian Hesselbarth diff --git a/arch/arm/boot/dts/berlin2.dtsi b/arch/arm/boot/dts/berlin2.dtsi index ef811de..40cf262 100644 --- a/arch/arm/boot/dts/berlin2.dtsi +++ b/arch/arm/boot/dts/berlin2.dtsi @@ -47,6 +47,12 @@ model = "Marvell Armada 1500 (BG2) SoC"; compatible = "marvell,berlin2", "marvell,berlin"; + aliases { + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + }; + cpus { #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/berlin2cd.dtsi b/arch/arm/boot/dts/berlin2cd.dtsi index 900213d..6246aec 100644 --- a/arch/arm/boot/dts/berlin2cd.dtsi +++ b/arch/arm/boot/dts/berlin2cd.dtsi @@ -47,6 +47,11 @@ model = "Marvell Armada 1500-mini (BG2CD) SoC"; compatible = "marvell,berlin2cd", "marvell,berlin"; + aliases { + serial0 = &uart0; + serial1 = &uart1; + }; + cpus { #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/berlin2q.dtsi b/arch/arm/boot/dts/berlin2q.dtsi index 63a4849..380fa18 100644 --- a/arch/arm/boot/dts/berlin2q.dtsi +++ b/arch/arm/boot/dts/berlin2q.dtsi @@ -43,6 +43,11 @@ model = "Marvell Armada 1500 pro (BG2-Q) SoC"; compatible = "marvell,berlin2q", "marvell,berlin"; + aliases { + serial0 = &uart0; + serial1 = &uart1; + }; + cpus { #address-cells = <1>; #size-cells = <0>; -- cgit v0.10.2 From c56e1a2be1cec29fb1de9358b0b2b20582cdca30 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Mon, 14 Sep 2015 14:42:13 +0800 Subject: arm: dts: berlin: use stdout-path Use stdout-path to specify the console and remove the console argument from the kernel command line. Signed-off-by: Jisheng Zhang Signed-off-by: Sebastian Hesselbarth diff --git a/arch/arm/boot/dts/berlin2-sony-nsz-gs7.dts b/arch/arm/boot/dts/berlin2-sony-nsz-gs7.dts index 5c99fb3..3c0907b 100644 --- a/arch/arm/boot/dts/berlin2-sony-nsz-gs7.dts +++ b/arch/arm/boot/dts/berlin2-sony-nsz-gs7.dts @@ -45,7 +45,8 @@ compatible = "sony,nsz-gs7", "marvell,berlin2", "marvell,berlin"; chosen { - bootargs = "console=ttyS0,115200 earlyprintk"; + bootargs = "earlyprintk"; + stdout-path = "serial0:115200n8"; }; memory { diff --git a/arch/arm/boot/dts/berlin2cd-google-chromecast.dts b/arch/arm/boot/dts/berlin2cd-google-chromecast.dts index 772165a..8ba8b50 100644 --- a/arch/arm/boot/dts/berlin2cd-google-chromecast.dts +++ b/arch/arm/boot/dts/berlin2cd-google-chromecast.dts @@ -46,7 +46,8 @@ compatible = "google,chromecast", "marvell,berlin2cd", "marvell,berlin"; chosen { - bootargs = "console=ttyS0,115200 earlyprintk"; + bootargs = "earlyprintk"; + stdout-path = "serial0:115200n8"; }; memory { diff --git a/arch/arm/boot/dts/berlin2q-marvell-dmp.dts b/arch/arm/boot/dts/berlin2q-marvell-dmp.dts index 4a749e5..da28c97 100644 --- a/arch/arm/boot/dts/berlin2q-marvell-dmp.dts +++ b/arch/arm/boot/dts/berlin2q-marvell-dmp.dts @@ -49,7 +49,8 @@ }; choosen { - bootargs = "console=ttyS0,115200 earlyprintk"; + bootargs = "earlyprintk"; + stdout-path = "serial0:115200n8"; }; regulators { -- cgit v0.10.2 From 5cfc5220a63b1008e7198fb4f91c3ef763e46657 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Fri, 18 Sep 2015 10:14:41 +0300 Subject: ARM: pxa: Remove unused clock_enable field from struct pxa2xx_spi_master Use for struct pxa2xx_spi_master clock_enable field was removed years ago from the pxa2xx-spi driver by the commit 2f1a74e5a2de ("[ARM] pxa: make pxa2xx_spi driver use ssp_request()/ssp_free()"). Therefore remove it from structure definition, documentation and from couple affected board files. Signed-off-by: Jarkko Nikula Acked-by: Mark Brown Signed-off-by: Robert Jarzmik diff --git a/Documentation/spi/pxa2xx b/Documentation/spi/pxa2xx index 3352f97..13a0b7f 100644 --- a/Documentation/spi/pxa2xx +++ b/Documentation/spi/pxa2xx @@ -22,15 +22,10 @@ Typically a SPI master is defined in the arch/.../mach-*/board-*.c as a found in include/linux/spi/pxa2xx_spi.h: struct pxa2xx_spi_master { - u32 clock_enable; u16 num_chipselect; u8 enable_dma; }; -The "pxa2xx_spi_master.clock_enable" field is used to enable/disable the -corresponding SSP peripheral block in the "Clock Enable Register (CKEN"). See -the "PXA2xx Developer Manual" section "Clocks and Power Management". - The "pxa2xx_spi_master.num_chipselect" field is used to determine the number of slave device (chips) attached to this SPI master. @@ -57,7 +52,6 @@ static struct resource pxa_spi_nssp_resources[] = { }; static struct pxa2xx_spi_master pxa_nssp_master_info = { - .clock_enable = CKEN_NSSP, /* NSSP Peripheral clock */ .num_chipselect = 1, /* Matches the number of chips attached to NSSP */ .enable_dma = 1, /* Enables NSSP DMA */ }; diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c index 5fb41ad..1e0301a 100644 --- a/arch/arm/mach-pxa/hx4700.c +++ b/arch/arm/mach-pxa/hx4700.c @@ -630,7 +630,6 @@ static struct spi_board_info tsc2046_board_info[] __initdata = { static struct pxa2xx_spi_master pxa_ssp2_master_info = { .num_chipselect = 1, - .clock_enable = CKEN_SSP2, .enable_dma = 1, }; diff --git a/arch/arm/mach-pxa/icontrol.c b/arch/arm/mach-pxa/icontrol.c index 9b0eb02..a1869f9 100644 --- a/arch/arm/mach-pxa/icontrol.c +++ b/arch/arm/mach-pxa/icontrol.c @@ -116,13 +116,11 @@ static struct spi_board_info mcp251x_board_info[] = { }; static struct pxa2xx_spi_master pxa_ssp3_spi_master_info = { - .clock_enable = CKEN_SSP3, .num_chipselect = 2, .enable_dma = 1 }; static struct pxa2xx_spi_master pxa_ssp4_spi_master_info = { - .clock_enable = CKEN_SSP4, .num_chipselect = 2, .enable_dma = 1 }; diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c index e1a121b..3deeca7b 100644 --- a/arch/arm/mach-pxa/z2.c +++ b/arch/arm/mach-pxa/z2.c @@ -595,13 +595,11 @@ static struct spi_board_info spi_board_info[] __initdata = { }; static struct pxa2xx_spi_master pxa_ssp1_master_info = { - .clock_enable = CKEN_SSP, .num_chipselect = 1, .enable_dma = 1, }; static struct pxa2xx_spi_master pxa_ssp2_master_info = { - .clock_enable = CKEN_SSP2, .num_chipselect = 1, }; diff --git a/include/linux/spi/pxa2xx_spi.h b/include/linux/spi/pxa2xx_spi.h index 6d36dac..9ec4c14 100644 --- a/include/linux/spi/pxa2xx_spi.h +++ b/include/linux/spi/pxa2xx_spi.h @@ -23,7 +23,6 @@ struct dma_chan; /* device.platform_data for SSP controller devices */ struct pxa2xx_spi_master { - u32 clock_enable; u16 num_chipselect; u8 enable_dma; -- cgit v0.10.2 From c582fbfba581d1331a52a85f0d712b0b7ec961c3 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Fri, 18 Sep 2015 21:47:37 +0800 Subject: arm64: berlin: enable ARCH_REQUIRE_GPIOLIB All berlin SoCs have GPIOs driven by the dwapb GPIO driver. Add GPIOLIB as a dependency to be able to support them. Signed-off-by: Jisheng Zhang Signed-off-by: Sebastian Hesselbarth diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index 23800a1..c6e2c75 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -7,6 +7,7 @@ config ARCH_BCM_IPROC config ARCH_BERLIN bool "Marvell Berlin SoC Family" + select ARCH_REQUIRE_GPIOLIB select DW_APB_ICTL help This enables support for Marvell Berlin SoC Family -- cgit v0.10.2 From 8884d8c7cc2fd8b8cd188204f340d16b3972deb0 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Fri, 18 Sep 2015 21:47:38 +0800 Subject: arm64: dts: berlin4ct: add GPIO nodes Marvell berlin4ct SoC has 6 GPIO ports powered by snps,dw-apb-gpio. This patch adds the corresponding device tree nodes. Signed-off-by: Jisheng Zhang Signed-off-by: Sebastian Hesselbarth diff --git a/arch/arm64/boot/dts/marvell/berlin4ct.dtsi b/arch/arm64/boot/dts/marvell/berlin4ct.dtsi index dd4a10d..a3b5f1d 100644 --- a/arch/arm64/boot/dts/marvell/berlin4ct.dtsi +++ b/arch/arm64/boot/dts/marvell/berlin4ct.dtsi @@ -135,6 +135,96 @@ interrupts = ; }; + apb@e80000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + + ranges = <0 0xe80000 0x10000>; + interrupt-parent = <&aic>; + + gpio0: gpio@0400 { + compatible = "snps,dw-apb-gpio"; + reg = <0x0400 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + porta: gpio-port@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + snps,nr-gpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <0>; + }; + }; + + gpio1: gpio@0800 { + compatible = "snps,dw-apb-gpio"; + reg = <0x0800 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + portb: gpio-port@1 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + snps,nr-gpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <1>; + }; + }; + + gpio2: gpio@0c00 { + compatible = "snps,dw-apb-gpio"; + reg = <0x0c00 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + portc: gpio-port@2 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + snps,nr-gpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <2>; + }; + }; + + gpio3: gpio@1000 { + compatible = "snps,dw-apb-gpio"; + reg = <0x1000 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + portd: gpio-port@3 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + snps,nr-gpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <3>; + }; + }; + + aic: interrupt-controller@3800 { + compatible = "snps,dw-apb-ictl"; + reg = <0x3800 0x30>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&gic>; + interrupts = ; + }; + }; + apb@fc0000 { compatible = "simple-bus"; #address-cells = <1>; @@ -151,6 +241,36 @@ interrupts = ; }; + sm_gpio0: gpio@8000 { + compatible = "snps,dw-apb-gpio"; + reg = <0x8000 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + porte: gpio-port@4 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + snps,nr-gpios = <32>; + reg = <0>; + }; + }; + + sm_gpio1: gpio@9000 { + compatible = "snps,dw-apb-gpio"; + reg = <0x9000 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + portf: gpio-port@5 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + snps,nr-gpios = <32>; + reg = <0>; + }; + }; + uart0: uart@d000 { compatible = "snps,dw-apb-uart"; reg = <0xd000 0x100>; -- cgit v0.10.2 From 59995f55973e23d957f1dad13446554f6aef73d0 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Fri, 18 Sep 2015 21:47:39 +0800 Subject: arm64: dts: add dts file for Marvell Berlin4CT STB board This patch adds dts for the Berlin4CT STB reference board which is also based on the Berlin4CT SoC. The Berlin4CT DMP board will be deprecated as time goes. Signed-off-by: Jisheng Zhang Signed-off-by: Sebastian Hesselbarth diff --git a/arch/arm64/boot/dts/marvell/Makefile b/arch/arm64/boot/dts/marvell/Makefile index e2f6afa..348f4db 100644 --- a/arch/arm64/boot/dts/marvell/Makefile +++ b/arch/arm64/boot/dts/marvell/Makefile @@ -1,4 +1,5 @@ dtb-$(CONFIG_ARCH_BERLIN) += berlin4ct-dmp.dtb +dtb-$(CONFIG_ARCH_BERLIN) += berlin4ct-stb.dtb always := $(dtb-y) subdir-y := $(dts-dirs) diff --git a/arch/arm64/boot/dts/marvell/berlin4ct-stb.dts b/arch/arm64/boot/dts/marvell/berlin4ct-stb.dts new file mode 100644 index 0000000..348c37e --- /dev/null +++ b/arch/arm64/boot/dts/marvell/berlin4ct-stb.dts @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2015 Marvell Technology Group Ltd. + * + * Author: Jisheng Zhang + * + * This file is dual-licensed: you can use it either under the terms + * of the GPLv2 or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; + +#include "berlin4ct.dtsi" + +/ { + model = "Marvell BG4CT STB board"; + compatible = "marvell,berlin4ct-stb", "marvell,berlin4ct", "marvell,berlin"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory { + device_type = "memory"; + /* the first 16MB is for firmwares' usage */ + reg = <0 0x01000000 0 0x7f000000>; + }; +}; + +&uart0 { + status = "okay"; +}; -- cgit v0.10.2 From 21e29d9afd1024b63a311172bf57c41223665299 Mon Sep 17 00:00:00 2001 From: Jonathan Liu Date: Mon, 21 Sep 2015 16:13:22 +1000 Subject: ARM: sunxi_defconfig: enable MODULE_UNLOAD Loadable module support is enabled so we should allow unloading modules too. This also allows lsmod to show values other than "-2" in the "Used by" column. Signed-off-by: Jonathan Liu Signed-off-by: Maxime Ripard diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig index f5fa019..3c36e16 100644 --- a/arch/arm/configs/sunxi_defconfig +++ b/arch/arm/configs/sunxi_defconfig @@ -5,6 +5,7 @@ CONFIG_CGROUPS=y CONFIG_BLK_DEV_INITRD=y CONFIG_PERF_EVENTS=y CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y CONFIG_ARCH_SUNXI=y CONFIG_SMP=y CONFIG_NR_CPUS=8 -- cgit v0.10.2 From a83a6a82250fe900be85c8e142f5cb504d9482bd Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Fri, 18 Sep 2015 18:58:21 +0200 Subject: pwm: atmel-hlcdc: Fix module autoload for OF platform driver This platform driver has a OF device ID table but the OF module alias information is not created so module autoloading won't work. This patch adds the missing MODULE_DEVICE_TABLE() for OF to export that information so modules have the correct aliases built-in and autoloading works correctly. A longer explanation by Javier Canillas can be found here: https://lkml.org/lkml/2015/7/30/519 Signed-off-by: Luis de Bethencourt Signed-off-by: Thierry Reding diff --git a/drivers/pwm/pwm-atmel-hlcdc.c b/drivers/pwm/pwm-atmel-hlcdc.c index 5df1db4..be7bb05 100644 --- a/drivers/pwm/pwm-atmel-hlcdc.c +++ b/drivers/pwm/pwm-atmel-hlcdc.c @@ -236,6 +236,7 @@ static const struct of_device_id atmel_hlcdc_dt_ids[] = { }, { /* sentinel */ }, }; +MODULE_DEVICE_TABLE(of, atmel_hlcdc_dt_ids); static int atmel_hlcdc_pwm_probe(struct platform_device *pdev) { -- cgit v0.10.2 From a78695d3ea045cd9977a8397c89171d762708f86 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 18 Sep 2015 15:54:50 +0300 Subject: drm/i915/skl: handle port E in cpt_digital_port_connected SKL port E handling was added in commit 26951caf55d73ceb1967b0bf12f6d0b96853508e Author: Xiong Zhang Date: Mon Aug 17 15:55:50 2015 +0800 drm/i915/skl: enable DDI-E hotplug but the whole function was moved in a another branch in commit b93433ccf64846820b9448f5ff5dd4348b58a8ed Author: Jani Nikula Date: Thu Aug 20 10:47:36 2015 +0300 drm/i915: move ibx_digital_port_connected to intel_dp.c and the addition was lost at some backmerge that I was unable to identify. Put it back in. Tested-by: Tomi Sarvela Reviewed-by: Mika Kuoppala Signed-off-by: Jani Nikula diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index b8c4fc5..9700f77 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4582,6 +4582,9 @@ static bool cpt_digital_port_connected(struct drm_i915_private *dev_priv, case PORT_D: bit = SDE_PORTD_HOTPLUG_CPT; break; + case PORT_E: + bit = SDE_PORTE_HOTPLUG_SPT; + break; default: MISSING_CASE(port->port); return false; -- cgit v0.10.2 From bc81beb80538cb4fc964baf1d7f43a2f9b58def0 Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Fri, 18 Sep 2015 19:28:22 +0800 Subject: ARM: at91/dt: ov2640: add hsync/vsync-active property On at91sam9x5ek/at91sam9m10g45ek/sama5d3xek boards, we use the parallel connection for ov2640. So we must set the hsync/vsync property (1 means active high). Otherwise, the connection would be seen as BT.656 or BT.1120. Signed-off-by: Josh Wu Signed-off-by: Nicolas Ferre diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts index d1ae60a..9d16ef8 100644 --- a/arch/arm/boot/dts/at91sam9m10g45ek.dts +++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts @@ -198,6 +198,8 @@ isi_0: endpoint { remote-endpoint = <&ov2640_0>; bus-width = <8>; + vsync-active = <1>; + hsync-active = <1>; }; }; }; diff --git a/arch/arm/boot/dts/at91sam9x5ek.dtsi b/arch/arm/boot/dts/at91sam9x5ek.dtsi index 36de329..52425a4 100644 --- a/arch/arm/boot/dts/at91sam9x5ek.dtsi +++ b/arch/arm/boot/dts/at91sam9x5ek.dtsi @@ -66,6 +66,8 @@ isi_0: endpoint@0 { remote-endpoint = <&ov2640_0>; bus-width = <8>; + vsync-active = <1>; + hsync-active = <1>; }; }; }; diff --git a/arch/arm/boot/dts/sama5d3xmb.dtsi b/arch/arm/boot/dts/sama5d3xmb.dtsi index 83bee7a..8901042 100644 --- a/arch/arm/boot/dts/sama5d3xmb.dtsi +++ b/arch/arm/boot/dts/sama5d3xmb.dtsi @@ -87,6 +87,8 @@ isi_0: endpoint { remote-endpoint = <&ov2640_0>; bus-width = <8>; + vsync-active = <1>; + hsync-active = <1>; }; }; }; -- cgit v0.10.2 From 6f112a08c1ed717a015dae190e289d53085c1bc4 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 8 Aug 2015 12:11:11 +0200 Subject: ARM: at91: debug: use DEBUG_UART_PHYS Instead of having to add a new configuration option each time support for new SoC is added, use CONFIG_DEBUG_UART_PHYS. For now, CONFIG_DEBUG_UART_VIRT is automatically computed. Signed-off-by: Alexandre Belloni Signed-off-by: Nicolas Ferre diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 0cfd7f9..abf65b6 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -123,29 +123,23 @@ choice 0x80020000 | 0xf0020000 | UART8 0x80024000 | 0xf0024000 | UART9 - config AT91_DEBUG_LL_DBGU0 - bool "Kernel low-level debugging on rm9200, 9260/9g20, 9261/9g10, 9rl, 9x5, 9n12" - select DEBUG_AT91_UART + config DEBUG_AT91_UART + bool "Kernel low-level debugging on Atmel SoCs" depends on ARCH_AT91 - depends on SOC_AT91RM9200 || SOC_AT91SAM9 + help + Say Y here if you want the debug print routines to direct + their output to the serial port on atmel devices. - config AT91_DEBUG_LL_DBGU1 - bool "Kernel low-level debugging on 9263, 9g45 and sama5d3" - select DEBUG_AT91_UART - depends on ARCH_AT91 - depends on SOC_AT91SAM9 || SOC_SAMA5 + SOC DEBUG_UART_PHYS DEBUG_UART_VIRT PORT + rm9200, 9260/9g20, 0xfffff200 0xfefff200 DBGU + 9261/9g10, 9rl + 9263, 9g45, sama5d3 0xffffee00 0xfeffee00 DBGU + sama5d4 0xfc00c000 0xfb00c000 USART3 + sama5d4 0xfc069000 0xfb069000 DBGU + sama5d2 0xf8020000 0xf7020000 UART1 - config AT91_DEBUG_LL_DBGU2 - bool "Kernel low-level debugging on sama5d4" - select DEBUG_AT91_UART - depends on ARCH_AT91 - depends on SOC_SAMA5 - - config AT91_DEBUG_LL_DBGU3 - bool "Kernel low-level debugging on sama5d2" - select DEBUG_AT91_UART - depends on ARCH_AT91 - depends on SOC_SAMA5 + Please adjust DEBUG_UART_PHYS configuration options based on + your needs. config DEBUG_BCM2835 bool "Kernel low-level debugging on BCM2835 PL011 UART" @@ -1249,10 +1243,6 @@ choice endchoice -config DEBUG_AT91_UART - bool - depends on ARCH_AT91 - config DEBUG_EXYNOS_UART bool @@ -1485,7 +1475,8 @@ config DEBUG_UART_PHYS DEBUG_RMOBILE_SCIFA0 || DEBUG_RMOBILE_SCIFA1 || \ DEBUG_RMOBILE_SCIFA4 || DEBUG_S3C24XX_UART || \ DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART || \ - DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0 + DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0 || \ + DEBUG_AT91_UART config DEBUG_UART_VIRT hex "Virtual base address of debug UART" diff --git a/arch/arm/include/debug/at91.S b/arch/arm/include/debug/at91.S index 2556a88..43243be 100644 --- a/arch/arm/include/debug/at91.S +++ b/arch/arm/include/debug/at91.S @@ -9,32 +9,22 @@ * */ -#if defined(CONFIG_AT91_DEBUG_LL_DBGU0) -#define AT91_DBGU 0xfffff200 /* AT91_BASE_DBGU0 */ -#elif defined(CONFIG_AT91_DEBUG_LL_DBGU1) -#define AT91_DBGU 0xffffee00 /* AT91_BASE_DBGU1 */ -#elif defined(CONFIG_AT91_DEBUG_LL_DBGU2) -/* On sama5d4, use USART3 as low level serial console */ -#define AT91_DBGU 0xfc00c000 /* SAMA5D4_BASE_USART3 */ -#else -/* On sama5d2, use UART1 as low level serial console */ -#define AT91_DBGU 0xf8020000 -#endif - #ifdef CONFIG_MMU #define AT91_IO_P2V(x) ((x) - 0x01000000) #else #define AT91_IO_P2V(x) (x) #endif +#define CONFIG_DEBUG_UART_VIRT AT91_IO_P2V(CONFIG_DEBUG_UART_PHYS) + #define AT91_DBGU_SR (0x14) /* Status Register */ #define AT91_DBGU_THR (0x1c) /* Transmitter Holding Register */ #define AT91_DBGU_TXRDY (1 << 1) /* Transmitter Ready */ #define AT91_DBGU_TXEMPTY (1 << 9) /* Transmitter Empty */ .macro addruart, rp, rv, tmp - ldr \rp, =AT91_DBGU @ System peripherals (phys address) - ldr \rv, =AT91_IO_P2V(AT91_DBGU) @ System peripherals (virt address) + ldr \rp, =CONFIG_DEBUG_UART_PHYS @ System peripherals (phys address) + ldr \rv, =CONFIG_DEBUG_UART_VIRT @ System peripherals (virt address) .endm .macro senduart,rd,rx -- cgit v0.10.2 From 7334de0de9869666b664683e18836d1ba9910387 Mon Sep 17 00:00:00 2001 From: Ding Tianhong Date: Sun, 6 Sep 2015 17:34:34 +0800 Subject: arm64: hip05-d02: Document devicetree bindings for Hisilicon Hip05-D02 Board This patch adds documentation for the devicetree bindings used by the DT files of Hisilicon Hip05-D02 development board. Signed-off-by: Ding Tianhong Signed-off-by: Wei Xu diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt index c733e28..3504dca 100644 --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt @@ -20,6 +20,10 @@ HiKey Board Required root node properties: - compatible = "hisilicon,hi6220-hikey", "hisilicon,hi6220"; +HiP05 D02 Board +Required root node properties: + - compatible = "hisilicon,hip05-d02"; + Hisilicon system controller Required properties: -- cgit v0.10.2 From fcab303c015397c307ae4873e02598f89a4a3ef6 Mon Sep 17 00:00:00 2001 From: Ding Tianhong Date: Sun, 6 Sep 2015 17:34:35 +0800 Subject: arm64: dts: add dts files for Hisilicon Hip05-D02 Development Board Add initial dtsi file to support Hisilicon Hip05-D02 Board with support of CPUs in four clusters and each cluster has quard Cortex-A57. Also add dts file to support Hip05-D02 development board. Signed-off-by: Ding Tianhong Signed-off-by: Kefeng Wang Signed-off-by: Wei Xu diff --git a/arch/arm64/boot/dts/hisilicon/Makefile b/arch/arm64/boot/dts/hisilicon/Makefile index fa81a6e..cd158b8 100644 --- a/arch/arm64/boot/dts/hisilicon/Makefile +++ b/arch/arm64/boot/dts/hisilicon/Makefile @@ -1,4 +1,4 @@ -dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb +dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb hip05-d02.dtb always := $(dtb-y) subdir-y := $(dts-dirs) diff --git a/arch/arm64/boot/dts/hisilicon/hip05-d02.dts b/arch/arm64/boot/dts/hisilicon/hip05-d02.dts new file mode 100644 index 0000000..ae34e25 --- /dev/null +++ b/arch/arm64/boot/dts/hisilicon/hip05-d02.dts @@ -0,0 +1,36 @@ +/** + * dts file for Hisilicon D02 Development Board + * + * Copyright (C) 2014,2015 Hisilicon Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * publishhed by the Free Software Foundation. + * + */ + +/dts-v1/; + +#include "hip05.dtsi" + +/ { + model = "Hisilicon Hip05 D02 Development Board"; + compatible = "hisilicon,hip05-d02"; + + memory@00000000 { + device_type = "memory"; + reg = <0x0 0x00000000 0x0 0x80000000>; + }; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&uart0 { + status = "ok"; +}; diff --git a/arch/arm64/boot/dts/hisilicon/hip05.dtsi b/arch/arm64/boot/dts/hisilicon/hip05.dtsi new file mode 100644 index 0000000..4ff16d0 --- /dev/null +++ b/arch/arm64/boot/dts/hisilicon/hip05.dtsi @@ -0,0 +1,271 @@ +/** + * dts file for Hisilicon D02 Development Board + * + * Copyright (C) 2014,2015 Hisilicon Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * publishhed by the Free Software Foundation. + * + */ + +#include + +/ { + compatible = "hisilicon,hip05-d02"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu-map { + cluster0 { + core0 { + cpu = <&cpu0>; + }; + core1 { + cpu = <&cpu1>; + }; + core2 { + cpu = <&cpu2>; + }; + core3 { + cpu = <&cpu3>; + }; + }; + cluster1 { + core0 { + cpu = <&cpu4>; + }; + core1 { + cpu = <&cpu5>; + }; + core2 { + cpu = <&cpu6>; + }; + core3 { + cpu = <&cpu7>; + }; + }; + cluster2 { + core0 { + cpu = <&cpu8>; + }; + core1 { + cpu = <&cpu9>; + }; + core2 { + cpu = <&cpu10>; + }; + core3 { + cpu = <&cpu11>; + }; + }; + cluster3 { + core0 { + cpu = <&cpu12>; + }; + core1 { + cpu = <&cpu13>; + }; + core2 { + cpu = <&cpu14>; + }; + core3 { + cpu = <&cpu15>; + }; + }; + }; + + cpu0: cpu@20000 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x20000>; + enable-method = "psci"; + }; + + cpu1: cpu@20001 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x20001>; + enable-method = "psci"; + }; + + cpu2: cpu@20002 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x20002>; + enable-method = "psci"; + }; + + cpu3: cpu@20003 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x20003>; + enable-method = "psci"; + }; + + cpu4: cpu@20100 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x20100>; + enable-method = "psci"; + }; + + cpu5: cpu@20101 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x20101>; + enable-method = "psci"; + }; + + cpu6: cpu@20102 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x20102>; + enable-method = "psci"; + }; + + cpu7: cpu@20103 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x20103>; + enable-method = "psci"; + }; + + cpu8: cpu@20200 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x20200>; + enable-method = "psci"; + }; + + cpu9: cpu@20201 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x20201>; + enable-method = "psci"; + }; + + cpu10: cpu@20202 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x20202>; + enable-method = "psci"; + }; + + cpu11: cpu@20203 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x20203>; + enable-method = "psci"; + }; + + cpu12: cpu@20300 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x20300>; + enable-method = "psci"; + }; + + cpu13: cpu@20301 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x20301>; + enable-method = "psci"; + }; + + cpu14: cpu@20302 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x20302>; + enable-method = "psci"; + }; + + cpu15: cpu@20303 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x20303>; + enable-method = "psci"; + }; + }; + + gic: interrupt-controller@8d000000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <3>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + interrupt-controller; + #redistributor-regions = <1>; + redistributor-stride = <0x0 0x30000>; + reg = <0x0 0x8d000000 0 0x10000>, /* GICD */ + <0x0 0x8d100000 0 0x300000>, /* GICR */ + <0x0 0xfe000000 0 0x10000>, /* GICC */ + <0x0 0xfe010000 0 0x10000>, /* GICH */ + <0x0 0xfe020000 0 0x10000>; /* GICV */ + interrupts = ; + + its_totems: interrupt-controller@8c000000 { + compatible = "arm,gic-v3-its"; + msi-controller; + reg = <0x0 0x8c000000 0x0 0x40000>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = ; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + refclk200mhz: refclk200mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <200000000>; + }; + + uart0: uart@80300000 { + compatible = "snps,dw-apb-uart"; + reg = <0x0 0x80300000 0x0 0x10000>; + interrupts = ; + clocks = <&refclk200mhz>; + clock-names = "apb_pclk"; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + uart1: uart@80310000 { + compatible = "snps,dw-apb-uart"; + reg = <0x0 0x80310000 0x0 0x10000>; + interrupts = ; + clocks = <&refclk200mhz>; + clock-names = "apb_pclk"; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + }; +}; -- cgit v0.10.2 From 9c811209eb87f26e83f1b1afea186d4797f8b71e Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Mon, 21 Sep 2015 20:56:58 +0530 Subject: dmaengine: xgene-dma: use dma_pool_zalloc We should use shiny new dma_pool_zalloc instead of dma_pool_alloc/memset Reported-by: Julia Lawall Reported-by: kbuild test robot Signed-off-by: Vinod Koul diff --git a/drivers/dma/xgene-dma.c b/drivers/dma/xgene-dma.c index b23e8d5..dc84ed1 100644 --- a/drivers/dma/xgene-dma.c +++ b/drivers/dma/xgene-dma.c @@ -556,14 +556,12 @@ static struct xgene_dma_desc_sw *xgene_dma_alloc_descriptor( struct xgene_dma_desc_sw *desc; dma_addr_t phys; - desc = dma_pool_alloc(chan->desc_pool, GFP_NOWAIT, &phys); + desc = dma_pool_zalloc(chan->desc_pool, GFP_NOWAIT, &phys); if (!desc) { chan_err(chan, "Failed to allocate LDs\n"); return NULL; } - memset(desc, 0, sizeof(*desc)); - INIT_LIST_HEAD(&desc->tx_list); desc->tx.phys = phys; desc->tx.tx_submit = xgene_dma_tx_submit; -- cgit v0.10.2 From ad4a7b5065c1b4f5176e7d031c3cc2b36f776884 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 26 Aug 2015 13:17:24 -0700 Subject: dmaengine: ioatdma: adding shutdown support The ioatdma needs to be queisced and block all additional op submission during reboots. When NET_DMA was used, this caused issue as ops were still being sent to ioatdma during reboots even though PCI BME has been turned off. Even though NET_DMA has been deprecated, we need to prevent similar situations. The shutdown handler should address that. Signed-off-by: Dave Jiang Signed-off-by: Vinod Koul diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c index f66b7e6..1d5df2e 100644 --- a/drivers/dma/ioat/dma.c +++ b/drivers/dma/ioat/dma.c @@ -197,7 +197,8 @@ static void __ioat_start_null_desc(struct ioatdma_chan *ioat_chan) void ioat_start_null_desc(struct ioatdma_chan *ioat_chan) { spin_lock_bh(&ioat_chan->prep_lock); - __ioat_start_null_desc(ioat_chan); + if (!test_bit(IOAT_CHAN_DOWN, &ioat_chan->state)) + __ioat_start_null_desc(ioat_chan); spin_unlock_bh(&ioat_chan->prep_lock); } diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h index 1bc08498..8f4e607 100644 --- a/drivers/dma/ioat/dma.h +++ b/drivers/dma/ioat/dma.h @@ -82,8 +82,9 @@ struct ioatdma_device { struct dma_pool *sed_hw_pool[MAX_SED_POOLS]; struct dma_device dma_dev; u8 version; - struct msix_entry msix_entries[4]; - struct ioatdma_chan *idx[4]; +#define IOAT_MAX_CHANS 4 + struct msix_entry msix_entries[IOAT_MAX_CHANS]; + struct ioatdma_chan *idx[IOAT_MAX_CHANS]; struct dca_provider *dca; enum ioat_irq_mode irq_mode; u32 cap; @@ -95,6 +96,7 @@ struct ioatdma_chan { dma_addr_t last_completion; spinlock_t cleanup_lock; unsigned long state; + #define IOAT_CHAN_DOWN 0 #define IOAT_COMPLETION_ACK 1 #define IOAT_RESET_PENDING 2 #define IOAT_KOBJ_INIT_FAIL 3 diff --git a/drivers/dma/ioat/init.c b/drivers/dma/ioat/init.c index 1c3c9b0..793c5dd 100644 --- a/drivers/dma/ioat/init.c +++ b/drivers/dma/ioat/init.c @@ -1186,6 +1186,31 @@ static int ioat3_dma_probe(struct ioatdma_device *ioat_dma, int dca) return 0; } +static void ioat_shutdown(struct pci_dev *pdev) +{ + struct ioatdma_device *ioat_dma = pci_get_drvdata(pdev); + struct ioatdma_chan *ioat_chan; + int i; + + if (!ioat_dma) + return; + + for (i = 0; i < IOAT_MAX_CHANS; i++) { + ioat_chan = ioat_dma->idx[i]; + if (!ioat_chan) + continue; + + spin_lock_bh(&ioat_chan->prep_lock); + set_bit(IOAT_CHAN_DOWN, &ioat_chan->state); + del_timer_sync(&ioat_chan->timer); + spin_unlock_bh(&ioat_chan->prep_lock); + /* this should quiesce then reset */ + ioat_reset_hw(ioat_chan); + } + + ioat_disable_interrupts(ioat_dma); +} + #define DRV_NAME "ioatdma" static struct pci_driver ioat_pci_driver = { @@ -1193,6 +1218,7 @@ static struct pci_driver ioat_pci_driver = { .id_table = ioat_pci_tbl, .probe = ioat_pci_probe, .remove = ioat_remove, + .shutdown = ioat_shutdown, }; static struct ioatdma_device * diff --git a/drivers/dma/ioat/prep.c b/drivers/dma/ioat/prep.c index ad4fb41..6bb4a13 100644 --- a/drivers/dma/ioat/prep.c +++ b/drivers/dma/ioat/prep.c @@ -121,6 +121,9 @@ ioat_dma_prep_memcpy_lock(struct dma_chan *c, dma_addr_t dma_dest, size_t total_len = len; int num_descs, idx, i; + if (test_bit(IOAT_CHAN_DOWN, &ioat_chan->state)) + return NULL; + num_descs = ioat_xferlen_to_descs(ioat_chan, len); if (likely(num_descs) && ioat_check_space_lock(ioat_chan, num_descs) == 0) @@ -254,6 +257,11 @@ struct dma_async_tx_descriptor * ioat_prep_xor(struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src, unsigned int src_cnt, size_t len, unsigned long flags) { + struct ioatdma_chan *ioat_chan = to_ioat_chan(chan); + + if (test_bit(IOAT_CHAN_DOWN, &ioat_chan->state)) + return NULL; + return __ioat_prep_xor_lock(chan, NULL, dest, src, src_cnt, len, flags); } @@ -262,6 +270,11 @@ ioat_prep_xor_val(struct dma_chan *chan, dma_addr_t *src, unsigned int src_cnt, size_t len, enum sum_check_flags *result, unsigned long flags) { + struct ioatdma_chan *ioat_chan = to_ioat_chan(chan); + + if (test_bit(IOAT_CHAN_DOWN, &ioat_chan->state)) + return NULL; + /* the cleanup routine only sets bits on validate failure, it * does not clear bits on validate success... so clear it here */ @@ -574,6 +587,11 @@ ioat_prep_pq(struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src, unsigned int src_cnt, const unsigned char *scf, size_t len, unsigned long flags) { + struct ioatdma_chan *ioat_chan = to_ioat_chan(chan); + + if (test_bit(IOAT_CHAN_DOWN, &ioat_chan->state)) + return NULL; + /* specify valid address for disabled result */ if (flags & DMA_PREP_PQ_DISABLE_P) dst[0] = dst[1]; @@ -614,6 +632,11 @@ ioat_prep_pq_val(struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src, unsigned int src_cnt, const unsigned char *scf, size_t len, enum sum_check_flags *pqres, unsigned long flags) { + struct ioatdma_chan *ioat_chan = to_ioat_chan(chan); + + if (test_bit(IOAT_CHAN_DOWN, &ioat_chan->state)) + return NULL; + /* specify valid address for disabled result */ if (flags & DMA_PREP_PQ_DISABLE_P) pq[0] = pq[1]; @@ -638,6 +661,10 @@ ioat_prep_pqxor(struct dma_chan *chan, dma_addr_t dst, dma_addr_t *src, { unsigned char scf[MAX_SCF]; dma_addr_t pq[2]; + struct ioatdma_chan *ioat_chan = to_ioat_chan(chan); + + if (test_bit(IOAT_CHAN_DOWN, &ioat_chan->state)) + return NULL; if (src_cnt > MAX_SCF) return NULL; @@ -661,6 +688,10 @@ ioat_prep_pqxor_val(struct dma_chan *chan, dma_addr_t *src, { unsigned char scf[MAX_SCF]; dma_addr_t pq[2]; + struct ioatdma_chan *ioat_chan = to_ioat_chan(chan); + + if (test_bit(IOAT_CHAN_DOWN, &ioat_chan->state)) + return NULL; if (src_cnt > MAX_SCF) return NULL; @@ -689,6 +720,9 @@ ioat_prep_interrupt_lock(struct dma_chan *c, unsigned long flags) struct ioat_ring_ent *desc; struct ioat_dma_descriptor *hw; + if (test_bit(IOAT_CHAN_DOWN, &ioat_chan->state)) + return NULL; + if (ioat_check_space_lock(ioat_chan, 1) == 0) desc = ioat_get_ring_ent(ioat_chan, ioat_chan->head); else -- cgit v0.10.2 From 4222a9074339fccc59526cbf30d8d2ec41468574 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 26 Aug 2015 13:17:30 -0700 Subject: dmaengine: ioatdma: add PCIe AER handlers Adding AER handlers in order to handle any PCIe errors. Signed-off-by: Dave Jiang Signed-off-by: Vinod Koul diff --git a/drivers/dma/ioat/init.c b/drivers/dma/ioat/init.c index 793c5dd..4ef0c5e 100644 --- a/drivers/dma/ioat/init.c +++ b/drivers/dma/ioat/init.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "dma.h" #include "registers.h" #include "hw.h" @@ -1211,14 +1212,91 @@ static void ioat_shutdown(struct pci_dev *pdev) ioat_disable_interrupts(ioat_dma); } +void ioat_resume(struct ioatdma_device *ioat_dma) +{ + struct ioatdma_chan *ioat_chan; + u32 chanerr; + int i; + + for (i = 0; i < IOAT_MAX_CHANS; i++) { + ioat_chan = ioat_dma->idx[i]; + if (!ioat_chan) + continue; + + spin_lock_bh(&ioat_chan->prep_lock); + clear_bit(IOAT_CHAN_DOWN, &ioat_chan->state); + spin_unlock_bh(&ioat_chan->prep_lock); + + chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET); + writel(chanerr, ioat_chan->reg_base + IOAT_CHANERR_OFFSET); + + /* no need to reset as shutdown already did that */ + } +} + #define DRV_NAME "ioatdma" +static pci_ers_result_t ioat_pcie_error_detected(struct pci_dev *pdev, + enum pci_channel_state error) +{ + dev_dbg(&pdev->dev, "%s: PCIe AER error %d\n", DRV_NAME, error); + + /* quiesce and block I/O */ + ioat_shutdown(pdev); + + return PCI_ERS_RESULT_NEED_RESET; +} + +static pci_ers_result_t ioat_pcie_error_slot_reset(struct pci_dev *pdev) +{ + pci_ers_result_t result = PCI_ERS_RESULT_RECOVERED; + int err; + + dev_dbg(&pdev->dev, "%s post reset handling\n", DRV_NAME); + + if (pci_enable_device_mem(pdev) < 0) { + dev_err(&pdev->dev, + "Failed to enable PCIe device after reset.\n"); + result = PCI_ERS_RESULT_DISCONNECT; + } else { + pci_set_master(pdev); + pci_restore_state(pdev); + pci_save_state(pdev); + pci_wake_from_d3(pdev, false); + } + + err = pci_cleanup_aer_uncorrect_error_status(pdev); + if (err) { + dev_err(&pdev->dev, + "AER uncorrect error status clear failed: %#x\n", err); + } + + return result; +} + +static void ioat_pcie_error_resume(struct pci_dev *pdev) +{ + struct ioatdma_device *ioat_dma = pci_get_drvdata(pdev); + + dev_dbg(&pdev->dev, "%s: AER handling resuming\n", DRV_NAME); + + /* initialize and bring everything back */ + ioat_resume(ioat_dma); +} + +static const struct pci_error_handlers ioat_err_handler = { + .error_detected = ioat_pcie_error_detected, + .slot_reset = ioat_pcie_error_slot_reset, + .resume = ioat_pcie_error_resume, +}; + static struct pci_driver ioat_pci_driver = { .name = DRV_NAME, .id_table = ioat_pci_tbl, .probe = ioat_pci_probe, .remove = ioat_remove, .shutdown = ioat_shutdown, + .err_handler = &ioat_err_handler, }; static struct ioatdma_device * @@ -1271,13 +1349,17 @@ static int ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_drvdata(pdev, device); device->version = readb(device->reg_base + IOAT_VER_OFFSET); - if (device->version >= IOAT_VER_3_0) + if (device->version >= IOAT_VER_3_0) { err = ioat3_dma_probe(device, ioat_dca_enabled); - else + + if (device->version >= IOAT_VER_3_3) + pci_enable_pcie_error_reporting(pdev); + } else return -ENODEV; if (err) { dev_err(dev, "Intel(R) I/OAT DMA Engine init failed\n"); + pci_disable_pcie_error_reporting(pdev); return -ENODEV; } @@ -1297,6 +1379,8 @@ static void ioat_remove(struct pci_dev *pdev) free_dca_provider(device->dca); device->dca = NULL; } + + pci_disable_pcie_error_reporting(pdev); ioat_dma_remove(device); } -- cgit v0.10.2 From 240eb916076c8deb206c7e66d1ee9eb37d6a499a Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 13 Sep 2015 14:15:19 +0200 Subject: dmaengine: drop null test before destroy functions Remove unneeded NULL test. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ expression x; @@ -if (x != NULL) \(kmem_cache_destroy\|mempool_destroy\|dma_pool_destroy\)(x); // Signed-off-by: Julia Lawall Signed-off-by: Vinod Koul diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 3ff284c..45df9a4 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -1066,11 +1066,9 @@ static void dmaengine_destroy_unmap_pool(void) for (i = 0; i < ARRAY_SIZE(unmap_pool); i++) { struct dmaengine_unmap_pool *p = &unmap_pool[i]; - if (p->pool) - mempool_destroy(p->pool); + mempool_destroy(p->pool); p->pool = NULL; - if (p->cache) - kmem_cache_destroy(p->cache); + kmem_cache_destroy(p->cache); p->cache = NULL; } } -- cgit v0.10.2 From 6c8c58b38f17e92691dd648c0e3b66f1a6942433 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 19 Sep 2015 13:25:54 +0200 Subject: ARM: BCM5301X: Netgear R6250 add USB GPIO Add GPIO number which is needed to activate the USB power supply. Signed-off-by: Hauke Mehrtens Signed-off-by: Florian Fainelli diff --git a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts index 64b8d10..ca92bba 100644 --- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts +++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts @@ -24,6 +24,17 @@ reg = <0x00000000 0x08000000>; }; + axi@18000000 { + usb3@23000 { + reg = <0x00023000 0x1000>; + + #address-cells = <1>; + #size-cells = <1>; + + vcc-gpio = <&chipcommon 0 GPIO_ACTIVE_HIGH>; + }; + }; + leds { compatible = "gpio-leds"; -- cgit v0.10.2 From 23998645f6e73f7038347255228ae1c60f1598da Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Thu, 17 Sep 2015 12:15:02 +0200 Subject: ARM: berlin: dts: add the cpufreq-dt bindings on the BG2Q The BG2Q uses cpugreq-dt. Add the corresponding bindings. The operating points can be updated by the bootloader. Signed-off-by: Antoine Tenart Signed-off-by: Sebastian Hesselbarth diff --git a/arch/arm/boot/dts/berlin2q.dtsi b/arch/arm/boot/dts/berlin2q.dtsi index 380fa18..32b871e 100644 --- a/arch/arm/boot/dts/berlin2q.dtsi +++ b/arch/arm/boot/dts/berlin2q.dtsi @@ -58,6 +58,17 @@ device_type = "cpu"; next-level-cache = <&l2>; reg = <0>; + + clocks = <&chip_clk CLKID_CPU>; + clock-latency = <100000>; + /* Can be modified by the bootloader */ + operating-points = < + /* kHz uV */ + 1200000 1200000 + 1000000 1200000 + 800000 1200000 + 600000 1200000 + >; }; cpu@1 { -- cgit v0.10.2 From 2e1782add72fbbb7309b2c120ce20a543a23f5b3 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Thu, 17 Sep 2015 12:15:03 +0200 Subject: ARM: berlin: dts: add the cpufreq-dt bindings on the BG2 The BG2 uses cpugreq-dt. Add the corresponding bindings. Signed-off-by: Antoine Tenart Signed-off-by: Sebastian Hesselbarth diff --git a/arch/arm/boot/dts/berlin2.dtsi b/arch/arm/boot/dts/berlin2.dtsi index 40cf262..11e446e 100644 --- a/arch/arm/boot/dts/berlin2.dtsi +++ b/arch/arm/boot/dts/berlin2.dtsi @@ -63,6 +63,16 @@ device_type = "cpu"; next-level-cache = <&l2>; reg = <0>; + + clocks = <&chip_clk CLKID_CPU>; + clock-latency = <100000>; + operating-points = < + /* kHz uV */ + 1200000 1200000 + 1000000 1200000 + 800000 1200000 + 600000 1200000 + >; }; cpu@1 { -- cgit v0.10.2 From 1e5c50572d9e587c88d6e976e582a9b3377f9153 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Thu, 17 Sep 2015 12:15:04 +0200 Subject: ARM: berlin: dts: add the cpufreq-dt bindings on the BG2CD The BG2CD uses cpugreq-dt. Add the corresponding bindings. Signed-off-by: Antoine Tenart Signed-off-by: Sebastian Hesselbarth diff --git a/arch/arm/boot/dts/berlin2cd.dtsi b/arch/arm/boot/dts/berlin2cd.dtsi index 6246aec..75b1421 100644 --- a/arch/arm/boot/dts/berlin2cd.dtsi +++ b/arch/arm/boot/dts/berlin2cd.dtsi @@ -61,6 +61,14 @@ device_type = "cpu"; next-level-cache = <&l2>; reg = <0>; + + clocks = <&chip_clk CLKID_CPU>; + clock-latency = <100000>; + operating-points = < + /* kHz uV */ + 800000 1200000 + 600000 1200000 + >; }; }; -- cgit v0.10.2 From e1a3e724a25761a2b2e9e0e059e33afac6409a76 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Thu, 17 Sep 2015 12:15:05 +0200 Subject: ARM: berlin: register cpufreq-dt The Berlin SoCs use cpufreq-dt for cpufreq. Register a platform device. Signed-off-by: Antoine Tenart Signed-off-by: Sebastian Hesselbarth diff --git a/arch/arm/mach-berlin/berlin.c b/arch/arm/mach-berlin/berlin.c index ac181c6..25d7387 100644 --- a/arch/arm/mach-berlin/berlin.c +++ b/arch/arm/mach-berlin/berlin.c @@ -18,6 +18,11 @@ #include #include +static void __init berlin_init_late(void) +{ + platform_device_register_simple("cpufreq-dt", -1, NULL, 0); +} + static const char * const berlin_dt_compat[] = { "marvell,berlin", NULL, @@ -25,6 +30,7 @@ static const char * const berlin_dt_compat[] = { DT_MACHINE_START(BERLIN_DT, "Marvell Berlin") .dt_compat = berlin_dt_compat, + .init_late = berlin_init_late, /* * with DT probing for L2CCs, berlin_init_machine can be removed. * Note: 88DE3005 (Armada 1500-mini) uses pl310 l2cc -- cgit v0.10.2 From a645654b817feba05e5156345325d19fc85ebc9f Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Sun, 23 Aug 2015 15:18:55 +0200 Subject: vga_switcheroo: Document _ALL_ the things! This adds an "Overview" DOC section plus two DOC sections for the modes of use ("Manual switching and manual power control" and "Driver power control"). Also included is kernel-doc for all public functions, structs and enums. Signed-off-by: Lukas Wunner Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index 2106066..b19a72f 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -1,20 +1,31 @@ /* + * vga_switcheroo.c - Support for laptop with dual GPU using one set of outputs + * * Copyright (c) 2010 Red Hat Inc. * Author : Dave Airlie * + * Copyright (c) 2015 Lukas Wunner * - * Licensed under GPLv2 + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: * - * vga_switcheroo.c - Support for laptop with dual GPU using one set of outputs + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. * - * Switcher interface - methods require for ATPX and DCM - * - switchto - this throws the output MUX switch - * - discrete_set_power - sets the power state for the discrete card + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS + * IN THE SOFTWARE. * - * GPU driver interface - * - set_gpu_state - this should do the equiv of s/r for the card - * - this should *not* set the discrete power state - * - switch_check - check if the device is in a position to switch now */ #define pr_fmt(fmt) "vga_switcheroo: " fmt @@ -33,6 +44,61 @@ #include +/** + * DOC: Overview + * + * vga_switcheroo is the Linux subsystem for laptop hybrid graphics. + * These come in two flavors: + * + * * muxed: Dual GPUs with a multiplexer chip to switch outputs between GPUs. + * * muxless: Dual GPUs but only one of them is connected to outputs. + * The other one is merely used to offload rendering, its results + * are copied over PCIe into the framebuffer. On Linux this is + * supported with DRI PRIME. + * + * Hybrid graphics started to appear in the late Naughties and were initially + * all muxed. Newer laptops moved to a muxless architecture for cost reasons. + * A notable exception is the MacBook Pro which continues to use a mux. + * Muxes come with varying capabilities: Some switch only the panel, others + * can also switch external displays. Some switch all display pins at once + * while others can switch just the DDC lines. (To allow EDID probing + * for the inactive GPU.) Also, muxes are often used to cut power to the + * discrete GPU while it is not used. + * + * DRM drivers register GPUs with vga_switcheroo, these are heretoforth called + * clients. The mux is called the handler. Muxless machines also register a + * handler to control the power state of the discrete GPU, its ->switchto + * callback is a no-op for obvious reasons. The discrete GPU is often equipped + * with an HDA controller for the HDMI/DP audio signal, this will also + * register as a client so that vga_switcheroo can take care of the correct + * suspend/resume order when changing the discrete GPU's power state. In total + * there can thus be up to three clients: Two vga clients (GPUs) and one audio + * client (on the discrete GPU). The code is mostly prepared to support + * machines with more than two GPUs should they become available. + * The GPU to which the outputs are currently switched is called the + * active client in vga_switcheroo parlance. The GPU not in use is the + * inactive client. + */ + +/** + * struct vga_switcheroo_client - registered client + * @pdev: client pci device + * @fb_info: framebuffer to which console is remapped on switching + * @pwr_state: current power state + * @ops: client callbacks + * @id: client identifier, see enum vga_switcheroo_client_id. + * Determining the id requires the handler, so GPUs are initially + * assigned -1 and later given their true id in vga_switcheroo_enable() + * @active: whether the outputs are currently switched to this client + * @driver_power_control: whether power state is controlled by the driver's + * runtime pm. If true, writing ON and OFF to the vga_switcheroo debugfs + * interface is a no-op so as not to interfere with runtime pm + * @list: client list + * + * Registered client. A client can be either a GPU or an audio device on a GPU. + * For audio clients, the @fb_info, @active and @driver_power_control members + * are bogus. + */ struct vga_switcheroo_client { struct pci_dev *pdev; struct fb_info *fb_info; @@ -44,10 +110,28 @@ struct vga_switcheroo_client { struct list_head list; }; +/* + * protects access to struct vgasr_priv + */ static DEFINE_MUTEX(vgasr_mutex); +/** + * struct vgasr_priv - vga_switcheroo private data + * @active: whether vga_switcheroo is enabled. + * Prerequisite is the registration of two GPUs and a handler + * @delayed_switch_active: whether a delayed switch is pending + * @delayed_client_id: client to which a delayed switch is pending + * @debugfs_root: directory for vga_switcheroo debugfs interface + * @switch_file: file for vga_switcheroo debugfs interface + * @registered_clients: number of registered GPUs + * (counting only vga clients, not audio clients) + * @clients: list of registered clients + * @handler: registered handler + * + * vga_switcheroo private data. Currently only one vga_switcheroo instance + * per system is supported. + */ struct vgasr_priv { - bool active; bool delayed_switch_active; enum vga_switcheroo_client_id delayed_client_id; @@ -103,6 +187,15 @@ static void vga_switcheroo_enable(void) vgasr_priv.active = true; } +/** + * vga_switcheroo_register_handler() - register handler + * @handler: handler callbacks + * + * Register handler. Enable vga_switcheroo if two vga clients have already + * registered. + * + * Return: 0 on success, -EINVAL if a handler was already registered. + */ int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) { mutex_lock(&vgasr_mutex); @@ -121,6 +214,11 @@ int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) } EXPORT_SYMBOL(vga_switcheroo_register_handler); +/** + * vga_switcheroo_unregister_handler() - unregister handler + * + * Unregister handler. Disable vga_switcheroo. + */ void vga_switcheroo_unregister_handler(void) { mutex_lock(&vgasr_mutex); @@ -164,6 +262,19 @@ static int register_client(struct pci_dev *pdev, return 0; } +/** + * vga_switcheroo_register_client - register vga client + * @pdev: client pci device + * @ops: client callbacks + * @driver_power_control: whether power state is controlled by the driver's + * runtime pm + * + * Register vga client (GPU). Enable vga_switcheroo if another GPU and a + * handler have already registered. The power state of the client is assumed + * to be ON. + * + * Return: 0 on success, -ENOMEM on memory allocation error. + */ int vga_switcheroo_register_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, bool driver_power_control) @@ -174,6 +285,18 @@ int vga_switcheroo_register_client(struct pci_dev *pdev, } EXPORT_SYMBOL(vga_switcheroo_register_client); +/** + * vga_switcheroo_register_audio_client - register audio client + * @pdev: client pci device + * @ops: client callbacks + * @id: client identifier, see enum vga_switcheroo_client_id + * @active: whether the audio device is fully initialized + * + * Register audio client (audio device on a GPU). The power state of the + * client is assumed to be ON. + * + * Return: 0 on success, -ENOMEM on memory allocation error. + */ int vga_switcheroo_register_audio_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, int id, bool active) @@ -215,6 +338,15 @@ find_active_client(struct list_head *head) return NULL; } +/** + * vga_switcheroo_get_client_state() - obtain power state of a given client + * @pdev: client pci device + * + * Obtain power state of a given client as seen from vga_switcheroo. + * The function is only called from hda_intel.c. + * + * Return: Power state. + */ int vga_switcheroo_get_client_state(struct pci_dev *pdev) { struct vga_switcheroo_client *client; @@ -228,6 +360,12 @@ int vga_switcheroo_get_client_state(struct pci_dev *pdev) } EXPORT_SYMBOL(vga_switcheroo_get_client_state); +/** + * vga_switcheroo_unregister_client() - unregister client + * @pdev: client pci device + * + * Unregister client. Disable vga_switcheroo if this is a vga client (GPU). + */ void vga_switcheroo_unregister_client(struct pci_dev *pdev) { struct vga_switcheroo_client *client; @@ -249,6 +387,14 @@ void vga_switcheroo_unregister_client(struct pci_dev *pdev) } EXPORT_SYMBOL(vga_switcheroo_unregister_client); +/** + * vga_switcheroo_client_fb_set() - set framebuffer of a given client + * @pdev: client pci device + * @info: framebuffer + * + * Set framebuffer of a given client. The console will be remapped to this + * on switching. + */ void vga_switcheroo_client_fb_set(struct pci_dev *pdev, struct fb_info *info) { @@ -262,6 +408,42 @@ void vga_switcheroo_client_fb_set(struct pci_dev *pdev, } EXPORT_SYMBOL(vga_switcheroo_client_fb_set); +/** + * DOC: Manual switching and manual power control + * + * In this mode of use, the file /sys/kernel/debug/vgaswitcheroo/switch + * can be read to retrieve the current vga_switcheroo state and commands + * can be written to it to change the state. The file appears as soon as + * two GPU drivers and one handler have registered with vga_switcheroo. + * The following commands are understood: + * + * * OFF: Power off the device not in use. + * * ON: Power on the device not in use. + * * IGD: Switch to the integrated graphics device. + * Power on the integrated GPU if necessary, power off the discrete GPU. + * Prerequisite is that no user space processes (e.g. Xorg, alsactl) + * have opened device files of the GPUs or the audio client. If the + * switch fails, the user may invoke lsof(8) or fuser(1) on /dev/dri/ + * and /dev/snd/controlC1 to identify processes blocking the switch. + * * DIS: Switch to the discrete graphics device. + * * DIGD: Delayed switch to the integrated graphics device. + * This will perform the switch once the last user space process has + * closed the device files of the GPUs and the audio client. + * * DDIS: Delayed switch to the discrete graphics device. + * * MIGD: Mux-only switch to the integrated graphics device. + * Does not remap console or change the power state of either gpu. + * If the integrated GPU is currently off, the screen will turn black. + * If it is on, the screen will show whatever happens to be in VRAM. + * Either way, the user has to blindly enter the command to switch back. + * * MDIS: Mux-only switch to the discrete graphics device. + * + * For GPUs whose power state is controlled by the driver's runtime pm, + * the ON and OFF commands are a no-op (see next section). + * + * For muxless machines, the IGD/DIS, DIGD/DDIS and MIGD/MDIS commands + * should not be used. + */ + static int vga_switcheroo_show(struct seq_file *m, void *v) { struct vga_switcheroo_client *client; @@ -559,6 +741,16 @@ fail: return -1; } +/** + * vga_switcheroo_process_delayed_switch() - helper for delayed switching + * + * Process a delayed switch if one is pending. DRM drivers should call this + * from their ->lastclose callback. + * + * Return: 0 on success. -EINVAL if no delayed switch is pending, if the client + * has unregistered in the meantime or if there are other clients blocking the + * switch. If the actual switch fails, an error is reported and 0 is returned. + */ int vga_switcheroo_process_delayed_switch(void) { struct vga_switcheroo_client *client; @@ -589,6 +781,39 @@ err: } EXPORT_SYMBOL(vga_switcheroo_process_delayed_switch); +/** + * DOC: Driver power control + * + * In this mode of use, the discrete GPU automatically powers up and down at + * the discretion of the driver's runtime pm. On muxed machines, the user may + * still influence the muxer state by way of the debugfs interface, however + * the ON and OFF commands become a no-op for the discrete GPU. + * + * This mode is the default on Nvidia HybridPower/Optimus and ATI PowerXpress. + * Specifying nouveau.runpm=0, radeon.runpm=0 or amdgpu.runpm=0 on the kernel + * command line disables it. + * + * When the driver decides to power up or down, it notifies vga_switcheroo + * thereof so that it can (a) power the audio device on the GPU up or down, + * and (b) update its internal power state representation for the device. + * This is achieved by vga_switcheroo_set_dynamic_switch(). + * + * After the GPU has been suspended, the handler needs to be called to cut + * power to the GPU. Likewise it needs to reinstate power before the GPU + * can resume. This is achieved by vga_switcheroo_init_domain_pm_ops(), + * which augments the GPU's suspend/resume functions by the requisite + * calls to the handler. + * + * When the audio device resumes, the GPU needs to be woken. This is achieved + * by vga_switcheroo_init_domain_pm_optimus_hdmi_audio(), which augments the + * audio device's resume function. + * + * On muxed machines, if the mux is initially switched to the discrete GPU, + * the user ends up with a black screen when the GPU powers down after boot. + * As a workaround, the mux is forced to the integrated GPU on runtime suspend, + * cf. https://bugs.freedesktop.org/show_bug.cgi?id=75917 + */ + static void vga_switcheroo_power_switch(struct pci_dev *pdev, enum vga_switcheroo_state state) { @@ -607,8 +832,17 @@ static void vga_switcheroo_power_switch(struct pci_dev *pdev, vgasr_priv.handler->power_state(client->id, state); } -/* force a PCI device to a certain state - mainly to turn off audio clients */ - +/** + * vga_switcheroo_set_dynamic_switch() - helper for driver power control + * @pdev: client pci device + * @dynamic: new power state + * + * Helper for GPUs whose power state is controlled by the driver's runtime pm. + * When the driver decides to power up or down, it notifies vga_switcheroo + * thereof using this helper so that it can (a) power the audio device on + * the GPU up or down, and (b) update its internal power state representation + * for the device. + */ void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev, enum vga_switcheroo_state dynamic) { @@ -654,8 +888,18 @@ static int vga_switcheroo_runtime_resume(struct device *dev) return 0; } -/* this version is for the case where the power switch is separate - to the device being powered down. */ +/** + * vga_switcheroo_init_domain_pm_ops() - helper for driver power control + * @dev: vga client device + * @domain: power domain + * + * Helper for GPUs whose power state is controlled by the driver's runtime pm. + * After the GPU has been suspended, the handler needs to be called to cut + * power to the GPU. Likewise it needs to reinstate power before the GPU + * can resume. To this end, this helper augments the suspend/resume functions + * by the requisite calls to the handler. It needs only be called on platforms + * where the power switch is separate to the device being powered down. + */ int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain *domain) { @@ -709,6 +953,19 @@ static int vga_switcheroo_runtime_resume_hdmi_audio(struct device *dev) return ret; } +/** + * vga_switcheroo_init_domain_pm_optimus_hdmi_audio() - helper for driver + * power control + * @dev: audio client device + * @domain: power domain + * + * Helper for GPUs whose power state is controlled by the driver's runtime pm. + * When the audio device resumes, the GPU needs to be woken. This helper + * augments the audio device's resume function to do that. + * + * Return: 0 on success, -EINVAL if no power management operations are + * defined for this device. + */ int vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev, struct dev_pm_domain *domain) diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h index b483abd..fe90bfc 100644 --- a/include/linux/vga_switcheroo.h +++ b/include/linux/vga_switcheroo.h @@ -1,10 +1,31 @@ /* + * vga_switcheroo.h - Support for laptop with dual GPU using one set of outputs + * * Copyright (c) 2010 Red Hat Inc. * Author : Dave Airlie * - * Licensed under GPLv2 + * Copyright (c) 2015 Lukas Wunner + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS + * IN THE SOFTWARE. * - * vga_switcheroo.h - Support for laptop with dual GPU using one set of outputs */ #ifndef _LINUX_VGA_SWITCHEROO_H_ @@ -14,6 +35,20 @@ struct pci_dev; +/** + * enum vga_switcheroo_state - client power state + * @VGA_SWITCHEROO_OFF: off + * @VGA_SWITCHEROO_ON: on + * @VGA_SWITCHEROO_INIT: client has registered with vga_switcheroo but + * vga_switcheroo is not enabled, i.e. no second client or no handler + * has registered. Only used in vga_switcheroo_get_client_state() which + * in turn is only called from hda_intel.c + * @VGA_SWITCHEROO_NOT_FOUND: client has not registered with vga_switcheroo. + * Only used in vga_switcheroo_get_client_state() which in turn is only + * called from hda_intel.c + * + * Client power state. + */ enum vga_switcheroo_state { VGA_SWITCHEROO_OFF, VGA_SWITCHEROO_ON, @@ -22,20 +57,64 @@ enum vga_switcheroo_state { VGA_SWITCHEROO_NOT_FOUND, }; +/** + * enum vga_switcheroo_client_id - client identifier + * @VGA_SWITCHEROO_IGD: integrated graphics device + * @VGA_SWITCHEROO_DIS: discrete graphics device + * @VGA_SWITCHEROO_MAX_CLIENTS: currently no more than two GPUs are supported + * + * Client identifier. Audio clients use the same identifier & 0x100. + */ enum vga_switcheroo_client_id { VGA_SWITCHEROO_IGD, VGA_SWITCHEROO_DIS, VGA_SWITCHEROO_MAX_CLIENTS, }; +/** + * struct vga_switcheroo_handler - handler callbacks + * @init: initialize handler. + * Optional. This gets called when vga_switcheroo is enabled, i.e. when + * two vga clients have registered. It allows the handler to perform + * some delayed initialization that depends on the existence of the + * vga clients. Currently only the radeon and amdgpu drivers use this. + * The return value is ignored + * @switchto: switch outputs to given client. + * Mandatory. For muxless machines this should be a no-op. Returning 0 + * denotes success, anything else failure (in which case the switch is + * aborted) + * @power_state: cut or reinstate power of given client. + * Optional. The return value is ignored + * @get_client_id: determine if given pci device is integrated or discrete GPU. + * Mandatory + * + * Handler callbacks. The multiplexer itself. The @switchto and @get_client_id + * methods are mandatory, all others may be set to NULL. + */ struct vga_switcheroo_handler { + int (*init)(void); int (*switchto)(enum vga_switcheroo_client_id id); int (*power_state)(enum vga_switcheroo_client_id id, enum vga_switcheroo_state state); - int (*init)(void); int (*get_client_id)(struct pci_dev *pdev); }; +/** + * struct vga_switcheroo_client_ops - client callbacks + * @set_gpu_state: do the equivalent of suspend/resume for the card. + * Mandatory. This should not cut power to the discrete GPU, + * which is the job of the handler + * @reprobe: poll outputs. + * Optional. This gets called after waking the GPU and switching + * the outputs to it + * @can_switch: check if the device is in a position to switch now. + * Mandatory. The client should return false if a user space process + * has one of its device files open + * + * Client callbacks. A client can be either a GPU or an audio device on a GPU. + * The @set_gpu_state and @can_switch methods are mandatory, @reprobe may be + * set to NULL. For audio clients, the @reprobe member is bogus. + */ struct vga_switcheroo_client_ops { void (*set_gpu_state)(struct pci_dev *dev, enum vga_switcheroo_state); void (*reprobe)(struct pci_dev *dev); -- cgit v0.10.2 From 4b813f09405823dcbb27a434f6ddcd1741e55e9b Mon Sep 17 00:00:00 2001 From: Andrew Price Date: Tue, 22 Sep 2015 07:41:21 -0500 Subject: GFS2: fallocate: do not rely on file_update_time to mark the inode dirty Previously __gfs2_fallocate() relied on file_update_time() marking the inode dirty, but that's not a safe assumption as that function doesn't dirty the inode in some cases. Mark the inode dirty explicitly. Signed-off-by: Andrew Price Signed-off-by: Bob Peterson diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index cf4ab89..71cd138 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -897,8 +897,8 @@ static long __gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t if (!(mode & FALLOC_FL_KEEP_SIZE) && (pos + count) > inode->i_size) { i_size_write(inode, pos + count); - /* Marks the inode as dirty */ file_update_time(file); + mark_inode_dirty(inode); } return generic_write_sync(file, pos, count); -- cgit v0.10.2 From 5389e916c3b64c3dd249018dfaf983e2e3a06c6f Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Fri, 4 Sep 2015 21:06:15 +0200 Subject: drm/i915: Spell vga_switcheroo consistently Currently everyone and their dog has their own favourite spelling for vga_switcheroo. This makes it hard to grep dmesg for log entries relating to vga_switcheroo. It also makes it hard to find related source files in the tree. vga_switcheroo.c uses pr_fmt "vga_switcheroo". Use that everywhere. Signed-off-by: Lukas Wunner Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c index d96eee1..8b13b9d 100644 --- a/drivers/gpu/drm/i915/intel_acpi.c +++ b/drivers/gpu/drm/i915/intel_acpi.c @@ -146,7 +146,7 @@ static bool intel_dsm_detect(void) if (vga_count == 2 && has_dsm) { acpi_get_name(intel_dsm_priv.dhandle, ACPI_FULL_PATHNAME, &buffer); - DRM_DEBUG_DRIVER("VGA switcheroo: detected DSM switching method %s handle\n", + DRM_DEBUG_DRIVER("vga_switcheroo: detected DSM switching method %s handle\n", acpi_method_name); return true; } diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 2034438a..2c11b4e 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -821,7 +821,7 @@ void intel_panel_disable_backlight(struct intel_connector *connector) return; /* - * Do not disable backlight on the vgaswitcheroo path. When switching + * Do not disable backlight on the vga_switcheroo path. When switching * away from i915, the other client may depend on i915 to handle the * backlight. This will leave the backlight on unnecessarily when * another client is not activated. -- cgit v0.10.2 From 604ef7346862bb761a091932e99c14204ff4050a Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Mon, 21 Sep 2015 15:33:35 +0200 Subject: drm/i915: fix handling gen8_emit_flush_coherentl3_wa result The function can return negative value. The problem has been detected using proposed semantic patch scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci [1]. [1]: http://permalink.gmane.org/gmane.linux.kernel/2038576 Signed-off-by: Andrzej Hajda Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index fe06accb0..ff9a481 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1254,9 +1254,10 @@ static int gen8_init_indirectctx_bb(struct intel_engine_cs *ring, /* WaFlushCoherentL3CacheLinesAtContextSwitch:bdw */ if (IS_BROADWELL(ring->dev)) { - index = gen8_emit_flush_coherentl3_wa(ring, batch, index); - if (index < 0) - return index; + int rc = gen8_emit_flush_coherentl3_wa(ring, batch, index); + if (rc < 0) + return rc; + index = rc; } /* WaClearSlmSpaceAtContextSwitch:bdw,chv */ -- cgit v0.10.2 From 25e1793f6c642604b13e33bc81a9c8d48d652c86 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 8 Sep 2015 13:56:23 +0200 Subject: drm/i915: Mark debug mod options as _unsafe We don't want random people to touch these. Especially true since we've just screwed up SKL by holding it way too long under the preliminary flag because of some ABI issues. And now there's howtos all over the internets about how to set this. Same pretty much for anything else. Cc: Jani Nikula Signed-off-by: Daniel Vetter Reviewed-by: Jani Nikula [danvet: drop fastboot changes, that option is gone.] Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index ca060d5..ca9b8f6 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -61,7 +61,7 @@ MODULE_PARM_DESC(modeset, "Use kernel modesetting [KMS] (0=disable, " "1=on, -1=force vga console preference [default])"); -module_param_named(panel_ignore_lid, i915.panel_ignore_lid, int, 0600); +module_param_named_unsafe(panel_ignore_lid, i915.panel_ignore_lid, int, 0600); MODULE_PARM_DESC(panel_ignore_lid, "Override lid status (0=autodetect, 1=autodetect disabled [default], " "-1=force lid closed, -2=force lid open)"); @@ -84,17 +84,17 @@ MODULE_PARM_DESC(enable_fbc, "Enable frame buffer compression for power savings " "(default: -1 (use per-chip default))"); -module_param_named(lvds_channel_mode, i915.lvds_channel_mode, int, 0600); +module_param_named_unsafe(lvds_channel_mode, i915.lvds_channel_mode, int, 0600); MODULE_PARM_DESC(lvds_channel_mode, "Specify LVDS channel mode " "(0=probe BIOS [default], 1=single-channel, 2=dual-channel)"); -module_param_named(lvds_use_ssc, i915.panel_use_ssc, int, 0600); +module_param_named_unsafe(lvds_use_ssc, i915.panel_use_ssc, int, 0600); MODULE_PARM_DESC(lvds_use_ssc, "Use Spread Spectrum Clock with panels [LVDS/eDP] " "(default: auto from VBT)"); -module_param_named(vbt_sdvo_panel_type, i915.vbt_sdvo_panel_type, int, 0600); +module_param_named_unsafe(vbt_sdvo_panel_type, i915.vbt_sdvo_panel_type, int, 0600); MODULE_PARM_DESC(vbt_sdvo_panel_type, "Override/Ignore selection of SDVO panel mode in the VBT " "(-2=ignore, -1=auto [default], index in VBT BIOS table)"); @@ -102,7 +102,7 @@ MODULE_PARM_DESC(vbt_sdvo_panel_type, module_param_named_unsafe(reset, i915.reset, bool, 0600); MODULE_PARM_DESC(reset, "Attempt GPU resets (default: true)"); -module_param_named(enable_hangcheck, i915.enable_hangcheck, bool, 0644); +module_param_named_unsafe(enable_hangcheck, i915.enable_hangcheck, bool, 0644); MODULE_PARM_DESC(enable_hangcheck, "Periodically check GPU activity for detecting hangs. " "WARNING: Disabling this can cause system wide hangs. " @@ -113,23 +113,23 @@ MODULE_PARM_DESC(enable_ppgtt, "Override PPGTT usage. " "(-1=auto [default], 0=disabled, 1=aliasing, 2=full)"); -module_param_named(enable_execlists, i915.enable_execlists, int, 0400); +module_param_named_unsafe(enable_execlists, i915.enable_execlists, int, 0400); MODULE_PARM_DESC(enable_execlists, "Override execlists usage. " "(-1=auto [default], 0=disabled, 1=enabled)"); -module_param_named(enable_psr, i915.enable_psr, int, 0600); +module_param_named_unsafe(enable_psr, i915.enable_psr, int, 0600); MODULE_PARM_DESC(enable_psr, "Enable PSR (default: false)"); -module_param_named(preliminary_hw_support, i915.preliminary_hw_support, int, 0600); +module_param_named_unsafe(preliminary_hw_support, i915.preliminary_hw_support, int, 0600); MODULE_PARM_DESC(preliminary_hw_support, "Enable preliminary hardware support."); -module_param_named(disable_power_well, i915.disable_power_well, int, 0600); +module_param_named_unsafe(disable_power_well, i915.disable_power_well, int, 0600); MODULE_PARM_DESC(disable_power_well, "Disable the power well when possible (default: true)"); -module_param_named(enable_ips, i915.enable_ips, int, 0600); +module_param_named_unsafe(enable_ips, i915.enable_ips, int, 0600); MODULE_PARM_DESC(enable_ips, "Enable IPS (default: true)"); module_param_named_unsafe(prefault_disable, i915.prefault_disable, bool, 0600); @@ -142,7 +142,7 @@ MODULE_PARM_DESC(load_detect_test, "Force-enable the VGA load detect code for testing (default:false). " "For developers only."); -module_param_named(invert_brightness, i915.invert_brightness, int, 0600); +module_param_named_unsafe(invert_brightness, i915.invert_brightness, int, 0600); MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness " "(-1 force normal, 0 machine defaults, 1 force inversion), please " @@ -153,14 +153,14 @@ MODULE_PARM_DESC(invert_brightness, module_param_named(disable_display, i915.disable_display, bool, 0600); MODULE_PARM_DESC(disable_display, "Disable display (default: false)"); -module_param_named(disable_vtd_wa, i915.disable_vtd_wa, bool, 0600); +module_param_named_unsafe(disable_vtd_wa, i915.disable_vtd_wa, bool, 0600); MODULE_PARM_DESC(disable_vtd_wa, "Disable all VT-d workarounds (default: false)"); -module_param_named(enable_cmd_parser, i915.enable_cmd_parser, int, 0600); +module_param_named_unsafe(enable_cmd_parser, i915.enable_cmd_parser, int, 0600); MODULE_PARM_DESC(enable_cmd_parser, "Enable command parsing (1=enabled [default], 0=disabled)"); -module_param_named(use_mmio_flip, i915.use_mmio_flip, int, 0600); +module_param_named_unsafe(use_mmio_flip, i915.use_mmio_flip, int, 0600); MODULE_PARM_DESC(use_mmio_flip, "use MMIO flips (-1=never, 0=driver discretion [default], 1=always)"); -- cgit v0.10.2 From adda50b8b32bd559906d82fa32caeaf6c9306f59 Mon Sep 17 00:00:00 2001 From: Bob Paauwe Date: Tue, 21 Jul 2015 10:42:53 -0700 Subject: drm/i915/skl: Don't clear all watermarks when updating. (v2) Clearing the watermarks for all pipes/planes when updating the watermarks for a single CRTC change seems like the wrong thing to do here. As is, this code will ony update any pipe/plane watermarks that need updating and leave the remaining set to zero. Later, the watermark checks in check_wm_state() will flag these zero'd out pipe/plane watermarks and throw errors. By clearing only the watermark values associated with the specific crtc the other watermark values may remain unchanged. v2: Make sure all the dirty flags are cleared. Damien Clear all values assoicated with crtc/pipe being updated. Damien Signed-off-by: Bob Paauwe Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 920872a..bec4e0e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3689,6 +3689,26 @@ static void skl_update_other_pipe_wm(struct drm_device *dev, } } +static void skl_clear_wm(struct skl_wm_values *watermarks, enum pipe pipe) +{ + watermarks->wm_linetime[pipe] = 0; + memset(watermarks->plane[pipe], 0, + sizeof(uint32_t) * 8 * I915_MAX_PLANES); + memset(watermarks->cursor[pipe], 0, sizeof(uint32_t) * 8); + memset(watermarks->plane_trans[pipe], + 0, sizeof(uint32_t) * I915_MAX_PLANES); + watermarks->cursor_trans[pipe] = 0; + + /* Clear ddb entries for pipe */ + memset(&watermarks->ddb.pipe[pipe], 0, sizeof(struct skl_ddb_entry)); + memset(&watermarks->ddb.plane[pipe], 0, + sizeof(struct skl_ddb_entry) * I915_MAX_PLANES); + memset(&watermarks->ddb.y_plane[pipe], 0, + sizeof(struct skl_ddb_entry) * I915_MAX_PLANES); + memset(&watermarks->ddb.cursor[pipe], 0, sizeof(struct skl_ddb_entry)); + +} + static void skl_update_wm(struct drm_crtc *crtc) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -3699,7 +3719,11 @@ static void skl_update_wm(struct drm_crtc *crtc) struct skl_pipe_wm pipe_wm = {}; struct intel_wm_config config = {}; - memset(results, 0, sizeof(*results)); + + /* Clear all dirty flags */ + memset(results->dirty, 0, sizeof(bool) * I915_MAX_PIPES); + + skl_clear_wm(results, intel_crtc->pipe); skl_compute_wm_global_parameters(dev, &config); -- cgit v0.10.2 From 45ddd2e3723a2ed9e5125ddcc3afbb0a27c2c425 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Tue, 22 Sep 2015 08:56:28 -0700 Subject: ARM: configs: keystone: sync to savedefconfig Sync up the defconfig to savedefconfig output. easier to integrate deltas as a result. Signed-off-by: Nishanth Menon Signed-off-by: Santosh Shilimkar diff --git a/arch/arm/configs/keystone_defconfig b/arch/arm/configs/keystone_defconfig index 95ce128..a7ec63e 100644 --- a/arch/arm/configs/keystone_defconfig +++ b/arch/arm/configs/keystone_defconfig @@ -27,6 +27,7 @@ CONFIG_SMP=y CONFIG_PREEMPT=y CONFIG_AEABI=y CONFIG_HIGHMEM=y +CONFIG_CMA=y CONFIG_VFP=y CONFIG_NEON=y # CONFIG_SUSPEND is not set @@ -57,7 +58,6 @@ CONFIG_IP_MROUTE_MULTIPLE_TABLES=y CONFIG_IP_PIMSM_V2=y CONFIG_INET_AH=y CONFIG_INET_IPCOMP=y -CONFIG_IPV6=y CONFIG_INET6_XFRM_MODE_TRANSPORT=m CONFIG_INET6_XFRM_MODE_TUNNEL=m CONFIG_INET6_XFRM_MODE_BEET=m @@ -93,7 +93,6 @@ CONFIG_IP_NF_MATCH_ECN=y CONFIG_IP_NF_MATCH_TTL=y CONFIG_IP_NF_FILTER=y CONFIG_IP_NF_TARGET_REJECT=y -CONFIG_IP_NF_TARGET_ULOG=y CONFIG_IP_NF_MANGLE=y CONFIG_IP_NF_TARGET_CLUSTERIP=y CONFIG_IP_NF_TARGET_ECN=y @@ -106,7 +105,7 @@ CONFIG_IP6_NF_IPTABLES=m CONFIG_IP_SCTP=y CONFIG_VLAN_8021Q=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_CMA=y +CONFIG_DEVTMPFS=y CONFIG_DMA_CMA=y CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y @@ -117,7 +116,6 @@ CONFIG_MTD_NAND=y CONFIG_MTD_NAND_DAVINCI=y CONFIG_MTD_SPI_NOR=y CONFIG_MTD_UBI=y -CONFIG_PROC_DEVICETREE=y CONFIG_BLK_DEV_LOOP=y CONFIG_EEPROM_AT24=y CONFIG_SCSI=y @@ -125,7 +123,7 @@ CONFIG_BLK_DEV_SD=y CONFIG_NETDEVICES=y CONFIG_TI_KEYSTONE_NETCP=y CONFIG_TI_KEYSTONE_NETCP_ETHSS=y -CONFIG_PHYLIB=y +CONFIG_MARVELL_PHY=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_OF_PLATFORM=y @@ -137,12 +135,15 @@ CONFIG_I2C_DAVINCI=y CONFIG_SPI=y CONFIG_SPI_DAVINCI=y CONFIG_SPI_SPIDEV=y -# CONFIG_HWMON is not set +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_DAVINCI=y +CONFIG_GPIO_SYSCON=y CONFIG_POWER_SUPPLY=y CONFIG_POWER_RESET=y CONFIG_POWER_RESET_KEYSTONE=y +# CONFIG_HWMON is not set CONFIG_WATCHDOG=y -CONFIG_WATCHDOG_CORE=y CONFIG_DAVINCI_WATCHDOG=y CONFIG_USB=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y @@ -150,9 +151,15 @@ CONFIG_USB_MON=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_STORAGE=y CONFIG_USB_DWC3=y -CONFIG_USB_DWC3_DEBUG=y -CONFIG_USB_DWC3_VERBOSE=y CONFIG_KEYSTONE_USB_PHY=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_ONESHOT=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_GPIO=y CONFIG_DMADEVICES=y CONFIG_TI_EDMA=y CONFIG_SOC_TI=y @@ -160,6 +167,7 @@ CONFIG_KEYSTONE_NAVIGATOR_QMSS=y CONFIG_KEYSTONE_NAVIGATOR_DMA=y CONFIG_MEMORY=y CONFIG_TI_AEMIF=y +CONFIG_KEYSTONE_IRQ=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_MSDOS_FS=y @@ -179,11 +187,10 @@ CONFIG_NFSD_V3_ACL=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y -CONFIG_DEBUG_SHIRQ=y CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_SHIRQ=y CONFIG_DEBUG_USER=y CONFIG_CRYPTO_USER=y -CONFIG_CRYPTO_NULL=y CONFIG_CRYPTO_AUTHENC=y CONFIG_CRYPTO_CBC=y CONFIG_CRYPTO_CTR=y @@ -192,19 +199,3 @@ CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_ANSI_CPRNG=y CONFIG_CRYPTO_USER_API_HASH=y CONFIG_CRYPTO_USER_API_SKCIPHER=y -CONFIG_GPIOLIB=y -CONFIG_GPIO_SYSFS=y -CONFIG_GPIO_DAVINCI=y -CONFIG_LEDS_CLASS=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_GPIO=y -CONFIG_LEDS_TRIGGERS=y -CONFIG_LEDS_TRIGGER_ONESHOT=y -CONFIG_LEDS_TRIGGER_HEARTBEAT=y -CONFIG_LEDS_TRIGGER_BACKLIGHT=y -CONFIG_LEDS_TRIGGER_GPIO=y -CONFIG_KEYSTONE_IRQ=y -CONFIG_GPIO_SYSCON=y -CONFIG_TI_DAVINCI_MDIO=y -CONFIG_MARVELL_PHY=y -CONFIG_DEVTMPFS=y -- cgit v0.10.2 From 1a3284542f2cedc14fa8c4b4de6b9a85eedf4402 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Tue, 22 Sep 2015 08:56:35 -0700 Subject: ARM: configs: keystone: Add basic systemd related options Add basic options to bootup on systemd based distros such as debian. See http://cgit.freedesktop.org/systemd/systemd/tree/README#n38 for more information. Signed-off-by: Nishanth Menon Signed-off-by: Santosh Shilimkar diff --git a/arch/arm/configs/keystone_defconfig b/arch/arm/configs/keystone_defconfig index a7ec63e..5bcc9cf 100644 --- a/arch/arm/configs/keystone_defconfig +++ b/arch/arm/configs/keystone_defconfig @@ -4,6 +4,12 @@ CONFIG_HIGH_RES_TIMERS=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 +CONFIG_CGROUPS=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_SCHED=y +CONFIG_BLK_CGROUP=y CONFIG_BLK_DEV_INITRD=y CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS_ALL=y @@ -106,6 +112,7 @@ CONFIG_IP_SCTP=y CONFIG_VLAN_8021Q=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y CONFIG_DMA_CMA=y CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y @@ -170,6 +177,8 @@ CONFIG_TI_AEMIF=y CONFIG_KEYSTONE_IRQ=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_FANOTIFY=y +CONFIG_AUTOFS4_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_NTFS_FS=y -- cgit v0.10.2 From 7dc87ff8815ef43717c936faea79013855e3dbef Mon Sep 17 00:00:00 2001 From: Fugang Duan Date: Mon, 7 Sep 2015 10:54:59 +0800 Subject: ARM: imx7d: add imx7d iomux-gpr field define Add imx7d iomux-gpr field define. Signed-off-by: Fugang Duan Signed-off-by: Shawn Guo diff --git a/include/linux/mfd/syscon/imx7-iomuxc-gpr.h b/include/linux/mfd/syscon/imx7-iomuxc-gpr.h new file mode 100644 index 0000000..4585d61 --- /dev/null +++ b/include/linux/mfd/syscon/imx7-iomuxc-gpr.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * + * 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. + */ + +#ifndef __LINUX_IMX7_IOMUXC_GPR_H +#define __LINUX_IMX7_IOMUXC_GPR_H + +#define IOMUXC_GPR0 0x00 +#define IOMUXC_GPR1 0x04 +#define IOMUXC_GPR2 0x08 +#define IOMUXC_GPR3 0x0c +#define IOMUXC_GPR4 0x10 +#define IOMUXC_GPR5 0x14 +#define IOMUXC_GPR6 0x18 +#define IOMUXC_GPR7 0x1c +#define IOMUXC_GPR8 0x20 +#define IOMUXC_GPR9 0x24 +#define IOMUXC_GPR10 0x28 +#define IOMUXC_GPR11 0x2c +#define IOMUXC_GPR12 0x30 +#define IOMUXC_GPR13 0x34 +#define IOMUXC_GPR14 0x38 +#define IOMUXC_GPR15 0x3c +#define IOMUXC_GPR16 0x40 +#define IOMUXC_GPR17 0x44 +#define IOMUXC_GPR18 0x48 +#define IOMUXC_GPR19 0x4c +#define IOMUXC_GPR20 0x50 +#define IOMUXC_GPR21 0x54 +#define IOMUXC_GPR22 0x58 + +/* For imx7d iomux gpr register field define */ +#define IMX7D_GPR1_IRQ_MASK (0x1 << 12) +#define IMX7D_GPR1_ENET1_TX_CLK_SEL_MASK (0x1 << 13) +#define IMX7D_GPR1_ENET2_TX_CLK_SEL_MASK (0x1 << 14) +#define IMX7D_GPR1_ENET_TX_CLK_SEL_MASK (0x3 << 13) +#define IMX7D_GPR1_ENET1_CLK_DIR_MASK (0x1 << 17) +#define IMX7D_GPR1_ENET2_CLK_DIR_MASK (0x1 << 18) +#define IMX7D_GPR1_ENET_CLK_DIR_MASK (0x3 << 17) + +#define IMX7D_GPR5_CSI_MUX_CONTROL_MIPI (0x1 << 4) + +#endif /* __LINUX_IMX7_IOMUXC_GPR_H */ -- cgit v0.10.2 From 69f9c5047d04945693ecc1bdfdb8a3dc2a1f48cf Mon Sep 17 00:00:00 2001 From: Fugang Duan Date: Mon, 7 Sep 2015 10:55:00 +0800 Subject: ARM: imx: add enet init for i.MX7D platform Add enet phy fixup, clock source init for i.MX7D platform. Signed-off-by: Fugang Duan Signed-off-by: Shawn Guo diff --git a/arch/arm/mach-imx/mach-imx7d.c b/arch/arm/mach-imx/mach-imx7d.c index 62f3437..b450f52 100644 --- a/arch/arm/mach-imx/mach-imx7d.c +++ b/arch/arm/mach-imx/mach-imx7d.c @@ -6,12 +6,85 @@ * published by the Free Software Foundation. */ #include +#include +#include #include +#include +#include + #include #include #include "common.h" +static int ar8031_phy_fixup(struct phy_device *dev) +{ + u16 val; + + /* Set RGMII IO voltage to 1.8V */ + phy_write(dev, 0x1d, 0x1f); + phy_write(dev, 0x1e, 0x8); + + /* disable phy AR8031 SmartEEE function. */ + phy_write(dev, 0xd, 0x3); + phy_write(dev, 0xe, 0x805d); + phy_write(dev, 0xd, 0x4003); + val = phy_read(dev, 0xe); + val &= ~(0x1 << 8); + phy_write(dev, 0xe, val); + + /* introduce tx clock delay */ + phy_write(dev, 0x1d, 0x5); + val = phy_read(dev, 0x1e); + val |= 0x0100; + phy_write(dev, 0x1e, val); + + return 0; +} + +static int bcm54220_phy_fixup(struct phy_device *dev) +{ + /* enable RXC skew select RGMII copper mode */ + phy_write(dev, 0x1e, 0x21); + phy_write(dev, 0x1f, 0x7ea8); + phy_write(dev, 0x1e, 0x2f); + phy_write(dev, 0x1f, 0x71b7); + + return 0; +} + +#define PHY_ID_AR8031 0x004dd074 +#define PHY_ID_BCM54220 0x600d8589 + +static void __init imx7d_enet_phy_init(void) +{ + if (IS_BUILTIN(CONFIG_PHYLIB)) { + phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff, + ar8031_phy_fixup); + phy_register_fixup_for_uid(PHY_ID_BCM54220, 0xffffffff, + bcm54220_phy_fixup); + } +} + +static void __init imx7d_enet_clk_sel(void) +{ + struct regmap *gpr; + + gpr = syscon_regmap_lookup_by_compatible("fsl,imx7d-iomuxc-gpr"); + if (!IS_ERR(gpr)) { + regmap_update_bits(gpr, IOMUXC_GPR1, IMX7D_GPR1_ENET_TX_CLK_SEL_MASK, 0); + regmap_update_bits(gpr, IOMUXC_GPR1, IMX7D_GPR1_ENET_CLK_DIR_MASK, 0); + } else { + pr_err("failed to find fsl,imx7d-iomux-gpr regmap\n"); + } +} + +static inline void imx7d_enet_init(void) +{ + imx7d_enet_phy_init(); + imx7d_enet_clk_sel(); +} + static void __init imx7d_init_machine(void) { struct device *parent; @@ -22,6 +95,7 @@ static void __init imx7d_init_machine(void) of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); imx_anatop_init(); + imx7d_enet_init(); } static void __init imx7d_init_irq(void) -- cgit v0.10.2 From de192ef14391dbec5057cf6c798aeb5fe0194e9e Mon Sep 17 00:00:00 2001 From: Ray Jui Date: Mon, 21 Sep 2015 15:12:42 -0700 Subject: ARM: dts: consolidate aliases for Cygnus dt files Move aliases into bcm-cygnus.dtsi to avoid duplications in Cygnus dts files Signed-off-by: Ray Jui Reviewed-by: Scott Branden Signed-off-by: Florian Fainelli diff --git a/arch/arm/boot/dts/bcm-cygnus.dtsi b/arch/arm/boot/dts/bcm-cygnus.dtsi index e1ac07a..30903ba 100644 --- a/arch/arm/boot/dts/bcm-cygnus.dtsi +++ b/arch/arm/boot/dts/bcm-cygnus.dtsi @@ -40,6 +40,10 @@ model = "Broadcom Cygnus SoC"; interrupt-parent = <&gic>; + aliases { + serial0 = &uart3; + }; + cpus { #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/bcm911360_entphn.dts b/arch/arm/boot/dts/bcm911360_entphn.dts index 7db4843..0e1320e 100644 --- a/arch/arm/boot/dts/bcm911360_entphn.dts +++ b/arch/arm/boot/dts/bcm911360_entphn.dts @@ -39,10 +39,6 @@ model = "Cygnus Enterprise Phone (BCM911360_ENTPHN)"; compatible = "brcm,bcm11360", "brcm,cygnus"; - aliases { - serial0 = &uart3; - }; - chosen { stdout-path = &uart3; bootargs = "console=ttyS0,115200"; diff --git a/arch/arm/boot/dts/bcm911360k.dts b/arch/arm/boot/dts/bcm911360k.dts index 9658d4f..2af40c6 100644 --- a/arch/arm/boot/dts/bcm911360k.dts +++ b/arch/arm/boot/dts/bcm911360k.dts @@ -38,10 +38,6 @@ model = "Cygnus SVK (BCM911360K)"; compatible = "brcm,bcm11360", "brcm,cygnus"; - aliases { - serial0 = &uart3; - }; - chosen { stdout-path = &uart3; bootargs = "console=ttyS0,115200"; diff --git a/arch/arm/boot/dts/bcm958300k.dts b/arch/arm/boot/dts/bcm958300k.dts index 2f63052..75e50f0 100644 --- a/arch/arm/boot/dts/bcm958300k.dts +++ b/arch/arm/boot/dts/bcm958300k.dts @@ -38,10 +38,6 @@ model = "Cygnus SVK (BCM958300K)"; compatible = "brcm,bcm58300", "brcm,cygnus"; - aliases { - serial0 = &uart3; - }; - chosen { stdout-path = &uart3; bootargs = "console=ttyS0,115200"; diff --git a/arch/arm/boot/dts/bcm958305k.dts b/arch/arm/boot/dts/bcm958305k.dts index 56b429a..bf62e1b 100644 --- a/arch/arm/boot/dts/bcm958305k.dts +++ b/arch/arm/boot/dts/bcm958305k.dts @@ -38,10 +38,6 @@ model = "Cygnus Wireless Audio (BCM958305K)"; compatible = "brcm,bcm58305", "brcm,cygnus"; - aliases { - serial0 = &uart3; - }; - chosen { stdout-path = &uart3; bootargs = "console=ttyS0,115200"; -- cgit v0.10.2 From 5b159b62eb2a6799d9dbe998d7635b346ca6fdf8 Mon Sep 17 00:00:00 2001 From: Ray Jui Date: Mon, 21 Sep 2015 15:12:43 -0700 Subject: ARM: dts: Use label for device nodes in Cygnus dts Use label instead of full path to reference device nodes in Cygnus dts files Signed-off-by: Ray Jui Reviewed-by: Scott Branden Signed-off-by: Florian Fainelli diff --git a/arch/arm/boot/dts/bcm911360_entphn.dts b/arch/arm/boot/dts/bcm911360_entphn.dts index 0e1320e..f791a3b 100644 --- a/arch/arm/boot/dts/bcm911360_entphn.dts +++ b/arch/arm/boot/dts/bcm911360_entphn.dts @@ -44,10 +44,6 @@ bootargs = "console=ttyS0,115200"; }; - uart3: serial@18023000 { - status = "okay"; - }; - gpio_keys { compatible = "gpio-keys"; #address-cells = <1>; @@ -60,3 +56,7 @@ }; }; }; + +&uart3 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/bcm911360k.dts b/arch/arm/boot/dts/bcm911360k.dts index 2af40c6..814011c 100644 --- a/arch/arm/boot/dts/bcm911360k.dts +++ b/arch/arm/boot/dts/bcm911360k.dts @@ -42,8 +42,8 @@ stdout-path = &uart3; bootargs = "console=ttyS0,115200"; }; +}; - uart3: serial@18023000 { - status = "okay"; - }; +&uart3 { + status = "okay"; }; diff --git a/arch/arm/boot/dts/bcm958300k.dts b/arch/arm/boot/dts/bcm958300k.dts index 75e50f0..d8dc9f0 100644 --- a/arch/arm/boot/dts/bcm958300k.dts +++ b/arch/arm/boot/dts/bcm958300k.dts @@ -42,32 +42,32 @@ stdout-path = &uart3; bootargs = "console=ttyS0,115200"; }; +}; - pcie0: pcie@18012000 { - status = "okay"; - }; +&pcie0 { + status = "okay"; +}; - pcie1: pcie@18013000 { - status = "okay"; - }; +&pcie1 { + status = "okay"; +}; - uart3: serial@18023000 { - status = "okay"; - }; +&uart3 { + status = "okay"; +}; - nand: nand@18046000 { - nandcs@1 { - compatible = "brcm,nandcs"; - reg = <0>; - nand-on-flash-bbt; +&nand { + nandcs@1 { + compatible = "brcm,nandcs"; + reg = <0>; + nand-on-flash-bbt; - #address-cells = <1>; - #size-cells = <1>; + #address-cells = <1>; + #size-cells = <1>; - nand-ecc-strength = <24>; - nand-ecc-step-size = <1024>; + nand-ecc-strength = <24>; + nand-ecc-step-size = <1024>; - brcm,nand-oob-sector-size = <27>; - }; + brcm,nand-oob-sector-size = <27>; }; }; diff --git a/arch/arm/boot/dts/bcm958305k.dts b/arch/arm/boot/dts/bcm958305k.dts index bf62e1b..af11a8e 100644 --- a/arch/arm/boot/dts/bcm958305k.dts +++ b/arch/arm/boot/dts/bcm958305k.dts @@ -42,8 +42,8 @@ stdout-path = &uart3; bootargs = "console=ttyS0,115200"; }; +}; - uart3: serial@18023000 { - status = "okay"; - }; +&uart3 { + status = "okay"; }; -- cgit v0.10.2 From ef5b812a4e8d088836e67ade113562ca5ad4579e Mon Sep 17 00:00:00 2001 From: Ray Jui Date: Mon, 21 Sep 2015 15:12:44 -0700 Subject: ARM: dts: Put Cygnus core components under core bus Put all Cygnus core components into "core" node of type "simple-bus" in bcm-cygnus.dtsi Signed-off-by: Ray Jui Reviewed-by: Scott Branden Signed-off-by: Florian Fainelli diff --git a/arch/arm/boot/dts/bcm-cygnus.dtsi b/arch/arm/boot/dts/bcm-cygnus.dtsi index 30903ba..97fd305 100644 --- a/arch/arm/boot/dts/bcm-cygnus.dtsi +++ b/arch/arm/boot/dts/bcm-cygnus.dtsi @@ -58,6 +58,36 @@ /include/ "bcm-cygnus-clock.dtsi" + core { + compatible = "simple-bus"; + ranges = <0x00000000 0x19000000 0x1000000>; + #address-cells = <1>; + #size-cells = <1>; + + timer@20200 { + compatible = "arm,cortex-a9-global-timer"; + reg = <0x20200 0x100>; + interrupts = ; + clocks = <&periph_clk>; + }; + + gic: interrupt-controller@21000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x21000 0x1000>, + <0x20100 0x100>; + }; + + L2: l2-cache { + compatible = "arm,pl310-cache"; + reg = <0x22000 0x1000>; + cache-unified; + cache-level = <2>; + }; + }; + pinctrl: pinctrl@0x0301d0c8 { compatible = "brcm,cygnus-pinmux"; reg = <0x0301d0c8 0x30>, @@ -227,28 +257,4 @@ brcm,nand-has-wp; }; - - gic: interrupt-controller@19021000 { - compatible = "arm,cortex-a9-gic"; - #interrupt-cells = <3>; - #address-cells = <0>; - interrupt-controller; - reg = <0x19021000 0x1000>, - <0x19020100 0x100>; - }; - - L2: l2-cache { - compatible = "arm,pl310-cache"; - reg = <0x19022000 0x1000>; - cache-unified; - cache-level = <2>; - }; - - timer@19020200 { - compatible = "arm,cortex-a9-global-timer"; - reg = <0x19020200 0x100>; - interrupts = ; - clocks = <&periph_clk>; - }; - }; -- cgit v0.10.2 From 0f0b21a83ad2285cd14082c7cfae57a0288dd813 Mon Sep 17 00:00:00 2001 From: Ray Jui Date: Mon, 21 Sep 2015 15:12:45 -0700 Subject: ARM: dts: Move all Cygnus peripherals into axi bus Move all Cygnus peripherals to be under the "axi" bus node of type "simple-bus" Signed-off-by: Ray Jui Reviewed-by: Scott Branden Signed-off-by: Florian Fainelli diff --git a/arch/arm/boot/dts/bcm-cygnus.dtsi b/arch/arm/boot/dts/bcm-cygnus.dtsi index 97fd305..5ee7543 100644 --- a/arch/arm/boot/dts/bcm-cygnus.dtsi +++ b/arch/arm/boot/dts/bcm-cygnus.dtsi @@ -88,173 +88,174 @@ }; }; - pinctrl: pinctrl@0x0301d0c8 { - compatible = "brcm,cygnus-pinmux"; - reg = <0x0301d0c8 0x30>, - <0x0301d24c 0x2c>; - }; + axi { + compatible = "simple-bus"; + ranges; + #address-cells = <1>; + #size-cells = <1>; - gpio_crmu: gpio@03024800 { - compatible = "brcm,cygnus-crmu-gpio"; - reg = <0x03024800 0x50>, - <0x03024008 0x18>; - #gpio-cells = <2>; - gpio-controller; - }; + pinctrl: pinctrl@0x0301d0c8 { + compatible = "brcm,cygnus-pinmux"; + reg = <0x0301d0c8 0x30>, + <0x0301d24c 0x2c>; + }; - gpio_ccm: gpio@1800a000 { - compatible = "brcm,cygnus-ccm-gpio"; - reg = <0x1800a000 0x50>, - <0x0301d164 0x20>; - #gpio-cells = <2>; - gpio-controller; - interrupts = ; - interrupt-controller; - }; + gpio_crmu: gpio@03024800 { + compatible = "brcm,cygnus-crmu-gpio"; + reg = <0x03024800 0x50>, + <0x03024008 0x18>; + #gpio-cells = <2>; + gpio-controller; + }; - gpio_asiu: gpio@180a5000 { - compatible = "brcm,cygnus-asiu-gpio"; - reg = <0x180a5000 0x668>; - #gpio-cells = <2>; - gpio-controller; + gpio_ccm: gpio@1800a000 { + compatible = "brcm,cygnus-ccm-gpio"; + reg = <0x1800a000 0x50>, + <0x0301d164 0x20>; + #gpio-cells = <2>; + gpio-controller; + interrupts = ; + interrupt-controller; + }; - pinmux = <&pinctrl>; + gpio_asiu: gpio@180a5000 { + compatible = "brcm,cygnus-asiu-gpio"; + reg = <0x180a5000 0x668>; + #gpio-cells = <2>; + gpio-controller; - interrupt-controller; - interrupts = ; - }; + pinmux = <&pinctrl>; - amba { - #address-cells = <1>; - #size-cells = <1>; - compatible = "arm,amba-bus", "simple-bus"; - interrupt-parent = <&gic>; - ranges; + interrupt-controller; + interrupts = ; + }; - wdt@18009000 { - compatible = "arm,sp805" , "arm,primecell"; - reg = <0x18009000 0x1000>; - interrupts = ; - clocks = <&axi81_clk>; - clock-names = "apb_pclk"; + wdt0: wdt@18009000 { + compatible = "arm,sp805" , "arm,primecell"; + reg = <0x18009000 0x1000>; + interrupts = ; + clocks = <&axi81_clk>; + clock-names = "apb_pclk"; }; - }; - i2c0: i2c@18008000 { - compatible = "brcm,cygnus-iproc-i2c", "brcm,iproc-i2c"; - reg = <0x18008000 0x100>; - #address-cells = <1>; - #size-cells = <0>; - interrupts = ; - clock-frequency = <100000>; - status = "disabled"; - }; + i2c0: i2c@18008000 { + compatible = "brcm,cygnus-iproc-i2c", "brcm,iproc-i2c"; + reg = <0x18008000 0x100>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clock-frequency = <100000>; + status = "disabled"; + }; - i2c1: i2c@1800b000 { - compatible = "brcm,cygnus-iproc-i2c", "brcm,iproc-i2c"; - reg = <0x1800b000 0x100>; - #address-cells = <1>; - #size-cells = <0>; - interrupts = ; - clock-frequency = <100000>; - status = "disabled"; - }; + i2c1: i2c@1800b000 { + compatible = "brcm,cygnus-iproc-i2c", "brcm,iproc-i2c"; + reg = <0x1800b000 0x100>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clock-frequency = <100000>; + status = "disabled"; + }; - pcie0: pcie@18012000 { - compatible = "brcm,iproc-pcie"; - reg = <0x18012000 0x1000>; + pcie0: pcie@18012000 { + compatible = "brcm,iproc-pcie"; + reg = <0x18012000 0x1000>; - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &gic GIC_SPI 100 IRQ_TYPE_NONE>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 100 IRQ_TYPE_NONE>; - linux,pci-domain = <0>; + linux,pci-domain = <0>; - bus-range = <0x00 0xff>; + bus-range = <0x00 0xff>; - #address-cells = <3>; - #size-cells = <2>; - device_type = "pci"; - ranges = <0x81000000 0 0 0x28000000 0 0x00010000 - 0x82000000 0 0x20000000 0x20000000 0 0x04000000>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges = <0x81000000 0 0 0x28000000 0 0x00010000 + 0x82000000 0 0x20000000 0x20000000 0 0x04000000>; - status = "disabled"; - }; + status = "disabled"; + }; - pcie1: pcie@18013000 { - compatible = "brcm,iproc-pcie"; - reg = <0x18013000 0x1000>; + pcie1: pcie@18013000 { + compatible = "brcm,iproc-pcie"; + reg = <0x18013000 0x1000>; - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &gic GIC_SPI 106 IRQ_TYPE_NONE>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 106 IRQ_TYPE_NONE>; - linux,pci-domain = <1>; + linux,pci-domain = <1>; - bus-range = <0x00 0xff>; + bus-range = <0x00 0xff>; - #address-cells = <3>; - #size-cells = <2>; - device_type = "pci"; - ranges = <0x81000000 0 0 0x48000000 0 0x00010000 - 0x82000000 0 0x40000000 0x40000000 0 0x04000000>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges = <0x81000000 0 0 0x48000000 0 0x00010000 + 0x82000000 0 0x40000000 0x40000000 0 0x04000000>; - status = "disabled"; - }; + status = "disabled"; + }; - uart0: serial@18020000 { - compatible = "snps,dw-apb-uart"; - reg = <0x18020000 0x100>; - reg-shift = <2>; - reg-io-width = <4>; - interrupts = ; - clocks = <&axi81_clk>; - clock-frequency = <100000000>; - status = "disabled"; - }; + uart0: serial@18020000 { + compatible = "snps,dw-apb-uart"; + reg = <0x18020000 0x100>; + reg-shift = <2>; + reg-io-width = <4>; + interrupts = ; + clocks = <&axi81_clk>; + clock-frequency = <100000000>; + status = "disabled"; + }; - uart1: serial@18021000 { - compatible = "snps,dw-apb-uart"; - reg = <0x18021000 0x100>; - reg-shift = <2>; - reg-io-width = <4>; - interrupts = ; - clocks = <&axi81_clk>; - clock-frequency = <100000000>; - status = "disabled"; - }; + uart1: serial@18021000 { + compatible = "snps,dw-apb-uart"; + reg = <0x18021000 0x100>; + reg-shift = <2>; + reg-io-width = <4>; + interrupts = ; + clocks = <&axi81_clk>; + clock-frequency = <100000000>; + status = "disabled"; + }; - uart2: serial@18022000 { - compatible = "snps,dw-apb-uart"; - reg = <0x18020000 0x100>; - reg-shift = <2>; - reg-io-width = <4>; - interrupts = ; - clocks = <&axi81_clk>; - clock-frequency = <100000000>; - status = "disabled"; - }; + uart2: serial@18022000 { + compatible = "snps,dw-apb-uart"; + reg = <0x18020000 0x100>; + reg-shift = <2>; + reg-io-width = <4>; + interrupts = ; + clocks = <&axi81_clk>; + clock-frequency = <100000000>; + status = "disabled"; + }; - uart3: serial@18023000 { - compatible = "snps,dw-apb-uart"; - reg = <0x18023000 0x100>; - reg-shift = <2>; - reg-io-width = <4>; - interrupts = ; - clocks = <&axi81_clk>; - clock-frequency = <100000000>; - status = "disabled"; - }; + uart3: serial@18023000 { + compatible = "snps,dw-apb-uart"; + reg = <0x18023000 0x100>; + reg-shift = <2>; + reg-io-width = <4>; + interrupts = ; + clocks = <&axi81_clk>; + clock-frequency = <100000000>; + status = "disabled"; + }; - nand: nand@18046000 { - compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1", "brcm,brcmnand"; - reg = <0x18046000 0x600>, <0xf8105408 0x600>, <0x18046f00 0x20>; - reg-names = "nand", "iproc-idm", "iproc-ext"; - interrupts = ; + nand: nand@18046000 { + compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1", + "brcm,brcmnand"; + reg = <0x18046000 0x600>, <0xf8105408 0x600>, + <0x18046f00 0x20>; + reg-names = "nand", "iproc-idm", "iproc-ext"; + interrupts = ; - #address-cells = <1>; - #size-cells = <0>; + #address-cells = <1>; + #size-cells = <0>; - brcm,nand-has-wp; + brcm,nand-has-wp; + }; }; }; -- cgit v0.10.2 From 9c5101f7a253c4f2f9bbe47e8bb681b63f4c65f5 Mon Sep 17 00:00:00 2001 From: Ray Jui Date: Mon, 21 Sep 2015 15:12:46 -0700 Subject: ARM: dts: Reorder Cygnus peripherals Reorder all Cygnus peripherals based on base register addresses in bcm-cygnus.dtsi Signed-off-by: Ray Jui Reviewed-by: Scott Branden Signed-off-by: Florian Fainelli diff --git a/arch/arm/boot/dts/bcm-cygnus.dtsi b/arch/arm/boot/dts/bcm-cygnus.dtsi index 5ee7543..33ec6a5 100644 --- a/arch/arm/boot/dts/bcm-cygnus.dtsi +++ b/arch/arm/boot/dts/bcm-cygnus.dtsi @@ -108,26 +108,14 @@ gpio-controller; }; - gpio_ccm: gpio@1800a000 { - compatible = "brcm,cygnus-ccm-gpio"; - reg = <0x1800a000 0x50>, - <0x0301d164 0x20>; - #gpio-cells = <2>; - gpio-controller; - interrupts = ; - interrupt-controller; - }; - - gpio_asiu: gpio@180a5000 { - compatible = "brcm,cygnus-asiu-gpio"; - reg = <0x180a5000 0x668>; - #gpio-cells = <2>; - gpio-controller; - - pinmux = <&pinctrl>; - - interrupt-controller; - interrupts = ; + i2c0: i2c@18008000 { + compatible = "brcm,cygnus-iproc-i2c", "brcm,iproc-i2c"; + reg = <0x18008000 0x100>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clock-frequency = <100000>; + status = "disabled"; }; wdt0: wdt@18009000 { @@ -138,14 +126,14 @@ clock-names = "apb_pclk"; }; - i2c0: i2c@18008000 { - compatible = "brcm,cygnus-iproc-i2c", "brcm,iproc-i2c"; - reg = <0x18008000 0x100>; - #address-cells = <1>; - #size-cells = <0>; - interrupts = ; - clock-frequency = <100000>; - status = "disabled"; + gpio_ccm: gpio@1800a000 { + compatible = "brcm,cygnus-ccm-gpio"; + reg = <0x1800a000 0x50>, + <0x0301d164 0x20>; + #gpio-cells = <2>; + gpio-controller; + interrupts = ; + interrupt-controller; }; i2c1: i2c@1800b000 { @@ -257,5 +245,17 @@ brcm,nand-has-wp; }; + + gpio_asiu: gpio@180a5000 { + compatible = "brcm,cygnus-asiu-gpio"; + reg = <0x180a5000 0x668>; + #gpio-cells = <2>; + gpio-controller; + + pinmux = <&pinctrl>; + + interrupt-controller; + interrupts = ; + }; }; }; -- cgit v0.10.2 From 894526cd466e4cb5fd88afbc5ff573b14933321f Mon Sep 17 00:00:00 2001 From: Ray Jui Date: Mon, 21 Sep 2015 15:12:47 -0700 Subject: ARM: dts: Enable various peripherals on bcm958305k This patch enables various peripherals on Broadcom Cygnus wireless audio board (bcm958305k). These peripherals include I2C, PCIe, and NAND Signed-off-by: Ray Jui Reviewed-by: Scott Branden Signed-off-by: Florian Fainelli diff --git a/arch/arm/boot/dts/bcm958305k.dts b/arch/arm/boot/dts/bcm958305k.dts index af11a8e..9863a19 100644 --- a/arch/arm/boot/dts/bcm958305k.dts +++ b/arch/arm/boot/dts/bcm958305k.dts @@ -44,6 +44,38 @@ }; }; +&i2c0 { + status = "okay"; +}; + +&i2c1 { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; + +&pcie1 { + status = "okay"; +}; + &uart3 { status = "okay"; }; + +&nand { + nandcs@1 { + compatible = "brcm,nandcs"; + reg = <0>; + nand-on-flash-bbt; + + #address-cells = <1>; + #size-cells = <1>; + + nand-ecc-strength = <24>; + nand-ecc-step-size = <1024>; + + brcm,nand-oob-sector-size = <27>; + }; +}; -- cgit v0.10.2 From 2e561f92dc12ea3de131d337516d58862fd7ef2c Mon Sep 17 00:00:00 2001 From: Ray Jui Date: Mon, 21 Sep 2015 15:12:48 -0700 Subject: ARM: dts: Enable NAND support on bcm911360_entphn This patch enables NAND support on Broadcom Cygnus form factor board (bcm911360_entphn) Signed-off-by: Ray Jui Reviewed-by: Scott Branden Signed-off-by: Florian Fainelli diff --git a/arch/arm/boot/dts/bcm911360_entphn.dts b/arch/arm/boot/dts/bcm911360_entphn.dts index f791a3b..8b3800f 100644 --- a/arch/arm/boot/dts/bcm911360_entphn.dts +++ b/arch/arm/boot/dts/bcm911360_entphn.dts @@ -60,3 +60,19 @@ &uart3 { status = "okay"; }; + +&nand { + nandcs@1 { + compatible = "brcm,nandcs"; + reg = <0>; + nand-on-flash-bbt; + + #address-cells = <1>; + #size-cells = <1>; + + nand-ecc-strength = <24>; + nand-ecc-step-size = <1024>; + + brcm,nand-oob-sector-size = <27>; + }; +}; -- cgit v0.10.2 From 35e372a3a1f016648f278aeb7b55fe347b6699da Mon Sep 17 00:00:00 2001 From: Ray Jui Date: Mon, 21 Sep 2015 15:12:49 -0700 Subject: ARM: dts: enable touchscreen support on Cygnus This patch enables touchscreen support on bcm958300k and bcm958305k. Touchscreen is connected to these boards through the bcm9hmidc daughter card, and therefore also adding bcm9hmidc.dtsi that describes the daughter card Signed-off-by: Ray Jui Reviewed-by: Vikram Prakash Reviewed-by: Scott Branden Signed-off-by: Florian Fainelli diff --git a/arch/arm/boot/dts/bcm-cygnus.dtsi b/arch/arm/boot/dts/bcm-cygnus.dtsi index 33ec6a5..24e058c 100644 --- a/arch/arm/boot/dts/bcm-cygnus.dtsi +++ b/arch/arm/boot/dts/bcm-cygnus.dtsi @@ -32,6 +32,7 @@ #include #include +#include #include "skeleton.dtsi" @@ -257,5 +258,14 @@ interrupt-controller; interrupts = ; }; + + touchscreen: tsc@180a6000 { + compatible = "brcm,iproc-touchscreen"; + reg = <0x180a6000 0x40>; + clocks = <&asiu_clks BCM_CYGNUS_ASIU_ADC_CLK>; + clock-names = "tsc_clk"; + interrupts = ; + status = "disabled"; + }; }; }; diff --git a/arch/arm/boot/dts/bcm958300k.dts b/arch/arm/boot/dts/bcm958300k.dts index d8dc9f0..2e31581 100644 --- a/arch/arm/boot/dts/bcm958300k.dts +++ b/arch/arm/boot/dts/bcm958300k.dts @@ -33,6 +33,7 @@ /dts-v1/; #include "bcm-cygnus.dtsi" +#include "bcm9hmidc.dtsi" / { model = "Cygnus SVK (BCM958300K)"; diff --git a/arch/arm/boot/dts/bcm958305k.dts b/arch/arm/boot/dts/bcm958305k.dts index 9863a19..288a637 100644 --- a/arch/arm/boot/dts/bcm958305k.dts +++ b/arch/arm/boot/dts/bcm958305k.dts @@ -33,6 +33,7 @@ /dts-v1/; #include "bcm-cygnus.dtsi" +#include "bcm9hmidc.dtsi" / { model = "Cygnus Wireless Audio (BCM958305K)"; diff --git a/arch/arm/boot/dts/bcm9hmidc.dtsi b/arch/arm/boot/dts/bcm9hmidc.dtsi new file mode 100644 index 0000000..65397c0 --- /dev/null +++ b/arch/arm/boot/dts/bcm9hmidc.dtsi @@ -0,0 +1,42 @@ +/* + * BSD LICENSE + * + * Copyright(c) 2015 Broadcom Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Broadcom Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Broadcom human machine interface daughter card (bcm9hmidc) installed on + * bcm958300k/bcm958305k boards + */ + +&touchscreen { + touchscreen-inverted-x; + touchscreen-inverted-y; + status = "okay"; +}; -- cgit v0.10.2 From 08668d9de98193936a082f36c105fc3de168b69b Mon Sep 17 00:00:00 2001 From: Ray Jui Date: Mon, 21 Sep 2015 15:12:50 -0700 Subject: ARM: dts: fix Cygnus nand device node The third compatible string "brcm,brcmnand" in bcm-cygnus.dtsi nand node is incorrect, redundant and should be removed. "brcm,brcmnand" is meant to be used by STB based Broadcom SoCs. All iProc based SoCs should use "brcm,nand-iproc". Signed-off-by: Ray Jui Signed-off-by: Florian Fainelli diff --git a/arch/arm/boot/dts/bcm-cygnus.dtsi b/arch/arm/boot/dts/bcm-cygnus.dtsi index 24e058c..b5f9f34 100644 --- a/arch/arm/boot/dts/bcm-cygnus.dtsi +++ b/arch/arm/boot/dts/bcm-cygnus.dtsi @@ -234,8 +234,7 @@ }; nand: nand@18046000 { - compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1", - "brcm,brcmnand"; + compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1"; reg = <0x18046000 0x600>, <0xf8105408 0x600>, <0x18046f00 0x20>; reg-names = "nand", "iproc-idm", "iproc-ext"; -- cgit v0.10.2 From 18c237c0f9fa2e1c66e1eb4c305aeff4f28f89bf Mon Sep 17 00:00:00 2001 From: Animesh Manna Date: Tue, 4 Aug 2015 22:02:41 +0530 Subject: drm/i915/bxt: Path added of dmc firmware ver1 for BXT. Broxton also has dmc to manage low-power display engine state. Path of the firmware added in intel_csr.c. Naming convention followed as _dmc_.bin v1: Initial version. v2: Commit description added based on review comment from Sunil. Cc: Damien Lespiau Cc: Rodrigo Vivi Cc: Sunil Kamath Signed-off-by: Animesh Manna Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 765dfcd..6d1aaff 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -42,8 +42,10 @@ */ #define I915_CSR_SKL "i915/skl_dmc_ver1.bin" +#define I915_CSR_BXT "i915/bxt_dmc_ver1.bin" MODULE_FIRMWARE(I915_CSR_SKL); +MODULE_FIRMWARE(I915_CSR_BXT); /* * SKL CSR registers for DC5 and DC6 @@ -409,6 +411,8 @@ void intel_csr_ucode_init(struct drm_device *dev) if (IS_SKYLAKE(dev)) csr->fw_path = I915_CSR_SKL; + else if (IS_BROXTON(dev_priv)) + csr->fw_path = I915_CSR_BXT; else { DRM_ERROR("Unexpected: no known CSR firmware for platform\n"); intel_csr_load_status_set(dev_priv, FW_FAILED); -- cgit v0.10.2 From cff765fb1383dff6787fa735fcc88aa122d3c00d Mon Sep 17 00:00:00 2001 From: Animesh Manna Date: Tue, 4 Aug 2015 22:02:43 +0530 Subject: drm/i915/bxt: Stepping info added for bxt. Added stepping info in intel_csr.c which is required to extract specific firmware from packaged dmc firmware. Stepping info is aligned with current bspec info. Cc: Vetter, Daniel Cc: Damien Lespiau Cc: Imre Deak Cc: Sunil Kamath Signed-off-by: Animesh Manna Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 6d1aaff..780d5d5 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -183,11 +183,19 @@ static const struct stepping_info skl_stepping_info[] = { {'G', '0'}, {'H', '0'}, {'I', '0'} }; +static struct stepping_info bxt_stepping_info[] = { + {'A', '0'}, {'A', '1'}, {'A', '2'}, + {'B', '0'}, {'B', '1'}, {'B', '2'} +}; + static char intel_get_stepping(struct drm_device *dev) { if (IS_SKYLAKE(dev) && (dev->pdev->revision < ARRAY_SIZE(skl_stepping_info))) return skl_stepping_info[dev->pdev->revision].stepping; + else if (IS_BROXTON(dev) && (dev->pdev->revision < + ARRAY_SIZE(bxt_stepping_info))) + return bxt_stepping_info[dev->pdev->revision].stepping; else return -ENODATA; } @@ -197,6 +205,9 @@ static char intel_get_substepping(struct drm_device *dev) if (IS_SKYLAKE(dev) && (dev->pdev->revision < ARRAY_SIZE(skl_stepping_info))) return skl_stepping_info[dev->pdev->revision].substepping; + else if (IS_BROXTON(dev) && (dev->pdev->revision < + ARRAY_SIZE(bxt_stepping_info))) + return bxt_stepping_info[dev->pdev->revision].substepping; else return -ENODATA; } -- cgit v0.10.2 From 7b403ffba8ed8636f3467a9008bd2e060792b2e4 Mon Sep 17 00:00:00 2001 From: Animesh Manna Date: Tue, 4 Aug 2015 22:02:42 +0530 Subject: drm/i915/bxt: Modified HAS_CSR, added support for BXT Modified HAS_CSR macro defination which earlier only supported for skl, now added support for BXT. v1: Initial version. v2: Instaed of skylake/broxton check added gen9 check alone based on review comment from Sunil. Cc: Vetter, Daniel Cc: Damien Lespiau Cc: Imre Deak Cc: Sunil Kamath Signed-off-by: Animesh Manna Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 677faa8..3795fdf 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2578,7 +2578,7 @@ struct drm_i915_cmd_table { #define HAS_RC6(dev) (INTEL_INFO(dev)->gen >= 6) #define HAS_RC6p(dev) (INTEL_INFO(dev)->gen == 6 || IS_IVYBRIDGE(dev)) -#define HAS_CSR(dev) (IS_SKYLAKE(dev)) +#define HAS_CSR(dev) (IS_GEN9(dev)) #define HAS_GUC_UCODE(dev) (IS_GEN9(dev)) #define HAS_GUC_SCHED(dev) (IS_GEN9(dev)) -- cgit v0.10.2 From 23eafea6a9d1faac0588a5275d0c755cb261346e Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Sun, 23 Aug 2015 17:52:48 +0530 Subject: drm/i915/bxt: WaGsvDisableTurbo Disable Turbo on steppings prior to B0 on BXT due to hangs seen during GT CPD exit. Change-Id: I50c5c03f59f5ba092db19e17234951d89db42c6c Signed-off-by: Sagar Arun Kamble Reviewed by: Alex Dai . Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index bec4e0e..f52431b 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4487,6 +4487,10 @@ static void gen6_set_rps(struct drm_device *dev, u8 val) { struct drm_i915_private *dev_priv = dev->dev_private; + /* WaGsvDisableTurbo: Workaround to disable turbo on BXT A* */ + if (IS_BROXTON(dev) && (INTEL_REVID(dev) < BXT_REVID_B0)) + return; + WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); WARN_ON(val > dev_priv->rps.max_freq); WARN_ON(val < dev_priv->rps.min_freq); @@ -4807,6 +4811,12 @@ static void gen9_enable_rps(struct drm_device *dev) gen6_init_rps_frequencies(dev); + /* WaGsvDisableTurbo: Workaround to disable turbo on BXT A* */ + if (IS_BROXTON(dev) && (INTEL_REVID(dev) < BXT_REVID_B0)) { + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); + return; + } + /* Program defaults and thresholds for RPS*/ I915_WRITE(GEN6_RC_VIDEO_FREQ, GEN9_FREQUENCY(dev_priv->rps.rp1_freq)); -- cgit v0.10.2 From 83e3337204b2385d20e149c8fe91bb2719978df2 Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Sun, 23 Aug 2015 17:52:47 +0530 Subject: drm/i915: Increase maximum polling time to 50ms for forcewake request/clear ack On BXT, We Observe timeout for forcewake request completion with 2ms polling period as given here: [drm:fw_domains_get] ERROR render: timed out waiting for forcewake ack request. Polling for 50ms is recommended to avoid these timeouts. Change-Id: Ie715b0069a3049606e9602bc5e97a6511890864d Signed-off-by: Sagar Arun Kamble Reviewed by: Alex Dai Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 440e2a5..14d0831 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -27,7 +27,7 @@ #include -#define FORCEWAKE_ACK_TIMEOUT_MS 2 +#define FORCEWAKE_ACK_TIMEOUT_MS 50 #define __raw_i915_read8(dev_priv__, reg__) readb((dev_priv__)->regs + (reg__)) #define __raw_i915_write8(dev_priv__, reg__, val__) writeb(val__, (dev_priv__)->regs + (reg__)) -- cgit v0.10.2 From cfe01a5eba1ff5723f3a47895fb7e9d890edf157 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Tue, 1 Sep 2015 19:41:38 +0530 Subject: drm/i915/bxt: Enable BXT DSI PLL This patch adds new functions for BXT clock and PLL programming. They are: 1. configure_dsi_pll for BXT. This function does the basic math and generates the divider ratio based on requested pixclock, and program clock registers. 2. enable_dsi_pll function. This function programs the calculated clock values on the PLL. 3. intel_enable_dsi_pll Wrapper function to use same code for multiple platforms. It checks the platform and calls appropriate core pll enable function. v2: Fixed Jani's review comments. Macros are adjusted as per convention. v3: Removed a redundant change wrt code comment. Signed-off-by: Shashank Sharma Signed-off-by: Uma Shankar Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index dd3d235..4ef16aa 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7507,6 +7507,28 @@ enum skl_disp_power_wells { #define _MIPI_PORT(port, a, c) _PORT3(port, a, 0, c) /* ports A and C only */ +#define BXT_DSI_PLL_CTL 0x161000 +#define BXT_DSI_PLL_PVD_RATIO_SHIFT 16 +#define BXT_DSI_PLL_PVD_RATIO_MASK (3 << BXT_DSI_PLL_PVD_RATIO_SHIFT) +#define BXT_DSI_PLL_PVD_RATIO_1 (1 << BXT_DSI_PLL_PVD_RATIO_SHIFT) +#define BXT_DSIC_16X_BY2 (1 << 10) +#define BXT_DSIC_16X_BY3 (2 << 10) +#define BXT_DSIC_16X_BY4 (3 << 10) +#define BXT_DSIA_16X_BY2 (1 << 8) +#define BXT_DSIA_16X_BY3 (2 << 8) +#define BXT_DSIA_16X_BY4 (3 << 8) +#define BXT_DSI_FREQ_SEL_SHIFT 8 +#define BXT_DSI_FREQ_SEL_MASK (0xF << BXT_DSI_FREQ_SEL_SHIFT) + +#define BXT_DSI_PLL_RATIO_MAX 0x7D +#define BXT_DSI_PLL_RATIO_MIN 0x22 +#define BXT_DSI_PLL_RATIO_MASK 0xFF +#define BXT_REF_CLOCK_KHZ 19500 + +#define BXT_DSI_PLL_ENABLE 0x46080 +#define BXT_DSI_PLL_DO_ENABLE (1 << 31) +#define BXT_DSI_PLL_LOCKED (1 << 30) + #define _MIPIA_PORT_CTRL (VLV_DISPLAY_BASE + 0x61190) #define _MIPIC_PORT_CTRL (VLV_DISPLAY_BASE + 0x61700) #define MIPI_PORT_CTRL(port) _MIPI_PORT(port, _MIPIA_PORT_CTRL, _MIPIC_PORT_CTRL) diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 781c267..f2f8196 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -914,8 +914,8 @@ static void intel_dsi_pre_pll_enable(struct intel_encoder *encoder) DRM_DEBUG_KMS("\n"); intel_dsi_prepare(encoder); + intel_enable_dsi_pll(encoder); - vlv_enable_dsi_pll(encoder); } static enum drm_connector_status diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index 42a6859..7f16c68 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -124,7 +124,7 @@ static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder) return container_of(encoder, struct intel_dsi, base.base); } -extern void vlv_enable_dsi_pll(struct intel_encoder *encoder); +extern void intel_enable_dsi_pll(struct intel_encoder *encoder); extern void vlv_disable_dsi_pll(struct intel_encoder *encoder); extern u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp); diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c index c6a8975..b07483b 100644 --- a/drivers/gpu/drm/i915/intel_dsi_pll.c +++ b/drivers/gpu/drm/i915/intel_dsi_pll.c @@ -246,7 +246,7 @@ static void vlv_configure_dsi_pll(struct intel_encoder *encoder) vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, dsi_mnp.dsi_pll_ctrl); } -void vlv_enable_dsi_pll(struct intel_encoder *encoder) +static void vlv_enable_dsi_pll(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; u32 tmp; @@ -363,3 +363,96 @@ u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp) return pclk; } + +static bool bxt_configure_dsi_pll(struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; + struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); + u8 dsi_ratio; + u32 dsi_clk; + u32 val; + + dsi_clk = dsi_clk_from_pclk(intel_dsi->pclk, intel_dsi->pixel_format, + intel_dsi->lane_count); + + /* + * From clock diagram, to get PLL ratio divider, divide double of DSI + * link rate (i.e., 2*8x=16x frequency value) by ref clock. Make sure to + * round 'up' the result + */ + dsi_ratio = DIV_ROUND_UP(dsi_clk * 2, BXT_REF_CLOCK_KHZ); + if (dsi_ratio < BXT_DSI_PLL_RATIO_MIN || + dsi_ratio > BXT_DSI_PLL_RATIO_MAX) { + DRM_ERROR("Cant get a suitable ratio from DSI PLL ratios\n"); + return false; + } + + /* + * Program DSI ratio and Select MIPIC and MIPIA PLL output as 8x + * Spec says both have to be programmed, even if one is not getting + * used. Configure MIPI_CLOCK_CTL dividers in modeset + */ + val = I915_READ(BXT_DSI_PLL_CTL); + val &= ~BXT_DSI_PLL_PVD_RATIO_MASK; + val &= ~BXT_DSI_FREQ_SEL_MASK; + val &= ~BXT_DSI_PLL_RATIO_MASK; + val |= (dsi_ratio | BXT_DSIA_16X_BY2 | BXT_DSIC_16X_BY2); + + /* As per recommendation from hardware team, + * Prog PVD ratio =1 if dsi ratio <= 50 + */ + if (dsi_ratio <= 50) { + val &= ~BXT_DSI_PLL_PVD_RATIO_MASK; + val |= BXT_DSI_PLL_PVD_RATIO_1; + } + + I915_WRITE(BXT_DSI_PLL_CTL, val); + POSTING_READ(BXT_DSI_PLL_CTL); + + return true; +} + +static void bxt_enable_dsi_pll(struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; + u32 val; + + DRM_DEBUG_KMS("\n"); + + val = I915_READ(BXT_DSI_PLL_ENABLE); + + if (val & BXT_DSI_PLL_DO_ENABLE) { + WARN(1, "DSI PLL already enabled. Disabling it.\n"); + val &= ~BXT_DSI_PLL_DO_ENABLE; + I915_WRITE(BXT_DSI_PLL_ENABLE, val); + } + + /* Configure PLL vales */ + if (!bxt_configure_dsi_pll(encoder)) { + DRM_ERROR("Configure DSI PLL failed, abort PLL enable\n"); + return; + } + + /* Enable DSI PLL */ + val = I915_READ(BXT_DSI_PLL_ENABLE); + val |= BXT_DSI_PLL_DO_ENABLE; + I915_WRITE(BXT_DSI_PLL_ENABLE, val); + + /* Timeout and fail if PLL not locked */ + if (wait_for(I915_READ(BXT_DSI_PLL_ENABLE) & BXT_DSI_PLL_LOCKED, 1)) { + DRM_ERROR("Timed out waiting for DSI PLL to lock\n"); + return; + } + + DRM_DEBUG_KMS("DSI PLL locked\n"); +} + +void intel_enable_dsi_pll(struct intel_encoder *encoder) +{ + struct drm_device *dev = encoder->base.dev; + + if (IS_VALLEYVIEW(dev)) + vlv_enable_dsi_pll(encoder); + else if (IS_BROXTON(dev)) + bxt_enable_dsi_pll(encoder); +} -- cgit v0.10.2 From fe88fc6828f6471c9eebc511aa15984d055d11c1 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Tue, 1 Sep 2015 19:41:39 +0530 Subject: drm/i915/bxt: Disable DSI PLL for BXT This patch adds two new functions: - disable_dsi_pll. BXT DSI disable sequence and registers are different from previous platforms. - intel_disable_dsi_pll wrapper function to re-use the same code for multiple platforms. It checks platform type and calls appropriate core pll disable function. v2: Fixed Jani's review comments. v3: Rebased on latest drm-nightly branch. Signed-off-by: Shashank Sharma Signed-off-by: Uma Shankar Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index f2f8196..50159a9 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -557,7 +557,7 @@ static void intel_dsi_clear_device_ready(struct intel_encoder *encoder) usleep_range(2000, 2500); } - vlv_disable_dsi_pll(encoder); + intel_disable_dsi_pll(encoder); } static void intel_dsi_post_disable(struct intel_encoder *encoder) diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index 7f16c68..5cc46b4 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -125,7 +125,7 @@ static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder) } extern void intel_enable_dsi_pll(struct intel_encoder *encoder); -extern void vlv_disable_dsi_pll(struct intel_encoder *encoder); +extern void intel_disable_dsi_pll(struct intel_encoder *encoder); extern u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp); struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id); diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c index b07483b..f335e6c 100644 --- a/drivers/gpu/drm/i915/intel_dsi_pll.c +++ b/drivers/gpu/drm/i915/intel_dsi_pll.c @@ -276,7 +276,7 @@ static void vlv_enable_dsi_pll(struct intel_encoder *encoder) DRM_DEBUG_KMS("DSI PLL locked\n"); } -void vlv_disable_dsi_pll(struct intel_encoder *encoder) +static void vlv_disable_dsi_pll(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; u32 tmp; @@ -293,6 +293,26 @@ void vlv_disable_dsi_pll(struct intel_encoder *encoder) mutex_unlock(&dev_priv->sb_lock); } +static void bxt_disable_dsi_pll(struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; + u32 val; + + DRM_DEBUG_KMS("\n"); + + val = I915_READ(BXT_DSI_PLL_ENABLE); + val &= ~BXT_DSI_PLL_DO_ENABLE; + I915_WRITE(BXT_DSI_PLL_ENABLE, val); + + /* + * PLL lock should deassert within 200us. + * Wait up to 1ms before timing out. + */ + if (wait_for((I915_READ(BXT_DSI_PLL_ENABLE) + & BXT_DSI_PLL_LOCKED) == 0, 1)) + DRM_ERROR("Timeout waiting for PLL lock deassertion\n"); +} + static void assert_bpp_mismatch(int pixel_format, int pipe_bpp) { int bpp = dsi_pixel_format_bpp(pixel_format); @@ -456,3 +476,13 @@ void intel_enable_dsi_pll(struct intel_encoder *encoder) else if (IS_BROXTON(dev)) bxt_enable_dsi_pll(encoder); } + +void intel_disable_dsi_pll(struct intel_encoder *encoder) +{ + struct drm_device *dev = encoder->base.dev; + + if (IS_VALLEYVIEW(dev)) + vlv_disable_dsi_pll(encoder); + else if (IS_BROXTON(dev)) + bxt_disable_dsi_pll(encoder); +} -- cgit v0.10.2 From d2e08c0f34438af791482de8abf2c8e4e573b1d3 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Tue, 1 Sep 2015 19:41:40 +0530 Subject: drm/i915/bxt: DSI prepare changes for BXT This patch modifies dsi_prepare() function to support the same modeset prepare sequence for BXT also. Main changes are: 1. BXT port control register is different than VLV. 2. BXT modeset sequence needs vdisplay and hdisplay programmed for transcoder. 3. BXT can select PIPE for MIPI transcoders. 4. BXT needs to program register MIPI_INIT_COUNT for both the ports, even if only one is being used. v2: Fixed Jani's review comments. Rectified the DSI Macros to get proper register offsets using _MIPI_PORT instead of _TRANSCODER v3: Rebased on latest drm-nightly branch. Fixed Jani's review comments. Signed-off-by: Shashank Sharma Signed-off-by: Uma Shankar Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 4ef16aa..c5287a1 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7507,6 +7507,22 @@ enum skl_disp_power_wells { #define _MIPI_PORT(port, a, c) _PORT3(port, a, 0, c) /* ports A and C only */ +/* BXT MIPI mode configure */ +#define _BXT_MIPIA_TRANS_HACTIVE 0x6B0F8 +#define _BXT_MIPIC_TRANS_HACTIVE 0x6B8F8 +#define BXT_MIPI_TRANS_HACTIVE(tc) _MIPI_PORT(tc, \ + _BXT_MIPIA_TRANS_HACTIVE, _BXT_MIPIC_TRANS_HACTIVE) + +#define _BXT_MIPIA_TRANS_VACTIVE 0x6B0FC +#define _BXT_MIPIC_TRANS_VACTIVE 0x6B8FC +#define BXT_MIPI_TRANS_VACTIVE(tc) _MIPI_PORT(tc, \ + _BXT_MIPIA_TRANS_VACTIVE, _BXT_MIPIC_TRANS_VACTIVE) + +#define _BXT_MIPIA_TRANS_VTOTAL 0x6B100 +#define _BXT_MIPIC_TRANS_VTOTAL 0x6B900 +#define BXT_MIPI_TRANS_VTOTAL(tc) _MIPI_PORT(tc, \ + _BXT_MIPIA_TRANS_VTOTAL, _BXT_MIPIC_TRANS_VTOTAL) + #define BXT_DSI_PLL_CTL 0x161000 #define BXT_DSI_PLL_PVD_RATIO_SHIFT 16 #define BXT_DSI_PLL_PVD_RATIO_MASK (3 << BXT_DSI_PLL_PVD_RATIO_SHIFT) @@ -7942,6 +7958,11 @@ enum skl_disp_power_wells { #define READ_REQUEST_PRIORITY_HIGH (3 << 3) #define RGB_FLIP_TO_BGR (1 << 2) +#define BXT_PIPE_SELECT_MASK (7 << 7) +#define BXT_PIPE_SELECT_C (2 << 7) +#define BXT_PIPE_SELECT_B (1 << 7) +#define BXT_PIPE_SELECT_A (0 << 7) + #define _MIPIA_DATA_ADDRESS (dev_priv->mipi_mmio_base + 0xb108) #define _MIPIC_DATA_ADDRESS (dev_priv->mipi_mmio_base + 0xb908) #define MIPI_DATA_ADDRESS(port) _MIPI_PORT(port, _MIPIA_DATA_ADDRESS, \ diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 50159a9..5b69b41 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -737,6 +737,21 @@ static void set_dsi_timings(struct drm_encoder *encoder, hbp = txbyteclkhs(hbp, bpp, lane_count, intel_dsi->burst_mode_ratio); for_each_dsi_port(port, intel_dsi->ports) { + if (IS_BROXTON(dev)) { + /* + * Program hdisplay and vdisplay on MIPI transcoder. + * This is different from calculated hactive and + * vactive, as they are calculated per channel basis, + * whereas these values should be based on resolution. + */ + I915_WRITE(BXT_MIPI_TRANS_HACTIVE(port), + mode->hdisplay); + I915_WRITE(BXT_MIPI_TRANS_VACTIVE(port), + mode->vdisplay); + I915_WRITE(BXT_MIPI_TRANS_VTOTAL(port), + mode->vtotal); + } + I915_WRITE(MIPI_HACTIVE_AREA_COUNT(port), hactive); I915_WRITE(MIPI_HFP_COUNT(port), hfp); @@ -777,16 +792,39 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder) } for_each_dsi_port(port, intel_dsi->ports) { - /* escape clock divider, 20MHz, shared for A and C. - * device ready must be off when doing this! txclkesc? */ - tmp = I915_READ(MIPI_CTRL(PORT_A)); - tmp &= ~ESCAPE_CLOCK_DIVIDER_MASK; - I915_WRITE(MIPI_CTRL(PORT_A), tmp | ESCAPE_CLOCK_DIVIDER_1); - - /* read request priority is per pipe */ - tmp = I915_READ(MIPI_CTRL(port)); - tmp &= ~READ_REQUEST_PRIORITY_MASK; - I915_WRITE(MIPI_CTRL(port), tmp | READ_REQUEST_PRIORITY_HIGH); + if (IS_VALLEYVIEW(dev)) { + /* + * escape clock divider, 20MHz, shared for A and C. + * device ready must be off when doing this! txclkesc? + */ + tmp = I915_READ(MIPI_CTRL(PORT_A)); + tmp &= ~ESCAPE_CLOCK_DIVIDER_MASK; + I915_WRITE(MIPI_CTRL(PORT_A), tmp | + ESCAPE_CLOCK_DIVIDER_1); + + /* read request priority is per pipe */ + tmp = I915_READ(MIPI_CTRL(port)); + tmp &= ~READ_REQUEST_PRIORITY_MASK; + I915_WRITE(MIPI_CTRL(port), tmp | + READ_REQUEST_PRIORITY_HIGH); + } else if (IS_BROXTON(dev)) { + /* + * FIXME: + * BXT can connect any PIPE to any MIPI port. + * Select the pipe based on the MIPI port read from + * VBT for now. Pick PIPE A for MIPI port A and C + * for port C. + */ + tmp = I915_READ(MIPI_CTRL(port)); + tmp &= ~BXT_PIPE_SELECT_MASK; + + if (port == PORT_A) + tmp |= BXT_PIPE_SELECT_A; + else if (port == PORT_C) + tmp |= BXT_PIPE_SELECT_C; + + I915_WRITE(MIPI_CTRL(port), tmp); + } /* XXX: why here, why like this? handling in irq handler?! */ I915_WRITE(MIPI_INTR_STAT(port), 0xffffffff); @@ -863,6 +901,17 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder) I915_WRITE(MIPI_INIT_COUNT(port), txclkesc(intel_dsi->escape_clk_div, 100)); + if (IS_BROXTON(dev) && (!intel_dsi->dual_link)) { + /* + * BXT spec says write MIPI_INIT_COUNT for + * both the ports, even if only one is + * getting used. So write the other port + * if not in dual link mode. + */ + I915_WRITE(MIPI_INIT_COUNT(port == + PORT_A ? PORT_C : PORT_A), + intel_dsi->init_count); + } /* recovery disables */ I915_WRITE(MIPI_EOT_DISABLE(port), tmp); -- cgit v0.10.2 From 237ed86c693d8a8e4db476976aeb30df4deac74b Mon Sep 17 00:00:00 2001 From: Sonika Jindal Date: Tue, 15 Sep 2015 09:44:20 +0530 Subject: drm/i915: Check live status before reading edid The Bspec is very clear that Live status must be checked about before trying to read EDID over DDC channel. This patch makes sure that HDMI EDID is read only when live status is up. The live status doesn't seem to perform very consistent across various platforms when tested with different monitors. The reason behind that is some monitors are late to provide right voltage to set live_status up. So, after getting the interrupt, for a small duration, live status reg fluctuates, and then settles down showing the correct staus. This is explained here in, in a rough way: HPD line ________________ |\ T1 = Monitor Hotplug causing IRQ | \______________________________________ | | | | | | T2 = Live status is stable | | _____________________________________ | | /| Live status _____________|_|/ | | | | | | | | | | T0 T1 T2 (Between T1 and T2 Live status fluctuates or can be even low, depending on the monitor) After several experiments, we have concluded that a max delay of 30ms is enough to allow the live status to settle down with most of the monitors. This total delay of 30ms has been split into a resolution of 3 retries of 10ms each, for the better cases. This delay is kept at 30ms, keeping in consideration that, HDCP compliance expect the HPD handler to respond a plug out in 100ms, by disabling port. v2: Adding checks for VLV/CHV as well. Reusing old ibx and g4x functions to check digital port status. Adding a separate function to get bxt live status (Daniel) v3: Using intel_encoder->hpd_pin to check the live status (Siva) Moving the live status read to intel_hdmi_probe and passing parameter to read/not to read the edid. (me) v4: * Added live status check for all platforms using intel_digital_port_connected. * Rebased on top of Jani's DP cleanup series * Some monitors take time in setting the live status. So retry for few times if this is a connect HPD v5: Removed extra "drm/i915" from commit message. Adding Shashank's sob which was missed. v6: Drop the (!detect_edid && !live_status check) check because for DDI ports which are enumerated as hdmi as well as DP, we don't have a mechanism to differentiate between DP and hdmi inside the encoder's hot_plug. This leads to call to the hdmi's hot_plug hook for DP as well as hdmi which leads to issues during unplug because of the above check. v7: Make intel_digital_port_connected global in this patch, some reformatting of while loop, adding a print when live status is not up. (Rodrigo) v8: Rebase it on nightly which involved skipping the hot_plug hook for now and letting the live_status check happen in detect until the hpd handling part is finalized (Daniel) Signed-off-by: Shashank Sharma Signed-off-by: Sonika Jindal Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 9700f77..02401a3 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4672,7 +4672,7 @@ static bool bxt_digital_port_connected(struct drm_i915_private *dev_priv, * * Return %true if @port is connected, %false otherwise. */ -static bool intel_digital_port_connected(struct drm_i915_private *dev_priv, +bool intel_digital_port_connected(struct drm_i915_private *dev_priv, struct intel_digital_port *port) { if (HAS_PCH_IBX(dev_priv)) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8760814..394018e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1218,6 +1218,8 @@ void intel_edp_drrs_disable(struct intel_dp *intel_dp); void intel_edp_drrs_invalidate(struct drm_device *dev, unsigned frontbuffer_bits); void intel_edp_drrs_flush(struct drm_device *dev, unsigned frontbuffer_bits); +bool intel_digital_port_connected(struct drm_i915_private *dev_priv, + struct intel_digital_port *port); void hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config); /* intel_dp_mst.c */ diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index e978c59..bb33c66 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1329,22 +1329,23 @@ intel_hdmi_unset_edid(struct drm_connector *connector) } static bool -intel_hdmi_set_edid(struct drm_connector *connector) +intel_hdmi_set_edid(struct drm_connector *connector, bool force) { struct drm_i915_private *dev_priv = to_i915(connector->dev); struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); struct intel_encoder *intel_encoder = &hdmi_to_dig_port(intel_hdmi)->base; enum intel_display_power_domain power_domain; - struct edid *edid; + struct edid *edid = NULL; bool connected = false; power_domain = intel_display_port_power_domain(intel_encoder); intel_display_power_get(dev_priv, power_domain); - edid = drm_get_edid(connector, - intel_gmbus_get_adapter(dev_priv, - intel_hdmi->ddc_bus)); + if (force) + edid = drm_get_edid(connector, + intel_gmbus_get_adapter(dev_priv, + intel_hdmi->ddc_bus)); intel_display_power_put(dev_priv, power_domain); @@ -1372,13 +1373,26 @@ static enum drm_connector_status intel_hdmi_detect(struct drm_connector *connector, bool force) { enum drm_connector_status status; + struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); + struct drm_i915_private *dev_priv = to_i915(connector->dev); + bool live_status = false; + unsigned int retry = 3; DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, connector->name); + while (!live_status && --retry) { + live_status = intel_digital_port_connected(dev_priv, + hdmi_to_dig_port(intel_hdmi)); + mdelay(10); + } + + if (!live_status) + DRM_DEBUG_KMS("Live status not up!"); + intel_hdmi_unset_edid(connector); - if (intel_hdmi_set_edid(connector)) { + if (intel_hdmi_set_edid(connector, live_status)) { struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI; @@ -1402,7 +1416,7 @@ intel_hdmi_force(struct drm_connector *connector) if (connector->status != connector_status_connected) return; - intel_hdmi_set_edid(connector); + intel_hdmi_set_edid(connector, true); hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI; } -- cgit v0.10.2 From 7f4c62840cc416986f983a8c68f7010c97e06daf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 10 Sep 2015 18:59:07 +0300 Subject: drm/i915: Assign hwmode after encoder state readout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dotclock is often calculated in encoder .get_config(), so we shouldn't copy the adjusted_mode to hwmode until we have read out the dotclock. Gets rid of some warnings like these: [drm:drm_calc_timestamping_constants [drm]] *ERROR* crtc 21: Can't calculate constants, dotclock = 0! [drm:i915_get_vblank_timestamp] crtc 0 is disabled v2: Steal Maarten's idea to move crtc->mode etc. assignment too Cc: Maarten Lankhorst Cc: Patrik Jakobsson Signed-off-by: Ville Syrjälä Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=91428 Reviewed-by: Patrik Jakobsson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a001cbb..ce9bb47 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -15121,33 +15121,6 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) crtc->base.state->active = crtc->active; crtc->base.enabled = crtc->active; - memset(&crtc->base.mode, 0, sizeof(crtc->base.mode)); - if (crtc->base.state->active) { - intel_mode_from_pipe_config(&crtc->base.mode, crtc->config); - intel_mode_from_pipe_config(&crtc->base.state->adjusted_mode, crtc->config); - WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, &crtc->base.mode)); - - /* - * The initial mode needs to be set in order to keep - * the atomic core happy. It wants a valid mode if the - * crtc's enabled, so we do the above call. - * - * At this point some state updated by the connectors - * in their ->detect() callback has not run yet, so - * no recalculation can be done yet. - * - * Even if we could do a recalculation and modeset - * right now it would cause a double modeset if - * fbdev or userspace chooses a different initial mode. - * - * If that happens, someone indicated they wanted a - * mode change, which means it's safe to do a full - * recalculation. - */ - crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED; - } - - crtc->base.hwmode = crtc->config->base.adjusted_mode; readout_plane_state(crtc, to_intel_crtc_state(crtc->base.state)); DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n", @@ -15207,6 +15180,36 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) connector->base.name, connector->base.encoder ? "enabled" : "disabled"); } + + for_each_intel_crtc(dev, crtc) { + crtc->base.hwmode = crtc->config->base.adjusted_mode; + + memset(&crtc->base.mode, 0, sizeof(crtc->base.mode)); + if (crtc->base.state->active) { + intel_mode_from_pipe_config(&crtc->base.mode, crtc->config); + intel_mode_from_pipe_config(&crtc->base.state->adjusted_mode, crtc->config); + WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, &crtc->base.mode)); + + /* + * The initial mode needs to be set in order to keep + * the atomic core happy. It wants a valid mode if the + * crtc's enabled, so we do the above call. + * + * At this point some state updated by the connectors + * in their ->detect() callback has not run yet, so + * no recalculation can be done yet. + * + * Even if we could do a recalculation and modeset + * right now it would cause a double modeset if + * fbdev or userspace chooses a different initial mode. + * + * If that happens, someone indicated they wanted a + * mode change, which means it's safe to do a full + * recalculation. + */ + crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED; + } + } } /* Scan out the current hw modeset state, -- cgit v0.10.2 From f9cd7b881a042dcc8f1b1236ecea6deb3eb4d5bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 10 Sep 2015 18:59:08 +0300 Subject: drm/i915: Move sprite/cursor plane disable to intel_sanitize_crtc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the sprite/cursor plane disabling to occur in intel_sanitize_crtc() where it belongs instead of doing it in intel_modeset_readout_hw_state(). The plane disabling was first added in 4cf0ebbd4fafbdf8e6431dbb315e5511c3efdc3b drm/i915: Rework plane readout. I got the idea from some patches from Partik and/or Maarten but those moved also the plane state readout to intel_sanitize_crtc() which isn't quite right in my opinion. Cc: Maarten Lankhorst Cc: Patrik Jakobsson Signed-off-by: Ville Syrjälä References: https://bugs.freedesktop.org/show_bug.cgi?id=91910 Reviewed-by: Patrik Jakobsson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ce9bb47..5064d8f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14905,9 +14905,19 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) /* restore vblank interrupts to correct state */ drm_crtc_vblank_reset(&crtc->base); if (crtc->active) { + struct intel_plane *plane; + drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode); update_scanline_offset(crtc); drm_crtc_vblank_on(&crtc->base); + + /* Disable everything but the primary plane */ + for_each_intel_plane_on_crtc(dev, crtc, plane) { + if (plane->base.type == DRM_PLANE_TYPE_PRIMARY) + continue; + + plane->disable_plane(&plane->base, &crtc->base); + } } /* We need to sanitize the plane -> pipe mapping first because this will @@ -15070,35 +15080,21 @@ void i915_redisable_vga(struct drm_device *dev) i915_redisable_vga_power_on(dev); } -static bool primary_get_hw_state(struct intel_crtc *crtc) +static bool primary_get_hw_state(struct intel_plane *plane) { - struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - return !!(I915_READ(DSPCNTR(crtc->plane)) & DISPLAY_PLANE_ENABLE); + return I915_READ(DSPCNTR(plane->plane)) & DISPLAY_PLANE_ENABLE; } -static void readout_plane_state(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state) +/* FIXME read out full plane state for all planes */ +static void readout_plane_state(struct intel_crtc *crtc) { - struct intel_plane *p; - struct intel_plane_state *plane_state; - bool active = crtc_state->base.active; + struct intel_plane_state *plane_state = + to_intel_plane_state(crtc->base.primary->state); - for_each_intel_plane(crtc->base.dev, p) { - if (crtc->pipe != p->pipe) - continue; - - plane_state = to_intel_plane_state(p->base.state); - - if (p->base.type == DRM_PLANE_TYPE_PRIMARY) - plane_state->visible = primary_get_hw_state(crtc); - else { - if (active) - p->disable_plane(&p->base, &crtc->base); - - plane_state->visible = false; - } - } + plane_state->visible = + primary_get_hw_state(to_intel_plane(crtc->base.primary)); } static void intel_modeset_readout_hw_state(struct drm_device *dev) @@ -15121,7 +15117,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) crtc->base.state->active = crtc->active; crtc->base.enabled = crtc->active; - readout_plane_state(crtc, to_intel_crtc_state(crtc->base.state)); + readout_plane_state(crtc); DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n", crtc->base.base.id, -- cgit v0.10.2 From 9eca6832f7254d49d25494da7d47c0f8a24f7862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 10 Sep 2015 18:59:10 +0300 Subject: drm/i915: Move scanline_offset and timestamping constant setup to intel_modeset_readout_hw_state() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_modeset_readout_hw_state() seems like the more appropriate place for populating the scanline_offset and timestamping constants than intel_sanitize_crtc() since they are basically part of the state we read out. Cc: Maarten Lankhorst Cc: Patrik Jakobsson Signed-off-by: Ville Syrjälä Reviewed-by: Maarten Lankhorst Reviewed-by: Patrik Jakobsson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5064d8f..8db2b13 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14907,8 +14907,6 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) if (crtc->active) { struct intel_plane *plane; - drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode); - update_scanline_offset(crtc); drm_crtc_vblank_on(&crtc->base); /* Disable everything but the primary plane */ @@ -15204,6 +15202,9 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) * recalculation. */ crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED; + + drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode); + update_scanline_offset(crtc); } } } -- cgit v0.10.2 From 3a5a0393ab5de28f8dad100bf604e4ab55550836 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 15 Sep 2015 10:03:01 -0700 Subject: drm/i915: fix crash in error state readout on non-execlist platforms v2 Looks like this was introduced in: commit d1675198ed1f21aec6e036336e4340c40b726497 Author: Alex Dai Date: Wed Aug 12 15:43:43 2015 +0100 drm/i915: Integrate GuC-based command submission This patch assumed LRC contexts and HWS layout, which is incorrect on platforms without execlists. This can lead to a crash in GPU error state readout on those platforms. I don't see a bug filed for this, but there may be one that I haven't found. v2: fixup offset handling for error capture fix (Dave) Cc: Alex Dai Reviewed-by: Dave Gordon Signed-off-by: Jesse Barnes Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 3379f9c..f95de05 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -457,17 +457,23 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, } if ((obj = error->ring[i].hws_page)) { + u64 hws_offset = obj->gtt_offset; + u32 *hws_page = &obj->pages[0][0]; + + if (i915.enable_execlists) { + hws_offset += LRC_PPHWSP_PN * PAGE_SIZE; + hws_page = &obj->pages[LRC_PPHWSP_PN][0]; + } err_printf(m, "%s --- HW Status = 0x%08llx\n", - dev_priv->ring[i].name, - obj->gtt_offset + LRC_PPHWSP_PN * PAGE_SIZE); + dev_priv->ring[i].name, hws_offset); offset = 0; for (elt = 0; elt < PAGE_SIZE/16; elt += 4) { err_printf(m, "[%04x] %08x %08x %08x %08x\n", offset, - obj->pages[LRC_PPHWSP_PN][elt], - obj->pages[LRC_PPHWSP_PN][elt+1], - obj->pages[LRC_PPHWSP_PN][elt+2], - obj->pages[LRC_PPHWSP_PN][elt+3]); + hws_page[elt], + hws_page[elt+1], + hws_page[elt+2], + hws_page[elt+3]); offset += 16; } } -- cgit v0.10.2 From 7a58bad0e63295dfa803973efcebc80cb730c7bd Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Sat, 12 Sep 2015 10:17:50 +0530 Subject: drm/i915: Add IS_SKL_GT3 and IS_SKL_GT4 macro. It will be usefull to specify w/a that affects only SKL GT3 and GT4. Signed-off-by: Sagar Arun Kamble Reviewed-by: Alex Dai Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3795fdf..7cbc81f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2488,6 +2488,11 @@ struct drm_i915_cmd_table { #define IS_SKL_ULX(dev) (INTEL_DEVID(dev) == 0x190E || \ INTEL_DEVID(dev) == 0x1915 || \ INTEL_DEVID(dev) == 0x191E) +#define IS_SKL_GT3(dev) (IS_SKYLAKE(dev) && \ + (INTEL_DEVID(dev) & 0x00F0) == 0x0020) +#define IS_SKL_GT4(dev) (IS_SKYLAKE(dev) && \ + (INTEL_DEVID(dev) & 0x00F0) == 0x0030) + #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary) #define SKL_REVID_A0 (0x0) -- cgit v0.10.2 From f2d2fe95072acd5404f8051b8bf1195c61a47fb5 Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Sat, 12 Sep 2015 10:17:51 +0530 Subject: drm/i915: WaRsDisableCoarsePowerGating WaRsDisableCoarsePowerGating: Coarse Power Gating (CPG) needs to be disabled for platforms prior to BXT B0 and SKL GT3/GT4 till E0. v2: Added GT3/GT4 Check. Change-Id: Ia3c4c16e050c88d3e259f601054875c812d69c3a Signed-off-by: Sagar Arun Kamble Reviewed-by: Alex Dai [danvet: Align continuation properly.] Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f52431b..09be8fc 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4877,11 +4877,14 @@ static void gen9_enable_rc6(struct drm_device *dev) /* * 3b: Enable Coarse Power Gating only when RC6 is enabled. - * WaDisableRenderPowerGating:skl,bxt - Render PG need to be disabled with RC6. + * WaRsDisableCoarsePowerGating:skl,bxt - Render/Media PG need to be disabled with RC6. */ - I915_WRITE(GEN9_PG_ENABLE, (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? - GEN9_MEDIA_PG_ENABLE : 0); - + if ((IS_BROXTON(dev) && (INTEL_REVID(dev) < BXT_REVID_B0)) || + ((IS_SKL_GT3(dev) || IS_SKL_GT4(dev)) && (INTEL_REVID(dev) <= SKL_REVID_E0))) + I915_WRITE(GEN9_PG_ENABLE, 0); + else + I915_WRITE(GEN9_PG_ENABLE, (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? + (GEN9_RENDER_PG_ENABLE | GEN9_MEDIA_PG_ENABLE) : 0); intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); -- cgit v0.10.2 From ed1098e4738d935cef12833b08916f6f5e700652 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 14 Sep 2015 14:42:09 -0300 Subject: ARM: imx_v6_v7_defconfig: Remove CONFIG_VMSPLIT_2G CONFIG_VMSPLIT_2G was added to mx5_defconfig by commit 06965c39b4c639 ("ARM i.MX5: update defconfig") to fix an issue where mx53 was not detecting the full 1GiB memory range. However, as explained by Russell King [1] the correct fix is to select CONFIG_HIGHMEM. imx_v6_v7_deconfig inherited such option from mx5_defconfig. As imx_v6_v7_deconfig has CONFIG_HIGHMEM=y, we should no longer select such non-standard CONFIG_VMSPLIT_2G option. [1] http://www.spinics.net/lists/arm-kernel/msg137839.html Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 61d4e02..4187f69 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -47,7 +47,6 @@ CONFIG_SOC_VF610=y CONFIG_PCI=y CONFIG_PCI_IMX6=y CONFIG_SMP=y -CONFIG_VMSPLIT_2G=y CONFIG_PREEMPT_VOLUNTARY=y CONFIG_AEABI=y CONFIG_HIGHMEM=y -- cgit v0.10.2 From e3429cd240b06c79df3ea90f28065a7e011744cd Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Sat, 12 Sep 2015 10:17:52 +0530 Subject: drm/i915: WaRsUseTimeoutMode Enable TO mode for RC6 for SKL till D0 and BXT till A0. Cc: Tom O'Rourke Cc: Akash Goel Signed-off-by: Sagar Arun Kamble Reviewed-by: Alex Dai [danvet: Fixup line continuation alignment.] Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 09be8fc..b4e0d15 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4871,9 +4871,16 @@ static void gen9_enable_rc6(struct drm_device *dev) rc6_mask = GEN6_RC_CTL_RC6_ENABLE; DRM_INFO("RC6 %s\n", (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off"); - I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE | - GEN6_RC_CTL_EI_MODE(1) | - rc6_mask); + + if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_D0) || + (IS_BROXTON(dev) && INTEL_REVID(dev) <= BXT_REVID_A0)) + I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE | + GEN7_RC_CTL_TO_MODE | + rc6_mask); + else + I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE | + GEN6_RC_CTL_EI_MODE(1) | + rc6_mask); /* * 3b: Enable Coarse Power Gating only when RC6 is enabled. -- cgit v0.10.2 From 63a4dec2c168b74a39df1eac494501f0f6bf3708 Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Sat, 12 Sep 2015 10:17:53 +0530 Subject: drm/i915: WaRsDoubleRc6WrlWithCoarsePowerGating Cc: Tom O'Rourke Cc: Akash Goel Signed-off-by: Sagar Arun Kamble Reviewed-by: Alex Dai [danvet: Fix continuation alignment.] Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b4e0d15..61162b2 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4854,7 +4854,13 @@ static void gen9_enable_rc6(struct drm_device *dev) I915_WRITE(GEN6_RC_CONTROL, 0); /* 2b: Program RC6 thresholds.*/ - I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16); + + /* WaRsDoubleRc6WrlWithCoarsePowerGating: Doubling WRL only when CPG is enabled */ + if (IS_SKYLAKE(dev) && !((IS_SKL_GT3(dev) || IS_SKL_GT4(dev)) && + (INTEL_REVID(dev) <= SKL_REVID_E0))) + I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 108 << 16); + else + I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16); I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ for_each_ring(ring, dev_priv, unused) -- cgit v0.10.2 From 97c322e713b92b5071ad276f65cabf8a503a7408 Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Sat, 12 Sep 2015 10:17:54 +0530 Subject: drm/i915: Program GuC MAX IDLE Count Cc: Alex Dai Cc: Tom O'Rourke Cc: Akash Goel Signed-off-by: Sagar Arun Kamble Reviewed-by: Alex Dai Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_guc_reg.h b/drivers/gpu/drm/i915/i915_guc_reg.h index 8c8e574..9d79a6b 100644 --- a/drivers/gpu/drm/i915/i915_guc_reg.h +++ b/drivers/gpu/drm/i915/i915_guc_reg.h @@ -53,6 +53,7 @@ #define START_DMA (1<<0) #define DMA_GUC_WOPCM_OFFSET 0xc340 #define GUC_WOPCM_OFFSET_VALUE 0x80000 /* 512KB */ +#define GUC_MAX_IDLE_COUNT 0xC3E4 #define GUC_WOPCM_SIZE 0xc050 #define GUC_WOPCM_SIZE_VALUE (0x80 << 12) /* 512KB */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 61162b2..566f5cd 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4865,6 +4865,10 @@ static void gen9_enable_rc6(struct drm_device *dev) I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ for_each_ring(ring, dev_priv, unused) I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10); + + if (HAS_GUC_UCODE(dev)) + I915_WRITE(GUC_MAX_IDLE_COUNT, 0xA); + I915_WRITE(GEN6_RC_SLEEP, 0); I915_WRITE(GEN6_RC6_THRESHOLD, 37500); /* 37.5/125ms per EI */ -- cgit v0.10.2 From 7aefe2b50a0be5c85e7702bff110e5e187fbe4b5 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 14 Sep 2015 11:30:10 +0200 Subject: drm/i915: Fix fastboot scalers for skylake. The scaler_id in intel_pipe_config_compare should not be checked when adjusting in intel_pipe_config_compare. The hw scaler id may be changed in intel_update_pipe_config. Signed-off-by: Maarten Lankhorst Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8db2b13..6d718c0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12459,9 +12459,9 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_X(pch_pfit.pos); PIPE_CONF_CHECK_X(pch_pfit.size); } - } - PIPE_CONF_CHECK_I(scaler_state.scaler_id); + PIPE_CONF_CHECK_I(scaler_state.scaler_id); + } /* BDW+ don't expose a synchronous way to read the state */ if (IS_HASWELL(dev)) -- cgit v0.10.2 From e8cb8d69d125f56fa3ba5239b215a56718e2ca44 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 14 Sep 2015 15:19:55 -0300 Subject: drm/i915: fix the FBC work allocation failure path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Always update the currrent crtc, fb and vertical offset after calling enable_fbc. We were forgetting to do so along the failure paths when enabling fbc synchronously. Fix this with a new helper to enable_fbc() and update the state simultaneously. v2: Improve commit message (Chris). v3: Constify struct drm_framebuffer (Ville). Reviewed-by: Ville Syrjälä Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 1f97fb5..9e42079 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -308,6 +308,18 @@ bool intel_fbc_enabled(struct drm_i915_private *dev_priv) return dev_priv->fbc.enabled; } +static void intel_fbc_enable(struct intel_crtc *crtc, + const struct drm_framebuffer *fb) +{ + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + + dev_priv->fbc.enable_fbc(crtc); + + dev_priv->fbc.crtc = crtc; + dev_priv->fbc.fb_id = fb->base.id; + dev_priv->fbc.y = crtc->base.y; +} + static void intel_fbc_work_fn(struct work_struct *__work) { struct intel_fbc_work *work = @@ -321,13 +333,8 @@ static void intel_fbc_work_fn(struct work_struct *__work) /* Double check that we haven't switched fb without cancelling * the prior work. */ - if (crtc_fb == work->fb) { - dev_priv->fbc.enable_fbc(work->crtc); - - dev_priv->fbc.crtc = work->crtc; - dev_priv->fbc.fb_id = crtc_fb->base.id; - dev_priv->fbc.y = work->crtc->base.y; - } + if (crtc_fb == work->fb) + intel_fbc_enable(work->crtc, work->fb); dev_priv->fbc.fbc_work = NULL; } @@ -361,7 +368,7 @@ static void intel_fbc_cancel_work(struct drm_i915_private *dev_priv) dev_priv->fbc.fbc_work = NULL; } -static void intel_fbc_enable(struct intel_crtc *crtc) +static void intel_fbc_schedule_enable(struct intel_crtc *crtc) { struct intel_fbc_work *work; struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; @@ -373,7 +380,7 @@ static void intel_fbc_enable(struct intel_crtc *crtc) work = kzalloc(sizeof(*work), GFP_KERNEL); if (work == NULL) { DRM_ERROR("Failed to allocate FBC work structure\n"); - dev_priv->fbc.enable_fbc(crtc); + intel_fbc_enable(crtc, crtc->base.primary->fb); return; } @@ -824,7 +831,7 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv) __intel_fbc_disable(dev_priv); } - intel_fbc_enable(intel_crtc); + intel_fbc_schedule_enable(intel_crtc); dev_priv->fbc.no_fbc_reason = FBC_OK; return; -- cgit v0.10.2 From adf70c65cff66d843d66469dbe13ef1ed21e062b Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 14 Sep 2015 15:19:56 -0300 Subject: drm/i915: check for the supported strides on HSW+ FBC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't allow FBC for cases where the spec says we can't FBC. v2: - Just WARN_ON() the strides that should have been caught earlier (Daniel) - Make it a new function since I expect this to grow more. v3: - Document which IGT test is exercised by this. v4: - Implement the restrictions for gens 2-6 too (Ville). - Fix off-by-one mistake (Ville). Testcase: igt/kms_frontbuffer_tracking/fbc-badstride Signed-off-by: Paulo Zanoni Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7cbc81f..d4240db 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -948,6 +948,7 @@ struct i915_fbc { FBC_CHIP_DEFAULT, /* disabled by default on this chip */ FBC_ROTATION, /* rotation is not supported */ FBC_IN_DBG_MASTER, /* kernel debugger is active */ + FBC_BAD_STRIDE, /* stride is not supported */ } no_fbc_reason; bool (*fbc_enabled)(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 9e42079..db38091 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -480,6 +480,8 @@ const char *intel_no_fbc_reason_str(enum no_fbc_reason reason) return "rotation unsupported"; case FBC_IN_DBG_MASTER: return "Kernel debugger is active"; + case FBC_BAD_STRIDE: + return "framebuffer stride not supported"; default: MISSING_CASE(reason); return "unknown reason"; @@ -671,6 +673,27 @@ static int intel_fbc_setup_cfb(struct drm_i915_private *dev_priv, int size, return intel_fbc_alloc_cfb(dev_priv, size, fb_cpp); } +static bool stride_is_valid(struct drm_i915_private *dev_priv, + unsigned int stride) +{ + /* These should have been caught earlier. */ + WARN_ON(stride < 512); + WARN_ON((stride & (64 - 1)) != 0); + + /* Below are the additional FBC restrictions. */ + + if (IS_GEN2(dev_priv) || IS_GEN3(dev_priv)) + return stride == 4096 || stride == 8192; + + if (IS_GEN4(dev_priv) && !IS_G4X(dev_priv) && stride < 2048) + return false; + + if (stride > 16384) + return false; + + return true; +} + /** * __intel_fbc_update - enable/disable FBC as needed, unlocked * @dev_priv: i915 device instance @@ -781,6 +804,11 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv) goto out_disable; } + if (!stride_is_valid(dev_priv, fb->pitches[0])) { + set_no_fbc_reason(dev_priv, FBC_BAD_STRIDE); + goto out_disable; + } + /* If the kernel debugger is active, always disable compression */ if (in_dbg_master()) { set_no_fbc_reason(dev_priv, FBC_IN_DBG_MASTER); -- cgit v0.10.2 From a9da512b3ed73045253afd778e40d4298f42905b Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 14 Sep 2015 15:19:57 -0300 Subject: drm/i915: avoid the last 8mb of stolen on BDW/SKL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The FBC hardware for these platforms doesn't have access to the bios_reserved range, so it always assumes the maximum (8mb) is used. So avoid this range while allocating. This solves a bunch of FIFO underruns that happen if you end up putting the CFB in that memory range. On my machine, with 32mb of stolen, I need a 2560x1440 mode for that. Testcase: igt/kms_frontbuffer_tracking/fbc-* (given the right setup) Signed-off-by: Paulo Zanoni Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d4240db..ffd4ab1 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3175,6 +3175,10 @@ static inline void i915_gem_chipset_flush(struct drm_device *dev) int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv, struct drm_mm_node *node, u64 size, unsigned alignment); +int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *dev_priv, + struct drm_mm_node *node, u64 size, + unsigned alignment, u64 start, + u64 end); void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv, struct drm_mm_node *node); int i915_gem_init_stolen(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 8275007..96ebb98 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -341,6 +341,7 @@ struct i915_gtt { struct i915_address_space base; size_t stolen_size; /* Total size of stolen memory */ + size_t stolen_usable_size; /* Total size minus BIOS reserved */ u64 mappable_end; /* End offset that we can CPU map */ struct io_mapping *mappable; /* Mapping to our CPU mappable region */ phys_addr_t mappable_base; /* PA of our GMADR */ diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index bf26ecc..081ef6d 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -42,9 +42,9 @@ * for is a boon. */ -int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv, - struct drm_mm_node *node, u64 size, - unsigned alignment) +int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *dev_priv, + struct drm_mm_node *node, u64 size, + unsigned alignment, u64 start, u64 end) { int ret; @@ -52,13 +52,23 @@ int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv, return -ENODEV; mutex_lock(&dev_priv->mm.stolen_lock); - ret = drm_mm_insert_node(&dev_priv->mm.stolen, node, size, alignment, - DRM_MM_SEARCH_DEFAULT); + ret = drm_mm_insert_node_in_range(&dev_priv->mm.stolen, node, size, + alignment, start, end, + DRM_MM_SEARCH_DEFAULT); mutex_unlock(&dev_priv->mm.stolen_lock); return ret; } +int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv, + struct drm_mm_node *node, u64 size, + unsigned alignment) +{ + return i915_gem_stolen_insert_node_in_range(dev_priv, node, size, + alignment, 0, + dev_priv->gtt.stolen_usable_size); +} + void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv, struct drm_mm_node *node) { @@ -355,9 +365,11 @@ int i915_gem_init_stolen(struct drm_device *dev) dev_priv->gtt.stolen_size >> 10, (dev_priv->gtt.stolen_size - reserved_total) >> 10); + dev_priv->gtt.stolen_usable_size = dev_priv->gtt.stolen_size - + reserved_total; + /* Basic memrange allocator for stolen space */ - drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_size - - reserved_total); + drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_usable_size); return 0; } diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index db38091..6f3c2ea 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -551,6 +551,16 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv, { int compression_threshold = 1; int ret; + u64 end; + + /* The FBC hardware for BDW/SKL doesn't have access to the stolen + * reserved range size, so it always assumes the maximum (8mb) is used. + * If we enable FBC using a CFB on that memory range we'll get FIFO + * underruns, even if that range is not reserved by the BIOS. */ + if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv)) + end = dev_priv->gtt.stolen_size - 8 * 1024 * 1024; + else + end = dev_priv->gtt.stolen_usable_size; /* HACK: This code depends on what we will do in *_enable_fbc. If that * code changes, this code needs to change as well. @@ -560,7 +570,8 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv, */ /* Try to over-allocate to reduce reallocations and fragmentation. */ - ret = i915_gem_stolen_insert_node(dev_priv, node, size <<= 1, 4096); + ret = i915_gem_stolen_insert_node_in_range(dev_priv, node, size <<= 1, + 4096, 0, end); if (ret == 0) return compression_threshold; @@ -570,7 +581,8 @@ again: (fb_cpp == 2 && compression_threshold == 2)) return 0; - ret = i915_gem_stolen_insert_node(dev_priv, node, size >>= 1, 4096); + ret = i915_gem_stolen_insert_node_in_range(dev_priv, node, size >>= 1, + 4096, 0, end); if (ret && INTEL_INFO(dev_priv)->gen <= 4) { return 0; } else if (ret) { -- cgit v0.10.2 From b8bf5d7fe0dee64ed0a73fa1e95ba8e464d605da Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 14 Sep 2015 15:19:58 -0300 Subject: drm/i915: print the correct amount of bytes allocated for the CFB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And also print the threshold. I was surprised to see a log message claiming the CFB size was 32mb when there was less than 24mb available for it. Reviewed-by: Ville Syrjälä Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 6f3c2ea..69726a7 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -634,8 +634,9 @@ static int intel_fbc_alloc_cfb(struct drm_i915_private *dev_priv, int size, dev_priv->fbc.uncompressed_size = size; - DRM_DEBUG_KMS("reserved %d bytes of contiguous stolen space for FBC\n", - size); + DRM_DEBUG_KMS("reserved %llu bytes of contiguous stolen space for FBC, threshold: %d\n", + dev_priv->fbc.compressed_fb.size, + dev_priv->fbc.threshold); return 0; -- cgit v0.10.2 From 7b24c9a696c1c68eaa471a27bf467e97a9986fa9 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 14 Sep 2015 15:19:59 -0300 Subject: drm/i915: don't enable FBC when pixel rate exceeds 95% on HSW/BDW MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BSpec says we shouldn't enable FBC on HSW/BDW when the pipe pixel rate exceeds 95% of the core display clock. v2: - HSW also needs the WA (Ville). - Add the WA name (Ville). - Use the current cdclk (Ville). Signed-off-by: Paulo Zanoni Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ffd4ab1..e5242c0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -949,6 +949,7 @@ struct i915_fbc { FBC_ROTATION, /* rotation is not supported */ FBC_IN_DBG_MASTER, /* kernel debugger is active */ FBC_BAD_STRIDE, /* stride is not supported */ + FBC_PIXEL_RATE, /* pixel rate is too big */ } no_fbc_reason; bool (*fbc_enabled)(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 69726a7..1c4536a 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -482,6 +482,8 @@ const char *intel_no_fbc_reason_str(enum no_fbc_reason reason) return "Kernel debugger is active"; case FBC_BAD_STRIDE: return "framebuffer stride not supported"; + case FBC_PIXEL_RATE: + return "pixel rate is too big"; default: MISSING_CASE(reason); return "unknown reason"; @@ -828,6 +830,14 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv) goto out_disable; } + /* WaFbcExceedCdClockThreshold:hsw,bdw */ + if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) && + ilk_pipe_pixel_rate(intel_crtc->config) >= + dev_priv->cdclk_freq * 95 / 100) { + set_no_fbc_reason(dev_priv, FBC_PIXEL_RATE); + goto out_disable; + } + if (intel_fbc_setup_cfb(dev_priv, obj->base.size, drm_format_plane_cpp(fb->pixel_format, 0))) { set_no_fbc_reason(dev_priv, FBC_STOLEN_TOO_SMALL); -- cgit v0.10.2 From 57012be9289b4f6d12b05878411d903982ec2a4e Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 14 Sep 2015 15:20:00 -0300 Subject: drm/i915: apply WaFbcAsynchFlipDisableFbcQueue earlier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The spec says the register should have that value for the entire time that FBC is enabled, so apply the WA before we enable FBC. Notice that we also have this WA for ILK/SNB, but it is implemented at init_clock_gating(). I could move the IVB/HSW/BDW WA code to init_clock_gating() too, but since we recently had some complaints about WAs not staying after being set, I'm going to play safe and keep this here for now. Reviewed-by: Ville Syrjälä Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 1c4536a..2b75003 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -272,8 +272,6 @@ static void gen7_fbc_enable(struct intel_crtc *crtc) if (dev_priv->fbc.false_color) dpfc_ctl |= FBC_CTL_FALSE_COLOR; - I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); - if (IS_IVYBRIDGE(dev_priv)) { /* WaFbcAsynchFlipDisableFbcQueue:ivb */ I915_WRITE(ILK_DISPLAY_CHICKEN1, @@ -286,6 +284,8 @@ static void gen7_fbc_enable(struct intel_crtc *crtc) HSW_FBCQ_DIS); } + I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); + I915_WRITE(SNB_DPFC_CTL_SA, SNB_CPU_FENCE_ENABLE | obj->fence_reg); I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->base.y); -- cgit v0.10.2 From 40f4022ef67f30cc0b7ee7453926d1803277d1af Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 14 Sep 2015 15:20:01 -0300 Subject: drm/i915: don't apply WaFbcAsynchFlipDisableFbcQueue on SKL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This WA is only for HSW/BDW. Reviewed-by: Ville Syrjälä Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 2b75003..56cf110 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -277,7 +277,7 @@ static void gen7_fbc_enable(struct intel_crtc *crtc) I915_WRITE(ILK_DISPLAY_CHICKEN1, I915_READ(ILK_DISPLAY_CHICKEN1) | ILK_FBCQ_DIS); - } else { + } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { /* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */ I915_WRITE(CHICKEN_PIPESL_1(crtc->pipe), I915_READ(CHICKEN_PIPESL_1(crtc->pipe)) | -- cgit v0.10.2 From b9e831dc3973bddfaa8e27629745c5948ed8b92d Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 21 Sep 2015 19:48:06 -0300 Subject: drm/i915: reject invalid formats for FBC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit is essentially a rewrite of "drm/i915: Check pixel format for fbc" from Ville Syrjälä. The idea is the same, but the code is different due to all the changes that happened since his original patch. So any bugs are due to my bad rewrite. v2: - Drop the alpha formats (Ville). v3: - Drop the stale comment (Ville). Testcases: igt/kms_frontbuffer_tracking/*fbc*-${format_name}-draw-* Credits-to: Ville Syrjälä Reviewed-by: Ville Syrjälä Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e5242c0..3044cbe 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -950,6 +950,7 @@ struct i915_fbc { FBC_IN_DBG_MASTER, /* kernel debugger is active */ FBC_BAD_STRIDE, /* stride is not supported */ FBC_PIXEL_RATE, /* pixel rate is too big */ + FBC_PIXEL_FORMAT /* pixel format is invalid */ } no_fbc_reason; bool (*fbc_enabled)(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 56cf110..9d2f56e 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -484,6 +484,8 @@ const char *intel_no_fbc_reason_str(enum no_fbc_reason reason) return "framebuffer stride not supported"; case FBC_PIXEL_RATE: return "pixel rate is too big"; + case FBC_PIXEL_FORMAT: + return "pixel format is invalid"; default: MISSING_CASE(reason); return "unknown reason"; @@ -709,6 +711,29 @@ static bool stride_is_valid(struct drm_i915_private *dev_priv, return true; } +static bool pixel_format_is_valid(struct drm_framebuffer *fb) +{ + struct drm_device *dev = fb->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + switch (fb->pixel_format) { + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_XBGR8888: + return true; + case DRM_FORMAT_XRGB1555: + case DRM_FORMAT_RGB565: + /* 16bpp not supported on gen2 */ + if (IS_GEN2(dev)) + return false; + /* WaFbcOnly1to1Ratio:ctg */ + if (IS_G4X(dev_priv)) + return false; + return true; + default: + return false; + } +} + /** * __intel_fbc_update - enable/disable FBC as needed, unlocked * @dev_priv: i915 device instance @@ -824,6 +849,11 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv) goto out_disable; } + if (!pixel_format_is_valid(fb)) { + set_no_fbc_reason(dev_priv, FBC_PIXEL_FORMAT); + goto out_disable; + } + /* If the kernel debugger is active, always disable compression */ if (in_dbg_master()) { set_no_fbc_reason(dev_priv, FBC_IN_DBG_MASTER); -- cgit v0.10.2 From 2db3366b18e6ee5c6cb09b5f3902bcacfa3d534e Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 14 Sep 2015 15:20:03 -0300 Subject: drm/i915: fix FBC for cases where crtc->base.y is non-zero MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I only tested this on BDW and SKL, but since the register description is the same ever since gen4, let's assume that all gens take the same register format. If that's not true, then hopefully someone will bisect a bug to this patch and we'll fix it. Notice that the wrong fence offset register just means that the hardware tracking will be wrong. Testcases: - igt/kms_frontbuffer_tracking/fbc-1p-primscrn-pri-shrfb-draw-mmap-gtt - igt/kms_frontbuffer_tracking/fbc-2p-primscrn-pri-shrfb-draw-mmap-gtt v2: - Add intel_crtc->adjusted_{x,y} so this code can work independently of intel_gen4_compute_page_offset(). (Ville). - This version also works on SKL. Signed-off-by: Paulo Zanoni Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 6d718c0..bf8754f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2730,6 +2730,9 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc, (intel_crtc->config->pipe_src_w - 1) * pixel_size; } + intel_crtc->adjusted_x = x; + intel_crtc->adjusted_y = y; + I915_WRITE(reg, dspcntr); I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); @@ -2830,6 +2833,9 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc, } } + intel_crtc->adjusted_x = x; + intel_crtc->adjusted_y = y; + I915_WRITE(reg, dspcntr); I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); @@ -3082,6 +3088,9 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc, } plane_offset = y_offset << 16 | x_offset; + intel_crtc->adjusted_x = x_offset; + intel_crtc->adjusted_y = y_offset; + I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl); I915_WRITE(PLANE_OFFSET(pipe, 0), plane_offset); I915_WRITE(PLANE_SIZE(pipe, 0), plane_size); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 394018e..ab3c296 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -537,6 +537,8 @@ struct intel_crtc { * gen4+ this only adjusts up to a tile, offsets within a tile are * handled in the hw itself (with the TILEOFF register). */ unsigned long dspaddr_offset; + int adjusted_x; + int adjusted_y; struct drm_i915_gem_object *cursor_bo; uint32_t cursor_addr; diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 9d2f56e..d38f464 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -41,6 +41,19 @@ #include "intel_drv.h" #include "i915_drv.h" +/* + * In some platforms where the CRTC's x:0/y:0 coordinates doesn't match the + * frontbuffer's x:0/y:0 coordinates we lie to the hardware about the plane's + * origin so the x and y offsets can actually fit the registers. As a + * consequence, the fence doesn't really start exactly at the display plane + * address we program because it starts at the real start of the buffer, so we + * have to take this into consideration here. + */ +static unsigned int get_crtc_fence_y_offset(struct intel_crtc *crtc) +{ + return crtc->base.y - crtc->adjusted_y; +} + static void i8xx_fbc_disable(struct drm_i915_private *dev_priv) { u32 fbc_ctl; @@ -97,7 +110,7 @@ static void i8xx_fbc_enable(struct intel_crtc *crtc) fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE; fbc_ctl2 |= FBC_CTL_PLANE(crtc->plane); I915_WRITE(FBC_CONTROL2, fbc_ctl2); - I915_WRITE(FBC_FENCE_OFF, crtc->base.y); + I915_WRITE(FBC_FENCE_OFF, get_crtc_fence_y_offset(crtc)); } /* enable it... */ @@ -135,7 +148,7 @@ static void g4x_fbc_enable(struct intel_crtc *crtc) dpfc_ctl |= DPFC_CTL_LIMIT_1X; dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg; - I915_WRITE(DPFC_FENCE_YOFF, crtc->base.y); + I915_WRITE(DPFC_FENCE_YOFF, get_crtc_fence_y_offset(crtc)); /* enable it... */ I915_WRITE(DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); @@ -177,6 +190,7 @@ static void ilk_fbc_enable(struct intel_crtc *crtc) struct drm_i915_gem_object *obj = intel_fb_obj(fb); u32 dpfc_ctl; int threshold = dev_priv->fbc.threshold; + unsigned int y_offset; dev_priv->fbc.enabled = true; @@ -200,7 +214,8 @@ static void ilk_fbc_enable(struct intel_crtc *crtc) if (IS_GEN5(dev_priv)) dpfc_ctl |= obj->fence_reg; - I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->base.y); + y_offset = get_crtc_fence_y_offset(crtc); + I915_WRITE(ILK_DPFC_FENCE_YOFF, y_offset); I915_WRITE(ILK_FBC_RT_BASE, i915_gem_obj_ggtt_offset(obj) | ILK_FBC_RT_VALID); /* enable it... */ I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); @@ -208,7 +223,7 @@ static void ilk_fbc_enable(struct intel_crtc *crtc) if (IS_GEN6(dev_priv)) { I915_WRITE(SNB_DPFC_CTL_SA, SNB_CPU_FENCE_ENABLE | obj->fence_reg); - I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->base.y); + I915_WRITE(DPFC_CPU_FENCE_OFFSET, y_offset); } intel_fbc_nuke(dev_priv); @@ -288,7 +303,7 @@ static void gen7_fbc_enable(struct intel_crtc *crtc) I915_WRITE(SNB_DPFC_CTL_SA, SNB_CPU_FENCE_ENABLE | obj->fence_reg); - I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->base.y); + I915_WRITE(DPFC_CPU_FENCE_OFFSET, get_crtc_fence_y_offset(crtc)); intel_fbc_nuke(dev_priv); -- cgit v0.10.2 From 7d316aecf883a19c9883e4dcbc058806fd25b152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 16 Sep 2015 21:28:50 +0300 Subject: drm/i915: Implement stolen reserved detection for ctg/elk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Finally managed to dig up enough hints as to where the stolen reserved stuff lives on ctg/elk. So add the code to decode it. This was a combination of old chipset specs, diggin up an old elk grits release with an ctg/elk AubLoad etc. This was only tested on an elk as I don't have a ctg here unfortunately. This leaves ilk as the only platform that doesn't have a way to detect this stuff. Looking at the register contents on my ilk, it might be that the elk way works there too, but I can't be sure since I can't affect the amount of reserved memory on that machine, and if I am to trust the register contents, by default it would reserve 0 bytes. v2: s/WARN_ON_ONCE/WARN_ON/ since it's in one time init code anyway (Paulo) Cc: Paulo Zanoni Cc: Chris Wilson Acked-by: Paulo Zanoni Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 081ef6d..55df6ce 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -196,6 +196,29 @@ void i915_gem_cleanup_stolen(struct drm_device *dev) drm_mm_takedown(&dev_priv->mm.stolen); } +static void g4x_get_stolen_reserved(struct drm_i915_private *dev_priv, + unsigned long *base, unsigned long *size) +{ + uint32_t reg_val = I915_READ(IS_GM45(dev_priv) ? + CTG_STOLEN_RESERVED : + ELK_STOLEN_RESERVED); + unsigned long stolen_top = dev_priv->mm.stolen_base + + dev_priv->gtt.stolen_size; + + *base = (reg_val & G4X_STOLEN_RESERVED_ADDR2_MASK) << 16; + + WARN_ON((reg_val & G4X_STOLEN_RESERVED_ADDR1_MASK) < *base); + + /* On these platforms, the register doesn't have a size field, so the + * size is the distance between the base and the top of the stolen + * memory. We also have the genuine case where base is zero and there's + * nothing reserved. */ + if (*base == 0) + *size = 0; + else + *size = stolen_top - *base; +} + static void gen6_get_stolen_reserved(struct drm_i915_private *dev_priv, unsigned long *base, unsigned long *size) { @@ -315,10 +338,12 @@ int i915_gem_init_stolen(struct drm_device *dev) switch (INTEL_INFO(dev_priv)->gen) { case 2: case 3: + break; case 4: - if (!IS_G4X(dev)) - break; - /* fall through */ + if (IS_G4X(dev)) + g4x_get_stolen_reserved(dev_priv, &reserved_base, + &reserved_size); + break; case 5: /* Assume the gen6 maximum for the older platforms. */ reserved_size = 1024 * 1024; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index c5287a1..881a47a 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2494,6 +2494,11 @@ enum skl_disp_power_wells { #define MCHBAR_MIRROR_BASE_SNB 0x140000 +#define CTG_STOLEN_RESERVED (MCHBAR_MIRROR_BASE + 0x34) +#define ELK_STOLEN_RESERVED (MCHBAR_MIRROR_BASE + 0x48) +#define G4X_STOLEN_RESERVED_ADDR1_MASK (0xFFFF << 16) +#define G4X_STOLEN_RESERVED_ADDR2_MASK (0xFFF << 4) + /* Memory controller frequency in MCHBAR for Haswell (possible SNB+) */ #define DCLK (MCHBAR_MIRROR_BASE_SNB + 0x5e04) -- cgit v0.10.2 From a2cad9dff4dd44d0244b966d980de9d602d87593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Winiarski?= Date: Wed, 16 Sep 2015 11:49:00 +0200 Subject: drm/i915/gtt: Do not initialize drm_mm twice. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It would be initialized just moments later by i915_init_vm. Rearrange the code such that i915_init_vm() is next to its callers inside i915_gem_gtt (and so we can make it static). After removing the dance around the files, it is clear that we are repeating some work inside the initializers (such as calling drm_mm_init() multiple times), so take advantage of the refactor to also remove some redundant code and clean up the interface. v2: Commit msg update, s/i915_init_vm/i915_address_space_init, move to i915_gem_gtt.c, init address_space during i915_gem_setup_global_gtt for ggtt. v3: Do not init global_link - we are adding it to vm_list moments later, make i915_address_space_init static, use OOP style parameter order. Cc: Chris Wilson Cc: Michel Thierry Cc: Mika Kuoppala Signed-off-by: Michał Winiarski Reviewed-by Chris Wilson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3044cbe..4e8178d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2809,8 +2809,6 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, size_t size); struct drm_i915_gem_object *i915_gem_object_create_from_data( struct drm_device *dev, const void *data, size_t size); -void i915_init_vm(struct drm_i915_private *dev_priv, - struct i915_address_space *vm); void i915_gem_free_object(struct drm_gem_object *obj); void i915_gem_vma_destroy(struct i915_vma *vma); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index e1b6457..58c7ad0 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4844,18 +4844,6 @@ init_ring_lists(struct intel_engine_cs *ring) INIT_LIST_HEAD(&ring->request_list); } -void i915_init_vm(struct drm_i915_private *dev_priv, - struct i915_address_space *vm) -{ - if (!i915_is_ggtt(vm)) - drm_mm_init(&vm->mm, vm->start, vm->total); - vm->dev = dev_priv->dev; - INIT_LIST_HEAD(&vm->active_list); - INIT_LIST_HEAD(&vm->inactive_list); - INIT_LIST_HEAD(&vm->global_link); - list_add_tail(&vm->global_link, &dev_priv->vm_list); -} - void i915_gem_load(struct drm_device *dev) { @@ -4879,8 +4867,6 @@ i915_gem_load(struct drm_device *dev) NULL); INIT_LIST_HEAD(&dev_priv->vm_list); - i915_init_vm(dev_priv, &dev_priv->gtt.base); - INIT_LIST_HEAD(&dev_priv->context_list); INIT_LIST_HEAD(&dev_priv->mm.unbound_list); INIT_LIST_HEAD(&dev_priv->mm.bound_list); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 8786281..01f3521 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2121,6 +2121,16 @@ static int __hw_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt) return gen8_ppgtt_init(ppgtt); } +static void i915_address_space_init(struct i915_address_space *vm, + struct drm_i915_private *dev_priv) +{ + drm_mm_init(&vm->mm, vm->start, vm->total); + vm->dev = dev_priv->dev; + INIT_LIST_HEAD(&vm->active_list); + INIT_LIST_HEAD(&vm->inactive_list); + list_add_tail(&vm->global_link, &dev_priv->vm_list); +} + int i915_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -2129,9 +2139,7 @@ int i915_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt) ret = __hw_ppgtt_init(dev, ppgtt); if (ret == 0) { kref_init(&ppgtt->ref); - drm_mm_init(&ppgtt->base.mm, ppgtt->base.start, - ppgtt->base.total); - i915_init_vm(dev_priv, &ppgtt->base); + i915_address_space_init(&ppgtt->base, dev_priv); } return ret; @@ -2618,11 +2626,13 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev, BUG_ON(mappable_end > end); - /* Subtract the guard page ... */ - drm_mm_init(&ggtt_vm->mm, start, end - start - PAGE_SIZE); + ggtt_vm->start = start; - dev_priv->gtt.base.start = start; - dev_priv->gtt.base.total = end - start; + /* Subtract the guard page before address space initialization to + * shrink the range used by drm_mm */ + ggtt_vm->total = end - start - PAGE_SIZE; + i915_address_space_init(ggtt_vm, dev_priv); + ggtt_vm->total += PAGE_SIZE; if (intel_vgpu_active(dev)) { ret = intel_vgt_balloon(dev); @@ -2631,7 +2641,7 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev, } if (!HAS_LLC(dev)) - dev_priv->gtt.base.mm.color_adjust = i915_gtt_color_adjust; + ggtt_vm->mm.color_adjust = i915_gtt_color_adjust; /* Mark any preallocated objects as occupied */ list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { -- cgit v0.10.2 From 8204502a6aa2eab8cd5779020c2881fbc6361a96 Mon Sep 17 00:00:00 2001 From: Dongwon Kim Date: Thu, 17 Sep 2015 11:26:35 -0700 Subject: drm/i915: Do not hardcode s_max, ss_max and eu_mask for BXT We can calculate BXT values correctly from GFX fuse values without hardcoding special limits. Cc: Imre Deak Cc: Matthew D Roper Signed-off-by: Dongwon Kim Reviewed-by: Arun Siluvery Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index c069550..817b05c 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -631,17 +631,6 @@ static void gen9_sseu_info_init(struct drm_device *dev) u32 fuse2, s_enable, ss_disable, eu_disable; u8 eu_mask = 0xff; - /* - * BXT has a single slice. BXT also has at most 6 EU per subslice, - * and therefore only the lowest 6 bits of the 8-bit EU disable - * fields are valid. - */ - if (IS_BROXTON(dev)) { - s_max = 1; - eu_max = 6; - eu_mask = 0x3f; - } - info = (struct intel_device_info *)&dev_priv->info; fuse2 = I915_READ(GEN8_FUSE2); s_enable = (fuse2 & GEN8_F2_S_ENA_MASK) >> -- cgit v0.10.2 From 6de20eb0dee4c802d9d228d6c08d00386e172e52 Mon Sep 17 00:00:00 2001 From: Andrew Price Date: Wed, 23 Sep 2015 08:45:43 -0500 Subject: GFS2: Set s_mode before parsing mount options In the generic mount_bdev() function, deactivate_locked_super() is called after the fill_super() call fails, at which point s_mode has been set. kill_block_super() expects this and dumps a warning when FMODE_EXCL is not set in s_mode. In gfs2_mount() we call deactivate_locked_super() on failure of gfs2_mount_args(), at which point s_mode has not yet been set. This causes kill_block_super() to dump a stack trace when gfs2 fails to mount with invalid options. Set s_mode earlier in gfs2_mount() to avoid that. Signed-off-by: Andrew Price Signed-off-by: Bob Peterson diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 02586e7..baab99b 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -1291,6 +1291,9 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags, up_write(&s->s_umount); blkdev_put(bdev, mode); down_write(&s->s_umount); + } else { + /* s_mode must be set before deactivate_locked_super calls */ + s->s_mode = mode; } memset(&args, 0, sizeof(args)); @@ -1314,7 +1317,6 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags, } else { char b[BDEVNAME_SIZE]; - s->s_mode = mode; strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id)); sb_set_blocksize(s, block_size(bdev)); error = fill_super(s, &args, flags & MS_SILENT ? 1 : 0); -- cgit v0.10.2 From 7f16cb676c006d87a97ed2e51815daf1fa17eb29 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Wed, 16 Sep 2015 17:37:02 +0200 Subject: ARM: at91/dt: add sama5d2 pinmux Add sama5d2 pin descriptions. Signed-off-by: Ludovic Desroches Acked-by: Linus Walleij Signed-off-by: Nicolas Ferre diff --git a/arch/arm/boot/dts/sama5d2-pinfunc.h b/arch/arm/boot/dts/sama5d2-pinfunc.h new file mode 100644 index 0000000..1afe246 --- /dev/null +++ b/arch/arm/boot/dts/sama5d2-pinfunc.h @@ -0,0 +1,880 @@ +#define PINMUX_PIN(no, func, ioset) \ +(((no) & 0xffff) | (((func) & 0xf) << 16) | (((ioset) & 0xff) << 20)) + +#define PIN_PA0 0 +#define PIN_PA0__GPIO PINMUX_PIN(PIN_PA0, 0, 0) +#define PIN_PA0__SDMMC0_CK PINMUX_PIN(PIN_PA0, 1, 1) +#define PIN_PA0__QSPI0_SCK PINMUX_PIN(PIN_PA0, 2, 1) +#define PIN_PA0__D0 PINMUX_PIN(PIN_PA0, 6, 2) +#define PIN_PA1 1 +#define PIN_PA1__GPIO PINMUX_PIN(PIN_PA1, 0, 0) +#define PIN_PA1__SDMMC0_CMD PINMUX_PIN(PIN_PA1, 1, 1) +#define PIN_PA1__QSPI0_CS PINMUX_PIN(PIN_PA1, 2, 1) +#define PIN_PA1__D1 PINMUX_PIN(PIN_PA1, 6, 2) +#define PIN_PA2 2 +#define PIN_PA2__GPIO PINMUX_PIN(PIN_PA2, 0, 0) +#define PIN_PA2__SDMMC0_DAT0 PINMUX_PIN(PIN_PA2, 1, 1) +#define PIN_PA2__QSPI0_IO0 PINMUX_PIN(PIN_PA2, 2, 1) +#define PIN_PA2__D2 PINMUX_PIN(PIN_PA2, 6, 2) +#define PIN_PA3 3 +#define PIN_PA3__GPIO PINMUX_PIN(PIN_PA3, 0, 0) +#define PIN_PA3__SDMMC0_DAT1 PINMUX_PIN(PIN_PA3, 1, 1) +#define PIN_PA3__QSPI0_IO1 PINMUX_PIN(PIN_PA3, 2, 1) +#define PIN_PA3__D3 PINMUX_PIN(PIN_PA3, 6, 2) +#define PIN_PA4 4 +#define PIN_PA4__GPIO PINMUX_PIN(PIN_PA4, 0, 0) +#define PIN_PA4__SDMMC0_DAT2 PINMUX_PIN(PIN_PA4, 1, 1) +#define PIN_PA4__QSPI0_IO2 PINMUX_PIN(PIN_PA4, 2, 1) +#define PIN_PA4__D4 PINMUX_PIN(PIN_PA4, 6, 2) +#define PIN_PA5 5 +#define PIN_PA5__GPIO PINMUX_PIN(PIN_PA5, 0, 0) +#define PIN_PA5__SDMMC0_DAT3 PINMUX_PIN(PIN_PA5, 1, 1) +#define PIN_PA5__QSPI0_IO3 PINMUX_PIN(PIN_PA5, 2, 1) +#define PIN_PA5__D5 PINMUX_PIN(PIN_PA5, 6, 2) +#define PIN_PA6 6 +#define PIN_PA6__GPIO PINMUX_PIN(PIN_PA6, 0, 0) +#define PIN_PA6__SDMMC0_DAT4 PINMUX_PIN(PIN_PA6, 1, 1) +#define PIN_PA6__QSPI1_SCK PINMUX_PIN(PIN_PA6, 2, 1) +#define PIN_PA6__TIOA5 PINMUX_PIN(PIN_PA6, 4, 1) +#define PIN_PA6__FLEXCOM2_IO0 PINMUX_PIN(PIN_PA6, 5, 1) +#define PIN_PA6__D6 PINMUX_PIN(PIN_PA6, 6, 2) +#define PIN_PA7 7 +#define PIN_PA7__GPIO PINMUX_PIN(PIN_PA7, 0, 0) +#define PIN_PA7__SDMMC0_DAT5 PINMUX_PIN(PIN_PA7, 1, 1) +#define PIN_PA7__QSPI1_IO0 PINMUX_PIN(PIN_PA7, 2, 1) +#define PIN_PA7__TIOB5 PINMUX_PIN(PIN_PA7, 4, 1) +#define PIN_PA7__FLEXCOM2_IO1 PINMUX_PIN(PIN_PA7, 5, 1) +#define PIN_PA7__D7 PINMUX_PIN(PIN_PA7, 6, 2) +#define PIN_PA8 8 +#define PIN_PA8__GPIO PINMUX_PIN(PIN_PA8, 0, 0) +#define PIN_PA8__SDMMC0_DAT6 PINMUX_PIN(PIN_PA8, 1, 1) +#define PIN_PA8__QSPI1_IO1 PINMUX_PIN(PIN_PA8, 2, 1) +#define PIN_PA8__TCLK5 PINMUX_PIN(PIN_PA8, 4, 1) +#define PIN_PA8__FLEXCOM2_IO2 PINMUX_PIN(PIN_PA8, 5, 1) +#define PIN_PA8__NWE_NANDWE PINMUX_PIN(PIN_PA8, 6, 2) +#define PIN_PA9 9 +#define PIN_PA9__GPIO PINMUX_PIN(PIN_PA9, 0, 0) +#define PIN_PA9__SDMMC0_DAT7 PINMUX_PIN(PIN_PA9, 1, 1) +#define PIN_PA9__QSPI1_IO2 PINMUX_PIN(PIN_PA9, 2, 1) +#define PIN_PA9__TIOA4 PINMUX_PIN(PIN_PA9, 4, 1) +#define PIN_PA9__FLEXCOM2_IO3 PINMUX_PIN(PIN_PA9, 5, 1) +#define PIN_PA9__NCS3 PINMUX_PIN(PIN_PA9, 6, 2) +#define PIN_PA10 10 +#define PIN_PA10__GPIO PINMUX_PIN(PIN_PA10, 0, 0) +#define PIN_PA10__SDMMC0_RSTN PINMUX_PIN(PIN_PA10, 1, 1) +#define PIN_PA10__QSPI1_IO3 PINMUX_PIN(PIN_PA10, 2, 1) +#define PIN_PA10__TIOB4 PINMUX_PIN(PIN_PA10, 4, 1) +#define PIN_PA10__FLEXCOM2_IO4 PINMUX_PIN(PIN_PA10, 5, 1) +#define PIN_PA10__A21_NANDALE PINMUX_PIN(PIN_PA10, 6, 2) +#define PIN_PA11 11 +#define PIN_PA11__GPIO PINMUX_PIN(PIN_PA11, 0, 0) +#define PIN_PA11__SDMMC0_VDDSEL PINMUX_PIN(PIN_PA11, 1, 1) +#define PIN_PA11__QSPI1_CS PINMUX_PIN(PIN_PA11, 2, 1) +#define PIN_PA11__TCLK4 PINMUX_PIN(PIN_PA11, 4, 1) +#define PIN_PA11__A22_NANDCLE PINMUX_PIN(PIN_PA11, 6, 2) +#define PIN_PA12 12 +#define PIN_PA12__GPIO PINMUX_PIN(PIN_PA12, 0, 0) +#define PIN_PA12__SDMMC0_WP PINMUX_PIN(PIN_PA12, 1, 1) +#define PIN_PA12__IRQ PINMUX_PIN(PIN_PA12, 2, 1) +#define PIN_PA12__NRD_NANDOE PINMUX_PIN(PIN_PA12, 6, 2) +#define PIN_PA13 13 +#define PIN_PA13__GPIO PINMUX_PIN(PIN_PA13, 0, 0) +#define PIN_PA13__SDMMC0_CD PINMUX_PIN(PIN_PA13, 1, 1) +#define PIN_PA13__FLEXCOM3_IO1 PINMUX_PIN(PIN_PA13, 5, 1) +#define PIN_PA13__D8 PINMUX_PIN(PIN_PA13, 6, 2) +#define PIN_PA14 14 +#define PIN_PA14__GPIO PINMUX_PIN(PIN_PA14, 0, 0) +#define PIN_PA14__SPI0_SPCK PINMUX_PIN(PIN_PA14, 1, 1) +#define PIN_PA14__TK1 PINMUX_PIN(PIN_PA14, 2, 1) +#define PIN_PA14__QSPI0_SCK PINMUX_PIN(PIN_PA14, 3, 2) +#define PIN_PA14__I2SC1_MCK PINMUX_PIN(PIN_PA14, 4, 2) +#define PIN_PA14__FLEXCOM3_IO2 PINMUX_PIN(PIN_PA14, 5, 1) +#define PIN_PA14__D9 PINMUX_PIN(PIN_PA14, 6, 2) +#define PIN_PA15 14 +#define PIN_PA15__GPIO PINMUX_PIN(PIN_PA15, 0, 0) +#define PIN_PA15__SPI0_MOSI PINMUX_PIN(PIN_PA15, 1, 1) +#define PIN_PA15__TF1 PINMUX_PIN(PIN_PA15, 2, 1) +#define PIN_PA15__QSPI0_CS PINMUX_PIN(PIN_PA15, 3, 2) +#define PIN_PA15__I2SC1_CK PINMUX_PIN(PIN_PA15, 4, 2) +#define PIN_PA15__FLEXCOM3_IO0 PINMUX_PIN(PIN_PA15, 5, 1) +#define PIN_PA15__D10 PINMUX_PIN(PIN_PA15, 6, 2) +#define PIN_PA16 16 +#define PIN_PA16__GPIO PINMUX_PIN(PIN_PA16, 0, 0) +#define PIN_PA16__SPI0_MISO PINMUX_PIN(PIN_PA16, 1, 1) +#define PIN_PA16__TD1 PINMUX_PIN(PIN_PA16, 2, 1) +#define PIN_PA16__QSPI0_IO0 PINMUX_PIN(PIN_PA16, 3, 2) +#define PIN_PA16__I2SC1_WS PINMUX_PIN(PIN_PA16, 4, 2) +#define PIN_PA16__FLEXCOM3_IO3 PINMUX_PIN(PIN_PA16, 5, 1) +#define PIN_PA16__D11 PINMUX_PIN(PIN_PA16, 6, 2) +#define PIN_PA17 17 +#define PIN_PA17__GPIO PINMUX_PIN(PIN_PA17, 0, 0) +#define PIN_PA17__SPI0_NPCS0 PINMUX_PIN(PIN_PA17, 1, 1) +#define PIN_PA17__RD1 PINMUX_PIN(PIN_PA17, 2, 1) +#define PIN_PA17__QSPI0_IO1 PINMUX_PIN(PIN_PA17, 3, 2) +#define PIN_PA17__I2SC1_DI0 PINMUX_PIN(PIN_PA17, 4, 2) +#define PIN_PA17__FLEXCOM3_IO4 PINMUX_PIN(PIN_PA17, 5, 1) +#define PIN_PA17__D12 PINMUX_PIN(PIN_PA17, 6, 2) +#define PIN_PA18 18 +#define PIN_PA18__GPIO PINMUX_PIN(PIN_PA18, 0, 0) +#define PIN_PA18__SPI0_NPCS1 PINMUX_PIN(PIN_PA18, 1, 1) +#define PIN_PA18__RK1 PINMUX_PIN(PIN_PA18, 2, 1) +#define PIN_PA18__QSPI0_IO2 PINMUX_PIN(PIN_PA18, 3, 2) +#define PIN_PA18__I2SC1_DO0 PINMUX_PIN(PIN_PA18, 4, 2) +#define PIN_PA18__SDMMC1_DAT0 PINMUX_PIN(PIN_PA18, 5, 1) +#define PIN_PA18__D13 PINMUX_PIN(PIN_PA18, 6, 2) +#define PIN_PA19 19 +#define PIN_PA19__GPIO PINMUX_PIN(PIN_PA19, 0, 0) +#define PIN_PA19__SPI0_NPCS2 PINMUX_PIN(PIN_PA19, 1, 1) +#define PIN_PA19__RF1 PINMUX_PIN(PIN_PA19, 2, 1) +#define PIN_PA19__QSPI0_IO3 PINMUX_PIN(PIN_PA19, 3, 2) +#define PIN_PA19__TIOA0 PINMUX_PIN(PIN_PA19, 4, 1) +#define PIN_PA19__SDMMC1_DAT1 PINMUX_PIN(PIN_PA19, 5, 1) +#define PIN_PA19__D14 PINMUX_PIN(PIN_PA19, 6, 2) +#define PIN_PA20 20 +#define PIN_PA20__GPIO PINMUX_PIN(PIN_PA20, 0, 0) +#define PIN_PA20__SPI0_NPCS3 PINMUX_PIN(PIN_PA20, 1, 1) +#define PIN_PA20__TIOB0 PINMUX_PIN(PIN_PA20, 4, 1) +#define PIN_PA20__SDMMC1_DAT2 PINMUX_PIN(PIN_PA20, 5, 1) +#define PIN_PA20__D15 PINMUX_PIN(PIN_PA20, 6, 2) +#define PIN_PA21 21 +#define PIN_PA21__GPIO PINMUX_PIN(PIN_PA21, 0, 0) +#define PIN_PA21__IRQ PINMUX_PIN(PIN_PA21, 1, 2) +#define PIN_PA21__PCK2 PINMUX_PIN(PIN_PA21, 2, 3) +#define PIN_PA21__TCLK0 PINMUX_PIN(PIN_PA21, 4, 1) +#define PIN_PA21__SDMMC1_DAT3 PINMUX_PIN(PIN_PA21, 5, 1) +#define PIN_PA21__NANDRDY PINMUX_PIN(PIN_PA21, 6, 2) +#define PIN_PA22 22 +#define PIN_PA22__GPIO PINMUX_PIN(PIN_PA22, 0, 0) +#define PIN_PA22__FLEXCOM1_IO2 PINMUX_PIN(PIN_PA22, 1, 1) +#define PIN_PA22__D0 PINMUX_PIN(PIN_PA22, 2, 1) +#define PIN_PA22__TCK PINMUX_PIN(PIN_PA22, 3, 4) +#define PIN_PA22__SPI1_SPCK PINMUX_PIN(PIN_PA22, 4, 2) +#define PIN_PA22__SDMMC1_CK PINMUX_PIN(PIN_PA22, 5, 1) +#define PIN_PA22__QSPI0_SCK PINMUX_PIN(PIN_PA22, 6, 3) +#define PIN_PA23 23 +#define PIN_PA23__GPIO PINMUX_PIN(PIN_PA23, 0, 0) +#define PIN_PA23__FLEXCOM1_IO1 PINMUX_PIN(PIN_PA23, 1, 1) +#define PIN_PA23__D1 PINMUX_PIN(PIN_PA23, 2, 1) +#define PIN_PA23__TDI PINMUX_PIN(PIN_PA23, 3, 4) +#define PIN_PA23__SPI1_MOSI PINMUX_PIN(PIN_PA23, 4, 2) +#define PIN_PA23__QSPI0_CS PINMUX_PIN(PIN_PA23, 6, 3) +#define PIN_PA24 24 +#define PIN_PA24__GPIO PINMUX_PIN(PIN_PA24, 0, 0) +#define PIN_PA24__FLEXCOM1_IO0 PINMUX_PIN(PIN_PA24, 1, 1) +#define PIN_PA24__D2 PINMUX_PIN(PIN_PA24, 2, 1) +#define PIN_PA24__TDO PINMUX_PIN(PIN_PA24, 3, 4) +#define PIN_PA24__SPI1_MISO PINMUX_PIN(PIN_PA24, 4, 2) +#define PIN_PA24__QSPI0_IO0 PINMUX_PIN(PIN_PA24, 6, 3) +#define PIN_PA25 25 +#define PIN_PA25__GPIO PINMUX_PIN(PIN_PA25, 0, 0) +#define PIN_PA25__FLEXCOM1_IO3 PINMUX_PIN(PIN_PA25, 1, 1) +#define PIN_PA25__D3 PINMUX_PIN(PIN_PA25, 2, 1) +#define PIN_PA25__TMS PINMUX_PIN(PIN_PA25, 3, 4) +#define PIN_PA25__SPI1_NPCS0 PINMUX_PIN(PIN_PA25, 4, 2) +#define PIN_PA25__QSPI0_IO1 PINMUX_PIN(PIN_PA25, 6, 3) +#define PIN_PA26 26 +#define PIN_PA26__GPIO PINMUX_PIN(PIN_PA26, 0, 0) +#define PIN_PA26__FLEXCOM1_IO4 PINMUX_PIN(PIN_PA26, 1, 1) +#define PIN_PA26__D4 PINMUX_PIN(PIN_PA26, 2, 1) +#define PIN_PA26__NTRST PINMUX_PIN(PIN_PA26, 3, 4) +#define PIN_PA26__SPI1_NPCS1 PINMUX_PIN(PIN_PA26, 4, 2) +#define PIN_PA26__QSPI0_IO2 PINMUX_PIN(PIN_PA26, 6, 3) +#define PIN_PA27 27 +#define PIN_PA27__GPIO PINMUX_PIN(PIN_PA27, 0, 0) +#define PIN_PA27__TIOA1 PINMUX_PIN(PIN_PA27, 1, 2) +#define PIN_PA27__D5 PINMUX_PIN(PIN_PA27, 2, 1) +#define PIN_PA27__SPI0_NPCS2 PINMUX_PIN(PIN_PA27, 3, 2) +#define PIN_PA27__SPI1_NPCS2 PINMUX_PIN(PIN_PA27, 4, 2) +#define PIN_PA27__SDMMC1_RSTN PINMUX_PIN(PIN_PA27, 5, 1) +#define PIN_PA27__QSPI0_IO3 PINMUX_PIN(PIN_PA27, 6, 3) +#define PIN_PA28 28 +#define PIN_PA28__GPIO PINMUX_PIN(PIN_PA28, 0, 0) +#define PIN_PA28__TIOB1 PINMUX_PIN(PIN_PA28, 1, 2) +#define PIN_PA28__D6 PINMUX_PIN(PIN_PA28, 2, 1) +#define PIN_PA28__SPI0_NPCS3 PINMUX_PIN(PIN_PA28, 3, 2) +#define PIN_PA28__SPI1_NPCS3 PINMUX_PIN(PIN_PA28, 4, 2) +#define PIN_PA28__SDMMC1_CMD PINMUX_PIN(PIN_PA28, 5, 1) +#define PIN_PA28__CLASSD_L0 PINMUX_PIN(PIN_PA28, 6, 1) +#define PIN_PA29 29 +#define PIN_PA29__GPIO PINMUX_PIN(PIN_PA29, 0, 0) +#define PIN_PA29__TCLK1 PINMUX_PIN(PIN_PA29, 1, 2) +#define PIN_PA29__D7 PINMUX_PIN(PIN_PA29, 2, 1) +#define PIN_PA29__SPI0_NPCS1 PINMUX_PIN(PIN_PA29, 3, 2) +#define PIN_PA29__SDMMC1_WP PINMUX_PIN(PIN_PA29, 5, 1) +#define PIN_PA29__CLASSD_L1 PINMUX_PIN(PIN_PA29, 6, 1) +#define PIN_PA30 30 +#define PIN_PA30__GPIO PINMUX_PIN(PIN_PA30, 0, 0) +#define PIN_PA30__NWE_NANDWE PINMUX_PIN(PIN_PA30, 2, 1) +#define PIN_PA30__SPI0_NPCS0 PINMUX_PIN(PIN_PA30, 3, 2) +#define PIN_PA30__PWMH0 PINMUX_PIN(PIN_PA30, 4, 1) +#define PIN_PA30__SDMMC1_CD PINMUX_PIN(PIN_PA30, 5, 1) +#define PIN_PA30__CLASSD_L2 PINMUX_PIN(PIN_PA30, 6, 1) +#define PIN_PA31 31 +#define PIN_PA31__GPIO PINMUX_PIN(PIN_PA31, 0, 0) +#define PIN_PA31__NCS3 PINMUX_PIN(PIN_PA31, 2, 1) +#define PIN_PA31__SPI0_MISO PINMUX_PIN(PIN_PA31, 3, 2) +#define PIN_PA31__PWML0 PINMUX_PIN(PIN_PA31, 4, 1) +#define PIN_PA31__CLASSD_L3 PINMUX_PIN(PIN_PA31, 6, 1) +#define PIN_PB0 32 +#define PIN_PB0__GPIO PINMUX_PIN(PIN_PB0, 0, 0) +#define PIN_PB0__A21_NANDALE PINMUX_PIN(PIN_PB0, 2, 1) +#define PIN_PB0__SPI0_MOSI PINMUX_PIN(PIN_PB0, 3, 2) +#define PIN_PB0__PWMH1 PINMUX_PIN(PIN_PB0, 4, 1) +#define PIN_PB1 33 +#define PIN_PB1__GPIO PINMUX_PIN(PIN_PB1, 0, 0) +#define PIN_PB1__A22_NANDCLE PINMUX_PIN(PIN_PB1, 2, 1) +#define PIN_PB1__SPI0_SPCK PINMUX_PIN(PIN_PB1, 3, 2) +#define PIN_PB1__PWML1 PINMUX_PIN(PIN_PB1, 4, 1) +#define PIN_PB1__CLASSD_R0 PINMUX_PIN(PIN_PB1, 6, 1) +#define PIN_PB2 34 +#define PIN_PB2__GPIO PINMUX_PIN(PIN_PB2, 0, 0) +#define PIN_PB2__NRD_NANDOE PINMUX_PIN(PIN_PB2, 2, 1) +#define PIN_PB2__PWMFI0 PINMUX_PIN(PIN_PB2, 4, 1) +#define PIN_PB2__CLASSD_R1 PINMUX_PIN(PIN_PB2, 6, 1) +#define PIN_PB3 35 +#define PIN_PB3__GPIO PINMUX_PIN(PIN_PB3, 0, 0) +#define PIN_PB3__URXD4 PINMUX_PIN(PIN_PB3, 1, 1) +#define PIN_PB3__D8 PINMUX_PIN(PIN_PB3, 2, 1) +#define PIN_PB3__IRQ PINMUX_PIN(PIN_PB3, 3, 3) +#define PIN_PB3__PWMEXTRG0 PINMUX_PIN(PIN_PB3, 4, 1) +#define PIN_PB3__CLASSD_R2 PINMUX_PIN(PIN_PB3, 6, 1) +#define PIN_PB4 36 +#define PIN_PB4__GPIO PINMUX_PIN(PIN_PB4, 0, 0) +#define PIN_PB4__UTXD4 PINMUX_PIN(PIN_PB4, 1, 1) +#define PIN_PB4__D9 PINMUX_PIN(PIN_PB4, 2, 1) +#define PIN_PB4__FIQ PINMUX_PIN(PIN_PB4, 3, 4) +#define PIN_PB4__CLASSD_R3 PINMUX_PIN(PIN_PB4, 6, 1) +#define PIN_PB5 37 +#define PIN_PB5__GPIO PINMUX_PIN(PIN_PB5, 0, 0) +#define PIN_PB5__TCLK2 PINMUX_PIN(PIN_PB5, 1, 1) +#define PIN_PB5__D10 PINMUX_PIN(PIN_PB5, 2, 1) +#define PIN_PB5__PWMH2 PINMUX_PIN(PIN_PB5, 3, 1) +#define PIN_PB5__QSPI1_SCK PINMUX_PIN(PIN_PB5, 4, 2) +#define PIN_PB5__GTSUCOMP PINMUX_PIN(PIN_PB5, 6, 3) +#define PIN_PB6 38 +#define PIN_PB6__GPIO PINMUX_PIN(PIN_PB6, 0, 0) +#define PIN_PB6__TIOA2 PINMUX_PIN(PIN_PB6, 1, 1) +#define PIN_PB6__D11 PINMUX_PIN(PIN_PB6, 2, 1) +#define PIN_PB6__PWML2 PINMUX_PIN(PIN_PB6, 3, 1) +#define PIN_PB6__QSPI1_CS PINMUX_PIN(PIN_PB6, 4, 2) +#define PIN_PB6__GTXER PINMUX_PIN(PIN_PB6, 6, 3) +#define PIN_PB7 39 +#define PIN_PB7__GPIO PINMUX_PIN(PIN_PB7, 0, 0) +#define PIN_PB7__TIOB2 PINMUX_PIN(PIN_PB7, 1, 1) +#define PIN_PB7__D12 PINMUX_PIN(PIN_PB7, 2, 1) +#define PIN_PB7__PWMH3 PINMUX_PIN(PIN_PB7, 3, 1) +#define PIN_PB7__QSPI1_IO0 PINMUX_PIN(PIN_PB7, 4, 2) +#define PIN_PB7__GRXCK PINMUX_PIN(PIN_PB7, 6, 3) +#define PIN_PB8 40 +#define PIN_PB8__GPIO PINMUX_PIN(PIN_PB8, 0, 0) +#define PIN_PB8__TCLK3 PINMUX_PIN(PIN_PB8, 1, 1) +#define PIN_PB8__D13 PINMUX_PIN(PIN_PB8, 2, 1) +#define PIN_PB8__PWML3 PINMUX_PIN(PIN_PB8, 3, 1) +#define PIN_PB8__QSPI1_IO1 PINMUX_PIN(PIN_PB8, 4, 2) +#define PIN_PB8__GCRS PINMUX_PIN(PIN_PB8, 6, 3) +#define PIN_PB9 41 +#define PIN_PB9__GPIO PINMUX_PIN(PIN_PB9, 0, 0) +#define PIN_PB9__TIOA3 PINMUX_PIN(PIN_PB9, 1, 1) +#define PIN_PB9__D14 PINMUX_PIN(PIN_PB9, 2, 1) +#define PIN_PB9__PWMFI1 PINMUX_PIN(PIN_PB9, 3, 1) +#define PIN_PB9__QSPI1_IO2 PINMUX_PIN(PIN_PB9, 4, 2) +#define PIN_PB9__GCOL PINMUX_PIN(PIN_PB9, 6, 3) +#define PIN_PB10 42 +#define PIN_PB10__GPIO PINMUX_PIN(PIN_PB10, 0, 0) +#define PIN_PB10__TIOB3 PINMUX_PIN(PIN_PB10, 1, 1) +#define PIN_PB10__D15 PINMUX_PIN(PIN_PB10, 2, 1) +#define PIN_PB10__PWMEXTRG1 PINMUX_PIN(PIN_PB10, 3, 1) +#define PIN_PB10__QSPI1_IO3 PINMUX_PIN(PIN_PB10, 4, 2) +#define PIN_PB10__GRX2 PINMUX_PIN(PIN_PB10, 6, 3) +#define PIN_PB11 43 +#define PIN_PB11__GPIO PINMUX_PIN(PIN_PB11, 0, 0) +#define PIN_PB11__LCDDAT0 PINMUX_PIN(PIN_PB11, 1, 1) +#define PIN_PB11__A0_NBS0 PINMUX_PIN(PIN_PB11, 2, 1) +#define PIN_PB11__URXD3 PINMUX_PIN(PIN_PB11, 3, 3) +#define PIN_PB11__PDMIC_DAT PINMUX_PIN(PIN_PB11, 4, 2) +#define PIN_PB11__GRX3 PINMUX_PIN(PIN_PB11, 6, 3) +#define PIN_PB12 44 +#define PIN_PB12__GPIO PINMUX_PIN(PIN_PB12, 0, 0) +#define PIN_PB12__LCDDAT1 PINMUX_PIN(PIN_PB12, 1, 1) +#define PIN_PB12__A1 PINMUX_PIN(PIN_PB12, 2, 1) +#define PIN_PB12__UTXD3 PINMUX_PIN(PIN_PB12, 3, 3) +#define PIN_PB12__PDMIC_CLK PINMUX_PIN(PIN_PB12, 4, 2) +#define PIN_PB12__GTX2 PINMUX_PIN(PIN_PB12, 6, 3) +#define PIN_PB13 45 +#define PIN_PB13__GPIO PINMUX_PIN(PIN_PB13, 0, 0) +#define PIN_PB13__LCDDAT2 PINMUX_PIN(PIN_PB13, 1, 1) +#define PIN_PB13__A2 PINMUX_PIN(PIN_PB13, 2, 1) +#define PIN_PB13__PCK1 PINMUX_PIN(PIN_PB13, 3, 3) +#define PIN_PB13__GTX3 PINMUX_PIN(PIN_PB13, 6, 3) +#define PIN_PB14 46 +#define PIN_PB14__GPIO PINMUX_PIN(PIN_PB14, 0, 0) +#define PIN_PB14__LCDDAT3 PINMUX_PIN(PIN_PB14, 1, 1) +#define PIN_PB14__A3 PINMUX_PIN(PIN_PB14, 2, 1) +#define PIN_PB14__TK1 PINMUX_PIN(PIN_PB14, 3, 2) +#define PIN_PB14__I2SC1_MCK PINMUX_PIN(PIN_PB14, 4, 1) +#define PIN_PB14__QSPI1_SCK PINMUX_PIN(PIN_PB14, 5, 3) +#define PIN_PB14__GTXCK PINMUX_PIN(PIN_PB14, 6, 3) +#define PIN_PB15 47 +#define PIN_PB15__GPIO PINMUX_PIN(PIN_PB15, 0, 0) +#define PIN_PB15__LCDDAT4 PINMUX_PIN(PIN_PB15, 1, 1) +#define PIN_PB15__A4 PINMUX_PIN(PIN_PB15, 2, 1) +#define PIN_PB15__TF1 PINMUX_PIN(PIN_PB15, 3, 2) +#define PIN_PB15__I2SC1_CK PINMUX_PIN(PIN_PB15, 4, 1) +#define PIN_PB15__QSPI1_CS PINMUX_PIN(PIN_PB15, 5, 3) +#define PIN_PB15__GTXEN PINMUX_PIN(PIN_PB15, 6, 3) +#define PIN_PB16 48 +#define PIN_PB16__GPIO PINMUX_PIN(PIN_PB16, 0, 0) +#define PIN_PB16__LCDDAT5 PINMUX_PIN(PIN_PB16, 1, 1) +#define PIN_PB16__A5 PINMUX_PIN(PIN_PB16, 2, 1) +#define PIN_PB16__TD1 PINMUX_PIN(PIN_PB16, 3, 2) +#define PIN_PB16__I2SC1_WS PINMUX_PIN(PIN_PB16, 4, 1) +#define PIN_PB16__QSPI1_IO0 PINMUX_PIN(PIN_PB16, 5, 3) +#define PIN_PB16__GRXDV PINMUX_PIN(PIN_PB16, 6, 3) +#define PIN_PB17 49 +#define PIN_PB17__GPIO PINMUX_PIN(PIN_PB17, 0, 0) +#define PIN_PB17__LCDDAT6 PINMUX_PIN(PIN_PB17, 1, 1) +#define PIN_PB17__A6 PINMUX_PIN(PIN_PB17, 2, 1) +#define PIN_PB17__RD1 PINMUX_PIN(PIN_PB17, 3, 2) +#define PIN_PB17__I2SC1_DI0 PINMUX_PIN(PIN_PB17, 4, 1) +#define PIN_PB17__QSPI1_IO1 PINMUX_PIN(PIN_PB17, 5, 3) +#define PIN_PB17__GRXER PINMUX_PIN(PIN_PB17, 6, 3) +#define PIN_PB18 50 +#define PIN_PB18__GPIO PINMUX_PIN(PIN_PB18, 0, 0) +#define PIN_PB18__LCDDAT7 PINMUX_PIN(PIN_PB18, 1, 1) +#define PIN_PB18__A7 PINMUX_PIN(PIN_PB18, 2, 1) +#define PIN_PB18__RK1 PINMUX_PIN(PIN_PB18, 3, 2) +#define PIN_PB18__I2SC1_DO0 PINMUX_PIN(PIN_PB18, 4, 1) +#define PIN_PB18__QSPI1_IO2 PINMUX_PIN(PIN_PB18, 5, 3) +#define PIN_PB18__GRX0 PINMUX_PIN(PIN_PB18, 6, 3) +#define PIN_PB19 51 +#define PIN_PB19__GPIO PINMUX_PIN(PIN_PB19, 0, 0) +#define PIN_PB19__LCDDAT8 PINMUX_PIN(PIN_PB19, 1, 1) +#define PIN_PB19__A8 PINMUX_PIN(PIN_PB19, 2, 1) +#define PIN_PB19__RF1 PINMUX_PIN(PIN_PB19, 3, 2) +#define PIN_PB19__TIOA3 PINMUX_PIN(PIN_PB19, 4, 2) +#define PIN_PB19__QSPI1_IO3 PINMUX_PIN(PIN_PB19, 5, 3) +#define PIN_PB19__GRX1 PINMUX_PIN(PIN_PB19, 6, 3) +#define PIN_PB20 52 +#define PIN_PB20__GPIO PINMUX_PIN(PIN_PB20, 0, 0) +#define PIN_PB20__LCDDAT9 PINMUX_PIN(PIN_PB20, 1, 1) +#define PIN_PB20__A9 PINMUX_PIN(PIN_PB20, 2, 1) +#define PIN_PB20__TK0 PINMUX_PIN(PIN_PB20, 3, 1) +#define PIN_PB20__TIOB3 PINMUX_PIN(PIN_PB20, 4, 2) +#define PIN_PB20__PCK1 PINMUX_PIN(PIN_PB20, 5, 4) +#define PIN_PB20__GTX0 PINMUX_PIN(PIN_PB20, 6, 3) +#define PIN_PB21 53 +#define PIN_PB21__GPIO PINMUX_PIN(PIN_PB21, 0, 0) +#define PIN_PB21__LCDDAT10 PINMUX_PIN(PIN_PB21, 1, 1) +#define PIN_PB21__A10 PINMUX_PIN(PIN_PB21, 2, 1) +#define PIN_PB21__TF0 PINMUX_PIN(PIN_PB21, 3, 1) +#define PIN_PB21__TCLK3 PINMUX_PIN(PIN_PB21, 4, 2) +#define PIN_PB21__FLEXCOM3_IO2 PINMUX_PIN(PIN_PB21, 5, 3) +#define PIN_PB21__GTX1 PINMUX_PIN(PIN_PB21, 6, 3) +#define PIN_PB22 54 +#define PIN_PB22__GPIO PINMUX_PIN(PIN_PB22, 0, 0) +#define PIN_PB22__LCDDAT11 PINMUX_PIN(PIN_PB22, 1, 1) +#define PIN_PB22__A11 PINMUX_PIN(PIN_PB22, 2, 1) +#define PIN_PB22__TDO PINMUX_PIN(PIN_PB22, 3, 1) +#define PIN_PB22__TIOA2 PINMUX_PIN(PIN_PB22, 4, 2) +#define PIN_PB22__FLEXCOM3_IO1 PINMUX_PIN(PIN_PB22, 5, 3) +#define PIN_PB22__GMDC PINMUX_PIN(PIN_PB22, 6, 3) +#define PIN_PB23 55 +#define PIN_PB23__GPIO PINMUX_PIN(PIN_PB23, 0, 0) +#define PIN_PB23__LCDDAT12 PINMUX_PIN(PIN_PB23, 1, 1) +#define PIN_PB23__A12 PINMUX_PIN(PIN_PB23, 2, 1) +#define PIN_PB23__RD0 PINMUX_PIN(PIN_PB23, 3, 1) +#define PIN_PB23__TIOB2 PINMUX_PIN(PIN_PB23, 4, 2) +#define PIN_PB23__FLEXCOM3_IO0 PINMUX_PIN(PIN_PB23, 5, 3) +#define PIN_PB23__GMDIO PINMUX_PIN(PIN_PB23, 6, 3) +#define PIN_PB24 56 +#define PIN_PB24__GPIO PINMUX_PIN(PIN_PB24, 0, 0) +#define PIN_PB24__LCDDAT13 PINMUX_PIN(PIN_PB24, 1, 1) +#define PIN_PB24__A13 PINMUX_PIN(PIN_PB24, 2, 1) +#define PIN_PB24__RK0 PINMUX_PIN(PIN_PB24, 3, 1) +#define PIN_PB24__TCLK2 PINMUX_PIN(PIN_PB24, 4, 2) +#define PIN_PB24__FLEXCOM3_IO3 PINMUX_PIN(PIN_PB24, 5, 3) +#define PIN_PB24__ISC_D10 PINMUX_PIN(PIN_PB24, 6, 3) +#define PIN_PB25 57 +#define PIN_PB25__GPIO PINMUX_PIN(PIN_PB25, 0, 0) +#define PIN_PB25__LCDDAT14 PINMUX_PIN(PIN_PB25, 1, 1) +#define PIN_PB25__A14 PINMUX_PIN(PIN_PB25, 2, 1) +#define PIN_PB25__RF0 PINMUX_PIN(PIN_PB25, 3, 1) +#define PIN_PB25__FLEXCOM3_IO4 PINMUX_PIN(PIN_PB25, 5, 3) +#define PIN_PB25__ISC_D11 PINMUX_PIN(PIN_PB25, 6, 3) +#define PIN_PB26 58 +#define PIN_PB26__GPIO PINMUX_PIN(PIN_PB26, 0, 0) +#define PIN_PB26__LCDDAT15 PINMUX_PIN(PIN_PB26, 1, 1) +#define PIN_PB26__A15 PINMUX_PIN(PIN_PB26, 2, 1) +#define PIN_PB26__URXD0 PINMUX_PIN(PIN_PB26, 3, 1) +#define PIN_PB26__PDMIC_DAT PINMUX_PIN(PIN_PB26, 4, 1) +#define PIN_PB26__ISC_D0 PINMUX_PIN(PIN_PB26, 6, 3) +#define PIN_PB27 59 +#define PIN_PB27__GPIO PINMUX_PIN(PIN_PB27, 0, 0) +#define PIN_PB27__LCDDAT16 PINMUX_PIN(PIN_PB27, 1, 1) +#define PIN_PB27__A16 PINMUX_PIN(PIN_PB27, 2, 1) +#define PIN_PB27__UTXD0 PINMUX_PIN(PIN_PB27, 3, 1) +#define PIN_PB27__PDMIC_CLK PINMUX_PIN(PIN_PB27, 4, 1) +#define PIN_PB27__ISC_D1 PINMUX_PIN(PIN_PB27, 6, 3) +#define PIN_PB28 60 +#define PIN_PB28__GPIO PINMUX_PIN(PIN_PB28, 0, 0) +#define PIN_PB28__LCDDAT17 PINMUX_PIN(PIN_PB28, 1, 1) +#define PIN_PB28__A17 PINMUX_PIN(PIN_PB28, 2, 1) +#define PIN_PB28__FLEXCOM0_IO0 PINMUX_PIN(PIN_PB28, 3, 1) +#define PIN_PB28__TIOA5 PINMUX_PIN(PIN_PB28, 4, 2) +#define PIN_PB28__ISC_D2 PINMUX_PIN(PIN_PB28, 6, 3) +#define PIN_PB29 61 +#define PIN_PB29__GPIO PINMUX_PIN(PIN_PB29, 0, 0) +#define PIN_PB29__LCDDAT18 PINMUX_PIN(PIN_PB29, 1, 1) +#define PIN_PB29__A18 PINMUX_PIN(PIN_PB29, 2, 1) +#define PIN_PB29__FLEXCOM0_IO1 PINMUX_PIN(PIN_PB29, 3, 1) +#define PIN_PB29__TIOB5 PINMUX_PIN(PIN_PB29, 4, 2) +#define PIN_PB29__ISC_D3 PINMUX_PIN(PIN_PB29, 7, 3) +#define PIN_PB30 62 +#define PIN_PB30__GPIO PINMUX_PIN(PIN_PB30, 0, 0) +#define PIN_PB30__LCDDAT19 PINMUX_PIN(PIN_PB30, 1, 1) +#define PIN_PB30__A19 PINMUX_PIN(PIN_PB30, 2, 1) +#define PIN_PB30__FLEXCOM0_IO2 PINMUX_PIN(PIN_PB30, 3, 1) +#define PIN_PB30__TCLK5 PINMUX_PIN(PIN_PB30, 4, 2) +#define PIN_PB30__ISC_D4 PINMUX_PIN(PIN_PB30, 6, 3) +#define PIN_PB31 63 +#define PIN_PB31__GPIO PINMUX_PIN(PIN_PB31, 0, 0) +#define PIN_PB31__LCDDAT20 PINMUX_PIN(PIN_PB31, 1, 1) +#define PIN_PB31__A20 PINMUX_PIN(PIN_PB31, 2, 1) +#define PIN_PB31__FLEXCOM0_IO3 PINMUX_PIN(PIN_PB31, 3, 1) +#define PIN_PB31__TWD0 PINMUX_PIN(PIN_PB31, 4, 1) +#define PIN_PB31__ISC_D5 PINMUX_PIN(PIN_PB31, 6, 3) +#define PIN_PC0 64 +#define PIN_PC0__GPIO PINMUX_PIN(PIN_PC0, 0, 0) +#define PIN_PC0__LCDDAT21 PINMUX_PIN(PIN_PC0, 1, 1) +#define PIN_PC0__A23 PINMUX_PIN(PIN_PC0, 2, 1) +#define PIN_PC0__FLEXCOM0_IO4 PINMUX_PIN(PIN_PC0, 3, 1) +#define PIN_PC0__TWCK0 PINMUX_PIN(PIN_PC0, 4, 1) +#define PIN_PC0__ISC_D6 PINMUX_PIN(PIN_PC0, 6, 3) +#define PIN_PC1 65 +#define PIN_PC1__GPIO PINMUX_PIN(PIN_PC1, 0, 0) +#define PIN_PC1__LCDDAT22 PINMUX_PIN(PIN_PC1, 1, 1) +#define PIN_PC1__A24 PINMUX_PIN(PIN_PC1, 2, 1) +#define PIN_PC1__CANTX0 PINMUX_PIN(PIN_PC1, 3, 1) +#define PIN_PC1__SPI1_SPCK PINMUX_PIN(PIN_PC1, 4, 1) +#define PIN_PC1__I2SC0_CK PINMUX_PIN(PIN_PC1, 5, 1) +#define PIN_PC1__ISC_D7 PINMUX_PIN(PIN_PC1, 6, 3) +#define PIN_PC2 66 +#define PIN_PC2__GPIO PINMUX_PIN(PIN_PC2, 0, 0) +#define PIN_PC2__LCDDAT23 PINMUX_PIN(PIN_PC2, 1, 1) +#define PIN_PC2__A25 PINMUX_PIN(PIN_PC2, 2, 1) +#define PIN_PC2__CANRX0 PINMUX_PIN(PIN_PC2, 3, 1) +#define PIN_PC2__SPI1_MOSI PINMUX_PIN(PIN_PC2, 4, 1) +#define PIN_PC2__I2SC0_MCK PINMUX_PIN(PIN_PC2, 5, 1) +#define PIN_PC2__ISC_D8 PINMUX_PIN(PIN_PC2, 6, 3) +#define PIN_PC3 67 +#define PIN_PC3__GPIO PINMUX_PIN(PIN_PC3, 0, 0) +#define PIN_PC3__LCDPWM PINMUX_PIN(PIN_PC3, 1, 1) +#define PIN_PC3__NWAIT PINMUX_PIN(PIN_PC3, 2, 1) +#define PIN_PC3__TIOA1 PINMUX_PIN(PIN_PC3, 3, 1) +#define PIN_PC3__SPI1_MISO PINMUX_PIN(PIN_PC3, 4, 1) +#define PIN_PC3__I2SC0_WS PINMUX_PIN(PIN_PC3, 5, 1) +#define PIN_PC3__ISC_D9 PINMUX_PIN(PIN_PC3, 6, 3) +#define PIN_PC4 68 +#define PIN_PC4__GPIO PINMUX_PIN(PIN_PC4, 0, 0) +#define PIN_PC4__LCDDISP PINMUX_PIN(PIN_PC4, 1, 1) +#define PIN_PC4__NWR1_NBS1 PINMUX_PIN(PIN_PC4, 2, 1) +#define PIN_PC4__TIOB1 PINMUX_PIN(PIN_PC4, 3, 1) +#define PIN_PC4__SPI1_NPCS0 PINMUX_PIN(PIN_PC4, 4, 1) +#define PIN_PC4__I2SC0_DI0 PINMUX_PIN(PIN_PC4, 5, 1) +#define PIN_PC4__ISC_PCK PINMUX_PIN(PIN_PC4, 6, 3) +#define PIN_PC5 69 +#define PIN_PC5__GPIO PINMUX_PIN(PIN_PC5, 0, 0) +#define PIN_PC5__LCDVSYNC PINMUX_PIN(PIN_PC5, 1, 1) +#define PIN_PC5__NCS0 PINMUX_PIN(PIN_PC5, 2, 1) +#define PIN_PC5__TCLK1 PINMUX_PIN(PIN_PC5, 3, 1) +#define PIN_PC5__SPI1_NPCS1 PINMUX_PIN(PIN_PC5, 4, 1) +#define PIN_PC5__I2SC0_DO0 PINMUX_PIN(PIN_PC5, 5, 1) +#define PIN_PC5__ISC_VSYNC PINMUX_PIN(PIN_PC5, 6, 3) +#define PIN_PC6 70 +#define PIN_PC6__GPIO PINMUX_PIN(PIN_PC6, 0, 0) +#define PIN_PC6__LCDHSYNC PINMUX_PIN(PIN_PC6, 1, 1) +#define PIN_PC6__NCS1 PINMUX_PIN(PIN_PC6, 2, 1) +#define PIN_PC6__TWD1 PINMUX_PIN(PIN_PC6, 3, 1) +#define PIN_PC6__SPI1_NPCS2 PINMUX_PIN(PIN_PC6, 4, 1) +#define PIN_PC6__ISC_HSYNC PINMUX_PIN(PIN_PC6, 6, 3) +#define PIN_PC7 71 +#define PIN_PC7__GPIO PINMUX_PIN(PIN_PC7, 0, 0) +#define PIN_PC7__LCDPCK PINMUX_PIN(PIN_PC7, 1, 1) +#define PIN_PC7__NCS2 PINMUX_PIN(PIN_PC7, 2, 1) +#define PIN_PC7__TWCK1 PINMUX_PIN(PIN_PC7, 3, 1) +#define PIN_PC7__SPI1_NPCS3 PINMUX_PIN(PIN_PC7, 4, 1) +#define PIN_PC7__URXD1 PINMUX_PIN(PIN_PC7, 5, 2) +#define PIN_PC7__ISC_MCK PINMUX_PIN(PIN_PC7, 6, 3) +#define PIN_PC8 72 +#define PIN_PC8__GPIO PINMUX_PIN(PIN_PC8, 0, 0) +#define PIN_PC8__LCDDEN PINMUX_PIN(PIN_PC8, 1, 1) +#define PIN_PC8__NANDRDY PINMUX_PIN(PIN_PC8, 2, 1) +#define PIN_PC8__FIQ PINMUX_PIN(PIN_PC8, 3, 1) +#define PIN_PC8__PCK0 PINMUX_PIN(PIN_PC8, 4, 3) +#define PIN_PC8__UTXD1 PINMUX_PIN(PIN_PC8, 5, 2) +#define PIN_PC8__ISC_FIELD PINMUX_PIN(PIN_PC8, 6, 3) +#define PIN_PC9 73 +#define PIN_PC9__GPIO PINMUX_PIN(PIN_PC9, 0, 0) +#define PIN_PC9__FIQ PINMUX_PIN(PIN_PC9, 1, 3) +#define PIN_PC9__GTSUCOMP PINMUX_PIN(PIN_PC9, 2, 1) +#define PIN_PC9__ISC_D0 PINMUX_PIN(PIN_PC9, 2, 1) +#define PIN_PC9__TIOA4 PINMUX_PIN(PIN_PC9, 4, 2) +#define PIN_PC10 74 +#define PIN_PC10__GPIO PINMUX_PIN(PIN_PC10, 0, 0) +#define PIN_PC10__LCDDAT2 PINMUX_PIN(PIN_PC10, 1, 2) +#define PIN_PC10__GTXCK PINMUX_PIN(PIN_PC10, 2, 1) +#define PIN_PC10__ISC_D1 PINMUX_PIN(PIN_PC10, 3, 1) +#define PIN_PC10__TIOB4 PINMUX_PIN(PIN_PC10, 4, 2) +#define PIN_PC10__CANTX0 PINMUX_PIN(PIN_PC10, 5, 2) +#define PIN_PC11 75 +#define PIN_PC11__GPIO PINMUX_PIN(PIN_PC11, 0, 0) +#define PIN_PC11__LCDDAT3 PINMUX_PIN(PIN_PC11, 1, 2) +#define PIN_PC11__GTXEN PINMUX_PIN(PIN_PC11, 2, 1) +#define PIN_PC11__ISC_D2 PINMUX_PIN(PIN_PC11, 3, 1) +#define PIN_PC11__TCLK4 PINMUX_PIN(PIN_PC11, 4, 2) +#define PIN_PC11__CANRX0 PINMUX_PIN(PIN_PC11, 5, 2) +#define PIN_PC11__A0_NBS0 PINMUX_PIN(PIN_PC11, 6, 2) +#define PIN_PC12 76 +#define PIN_PC12__GPIO PINMUX_PIN(PIN_PC12, 0, 0) +#define PIN_PC12__LCDDAT4 PINMUX_PIN(PIN_PC12, 1, 2) +#define PIN_PC12__GRXDV PINMUX_PIN(PIN_PC12, 2, 1) +#define PIN_PC12__ISC_D3 PINMUX_PIN(PIN_PC12, 3, 1) +#define PIN_PC12__URXD3 PINMUX_PIN(PIN_PC12, 4, 1) +#define PIN_PC12__TK0 PINMUX_PIN(PIN_PC12, 5, 2) +#define PIN_PC12__A1 PINMUX_PIN(PIN_PC12, 6, 2) +#define PIN_PC13 77 +#define PIN_PC13__GPIO PINMUX_PIN(PIN_PC13, 0, 0) +#define PIN_PC13__LCDDAT5 PINMUX_PIN(PIN_PC13, 1, 2) +#define PIN_PC13__GRXER PINMUX_PIN(PIN_PC13, 2, 1) +#define PIN_PC13__ISC_D4 PINMUX_PIN(PIN_PC13, 3, 1) +#define PIN_PC13__UTXD3 PINMUX_PIN(PIN_PC13, 4, 1) +#define PIN_PC13__TF0 PINMUX_PIN(PIN_PC13, 5, 2) +#define PIN_PC13__A2 PINMUX_PIN(PIN_PC13, 6, 2) +#define PIN_PC14 78 +#define PIN_PC14__GPIO PINMUX_PIN(PIN_PC14, 0, 0) +#define PIN_PC14__LCDDAT6 PINMUX_PIN(PIN_PC14, 1, 2) +#define PIN_PC14__GRX0 PINMUX_PIN(PIN_PC14, 2, 1) +#define PIN_PC14__ISC_D5 PINMUX_PIN(PIN_PC14, 3, 1) +#define PIN_PC14__TDO PINMUX_PIN(PIN_PC14, 5, 2) +#define PIN_PC14__A3 PINMUX_PIN(PIN_PC14, 6, 2) +#define PIN_PC15 79 +#define PIN_PC15__GPIO PINMUX_PIN(PIN_PC15, 0, 0) +#define PIN_PC15__LCDDAT7 PINMUX_PIN(PIN_PC15, 1, 2) +#define PIN_PC15__GRX1 PINMUX_PIN(PIN_PC15, 2, 1) +#define PIN_PC15__ISC_D6 PINMUX_PIN(PIN_PC15, 3, 1) +#define PIN_PC15__RD0 PINMUX_PIN(PIN_PC15, 5, 2) +#define PIN_PC15__A4 PINMUX_PIN(PIN_PC15, 6, 2) +#define PIN_PC16 80 +#define PIN_PC16__GPIO PINMUX_PIN(PIN_PC16, 0, 0) +#define PIN_PC16__LCDDAT10 PINMUX_PIN(PIN_PC16, 1, 2) +#define PIN_PC16__GTX0 PINMUX_PIN(PIN_PC16, 2, 1) +#define PIN_PC16__ISC_D7 PINMUX_PIN(PIN_PC16, 3, 1) +#define PIN_PC16__RK0 PINMUX_PIN(PIN_PC16, 5, 2) +#define PIN_PC16__A5 PINMUX_PIN(PIN_PC16, 6, 2) +#define PIN_PC17 81 +#define PIN_PC17__GPIO PINMUX_PIN(PIN_PC17, 0, 0) +#define PIN_PC17__LCDDAT11 PINMUX_PIN(PIN_PC17, 1, 2) +#define PIN_PC17__GTX1 PINMUX_PIN(PIN_PC17, 2, 1) +#define PIN_PC17__ISC_D8 PINMUX_PIN(PIN_PC17, 3, 1) +#define PIN_PC17__RF0 PINMUX_PIN(PIN_PC17, 5, 2) +#define PIN_PC17__A6 PINMUX_PIN(PIN_PC17, 6, 2) +#define PIN_PC18 82 +#define PIN_PC18__GPIO PINMUX_PIN(PIN_PC18, 0, 0) +#define PIN_PC18__LCDDAT12 PINMUX_PIN(PIN_PC18, 1, 2) +#define PIN_PC18__GMDC PINMUX_PIN(PIN_PC18, 2, 1) +#define PIN_PC18__ISC_D9 PINMUX_PIN(PIN_PC18, 3, 1) +#define PIN_PC18__FLEXCOM3_IO2 PINMUX_PIN(PIN_PC18, 5, 2) +#define PIN_PC18__A7 PINMUX_PIN(PIN_PC18, 6, 2) +#define PIN_PC19 83 +#define PIN_PC19__GPIO PINMUX_PIN(PIN_PC19, 0, 0) +#define PIN_PC19__LCDDAT13 PINMUX_PIN(PIN_PC19, 1, 2) +#define PIN_PC19__GMDIO PINMUX_PIN(PIN_PC19, 2, 1) +#define PIN_PC19__ISC_D10 PINMUX_PIN(PIN_PC19, 3, 1) +#define PIN_PC19__FLEXCOM3_IO1 PINMUX_PIN(PIN_PC19, 5, 2) +#define PIN_PC19__A8 PINMUX_PIN(PIN_PC19, 6, 2) +#define PIN_PC20 84 +#define PIN_PC20__GPIO PINMUX_PIN(PIN_PC20, 0, 0) +#define PIN_PC20__LCDDAT14 PINMUX_PIN(PIN_PC20, 1, 2) +#define PIN_PC20__GRXCK PINMUX_PIN(PIN_PC20, 2, 1) +#define PIN_PC20__ISC_D11 PINMUX_PIN(PIN_PC20, 3, 1) +#define PIN_PC20__FLEXCOM3_IO0 PINMUX_PIN(PIN_PC20, 5, 2) +#define PIN_PC20__A9 PINMUX_PIN(PIN_PC20, 6, 2) +#define PIN_PC21 85 +#define PIN_PC21__GPIO PINMUX_PIN(PIN_PC21, 0, 0) +#define PIN_PC21__LCDDAT15 PINMUX_PIN(PIN_PC21, 1, 2) +#define PIN_PC21__GTXER PINMUX_PIN(PIN_PC21, 2, 1) +#define PIN_PC21__ISC_PCK PINMUX_PIN(PIN_PC21, 3, 1) +#define PIN_PC21__FLEXCOM3_IO3 PINMUX_PIN(PIN_PC21, 5, 2) +#define PIN_PC21__A10 PINMUX_PIN(PIN_PC21, 6, 2) +#define PIN_PC22 86 +#define PIN_PC22__GPIO PINMUX_PIN(PIN_PC22, 0, 0) +#define PIN_PC22__LCDDAT18 PINMUX_PIN(PIN_PC22, 1, 2) +#define PIN_PC22__GCRS PINMUX_PIN(PIN_PC22, 2, 1) +#define PIN_PC22__ISC_VSYNC PINMUX_PIN(PIN_PC22, 3, 1) +#define PIN_PC22__FLEXCOM3_IO4 PINMUX_PIN(PIN_PC22, 5, 2) +#define PIN_PC22__A11 PINMUX_PIN(PIN_PC22, 6, 2) +#define PIN_PC23 87 +#define PIN_PC23__GPIO PINMUX_PIN(PIN_PC23, 0, 0) +#define PIN_PC23__LCDDAT19 PINMUX_PIN(PIN_PC23, 1, 2) +#define PIN_PC23__GCOL PINMUX_PIN(PIN_PC23, 2, 1) +#define PIN_PC23__ISC_HSYNC PINMUX_PIN(PIN_PC23, 3, 1) +#define PIN_PC23__A12 PINMUX_PIN(PIN_PC23, 6, 2) +#define PIN_PC24 88 +#define PIN_PC24__GPIO PINMUX_PIN(PIN_PC24, 0, 0) +#define PIN_PC24__LCDDAT20 PINMUX_PIN(PIN_PC24, 1, 2) +#define PIN_PC24__GRX2 PINMUX_PIN(PIN_PC24, 2, 1) +#define PIN_PC24__ISC_MCK PINMUX_PIN(PIN_PC24, 3, 1) +#define PIN_PC24__A13 PINMUX_PIN(PIN_PC24, 6, 2) +#define PIN_PC25 89 +#define PIN_PC25__GPIO PINMUX_PIN(PIN_PC25, 0, 0) +#define PIN_PC25__LCDDAT21 PINMUX_PIN(PIN_PC25, 1, 2) +#define PIN_PC25__GRX3 PINMUX_PIN(PIN_PC25, 2, 1) +#define PIN_PC25__ISC_FIELD PINMUX_PIN(PIN_PC25, 3, 1) +#define PIN_PC25__A14 PINMUX_PIN(PIN_PC25, 6, 2) +#define PIN_PC26 90 +#define PIN_PC26__GPIO PINMUX_PIN(PIN_PC26, 0, 0) +#define PIN_PC26__LCDDAT22 PINMUX_PIN(PIN_PC26, 1, 2) +#define PIN_PC26__GTX2 PINMUX_PIN(PIN_PC26, 2, 1) +#define PIN_PC26__CANTX1 PINMUX_PIN(PIN_PC26, 4, 1) +#define PIN_PC26__A15 PINMUX_PIN(PIN_PC26, 6, 2) +#define PIN_PC27 91 +#define PIN_PC27__GPIO PINMUX_PIN(PIN_PC27, 0, 0) +#define PIN_PC27__LCDDAT23 PINMUX_PIN(PIN_PC27, 1, 2) +#define PIN_PC27__GTX3 PINMUX_PIN(PIN_PC27, 2, 1) +#define PIN_PC27__PCK1 PINMUX_PIN(PIN_PC27, 3, 2) +#define PIN_PC27__CANRX1 PINMUX_PIN(PIN_PC27, 4, 1) +#define PIN_PC27__TWD0 PINMUX_PIN(PIN_PC27, 5, 2) +#define PIN_PC27__A16 PINMUX_PIN(PIN_PC27, 6, 2) +#define PIN_PC28 92 +#define PIN_PC28__GPIO PINMUX_PIN(PIN_PC28, 0, 0) +#define PIN_PC28__LCDPWM PINMUX_PIN(PIN_PC28, 1, 2) +#define PIN_PC28__FLEXCOM4_IO0 PINMUX_PIN(PIN_PC28, 2, 1) +#define PIN_PC28__PCK2 PINMUX_PIN(PIN_PC28, 3, 2) +#define PIN_PC28__TWCK0 PINMUX_PIN(PIN_PC28, 5, 2) +#define PIN_PC28__A17 PINMUX_PIN(PIN_PC28, 6, 2) +#define PIN_PC29 93 +#define PIN_PC29__GPIO PINMUX_PIN(PIN_PC29, 0, 0) +#define PIN_PC29__LCDDISP PINMUX_PIN(PIN_PC29, 1, 2) +#define PIN_PC29__FLEXCOM4_IO1 PINMUX_PIN(PIN_PC29, 2, 1) +#define PIN_PC29__A18 PINMUX_PIN(PIN_PC29, 6, 2) +#define PIN_PC30 94 +#define PIN_PC30__GPIO PINMUX_PIN(PIN_PC30, 0, 0) +#define PIN_PC30__LCDVSYNC PINMUX_PIN(PIN_PC30, 1, 2) +#define PIN_PC30__FLEXCOM4_IO2 PINMUX_PIN(PIN_PC30, 2, 1) +#define PIN_PC30__A19 PINMUX_PIN(PIN_PC30, 6, 2) +#define PIN_PC31 95 +#define PIN_PC31__GPIO PINMUX_PIN(PIN_PC31, 0, 0) +#define PIN_PC31__LCDHSYNC PINMUX_PIN(PIN_PC31, 1, 2) +#define PIN_PC31__FLEXCOM4_IO3 PINMUX_PIN(PIN_PC31, 2, 1) +#define PIN_PC31__URXD3 PINMUX_PIN(PIN_PC31, 3, 2) +#define PIN_PC31__A20 PINMUX_PIN(PIN_PC31, 6, 2) +#define PIN_PD0 96 +#define PIN_PD0__GPIO PINMUX_PIN(PIN_PD0, 0, 0) +#define PIN_PD0__LCDPCK PINMUX_PIN(PIN_PD0, 1, 2) +#define PIN_PD0__FLEXCOM4_IO4 PINMUX_PIN(PIN_PD0, 2, 1) +#define PIN_PD0__UTXD3 PINMUX_PIN(PIN_PD0, 3, 2) +#define PIN_PD0__GTSUCOMP PINMUX_PIN(PIN_PD0, 4, 2) +#define PIN_PD0__A23 PINMUX_PIN(PIN_PD0, 6, 2) +#define PIN_PD1 97 +#define PIN_PD1__GPIO PINMUX_PIN(PIN_PD1, 0, 0) +#define PIN_PD1__LCDDEN PINMUX_PIN(PIN_PD1, 1, 2) +#define PIN_PD1__GRXCK PINMUX_PIN(PIN_PD1, 4, 2) +#define PIN_PD1__A24 PINMUX_PIN(PIN_PD1, 6, 2) +#define PIN_PD2 98 +#define PIN_PD2__GPIO PINMUX_PIN(PIN_PD2, 0, 0) +#define PIN_PD2__URXD1 PINMUX_PIN(PIN_PD2, 1, 1) +#define PIN_PD2__GTXER PINMUX_PIN(PIN_PD2, 4, 2) +#define PIN_PD2__ISC_MCK PINMUX_PIN(PIN_PD2, 5, 2) +#define PIN_PD2__A25 PINMUX_PIN(PIN_PD2, 6, 2) +#define PIN_PD3 99 +#define PIN_PD3__GPIO PINMUX_PIN(PIN_PD3, 0, 0) +#define PIN_PD3__UTXD1 PINMUX_PIN(PIN_PD3, 1, 1) +#define PIN_PD3__FIQ PINMUX_PIN(PIN_PD3, 2, 2) +#define PIN_PD3__GCRS PINMUX_PIN(PIN_PD3, 4, 2) +#define PIN_PD3__ISC_D11 PINMUX_PIN(PIN_PD3, 5, 2) +#define PIN_PD3__NWAIT PINMUX_PIN(PIN_PD3, 6, 2) +#define PIN_PD4 100 +#define PIN_PD4__GPIO PINMUX_PIN(PIN_PD4, 0, 0) +#define PIN_PD4__TWD1 PINMUX_PIN(PIN_PD4, 1, 2) +#define PIN_PD4__URXD2 PINMUX_PIN(PIN_PD4, 2, 1) +#define PIN_PD4__GCOL PINMUX_PIN(PIN_PD4, 4, 2) +#define PIN_PD4__ISC_D10 PINMUX_PIN(PIN_PD4, 5, 2) +#define PIN_PD4__NCS0 PINMUX_PIN(PIN_PD4, 6, 2) +#define PIN_PD5 101 +#define PIN_PD5__GPIO PINMUX_PIN(PIN_PD5, 0, 0) +#define PIN_PD5__TWCK1 PINMUX_PIN(PIN_PD5, 1, 2) +#define PIN_PD5__UTXD2 PINMUX_PIN(PIN_PD5, 2, 1) +#define PIN_PD5__GRX2 PINMUX_PIN(PIN_PD5, 4, 2) +#define PIN_PD5__ISC_D9 PINMUX_PIN(PIN_PD5, 5, 2) +#define PIN_PD5__NCS1 PINMUX_PIN(PIN_PD5, 6, 2) +#define PIN_PD6 102 +#define PIN_PD6__GPIO PINMUX_PIN(PIN_PD6, 0, 0) +#define PIN_PD6__TCK PINMUX_PIN(PIN_PD6, 1, 2) +#define PIN_PD6__PCK1 PINMUX_PIN(PIN_PD6, 2, 1) +#define PIN_PD6__GRX3 PINMUX_PIN(PIN_PD6, 4, 2) +#define PIN_PD6__ISC_D8 PINMUX_PIN(PIN_PD6, 5, 2) +#define PIN_PD6__NCS2 PINMUX_PIN(PIN_PD6, 6, 2) +#define PIN_PD7 103 +#define PIN_PD7__GPIO PINMUX_PIN(PIN_PD7, 0, 0) +#define PIN_PD7__TDI PINMUX_PIN(PIN_PD7, 1, 2) +#define PIN_PD7__UTMI_RXVAL PINMUX_PIN(PIN_PD7, 3, 1) +#define PIN_PD7__GTX2 PINMUX_PIN(PIN_PD7, 4, 2) +#define PIN_PD7__ISC_D0 PINMUX_PIN(PIN_PD7, 5, 2) +#define PIN_PD7__NWR1_NBS1 PINMUX_PIN(PIN_PD7, 6, 2) +#define PIN_PD8 104 +#define PIN_PD8__GPIO PINMUX_PIN(PIN_PD8, 0, 0) +#define PIN_PD8__TDO PINMUX_PIN(PIN_PD8, 1, 2) +#define PIN_PD8__UTMI_RXERR PINMUX_PIN(PIN_PD8, 3, 1) +#define PIN_PD8__GTX3 PINMUX_PIN(PIN_PD8, 4, 2) +#define PIN_PD8__ISC_D1 PINMUX_PIN(PIN_PD8, 5, 2) +#define PIN_PD8__NANDRDY PINMUX_PIN(PIN_PD8, 6, 2) +#define PIN_PD9 105 +#define PIN_PD9__GPIO PINMUX_PIN(PIN_PD9, 0, 0) +#define PIN_PD9__TMS PINMUX_PIN(PIN_PD9, 1, 2) +#define PIN_PD9__UTMI_RXACT PINMUX_PIN(PIN_PD9, 3, 1) +#define PIN_PD9__GTXCK PINMUX_PIN(PIN_PD9, 4, 2) +#define PIN_PD9__ISC_D2 PINMUX_PIN(PIN_PD9, 5, 2) +#define PIN_PD10 106 +#define PIN_PD10__GPIO PINMUX_PIN(PIN_PD10, 0, 0) +#define PIN_PD10__NTRST PINMUX_PIN(PIN_PD10, 1, 2) +#define PIN_PD10__UTMI_HDIS PINMUX_PIN(PIN_PD10, 3, 1) +#define PIN_PD10__GTXEN PINMUX_PIN(PIN_PD10, 4, 2) +#define PIN_PD10__ISC_D3 PINMUX_PIN(PIN_PD10, 5, 2) +#define PIN_PD11 107 +#define PIN_PD11__GPIO PINMUX_PIN(PIN_PD11, 0, 0) +#define PIN_PD11__TIOA1 PINMUX_PIN(PIN_PD11, 1, 3) +#define PIN_PD11__PCK2 PINMUX_PIN(PIN_PD11, 2, 2) +#define PIN_PD11__UTMI_LS0 PINMUX_PIN(PIN_PD11, 3, 1) +#define PIN_PD11__GRXDV PINMUX_PIN(PIN_PD11, 4, 2) +#define PIN_PD11__ISC_D4 PINMUX_PIN(PIN_PD11, 5, 2) +#define PIN_PD11__ISC_MCK PINMUX_PIN(PIN_PD11, 7, 4) +#define PIN_PD12 108 +#define PIN_PD12__GPIO PINMUX_PIN(PIN_PD12, 0, 0) +#define PIN_PD12__TIOB1 PINMUX_PIN(PIN_PD12, 1, 3) +#define PIN_PD12__FLEXCOM4_IO0 PINMUX_PIN(PIN_PD12, 2, 2) +#define PIN_PD12__UTMI_LS1 PINMUX_PIN(PIN_PD12, 3, 1) +#define PIN_PD12__GRXER PINMUX_PIN(PIN_PD12, 4, 2) +#define PIN_PD12__ISC_D5 PINMUX_PIN(PIN_PD12, 5, 2) +#define PIN_PD12__ISC_D4 PINMUX_PIN(PIN_PD12, 6, 4) +#define PIN_PD13 109 +#define PIN_PD13__GPIO PINMUX_PIN(PIN_PD13, 0, 0) +#define PIN_PD13__TCLK1 PINMUX_PIN(PIN_PD13, 1, 3) +#define PIN_PD13__FLEXCOM4_IO1 PINMUX_PIN(PIN_PD13, 2, 2) +#define PIN_PD13__UTMI_CDRPCSEL0 PINMUX_PIN(PIN_PD13, 3, 1) +#define PIN_PD13__GRX0 PINMUX_PIN(PIN_PD13, 4, 2) +#define PIN_PD13__ISC_D6 PINMUX_PIN(PIN_PD13, 5, 2) +#define PIN_PD13__ISC_D5 PINMUX_PIN(PIN_PD13, 6, 4) +#define PIN_PD14 110 +#define PIN_PD14__GPIO PINMUX_PIN(PIN_PD14, 0, 0) +#define PIN_PD14__TCK PINMUX_PIN(PIN_PD14, 1, 1) +#define PIN_PD14__FLEXCOM4_IO2 PINMUX_PIN(PIN_PD14, 2, 2) +#define PIN_PD14__UTMI_CDRPCSEL1 PINMUX_PIN(PIN_PD14, 3, 1) +#define PIN_PD14__GRX1 PINMUX_PIN(PIN_PD14, 4, 2) +#define PIN_PD14__ISC_D7 PINMUX_PIN(PIN_PD14, 5, 2) +#define PIN_PD14__ISC_D6 PINMUX_PIN(PIN_PD14, 6, 4) +#define PIN_PD15 111 +#define PIN_PD15__GPIO PINMUX_PIN(PIN_PD15, 0, 0) +#define PIN_PD15__TDI PINMUX_PIN(PIN_PD15, 1, 1) +#define PIN_PD15__FLEXCOM4_IO3 PINMUX_PIN(PIN_PD15, 2, 2) +#define PIN_PD15__UTMI_CDRCPDIVEN PINMUX_PIN(PIN_PD15, 3, 1) +#define PIN_PD15__GTX0 PINMUX_PIN(PIN_PD15, 4, 2) +#define PIN_PD15__ISC_PCK PINMUX_PIN(PIN_PD15, 5, 2) +#define PIN_PD15__ISC_D7 PINMUX_PIN(PIN_PD15, 6, 4) +#define PIN_PD16 112 +#define PIN_PD16__GPIO PINMUX_PIN(PIN_PD16, 0, 0) +#define PIN_PD16__TDO PINMUX_PIN(PIN_PD16, 1, 1) +#define PIN_PD16__FLEXCOM4_IO4 PINMUX_PIN(PIN_PD16, 2, 2) +#define PIN_PD16__UTMI_CDRBISTEN PINMUX_PIN(PIN_PD16, 3, 1) +#define PIN_PD16__GTX1 PINMUX_PIN(PIN_PD16, 4, 2) +#define PIN_PD16__ISC_VSYNC PINMUX_PIN(PIN_PD16, 5, 2) +#define PIN_PD16__ISC_D8 PINMUX_PIN(PIN_PD16, 6, 4) +#define PIN_PD17 113 +#define PIN_PD17__GPIO PINMUX_PIN(PIN_PD17, 0, 0) +#define PIN_PD17__TMS PINMUX_PIN(PIN_PD17, 1, 1) +#define PIN_PD17__UTMI_CDRCPSELDIV PINMUX_PIN(PIN_PD17, 3, 1) +#define PIN_PD17__GMDC PINMUX_PIN(PIN_PD17, 4, 2) +#define PIN_PD17__ISC_HSYNC PINMUX_PIN(PIN_PD17, 5, 2) +#define PIN_PD17__ISC_D9 PINMUX_PIN(PIN_PD17, 6, 4) +#define PIN_PD18 114 +#define PIN_PD18__GPIO PINMUX_PIN(PIN_PD18, 0, 0) +#define PIN_PD18__NTRST PINMUX_PIN(PIN_PD18, 1, 1) +#define PIN_PD18__GMDIO PINMUX_PIN(PIN_PD18, 4, 2) +#define PIN_PD18__ISC_FIELD PINMUX_PIN(PIN_PD18, 5, 2) +#define PIN_PD18__ISC_D10 PINMUX_PIN(PIN_PD18, 6, 4) +#define PIN_PD19 115 +#define PIN_PD19__GPIO PINMUX_PIN(PIN_PD19, 0, 0) +#define PIN_PD19__PCK0 PINMUX_PIN(PIN_PD19, 1, 1) +#define PIN_PD19__TWD1 PINMUX_PIN(PIN_PD19, 2, 3) +#define PIN_PD19__URXD2 PINMUX_PIN(PIN_PD19, 3, 3) +#define PIN_PD19__I2SC0_CK PINMUX_PIN(PIN_PD19, 5, 2) +#define PIN_PD19__ISC_D11 PINMUX_PIN(PIN_PD19, 6, 4) +#define PIN_PD20 116 +#define PIN_PD20__GPIO PINMUX_PIN(PIN_PD20, 0, 0) +#define PIN_PD20__TIOA2 PINMUX_PIN(PIN_PD20, 1, 3) +#define PIN_PD20__TWCK1 PINMUX_PIN(PIN_PD20, 2, 3) +#define PIN_PD20__UTXD2 PINMUX_PIN(PIN_PD20, 3, 3) +#define PIN_PD20__I2SC0_MCK PINMUX_PIN(PIN_PD20, 5, 2) +#define PIN_PD20__ISC_PCK PINMUX_PIN(PIN_PD20, 6, 4) +#define PIN_PD21 117 +#define PIN_PD21__GPIO PINMUX_PIN(PIN_PD21, 0, 0) +#define PIN_PD21__TIOB2 PINMUX_PIN(PIN_PD21, 1, 3) +#define PIN_PD21__TWD0 PINMUX_PIN(PIN_PD21, 2, 4) +#define PIN_PD21__FLEXCOM4_IO0 PINMUX_PIN(PIN_PD21, 3, 3) +#define PIN_PD21__I2SC0_WS PINMUX_PIN(PIN_PD21, 5, 2) +#define PIN_PD21__ISC_VSYNC PINMUX_PIN(PIN_PD21, 6, 4) +#define PIN_PD22 118 +#define PIN_PD22__GPIO PINMUX_PIN(PIN_PD22, 0, 0) +#define PIN_PD22__TCLK2 PINMUX_PIN(PIN_PD22, 1, 3) +#define PIN_PD22__TWCK0 PINMUX_PIN(PIN_PD22, 2, 4) +#define PIN_PD22__FLEXCOM4_IO1 PINMUX_PIN(PIN_PD22, 3, 3) +#define PIN_PD22__I2SC0_DI0 PINMUX_PIN(PIN_PD22, 5, 2) +#define PIN_PD22__ISC_HSYNC PINMUX_PIN(PIN_PD22, 6, 4) +#define PIN_PD23 119 +#define PIN_PD23__GPIO PINMUX_PIN(PIN_PD23, 0, 0) +#define PIN_PD23__URXD2 PINMUX_PIN(PIN_PD23, 1, 2) +#define PIN_PD23__FLEXCOM4_IO2 PINMUX_PIN(PIN_PD23, 3, 3) +#define PIN_PD23__I2SC0_DO0 PINMUX_PIN(PIN_PD23, 5, 2) +#define PIN_PD23__ISC_FIELD PINMUX_PIN(PIN_PD23, 6, 4) +#define PIN_PD24 120 +#define PIN_PD24__GPIO PINMUX_PIN(PIN_PD24, 0, 0) +#define PIN_PD24__UTXD2 PINMUX_PIN(PIN_PD23, 1, 2) +#define PIN_PD24__FLEXCOM4_IO3 PINMUX_PIN(PIN_PD23, 3, 3) +#define PIN_PD25 121 +#define PIN_PD25__GPIO PINMUX_PIN(PIN_PD25, 0, 0) +#define PIN_PD25__SPI1_SPCK PINMUX_PIN(PIN_PD25, 1, 3) +#define PIN_PD25__FLEXCOM4_IO4 PINMUX_PIN(PIN_PD25, 3, 3) +#define PIN_PD26 122 +#define PIN_PD26__GPIO PINMUX_PIN(PIN_PD26, 0, 0) +#define PIN_PD26__SPI1_MOSI PINMUX_PIN(PIN_PD26, 1, 3) +#define PIN_PD26__FLEXCOM2_IO0 PINMUX_PIN(PIN_PD26, 3, 2) +#define PIN_PD27 123 +#define PIN_PD27__GPIO PINMUX_PIN(PIN_PD27, 0, 0) +#define PIN_PD27__SPI1_MISO PINMUX_PIN(PIN_PD27, 1, 3) +#define PIN_PD27__TCK PINMUX_PIN(PIN_PD27, 2, 3) +#define PIN_PD27__FLEXCOM2_IO1 PINMUX_PIN(PIN_PD27, 3, 2) +#define PIN_PD28 124 +#define PIN_PD28__GPIO PINMUX_PIN(PIN_PD28, 0, 0) +#define PIN_PD28__SPI1_NPCS0 PINMUX_PIN(PIN_PD28, 1, 3) +#define PIN_PD28__TCI PINMUX_PIN(PIN_PD28, 2, 3) +#define PIN_PD28__FLEXCOM2_IO2 PINMUX_PIN(PIN_PD28, 3, 2) +#define PIN_PD29 125 +#define PIN_PD29__GPIO PINMUX_PIN(PIN_PD29, 0, 0) +#define PIN_PD29__SPI1_NPCS1 PINMUX_PIN(PIN_PD29, 1, 3) +#define PIN_PD29__TDO PINMUX_PIN(PIN_PD29, 2, 3) +#define PIN_PD29__FLEXCOM2_IO3 PINMUX_PIN(PIN_PD29, 3, 2) +#define PIN_PD29__TIOA3 PINMUX_PIN(PIN_PD29, 4, 3) +#define PIN_PD29__TWD0 PINMUX_PIN(PIN_PD29, 5, 3) +#define PIN_PD30 126 +#define PIN_PD30__GPIO PINMUX_PIN(PIN_PD30, 0, 0) +#define PIN_PD30__SPI1_NPCS2 PINMUX_PIN(PIN_PD30, 1, 3) +#define PIN_PD30__TMS PINMUX_PIN(PIN_PD30, 2, 3) +#define PIN_PD30__FLEXCOM2_IO4 PINMUX_PIN(PIN_PD30, 3, 2) +#define PIN_PD30__TIOB3 PINMUX_PIN(PIN_PD30, 4, 3) +#define PIN_PD30__TWCK0 PINMUX_PIN(PIN_PD30, 5, 3) +#define PIN_PD31 127 +#define PIN_PD31__GPIO PINMUX_PIN(PIN_PD31, 0, 0) +#define PIN_PD31__ADTRG PINMUX_PIN(PIN_PD31, 1, 1) +#define PIN_PD31__NTRST PINMUX_PIN(PIN_PD31, 2, 3) +#define PIN_PD31__IRQ PINMUX_PIN(PIN_PD31, 3, 4) +#define PIN_PD31__TCLK3 PINMUX_PIN(PIN_PD31, 4, 3) +#define PIN_PD31__PCK0 PINMUX_PIN(PIN_PD31, 5, 2) -- cgit v0.10.2 From a9b672a636a599cc052afcb6837e3177dc53c143 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Wed, 16 Sep 2015 17:37:03 +0200 Subject: ARM: at91/dt: sama5d2 Xplained: add device pin muxing Add device pin muxing for the sama5d2 Xplained board. Signed-off-by: Ludovic Desroches Acked-by: Linus Walleij Signed-off-by: Nicolas Ferre diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts index e8d63afd..dc23979 100644 --- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts +++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts @@ -44,6 +44,7 @@ */ /dts-v1/; #include "sama5d2.dtsi" +#include "sama5d2-pinfunc.h" / { model = "Atmel SAMA5D2 Xplained"; @@ -92,6 +93,8 @@ apb { spi0: spi@f8000000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi0_default>; status = "okay"; m25p80@0 { @@ -102,25 +105,35 @@ }; macb0: ethernet@f8008000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_macb0_default>; phy-mode = "rmii"; status = "okay"; }; uart1: serial@f8020000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1_default>; status = "okay"; }; i2c0: i2c@f8028000 { dmas = <0>, <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c0_default>; status = "okay"; }; uart3: serial@fc008000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3_default>; status = "okay"; }; i2c1: i2c@fc028000 { dmas = <0>, <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1_default>; status = "okay"; at24@54 { @@ -129,6 +142,54 @@ pagesize = <16>; }; }; + + pinctrl@fc038000 { + pinctrl_i2c0_default: i2c0_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_i2c1_default: i2c1_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_macb0_default: macb0_default { + pinmux = , + , + , + , + , + , + , + , + , + ; + bias-disable; + }; + + pinctrl_spi0_default: spi0_default { + pinmux = , + , + , + ; + bias-disable; + }; + + pinctrl_uart1_default: uart1_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_uart3_default: uart3_default { + pinmux = , + ; + bias-disable; + }; + }; }; }; }; -- cgit v0.10.2 From 0706f17c307b056ff6f1848320ba82d76945a6ff Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Wed, 23 Sep 2015 16:15:27 +0200 Subject: drm/i915: Avoid race of intel_crt_detect_hotplug() with HPD interrupt, v2 An HPD interrupt may fire while we are in a function that changes the PORT_HOTPLUG_EN register - especially when an HPD interrupt storm occurs. Since the interrupt handler changes the enabled HPD lines when it detects such a storm the read-modify-write cycles may interfere. To avoid this, shiled the rmw cycles with IRQ save spinlocks. Changes since v1: - Implement a function which takes care of accessing PORT_HOTPLUG_EN. Signed-off-by: Egbert Eich Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4e8178d..ba4596e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2742,6 +2742,9 @@ i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv); void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv); +void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv, + uint32_t mask, + uint32_t bits); void ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask); void diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index ca6d806..6ca6c16 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -167,6 +167,44 @@ static const u32 hpd_bxt[HPD_NUM_PINS] = { static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir); +/* For display hotplug interrupt */ +static inline void +i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv, + uint32_t mask, + uint32_t bits) +{ + uint32_t val; + + assert_spin_locked(&dev_priv->irq_lock); + WARN_ON(bits & ~mask); + + val = I915_READ(PORT_HOTPLUG_EN); + val &= ~mask; + val |= bits; + I915_WRITE(PORT_HOTPLUG_EN, val); +} + +/** + * i915_hotplug_interrupt_update - update hotplug interrupt enable + * @dev_priv: driver private + * @mask: bits to update + * @bits: bits to enable + * NOTE: the HPD enable bits are modified both inside and outside + * of an interrupt context. To avoid that read-modify-write cycles + * interfer, these bits are protected by a spinlock. Since this + * function is usually not called from a context where the lock is + * held already, this function acquires the lock itself. A non-locking + * version is also available. + */ +void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv, + uint32_t mask, + uint32_t bits) +{ + spin_lock_irq(&dev_priv->irq_lock); + i915_hotplug_interrupt_update_locked(dev_priv, mask, bits); + spin_unlock_irq(&dev_priv->irq_lock); +} + /** * ilk_update_display_irq - update DEIMR * @dev_priv: driver private @@ -3050,7 +3088,7 @@ static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) { enum pipe pipe; - I915_WRITE(PORT_HOTPLUG_EN, 0); + i915_hotplug_interrupt_update(dev_priv, 0xFFFFFFFF, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); for_each_pipe(dev_priv, pipe) @@ -3466,7 +3504,7 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) { dev_priv->irq_mask = ~0; - I915_WRITE(PORT_HOTPLUG_EN, 0); + i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); POSTING_READ(PORT_HOTPLUG_EN); I915_WRITE(VLV_IIR, 0xffffffff); @@ -3840,7 +3878,7 @@ static void i915_irq_preinstall(struct drm_device * dev) int pipe; if (I915_HAS_HOTPLUG(dev)) { - I915_WRITE(PORT_HOTPLUG_EN, 0); + i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); } @@ -3874,7 +3912,7 @@ static int i915_irq_postinstall(struct drm_device *dev) I915_USER_INTERRUPT; if (I915_HAS_HOTPLUG(dev)) { - I915_WRITE(PORT_HOTPLUG_EN, 0); + i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); POSTING_READ(PORT_HOTPLUG_EN); /* Enable in IER... */ @@ -4036,7 +4074,7 @@ static void i915_irq_uninstall(struct drm_device * dev) int pipe; if (I915_HAS_HOTPLUG(dev)) { - I915_WRITE(PORT_HOTPLUG_EN, 0); + i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); } @@ -4057,7 +4095,7 @@ static void i965_irq_preinstall(struct drm_device * dev) struct drm_i915_private *dev_priv = dev->dev_private; int pipe; - I915_WRITE(PORT_HOTPLUG_EN, 0); + i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); I915_WRITE(HWSTAM, 0xeffe); @@ -4118,7 +4156,7 @@ static int i965_irq_postinstall(struct drm_device *dev) I915_WRITE(IER, enable_mask); POSTING_READ(IER); - I915_WRITE(PORT_HOTPLUG_EN, 0); + i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); POSTING_READ(PORT_HOTPLUG_EN); i915_enable_asle_pipestat(dev); @@ -4133,22 +4171,22 @@ static void i915_hpd_irq_setup(struct drm_device *dev) assert_spin_locked(&dev_priv->irq_lock); - hotplug_en = I915_READ(PORT_HOTPLUG_EN); - hotplug_en &= ~HOTPLUG_INT_EN_MASK; /* Note HDMI and DP share hotplug bits */ /* enable bits are the same for all generations */ - hotplug_en |= intel_hpd_enabled_irqs(dev, hpd_mask_i915); + hotplug_en = intel_hpd_enabled_irqs(dev, hpd_mask_i915); /* Programming the CRT detection parameters tends to generate a spurious hotplug event about three seconds later. So just do it once. */ if (IS_G4X(dev)) hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; - hotplug_en &= ~CRT_HOTPLUG_VOLTAGE_COMPARE_MASK; hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; /* Ignore TV since it's buggy */ - I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); + i915_hotplug_interrupt_update_locked(dev_priv, + (HOTPLUG_INT_EN_MASK + | CRT_HOTPLUG_VOLTAGE_COMPARE_MASK), + hotplug_en); } static irqreturn_t i965_irq_handler(int irq, void *arg) @@ -4261,7 +4299,7 @@ static void i965_irq_uninstall(struct drm_device * dev) if (!dev_priv) return; - I915_WRITE(PORT_HOTPLUG_EN, 0); + i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); I915_WRITE(HWSTAM, 0xffffffff); diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index af5e43b..6ce38e3 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -376,7 +376,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) { struct drm_device *dev = connector->dev; struct drm_i915_private *dev_priv = dev->dev_private; - u32 hotplug_en, orig, stat; + u32 stat; bool ret = false; int i, tries = 0; @@ -395,12 +395,12 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) tries = 2; else tries = 1; - hotplug_en = orig = I915_READ(PORT_HOTPLUG_EN); - hotplug_en |= CRT_HOTPLUG_FORCE_DETECT; for (i = 0; i < tries ; i++) { /* turn on the FORCE_DETECT */ - I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); + i915_hotplug_interrupt_update(dev_priv, + CRT_HOTPLUG_FORCE_DETECT, + CRT_HOTPLUG_FORCE_DETECT); /* wait for FORCE_DETECT to go off */ if (wait_for((I915_READ(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT) == 0, @@ -415,8 +415,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) /* clear the interrupt we just generated, if any */ I915_WRITE(PORT_HOTPLUG_STAT, CRT_HOTPLUG_INT_STATUS); - /* and put the bits back */ - I915_WRITE(PORT_HOTPLUG_EN, orig); + i915_hotplug_interrupt_update(dev_priv, CRT_HOTPLUG_FORCE_DETECT, 0); return ret; } -- cgit v0.10.2 From 53ce81a761fb130c5d7ad653239fc9f9adc32237 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Sep 2015 21:04:38 +0300 Subject: drm/i915: Make sure we don't detect eDP on g4x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't support eDP on g4x, so let's not even look at the VBT to determine the port type, just in case the VBT is bonkers on some g4x machines and indicates the precense of eDP. Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 02401a3..5fe1648 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -5255,6 +5255,13 @@ bool intel_dp_is_edp(struct drm_device *dev, enum port port) [PORT_E] = DVO_PORT_DPE, }; + /* + * eDP not supported on g4x. so bail out early just + * for a bit extra safety in case the VBT is bonkers. + */ + if (INTEL_INFO(dev)->gen < 5) + return false; + if (port == PORT_A) return true; -- cgit v0.10.2 From 972e7d71c82ea70100b808695d5cf735c1df5ef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Sep 2015 21:04:39 +0300 Subject: drm/i915: Ignore "digital output" and "not HDMI output" bits for eDP detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ignore DEVICE_TYPE_NOT_HDMI_OUTPUT and DEVICE_TYPE_DIGITAL_OUTPUT when trying to determine the presence of eDP based on the VBT child device type. Apparently a significant portion of VLV systems have these bits set incorrectly, and so we currently fail to detect eDP on said systems. This is based on an earlier patch [1] from Andreas Lampersperger. Instead of ignoring the bits just on VLV as was done in the orignal patch, we now ignore them for all platforms. We should still have enough bits in there to avoid false positives (unless the VBT is totally bonkers). Quoting the orignal patch: > When the i915.ko identify an eDP output on a valleyview > board, it should be more slackly. The reason for that is, > that BIOS DATA TABLES generated with intel BMP (Binary > Modification Program) do not set bits for NOT_HDMI or > DIGITAL_OUTPUT on the device type. Due to Adolfo > Sanchez from Intel EMGD, this is not possible. > To solve this problem and enable i915.ko on embedded > vlv boards with eDP, we ignore this two bits. [1] http://lists.freedesktop.org/archives/intel-gfx/2015-June/069416.html Cc: Andreas Lampersperger Cc: "Sanchez, AdolfoX" Signed-off-by: Ville Syrjälä Acked-by: Jani Nikula Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 1b7417e..7ec8c9a 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -741,7 +741,6 @@ int intel_parse_bios(struct drm_device *dev); */ #define DEVICE_TYPE_eDP_BITS \ (DEVICE_TYPE_INTERNAL_CONNECTOR | \ - DEVICE_TYPE_NOT_HDMI_OUTPUT | \ DEVICE_TYPE_MIPI_OUTPUT | \ DEVICE_TYPE_COMPOSITE_OUTPUT | \ DEVICE_TYPE_DUAL_CHANNEL | \ @@ -749,7 +748,6 @@ int intel_parse_bios(struct drm_device *dev); DEVICE_TYPE_TMDS_DVI_SIGNALING | \ DEVICE_TYPE_VIDEO_SIGNALING | \ DEVICE_TYPE_DISPLAYPORT_OUTPUT | \ - DEVICE_TYPE_DIGITAL_OUTPUT | \ DEVICE_TYPE_ANALOG_OUTPUT) /* define the DVO port for HDMI output type */ -- cgit v0.10.2 From 8bd864b81a7472a19eb6ed536e028a10e7d71239 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Sep 2015 20:03:14 +0300 Subject: drm/i915: Don't pass sdvo_reg to intel_sdvo_select_{ddc, i2c}_bus() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_sdvo_select_ddc_bus() and intel_sdvo_select_i2c_bus() have no used for the passed in 'reg', so just drop it. Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index ca3dd7c..05521b5 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2222,7 +2222,7 @@ intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo) */ static void intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv, - struct intel_sdvo *sdvo, u32 reg) + struct intel_sdvo *sdvo) { struct sdvo_device_mapping *mapping; @@ -2239,7 +2239,7 @@ intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv, static void intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv, - struct intel_sdvo *sdvo, u32 reg) + struct intel_sdvo *sdvo) { struct sdvo_device_mapping *mapping; u8 pin; @@ -2925,7 +2925,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) intel_sdvo->sdvo_reg = sdvo_reg; intel_sdvo->is_sdvob = is_sdvob; intel_sdvo->slave_addr = intel_sdvo_get_slave_addr(dev, intel_sdvo) >> 1; - intel_sdvo_select_i2c_bus(dev_priv, intel_sdvo, sdvo_reg); + intel_sdvo_select_i2c_bus(dev_priv, intel_sdvo); if (!intel_sdvo_init_ddc_proxy(intel_sdvo, dev)) goto err_i2c_bus; @@ -2987,7 +2987,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) */ intel_sdvo->base.cloneable = 0; - intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg); + intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo); /* Set the input timing to the screen. Assume always input 0. */ if (!intel_sdvo_set_target_input(intel_sdvo)) -- cgit v0.10.2 From 83843d84fcd38a7e9b30ff0b9af04669c77ecf8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Sep 2015 20:03:15 +0300 Subject: drm/i915: Parametrize LRC registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 72ae347..5615d3d 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2069,8 +2069,8 @@ static int i915_execlists(struct seq_file *m, void *data) seq_printf(m, "%s\n", ring->name); - status = I915_READ(RING_EXECLIST_STATUS(ring)); - ctx_id = I915_READ(RING_EXECLIST_STATUS(ring) + 4); + status = I915_READ(RING_EXECLIST_STATUS_LO(ring)); + ctx_id = I915_READ(RING_EXECLIST_STATUS_HI(ring)); seq_printf(m, "\tExeclist status: 0x%08X, context: %u\n", status, ctx_id); @@ -2085,8 +2085,8 @@ static int i915_execlists(struct seq_file *m, void *data) read_pointer, write_pointer); for (i = 0; i < 6; i++) { - status = I915_READ(RING_CONTEXT_STATUS_BUF(ring) + 8*i); - ctx_id = I915_READ(RING_CONTEXT_STATUS_BUF(ring) + 8*i + 4); + status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(ring, i)); + ctx_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(ring, i)); seq_printf(m, "\tStatus buffer %d: 0x%08X, context: %u\n", i, status, ctx_id); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index ff9a481..7417650 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -349,7 +349,7 @@ static void execlists_elsp_write(struct drm_i915_gem_request *rq0, I915_WRITE_FW(RING_ELSP(ring), lower_32_bits(desc[0])); /* ELSP is a wo register, use another nearby reg for posting */ - POSTING_READ_FW(RING_EXECLIST_STATUS(ring)); + POSTING_READ_FW(RING_EXECLIST_STATUS_LO(ring)); intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL); spin_unlock(&dev_priv->uncore.lock); } @@ -519,10 +519,8 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring) while (read_pointer < write_pointer) { read_pointer++; - status = I915_READ(RING_CONTEXT_STATUS_BUF(ring) + - (read_pointer % 6) * 8); - status_id = I915_READ(RING_CONTEXT_STATUS_BUF(ring) + - (read_pointer % 6) * 8 + 4); + status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(ring, read_pointer % 6)); + status_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(ring, read_pointer % 6)); if (status & GEN8_CTX_STATUS_IDLE_ACTIVE) continue; diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index 69d99f0..8a08a27 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -28,12 +28,14 @@ /* Execlists regs */ #define RING_ELSP(ring) ((ring)->mmio_base+0x230) -#define RING_EXECLIST_STATUS(ring) ((ring)->mmio_base+0x234) +#define RING_EXECLIST_STATUS_LO(ring) ((ring)->mmio_base+0x234) +#define RING_EXECLIST_STATUS_HI(ring) ((ring)->mmio_base+0x234 + 4) #define RING_CONTEXT_CONTROL(ring) ((ring)->mmio_base+0x244) #define CTX_CTRL_INHIBIT_SYN_CTX_SWITCH (1 << 3) #define CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT (1 << 0) #define CTX_CTRL_RS_CTX_ENABLE (1 << 1) -#define RING_CONTEXT_STATUS_BUF(ring) ((ring)->mmio_base+0x370) +#define RING_CONTEXT_STATUS_BUF_LO(ring, i) ((ring)->mmio_base+0x370 + (i) * 8) +#define RING_CONTEXT_STATUS_BUF_HI(ring, i) ((ring)->mmio_base+0x370 + (i) * 8 + 4) #define RING_CONTEXT_STATUS_PTR(ring) ((ring)->mmio_base+0x3a0) /* Logical Rings */ -- cgit v0.10.2 From 22dfe79fd9c3951017bd68cad1d3257631307dde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Sep 2015 20:03:16 +0300 Subject: drm/i915: Parametrize GEN7_GT_SCRATCH and GEN7_LRA_LIMITS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index bdec64c..947bd43 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1120,7 +1120,7 @@ static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv) s->gfx_pend_tlb1 = I915_READ(GEN7_GFX_PEND_TLB1); for (i = 0; i < ARRAY_SIZE(s->lra_limits); i++) - s->lra_limits[i] = I915_READ(GEN7_LRA_LIMITS_BASE + i * 4); + s->lra_limits[i] = I915_READ(GEN7_LRA_LIMITS(i)); s->media_max_req_count = I915_READ(GEN7_MEDIA_MAX_REQ_COUNT); s->gfx_max_req_count = I915_READ(GEN7_GFX_MAX_REQ_COUNT); @@ -1164,7 +1164,7 @@ static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv) s->pm_ier = I915_READ(GEN6_PMIER); for (i = 0; i < ARRAY_SIZE(s->gt_scratch); i++) - s->gt_scratch[i] = I915_READ(GEN7_GT_SCRATCH_BASE + i * 4); + s->gt_scratch[i] = I915_READ(GEN7_GT_SCRATCH(i)); /* GT SA CZ domain, 0x100000-0x138124 */ s->tilectl = I915_READ(TILECTL); @@ -1202,7 +1202,7 @@ static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *dev_priv) I915_WRITE(GEN7_GFX_PEND_TLB1, s->gfx_pend_tlb1); for (i = 0; i < ARRAY_SIZE(s->lra_limits); i++) - I915_WRITE(GEN7_LRA_LIMITS_BASE + i * 4, s->lra_limits[i]); + I915_WRITE(GEN7_LRA_LIMITS(i), s->lra_limits[i]); I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->media_max_req_count); I915_WRITE(GEN7_GFX_MAX_REQ_COUNT, s->gfx_max_req_count); @@ -1246,7 +1246,7 @@ static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_PMIER, s->pm_ier); for (i = 0; i < ARRAY_SIZE(s->gt_scratch); i++) - I915_WRITE(GEN7_GT_SCRATCH_BASE + i * 4, s->gt_scratch[i]); + I915_WRITE(GEN7_GT_SCRATCH(i), s->gt_scratch[i]); /* GT SA CZ domain, 0x100000-0x138124 */ I915_WRITE(TILECTL, s->tilectl); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 881a47a..90ce688 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1527,7 +1527,7 @@ enum skl_disp_power_wells { #define GEN7_GFX_PEND_TLB0 0x4034 #define GEN7_GFX_PEND_TLB1 0x4038 /* L3, CVS, ZTLB, RCC, CASC LRA min, max values */ -#define GEN7_LRA_LIMITS_BASE 0x403C +#define GEN7_LRA_LIMITS(i) (0x403C + (i) * 4) #define GEN7_LRA_LIMITS_REG_NUM 13 #define GEN7_MEDIA_MAX_REQ_COUNT 0x4070 #define GEN7_GFX_MAX_REQ_COUNT 0x4074 @@ -6813,7 +6813,7 @@ enum skl_disp_power_wells { GEN6_PM_RP_DOWN_THRESHOLD | \ GEN6_PM_RP_DOWN_TIMEOUT) -#define GEN7_GT_SCRATCH_BASE 0x4F100 +#define GEN7_GT_SCRATCH(i) (0x4F100 + (i) * 4) #define GEN7_GT_SCRATCH_REG_NUM 8 #define VLV_GTLC_SURVIVABILITY_REG 0x130098 -- cgit v0.10.2 From 4d110c71fb87c5601832e918c36af8cd4ef739f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Sep 2015 20:03:18 +0300 Subject: drm/i915: Parametrize FBC_TAG registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 90ce688..ffd0f6b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2011,7 +2011,7 @@ enum skl_disp_power_wells { #define FBC_CTL_CPU_FENCE (1<<1) #define FBC_CTL_PLANE(plane) ((plane)<<0) #define FBC_FENCE_OFF 0x03218 /* BSpec typo has 321Bh */ -#define FBC_TAG 0x03300 +#define FBC_TAG(i) (0x03300 + (i) * 4) #define FBC_STATUS2 0x43214 #define FBC_COMPRESSION_MASK 0x7ff diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index d38f464..6777fbb 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -101,7 +101,7 @@ static void i8xx_fbc_enable(struct intel_crtc *crtc) /* Clear old tags */ for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++) - I915_WRITE(FBC_TAG + (i * 4), 0); + I915_WRITE(FBC_TAG(i), 0); if (IS_GEN4(dev_priv)) { u32 fbc_ctl2; -- cgit v0.10.2 From 616847e7e8569a28e46a56d4cc1ac28f061e29e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Sep 2015 20:03:19 +0300 Subject: drm/i915: Parametrize ILK turbo registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ffd0f6b..07fcd06 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2579,7 +2579,7 @@ enum skl_disp_power_wells { #define TSFS_INTR_MASK 0x000000ff #define CRSTANDVID 0x11100 -#define PXVFREQ_BASE 0x11110 /* P[0-15]VIDFREQ (0x1114c) (Ironlake) */ +#define PXVFREQ(i) (0x11110 + (i) * 4) /* P[0-15]VIDFREQ (0x1114c) (Ironlake) */ #define PXVFREQ_PX_MASK 0x7f000000 #define PXVFREQ_PX_SHIFT 24 #define VIDFREQ_BASE 0x11110 @@ -2763,8 +2763,8 @@ enum skl_disp_power_wells { #define CSIEW0 0x11250 #define CSIEW1 0x11254 #define CSIEW2 0x11258 -#define PEW 0x1125c -#define DEW 0x11270 +#define PEW(i) (0x1125c + (i) * 4) /* 5 registers */ +#define DEW(i) (0x11270 + (i) * 4) /* 3 registers */ #define MCHAFE 0x112c0 #define CSIEC 0x112e0 #define DMIEC 0x112e4 @@ -2788,8 +2788,8 @@ enum skl_disp_power_wells { #define EG5 0x11624 #define EG6 0x11628 #define EG7 0x1162c -#define PXW 0x11664 -#define PXWL 0x11680 +#define PXW(i) (0x11664 + (i) * 4) /* 4 registers */ +#define PXWL(i) (0x11680 + (i) * 4) /* 8 registers */ #define LCFUSE02 0x116c0 #define LCFUSE_HIV_MASK 0x000000ff #define CSIPLL0 0x12c10 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 566f5cd..cb747f1 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4282,7 +4282,7 @@ static void ironlake_enable_drps(struct drm_device *dev) fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >> MEMMODE_FSTART_SHIFT; - vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >> + vstart = (I915_READ(PXVFREQ(fstart)) & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT; dev_priv->ips.fmax = fmax; /* IPS callback will increase this */ @@ -5915,7 +5915,7 @@ static unsigned long __i915_gfx_val(struct drm_i915_private *dev_priv) assert_spin_locked(&mchdev_lock); - pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->rps.cur_freq * 4)); + pxvid = I915_READ(PXVFREQ(dev_priv->rps.cur_freq)); pxvid = (pxvid >> 24) & 0x7f; ext_v = pvid_to_extvid(dev_priv, pxvid); @@ -6158,13 +6158,13 @@ static void intel_init_emon(struct drm_device *dev) I915_WRITE(CSIEW2, 0x04000004); for (i = 0; i < 5; i++) - I915_WRITE(PEW + (i * 4), 0); + I915_WRITE(PEW(i), 0); for (i = 0; i < 3; i++) - I915_WRITE(DEW + (i * 4), 0); + I915_WRITE(DEW(i), 0); /* Program P-state weights to account for frequency power adjustment */ for (i = 0; i < 16; i++) { - u32 pxvidfreq = I915_READ(PXVFREQ_BASE + (i * 4)); + u32 pxvidfreq = I915_READ(PXVFREQ(i)); unsigned long freq = intel_pxfreq(pxvidfreq); unsigned long vid = (pxvidfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT; @@ -6185,7 +6185,7 @@ static void intel_init_emon(struct drm_device *dev) for (i = 0; i < 4; i++) { u32 val = (pxw[i*4] << 24) | (pxw[(i*4)+1] << 16) | (pxw[(i*4)+2] << 8) | (pxw[(i*4)+3]); - I915_WRITE(PXW + (i * 4), val); + I915_WRITE(PXW(i), val); } /* Adjust magic regs to magic values (more experimental results) */ @@ -6201,7 +6201,7 @@ static void intel_init_emon(struct drm_device *dev) I915_WRITE(EG7, 0); for (i = 0; i < 8; i++) - I915_WRITE(PXWL + (i * 4), 0); + I915_WRITE(PXWL(i), 0); /* Enable PMON + select events */ I915_WRITE(ECR, 0x80000019); -- cgit v0.10.2 From 7d81c3e02b685074e437cdb48ea3a9efd82873c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Sep 2015 20:03:20 +0300 Subject: drm/i915: Replace raw numbers with the approproate register name in ILK turbo code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index cb747f1..6870069 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4313,10 +4313,10 @@ static void ironlake_enable_drps(struct drm_device *dev) ironlake_set_drps(dev, fstart); - dev_priv->ips.last_count1 = I915_READ(0x112e4) + I915_READ(0x112e8) + - I915_READ(0x112e0); + dev_priv->ips.last_count1 = I915_READ(DMIEC) + + I915_READ(DDREC) + I915_READ(CSIEC); dev_priv->ips.last_time1 = jiffies_to_msecs(jiffies); - dev_priv->ips.last_count2 = I915_READ(0x112f4); + dev_priv->ips.last_count2 = I915_READ(GFXEC); dev_priv->ips.last_time2 = ktime_get_raw_ns(); spin_unlock_irq(&mchdev_lock); -- cgit v0.10.2 From 184d7c06227349aad07921e8da63f61ab67e6727 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Sep 2015 20:03:21 +0300 Subject: drm/i915: Parametrize TV luma/chroma filter registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 07fcd06..dad7307 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4082,14 +4082,10 @@ enum skl_disp_power_wells { # define TV_CC_DATA_1_MASK 0x0000007f # define TV_CC_DATA_1_SHIFT 0 -#define TV_H_LUMA_0 0x68100 -#define TV_H_LUMA_59 0x681ec -#define TV_H_CHROMA_0 0x68200 -#define TV_H_CHROMA_59 0x682ec -#define TV_V_LUMA_0 0x68300 -#define TV_V_LUMA_42 0x683a8 -#define TV_V_CHROMA_0 0x68400 -#define TV_V_CHROMA_42 0x684a8 +#define TV_H_LUMA(i) (0x68100 + (i) * 4) /* 60 registers */ +#define TV_H_CHROMA(i) (0x68200 + (i) * 4) /* 60 registers */ +#define TV_V_LUMA(i) (0x68300 + (i) * 4) /* 43 registers */ +#define TV_V_CHROMA(i) (0x68400 + (i) * 4) /* 43 registers */ /* Display Port */ #define DP_A 0x64000 /* eDP */ diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index cbe39dc..c69e1af 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1138,13 +1138,13 @@ static void intel_tv_pre_enable(struct intel_encoder *encoder) j = 0; for (i = 0; i < 60; i++) - I915_WRITE(TV_H_LUMA_0 + (i<<2), tv_mode->filter_table[j++]); + I915_WRITE(TV_H_LUMA(i), tv_mode->filter_table[j++]); for (i = 0; i < 60; i++) - I915_WRITE(TV_H_CHROMA_0 + (i<<2), tv_mode->filter_table[j++]); + I915_WRITE(TV_H_CHROMA(i), tv_mode->filter_table[j++]); for (i = 0; i < 43; i++) - I915_WRITE(TV_V_LUMA_0 + (i<<2), tv_mode->filter_table[j++]); + I915_WRITE(TV_V_LUMA(i), tv_mode->filter_table[j++]); for (i = 0; i < 43; i++) - I915_WRITE(TV_V_CHROMA_0 + (i<<2), tv_mode->filter_table[j++]); + I915_WRITE(TV_V_CHROMA(i), tv_mode->filter_table[j++]); I915_WRITE(TV_DAC, I915_READ(TV_DAC) & TV_DAC_SAVE); I915_WRITE(TV_CTL, tv_ctl); } -- cgit v0.10.2 From 9712e68840cf09d138be6226f6e6f6dcd9b009f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Sep 2015 20:03:22 +0300 Subject: drm/i915: Parametrize DDI_BUF_TRANS registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FIXME: Should there be a WARN(i != 9) or something, or what does the entry 9 comment mean? Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index dad7307..56157eb 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7197,7 +7197,8 @@ enum skl_disp_power_wells { /* DDI Buffer Translations */ #define DDI_BUF_TRANS_A 0x64E00 #define DDI_BUF_TRANS_B 0x64E60 -#define DDI_BUF_TRANS(port) _PORT(port, DDI_BUF_TRANS_A, DDI_BUF_TRANS_B) +#define DDI_BUF_TRANS_LO(port, i) (_PORT(port, DDI_BUF_TRANS_A, DDI_BUF_TRANS_B) + (i) * 8) +#define DDI_BUF_TRANS_HI(port, i) (_PORT(port, DDI_BUF_TRANS_A, DDI_BUF_TRANS_B) + (i) * 8 + 4) /* Sideband Interface (SBI) is programmed indirectly, via * SBI_ADDR, which contains the register offset; and SBI_DATA, diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 5b600bf..9e640ea 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -414,7 +414,6 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, bool supports_hdmi) { struct drm_i915_private *dev_priv = dev->dev_private; - u32 reg; u32 iboost_bit = 0; int i, n_hdmi_entries, n_dp_entries, n_edp_entries, hdmi_default_entry, size; @@ -505,11 +504,11 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, BUG(); } - for (i = 0, reg = DDI_BUF_TRANS(port); i < size; i++) { - I915_WRITE(reg, ddi_translations[i].trans1 | iboost_bit); - reg += 4; - I915_WRITE(reg, ddi_translations[i].trans2); - reg += 4; + for (i = 0; i < size; i++) { + I915_WRITE(DDI_BUF_TRANS_LO(port, i), + ddi_translations[i].trans1 | iboost_bit); + I915_WRITE(DDI_BUF_TRANS_HI(port, i), + ddi_translations[i].trans2); } if (!supports_hdmi) @@ -521,10 +520,10 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, hdmi_level = hdmi_default_entry; /* Entry 9 is for HDMI: */ - I915_WRITE(reg, ddi_translations_hdmi[hdmi_level].trans1 | iboost_bit); - reg += 4; - I915_WRITE(reg, ddi_translations_hdmi[hdmi_level].trans2); - reg += 4; + I915_WRITE(DDI_BUF_TRANS_LO(port, i), + ddi_translations_hdmi[hdmi_level].trans1 | iboost_bit); + I915_WRITE(DDI_BUF_TRANS_HI(port, i), + ddi_translations_hdmi[hdmi_level].trans2); } /* Program DDI buffers translations for DP. By default, program ports A-D in DP -- cgit v0.10.2 From d2aa5ae8e721bfe319e68ef5c08380385d452787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Sep 2015 20:03:23 +0300 Subject: drm/i915: Parametrize CSR_PROGRAM registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Syrjälä Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 780d5d5..61b4a47 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -50,7 +50,7 @@ MODULE_FIRMWARE(I915_CSR_BXT); /* * SKL CSR registers for DC5 and DC6 */ -#define CSR_PROGRAM_BASE 0x80000 +#define CSR_PROGRAM(i) (0x80000 + (i) * 4) #define CSR_SSP_BASE_ADDR_GEN9 0x00002FC0 #define CSR_HTP_ADDR_SKL 0x00500034 #define CSR_SSP_BASE 0x8F074 @@ -268,8 +268,7 @@ void intel_csr_load_program(struct drm_device *dev) mutex_lock(&dev_priv->csr_lock); fw_size = dev_priv->csr.dmc_fw_size; for (i = 0; i < fw_size; i++) - I915_WRITE(CSR_PROGRAM_BASE + i * 4, - payload[i]); + I915_WRITE(CSR_PROGRAM(i), payload[i]); for (i = 0; i < dev_priv->csr.mmio_count; i++) { I915_WRITE(dev_priv->csr.mmioaddr[i], @@ -471,7 +470,7 @@ void assert_csr_loaded(struct drm_i915_private *dev_priv) { WARN_ONCE(intel_csr_load_status_get(dev_priv) != FW_LOADED, "CSR is not loaded.\n"); - WARN_ONCE(!I915_READ(CSR_PROGRAM_BASE), + WARN_ONCE(!I915_READ(CSR_PROGRAM(0)), "CSR program storage start is NULL\n"); WARN_ONCE(!I915_READ(CSR_SSP_BASE), "CSR SSP Base Not fine\n"); WARN_ONCE(!I915_READ(CSR_HTP_SKL), "CSR HTP Not fine\n"); -- cgit v0.10.2 From 5ca4163a612068d8f942c454218d3d631f22af1b Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Fri, 18 Sep 2015 17:52:47 +0100 Subject: drm/i915/bxt: Update revision id for BXT C0 Cc: Nick Hoath Cc: Imre Deak Signed-off-by: Arun Siluvery Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ba4596e..6c3ef9c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2507,7 +2507,7 @@ struct drm_i915_cmd_table { #define BXT_REVID_A0 (0x0) #define BXT_REVID_B0 (0x3) -#define BXT_REVID_C0 (0x6) +#define BXT_REVID_C0 (0x9) /* * The genX designation typically refers to the render engine, so render -- cgit v0.10.2 From fe47ea0cfa4adffe2a20edb22376d7af76b6a74c Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 21 Sep 2015 10:45:32 +0100 Subject: drm/i915: Support planar formats in tile height calculations This will be needed for NV12 support. v2: Rebase. Signed-off-by: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bf8754f..1f3af24 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2190,7 +2190,7 @@ static bool need_vtd_wa(struct drm_device *dev) unsigned int intel_tile_height(struct drm_device *dev, uint32_t pixel_format, - uint64_t fb_format_modifier) + uint64_t fb_format_modifier, unsigned int plane) { unsigned int tile_height; uint32_t pixel_bytes; @@ -2206,7 +2206,7 @@ intel_tile_height(struct drm_device *dev, uint32_t pixel_format, tile_height = 32; break; case I915_FORMAT_MOD_Yf_TILED: - pixel_bytes = drm_format_plane_cpp(pixel_format, 0); + pixel_bytes = drm_format_plane_cpp(pixel_format, plane); switch (pixel_bytes) { default: case 1: @@ -2240,7 +2240,7 @@ intel_fb_align_height(struct drm_device *dev, unsigned int height, uint32_t pixel_format, uint64_t fb_format_modifier) { return ALIGN(height, intel_tile_height(dev, pixel_format, - fb_format_modifier)); + fb_format_modifier, 0)); } static int @@ -2266,7 +2266,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, info->fb_modifier = fb->modifier[0]; tile_height = intel_tile_height(fb->dev, fb->pixel_format, - fb->modifier[0]); + fb->modifier[0], 0); tile_pitch = PAGE_SIZE / tile_height; info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_pitch); info->height_pages = DIV_ROUND_UP(fb->height, tile_height); @@ -3075,7 +3075,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc, if (intel_rotation_90_or_270(rotation)) { /* stride = Surface height in tiles */ tile_height = intel_tile_height(dev, fb->pixel_format, - fb->modifier[0]); + fb->modifier[0], 0); stride = DIV_ROUND_UP(fb->height, tile_height); x_offset = stride * tile_height - y - src_h; y_offset = x; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index ab3c296..858c382 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1089,7 +1089,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, unsigned int intel_tile_height(struct drm_device *dev, uint32_t pixel_format, - uint64_t fb_format_modifier); + uint64_t fb_format_modifier, unsigned int plane); static inline bool intel_rotation_90_or_270(unsigned int rotation) diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 79f7cc2..4372fa0 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -240,7 +240,7 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc, if (intel_rotation_90_or_270(rotation)) { /* stride: Surface height in tiles */ tile_height = intel_tile_height(dev, fb->pixel_format, - fb->modifier[0]); + fb->modifier[0], 0); stride = DIV_ROUND_UP(fb->height, tile_height); plane_size = (src_w << 16) | src_h; x_offset = stride * tile_height - y - (src_h + 1); -- cgit v0.10.2 From 804beb4b5b76e41352b41027ab2804b8462c1686 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 21 Sep 2015 10:45:33 +0100 Subject: drm/i915: Support appending to the rotated pages mapping By providing a start offset into the source array of pages, and returning the end position in the scatter-gather table, we will be able to append the UV plane to the rotated mapping in later patches. v2: Rebase. Signed-off-by: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 01f3521..2a8f64d 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3244,15 +3244,18 @@ i915_gem_obj_lookup_or_create_ggtt_vma(struct drm_i915_gem_object *obj, } -static void -rotate_pages(dma_addr_t *in, unsigned int width, unsigned int height, - struct sg_table *st) +static struct scatterlist * +rotate_pages(dma_addr_t *in, unsigned int offset, + unsigned int width, unsigned int height, + struct sg_table *st, struct scatterlist *sg) { unsigned int column, row; unsigned int src_idx; - struct scatterlist *sg = st->sgl; - st->nents = 0; + if (!sg) { + st->nents = 0; + sg = st->sgl; + } for (column = 0; column < width; column++) { src_idx = width * (height - 1) + column; @@ -3263,12 +3266,14 @@ rotate_pages(dma_addr_t *in, unsigned int width, unsigned int height, * The only thing we need are DMA addresses. */ sg_set_page(sg, NULL, PAGE_SIZE, 0); - sg_dma_address(sg) = in[src_idx]; + sg_dma_address(sg) = in[offset + src_idx]; sg_dma_len(sg) = PAGE_SIZE; sg = sg_next(sg); src_idx -= width; } } + + return sg; } static struct sg_table * @@ -3306,9 +3311,9 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view, } /* Rotate the pages. */ - rotate_pages(page_addr_list, + rotate_pages(page_addr_list, 0, rot_info->width_pages, rot_info->height_pages, - st); + st, NULL); DRM_DEBUG_KMS( "Created rotated page mapping for object size %zu (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages).\n", -- cgit v0.10.2 From 89e3e1427629027dc33e576fc002880a02a7e50c Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 21 Sep 2015 10:45:34 +0100 Subject: drm/i915: Support NV12 in rotated GGTT mapping Just adding the rotated UV plane at the end of the rotated Y plane. v2: Rebase. Signed-off-by: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 2a8f64d..ad0e7e0 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3282,10 +3282,13 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view, { struct intel_rotation_info *rot_info = &ggtt_view->rotation_info; unsigned int size_pages = rot_info->size >> PAGE_SHIFT; + unsigned int size_pages_uv; struct sg_page_iter sg_iter; unsigned long i; dma_addr_t *page_addr_list; struct sg_table *st; + unsigned int uv_start_page; + struct scatterlist *sg; int ret = -ENOMEM; /* Allocate a temporary list of source pages for random access. */ @@ -3294,12 +3297,18 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view, if (!page_addr_list) return ERR_PTR(ret); + /* Account for UV plane with NV12. */ + if (rot_info->pixel_format == DRM_FORMAT_NV12) + size_pages_uv = rot_info->size_uv >> PAGE_SHIFT; + else + size_pages_uv = 0; + /* Allocate target SG list. */ st = kmalloc(sizeof(*st), GFP_KERNEL); if (!st) goto err_st_alloc; - ret = sg_alloc_table(st, size_pages, GFP_KERNEL); + ret = sg_alloc_table(st, size_pages + size_pages_uv, GFP_KERNEL); if (ret) goto err_sg_alloc; @@ -3311,15 +3320,30 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view, } /* Rotate the pages. */ - rotate_pages(page_addr_list, 0, + sg = rotate_pages(page_addr_list, 0, rot_info->width_pages, rot_info->height_pages, st, NULL); + /* Append the UV plane if NV12. */ + if (rot_info->pixel_format == DRM_FORMAT_NV12) { + uv_start_page = size_pages; + + /* Check for tile-row un-alignment. */ + if (offset_in_page(rot_info->uv_offset)) + uv_start_page--; + + rotate_pages(page_addr_list, uv_start_page, + rot_info->width_pages_uv, + rot_info->height_pages_uv, + st, sg); + } + DRM_DEBUG_KMS( - "Created rotated page mapping for object size %zu (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages).\n", + "Created rotated page mapping for object size %zu (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages (%u plane 0)).\n", obj->base.size, rot_info->pitch, rot_info->height, rot_info->pixel_format, rot_info->width_pages, - rot_info->height_pages, size_pages); + rot_info->height_pages, size_pages + size_pages_uv, + size_pages); drm_free_large(page_addr_list); @@ -3331,10 +3355,11 @@ err_st_alloc: drm_free_large(page_addr_list); DRM_DEBUG_KMS( - "Failed to create rotated mapping for object size %zu! (%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages)\n", + "Failed to create rotated mapping for object size %zu! (%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages (%u plane 0))\n", obj->base.size, ret, rot_info->pitch, rot_info->height, rot_info->pixel_format, rot_info->width_pages, - rot_info->height_pages, size_pages); + rot_info->height_pages, size_pages + size_pages_uv, + size_pages); return ERR_PTR(ret); } diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 96ebb98..c807586 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -138,10 +138,13 @@ enum i915_ggtt_view_type { struct intel_rotation_info { unsigned int height; unsigned int pitch; + unsigned int uv_offset; uint32_t pixel_format; uint64_t fb_modifier; unsigned int width_pages, height_pages; uint64_t size; + unsigned int width_pages_uv, height_pages_uv; + uint64_t size_uv; }; struct i915_ggtt_view { diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1f3af24..bdce458 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2263,6 +2263,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, info->height = fb->height; info->pixel_format = fb->pixel_format; info->pitch = fb->pitches[0]; + info->uv_offset = fb->offsets[1]; info->fb_modifier = fb->modifier[0]; tile_height = intel_tile_height(fb->dev, fb->pixel_format, @@ -2272,6 +2273,17 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, info->height_pages = DIV_ROUND_UP(fb->height, tile_height); info->size = info->width_pages * info->height_pages * PAGE_SIZE; + if (info->pixel_format == DRM_FORMAT_NV12) { + tile_height = intel_tile_height(fb->dev, fb->pixel_format, + fb->modifier[0], 1); + tile_pitch = PAGE_SIZE / tile_height; + info->width_pages_uv = DIV_ROUND_UP(fb->pitches[0], tile_pitch); + info->height_pages_uv = DIV_ROUND_UP(fb->height / 2, + tile_height); + info->size_uv = info->width_pages_uv * info->height_pages_uv * + PAGE_SIZE; + } + return 0; } -- cgit v0.10.2 From dedf278ce69cac6b29c324d280183da31093e0b0 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 21 Sep 2015 10:45:35 +0100 Subject: drm/i915: Enable querying offset of UV plane with intel_plane_obj_offset v2: Rebase. Signed-off-by: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index ad0e7e0..bbb96a4 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3332,6 +3332,8 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view, if (offset_in_page(rot_info->uv_offset)) uv_start_page--; + rot_info->uv_start_page = uv_start_page; + rotate_pages(page_addr_list, uv_start_page, rot_info->width_pages_uv, rot_info->height_pages_uv, diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index c807586..9fbb07d 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -145,6 +145,7 @@ struct intel_rotation_info { uint64_t size; unsigned int width_pages_uv, height_pages_uv; uint64_t size_uv; + unsigned int uv_start_page; }; struct i915_ggtt_view { diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bdce458..9b19891 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2897,14 +2897,29 @@ u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier, } unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane, - struct drm_i915_gem_object *obj) + struct drm_i915_gem_object *obj, + unsigned int plane) { const struct i915_ggtt_view *view = &i915_ggtt_view_normal; + struct i915_vma *vma; + unsigned char *offset; if (intel_rotation_90_or_270(intel_plane->base.state->rotation)) view = &i915_ggtt_view_rotated; - return i915_gem_obj_ggtt_offset_view(obj, view); + vma = i915_gem_obj_to_ggtt_view(obj, view); + if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n", + view->type)) + return -1; + + offset = (unsigned char *)vma->node.start; + + if (plane == 1) { + offset += vma->ggtt_view.rotation_info.uv_start_page * + PAGE_SIZE; + } + + return (unsigned long)offset; } static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id) @@ -3060,7 +3075,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc, obj = intel_fb_obj(fb); stride_div = intel_fb_stride_alignment(dev, fb->modifier[0], fb->pixel_format); - surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj); + surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj, 0); /* * FIXME: intel_plane_state->src, dst aren't set when transitional @@ -11423,8 +11438,9 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, if (ret) goto cleanup_pending; - work->gtt_offset = intel_plane_obj_offset(to_intel_plane(primary), obj) - + intel_crtc->dspaddr_offset; + work->gtt_offset = intel_plane_obj_offset(to_intel_plane(primary), + obj, 0); + work->gtt_offset += intel_crtc->dspaddr_offset; if (mmio_flip) { ret = intel_queue_mmio_flip(dev, crtc, fb, obj, ring, diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 858c382..bc674aa 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1170,7 +1170,9 @@ int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state); int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state); unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane, - struct drm_i915_gem_object *obj); + struct drm_i915_gem_object *obj, + unsigned int plane); + u32 skl_plane_ctl_format(uint32_t pixel_format); u32 skl_plane_ctl_tiling(uint64_t fb_modifier); u32 skl_plane_ctl_rotation(unsigned int rotation); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 4372fa0..4349fde 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -235,7 +235,7 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc, else if (key->flags & I915_SET_COLORKEY_SOURCE) plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE; - surf_addr = intel_plane_obj_offset(intel_plane, obj); + surf_addr = intel_plane_obj_offset(intel_plane, obj, 0); if (intel_rotation_90_or_270(rotation)) { /* stride: Surface height in tiles */ -- cgit v0.10.2 From cd1736ad0a6f0f7a31773ddf90040bd15969bc21 Mon Sep 17 00:00:00 2001 From: Nick Hoath Date: Mon, 21 Sep 2015 14:02:29 +0100 Subject: drm/i915: Remove extraneous request cancel. Remove extraneous request cancel in request allocation failure path in intel_lr_context_deferred_alloc (Tvrtko Ursulin) Regression from: commit e84fe80337dc85cca07d0417ea97edbec4789d8b Author: Nick Hoath Date: Fri Sep 11 12:53:46 2015 +0100 drm/i915: Split alloc from init for lrc Signed-off-by: Nick Hoath Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 7417650..256167b 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -2487,7 +2487,6 @@ int intel_lr_context_deferred_alloc(struct intel_context *ctx, if (ret) { DRM_ERROR("ring create req: %d\n", ret); - i915_gem_request_cancel(req); goto error_ringbuf; } -- cgit v0.10.2 From 8a9d4626db312fe0a682c35ef43fe8d9160c2ecd Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Fri, 28 Aug 2015 17:21:46 +0300 Subject: OMAPDSS: hdmi: Reconfigure and restart audio when display is enabled Reconfigure and restart audio when display is enabled, if audio playback was active before. This is needed in a situation when an audio+video stream application opens the audio stream before the video. When video stream is opened the display mode may change and that aborts audio playback, because the display is momentarily turned off. The audio configuration is stored when it is successfully applied and a boolean is set when the audio playback is started and unset when stopped. This data is used to reconfigure the audio when display is re-enabled. The audio playback is aborted if the reconfiguration fails. A new spin lock is introduced in order to protect state variables related to audio playback status. This is needed for the transition from display enabled state (when audio start/stop commands can be written to HW) to display disabled state (when audio start/stop commands update only the hdmi.audio_playing variable) to always serialize correctly with the start/stop audio commands. The already existing mutex can not be used, because the audio start and stop commands are executed in atomic context. For example: when display is turned back on we take the spinlock and we can be sure that the audio start/stop status will not change while we update the HW according to hdmi.audio_playing state and set hdmi.display_enabled to true. After releasing the lock hdmi.display_enabled is true and all audio_start and audio_stop commands write their stuff directly to HW. Signed-off-by: Jyri Sarha Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/fbdev/omap2/dss/hdmi.h b/drivers/video/fbdev/omap2/dss/hdmi.h index e4a32fe..53616b0 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi.h +++ b/drivers/video/fbdev/omap2/dss/hdmi.h @@ -351,13 +351,20 @@ struct omap_hdmi { struct regulator *vdda_reg; bool core_enabled; - bool display_enabled; struct omap_dss_device output; struct platform_device *audio_pdev; void (*audio_abort_cb)(struct device *dev); int wp_idlemode; + + bool audio_configured; + struct omap_dss_audio audio_config; + + /* This lock should be taken when booleans bellow are touched. */ + spinlock_t audio_playing_lock; + bool audio_playing; + bool display_enabled; }; #endif diff --git a/drivers/video/fbdev/omap2/dss/hdmi4.c b/drivers/video/fbdev/omap2/dss/hdmi4.c index 6d3aa3f..94c8d55 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi4.c +++ b/drivers/video/fbdev/omap2/dss/hdmi4.c @@ -321,9 +321,22 @@ static int read_edid(u8 *buf, int len) return r; } +static void hdmi_start_audio_stream(struct omap_hdmi *hd) +{ + hdmi_wp_audio_enable(&hd->wp, true); + hdmi4_audio_start(&hd->core, &hd->wp); +} + +static void hdmi_stop_audio_stream(struct omap_hdmi *hd) +{ + hdmi4_audio_stop(&hd->core, &hd->wp); + hdmi_wp_audio_enable(&hd->wp, false); +} + static int hdmi_display_enable(struct omap_dss_device *dssdev) { struct omap_dss_device *out = &hdmi.output; + unsigned long flags; int r = 0; DSSDBG("ENTER hdmi_display_enable\n"); @@ -342,7 +355,21 @@ static int hdmi_display_enable(struct omap_dss_device *dssdev) goto err0; } + if (hdmi.audio_configured) { + r = hdmi4_audio_config(&hdmi.core, &hdmi.wp, &hdmi.audio_config, + hdmi.cfg.timings.pixelclock); + if (r) { + DSSERR("Error restoring audio configuration: %d", r); + hdmi.audio_abort_cb(&hdmi.pdev->dev); + hdmi.audio_configured = false; + } + } + + spin_lock_irqsave(&hdmi.audio_playing_lock, flags); + if (hdmi.audio_configured && hdmi.audio_playing) + hdmi_start_audio_stream(&hdmi); hdmi.display_enabled = true; + spin_unlock_irqrestore(&hdmi.audio_playing_lock, flags); mutex_unlock(&hdmi.lock); return 0; @@ -354,17 +381,19 @@ err0: static void hdmi_display_disable(struct omap_dss_device *dssdev) { + unsigned long flags; + DSSDBG("Enter hdmi_display_disable\n"); mutex_lock(&hdmi.lock); - if (hdmi.audio_pdev && hdmi.audio_abort_cb) - hdmi.audio_abort_cb(&hdmi.audio_pdev->dev); + spin_lock_irqsave(&hdmi.audio_playing_lock, flags); + hdmi_stop_audio_stream(&hdmi); + hdmi.display_enabled = false; + spin_unlock_irqrestore(&hdmi.audio_playing_lock, flags); hdmi_power_off_full(dssdev); - hdmi.display_enabled = false; - mutex_unlock(&hdmi.lock); } @@ -568,6 +597,8 @@ static int hdmi_audio_shutdown(struct device *dev) mutex_lock(&hd->lock); hd->audio_abort_cb = NULL; + hd->audio_configured = false; + hd->audio_playing = false; mutex_unlock(&hd->lock); return 0; @@ -576,25 +607,34 @@ static int hdmi_audio_shutdown(struct device *dev) static int hdmi_audio_start(struct device *dev) { struct omap_hdmi *hd = dev_get_drvdata(dev); + unsigned long flags; WARN_ON(!hdmi_mode_has_audio(&hd->cfg)); - WARN_ON(!hd->display_enabled); - hdmi_wp_audio_enable(&hd->wp, true); - hdmi4_audio_start(&hd->core, &hd->wp); + spin_lock_irqsave(&hd->audio_playing_lock, flags); + + if (hd->display_enabled) + hdmi_start_audio_stream(hd); + hd->audio_playing = true; + spin_unlock_irqrestore(&hd->audio_playing_lock, flags); return 0; } static void hdmi_audio_stop(struct device *dev) { struct omap_hdmi *hd = dev_get_drvdata(dev); + unsigned long flags; WARN_ON(!hdmi_mode_has_audio(&hd->cfg)); - WARN_ON(!hd->display_enabled); - hdmi4_audio_stop(&hd->core, &hd->wp); - hdmi_wp_audio_enable(&hd->wp, false); + spin_lock_irqsave(&hd->audio_playing_lock, flags); + + if (hd->display_enabled) + hdmi_stop_audio_stream(hd); + hd->audio_playing = false; + + spin_unlock_irqrestore(&hd->audio_playing_lock, flags); } static int hdmi_audio_config(struct device *dev, @@ -612,7 +652,10 @@ static int hdmi_audio_config(struct device *dev, ret = hdmi4_audio_config(&hd->core, &hd->wp, dss_audio, hd->cfg.timings.pixelclock); - + if (!ret) { + hd->audio_configured = true; + hd->audio_config = *dss_audio; + } out: mutex_unlock(&hd->lock); @@ -657,6 +700,7 @@ static int hdmi4_bind(struct device *dev, struct device *master, void *data) dev_set_drvdata(&pdev->dev, &hdmi); mutex_init(&hdmi.lock); + spin_lock_init(&hdmi.audio_playing_lock); if (pdev->dev.of_node) { r = hdmi_probe_of(pdev); diff --git a/drivers/video/fbdev/omap2/dss/hdmi5.c b/drivers/video/fbdev/omap2/dss/hdmi5.c index 7f87578..b59ba79 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi5.c +++ b/drivers/video/fbdev/omap2/dss/hdmi5.c @@ -349,9 +349,24 @@ static int read_edid(u8 *buf, int len) return r; } +static void hdmi_start_audio_stream(struct omap_hdmi *hd) +{ + REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2); + hdmi_wp_audio_enable(&hd->wp, true); + hdmi_wp_audio_core_req_enable(&hd->wp, true); +} + +static void hdmi_stop_audio_stream(struct omap_hdmi *hd) +{ + hdmi_wp_audio_core_req_enable(&hd->wp, false); + hdmi_wp_audio_enable(&hd->wp, false); + REG_FLD_MOD(hd->wp.base, HDMI_WP_SYSCONFIG, hd->wp_idlemode, 3, 2); +} + static int hdmi_display_enable(struct omap_dss_device *dssdev) { struct omap_dss_device *out = &hdmi.output; + unsigned long flags; int r = 0; DSSDBG("ENTER hdmi_display_enable\n"); @@ -370,7 +385,21 @@ static int hdmi_display_enable(struct omap_dss_device *dssdev) goto err0; } + if (hdmi.audio_configured) { + r = hdmi5_audio_config(&hdmi.core, &hdmi.wp, &hdmi.audio_config, + hdmi.cfg.timings.pixelclock); + if (r) { + DSSERR("Error restoring audio configuration: %d", r); + hdmi.audio_abort_cb(&hdmi.pdev->dev); + hdmi.audio_configured = false; + } + } + + spin_lock_irqsave(&hdmi.audio_playing_lock, flags); + if (hdmi.audio_configured && hdmi.audio_playing) + hdmi_start_audio_stream(&hdmi); hdmi.display_enabled = true; + spin_unlock_irqrestore(&hdmi.audio_playing_lock, flags); mutex_unlock(&hdmi.lock); return 0; @@ -382,17 +411,19 @@ err0: static void hdmi_display_disable(struct omap_dss_device *dssdev) { + unsigned long flags; + DSSDBG("Enter hdmi_display_disable\n"); mutex_lock(&hdmi.lock); - if (hdmi.audio_pdev && hdmi.audio_abort_cb) - hdmi.audio_abort_cb(&hdmi.audio_pdev->dev); + spin_lock_irqsave(&hdmi.audio_playing_lock, flags); + hdmi_stop_audio_stream(&hdmi); + hdmi.display_enabled = false; + spin_unlock_irqrestore(&hdmi.audio_playing_lock, flags); hdmi_power_off_full(dssdev); - hdmi.display_enabled = false; - mutex_unlock(&hdmi.lock); } @@ -596,6 +627,8 @@ static int hdmi_audio_shutdown(struct device *dev) mutex_lock(&hd->lock); hd->audio_abort_cb = NULL; + hd->audio_configured = false; + hd->audio_playing = false; mutex_unlock(&hd->lock); return 0; @@ -604,32 +637,34 @@ static int hdmi_audio_shutdown(struct device *dev) static int hdmi_audio_start(struct device *dev) { struct omap_hdmi *hd = dev_get_drvdata(dev); + unsigned long flags; WARN_ON(!hdmi_mode_has_audio(&hd->cfg)); - WARN_ON(!hd->display_enabled); - /* No-idle while playing audio, store the old value */ - hd->wp_idlemode = REG_GET(hdmi.wp.base, HDMI_WP_SYSCONFIG, 3, 2); - REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2); + spin_lock_irqsave(&hd->audio_playing_lock, flags); - hdmi_wp_audio_enable(&hd->wp, true); - hdmi_wp_audio_core_req_enable(&hd->wp, true); + if (hd->display_enabled) + hdmi_start_audio_stream(hd); + hd->audio_playing = true; + spin_unlock_irqrestore(&hd->audio_playing_lock, flags); return 0; } static void hdmi_audio_stop(struct device *dev) { struct omap_hdmi *hd = dev_get_drvdata(dev); + unsigned long flags; WARN_ON(!hdmi_mode_has_audio(&hd->cfg)); - WARN_ON(!hd->display_enabled); - hdmi_wp_audio_core_req_enable(&hd->wp, false); - hdmi_wp_audio_enable(&hd->wp, false); + spin_lock_irqsave(&hd->audio_playing_lock, flags); + + if (hd->display_enabled) + hdmi_stop_audio_stream(hd); + hd->audio_playing = false; - /* Playback stopped, restore original idlemode */ - REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, hd->wp_idlemode, 3, 2); + spin_unlock_irqrestore(&hd->audio_playing_lock, flags); } static int hdmi_audio_config(struct device *dev, @@ -648,6 +683,10 @@ static int hdmi_audio_config(struct device *dev, ret = hdmi5_audio_config(&hd->core, &hd->wp, dss_audio, hd->cfg.timings.pixelclock); + if (!ret) { + hd->audio_configured = true; + hd->audio_config = *dss_audio; + } out: mutex_unlock(&hd->lock); @@ -678,6 +717,11 @@ static int hdmi_audio_register(struct device *dev) if (IS_ERR(hdmi.audio_pdev)) return PTR_ERR(hdmi.audio_pdev); + hdmi_runtime_get(); + hdmi.wp_idlemode = + REG_GET(hdmi.wp.base, HDMI_WP_SYSCONFIG, 3, 2); + hdmi_runtime_put(); + return 0; } @@ -692,6 +736,7 @@ static int hdmi5_bind(struct device *dev, struct device *master, void *data) dev_set_drvdata(&pdev->dev, &hdmi); mutex_init(&hdmi.lock); + spin_lock_init(&hdmi.audio_playing_lock); if (pdev->dev.of_node) { r = hdmi_probe_of(pdev); -- cgit v0.10.2 From c50d5cd235210abffa1e88affbead1adbd5f294a Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Mon, 21 Sep 2015 15:34:00 +0200 Subject: video/omap: remove invalid check regno is unsigned so it cannot be negative. The problem has been detected using proposed semantic patch scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci [1]. [1]: http://permalink.gmane.org/gmane.linux.kernel/2038576 Signed-off-by: Andrzej Hajda Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/fbdev/omap/omapfb_main.c b/drivers/video/fbdev/omap/omapfb_main.c index 1fb3ea3..393ae1b 100644 --- a/drivers/video/fbdev/omap/omapfb_main.c +++ b/drivers/video/fbdev/omap/omapfb_main.c @@ -276,11 +276,6 @@ static int _setcolreg(struct fb_info *info, u_int regno, u_int red, u_int green, if (r != 0) break; - if (regno < 0) { - r = -EINVAL; - break; - } - if (regno < 16) { u16 pal; pal = ((red >> (16 - var->red.length)) << -- cgit v0.10.2 From 48846ec502525bd93ee6e611eeacb397f5662f9b Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Tue, 8 Sep 2015 21:19:50 +0200 Subject: fbdev: ssd1307fb: alphabetize headers This patch sorts the headers on ssd1307fb driver. Signed-off-by: Olliver Schinagl Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c index 93f4c90..8c01108 100644 --- a/drivers/video/fbdev/ssd1307fb.c +++ b/drivers/video/fbdev/ssd1307fb.c @@ -6,16 +6,16 @@ * Licensed under the GPLv2 or later. */ -#include #include -#include -#include +#include #include -#include +#include +#include +#include #include #include #include -#include +#include #define SSD1307FB_DATA 0x40 #define SSD1307FB_COMMAND 0x80 -- cgit v0.10.2 From 3ac58d58087e65592f2b91957c7a106a7a409aa4 Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Tue, 8 Sep 2015 21:19:51 +0200 Subject: fbdev: ssd1307fb: add ssd1309 support The ssd1307fb driver supports a lot of chips from the ssd130xfb series. This patch adds the ssd1309 chip, a 128x64 OLED driver chip. It is very similar to the other chips and only has some definitions added to support it. Signed-off-by: Olliver Schinagl Acked-by: Rob Herring Acked-by: Prabhakar Lad Signed-off-by: Tomi Valkeinen diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt index d1be78d..eb31ed4 100644 --- a/Documentation/devicetree/bindings/video/ssd1307fb.txt +++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt @@ -2,7 +2,8 @@ Required properties: - compatible: Should be "solomon,fb-". The only supported bus for - now is i2c, and the supported chips are ssd1305, ssd1306 and ssd1307. + now is i2c, and the supported chips are ssd1305, ssd1306, ssd1307 and + ssd1309. - reg: Should contain address of the controller on the I2C bus. Most likely 0x3c or 0x3d - pwm: Should contain the pwm to use according to the OF device tree PWM diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c index 8c01108..fa34808 100644 --- a/drivers/video/fbdev/ssd1307fb.c +++ b/drivers/video/fbdev/ssd1307fb.c @@ -495,6 +495,12 @@ static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = { .need_pwm = 1, }; +static struct ssd1307fb_deviceinfo ssd1307fb_ssd1309_deviceinfo = { + .default_vcomh = 0x34, + .default_dclk_div = 1, + .default_dclk_frq = 10, +}; + static const struct of_device_id ssd1307fb_of_match[] = { { .compatible = "solomon,ssd1305fb-i2c", @@ -508,6 +514,10 @@ static const struct of_device_id ssd1307fb_of_match[] = { .compatible = "solomon,ssd1307fb-i2c", .data = (void *)&ssd1307fb_ssd1307_deviceinfo, }, + { + .compatible = "solomon,ssd1309fb-i2c", + .data = (void *)&ssd1307fb_ssd1309_deviceinfo, + }, {}, }; MODULE_DEVICE_TABLE(of, ssd1307fb_of_match); @@ -709,6 +719,7 @@ static const struct i2c_device_id ssd1307fb_i2c_id[] = { { "ssd1305fb", 0 }, { "ssd1306fb", 0 }, { "ssd1307fb", 0 }, + { "ssd1309fb", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, ssd1307fb_i2c_id); -- cgit v0.10.2 From 7c4a7d60bcda9449bca1ed2ee47392cd7acb8535 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 24 Sep 2015 11:57:45 +0100 Subject: drm/i915: Defer adding preallocated stolen objects to the VM list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When preallocating a stolen object during early initialisation, we may be running before we have setup the the global GTT VM state, in particular before we have initialised the range manager and associated lists. As this is the case, we defer binding the stolen object until we call i915_gem_setup_global_gtt(). Not only should we defer the binding, but we should also defer the VM list manipulation. Fixes regression uncovered by commit a2cad9dff4dd44d0244b966d980de9d602d87593 Author: Michał Winiarski Date: Wed Sep 16 11:49:00 2015 +0200 drm/i915/gtt: Do not initialize drm_mm twice. Whilst I am here remove the duplicate work leaving dangling pointers from the error path... v2: Typos galore before coffee. Reported-by: Jesse Barnes Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92099 Signed-off-by: Chris Wilson Cc: Jesse Barnes Cc: Michel Thierry Cc: Mika Kuoppala Cc: Michał Winiarski Cc: Daniel Vetter Cc: Jani Nikula Reviewed-by: Michał Winiarski Tested-by: Jani Nikula Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index bbb96a4..47344d0 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2533,7 +2533,6 @@ static int ggtt_bind_vma(struct i915_vma *vma, * the bound flag ourselves. */ vma->bound |= GLOBAL_BIND; - } if (dev_priv->mm.aliasing_ppgtt && flags & LOCAL_BIND) { @@ -2657,6 +2656,7 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev, return ret; } vma->bound |= GLOBAL_BIND; + list_add_tail(&vma->mm_list, &ggtt_vm->inactive_list); } /* Clear any non-preallocated blocks */ diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 55df6ce..1520779 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -584,7 +584,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev, vma = i915_gem_obj_lookup_or_create_vma(obj, ggtt); if (IS_ERR(vma)) { ret = PTR_ERR(vma); - goto err_out; + goto err; } /* To simplify the initialisation sequence between KMS and GTT, @@ -598,23 +598,19 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev, ret = drm_mm_reserve_node(&ggtt->mm, &vma->node); if (ret) { DRM_DEBUG_KMS("failed to allocate stolen GTT space\n"); - goto err_vma; + goto err; } - } - vma->bound |= GLOBAL_BIND; + vma->bound |= GLOBAL_BIND; + list_add_tail(&vma->mm_list, &ggtt->inactive_list); + } list_add_tail(&obj->global_list, &dev_priv->mm.bound_list); - list_add_tail(&vma->mm_list, &ggtt->inactive_list); i915_gem_object_pin_pages(obj); return obj; -err_vma: - i915_gem_vma_destroy(vma); -err_out: - i915_gem_stolen_remove_node(dev_priv, stolen); - kfree(stolen); +err: drm_gem_object_unreference(&obj->base); return NULL; } -- cgit v0.10.2 From 9ab8b4e7cacfc4a03e4f39fe8a090436ce456720 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Mon, 21 Sep 2015 22:18:45 +0530 Subject: dmaengine: idma: rename to INTEL_IDMA64 the symbol CONFIG_IDMA64 should rather be CONFIG_INTEL_IDMA64 to conform to rest of the intel dmaengine drivers. This was found after sorting the entries and trying to place this odd one Suggested-by: Linus Torvalds Acked-by: Andy Shevchenko Signed-off-by: Vinod Koul diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index b458475..5c931d4 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -229,7 +229,7 @@ config IMX_SDMA Support the i.MX SDMA engine. This engine is integrated into Freescale i.MX25/31/35/51/53/6 chips. -config IDMA64 +config INTEL_IDMA64 tristate "Intel integrated DMA 64-bit support" select DMA_ENGINE select DMA_VIRTUAL_CHANNELS diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 7711a71..ef9c099 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -34,7 +34,7 @@ obj-$(CONFIG_HSU_DMA) += hsu/ obj-$(CONFIG_IMG_MDC_DMA) += img-mdc-dma.o obj-$(CONFIG_IMX_DMA) += imx-dma.o obj-$(CONFIG_IMX_SDMA) += imx-sdma.o -obj-$(CONFIG_IDMA64) += idma64.o +obj-$(CONFIG_INTEL_IDMA64) += idma64.o obj-$(CONFIG_INTEL_IOATDMA) += ioat/ obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o obj-$(CONFIG_INTEL_MIC_X100_DMA) += mic_x100_dma.o -- cgit v0.10.2 From 1da248a583de4e63a006dd84d9d53e6784b958a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Sep 2015 22:43:42 +0300 Subject: drm: s/int crtc/unsigned int pipe/ straggles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Finish the recent replacement of 'int pipe' with 'unsigned int pipe' Cc: Thierry Reding Signed-off-by: Ville Syrjälä Reviewed-by: Thierry Reding Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 22d207e..8df4133 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -74,11 +74,11 @@ module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600); module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600); module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600); -static void store_vblank(struct drm_device *dev, int crtc, +static void store_vblank(struct drm_device *dev, unsigned int pipe, u32 vblank_count_inc, struct timeval *t_vblank) { - struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; u32 tslot; assert_spin_locked(&dev->vblank_time_lock); @@ -88,7 +88,7 @@ static void store_vblank(struct drm_device *dev, int crtc, * the latching of vblank->count below. */ tslot = vblank->count + vblank_count_inc; - vblanktimestamp(dev, crtc, tslot) = *t_vblank; + vblanktimestamp(dev, pipe, tslot) = *t_vblank; } /* @@ -110,7 +110,7 @@ static void store_vblank(struct drm_device *dev, int crtc, * @pipe: counter to update * * Call back into the driver to update the appropriate vblank counter - * (specified by @crtc). Deal with wraparound, if it occurred, and + * (specified by @pipe). Deal with wraparound, if it occurred, and * update the last read value so we can deal with wraparound on the next * call if necessary. * @@ -1154,8 +1154,8 @@ EXPORT_SYMBOL(drm_crtc_vblank_put); * @dev: DRM device * @pipe: CRTC index * - * This waits for one vblank to pass on @crtc, using the irq driver interfaces. - * It is a failure to call this when the vblank irq for @crtc is disabled, e.g. + * This waits for one vblank to pass on @pipe, using the irq driver interfaces. + * It is a failure to call this when the vblank irq for @pipe is disabled, e.g. * due to lack of driver support or because the crtc is off. */ void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe) @@ -1288,8 +1288,8 @@ void drm_crtc_vblank_reset(struct drm_crtc *drm_crtc) { struct drm_device *dev = drm_crtc->dev; unsigned long irqflags; - int crtc = drm_crtc_index(drm_crtc); - struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; + unsigned int pipe = drm_crtc_index(drm_crtc); + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; spin_lock_irqsave(&dev->vbl_lock, irqflags); /* -- cgit v0.10.2 From f15a66e68422ca6bb783142780ad440067f6cc89 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Sat, 5 Sep 2015 11:22:39 +0200 Subject: drm: Spell vga_switcheroo consistently Currently everyone and their dog has their own favourite spelling for vga_switcheroo. This makes it hard to grep dmesg for log entries relating to vga_switcheroo. It also makes it hard to find related source files in the tree. vga_switcheroo.c uses pr_fmt "vga_switcheroo". Use that everywhere. Signed-off-by: Lukas Wunner Signed-off-by: Daniel Vetter diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 9ddf8c6..30401f9 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -3646,7 +3646,7 @@ void (*postclose) (struct drm_device *, struct drm_file *); plane properties to default value, so that a subsequent open of the device will not inherit state from the previous user. It can also be used to execute delayed power switching state changes, e.g. in - conjunction with the vga-switcheroo infrastructure. Beyond that KMS + conjunction with the vga_switcheroo infrastructure. Beyond that KMS drivers should not do any further cleanup. Only legacy UMS drivers might need to clean up device state so that the vga console or an independent fbdev driver could take over. diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index a5f9d8b..d685e23 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -753,7 +753,7 @@ static void dev_lastclose(struct drm_device *dev) { int i; - /* we don't support vga-switcheroo.. so just make sure the fbdev + /* we don't support vga_switcheroo.. so just make sure the fbdev * mode is active */ struct omap_drm_private *priv = dev->dev_private; diff --git a/include/linux/fb.h b/include/linux/fb.h index bc9afa7..be40dba 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -156,7 +156,7 @@ struct fb_cursor_user { #define FB_EVENT_GET_REQ 0x0D /* Unbind from the console if possible */ #define FB_EVENT_FB_UNBIND 0x0E -/* CONSOLE-SPECIFIC: remap all consoles to new fb - for vga switcheroo */ +/* CONSOLE-SPECIFIC: remap all consoles to new fb - for vga_switcheroo */ #define FB_EVENT_REMAP_ALL_CONSOLE 0x0F /* A hardware display blank early change occured */ #define FB_EARLY_EVENT_BLANK 0x10 -- cgit v0.10.2 From 4127838c460ab66f60ea8cdb069654972f8c277f Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Sat, 5 Sep 2015 13:40:23 +0200 Subject: vga_switcheroo: Sort headers alphabetically Signed-off-by: Lukas Wunner Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index b19a72f..67a5709 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -30,19 +30,17 @@ #define pr_fmt(fmt) "vga_switcheroo: " fmt -#include -#include -#include -#include +#include #include #include - +#include +#include #include -#include -#include #include - +#include +#include #include +#include /** * DOC: Overview -- cgit v0.10.2 From 5e7d49446b5964d2866ea1912cc9f65ab33ed76f Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Wed, 16 Sep 2015 23:25:22 -0700 Subject: drm: fix kernel-doc warnings in drm_crtc.h Fix the following 'make htmldocs' warning: .//include/drm/drm_crtc.h:929: warning: Excess struct/union/enum/typedef member 'base' description in 'drm_bridge' Signed-off-by: Geliang Tang Signed-off-by: Daniel Vetter diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index c0366e9..6566f72 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -911,7 +911,6 @@ struct drm_bridge_funcs { * @next: the next bridge in the encoder chain * @of_node: device node pointer to the bridge * @list: to keep track of all added bridges - * @base: base mode object * @funcs: control functions * @driver_private: pointer to the bridge driver's internal context */ -- cgit v0.10.2 From 942840371cde152fe57c15e0e8483b760e7763e3 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Mon, 21 Sep 2015 17:21:48 -0700 Subject: drm/fbdev: Update legacy plane->fb refcounting for atomic restore Starting with commit commit 28cc504e8d52248962f5b485bdc65f539e3fe21d Author: Rob Clark Date: Tue Aug 25 15:36:00 2015 -0400 drm/i915: enable atomic fb-helper I've been seeing some panics on i915 when the DRM master shuts down that appear to be caused by using an already-freed framebuffer (i.e., we're unexpectedly dropping our initial FB's reference count to 0 and freeing it, which causes a crash when we try to restore it later). Digging deeper, the state FB refcounting is working as expected, but we seem to be missing proper refcounting on the legacy plane->fb pointers in the new atomic fbdev code. Tracking plane->old_fb and then doing a ref/unref at the end of the fbdev restore like we do in the legacy ioctl's ensures we don't miscount references on plane->fb and avoids the panics. v2 from Daniel: Really do what the atomic ioctl does: - Also update plane->fb and plane->crtc. - Clear out plane->old_fb on failures too. v3: git add everything. Oops. v4: Also clear old_fb in all other failure paths, spotted by David. Cc: Rob Clark Cc: intel-gfx@lists.freedesktop.org Cc: David Herrmann Cc: Maarten Lankhorst Signed-off-by: Matt Roper (v1) Reviewd-by: David Herrmann Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 64fc5ca..abe9793 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -352,6 +352,8 @@ retry: drm_for_each_plane(plane, dev) { struct drm_plane_state *plane_state; + plane->old_fb = plane->fb; + plane_state = drm_atomic_get_plane_state(state, plane); if (IS_ERR(plane_state)) { ret = PTR_ERR(plane_state); @@ -382,16 +384,27 @@ retry: } ret = drm_atomic_commit(state); - if (ret != 0) - goto fail; - - return 0; fail: + drm_for_each_plane(plane, dev) { + if (ret == 0) { + struct drm_framebuffer *new_fb = plane->state->fb; + if (new_fb) + drm_framebuffer_reference(new_fb); + plane->fb = new_fb; + plane->crtc = plane->state->crtc; + + if (plane->old_fb) + drm_framebuffer_unreference(plane->old_fb); + } + plane->old_fb = NULL; + } + if (ret == -EDEADLK) goto backoff; - drm_atomic_state_free(state); + if (ret != 0) + drm_atomic_state_free(state); return ret; -- cgit v0.10.2 From eba1f35dfe145247c7eb690c7c32740fde8ec699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Sep 2015 22:43:43 +0300 Subject: drm: Move timestamping constants into drm_vblank_crtc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Collect the timestamping constants alongside the rest of the relevant stuff under drm_vblank_crtc. We can now get rid of the 'refcrtc' parameter to drm_calc_vbltimestamp_from_scanoutpos(). Signed-off-by: Ville Syrjälä Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 2236793..ecfa703 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -681,7 +681,7 @@ int amdgpu_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, /* Helper routine in DRM core does all the work: */ return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error, vblank_time, flags, - drmcrtc, &drmcrtc->hwmode); + &drmcrtc->hwmode); } const struct drm_ioctl_desc amdgpu_ioctls_kms[] = { diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 8df4133..6b2fefd 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -603,6 +603,7 @@ int drm_control(struct drm_device *dev, void *data, void drm_calc_timestamping_constants(struct drm_crtc *crtc, const struct drm_display_mode *mode) { + struct drm_vblank_crtc *vblank = &crtc->dev->vblank[drm_crtc_index(crtc)]; int linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0; int dotclock = mode->crtc_clock; @@ -628,9 +629,9 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc, DRM_ERROR("crtc %u: Can't calculate constants, dotclock = 0!\n", crtc->base.id); - crtc->pixeldur_ns = pixeldur_ns; - crtc->linedur_ns = linedur_ns; - crtc->framedur_ns = framedur_ns; + vblank->pixeldur_ns = pixeldur_ns; + vblank->linedur_ns = linedur_ns; + vblank->framedur_ns = framedur_ns; DRM_DEBUG("crtc %u: hwmode: htotal %d, vtotal %d, vdisplay %d\n", crtc->base.id, mode->crtc_htotal, @@ -651,7 +652,6 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants); * @flags: Flags to pass to driver: * 0 = Default, * DRM_CALLED_FROM_VBLIRQ = If function is called from vbl IRQ handler - * @refcrtc: CRTC which defines scanout timing * @mode: mode which defines the scanout timings * * Implements calculation of exact vblank timestamps from given drm_display_mode @@ -692,9 +692,9 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int *max_error, struct timeval *vblank_time, unsigned flags, - const struct drm_crtc *refcrtc, const struct drm_display_mode *mode) { + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; struct timeval tv_etime; ktime_t stime, etime; int vbl_status; @@ -714,9 +714,9 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, } /* Durations of frames, lines, pixels in nanoseconds. */ - framedur_ns = refcrtc->framedur_ns; - linedur_ns = refcrtc->linedur_ns; - pixeldur_ns = refcrtc->pixeldur_ns; + framedur_ns = vblank->framedur_ns; + linedur_ns = vblank->linedur_ns; + pixeldur_ns = vblank->pixeldur_ns; /* If mode timing undefined, just return as no-op: * Happens during initial modesetting of a crtc. diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 5a244ab..4cbc722 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -810,7 +810,6 @@ static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe, /* Helper routine in DRM core does all the work: */ return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error, vblank_time, flags, - crtc, &crtc->hwmode); } diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index cc6c228..425515f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -103,6 +103,7 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos, .base.head = nouveau_crtc(crtc)->index, }; struct nouveau_display *disp = nouveau_display(crtc->dev); + struct drm_vblank_crtc *vblank = &crtc->dev->vblank[drm_crtc_index(crtc)]; int ret, retry = 1; do { @@ -116,7 +117,7 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos, break; } - if (retry) ndelay(crtc->linedur_ns); + if (retry) ndelay(vblank->linedur_ns); } while (retry--); *hpos = args.scan.hline; @@ -155,7 +156,7 @@ nouveau_display_vblstamp(struct drm_device *dev, int head, int *max_error, list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { if (nouveau_crtc(crtc)->index == head) { return drm_calc_vbltimestamp_from_scanoutpos(dev, - head, max_error, time, flags, crtc, + head, max_error, time, flags, &crtc->hwmode); } } diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 4a119c2..fd9da28 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -841,7 +841,7 @@ int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, /* Helper routine in DRM core does all the work: */ return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error, vblank_time, flags, - drmcrtc, &drmcrtc->hwmode); + &drmcrtc->hwmode); } #define KMS_INVALID_IOCTL(name) \ diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 8b5ce7c..2998867 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -701,6 +701,9 @@ struct drm_vblank_crtc { u32 last_wait; /* Last vblank seqno waited per CRTC */ unsigned int inmodeset; /* Display driver is setting mode */ unsigned int pipe; /* crtc index */ + int framedur_ns; /* frame/field duration in ns */ + int linedur_ns; /* line duration in ns */ + int pixeldur_ns; /* pixel duration in ns */ bool enabled; /* so we don't call enable more than once per disable */ }; @@ -951,7 +954,6 @@ extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, unsigned int pipe, int *max_error, struct timeval *vblank_time, unsigned flags, - const struct drm_crtc *refcrtc, const struct drm_display_mode *mode); extern void drm_calc_timestamping_constants(struct drm_crtc *crtc, const struct drm_display_mode *mode); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 6566f72..683f142 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -413,9 +413,6 @@ struct drm_crtc_funcs { * @funcs: CRTC control functions * @gamma_size: size of gamma ramp * @gamma_store: gamma ramp values - * @framedur_ns: precise frame timing - * @linedur_ns: precise line timing - * @pixeldur_ns: precise pixel timing * @helper_private: mid-layer private data * @properties: property tracking for this CRTC * @state: current atomic state for this CRTC @@ -468,9 +465,6 @@ struct drm_crtc { uint32_t gamma_size; uint16_t *gamma_store; - /* Constants needed for precise vblank and swap timestamping. */ - int framedur_ns, linedur_ns, pixeldur_ns; - /* if you are using the helper */ const void *helper_private; -- cgit v0.10.2 From 3bb403bf421b5b00366a9041a7edc0a1f6494f5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Sep 2015 22:43:44 +0300 Subject: drm: Stop using linedur_ns and pixeldur_ns for vblank timestamps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit linedur_ns, and especially pixeldur_ns are becoming rather inaccurate to be used for the vblank timestamp correction. With 4k@60 the pixel duration is already below 2ns, so the amount of error due to the truncation to nanoseconds is introducing quite a bit of error. We can avoid such problems if we instead calculate the timestamp delta_ns directly from the dislay timings, avoiding the use of these intermediate truncated values. Signed-off-by: Ville Syrjälä Reviewed-by: Maarten Lankhorst [danvet: Squash in fixup from Thierry Reding for amdgpu.] Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index e3d7077..9b34a34 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -745,7 +745,8 @@ bool amdgpu_crtc_scaling_mode_fixup(struct drm_crtc *crtc, * */ int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int flags, - int *vpos, int *hpos, ktime_t *stime, ktime_t *etime) + int *vpos, int *hpos, ktime_t *stime, ktime_t *etime, + const struct drm_display_mode *mode) { u32 vbl = 0, position = 0; int vbl_start, vbl_end, vtotal, ret = 0; @@ -781,7 +782,7 @@ int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl } else { /* No: Fake something reasonable which gives at least ok results. */ - vbl_start = adev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay; + vbl_start = mode->crtc_vdisplay; vbl_end = 0; } @@ -797,7 +798,7 @@ int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl /* Inside "upper part" of vblank area? Apply corrective offset if so: */ if (in_vbl && (*vpos >= vbl_start)) { - vtotal = adev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal; + vtotal = mode->crtc_vtotal; *vpos = *vpos - vtotal; } @@ -819,8 +820,8 @@ int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl * We only do this if DRM_CALLED_FROM_VBLIRQ. */ if ((flags & DRM_CALLED_FROM_VBLIRQ) && !in_vbl) { - vbl_start = adev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay; - vtotal = adev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal; + vbl_start = mode->crtc_vdisplay; + vtotal = mode->crtc_vtotal; if (vbl_start - *vpos < vtotal / 100) { *vpos -= vtotal; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 64efe5b..2b03425 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -543,7 +543,8 @@ void amdgpu_encoder_set_active_device(struct drm_encoder *encoder); int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int flags, int *vpos, int *hpos, ktime_t *stime, - ktime_t *etime); + ktime_t *etime, + const struct drm_display_mode *mode); int amdgpu_framebuffer_init(struct drm_device *dev, struct amdgpu_framebuffer *rfb, diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 6b2fefd..9fab333 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -694,12 +694,11 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, unsigned flags, const struct drm_display_mode *mode) { - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; struct timeval tv_etime; ktime_t stime, etime; int vbl_status; int vpos, hpos, i; - int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns; + int delta_ns, duration_ns; bool invbl; if (pipe >= dev->num_crtcs) { @@ -713,15 +712,10 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, return -EIO; } - /* Durations of frames, lines, pixels in nanoseconds. */ - framedur_ns = vblank->framedur_ns; - linedur_ns = vblank->linedur_ns; - pixeldur_ns = vblank->pixeldur_ns; - /* If mode timing undefined, just return as no-op: * Happens during initial modesetting of a crtc. */ - if (framedur_ns == 0) { + if (mode->crtc_clock == 0) { DRM_DEBUG("crtc %u: Noop due to uninitialized mode.\n", pipe); return -EAGAIN; } @@ -738,8 +732,10 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, * Get vertical and horizontal scanout position vpos, hpos, * and bounding timestamps stime, etime, pre/post query. */ - vbl_status = dev->driver->get_scanout_position(dev, pipe, flags, &vpos, - &hpos, &stime, &etime); + vbl_status = dev->driver->get_scanout_position(dev, pipe, flags, + &vpos, &hpos, + &stime, &etime, + mode); /* Return as no-op if scanout query unsupported or failed. */ if (!(vbl_status & DRM_SCANOUTPOS_VALID)) { @@ -776,7 +772,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, * since start of scanout at first display scanline. delta_ns * can be negative if start of scanout hasn't happened yet. */ - delta_ns = vpos * linedur_ns + hpos * pixeldur_ns; + delta_ns = div_s64(1000000LL * (vpos * mode->crtc_htotal + hpos), + mode->crtc_clock); if (!drm_timestamp_monotonic) etime = ktime_mono_to_real(etime); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 4cbc722..ce1e0f5 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -648,12 +648,12 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc) static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, unsigned int flags, int *vpos, int *hpos, - ktime_t *stime, ktime_t *etime) + ktime_t *stime, ktime_t *etime, + const struct drm_display_mode *mode) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - const struct drm_display_mode *mode = &intel_crtc->base.hwmode; int position; int vbl_start, vbl_end, hsync_start, htotal, vtotal; bool in_vbl = true; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 425515f..a82c3cb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -133,7 +133,8 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos, int nouveau_display_scanoutpos(struct drm_device *dev, int head, unsigned int flags, - int *vpos, int *hpos, ktime_t *stime, ktime_t *etime) + int *vpos, int *hpos, ktime_t *stime, ktime_t *etime, + const struct drm_display_mode *mode) { struct drm_crtc *crtc; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h index a6213e2..4182d21 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.h +++ b/drivers/gpu/drm/nouveau/nouveau_display.h @@ -68,7 +68,8 @@ void nouveau_display_resume(struct drm_device *dev, bool runtime); int nouveau_display_vblank_enable(struct drm_device *, int); void nouveau_display_vblank_disable(struct drm_device *, int); int nouveau_display_scanoutpos(struct drm_device *, int, unsigned int, - int *, int *, ktime_t *, ktime_t *); + int *, int *, ktime_t *, ktime_t *, + const struct drm_display_mode *); int nouveau_display_vblstamp(struct drm_device *, int, int *, struct timeval *, unsigned); diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index d2e9e9e..0503af7 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -323,7 +323,8 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) */ if (update_pending && (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, 0, - &vpos, &hpos, NULL, NULL)) && + &vpos, &hpos, NULL, NULL, + &rdev->mode_info.crtcs[crtc_id]->base.hwmode)) && ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) || (vpos < 0 && !ASIC_IS_AVIVO(rdev)))) { /* crtc didn't flip in this target vblank interval, @@ -1799,7 +1800,8 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, * */ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int flags, - int *vpos, int *hpos, ktime_t *stime, ktime_t *etime) + int *vpos, int *hpos, ktime_t *stime, ktime_t *etime, + const struct drm_display_mode *mode) { u32 stat_crtc = 0, vbl = 0, position = 0; int vbl_start, vbl_end, vtotal, ret = 0; @@ -1914,7 +1916,7 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl } else { /* No: Fake something reasonable which gives at least ok results. */ - vbl_start = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay; + vbl_start = mode->crtc_vdisplay; vbl_end = 0; } @@ -1930,7 +1932,7 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl /* Inside "upper part" of vblank area? Apply corrective offset if so: */ if (in_vbl && (*vpos >= vbl_start)) { - vtotal = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal; + vtotal = mode->crtc_vtotal; *vpos = *vpos - vtotal; } @@ -1952,8 +1954,8 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl * We only do this if DRM_CALLED_FROM_VBLIRQ. */ if ((flags & DRM_CALLED_FROM_VBLIRQ) && !in_vbl) { - vbl_start = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay; - vtotal = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal; + vbl_start = mode->crtc_vdisplay; + vtotal = mode->crtc_vtotal; if (vbl_start - *vpos < vtotal / 100) { *vpos -= vtotal; diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 5751446..e30c1d7 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -126,8 +126,9 @@ struct dma_buf *radeon_gem_prime_export(struct drm_device *dev, int flags); extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int flags, - int *vpos, int *hpos, ktime_t *stime, - ktime_t *etime); + int *vpos, int *hpos, + ktime_t *stime, ktime_t *etime, + const struct drm_display_mode *mode); extern bool radeon_is_px(struct drm_device *dev); extern const struct drm_ioctl_desc radeon_ioctls_kms[]; extern int radeon_max_kms_ioctl; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index aecc3e3..2317d04 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -876,8 +876,9 @@ extern void radeon_cursor_reset(struct drm_crtc *crtc); extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int flags, - int *vpos, int *hpos, ktime_t *stime, - ktime_t *etime); + int *vpos, int *hpos, + ktime_t *stime, ktime_t *etime, + const struct drm_display_mode *mode); extern bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev); extern struct edid * diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 05751f3..10f4c12 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -1733,7 +1733,9 @@ static bool radeon_pm_in_vbl(struct radeon_device *rdev) */ for (crtc = 0; (crtc < rdev->num_crtc) && in_vbl; crtc++) { if (rdev->pm.active_crtcs & (1 << crtc)) { - vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, crtc, 0, &vpos, &hpos, NULL, NULL); + vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, crtc, 0, + &vpos, &hpos, NULL, NULL, + &rdev->mode_info.crtcs[crtc]->base.hwmode); if ((vbl_status & DRM_SCANOUTPOS_VALID) && !(vbl_status & DRM_SCANOUTPOS_IN_VBLANK)) in_vbl = false; diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 2998867..b2a95e7 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -482,6 +482,7 @@ struct drm_driver { * scanout position query. Can be NULL to skip timestamp. * \param *etime Target location for timestamp taken immediately after * scanout position query. Can be NULL to skip timestamp. + * \param mode Current display timings. * * Returns vpos as a positive number while in active scanout area. * Returns vpos as a negative number inside vblank, counting the number @@ -499,8 +500,9 @@ struct drm_driver { */ int (*get_scanout_position) (struct drm_device *dev, int crtc, unsigned int flags, - int *vpos, int *hpos, ktime_t *stime, - ktime_t *etime); + int *vpos, int *hpos, + ktime_t *stime, ktime_t *etime, + const struct drm_display_mode *mode); /** * Called by \c drm_get_last_vbltimestamp. Should return a precise -- cgit v0.10.2 From 20b2020334110f9afb8316ba158b9549f2f07ff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Sep 2015 22:43:45 +0300 Subject: drm: Kill pixeldur_ns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pixeldur_ns is now unsued, so kill it from drm_vblank_crtc. framedur_ns is also currently unused but we will have use for it in the near future so leave it be. linedur_ns is still used by nouveau for some internal delays. Signed-off-by: Ville Syrjälä Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 9fab333..ac17602 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -604,7 +604,7 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc, const struct drm_display_mode *mode) { struct drm_vblank_crtc *vblank = &crtc->dev->vblank[drm_crtc_index(crtc)]; - int linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0; + int linedur_ns = 0, framedur_ns = 0; int dotclock = mode->crtc_clock; /* Valid dotclock? */ @@ -613,10 +613,9 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc, /* * Convert scanline length in pixels and video - * dot clock to line duration, frame duration - * and pixel duration in nanoseconds: + * dot clock to line duration and frame duration + * in nanoseconds: */ - pixeldur_ns = 1000000 / dotclock; linedur_ns = div_u64((u64) mode->crtc_htotal * 1000000, dotclock); framedur_ns = div_u64((u64) frame_size * 1000000, dotclock); @@ -629,16 +628,14 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc, DRM_ERROR("crtc %u: Can't calculate constants, dotclock = 0!\n", crtc->base.id); - vblank->pixeldur_ns = pixeldur_ns; vblank->linedur_ns = linedur_ns; vblank->framedur_ns = framedur_ns; DRM_DEBUG("crtc %u: hwmode: htotal %d, vtotal %d, vdisplay %d\n", crtc->base.id, mode->crtc_htotal, mode->crtc_vtotal, mode->crtc_vdisplay); - DRM_DEBUG("crtc %u: clock %d kHz framedur %d linedur %d, pixeldur %d\n", - crtc->base.id, dotclock, framedur_ns, - linedur_ns, pixeldur_ns); + DRM_DEBUG("crtc %u: clock %d kHz framedur %d linedur %d\n", + crtc->base.id, dotclock, framedur_ns, linedur_ns); } EXPORT_SYMBOL(drm_calc_timestamping_constants); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index b2a95e7..6717a7d 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -705,7 +705,6 @@ struct drm_vblank_crtc { unsigned int pipe; /* crtc index */ int framedur_ns; /* frame/field duration in ns */ int linedur_ns; /* line duration in ns */ - int pixeldur_ns; /* pixel duration in ns */ bool enabled; /* so we don't call enable more than once per disable */ }; -- cgit v0.10.2 From 66f59c5ccf50eec42bbe4f5029ad9434f73eaf75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Sep 2015 22:43:46 +0300 Subject: drm/i915: Fix vblank count variable types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vblank counts are u32 so make flip_queued_vblank and flip_ready_vblank u32 as well. Signed-off-by: Ville Syrjälä Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index bfd1204..354432f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -834,8 +834,8 @@ struct intel_unpin_work { u32 flip_count; u32 gtt_offset; struct drm_i915_gem_request *flip_queued_req; - int flip_queued_vblank; - int flip_ready_vblank; + u32 flip_queued_vblank; + u32 flip_ready_vblank; bool enable_stall_check; }; -- cgit v0.10.2 From a6e610dcce3c8cbd5217527a089c8811d4412184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Sep 2015 22:43:47 +0300 Subject: drm: Pass flags to drm_update_vblank_count() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We'll soon have use for the 'flags' in drm_update_vblank_count() so pass it in. Signed-off-by: Ville Syrjälä Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index ac17602..0353224 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -120,7 +120,8 @@ static void store_vblank(struct drm_device *dev, unsigned int pipe, * Note: caller must hold dev->vbl_lock since this reads & writes * device vblank fields. */ -static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe) +static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, + unsigned long flags) { struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; u32 cur_vblank, diff; @@ -141,7 +142,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe) */ do { cur_vblank = dev->driver->get_vblank_counter(dev, pipe); - rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, 0); + rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, flags); } while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe)); /* Deal with counter wrap */ @@ -207,7 +208,7 @@ static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe) */ if (!vblank->enabled && drm_get_last_vbltimestamp(dev, pipe, &tvblank, 0)) { - drm_update_vblank_count(dev, pipe); + drm_update_vblank_count(dev, pipe, 0); spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); return; } @@ -1027,7 +1028,7 @@ static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe) atomic_dec(&vblank->refcount); else { vblank->enabled = true; - drm_update_vblank_count(dev, pipe); + drm_update_vblank_count(dev, pipe, 0); } } -- cgit v0.10.2 From facfb062e8c958f321c366c6ea3d98db899a4c6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Sep 2015 22:43:48 +0300 Subject: drm: Limit the number of .get_vblank_counter() retries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pontential infinite loops in the vblank code are a bad idea. Add some limits. Signed-off-by: Ville Syrjälä Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 0353224..93fe582 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -127,6 +127,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, u32 cur_vblank, diff; bool rc; struct timeval t_vblank; + int count = DRM_TIMESTAMP_MAXRETRIES; /* * Interrupts were disabled prior to this call, so deal with counter @@ -143,7 +144,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, do { cur_vblank = dev->driver->get_vblank_counter(dev, pipe); rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, flags); - } while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe)); + } while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe) && --count > 0); /* Deal with counter wrap */ diff = cur_vblank - vblank->last; @@ -914,6 +915,7 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, struct timeval *vblanktime) { struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + int count = DRM_TIMESTAMP_MAXRETRIES; u32 cur_vblank; if (WARN_ON(pipe >= dev->num_crtcs)) @@ -929,7 +931,7 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, smp_rmb(); *vblanktime = vblanktimestamp(dev, pipe, cur_vblank); smp_rmb(); - } while (cur_vblank != vblank->count); + } while (cur_vblank != vblank->count && --count > 0); return cur_vblank; } -- cgit v0.10.2 From ad1716ecca9d9099199cfc9278672c17d1484c75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Sep 2015 22:43:49 +0300 Subject: drm: Clean up drm_calc_vbltimestamp_from_scanoutpos() vbl_status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid confusion and don't use 'vbl_status' as both the .get_scanout_position() return value and the return value from drm_calc_vbltimestamp_from_scanoutpos(). While at it make 'vbl_status' unsigned and print it as hex in the debug prints since it's a bitmask. Signed-off-by: Ville Syrjälä Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 93fe582..aad4f1d 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -695,10 +695,10 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, { struct timeval tv_etime; ktime_t stime, etime; - int vbl_status; + unsigned int vbl_status; + int ret = DRM_VBLANKTIME_SCANOUTPOS_METHOD; int vpos, hpos, i; int delta_ns, duration_ns; - bool invbl; if (pipe >= dev->num_crtcs) { DRM_ERROR("Invalid crtc %u\n", pipe); @@ -738,7 +738,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, /* Return as no-op if scanout query unsupported or failed. */ if (!(vbl_status & DRM_SCANOUTPOS_VALID)) { - DRM_DEBUG("crtc %u : scanoutpos query failed [%d].\n", + DRM_DEBUG("crtc %u : scanoutpos query failed [0x%x].\n", pipe, vbl_status); return -EIO; } @@ -765,7 +765,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, * within vblank area, counting down the number of lines until * start of scanout. */ - invbl = vbl_status & DRM_SCANOUTPOS_IN_VBLANK; + if (vbl_status & DRM_SCANOUTPOS_IN_VBLANK) + ret |= DRM_VBLANKTIME_IN_VBLANK; /* Convert scanout position into elapsed time at raw_time query * since start of scanout at first display scanline. delta_ns @@ -788,17 +789,13 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, etime = ktime_sub_ns(etime, delta_ns); *vblank_time = ktime_to_timeval(etime); - DRM_DEBUG("crtc %u : v %d p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n", - pipe, (int)vbl_status, hpos, vpos, + DRM_DEBUG("crtc %u : v 0x%x p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n", + pipe, vbl_status, hpos, vpos, (long)tv_etime.tv_sec, (long)tv_etime.tv_usec, (long)vblank_time->tv_sec, (long)vblank_time->tv_usec, duration_ns/1000, i); - vbl_status = DRM_VBLANKTIME_SCANOUTPOS_METHOD; - if (invbl) - vbl_status |= DRM_VBLANKTIME_IN_VBLANK; - - return vbl_status; + return ret; } EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos); -- cgit v0.10.2 From 1b2eb71050915d88e62a0ca0c448e0e93484ae9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Sep 2015 22:43:50 +0300 Subject: drm: store_vblank() is never called with NULL timestamp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the NULL 't_vblank' checks from store_vblank() since that will never happen. Signed-off-by: Ville Syrjälä Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index aad4f1d..07b0cb1 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -83,13 +83,11 @@ static void store_vblank(struct drm_device *dev, unsigned int pipe, assert_spin_locked(&dev->vblank_time_lock); - if (t_vblank) { - /* All writers hold the spinlock, but readers are serialized by - * the latching of vblank->count below. - */ - tslot = vblank->count + vblank_count_inc; - vblanktimestamp(dev, pipe, tslot) = *t_vblank; - } + /* All writers hold the spinlock, but readers are serialized by + * the latching of vblank->count below. + */ + tslot = vblank->count + vblank_count_inc; + vblanktimestamp(dev, pipe, tslot) = *t_vblank; /* * vblank timestamp updates are protected on the write side with -- cgit v0.10.2 From 4dfd64862ff852df7b1198d667dda778715ee88f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Sep 2015 22:43:51 +0300 Subject: drm: Use vblank timestamps to guesstimate how many vblanks were missed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When lacking am accurate hardware frame counter, we can fall back to using the vblank timestamps to guesstimagte how many vblanks have elapsed since the last time the vblank counter was updated. Take the oppostunity to unify the vblank_disable_and_save() and drm_handle_vblank_events() to call the same function (drm_update_vblank_count()) to perform the vblank updates. If the hardware/driver has an accurate frame counter use it instead of the timestamp based guesstimate. If the hardware/driver has neither a frame counter nor acurate vblank timestamps, we fall back to assuming that each drm_handle_vblank_events() should increment the vblank count by one. Signed-off-by: Ville Syrjälä Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 07b0cb1..88fbee4 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -76,13 +76,15 @@ module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600); static void store_vblank(struct drm_device *dev, unsigned int pipe, u32 vblank_count_inc, - struct timeval *t_vblank) + struct timeval *t_vblank, u32 last) { struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; u32 tslot; assert_spin_locked(&dev->vblank_time_lock); + vblank->last = last; + /* All writers hold the spinlock, but readers are serialized by * the latching of vblank->count below. */ @@ -103,6 +105,54 @@ static void store_vblank(struct drm_device *dev, unsigned int pipe, } /** + * drm_reset_vblank_timestamp - reset the last timestamp to the last vblank + * @dev: DRM device + * @pipe: index of CRTC for which to reset the timestamp + * + * Reset the stored timestamp for the current vblank count to correspond + * to the last vblank occurred. + * + * Only to be called from drm_vblank_on(). + * + * Note: caller must hold dev->vbl_lock since this reads & writes + * device vblank fields. + */ +static void drm_reset_vblank_timestamp(struct drm_device *dev, unsigned int pipe) +{ + u32 cur_vblank; + bool rc; + struct timeval t_vblank; + int count = DRM_TIMESTAMP_MAXRETRIES; + + spin_lock(&dev->vblank_time_lock); + + /* + * sample the current counter to avoid random jumps + * when drm_vblank_enable() applies the diff + */ + do { + cur_vblank = dev->driver->get_vblank_counter(dev, pipe); + rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, 0); + } while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe) && --count > 0); + + /* + * Only reinitialize corresponding vblank timestamp if high-precision query + * available and didn't fail. Otherwise reinitialize delayed at next vblank + * interrupt and assign 0 for now, to mark the vblanktimestamp as invalid. + */ + if (!rc) + t_vblank = (struct timeval) {0, 0}; + + /* + * +1 to make sure user will never see the same + * vblank counter value before and after a modeset + */ + store_vblank(dev, pipe, 1, &t_vblank, cur_vblank); + + spin_unlock(&dev->vblank_time_lock); +} + +/** * drm_update_vblank_count - update the master vblank counter * @dev: DRM device * @pipe: counter to update @@ -126,6 +176,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, bool rc; struct timeval t_vblank; int count = DRM_TIMESTAMP_MAXRETRIES; + int framedur_ns = vblank->framedur_ns; /* * Interrupts were disabled prior to this call, so deal with counter @@ -144,20 +195,40 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, flags); } while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe) && --count > 0); - /* Deal with counter wrap */ - diff = cur_vblank - vblank->last; - if (cur_vblank < vblank->last) { - diff += dev->max_vblank_count + 1; + if (dev->max_vblank_count != 0) { + /* trust the hw counter when it's around */ + diff = (cur_vblank - vblank->last) & dev->max_vblank_count; + } else if (rc && framedur_ns) { + const struct timeval *t_old; + u64 diff_ns; + + t_old = &vblanktimestamp(dev, pipe, vblank->count); + diff_ns = timeval_to_ns(&t_vblank) - timeval_to_ns(t_old); - DRM_DEBUG("last_vblank[%u]=0x%x, cur_vblank=0x%x => diff=0x%x\n", - pipe, vblank->last, cur_vblank, diff); + /* + * Figure out how many vblanks we've missed based + * on the difference in the timestamps and the + * frame/field duration. + */ + diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns); + + if (diff == 0 && flags & DRM_CALLED_FROM_VBLIRQ) + DRM_DEBUG("crtc %u: Redundant vblirq ignored." + " diff_ns = %lld, framedur_ns = %d)\n", + pipe, (long long) diff_ns, framedur_ns); + } else { + /* some kind of default for drivers w/o accurate vbl timestamping */ + diff = (flags & DRM_CALLED_FROM_VBLIRQ) != 0; } - DRM_DEBUG("updating vblank count on crtc %u, missed %d\n", - pipe, diff); + DRM_DEBUG("updating vblank count on crtc %u:" + " current=%u, diff=%u, hw=%u hw_last=%u\n", + pipe, vblank->count, diff, cur_vblank, vblank->last); - if (diff == 0) + if (diff == 0) { + WARN_ON_ONCE(cur_vblank != vblank->last); return; + } /* * Only reinitialize corresponding vblank timestamp if high-precision query @@ -167,7 +238,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, if (!rc) t_vblank = (struct timeval) {0, 0}; - store_vblank(dev, pipe, diff, &t_vblank); + store_vblank(dev, pipe, diff, &t_vblank, cur_vblank); } /* @@ -180,11 +251,6 @@ static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe) { struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; unsigned long irqflags; - u32 vblcount; - s64 diff_ns; - bool vblrc; - struct timeval tvblank; - int count = DRM_TIMESTAMP_MAXRETRIES; /* Prevent vblank irq processing while disabling vblank irqs, * so no updates of timestamps or count can happen after we've @@ -193,26 +259,6 @@ static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe) spin_lock_irqsave(&dev->vblank_time_lock, irqflags); /* - * If the vblank interrupt was already disabled update the count - * and timestamp to maintain the appearance that the counter - * has been ticking all along until this time. This makes the - * count account for the entire time between drm_vblank_on() and - * drm_vblank_off(). - * - * But only do this if precise vblank timestamps are available. - * Otherwise we might read a totally bogus timestamp since drivers - * lacking precise timestamp support rely upon sampling the system clock - * at vblank interrupt time. Which obviously won't work out well if the - * vblank interrupt is disabled. - */ - if (!vblank->enabled && - drm_get_last_vbltimestamp(dev, pipe, &tvblank, 0)) { - drm_update_vblank_count(dev, pipe, 0); - spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); - return; - } - - /* * Only disable vblank interrupts if they're enabled. This avoids * calling the ->disable_vblank() operation in atomic context with the * hardware potentially runtime suspended. @@ -222,47 +268,13 @@ static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe) vblank->enabled = false; } - /* No further vblank irq's will be processed after - * this point. Get current hardware vblank count and - * vblank timestamp, repeat until they are consistent. - * - * FIXME: There is still a race condition here and in - * drm_update_vblank_count() which can cause off-by-one - * reinitialization of software vblank counter. If gpu - * vblank counter doesn't increment exactly at the leading - * edge of a vblank interval, then we can lose 1 count if - * we happen to execute between start of vblank and the - * delayed gpu counter increment. - */ - do { - vblank->last = dev->driver->get_vblank_counter(dev, pipe); - vblrc = drm_get_last_vbltimestamp(dev, pipe, &tvblank, 0); - } while (vblank->last != dev->driver->get_vblank_counter(dev, pipe) && (--count) && vblrc); - - if (!count) - vblrc = 0; - - /* Compute time difference to stored timestamp of last vblank - * as updated by last invocation of drm_handle_vblank() in vblank irq. - */ - vblcount = vblank->count; - diff_ns = timeval_to_ns(&tvblank) - - timeval_to_ns(&vblanktimestamp(dev, pipe, vblcount)); - - /* If there is at least 1 msec difference between the last stored - * timestamp and tvblank, then we are currently executing our - * disable inside a new vblank interval, the tvblank timestamp - * corresponds to this new vblank interval and the irq handler - * for this vblank didn't run yet and won't run due to our disable. - * Therefore we need to do the job of drm_handle_vblank() and - * increment the vblank counter by one to account for this vblank. - * - * Skip this step if there isn't any high precision timestamp - * available. In that case we can't account for this and just - * hope for the best. + /* + * Always update the count and timestamp to maintain the + * appearance that the counter has been ticking all along until + * this time. This makes the count account for the entire time + * between drm_vblank_on() and drm_vblank_off(). */ - if (vblrc && (abs64(diff_ns) > 1000000)) - store_vblank(dev, pipe, 1, &tvblank); + drm_update_vblank_count(dev, pipe, 0); spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); } @@ -1325,16 +1337,8 @@ void drm_vblank_on(struct drm_device *dev, unsigned int pipe) vblank->inmodeset = 0; } - /* - * sample the current counter to avoid random jumps - * when drm_vblank_enable() applies the diff - * - * -1 to make sure user will never see the same - * vblank counter value before and after a modeset - */ - vblank->last = - (dev->driver->get_vblank_counter(dev, pipe) - 1) & - dev->max_vblank_count; + drm_reset_vblank_timestamp(dev, pipe); + /* * re-enable interrupts if there are users left, or the * user wishes vblank interrupts to be enabled all the time. @@ -1717,9 +1721,6 @@ static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe) bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe) { struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; - u32 vblcount; - s64 diff_ns; - struct timeval tvblank; unsigned long irqflags; if (WARN_ON_ONCE(!dev->num_crtcs)) @@ -1743,32 +1744,7 @@ bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe) return false; } - /* Fetch corresponding timestamp for this vblank interval from - * driver and store it in proper slot of timestamp ringbuffer. - */ - - /* Get current timestamp and count. */ - vblcount = vblank->count; - drm_get_last_vbltimestamp(dev, pipe, &tvblank, DRM_CALLED_FROM_VBLIRQ); - - /* Compute time difference to timestamp of last vblank */ - diff_ns = timeval_to_ns(&tvblank) - - timeval_to_ns(&vblanktimestamp(dev, pipe, vblcount)); - - /* Update vblank timestamp and count if at least - * DRM_REDUNDANT_VBLIRQ_THRESH_NS nanoseconds - * difference between last stored timestamp and current - * timestamp. A smaller difference means basically - * identical timestamps. Happens if this vblank has - * been already processed and this is a redundant call, - * e.g., due to spurious vblank interrupts. We need to - * ignore those for accounting. - */ - if (abs64(diff_ns) > DRM_REDUNDANT_VBLIRQ_THRESH_NS) - store_vblank(dev, pipe, 1, &tvblank); - else - DRM_DEBUG("crtc %u: Redundant vblirq ignored. diff_ns = %d\n", - pipe, (int) diff_ns); + drm_update_vblank_count(dev, pipe, DRM_CALLED_FROM_VBLIRQ); spin_unlock(&dev->vblank_time_lock); -- cgit v0.10.2 From 13803132818cf8084d169617be060fd8e3411a98 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 9 Sep 2015 16:40:56 +0200 Subject: drm/core: Preserve the framebuffer after removing it. Previously RMFB and fd close chose to disable any plane that had an active framebuffer from this file. If it was a primary plane the crtc was disabled. However the fbdev code or any system compositor should restore the planes anyway so there's no need to do it twice. The old fb_id is zero'd, so there's no danger of being able to restore the fb from fb_id. Signed-off-by: Maarten Lankhorst Reviewed-by: David Herrmann Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 9b9c4b4..626b0a5 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -3327,7 +3327,7 @@ int drm_mode_rmfb(struct drm_device *dev, mutex_unlock(&dev->mode_config.fb_lock); mutex_unlock(&file_priv->fbs_lock); - drm_framebuffer_remove(fb); + drm_framebuffer_unreference(fb); return 0; @@ -3517,7 +3517,7 @@ void drm_fb_release(struct drm_file *priv) list_del_init(&fb->filp_head); /* This will also drop the fpriv->fbs reference. */ - drm_framebuffer_remove(fb); + drm_framebuffer_unreference(fb); } } -- cgit v0.10.2 From 73f7570bc6c853ca1fad24f9d31815b20e405354 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 9 Sep 2015 16:40:57 +0200 Subject: drm/core: Preserve the fb id on close. Keep the fb_id, which means that any application exiting without unsetting the framebuffer from all planes will preserve its contents. This is similar to preserving the initial framebuffer, except all planes are preserved. Signed-off-by: Maarten Lankhorst Reviewed-by: David Herrmann [danvet: Remove unused variable, reported by Stephen Rothwell.] Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 626b0a5..e600a5f 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -3320,9 +3320,6 @@ int drm_mode_rmfb(struct drm_device *dev, if (!found) goto fail_lookup; - /* Mark fb as reaped, we still have a ref from fpriv->fbs. */ - __drm_framebuffer_unregister(dev, fb); - list_del_init(&fb->filp_head); mutex_unlock(&dev->mode_config.fb_lock); mutex_unlock(&file_priv->fbs_lock); @@ -3494,7 +3491,6 @@ out_err1: */ void drm_fb_release(struct drm_file *priv) { - struct drm_device *dev = priv->minor->dev; struct drm_framebuffer *fb, *tfb; /* @@ -3508,15 +3504,9 @@ void drm_fb_release(struct drm_file *priv) * at it any more. */ list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { - - mutex_lock(&dev->mode_config.fb_lock); - /* Mark fb as reaped, we still have a ref from fpriv->fbs. */ - __drm_framebuffer_unregister(dev, fb); - mutex_unlock(&dev->mode_config.fb_lock); - list_del_init(&fb->filp_head); - /* This will also drop the fpriv->fbs reference. */ + /* This drops the fpriv->fbs reference. */ drm_framebuffer_unreference(fb); } } -- cgit v0.10.2 From 21b45676b7c4b79334d8fe3c5a112af0517b66e9 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Thu, 27 Aug 2015 16:43:43 +0200 Subject: vga_switcheroo: Set active attribute to false for audio clients The active attribute in struct vga_switcheroo_client denotes whether the outputs are currently switched to this client. The attribute is only meaningful for vga clients. It is never used for audio clients. The function vga_switcheroo_register_audio_client() misuses this attribute to store whether the audio device is fully initialized. Most likely there was a misunderstanding about the meaning of "active" when this was added. Comment from Takashi's review: "Not really. The full initialization of audio was meant that the audio is active indeed. Admittedly, though, the active flag for each audio client doesn't play any role because the audio always follows the gfx state changes, and the value passed there doesn't reflect the actual state due to the later change. So, I agree with the removal of the flag itself -- or let the audio active flag following the corresponding gfx flag. The latter will make the proc output more consistent while the former is certainly more reduction of code." Set the active attribute to false for audio clients. Remove the active parameter from vga_switcheroo_register_audio_client() and its sole caller, hda_intel.c:register_vga_switcheroo(). vga_switcheroo_register_audio_client() was introduced by 3e9e63dbd374 ("vga_switcheroo: Add the support for audio clients"). Its use in hda_intel.c was introduced by a82d51ed24bb ("ALSA: hda - Support VGA-switcheroo"). v1.1: The changes above imply that in find_active_client() the call to client_is_vga() is now superfluous. Drop it. Cc: Takashi Iwai Signed-off-by: Lukas Wunner [danvet: Add Takashi's clarification to the commit message.] Reviewed-by: Takashi Iwai Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index 67a5709..86c03b5 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -288,7 +288,6 @@ EXPORT_SYMBOL(vga_switcheroo_register_client); * @pdev: client pci device * @ops: client callbacks * @id: client identifier, see enum vga_switcheroo_client_id - * @active: whether the audio device is fully initialized * * Register audio client (audio device on a GPU). The power state of the * client is assumed to be ON. @@ -297,9 +296,9 @@ EXPORT_SYMBOL(vga_switcheroo_register_client); */ int vga_switcheroo_register_audio_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, - int id, bool active) + int id) { - return register_client(pdev, ops, id | ID_BIT_AUDIO, active, false); + return register_client(pdev, ops, id | ID_BIT_AUDIO, false, false); } EXPORT_SYMBOL(vga_switcheroo_register_audio_client); @@ -331,7 +330,7 @@ find_active_client(struct list_head *head) struct vga_switcheroo_client *client; list_for_each_entry(client, head, list) - if (client->active && client_is_vga(client)) + if (client->active) return client; return NULL; } diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h index fe90bfc..3764991 100644 --- a/include/linux/vga_switcheroo.h +++ b/include/linux/vga_switcheroo.h @@ -128,7 +128,7 @@ int vga_switcheroo_register_client(struct pci_dev *dev, bool driver_power_control); int vga_switcheroo_register_audio_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, - int id, bool active); + int id); void vga_switcheroo_client_fb_set(struct pci_dev *dev, struct fb_info *info); @@ -154,7 +154,7 @@ static inline void vga_switcheroo_client_fb_set(struct pci_dev *dev, struct fb_i static inline int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) { return 0; } static inline int vga_switcheroo_register_audio_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, - int id, bool active) { return 0; } + int id) { return 0; } static inline void vga_switcheroo_unregister_handler(void) {} static inline int vga_switcheroo_process_delayed_switch(void) { return 0; } static inline int vga_switcheroo_get_client_state(struct pci_dev *dev) { return VGA_SWITCHEROO_ON; } diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index c38c68f..e819013 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1143,8 +1143,7 @@ static int register_vga_switcheroo(struct azx *chip) * is there any machine with two switchable HDMI audio controllers? */ err = vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops, - VGA_SWITCHEROO_DIS, - hda->probe_continued); + VGA_SWITCHEROO_DIS); if (err < 0) return err; hda->vga_switcheroo_registered = 1; -- cgit v0.10.2 From 5fbec9014b5ab9deecb3338cd14aae82ed14d0ec Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 24 Sep 2015 10:07:32 +0200 Subject: drm/gma500: Remove DP_LINK_STATUS_SIZE redefinition The DRM/DP helpers already contain a definition for this macro. Remove the duplicate in the GMA500 driver to avoid having to keep both updated synchronously. Cc: Patrik Jakobsson Signed-off-by: Thierry Reding Reviewed-by: Patrik Jakobsson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index 0fafb8e..17cea40 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c @@ -247,7 +247,6 @@ i2c_dp_aux_add_bus(struct i2c_adapter *adapter) #define wait_for(COND, MS) _wait_for(COND, MS, 1) -#define DP_LINK_STATUS_SIZE 6 #define DP_LINK_CHECK_TIMEOUT (10 * 1000) #define DP_LINK_CONFIGURATION_SIZE 9 -- cgit v0.10.2 From bf22f3be15630234b76d7ece0b1f97627ea833a8 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Thu, 24 Sep 2015 03:01:03 -0700 Subject: drm: drm_atomic_crtc_get_property should be static Fixes the following sparse warning: drivers/gpu/drm/drm_atomic.c:442:5: warning: symbol 'drm_atomic_crtc_get_property' was not declared. Should it be static? Signed-off-by: Geliang Tang Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 940f80b..7bb3845 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -438,7 +438,8 @@ EXPORT_SYMBOL(drm_atomic_crtc_set_property); * consistent behavior you must call this function rather than the * driver hook directly. */ -int drm_atomic_crtc_get_property(struct drm_crtc *crtc, +static int +drm_atomic_crtc_get_property(struct drm_crtc *crtc, const struct drm_crtc_state *state, struct drm_property *property, uint64_t *val) { -- cgit v0.10.2 From 2b193f023dc8f43b005bc7844b07e437a4e418db Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 24 Sep 2015 18:35:30 +0200 Subject: drm/irq: Rename drm_crtc -> crtc Since the original crtc parameter was renamed to pipe, there is no longer a need to artificially prefix the CRTC parameter. Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 88fbee4..29a6dcd 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -1280,7 +1280,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_off); /** * drm_crtc_vblank_reset - reset vblank state to off on a CRTC - * @drm_crtc: CRTC in question + * @crtc: CRTC in question * * Drivers can use this function to reset the vblank state to off at load time. * Drivers should use this together with the drm_crtc_vblank_off() and @@ -1288,11 +1288,11 @@ EXPORT_SYMBOL(drm_crtc_vblank_off); * drm_crtc_vblank_off() is that this function doesn't save the vblank counter * and hence doesn't need to call any driver hooks. */ -void drm_crtc_vblank_reset(struct drm_crtc *drm_crtc) +void drm_crtc_vblank_reset(struct drm_crtc *crtc) { - struct drm_device *dev = drm_crtc->dev; + struct drm_device *dev = crtc->dev; unsigned long irqflags; - unsigned int pipe = drm_crtc_index(drm_crtc); + unsigned int pipe = drm_crtc_index(crtc); struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; spin_lock_irqsave(&dev->vbl_lock, irqflags); -- cgit v0.10.2 From cf6483050e9bf13979415d9fd388554d8c8f3477 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 24 Sep 2015 18:35:36 +0200 Subject: drm/irq: Add drm_crtc_vblank_count_and_time() This function is the KMS native variant of drm_vblank_count_and_time(). It takes a struct drm_crtc * instead of a struct drm_device * and an index of the CRTC. Eventually the goal is to access vblank data through the CRTC only so that the per-CRTC data can be moved to struct drm_crtc. Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 29a6dcd..ed2394e 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -917,6 +917,8 @@ EXPORT_SYMBOL(drm_crtc_vblank_count); * vblank events since the system was booted, including lost events due to * modesetting activity. Returns corresponding system timestamp of the time * of the vblank interval that corresponds to the current vblank counter value. + * + * This is the legacy version of drm_crtc_vblank_count_and_time(). */ u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, struct timeval *vblanktime) @@ -944,6 +946,27 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, } EXPORT_SYMBOL(drm_vblank_count_and_time); +/** + * drm_crtc_vblank_count_and_time - retrieve "cooked" vblank counter value + * and the system timestamp corresponding to that vblank counter value + * @crtc: which counter to retrieve + * @vblanktime: Pointer to struct timeval to receive the vblank timestamp. + * + * Fetches the "cooked" vblank count value that represents the number of + * vblank events since the system was booted, including lost events due to + * modesetting activity. Returns corresponding system timestamp of the time + * of the vblank interval that corresponds to the current vblank counter value. + * + * This is the native KMS version of drm_vblank_count_and_time(). + */ +u32 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc, + struct timeval *vblanktime) +{ + return drm_vblank_count_and_time(crtc->dev, drm_crtc_index(crtc), + vblanktime); +} +EXPORT_SYMBOL(drm_crtc_vblank_count_and_time); + static void send_vblank_event(struct drm_device *dev, struct drm_pending_vblank_event *e, unsigned long seq, struct timeval *now) diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 6717a7d..d0251ac 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -932,6 +932,8 @@ extern u32 drm_vblank_count(struct drm_device *dev, int pipe); extern u32 drm_crtc_vblank_count(struct drm_crtc *crtc); extern u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, struct timeval *vblanktime); +extern u32 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc, + struct timeval *vblanktime); extern void drm_send_vblank_event(struct drm_device *dev, unsigned int pipe, struct drm_pending_vblank_event *e); extern void drm_crtc_send_vblank_event(struct drm_crtc *crtc, -- cgit v0.10.2 From eef228e3191de0b62ef5913be216f25ba6b23a4c Mon Sep 17 00:00:00 2001 From: Ray Jui Date: Thu, 24 Sep 2015 15:21:23 -0700 Subject: ARM: dts: move aliases back to .dts in Cygnus Move aliases from bcm-cygnus.dtsi back to individual .dts files. Also clean up the chosen node to have the stdout-path using the proper alias Signed-off-by: Ray Jui Signed-off-by: Florian Fainelli diff --git a/arch/arm/boot/dts/bcm-cygnus.dtsi b/arch/arm/boot/dts/bcm-cygnus.dtsi index b5f9f34..2778533 100644 --- a/arch/arm/boot/dts/bcm-cygnus.dtsi +++ b/arch/arm/boot/dts/bcm-cygnus.dtsi @@ -41,10 +41,6 @@ model = "Broadcom Cygnus SoC"; interrupt-parent = <&gic>; - aliases { - serial0 = &uart3; - }; - cpus { #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/bcm911360k.dts b/arch/arm/boot/dts/bcm911360k.dts index 814011c..091c73a 100644 --- a/arch/arm/boot/dts/bcm911360k.dts +++ b/arch/arm/boot/dts/bcm911360k.dts @@ -38,9 +38,12 @@ model = "Cygnus SVK (BCM911360K)"; compatible = "brcm,bcm11360", "brcm,cygnus"; + aliases { + serial0 = &uart3; + }; + chosen { - stdout-path = &uart3; - bootargs = "console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; }; }; diff --git a/arch/arm/boot/dts/bcm958300k.dts b/arch/arm/boot/dts/bcm958300k.dts index 2e31581..b4a1392 100644 --- a/arch/arm/boot/dts/bcm958300k.dts +++ b/arch/arm/boot/dts/bcm958300k.dts @@ -39,9 +39,12 @@ model = "Cygnus SVK (BCM958300K)"; compatible = "brcm,bcm58300", "brcm,cygnus"; + aliases { + serial0 = &uart3; + }; + chosen { - stdout-path = &uart3; - bootargs = "console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; }; }; diff --git a/arch/arm/boot/dts/bcm958305k.dts b/arch/arm/boot/dts/bcm958305k.dts index 288a637..3378683 100644 --- a/arch/arm/boot/dts/bcm958305k.dts +++ b/arch/arm/boot/dts/bcm958305k.dts @@ -39,9 +39,12 @@ model = "Cygnus Wireless Audio (BCM958305K)"; compatible = "brcm,bcm58305", "brcm,cygnus"; + aliases { + serial0 = &uart3; + }; + chosen { - stdout-path = &uart3; - bootargs = "console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; }; }; -- cgit v0.10.2 From 87b045969ad3fe021ccbd1ed88e7cb90adf4ca80 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 14 Sep 2015 11:55:37 +0300 Subject: dmaengine: idma64: convert to __ffs() We replace __fls() by __ffs() since we have to find a *minimum* data width that satisfies both source and destination. Signed-off-by: Andy Shevchenko Signed-off-by: Vinod Koul diff --git a/drivers/dma/idma64.c b/drivers/dma/idma64.c index 18c14e1..13c52b8 100644 --- a/drivers/dma/idma64.c +++ b/drivers/dma/idma64.c @@ -257,15 +257,15 @@ static u64 idma64_hw_desc_fill(struct idma64_hw_desc *hw, dar = config->dst_addr; ctllo |= IDMA64C_CTLL_DST_FIX | IDMA64C_CTLL_SRC_INC | IDMA64C_CTLL_FC_M2P; - src_width = min_t(u32, 2, __fls(sar | hw->len)); - dst_width = __fls(config->dst_addr_width); + src_width = min_t(u32, 2, __ffs(sar | hw->len)); + dst_width = __ffs(config->dst_addr_width); } else { /* DMA_DEV_TO_MEM */ sar = config->src_addr; dar = hw->phys; ctllo |= IDMA64C_CTLL_DST_INC | IDMA64C_CTLL_SRC_FIX | IDMA64C_CTLL_FC_P2M; - src_width = __fls(config->src_addr_width); - dst_width = min_t(u32, 2, __fls(dar | hw->len)); + src_width = __ffs(config->src_addr_width); + dst_width = min_t(u32, 2, __ffs(dar | hw->len)); } lli->sar = sar; -- cgit v0.10.2 From 22b74406c5ac1829cd60f75c8c6a4ed1e0f4da03 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 14 Sep 2015 11:55:38 +0300 Subject: dmaengine: idma64: useless use of min_t() We use a pattern x = min_t(u32, , __ffs(expr)); There is no need to use min_t() since we can replace it by x = __ffs(expr | <2^LOG2_CONST>); and moreover guarantee that argument of __ffs() will be not zero. Signed-off-by: Andy Shevchenko Signed-off-by: Vinod Koul diff --git a/drivers/dma/idma64.c b/drivers/dma/idma64.c index 13c52b8..e91e499 100644 --- a/drivers/dma/idma64.c +++ b/drivers/dma/idma64.c @@ -257,7 +257,7 @@ static u64 idma64_hw_desc_fill(struct idma64_hw_desc *hw, dar = config->dst_addr; ctllo |= IDMA64C_CTLL_DST_FIX | IDMA64C_CTLL_SRC_INC | IDMA64C_CTLL_FC_M2P; - src_width = min_t(u32, 2, __ffs(sar | hw->len)); + src_width = __ffs(sar | hw->len | 4); dst_width = __ffs(config->dst_addr_width); } else { /* DMA_DEV_TO_MEM */ sar = config->src_addr; @@ -265,7 +265,7 @@ static u64 idma64_hw_desc_fill(struct idma64_hw_desc *hw, ctllo |= IDMA64C_CTLL_DST_INC | IDMA64C_CTLL_SRC_FIX | IDMA64C_CTLL_FC_P2M; src_width = __ffs(config->src_addr_width); - dst_width = min_t(u32, 2, __ffs(dar | hw->len)); + dst_width = __ffs(dar | hw->len | 4); } lli->sar = sar; -- cgit v0.10.2 From 581ec089a5476a9ddc8d0707e47315a2609297ad Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 14 Sep 2015 11:55:39 +0300 Subject: dmaengine: idma64: this is not DesignWare This patch fixes a comment where DesignWare is wrongly mentioned. There is no functional change. Signed-off-by: Andy Shevchenko Signed-off-by: Vinod Koul diff --git a/drivers/dma/idma64.h b/drivers/dma/idma64.h index a4d9968..323c3f1 100644 --- a/drivers/dma/idma64.h +++ b/drivers/dma/idma64.h @@ -217,7 +217,7 @@ static inline void idma64_writel(struct idma64 *idma64, int offset, u32 value) idma64_writel(idma64, IDMA64_##reg, (value)) /** - * struct idma64_chip - representation of DesignWare DMA controller hardware + * struct idma64_chip - representation of iDMA 64-bit controller hardware * @dev: struct device of the DMA controller * @irq: irq line * @regs: memory mapped I/O space -- cgit v0.10.2 From 2e9b55becc905207eb01e24bc282f8062cc497b5 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 14 Sep 2015 11:55:40 +0300 Subject: dmaengine: idma64: make better performance on pause / resume Accordingly to the documentation the CH_DRAIN bit enforses single bursts when channel is going to be suspended. This, in case when channel will be resumed, makes data to flow in non-optimal mode until DMA returns to full burst mode. The fix differentiates pause / resume cycle from pause / terminate and sets CH_DRAIN bit accordingly. Signed-off-by: Andy Shevchenko Signed-off-by: Vinod Koul diff --git a/drivers/dma/idma64.c b/drivers/dma/idma64.c index e91e499..39e6ab1 100644 --- a/drivers/dma/idma64.c +++ b/drivers/dma/idma64.c @@ -65,9 +65,6 @@ static void idma64_chan_init(struct idma64 *idma64, struct idma64_chan *idma64c) u32 cfghi = IDMA64C_CFGH_SRC_PER(1) | IDMA64C_CFGH_DST_PER(0); u32 cfglo = 0; - /* Enforce FIFO drain when channel is suspended */ - cfglo |= IDMA64C_CFGL_CH_DRAIN; - /* Set default burst alignment */ cfglo |= IDMA64C_CFGL_DST_BURST_ALIGN | IDMA64C_CFGL_SRC_BURST_ALIGN; @@ -428,12 +425,17 @@ static int idma64_slave_config(struct dma_chan *chan, return 0; } -static void idma64_chan_deactivate(struct idma64_chan *idma64c) +static void idma64_chan_deactivate(struct idma64_chan *idma64c, bool drain) { unsigned short count = 100; u32 cfglo; cfglo = channel_readl(idma64c, CFG_LO); + if (drain) + cfglo |= IDMA64C_CFGL_CH_DRAIN; + else + cfglo &= ~IDMA64C_CFGL_CH_DRAIN; + channel_writel(idma64c, CFG_LO, cfglo | IDMA64C_CFGL_CH_SUSP); do { udelay(1); @@ -456,7 +458,7 @@ static int idma64_pause(struct dma_chan *chan) spin_lock_irqsave(&idma64c->vchan.lock, flags); if (idma64c->desc && idma64c->desc->status == DMA_IN_PROGRESS) { - idma64_chan_deactivate(idma64c); + idma64_chan_deactivate(idma64c, false); idma64c->desc->status = DMA_PAUSED; } spin_unlock_irqrestore(&idma64c->vchan.lock, flags); @@ -486,7 +488,7 @@ static int idma64_terminate_all(struct dma_chan *chan) LIST_HEAD(head); spin_lock_irqsave(&idma64c->vchan.lock, flags); - idma64_chan_deactivate(idma64c); + idma64_chan_deactivate(idma64c, true); idma64_stop_transfer(idma64c); if (idma64c->desc) { idma64_vdesc_free(&idma64c->desc->vdesc); -- cgit v0.10.2 From 97c37accd38f6136fa0abbdef01b5f864e91e6c7 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 14 Sep 2015 11:55:41 +0300 Subject: dmaengine: idma64: use lo_hi_readq() / lo_hi_writeq() There are already helper functions to do 64-bit I/O on 32-bit machines, thus we don't need to reinvent the wheel. In our case we can't use readq() / writeq() even on 64-bit kernel since there is a hardware limitation (OCP bus is a 32-bit bus). Signed-off-by: Andy Shevchenko Signed-off-by: Vinod Koul diff --git a/drivers/dma/idma64.h b/drivers/dma/idma64.h index 323c3f1..f6aeff0 100644 --- a/drivers/dma/idma64.h +++ b/drivers/dma/idma64.h @@ -16,6 +16,8 @@ #include #include +#include + #include "virt-dma.h" /* Channel registers */ @@ -166,19 +168,13 @@ static inline void idma64c_writel(struct idma64_chan *idma64c, int offset, static inline u64 idma64c_readq(struct idma64_chan *idma64c, int offset) { - u64 l, h; - - l = idma64c_readl(idma64c, offset); - h = idma64c_readl(idma64c, offset + 4); - - return l | (h << 32); + return lo_hi_readq(idma64c->regs + offset); } static inline void idma64c_writeq(struct idma64_chan *idma64c, int offset, u64 value) { - idma64c_writel(idma64c, offset, value); - idma64c_writel(idma64c, offset + 4, value >> 32); + lo_hi_writeq(value, idma64c->regs + offset); } #define channel_readq(idma64c, reg) \ -- cgit v0.10.2 From 7cb5dff8d59da8008c6ec30d4161e8e96aa4afe8 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Fri, 25 Sep 2015 03:58:11 -0700 Subject: drm/i915: fix task reference leak in i915_debugfs.c Leak a task reference in i915_ppgtt_info(), add put_task_struct() to fix it. Introduced by commit 1c60fef535d143860d5bf6593e24ab6417f5227c Author: Ben Widawsky Date: Fri Dec 6 14:11:30 2013 -0800 drm/i915: Dump all ppgtt Signed-off-by: Geliang Tang [danvet: Add note provided by Jani about which commit introduced this issue.] Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 5615d3d..8797717 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2288,9 +2288,13 @@ static int i915_ppgtt_info(struct seq_file *m, void *data) list_for_each_entry_reverse(file, &dev->filelist, lhead) { struct drm_i915_file_private *file_priv = file->driver_priv; + struct task_struct *task; - seq_printf(m, "\nproc: %s\n", - get_pid_task(file->pid, PIDTYPE_PID)->comm); + task = get_pid_task(file->pid, PIDTYPE_PID); + if (!task) + return -ESRCH; + seq_printf(m, "\nproc: %s\n", task->comm); + put_task_struct(task); idr_for_each(&file_priv->context_idr, per_file_ctx, (void *)(unsigned long)m); } -- cgit v0.10.2 From 48a629da63480089561d794b316644b4362b0a82 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 12 Sep 2015 13:36:49 +0200 Subject: ARM: pxa: add resources to pxaficp_ir Add io memory and dma requestor lines to the irda pxa device. This is part of the conversion of pxaficp_ir to dmaengine, and to shrink its adherence to 'mach' includes. Signed-off-by: Robert Jarzmik Tested-by: Petr Cvek diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c index c624732..2a6e0ae 100644 --- a/arch/arm/mach-pxa/devices.c +++ b/arch/arm/mach-pxa/devices.c @@ -395,6 +395,26 @@ static struct resource pxa_ir_resources[] = { .end = IRQ_ICP, .flags = IORESOURCE_IRQ, }, + [3] = { + .start = 0x40800000, + .end = 0x4080001b, + .flags = IORESOURCE_MEM, + }, + [4] = { + .start = 0x40700000, + .end = 0x40700023, + .flags = IORESOURCE_MEM, + }, + [5] = { + .start = 17, + .end = 17, + .flags = IORESOURCE_DMA, + }, + [6] = { + .start = 18, + .end = 18, + .flags = IORESOURCE_DMA, + }, }; struct platform_device pxa_device_ficp = { -- cgit v0.10.2 From 688538636bec2d49d6aae3f9c152216c7aafb8e7 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Fri, 18 Sep 2015 18:40:12 +0200 Subject: ARM: pxa: mioa701: add wm9713 codec The mioa701 is using the wm9713 for audio, battery and touchscreen. Add the missing audio part, which disappeared. Signed-off-by: Robert Jarzmik diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c index 29997bd..02317ad 100644 --- a/arch/arm/mach-pxa/mioa701.c +++ b/arch/arm/mach-pxa/mioa701.c @@ -678,6 +678,7 @@ MIO_SIMPLE_DEV(mioa701_led, "leds-gpio", &gpio_led_info) MIO_SIMPLE_DEV(pxa2xx_pcm, "pxa2xx-pcm", NULL) MIO_SIMPLE_DEV(mioa701_sound, "mioa701-wm9713", NULL) MIO_SIMPLE_DEV(mioa701_board, "mioa701-board", NULL) +MIO_SIMPLE_DEV(wm9713_acodec, "wm9713-codec", NULL); MIO_SIMPLE_DEV(gpio_vbus, "gpio-vbus", &gpio_vbus_data); MIO_SIMPLE_DEV(mioa701_camera, "soc-camera-pdrv",&iclink); @@ -685,6 +686,7 @@ static struct platform_device *devices[] __initdata = { &mioa701_gpio_keys, &mioa701_backlight, &mioa701_led, + &wm9713_acodec, &pxa2xx_pcm, &mioa701_sound, &power_dev, -- cgit v0.10.2 From 465274d73c7b17578cf1f2444c50086bb2697c2c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 7 Aug 2015 17:22:35 +0200 Subject: ARM: dts: sun6i: Columbus: Add i2c controller for communicating with the LCD The Colombus development kit uses an optional 2048x1536 edp panel using an anx9804 parallel lcd to edp converter. The anx9804 chip is controlled via an i2c bus which is connected to 2 regular gpio pins. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun6i-a31-colombus.dts b/arch/arm/boot/dts/sun6i-a31-colombus.dts index 0cf9926..8843420 100644 --- a/arch/arm/boot/dts/sun6i-a31-colombus.dts +++ b/arch/arm/boot/dts/sun6i-a31-colombus.dts @@ -60,6 +60,16 @@ chosen { stdout-path = "serial0:115200n8"; }; + + i2c_lcd: i2c@0 { + /* The lcd panel i2c interface is hooked up via gpios */ + compatible = "i2c-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c_lcd_pins>; + gpios = <&pio 0 23 GPIO_ACTIVE_HIGH>, /* PA23, sda */ + <&pio 0 24 GPIO_ACTIVE_HIGH>; /* PA24, scl */ + i2c-gpio,delay-us = <5>; + }; }; &ehci1 { @@ -112,6 +122,13 @@ allwinner,drive = ; allwinner,pull = ; }; + + i2c_lcd_pins: i2c_lcd_pin@0 { + allwinner,pins = "PA23", "PA24"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; }; ®_usb2_vbus { -- cgit v0.10.2 From af283532415f756900807c2b5ca0312c01e57cde Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Aug 2015 16:44:32 +0200 Subject: ARM: dts: sun5i: Add simplefb node for tvencoder output Add a simplefb node for tvencoder / composite-video output, such as found on the Auxtek-T003 and the CHIP. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi index a513b41..7dd016f 100644 --- a/arch/arm/boot/dts/sun5i-a10s.dtsi +++ b/arch/arm/boot/dts/sun5i-a10s.dtsi @@ -77,6 +77,15 @@ clocks = <&pll5 1>, <&ahb_gates 36>, <&ahb_gates 44>; status = "disabled"; }; + + framebuffer@2 { + compatible = "allwinner,simple-framebuffer", + "simple-framebuffer"; + allwinner,pipeline = "de_be0-lcd0-tve0"; + clocks = <&pll5 1>, <&ahb_gates 34>, <&ahb_gates 36>, + <&ahb_gates 44>; + status = "disabled"; + }; }; clocks { -- cgit v0.10.2 From 770df8c87eda3185cd16fbf11638145e098d545e Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Fri, 14 Aug 2015 16:44:34 +0200 Subject: ARM: dts: sun7i: Add regulator configuration to the pcduino3 dts file Add regulator configuration to the pcduino3 dts file. Signed-off-by: Jelle van der Waa Signed-off-by: Hans de Goede [Maxime: Removed usb_power_supply node that isn't defined in the DTSI] Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun7i-a20-pcduino3.dts b/arch/arm/boot/dts/sun7i-a20-pcduino3.dts index afc9ece..ad8169d 100644 --- a/arch/arm/boot/dts/sun7i-a20-pcduino3.dts +++ b/arch/arm/boot/dts/sun7i-a20-pcduino3.dts @@ -111,6 +111,10 @@ allwinner,pins = "PH2"; }; +&cpu0 { + cpu-supply = <®_dcdc2>; +}; + &ehci0 { status = "okay"; }; @@ -137,16 +141,14 @@ status = "okay"; axp209: pmic@34 { - compatible = "x-powers,axp209"; reg = <0x34>; interrupt-parent = <&nmi_intc>; interrupts = <0 IRQ_TYPE_LEVEL_LOW>; - - interrupt-controller; - #interrupt-cells = <1>; }; }; +#include "axp209.dtsi" + &ir0 { pinctrl-names = "default"; pinctrl-0 = <&ir0_rx_pins_a>; @@ -192,6 +194,31 @@ status = "okay"; }; +®_dcdc2 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-cpu"; +}; + +®_dcdc3 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-int-pll"; +}; + +®_ldo1 { + regulator-name = "vdd-rtc"; +}; + +®_ldo2 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "avcc"; +}; + ®_usb1_vbus { status = "okay"; }; -- cgit v0.10.2 From 2f40620aedab9c2de1c3be76ce3af6cea6903bd6 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Aug 2015 16:44:37 +0200 Subject: ARM: dts: sun8i: Add support for qt90h-v4 tablets The gt90h is a pcb found in generic 9" tablets with an A23 soc, 1G RAM and 8G nand, rtl8723as usb wifi, 1 micro usb port and 1 micro sd slot. This commit adds a dts for v4 of the gt90h pcb. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index bb8fa02..1920876 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -622,6 +622,7 @@ dtb-$(CONFIG_MACH_SUN7I) += \ sun7i-a20-wexler-tab7200.dtb dtb-$(CONFIG_MACH_SUN8I) += \ sun8i-a23-evb.dtb \ + sun8i-a23-gt90h-v4.dtb \ sun8i-a23-ippo-q8h-v5.dtb \ sun8i-a23-ippo-q8h-v1.2.dtb \ sun8i-a33-et-q8-v1.6.dtb \ diff --git a/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts b/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts new file mode 100644 index 0000000..1aeb06c --- /dev/null +++ b/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts @@ -0,0 +1,145 @@ +/* + * Copyright 2015 Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun8i-a23.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include +#include +#include + +/ { + model = "Allwinner GT90H Quad Core Tablet (v4)"; + compatible = "allwinner,gt90h-v4", "allwinner,sun8i-a33"; + + aliases { + serial0 = &r_uart; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&ehci0 { + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; +}; + +&lradc { + vref-supply = <®_vcc3v0>; + status = "okay"; + + button@200 { + label = "Volume Up"; + linux,code = ; + channel = <0>; + voltage = <200000>; + }; + + button@400 { + label = "Volume Down"; + linux,code = ; + channel = <0>; + voltage = <400000>; + }; + + button@600 { + label = "Back"; + linux,code = ; + channel = <0>; + voltage = <600000>; + }; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_gt90h>; + /* FIXME this really is aldo1, correct once we've pmic support */ + vmmc-supply = <®_vcc3v0>; + bus-width = <4>; + cd-gpios = <&pio 1 4 GPIO_ACTIVE_HIGH>; /* PB4 */ + cd-inverted; + status = "okay"; +}; + +&pio { + mmc0_cd_pin_gt90h: mmc0_cd_pin@0 { + allwinner,pins = "PB4"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +&r_uart { + pinctrl-names = "default"; + pinctrl-0 = <&r_uart_pins_a>; + status = "okay"; +}; + +/* + * FIXME for now we only support host mode and rely on u-boot to have + * turned on Vbus which is controlled by the axp223 pmic on the board. + * + * Once we have axp223 support we should switch to fully supporting otg. + */ +&usb_otg { + dr_mode = "host"; + status = "okay"; +}; + +&usbphy { + status = "okay"; +}; -- cgit v0.10.2 From 87cf56ec311f31822a6507beaeb837f96a0607aa Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Fri, 14 Aug 2015 16:44:35 +0200 Subject: ARM: dts: sun7i: Enable USB DRC on pcDuino 3 Enable the otg/drc usb controller on the pcDuino 3. Note this board has the otg-vbus connected directly to the 5v-dcc of the board, so there is no vbus0 regulator, nor vbus0-det. Signed-off-by: Jelle van der Waa Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun7i-a20-pcduino3.dts b/arch/arm/boot/dts/sun7i-a20-pcduino3.dts index ad8169d..861a4a6 100644 --- a/arch/arm/boot/dts/sun7i-a20-pcduino3.dts +++ b/arch/arm/boot/dts/sun7i-a20-pcduino3.dts @@ -173,6 +173,10 @@ status = "okay"; }; +&otg_sram { + status = "okay"; +}; + &pio { led_pins_pcduino3: led_pins@0 { allwinner,pins = "PH15", "PH16"; @@ -187,6 +191,13 @@ allwinner,drive = ; allwinner,pull = ; }; + + usb0_id_detect_pin: usb0_id_detect_pin@0 { + allwinner,pins = "PH4"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; }; ®_ahci_5v { @@ -233,7 +244,15 @@ status = "okay"; }; +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + &usbphy { + pinctrl-names = "default"; + pinctrl-0 = <&usb0_id_detect_pin>; + usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */ usb1_vbus-supply = <®_usb1_vbus>; usb2_vbus-supply = <®_usb2_vbus>; status = "okay"; -- cgit v0.10.2 From b8962f7ee700580a148e05eceb2302bcfc59ffbc Mon Sep 17 00:00:00 2001 From: Ralph Benadski Date: Fri, 14 Aug 2015 16:44:36 +0200 Subject: ARM: dts: sun7i: Enable USB DRC on cubieboard2 Enable the otg/drc usb controller on the cubieboard2. Note this board has the otg-vbus connected directly to the 5v-dcc of the board, so there is no vbus0 regulator, nor vbus0-det. Signed-off-by: Ralph Benadski Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts index 39a51d5..9ff459b 100644 --- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts @@ -150,6 +150,10 @@ status = "okay"; }; +&otg_sram { + status = "okay"; +}; + &pio { led_pins_cubieboard2: led_pins@0 { allwinner,pins = "PH20", "PH21"; @@ -157,12 +161,24 @@ allwinner,drive = ; allwinner,pull = ; }; + + usb0_id_detect_pin: usb0_id_detect_pin@0 { + allwinner,pins = "PH4"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; }; ®_ahci_5v { status = "okay"; }; +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + #include "axp209.dtsi" ®_dcdc2 { @@ -205,6 +221,9 @@ }; &usbphy { + pinctrl-names = "default"; + pinctrl-0 = <&usb0_id_detect_pin>; + usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */ usb1_vbus-supply = <®_usb1_vbus>; usb2_vbus-supply = <®_usb2_vbus>; status = "okay"; -- cgit v0.10.2 From 49e86fd98b726d176ed3fd15d1bc14352bb4b171 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 19 Aug 2015 16:57:22 +0800 Subject: ARM: dts: sun6i: hummingbird: Add missing pinmux setting for gmac phy reset Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts index d0cfada..06d9391 100644 --- a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts +++ b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts @@ -73,7 +73,7 @@ &gmac { pinctrl-names = "default"; - pinctrl-0 = <&gmac_pins_rgmii_a>; + pinctrl-0 = <&gmac_pins_rgmii_a>, <&gmac_phy_reset_pin_hummingbird>; phy = <&phy1>; phy-mode = "rgmii"; snps,reset-gpio = <&pio 0 21 GPIO_ACTIVE_HIGH>; @@ -146,6 +146,13 @@ }; &pio { + gmac_phy_reset_pin_hummingbird: gmac_phy_reset_pin@0 { + allwinner,pins = "PA21"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + mmc0_cd_pin_hummingbird: mmc0_cd_pin@0 { allwinner,pins = "PA8"; allwinner,function = "gpio_in"; -- cgit v0.10.2 From 2a9a5cfaf1c1d0d6f34887faaa05cc86ff9b4288 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 7 Aug 2015 17:22:33 +0200 Subject: ARM: dts: sun5i: Add support for the Auxtek-T003 HDMI stick The Auxtek-T003 HDMI stick is an A10s based HDMI stick with USB wifi, and composite video out support. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 1920876..b4b9ed6 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -587,6 +587,7 @@ dtb-$(CONFIG_MACH_SUN4I) += \ sun4i-a10-olinuxino-lime.dtb \ sun4i-a10-pcduino.dtb dtb-$(CONFIG_MACH_SUN5I) += \ + sun5i-a10s-auxtek-t003.dtb \ sun5i-a10s-auxtek-t004.dtb \ sun5i-a10s-mk802.dtb \ sun5i-a10s-olinuxino-micro.dtb \ diff --git a/arch/arm/boot/dts/sun5i-a10s-auxtek-t003.dts b/arch/arm/boot/dts/sun5i-a10s-auxtek-t003.dts new file mode 100644 index 0000000..d4ad021 --- /dev/null +++ b/arch/arm/boot/dts/sun5i-a10s-auxtek-t003.dts @@ -0,0 +1,159 @@ +/* + * Copyright 2015 Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun5i-a10s.dtsi" +#include "sunxi-common-regulators.dtsi" +#include +#include + +/ { + model = "Auxtek t003 A10s hdmi tv-stick"; + compatible = "allwinner,auxtek-t003", "allwinner,sun5i-a10s"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_t003>; + + red { + label = "t003-tv-dongle:red:usr"; + gpios = <&pio 1 2 GPIO_ACTIVE_HIGH>; /* PB2 */ + default-state = "on"; + }; + }; +}; + +&ehci0 { + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp152: pmic@30 { + compatible = "x-powers,axp152"; + reg = <0x30>; + interrupts = <0>; + interrupt-controller; + #interrupt-cells = <1>; + }; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_t003>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */ + cd-inverted; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&otg_sram { + status = "okay"; +}; + +&pio { + mmc0_cd_pin_t003: mmc0_cd_pin@0 { + allwinner,pins = "PG1"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + led_pins_t003: led_pins@0 { + allwinner,pins = "PB2"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_usb0_vbus { + gpio = <&pio 6 13 GPIO_ACTIVE_HIGH>; /* PG13 */ + status = "okay"; +}; + +®_usb1_vbus { + gpio = <&pio 1 10 GPIO_ACTIVE_HIGH>; /* PB10 */ + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usb0_vbus_pin_a { + allwinner,pins = "PG13"; +}; + +&usb1_vbus_pin_a { + allwinner,pins = "PB10"; +}; + +&usb_otg { + dr_mode = "host"; + status = "okay"; +}; + +&usbphy { + usb0_vbus-supply = <®_usb0_vbus>; + usb1_vbus-supply = <®_usb1_vbus>; + status = "okay"; +}; -- cgit v0.10.2 From cb8b85a89ac80d9a15ad518b7fc74a360c59e5c2 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 24 Aug 2015 00:37:22 +0200 Subject: ARM: dts: sun4i: inet97fv2: Disable unused usb controllers The inet97fv2 tablet only has a usb-2 wifi device connected to the second ehci controller, disable the first ehci controller and both ohci controllers. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts b/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts index 6c927a8..51621c5 100644 --- a/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts +++ b/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts @@ -61,10 +61,6 @@ }; }; -&ehci0 { - status = "okay"; -}; - &ehci1 { status = "okay"; }; @@ -94,18 +90,6 @@ status = "okay"; }; -&ohci0 { - status = "okay"; -}; - -&ohci1 { - status = "okay"; -}; - -®_usb1_vbus { - status = "okay"; -}; - ®_usb2_vbus { status = "okay"; }; @@ -117,7 +101,6 @@ }; &usbphy { - usb1_vbus-supply = <®_usb1_vbus>; usb2_vbus-supply = <®_usb2_vbus>; status = "okay"; }; -- cgit v0.10.2 From 5fed0cbf4f65ff91694e64899cdcca67c59a5767 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 24 Aug 2015 00:37:23 +0200 Subject: ARM: dts: sun4i: inet97fv2: Add regulator nodes Use axp209.dtsi and add regulator nodes for the regulators used on the inet97fv2 tablet. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts b/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts index 51621c5..69e22bd 100644 --- a/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts +++ b/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts @@ -61,6 +61,10 @@ }; }; +&cpu0 { + cpu-supply = <®_dcdc2>; +}; + &ehci1 { status = "okay"; }; @@ -71,15 +75,13 @@ status = "okay"; axp209: pmic@34 { - compatible = "x-powers,axp209"; reg = <0x34>; interrupts = <0>; - - interrupt-controller; - #interrupt-cells = <1>; }; }; +#include "axp209.dtsi" + &mmc0 { pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; @@ -90,6 +92,31 @@ status = "okay"; }; +®_dcdc2 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-cpu"; +}; + +®_dcdc3 { + regulator-always-on; + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <1250000>; + regulator-name = "vdd-int-dll"; +}; + +®_ldo1 { + regulator-name = "vdd-rtc"; +}; + +®_ldo2 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "avcc"; +}; + ®_usb2_vbus { status = "okay"; }; -- cgit v0.10.2 From 64a6295e620204e8a9d4429c3e59544022eeef45 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 24 Aug 2015 00:37:24 +0200 Subject: ARM: dts: sun4i: inet97fv2: Enable otg controller Enable the otg controller on the inet97fv2 tablet. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts b/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts index 69e22bd..309a0da 100644 --- a/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts +++ b/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts @@ -92,6 +92,26 @@ status = "okay"; }; +&otg_sram { + status = "okay"; +}; + +&pio { + usb0_id_detect_pin: usb0_id_detect_pin@0 { + allwinner,pins = "PH4"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb0_vbus_detect_pin: usb0_vbus_detect_pin@0 { + allwinner,pins = "PH5"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + ®_dcdc2 { regulator-always-on; regulator-min-microvolt = <1000000>; @@ -117,6 +137,10 @@ regulator-name = "avcc"; }; +®_usb0_vbus { + status = "okay"; +}; + ®_usb2_vbus { status = "okay"; }; @@ -127,7 +151,17 @@ status = "okay"; }; +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + &usbphy { + pinctrl-names = "default"; + pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>; + usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */ + usb0_vbus_det-gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */ + usb0_vbus-supply = <®_usb0_vbus>; usb2_vbus-supply = <®_usb2_vbus>; status = "okay"; }; -- cgit v0.10.2 From 2d4f66355b37b149efb63887226f3bb71342b5aa Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 24 Aug 2015 00:37:25 +0200 Subject: ARM: dts: sun4i: inet97fv2: Enable support for tablet keys Enable support for the tablet keys which are connected via the lradc. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts b/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts index 309a0da..909fde9 100644 --- a/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts +++ b/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts @@ -47,6 +47,7 @@ #include "sunxi-common-regulators.dtsi" #include +#include / { model = "INet-97F Rev 02"; @@ -82,6 +83,46 @@ #include "axp209.dtsi" +&lradc { + vref-supply = <®_ldo2>; + status = "okay"; + + button@200 { + label = "Menu"; + linux,code = ; + channel = <0>; + voltage = <200000>; + }; + + button@600 { + label = "Volume Up"; + linux,code = ; + channel = <0>; + voltage = <600000>; + }; + + button@800 { + label = "Volume Down"; + linux,code = ; + channel = <0>; + voltage = <800000>; + }; + + button@1000 { + label = "Home"; + linux,code = ; + channel = <0>; + voltage = <1000000>; + }; + + button@1200 { + label = "Esc"; + linux,code = ; + channel = <0>; + voltage = <1200000>; + }; +}; + &mmc0 { pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; -- cgit v0.10.2 From ff9dc0b93b7ef0e3b431d76cbc6d4babb6a0dabb Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 24 Aug 2015 00:37:26 +0200 Subject: ARM: dts: sun4i: inet97fv2: Enable i2c1 and i2c2 controllers Enable i2c1 and i2c2 controllers, these are used for the touchscreen resp. the accelerometer. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts b/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts index 909fde9..77c31da 100644 --- a/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts +++ b/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts @@ -83,6 +83,18 @@ #include "axp209.dtsi" +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; +}; + &lradc { vref-supply = <®_ldo2>; status = "okay"; -- cgit v0.10.2 From 61d2595cd12931708a69960df8b674c5e3fbba03 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 28 Aug 2015 17:54:34 +0800 Subject: ARM: dts: sun6i: Add lradc node sun6i also has the LRADC for tablet buttons. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index 54bb83b..431c7c8 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -768,6 +768,13 @@ reg = <0x01c20ca0 0x20>; }; + lradc: lradc@01c22800 { + compatible = "allwinner,sun4i-a10-lradc-keys"; + reg = <0x01c22800 0x100>; + interrupts = ; + status = "disabled"; + }; + rtp: rtp@01c25000 { compatible = "allwinner,sun6i-a31-ts"; reg = <0x01c25000 0x100>; -- cgit v0.10.2 From 4917c46ced2f225e2f94f066c1c52d9f264cce3b Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 28 Aug 2015 17:54:37 +0800 Subject: ARM: dts: sun6i: Add mmc2 pins for 8 bit emmc This also includes the reset pin for emmc. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index 431c7c8..98359f3 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -691,6 +691,16 @@ allwinner,pull = ; }; + mmc2_8bit_emmc_pins: mmc2@0 { + allwinner,pins = "PC6", "PC7", "PC8", "PC9", + "PC10", "PC11", "PC12", + "PC13", "PC14", "PC15", + "PC24"; + allwinner,function = "mmc2"; + allwinner,drive = ; + allwinner,pull = ; + }; + gmac_pins_mii_a: gmac_mii@0 { allwinner,pins = "PA0", "PA1", "PA2", "PA3", "PA8", "PA9", "PA11", -- cgit v0.10.2 From ac1dd1dcc55044dfd2b8039ae974fec6d2ab2c77 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 28 Aug 2015 15:15:17 +0200 Subject: ARM: dts: sun5i: Add dts file for inet98v_rev2 based tablets The inet98v_rev2 is a pcb used in generic A13 based tablets. It features volume buttons, a power barrel, micro-usb otg, headphone connector and a power button. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index b4b9ed6..0fbe29b 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -593,6 +593,7 @@ dtb-$(CONFIG_MACH_SUN5I) += \ sun5i-a10s-olinuxino-micro.dtb \ sun5i-a10s-r7-tv-dongle.dtb \ sun5i-a13-hsg-h702.dtb \ + sun5i-a13-inet-98v-rev2.dtb \ sun5i-a13-olinuxino.dtb \ sun5i-a13-olinuxino-micro.dtb \ sun5i-a13-utoo-p66.dtb diff --git a/arch/arm/boot/dts/sun5i-a13-inet-98v-rev2.dts b/arch/arm/boot/dts/sun5i-a13-inet-98v-rev2.dts new file mode 100644 index 0000000..6fa54b6 --- /dev/null +++ b/arch/arm/boot/dts/sun5i-a13-inet-98v-rev2.dts @@ -0,0 +1,227 @@ +/* + * Copyright 2015 Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun5i-a13.dtsi" +#include "sunxi-common-regulators.dtsi" +#include +#include +#include +#include + +/ { + model = "INet-98V Rev 02"; + compatible = "primux,inet98v-rev2", "allwinner,sun5i-a13"; + + aliases { + serial0 = &uart1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + +}; + +&cpu0 { + cpu-supply = <®_dcdc2>; +}; + +&ehci0 { + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + reg = <0x34>; + interrupts = <0>; + }; +}; + +#include "axp209.dtsi" + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; + + pcf8563: rtc@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + }; +}; + +&lradc { + vref-supply = <®_ldo2>; + status = "okay"; + + button@200 { + label = "Volume Up"; + linux,code = ; + channel = <0>; + voltage = <200000>; + }; + + button@400 { + label = "Volume Down"; + linux,code = ; + channel = <0>; + voltage = <400000>; + }; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_inet98fv2>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 6 0 GPIO_ACTIVE_HIGH>; /* PG0 */ + cd-inverted; + status = "okay"; +}; + +&mmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins_a>; + vmmc-supply = <®_vcc3v3>; + bus-width = <8>; + non-removable; + status = "okay"; + + mmccard: mmccard@0 { + reg = <0>; + compatible = "mmc-card"; + broken-hpi; + }; +}; + +&otg_sram { + status = "okay"; +}; + +&pio { + mmc0_cd_pin_inet98fv2: mmc0_cd_pin@0 { + allwinner,pins = "PG0"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb0_vbus_detect_pin: usb0_vbus_detect_pin@0 { + allwinner,pins = "PG1"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb0_id_detect_pin: usb0_id_detect_pin@0 { + allwinner,pins = "PG2"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_dcdc2 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-cpu"; +}; + +®_dcdc3 { + regulator-always-on; + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <1250000>; + regulator-name = "vdd-int-pll"; +}; + +®_ldo1 { + regulator-name = "vdd-rtc"; +}; + +®_ldo2 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "avcc"; +}; + +®_ldo3 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-wifi"; +}; + +®_usb0_vbus { + gpio = <&pio 6 12 GPIO_ACTIVE_HIGH>; /* PG12 */ + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins_b>; + status = "okay"; +}; + +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + +&usb0_vbus_pin_a { + allwinner,pins = "PG12"; +}; + +&usbphy { + pinctrl-names = "default"; + pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>; + usb0_id_det-gpio = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */ + usb0_vbus_det-gpio = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */ + usb0_vbus-supply = <®_usb0_vbus>; + usb1_vbus-supply = <®_ldo3>; + status = "okay"; +}; -- cgit v0.10.2 From 72df94cbec320860f759258b5677f72caa5d4777 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 5 Sep 2015 16:55:51 +0200 Subject: ARM: dts: sunxi: Add sun?i-q8-common.dtsi files for q8 tablets Cheap allwinner based devices in the q8 enclosure come in many variants, all sharing the case and a number of other basic features. They differ in the display, touchscreen, accelerometer and wifi chips used. This commit adds 2 dtsi files defining the shared features of all the q8 tablets. sunxi-q8-common.dtsi defines features shared amongst all q8 tablets, sun8i-q8-common.dtsi defines features shared amongst all a23 / a33 based q8 tablets, but not with a13 q8 based tablets. a13 based tablets use a different card-detect pin for the mmc, and use uart1 instead of the r_uart for the serial console. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts b/arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts index 8d9da68..4f47fd6 100644 --- a/arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts +++ b/arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts @@ -44,35 +44,11 @@ /dts-v1/; #include "sun8i-a23.dtsi" -#include "sunxi-common-regulators.dtsi" - -#include -#include -#include +#include "sun8i-q8-common.dtsi" / { model = "Ippo Q8H Dual Core Tablet (v5)"; compatible = "ippo,q8h-v5", "allwinner,sun8i-a23"; - - aliases { - serial0 = &r_uart; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; -}; - -&i2c0 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; -}; - -&i2c1 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins_a>; - status = "okay"; }; &i2c2 { @@ -82,50 +58,12 @@ status = "failed"; }; -&lradc { - vref-supply = <®_vcc3v0>; - status = "okay"; - - button@200 { - label = "Volume Up"; - linux,code = ; - channel = <0>; - voltage = <200000>; - }; - - button@400 { - label = "Volume Down"; - linux,code = ; - channel = <0>; - voltage = <400000>; - }; -}; - -&mmc0 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_q8h>; - vmmc-supply = <®_vcc3v0>; - bus-width = <4>; - cd-gpios = <&pio 1 4 GPIO_ACTIVE_HIGH>; /* PB4 */ - cd-inverted; - status = "okay"; -}; - -&pio { - mmc0_cd_pin_q8h: mmc0_cd_pin@0 { - allwinner,pins = "PB4"; - allwinner,function = "gpio_in"; - allwinner,drive = ; - allwinner,pull = ; - }; -}; - -&r_uart { - pinctrl-names = "default"; - pinctrl-0 = <&r_uart_pins_a>; - status = "okay"; -}; - +/* + * FIXME for now we only support host mode and rely on u-boot to have + * turned on Vbus which is controlled by the axp223 pmic on the board. + * + * Once we have axp223 support we should switch to fully supporting otg. + */ &usb_otg { dr_mode = "host"; status = "okay"; diff --git a/arch/arm/boot/dts/sun8i-a33-ippo-q8h-v1.2.dts b/arch/arm/boot/dts/sun8i-a33-ippo-q8h-v1.2.dts index a438975..b8439cb 100644 --- a/arch/arm/boot/dts/sun8i-a33-ippo-q8h-v1.2.dts +++ b/arch/arm/boot/dts/sun8i-a33-ippo-q8h-v1.2.dts @@ -42,79 +42,11 @@ /dts-v1/; #include "sun8i-a33.dtsi" -#include "sunxi-common-regulators.dtsi" - -#include -#include -#include +#include "sun8i-q8-common.dtsi" / { model = "Ippo Q8H Quad Core Tablet (v1.2)"; compatible = "ippo,a33-q8h-v1.2", "allwinner,sun8i-a33"; - - aliases { - serial0 = &r_uart; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; -}; - -&i2c0 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; -}; - -&i2c1 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins_a>; - status = "okay"; -}; - -&lradc { - vref-supply = <®_vcc3v0>; - status = "okay"; - - button@200 { - label = "Volume Up"; - linux,code = ; - channel = <0>; - voltage = <200000>; - }; - - button@400 { - label = "Volume Down"; - linux,code = ; - channel = <0>; - voltage = <400000>; - }; -}; - -&mmc0 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_q8h>; - vmmc-supply = <®_vcc3v0>; - bus-width = <4>; - cd-gpios = <&pio 1 4 GPIO_ACTIVE_HIGH>; /* PB4 */ - cd-inverted; - status = "okay"; -}; - -&pio { - mmc0_cd_pin_q8h: mmc0_cd_pin@0 { - allwinner,pins = "PB4"; - allwinner,function = "gpio_in"; - allwinner,drive = ; - allwinner,pull = ; - }; -}; - -&r_uart { - pinctrl-names = "default"; - pinctrl-0 = <&r_uart_pins_a>; - status = "okay"; }; /* diff --git a/arch/arm/boot/dts/sun8i-q8-common.dtsi b/arch/arm/boot/dts/sun8i-q8-common.dtsi new file mode 100644 index 0000000..6f8a8bb --- /dev/null +++ b/arch/arm/boot/dts/sun8i-q8-common.dtsi @@ -0,0 +1,77 @@ +/* + * Copyright 2015 Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "sunxi-q8-common.dtsi" + +/ { + aliases { + serial0 = &r_uart; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_q8>; + vmmc-supply = <®_vcc3v0>; + bus-width = <4>; + cd-gpios = <&pio 1 4 GPIO_ACTIVE_HIGH>; /* PB4 */ + cd-inverted; + status = "okay"; +}; + +&pio { + mmc0_cd_pin_q8: mmc0_cd_pin@0 { + allwinner,pins = "PB4"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +&r_uart { + pinctrl-names = "default"; + pinctrl-0 = <&r_uart_pins_a>; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/sunxi-q8-common.dtsi b/arch/arm/boot/dts/sunxi-q8-common.dtsi new file mode 100644 index 0000000..17b26ff --- /dev/null +++ b/arch/arm/boot/dts/sunxi-q8-common.dtsi @@ -0,0 +1,77 @@ +/* + * Copyright 2015 Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include "sunxi-common-regulators.dtsi" + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; +}; + +&lradc { + vref-supply = <®_vcc3v0>; + status = "okay"; + + button@200 { + label = "Volume Up"; + linux,code = ; + channel = <0>; + voltage = <200000>; + }; + + button@400 { + label = "Volume Down"; + linux,code = ; + channel = <0>; + voltage = <400000>; + }; +}; -- cgit v0.10.2 From 2ecf488b149c88f2f94e63df38d4d038e7fb6247 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 9 Sep 2015 10:23:23 +0200 Subject: ARM: dts: sun4i: Add dts file inet9f-rev03 based tablets The inet9f-rev03 pcb is specially designed for gaming tablets, such as the qware tb-g100 tablet. These 7" tablets feature a dpad, firebuttons and 2 joysticks on the sides of the screen. Besides this they have the usual connectors: power-barrel, mini usb, mini hdmi, headphone and micro-sd slot. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 0fbe29b..332054f 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -578,6 +578,7 @@ dtb-$(CONFIG_MACH_SUN4I) += \ sun4i-a10-hackberry.dtb \ sun4i-a10-hyundai-a7hd.dtb \ sun4i-a10-inet97fv2.dtb \ + sun4i-a10-inet9f-rev03.dtb \ sun4i-a10-itead-iteaduino-plus.dtb \ sun4i-a10-jesurun-q5.dtb \ sun4i-a10-marsboard.dtb \ diff --git a/arch/arm/boot/dts/sun4i-a10-inet9f-rev03.dts b/arch/arm/boot/dts/sun4i-a10-inet9f-rev03.dts new file mode 100644 index 0000000..2fffc04 --- /dev/null +++ b/arch/arm/boot/dts/sun4i-a10-inet9f-rev03.dts @@ -0,0 +1,227 @@ +/* + * Copyright 2015 Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun4i-a10.dtsi" +#include "sunxi-common-regulators.dtsi" +#include +#include +#include +#include + +/ { + model = "iNet-9F Rev 03"; + compatible = "inet-tek,inet9f-rev03", "allwinner,sun4i-a10"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&cpu0 { + cpu-supply = <®_dcdc2>; +}; + +&ehci1 { + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + reg = <0x34>; + interrupts = <0>; + }; +}; + +#include "axp209.dtsi" + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; + + /* Accelerometer */ + bma250@18 { + compatible = "bosch,bma250"; + reg = <0x18>; + interrupt-parent = <&pio>; + interrupts = <7 0 IRQ_TYPE_EDGE_RISING>; /* PH0 / EINT0 */ + }; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; +}; + +&lradc { + vref-supply = <®_ldo2>; + status = "okay"; + + button@200 { + label = "Menu"; + linux,code = ; + channel = <0>; + voltage = <200000>; + }; + + button@600 { + label = "Volume Up"; + linux,code = ; + channel = <0>; + voltage = <600000>; + }; + + button@800 { + label = "Volume Down"; + linux,code = ; + channel = <0>; + voltage = <800000>; + }; + + button@1000 { + label = "Home"; + linux,code = ; + channel = <0>; + voltage = <1000000>; + }; + + button@1200 { + label = "Esc"; + linux,code = ; + channel = <0>; + voltage = <1200000>; + }; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; + +&otg_sram { + status = "okay"; +}; + +&pio { + usb0_id_detect_pin: usb0_id_detect_pin@0 { + allwinner,pins = "PH4"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb0_vbus_detect_pin: usb0_vbus_detect_pin@0 { + allwinner,pins = "PH5"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_dcdc2 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-cpu"; +}; + +®_dcdc3 { + regulator-always-on; + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <1250000>; + regulator-name = "vdd-int-dll"; +}; + +®_ldo1 { + regulator-name = "vdd-rtc"; +}; + +®_ldo2 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "avcc"; +}; + +®_usb0_vbus { + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + +&usbphy { + pinctrl-names = "default"; + pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>; + usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */ + usb0_vbus_det-gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */ + usb0_vbus-supply = <®_usb0_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; -- cgit v0.10.2 From b92b14909eba9ebe30da6aa041d99f9d4b47dc3e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 9 Sep 2015 10:23:24 +0200 Subject: ARM: dts: sun4i: Add dts file for iNet-1 based tablets The iNet-tek iNet-1 PCB is a PCB found in various generic 10.1" 1024x600 A10 based tablets such as the Point of View Protab2 XXL and the Cherry M1007. This patch has been tested on both rev2 and rev5 of this board / these tablets. It comes with a rtl8188cus usb wifi connected to ehci1, focal ft5406ee8 touchscreen connected to i2c2 addr 0x38, bosch bma 250 accelerometer connected to i2c1 addr 0x18 and the usual connectors: headphone, mini hdmi, power-barrel, mini-usb and a micro-sd slot. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 332054f..7b554f7 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -577,6 +577,7 @@ dtb-$(CONFIG_MACH_SUN4I) += \ sun4i-a10-gemei-g9.dtb \ sun4i-a10-hackberry.dtb \ sun4i-a10-hyundai-a7hd.dtb \ + sun4i-a10-inet1.dtb \ sun4i-a10-inet97fv2.dtb \ sun4i-a10-inet9f-rev03.dtb \ sun4i-a10-itead-iteaduino-plus.dtb \ diff --git a/arch/arm/boot/dts/sun4i-a10-inet1.dts b/arch/arm/boot/dts/sun4i-a10-inet1.dts new file mode 100644 index 0000000..487ce63 --- /dev/null +++ b/arch/arm/boot/dts/sun4i-a10-inet1.dts @@ -0,0 +1,226 @@ +/* + * Copyright 2015 Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun4i-a10.dtsi" +#include "sunxi-common-regulators.dtsi" +#include +#include +#include +#include + +/ { + model = "iNet-1"; + compatible = "inet-tek,inet1", "allwinner,sun4i-a10"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&cpu0 { + cpu-supply = <®_dcdc2>; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + reg = <0x34>; + interrupts = <0>; + }; +}; + +#include "axp209.dtsi" + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; + + /* Accelerometer */ + bma250@18 { + compatible = "bosch,bma250"; + reg = <0x18>; + interrupt-parent = <&pio>; + interrupts = <7 0 IRQ_TYPE_EDGE_RISING>; /* PH0 / EINT0 */ + }; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; +}; + +&lradc { + vref-supply = <®_ldo2>; + status = "okay"; + + button@200 { + label = "Volume Up"; + linux,code = ; + channel = <0>; + voltage = <200000>; + }; + + button@1000 { + label = "Volume Down"; + linux,code = ; + channel = <0>; + voltage = <1000000>; + }; + + button@1200 { + label = "Home"; + linux,code = ; + channel = <0>; + voltage = <1200000>; + }; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&otg_sram { + status = "okay"; +}; + +&pio { + usb0_id_detect_pin: usb0_id_detect_pin@0 { + allwinner,pins = "PH4"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb0_vbus_detect_pin: usb0_vbus_detect_pin@0 { + allwinner,pins = "PH5"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_dcdc2 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-cpu"; +}; + +®_dcdc3 { + regulator-always-on; + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <1250000>; + regulator-name = "vdd-int-dll"; +}; + +®_ldo1 { + regulator-name = "vdd-rtc"; +}; + +®_ldo2 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "avcc"; +}; + +®_usb0_vbus { + status = "okay"; +}; + +®_usb1_vbus { + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + +&usbphy { + pinctrl-names = "default"; + pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>; + usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */ + usb0_vbus_det-gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */ + usb0_vbus-supply = <®_usb0_vbus>; + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; -- cgit v0.10.2 From e89ecbf141aa6301b3d5dff9d2a123700140a920 Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Thu, 10 Sep 2015 10:31:17 +0200 Subject: dts: sunxi: add eeprom to A10 OLinuXino Lime board The Olimex A10 OLinuXino Lime features an eeprom that is always on the board. This patch adds it to the dts. Signed-off-by: Olliver Schinagl Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts index 28e32ad..b350448 100644 --- a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts +++ b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts @@ -124,6 +124,18 @@ }; }; +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; + + eeprom: eeprom@50 { + compatible = "atmel,24c16"; + reg = <0x50>; + pagesize = <16>; + }; +}; + &mdio { status = "okay"; -- cgit v0.10.2 From ce350094cadc53ee21abe9f697bfb2dd3a8aaa49 Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Thu, 10 Sep 2015 10:31:18 +0200 Subject: dts: sunxi: correct vendor prefix on OLinuXino a10s micro The OLinuXino A10S micro features an eeprom. According to the eeprom.txt binding document, we should use the manufacturer and 'at' is not the proper manufacturer id according to the vendor-prefixes. This patch takes the proper vendor-prefix and uses it for the eeprom node. Signed-off-by: Olliver Schinagl Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts index 5a422c1..86d046a 100644 --- a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts +++ b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts @@ -111,7 +111,7 @@ status = "okay"; at24@50 { - compatible = "at,24c16"; + compatible = "atmel,24c16"; pagesize = <16>; reg = <0x50>; read-only; -- cgit v0.10.2 From d2057c59beec4b977b6b4c199f549ecfcf980cf9 Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Thu, 10 Sep 2015 10:31:19 +0200 Subject: dts: sunxi: add eeprom to A20 OLinuXino Lime board The Olimex A20 OLinuXino Lime features an eeprom that is always on the board. This patch adds it to the dts. Signed-off-by: Olliver Schinagl Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts index 0423708..35ad700 100644 --- a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts @@ -117,6 +117,18 @@ }; }; +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; + + eeprom: eeprom@50 { + compatible = "atmel,24c16"; + reg = <0x50>; + pagesize = <16>; + }; +}; + &mmc0 { pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; -- cgit v0.10.2 From dbca81d2f9eec95b50fb79752dad0cc5d821eeb2 Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Thu, 10 Sep 2015 10:31:20 +0200 Subject: dts: sunxi: add eeprom to A20 OLinuXino Lime2 board The Olimex A20 OLinuXino Lime2 features an eeprom that is always on the board. This patch adds it to the dts. Signed-off-by: Olliver Schinagl Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts index 913032f..d5c796c 100644 --- a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts @@ -170,6 +170,12 @@ pinctrl-names = "default"; pinctrl-0 = <&i2c1_pins_a>; status = "okay"; + + eeprom: eeprom@50 { + compatible = "atmel,24c16"; + reg = <0x50>; + pagesize = <16>; + }; }; &mmc0 { -- cgit v0.10.2 From f49243f13075901a0674e19b6e77d5ccd27d6a24 Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Thu, 10 Sep 2015 10:31:21 +0200 Subject: dts: sunxi: add eeprom to A20 OLinuXino micro board The Olimex A20 OLinuXino Micro features an eeprom that is always on the board. This patch adds it to the dts. Signed-off-by: Olliver Schinagl Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts index c5d70ca..7e3006f 100644 --- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts @@ -125,6 +125,12 @@ pinctrl-names = "default"; pinctrl-0 = <&i2c1_pins_a>; status = "okay"; + + eeprom: eeprom@50 { + compatible = "atmel,24c16"; + reg = <0x50>; + pagesize = <16>; + }; }; &i2c2 { -- cgit v0.10.2 From bea9b7bcf3f7597092de7cac5d43370fa004e2c5 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Thu, 10 Sep 2015 15:05:58 +0200 Subject: ARM: dts: sun5i: Add emac_pins_b definition The emac pins on an A10s can also be routed to the outside through PORTD rather then through PORTA, add a pinctrl node for this. Signed-off-by: Jelle van der Waa Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi index 7dd016f..0fdabe8 100644 --- a/arch/arm/boot/dts/sun5i-a10s.dtsi +++ b/arch/arm/boot/dts/sun5i-a10s.dtsi @@ -222,6 +222,17 @@ allwinner,pull = ; }; + emac_pins_b: emac0@1 { + allwinner,pins = "PD6", "PD7", "PD10", + "PD11", "PD12", "PD13", "PD14", + "PD15", "PD18", "PD19", "PD20", + "PD21", "PD22", "PD23", "PD24", + "PD25", "PD26", "PD27"; + allwinner,function = "emac"; + allwinner,drive = ; + allwinner,pull = ; + }; + mmc1_pins_a: mmc1@0 { allwinner,pins = "PG3", "PG4", "PG5", "PG6", "PG7", "PG8"; -- cgit v0.10.2 From adfa06ce9bd30f8bc5439be49bcfaa7ceb1b6c2a Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Thu, 10 Sep 2015 15:05:59 +0200 Subject: ARM: dts: sun5i: Add dts file for the Wobo i5 top set box The Wobo i5 top set box is a somewhat curious A10s based top set box, it uses an AXP209 rather then the AXP152 usually used in combination with the A10s. It has an ethernet phy connected to PORTD rather then PORTA, and its built-in usb wifi is connected via the otg controller. This commit adds a dts file adding support for this top set box. Signed-off-by: Jelle van der Waa Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 7b554f7..59c53cb 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -594,6 +594,7 @@ dtb-$(CONFIG_MACH_SUN5I) += \ sun5i-a10s-mk802.dtb \ sun5i-a10s-olinuxino-micro.dtb \ sun5i-a10s-r7-tv-dongle.dtb \ + sun5i-a10s-wobo-i5.dtb \ sun5i-a13-hsg-h702.dtb \ sun5i-a13-inet-98v-rev2.dtb \ sun5i-a13-olinuxino.dtb \ diff --git a/arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts b/arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts new file mode 100644 index 0000000..9fea918 --- /dev/null +++ b/arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts @@ -0,0 +1,224 @@ +/* + * Copyright 2015 Jelle van der Waa + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun5i-a10s.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include +#include +#include + +/ { + model = "A10s-Wobo i5"; + compatible = "wobo,a10s-wobo-i5", "allwinner,sun5i-a10s"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_wobo_i5>; + + blue { + label = "a10s-wobo-i5:blue:usr"; + gpios = <&pio 1 2 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + }; + + reg_emac_3v3: emac-3v3 { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&emac_power_pin_wobo>; + regulator-name = "emac-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + gpio = <&pio 0 2 GPIO_ACTIVE_HIGH>; + }; +}; + +&cpu0 { + cpu-supply = <®_dcdc2>; +}; + +&ehci0 { + status = "okay"; +}; + +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&emac_pins_b>; + phy = <&phy1>; + status = "okay"; +}; + +&emac_sram { + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + reg = <0x34>; + interrupts = <0>; + }; +}; + +#include "axp209.dtsi" + +&mdio { + phy-supply = <®_emac_3v3>; + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_wobo_i5>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */ + cd-inverted; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&otg_sram { + status = "okay"; +}; + +&pio { + led_pins_wobo_i5: led_pins@0 { + allwinner,pins = "PB2"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + mmc0_cd_pin_wobo_i5: mmc0_cd_pin@0 { + allwinner,pins = "PB3"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + emac_power_pin_wobo: emac_power_pin@0 { + allwinner,pins = "PA02"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_dcdc2 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-cpu"; +}; + +®_dcdc3 { + regulator-always-on; + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <1250000>; + regulator-name = "vdd-int-dll"; +}; + +®_ldo1 { + regulator-name = "vdd-rtc"; +}; + +®_ldo2 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "avcc"; +}; + +®_ldo3 { + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-wifi"; +}; + +®_usb1_vbus { + gpio = <&pio 6 12 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usb_otg { + dr_mode = "host"; + status = "okay"; +}; + +&usb1_vbus_pin_a { + allwinner,pins = "PG12"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + status = "okay"; +}; -- cgit v0.10.2 From 5d97c677a94ea701650b642b3425b46d993e2af7 Mon Sep 17 00:00:00 2001 From: Sander Vermin Date: Sun, 13 Sep 2015 20:26:01 +0200 Subject: ARM: dts: sun6i: Add accelerometer on Columbus A31 Add mma8452 accelerometer to sun6i-a31-colombus.dts. Signed-off-by: Sander Vermin Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun6i-a31-colombus.dts b/arch/arm/boot/dts/sun6i-a31-colombus.dts index 8843420..813f715 100644 --- a/arch/arm/boot/dts/sun6i-a31-colombus.dts +++ b/arch/arm/boot/dts/sun6i-a31-colombus.dts @@ -92,6 +92,13 @@ pinctrl-names = "default"; pinctrl-0 = <&i2c2_pins_a>; status = "okay"; + + mma8452: mma8452@1d { + compatible = "fsl,mma8452"; + reg = <0x1d>; + interrupt-parent = <&pio>; + interrupts = <0 9 IRQ_TYPE_LEVEL_LOW>; /* PA9 */ + }; }; &mmc0 { -- cgit v0.10.2 From 6f1606bfe9cc2111072d48c65bab33d4d267024c Mon Sep 17 00:00:00 2001 From: Yassin Jaffer Date: Wed, 16 Sep 2015 00:05:54 +1000 Subject: ARM: dts: sun7i: Add keypad clk node This patch add support to the keypad clock on sun7i Signed-off-by: Yassin Jaffer Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 391230c..3a68852 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -465,6 +465,14 @@ clock-output-names = "ir1"; }; + keypad_clk: clk@01c200c4 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-mod0-clk"; + reg = <0x01c200c4 0x4>; + clocks = <&osc24M>; + clock-output-names = "keypad"; + }; + usb_clk: clk@01c200cc { #clock-cells = <1>; #reset-cells = <1>; -- cgit v0.10.2 From 832f977c8bb7c4a0ddfdc809448af6af34436f99 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 18 Sep 2015 15:35:36 +0800 Subject: ARM: dts: sun8i: Add PWM controller node for A23/A33 A23/A33 have a PWM controller that is compatible to the one on the A20. Add a device node for it. Signed-off-by: Chen-Yu Tsai Reviewed-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun8i-a23-a33.dtsi b/arch/arm/boot/dts/sun8i-a23-a33.dtsi index 27a925e..e705430 100644 --- a/arch/arm/boot/dts/sun8i-a23-a33.dtsi +++ b/arch/arm/boot/dts/sun8i-a23-a33.dtsi @@ -466,6 +466,14 @@ interrupts = ; }; + pwm: pwm@01c21400 { + compatible = "allwinner,sun7i-a20-pwm"; + reg = <0x01c21400 0xc>; + clocks = <&osc24M>; + #pwm-cells = <3>; + status = "disabled"; + }; + lradc: lradc@01c22800 { compatible = "allwinner,sun4i-a10-lradc-keys"; reg = <0x01c22800 0x100>; -- cgit v0.10.2 From 29a0d085b759ef7c1d63918c4dd04daec3860a12 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 18 Sep 2015 15:35:37 +0800 Subject: ARM: dts: sun8i: Add PWM channel 0 pinmux setting for A23/A33 The PWM controller has 2 outputs, with one usable pin for each. Add a pinmux setting for the first channel. This is often used for backlight dimming on tablets. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun8i-a23-a33.dtsi b/arch/arm/boot/dts/sun8i-a23-a33.dtsi index e705430..8f4db82 100644 --- a/arch/arm/boot/dts/sun8i-a23-a33.dtsi +++ b/arch/arm/boot/dts/sun8i-a23-a33.dtsi @@ -412,6 +412,13 @@ allwinner,pull = ; }; + pwm0_pins: pwm0 { + allwinner,pins = "PH0"; + allwinner,function = "pwm0"; + allwinner,drive = ; + allwinner,pull = ; + }; + i2c0_pins_a: i2c0@0 { allwinner,pins = "PH2", "PH3"; allwinner,function = "i2c0"; -- cgit v0.10.2 From d5c1274f26c18c4e3037cf7667d967388a73348b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 5 Sep 2015 16:55:52 +0200 Subject: ARM: dts: sun5i: Add sun5i-q8-common.dtsi This is the sun5i / a13 version of sun8i-q8-common.dtsi for use in dts files for a13 q8 based tablets. Compared to sun8i this uses uart1 for the serial console, and PG0 for card-detect for mmc0. This also adds pmic and otg support, which both use the same config on all known q8 a13 devices. This is not present in sun5i-q8-common.dtsi because pmic / otg support for sun8i has not yet been merged. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun5i-q8-common.dtsi b/arch/arm/boot/dts/sun5i-q8-common.dtsi new file mode 100644 index 0000000..0641d68 --- /dev/null +++ b/arch/arm/boot/dts/sun5i-q8-common.dtsi @@ -0,0 +1,170 @@ +/* + * Copyright 2015 Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "sunxi-q8-common.dtsi" + +/ { + aliases { + serial0 = &uart1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&cpu0 { + cpu-supply = <®_dcdc2>; +}; + +&ehci0 { + status = "okay"; +}; + +&i2c0 { + axp209: pmic@34 { + reg = <0x34>; + interrupts = <0>; + }; +}; + +&i2c1 { + pcf8563: rtc@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + }; +}; + +#include "axp209.dtsi" + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_q8>; + vmmc-supply = <®_vcc3v0>; + bus-width = <4>; + cd-gpios = <&pio 6 0 GPIO_ACTIVE_HIGH>; /* PG0 */ + cd-inverted; + status = "okay"; +}; + +&otg_sram { + status = "okay"; +}; + +&pio { + mmc0_cd_pin_q8: mmc0_cd_pin@0 { + allwinner,pins = "PG0"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb0_vbus_detect_pin: usb0_vbus_detect_pin@0 { + allwinner,pins = "PG1"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb0_id_detect_pin: usb0_id_detect_pin@0 { + allwinner,pins = "PG2"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb0_vbus_pin_a: usb0_vbus_pin@0 { + allwinner,pins = "PG12"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_dcdc2 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1500000>; + regulator-name = "vdd-cpu"; +}; + +®_dcdc3 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-int-pll"; +}; + +®_ldo1 { + regulator-name = "vdd-rtc"; +}; + +®_ldo2 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "avcc"; +}; + +®_usb0_vbus { + gpio = <&pio 6 12 GPIO_ACTIVE_HIGH>; /* PG12 */ + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins_b>; + status = "okay"; +}; + +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + +&usbphy { + pinctrl-names = "default"; + pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>; + usb0_id_det-gpio = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */ + usb0_vbus_det-gpio = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */ + usb0_vbus-supply = <®_usb0_vbus>; + status = "okay"; +}; -- cgit v0.10.2 From eb2217b4c25e3796b0e834ce6e4fb5490ee9ab27 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 5 Sep 2015 16:55:53 +0200 Subject: ARM: dts: sun5i: Add dts file for q8 formfactor a13 based tablets This commits adds a generic dts file for q8 formfactor a13 based tablets. The tablets ship in many variants, with the difference mainly being the touchscreen controller / accelerometer / wifi chip used. The wifi is USB based, and thus not listed in devicetree. The touchscreen controller / accelerometer may turn out to be a problem once we add support for those. We can either do something with devicetree overlays, or add sun5i-a13--.dts files. The latter is what the android mod community is doing with firmware images. This dts was tested with an a13 q8 tablet with a pcb labelled: "94V-0", silead gsl1680 touchscreen controller and a mc32x0 accelerometer. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 59c53cb..d811bff 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -599,6 +599,7 @@ dtb-$(CONFIG_MACH_SUN5I) += \ sun5i-a13-inet-98v-rev2.dtb \ sun5i-a13-olinuxino.dtb \ sun5i-a13-olinuxino-micro.dtb \ + sun5i-a13-q8-tablet.dtb \ sun5i-a13-utoo-p66.dtb dtb-$(CONFIG_MACH_SUN6I) += \ sun6i-a31-app4-evb1.dtb \ diff --git a/arch/arm/boot/dts/sun5i-a13-q8-tablet.dts b/arch/arm/boot/dts/sun5i-a13-q8-tablet.dts new file mode 100644 index 0000000..72e93ac --- /dev/null +++ b/arch/arm/boot/dts/sun5i-a13-q8-tablet.dts @@ -0,0 +1,60 @@ +/* + * Copyright 2015 Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun5i-a13.dtsi" +#include "sun5i-q8-common.dtsi" + +/ { + model = "Q8 A13 Tablet"; + compatible = "allwinner,q8-a13", "allwinner,sun5i-a13"; +}; + +®_ldo3 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-wifi"; +}; + +&usbphy { + usb1_vbus-supply = <®_ldo3>; +}; -- cgit v0.10.2 From fe8872c176255c13a9c72e1a3679fec475b849c4 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 18 Aug 2015 19:32:56 +0200 Subject: ARM: sun8i: Add the A33 AHB1 gates clock driver The A33 has a different gates array than the A23, add the node to the DT. Reported-by: Chen-Yu Tsai Reviewed-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun8i-a33.dtsi b/arch/arm/boot/dts/sun8i-a33.dtsi index faa7d3c..3457edb 100644 --- a/arch/arm/boot/dts/sun8i-a33.dtsi +++ b/arch/arm/boot/dts/sun8i-a33.dtsi @@ -72,6 +72,33 @@ clock-output-names = "pll11"; }; + ahb1_gates: clk@01c20060 { + #clock-cells = <1>; + compatible = "allwinner,sun8i-a33-ahb1-gates-clk"; + reg = <0x01c20060 0x8>; + clocks = <&ahb1>; + clock-indices = <1>, <5>, + <6>, <8>, <9>, + <10>, <13>, <14>, + <19>, <20>, + <21>, <24>, <26>, + <29>, <32>, <36>, + <40>, <44>, <46>, + <52>, <53>, + <54>, <57>, + <58>; + clock-output-names = "ahb1_mipidsi", "ahb1_ss", + "ahb1_dma","ahb1_mmc0", "ahb1_mmc1", + "ahb1_mmc2", "ahb1_nand", "ahb1_sdram", + "ahb1_hstimer", "ahb1_spi0", + "ahb1_spi1", "ahb1_otg", "ahb1_ehci", + "ahb1_ohci", "ahb1_ve", "ahb1_lcd", + "ahb1_csi", "ahb1_be", "ahb1_fe", + "ahb1_gpu", "ahb1_msgbox", + "ahb1_spinlock", "ahb1_drc", + "ahb1_sat"; + }; + mbus_clk: clk@01c2015c { #clock-cells = <0>; compatible = "allwinner,sun8i-a23-mbus-clk"; -- cgit v0.10.2 From f42a9505d1da7b0caf4bc6e7b3eb133631ed03ec Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 18 Aug 2015 19:34:06 +0200 Subject: ARM: sun8i: Move A23 AHB1 gates out of common DTSI The AHB1 gates were assumed to be identical between the A23 and the A33, which turned out to be wrong. Move the A23 gates definition to the A23 DTSI. Reported-by: Chen-Yu Tsai Reviewed-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun8i-a23-a33.dtsi b/arch/arm/boot/dts/sun8i-a23-a33.dtsi index 8f4db82..04bccad 100644 --- a/arch/arm/boot/dts/sun8i-a23-a33.dtsi +++ b/arch/arm/boot/dts/sun8i-a23-a33.dtsi @@ -175,31 +175,6 @@ clock-output-names = "apb1"; }; - ahb1_gates: clk@01c20060 { - #clock-cells = <1>; - compatible = "allwinner,sun8i-a23-ahb1-gates-clk"; - reg = <0x01c20060 0x8>; - clocks = <&ahb1>; - clock-indices = <1>, <6>, - <8>, <9>, <10>, - <13>, <14>, - <19>, <20>, - <21>, <24>, <26>, - <29>, <32>, <36>, - <40>, <44>, <46>, - <52>, <54>, - <57>; - clock-output-names = "ahb1_mipidsi", "ahb1_dma", - "ahb1_mmc0", "ahb1_mmc1", "ahb1_mmc2", - "ahb1_nand", "ahb1_sdram", - "ahb1_hstimer", "ahb1_spi0", - "ahb1_spi1", "ahb1_otg", "ahb1_ehci", - "ahb1_ohci", "ahb1_ve", "ahb1_lcd", - "ahb1_csi", "ahb1_be", "ahb1_fe", - "ahb1_gpu", "ahb1_spinlock", - "ahb1_drc"; - }; - apb1_gates: clk@01c20068 { #clock-cells = <1>; compatible = "allwinner,sun8i-a23-apb1-gates-clk"; diff --git a/arch/arm/boot/dts/sun8i-a23.dtsi b/arch/arm/boot/dts/sun8i-a23.dtsi index 2cc27c7..4a85e21 100644 --- a/arch/arm/boot/dts/sun8i-a23.dtsi +++ b/arch/arm/boot/dts/sun8i-a23.dtsi @@ -50,6 +50,31 @@ }; clocks { + ahb1_gates: clk@01c20060 { + #clock-cells = <1>; + compatible = "allwinner,sun8i-a23-ahb1-gates-clk"; + reg = <0x01c20060 0x8>; + clocks = <&ahb1>; + clock-indices = <1>, <6>, + <8>, <9>, <10>, + <13>, <14>, + <19>, <20>, + <21>, <24>, <26>, + <29>, <32>, <36>, + <40>, <44>, <46>, + <52>, <54>, + <57>; + clock-output-names = "ahb1_mipidsi", "ahb1_dma", + "ahb1_mmc0", "ahb1_mmc1", "ahb1_mmc2", + "ahb1_nand", "ahb1_sdram", + "ahb1_hstimer", "ahb1_spi0", + "ahb1_spi1", "ahb1_otg", "ahb1_ehci", + "ahb1_ohci", "ahb1_ve", "ahb1_lcd", + "ahb1_csi", "ahb1_be", "ahb1_fe", + "ahb1_gpu", "ahb1_spinlock", + "ahb1_drc"; + }; + mbus_clk: clk@01c2015c { #clock-cells = <0>; compatible = "allwinner,sun8i-a23-mbus-clk"; -- cgit v0.10.2 From 36034fc1957d55837189075076a502051784a805 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 18 Aug 2015 19:36:18 +0200 Subject: ARM: sun8i: A23: Add missing msgbox gate Even though it's not mentionned in the A23 user manual, the A23 has a gate for the AHB1 clock to the msgbox IP. Add it to the clock-indices. Reported-by: Chen-Yu Tsai Reviewed-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun8i-a23.dtsi b/arch/arm/boot/dts/sun8i-a23.dtsi index 4a85e21..92e6616 100644 --- a/arch/arm/boot/dts/sun8i-a23.dtsi +++ b/arch/arm/boot/dts/sun8i-a23.dtsi @@ -62,8 +62,8 @@ <21>, <24>, <26>, <29>, <32>, <36>, <40>, <44>, <46>, - <52>, <54>, - <57>; + <52>, <53>, + <54>, <57>; clock-output-names = "ahb1_mipidsi", "ahb1_dma", "ahb1_mmc0", "ahb1_mmc1", "ahb1_mmc2", "ahb1_nand", "ahb1_sdram", @@ -71,8 +71,8 @@ "ahb1_spi1", "ahb1_otg", "ahb1_ehci", "ahb1_ohci", "ahb1_ve", "ahb1_lcd", "ahb1_csi", "ahb1_be", "ahb1_fe", - "ahb1_gpu", "ahb1_spinlock", - "ahb1_drc"; + "ahb1_gpu", "ahb1_msgbox", + "ahb1_spinlock", "ahb1_drc"; }; mbus_clk: clk@01c2015c { -- cgit v0.10.2 From f5f1c2cbe8785c212794067ce57aeb6439be7ac1 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sun, 20 Sep 2015 08:30:50 -0400 Subject: ARM: dts: sun8i: Add pwm-backlight device for A23/A33 Q8 format tablets The LCD backlight on the A23/A33 Q8 format tablets is enabled with a GPIO controlled regulator, and brightness controlled with the SoC's PWM controller. The backlight is powered from the AXP223 PMIC's DC1SW output, which is not supported yet. A proper bootloader is required to enable it. The brightness levels are arbitrary. The FEX files do not have such information. As such, actual brightness levels may differ from device to device. Signed-off-by: Chen-Yu Tsai Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun8i-q8-common.dtsi b/arch/arm/boot/dts/sun8i-q8-common.dtsi index 6f8a8bb..f342736 100644 --- a/arch/arm/boot/dts/sun8i-q8-common.dtsi +++ b/arch/arm/boot/dts/sun8i-q8-common.dtsi @@ -41,11 +41,24 @@ */ #include "sunxi-q8-common.dtsi" +#include + / { aliases { serial0 = &r_uart; }; + backlight: backlight { + compatible = "pwm-backlight"; + pinctrl-names = "default"; + pinctrl-0 = <&bl_en_pin_q8>; + pwms = <&pwm 0 50000 PWM_POLARITY_INVERTED>; + brightness-levels = <0 10 20 30 40 50 60 70 80 90 100>; + default-brightness-level = <8>; + enable-gpios = <&pio 7 6 GPIO_ACTIVE_HIGH>; /* PH6 */ + /* backlight is powered by AXP223 DC1SW */ + }; + chosen { stdout-path = "serial0:115200n8"; }; @@ -62,6 +75,13 @@ }; &pio { + bl_en_pin_q8: bl_en_pin@0 { + allwinner,pins = "PH6"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + mmc0_cd_pin_q8: mmc0_cd_pin@0 { allwinner,pins = "PB4"; allwinner,function = "gpio_in"; -- cgit v0.10.2 From f7ad082cac8ec0a6af2d77513f9897374b9b3e9d Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 23 Sep 2015 12:34:39 +0800 Subject: ARM: dts: sun8i-a33: Add security system crypto engine clock and device nodes A33 has the same "Security System" crypto engine as A10/A20, but with a separate reset control. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun8i-a33.dtsi b/arch/arm/boot/dts/sun8i-a33.dtsi index 3457edb..001d840 100644 --- a/arch/arm/boot/dts/sun8i-a33.dtsi +++ b/arch/arm/boot/dts/sun8i-a33.dtsi @@ -99,6 +99,14 @@ "ahb1_sat"; }; + ss_clk: clk@01c2009c { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-mod0-clk"; + reg = <0x01c2009c 0x4>; + clocks = <&osc24M>, <&pll6 0>; + clock-output-names = "ss"; + }; + mbus_clk: clk@01c2015c { #clock-cells = <0>; compatible = "allwinner,sun8i-a23-mbus-clk"; @@ -109,6 +117,16 @@ }; soc@01c00000 { + crypto: crypto-engine@01c15000 { + compatible = "allwinner,sun4i-a10-crypto"; + reg = <0x01c15000 0x1000>; + interrupts = ; + clocks = <&ahb1_gates 5>, <&ss_clk>; + clock-names = "ahb", "mod"; + resets = <&ahb1_rst 5>; + reset-names = "ahb"; + }; + usb_otg: usb@01c19000 { compatible = "allwinner,sun8i-a33-musb"; reg = <0x01c19000 0x0400>; -- cgit v0.10.2 From 0372bb6b92a438a539f5a2d58b1979f999170813 Mon Sep 17 00:00:00 2001 From: Priit Laes Date: Wed, 23 Sep 2015 10:38:31 +0300 Subject: ARM: dts: sun4i: gemei-g9: Add accelerometer (bma250) IRQ Add IRQ configuration for bma250 accelerometer. Signed-off-by: Priit Laes Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun4i-a10-gemei-g9.dts b/arch/arm/boot/dts/sun4i-a10-gemei-g9.dts index 570754d..3f0aeb8 100644 --- a/arch/arm/boot/dts/sun4i-a10-gemei-g9.dts +++ b/arch/arm/boot/dts/sun4i-a10-gemei-g9.dts @@ -47,6 +47,7 @@ #include "sunxi-common-regulators.dtsi" #include #include +#include / { model = "Gemei G9 Tablet"; @@ -64,7 +65,7 @@ /* * TODO: * 2x cameras via CSI - * bma250 IRQs + * audio * AXP battery management * NAND * OTG @@ -103,12 +104,8 @@ bma250@18 { compatible = "bosch,bma250"; reg = <0x18>; - - /* - * TODO: interrupt pins: - * int1 - PH00 - * int2 - PI10 - */ + interrupt-parent = <&pio>; + interrupts = <7 0 IRQ_TYPE_EDGE_RISING>; /* PH00 / EINT0 */ }; }; -- cgit v0.10.2 From 40088eb4071ecc40e2b7ded71b0c06f216385efe Mon Sep 17 00:00:00 2001 From: Aleksei Mamlin Date: Thu, 24 Sep 2015 10:33:46 +0300 Subject: ARM: dts: sun4i: Enable USB DRC on the Marsboard A10 Enable the otg/drc usb controller on the Marsboard A10. Similar to Cubieboard, the 5V of the otg is directly connected to the general 5V, so we only use the id pin. Signed-off-by: Aleksei Mamlin Reviewed-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun4i-a10-marsboard.dts b/arch/arm/boot/dts/sun4i-a10-marsboard.dts index 02158bc..9a012db 100644 --- a/arch/arm/boot/dts/sun4i-a10-marsboard.dts +++ b/arch/arm/boot/dts/sun4i-a10-marsboard.dts @@ -154,6 +154,10 @@ status = "okay"; }; +&otg_sram { + status = "okay"; +}; + &pio { led_pins_marsboard: led_pins@0 { allwinner,pins = "PB5", "PB6", "PB7", "PB8"; @@ -161,6 +165,13 @@ allwinner,drive = ; allwinner,pull = ; }; + + usb0_id_detect_pin: usb0_id_detect_pin@0 { + allwinner,pins = "PH4"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; }; ®_usb1_vbus { @@ -184,7 +195,15 @@ status = "okay"; }; +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + &usbphy { + pinctrl-names = "default"; + pinctrl-0 = <&usb0_id_detect_pin>; + usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */ usb1_vbus-supply = <®_usb1_vbus>; usb2_vbus-supply = <®_usb2_vbus>; status = "okay"; -- cgit v0.10.2 From 849147cdb540266883cb49f2094a87b3ee6e12ec Mon Sep 17 00:00:00 2001 From: Lawrence Yu Date: Tue, 22 Sep 2015 08:50:50 -0700 Subject: ARM: dts: sun6i: Add support for Yones Toptech bs1078v2 tablets The bs1078v2 is a pcb found in 10.1" tablets with an A31 soc, 1G RAM and 8G NAND, rtl8723as usb wifi, 1 micro USB OTG port, 1 USB HOST port This commit adds a dts for v2 of the bs1078 pcb. Signed-off-by: Lawrence Yu Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index d811bff..5dbfcb9 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -608,7 +608,8 @@ dtb-$(CONFIG_MACH_SUN6I) += \ sun6i-a31-i7.dtb \ sun6i-a31-m9.dtb \ sun6i-a31-mele-a1000g-quad.dtb \ - sun6i-a31s-cs908.dtb + sun6i-a31s-cs908.dtb \ + sun6i-a31s-yones-toptech-bs1078-v2.dtb dtb-$(CONFIG_MACH_SUN7I) += \ sun7i-a20-bananapi.dtb \ sun7i-a20-bananapro.dtb \ diff --git a/arch/arm/boot/dts/sun6i-a31s-yones-toptech-bs1078-v2.dts b/arch/arm/boot/dts/sun6i-a31s-yones-toptech-bs1078-v2.dts new file mode 100644 index 0000000..b199020 --- /dev/null +++ b/arch/arm/boot/dts/sun6i-a31s-yones-toptech-bs1078-v2.dts @@ -0,0 +1,134 @@ +/* + * Copyright 2015 Lawrence Yu + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun6i-a31s.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include +#include + +/ { + model = "Yones TopTech BS1078 v2 Tablet"; + compatible = "yones-toptech,bs1078-v2", "allwinner,sun6i-a31s"; + + aliases { + serial0 = &uart0; + i2c1 = &i2c1; + i2c2 = &i2c2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&pio { + mmc0_cd_pin_bs1078v2: mmc0_cd_pin@0 { + allwinner,pins = "PA8"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_bs1078v2>; + vmmc-supply = <®_vcc3v0>; + bus-width = <4>; + cd-gpios = <&pio 0 8 GPIO_ACTIVE_HIGH>; /* PA8 */ + cd-inverted; + status = "okay"; +}; + +&mmc0_pins_a { + allwinner,pull = ; +}; + +®_usb1_vbus { + gpio = <&pio 7 27 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&usb1_vbus_pin_a { + allwinner,pins = "PH27"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; -- cgit v0.10.2 From bbe379fc7ca5cae09b1bc44fe5ee4173ad883fbf Mon Sep 17 00:00:00 2001 From: Henry Chen Date: Fri, 11 Sep 2015 21:05:20 +0800 Subject: soc: mediatek: Move the initial setting of pmic wrap interrupt before requesting irq. The watchdog may not be initialized by the bootloader, even if the rest of the pwrap is. Move the watchdog initialization out of pwrap_init() to make sure the watchdog is always initialized and not only when the pwrap is uninitialized. Signed-off-by: Henry Chen Acked-by: Sascha Hauer Signed-off-by: Matthias Brugger diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index 8bc7b41..105597a 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -725,10 +725,6 @@ static int pwrap_init(struct pmic_wrapper *wrp) pwrap_writel(wrp, 0x1, PWRAP_WACS2_EN); pwrap_writel(wrp, 0x5, PWRAP_STAUPD_PRD); pwrap_writel(wrp, 0xff, PWRAP_STAUPD_GRPEN); - pwrap_writel(wrp, 0xf, PWRAP_WDT_UNIT); - pwrap_writel(wrp, 0xffffffff, PWRAP_WDT_SRC_EN); - pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN); - pwrap_writel(wrp, ~((1 << 31) | (1 << 1)), PWRAP_INT_EN); if (pwrap_is_mt8135(wrp)) { /* enable pwrap events and pwrap bridge in AP side */ @@ -896,6 +892,12 @@ static int pwrap_probe(struct platform_device *pdev) return -ENODEV; } + /* Initialize watchdog, may not be done by the bootloader */ + pwrap_writel(wrp, 0xf, PWRAP_WDT_UNIT); + pwrap_writel(wrp, 0xffffffff, PWRAP_WDT_SRC_EN); + pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN); + pwrap_writel(wrp, ~((1 << 31) | (1 << 1)), PWRAP_INT_EN); + irq = platform_get_irq(pdev, 0); ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt, IRQF_TRIGGER_HIGH, "mt-pmic-pwrap", wrp); -- cgit v0.10.2 From 1ee35c05d9c67771d649f687e6f76e61e76eb779 Mon Sep 17 00:00:00 2001 From: Yingjoe Chen Date: Wed, 16 Sep 2015 09:35:25 +0800 Subject: arm64: mt8173.dtsi: correct i2c node names Node name in device tree should describe general class of the device. Correct incorrect i2c node names. Signed-off-by: Yingjoe Chen Reviewed-by: Daniel Kurtz Signed-off-by: Matthias Brugger diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index d18ee42..7f360b7 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -365,7 +365,7 @@ status = "disabled"; }; - i2c3: i2c3@11010000 { + i2c3: i2c@11010000 { compatible = "mediatek,mt8173-i2c"; reg = <0 0x11010000 0 0x70>, <0 0x11000280 0 0x80>; @@ -381,7 +381,7 @@ status = "disabled"; }; - i2c4: i2c4@11011000 { + i2c4: i2c@11011000 { compatible = "mediatek,mt8173-i2c"; reg = <0 0x11011000 0 0x70>, <0 0x11000300 0 0x80>; @@ -397,7 +397,7 @@ status = "disabled"; }; - i2c6: i2c6@11013000 { + i2c6: i2c@11013000 { compatible = "mediatek,mt8173-i2c"; reg = <0 0x11013000 0 0x70>, <0 0x11000080 0 0x80>; -- cgit v0.10.2 From 47e90154fafd1a1310e3c5baed77d8f4c33ab271 Mon Sep 17 00:00:00 2001 From: Eddie Huang Date: Wed, 26 Aug 2015 15:14:41 +0800 Subject: soc: mediatek: add scpsys support active_wakeup Register gpd_dev_ops.active_wakeup function to support keep power during suspend state. And add flag to each power domain to decide whether keep power during suspend or not. Signed-off-by: Chunfeng Yun Signed-off-by: Eddie Huang Acked-by: Sascha Hauer Reviewed-by: Daniel Kurtz Signed-off-by: Matthias Brugger diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c index 164a7d8..55ab08f 100644 --- a/drivers/soc/mediatek/mtk-scpsys.c +++ b/drivers/soc/mediatek/mtk-scpsys.c @@ -68,6 +68,7 @@ struct scp_domain_data { u32 sram_pdn_ack_bits; u32 bus_prot_mask; enum clk_id clk_id; + bool active_wakeup; }; static const struct scp_domain_data scp_domain_data[] __initconst = { @@ -128,6 +129,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = { .sram_pdn_bits = GENMASK(11, 8), .sram_pdn_ack_bits = GENMASK(15, 12), .clk_id = MT8173_CLK_NONE, + .active_wakeup = true, }, [MT8173_POWER_DOMAIN_MFG_ASYNC] = { .name = "mfg_async", @@ -172,6 +174,7 @@ struct scp_domain { u32 sram_pdn_bits; u32 sram_pdn_ack_bits; u32 bus_prot_mask; + bool active_wakeup; }; struct scp { @@ -371,6 +374,17 @@ out: return ret; } +static bool scpsys_active_wakeup(struct device *dev) +{ + struct generic_pm_domain *genpd; + struct scp_domain *scpd; + + genpd = pd_to_genpd(dev->pm_domain); + scpd = container_of(genpd, struct scp_domain, genpd); + + return scpd->active_wakeup; +} + static int __init scpsys_probe(struct platform_device *pdev) { struct genpd_onecell_data *pd_data; @@ -428,12 +442,14 @@ static int __init scpsys_probe(struct platform_device *pdev) scpd->sram_pdn_bits = data->sram_pdn_bits; scpd->sram_pdn_ack_bits = data->sram_pdn_ack_bits; scpd->bus_prot_mask = data->bus_prot_mask; + scpd->active_wakeup = data->active_wakeup; if (data->clk_id != MT8173_CLK_NONE) scpd->clk = clk[data->clk_id]; genpd->name = data->name; genpd->power_off = scpsys_power_off; genpd->power_on = scpsys_power_on; + genpd->dev_ops.active_wakeup = scpsys_active_wakeup; /* * Initially turn on all domains to make the domains usable -- cgit v0.10.2 From b0c936f59c8928dac2b230322dd51cbfae289151 Mon Sep 17 00:00:00 2001 From: Leilk Liu Date: Mon, 31 Aug 2015 21:44:19 +0800 Subject: arm64: dts: Add spi bus dts This patch adds MT8173 spi bus controllers into device tree. Signed-off-by: Leilk Liu Reviewed-and-Tested-by: Nicolas Boichat Signed-off-by: Matthias Brugger diff --git a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts index 4be66ca..811cb76 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts +++ b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts @@ -387,6 +387,24 @@ }; }; +&pio { + spi_pins_a: spi0 { + pins_spi { + pinmux = , + , + , + ; + }; + }; +}; + +&spi { + pinctrl-names = "default"; + pinctrl-0 = <&spi_pins_a>; + mediatek,pad-select = <0>; + status = "okay"; +}; + &uart0 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index 7f360b7..4bce167 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -365,6 +365,19 @@ status = "disabled"; }; + spi: spi@1100a000 { + compatible = "mediatek,mt8173-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0 0x1100a000 0 0x1000>; + interrupts = ; + clocks = <&topckgen CLK_TOP_SYSPLL3_D2>, + <&topckgen CLK_TOP_SPI_SEL>, + <&pericfg CLK_PERI_SPI0>; + clock-names = "parent-clk", "sel-clk", "spi-clk"; + status = "disabled"; + }; + i2c3: i2c@11010000 { compatible = "mediatek,mt8173-i2c"; reg = <0 0x11010000 0 0x70>, -- cgit v0.10.2 From d4499e255eec6b004f97610efa90cae4d1b41ec1 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 25 Sep 2015 15:46:35 +0200 Subject: ARM: dts: mt8135-evbp1: remove regulator-compatible usage The regulator-compatible property from the regulator DT binding was deprecated and the correct approach is to use the node's name. This patch has no functional changes since the values of the node's name and the regulator-compatible match for all the regulators. Signed-off-by: Javier Martinez Canillas Signed-off-by: Matthias Brugger diff --git a/arch/arm/boot/dts/mt8135-evbp1.dts b/arch/arm/boot/dts/mt8135-evbp1.dts index 357a91f..460db6d 100644 --- a/arch/arm/boot/dts/mt8135-evbp1.dts +++ b/arch/arm/boot/dts/mt8135-evbp1.dts @@ -32,7 +32,6 @@ compatible = "mediatek,mt6397-regulator"; mt6397_vpca15_reg: buck_vpca15 { - regulator-compatible = "buck_vpca15"; regulator-name = "vpca15"; regulator-min-microvolt = < 850000>; regulator-max-microvolt = <1350000>; @@ -41,7 +40,6 @@ }; mt6397_vpca7_reg: buck_vpca7 { - regulator-compatible = "buck_vpca7"; regulator-name = "vpca7"; regulator-min-microvolt = < 850000>; regulator-max-microvolt = <1350000>; @@ -50,7 +48,6 @@ }; mt6397_vsramca15_reg: buck_vsramca15 { - regulator-compatible = "buck_vsramca15"; regulator-name = "vsramca15"; regulator-min-microvolt = < 850000>; regulator-max-microvolt = <1350000>; @@ -59,7 +56,6 @@ }; mt6397_vsramca7_reg: buck_vsramca7 { - regulator-compatible = "buck_vsramca7"; regulator-name = "vsramca7"; regulator-min-microvolt = < 850000>; regulator-max-microvolt = <1350000>; @@ -68,7 +64,6 @@ }; mt6397_vcore_reg: buck_vcore { - regulator-compatible = "buck_vcore"; regulator-name = "vcore"; regulator-min-microvolt = < 850000>; regulator-max-microvolt = <1350000>; @@ -77,7 +72,6 @@ }; mt6397_vgpu_reg: buck_vgpu { - regulator-compatible = "buck_vgpu"; regulator-name = "vgpu"; regulator-min-microvolt = < 700000>; regulator-max-microvolt = <1350000>; @@ -86,7 +80,6 @@ }; mt6397_vdrm_reg: buck_vdrm { - regulator-compatible = "buck_vdrm"; regulator-name = "vdrm"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1400000>; @@ -95,7 +88,6 @@ }; mt6397_vio18_reg: buck_vio18 { - regulator-compatible = "buck_vio18"; regulator-name = "vio18"; regulator-min-microvolt = <1620000>; regulator-max-microvolt = <1980000>; @@ -104,19 +96,16 @@ }; mt6397_vtcxo_reg: ldo_vtcxo { - regulator-compatible = "ldo_vtcxo"; regulator-name = "vtcxo"; regulator-always-on; }; mt6397_va28_reg: ldo_va28 { - regulator-compatible = "ldo_va28"; regulator-name = "va28"; regulator-always-on; }; mt6397_vcama_reg: ldo_vcama { - regulator-compatible = "ldo_vcama"; regulator-name = "vcama"; regulator-min-microvolt = <1500000>; regulator-max-microvolt = <2800000>; @@ -124,18 +113,15 @@ }; mt6397_vio28_reg: ldo_vio28 { - regulator-compatible = "ldo_vio28"; regulator-name = "vio28"; regulator-always-on; }; mt6397_vusb_reg: ldo_vusb { - regulator-compatible = "ldo_vusb"; regulator-name = "vusb"; }; mt6397_vmc_reg: ldo_vmc { - regulator-compatible = "ldo_vmc"; regulator-name = "vmc"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <3300000>; @@ -143,7 +129,6 @@ }; mt6397_vmch_reg: ldo_vmch { - regulator-compatible = "ldo_vmch"; regulator-name = "vmch"; regulator-min-microvolt = <3000000>; regulator-max-microvolt = <3300000>; @@ -151,7 +136,6 @@ }; mt6397_vemc_3v3_reg: ldo_vemc3v3 { - regulator-compatible = "ldo_vemc3v3"; regulator-name = "vemc_3v3"; regulator-min-microvolt = <3000000>; regulator-max-microvolt = <3300000>; @@ -159,7 +143,6 @@ }; mt6397_vgp1_reg: ldo_vgp1 { - regulator-compatible = "ldo_vgp1"; regulator-name = "vcamd"; regulator-min-microvolt = <1220000>; regulator-max-microvolt = <3300000>; @@ -167,7 +150,6 @@ }; mt6397_vgp2_reg: ldo_vgp2 { - regulator-compatible = "ldo_vgp2"; regulator-name = "vcamio"; regulator-min-microvolt = <1000000>; regulator-max-microvolt = <3300000>; @@ -175,7 +157,6 @@ }; mt6397_vgp3_reg: ldo_vgp3 { - regulator-compatible = "ldo_vgp3"; regulator-name = "vcamaf"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <3300000>; @@ -183,7 +164,6 @@ }; mt6397_vgp4_reg: ldo_vgp4 { - regulator-compatible = "ldo_vgp4"; regulator-name = "vgp4"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <3300000>; @@ -191,7 +171,6 @@ }; mt6397_vgp5_reg: ldo_vgp5 { - regulator-compatible = "ldo_vgp5"; regulator-name = "vgp5"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <3000000>; @@ -199,7 +178,6 @@ }; mt6397_vgp6_reg: ldo_vgp6 { - regulator-compatible = "ldo_vgp6"; regulator-name = "vgp6"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <3300000>; @@ -207,7 +185,6 @@ }; mt6397_vibr_reg: ldo_vibr { - regulator-compatible = "ldo_vibr"; regulator-name = "vibr"; regulator-min-microvolt = <1300000>; regulator-max-microvolt = <3300000>; -- cgit v0.10.2 From 0745c70260dbd763e93230acce92c6be43ba4a55 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Sun, 27 Sep 2015 22:28:38 +0200 Subject: ARM: dts: lpc18xx: add rgu node Add the NXP LPC1850 RGU (Reset Generation Unit) reset controller node to the dtsi for all lpc18xx/43xx devices. Signed-off-by: Joachim Eastwood diff --git a/arch/arm/boot/dts/lpc18xx.dtsi b/arch/arm/boot/dts/lpc18xx.dtsi index 2c569a6..29a62b6 100644 --- a/arch/arm/boot/dts/lpc18xx.dtsi +++ b/arch/arm/boot/dts/lpc18xx.dtsi @@ -178,6 +178,14 @@ "base_ssp0_clk", "base_sdio_clk"; }; + rgu: reset-controller@40053000 { + compatible = "nxp,lpc1850-rgu"; + reg = <0x40053000 0x1000>; + clocks = <&cgu BASE_SAFE_CLK>, <&ccu1 CLK_CPU_BUS>; + clock-names = "delay", "reg"; + #reset-cells = <1>; + }; + uart0: serial@40081000 { compatible = "nxp,lpc1850-uart", "ns16550a"; reg = <0x40081000 0x1000>; -- cgit v0.10.2 From 4f85dd16a52de59f6676bd55db309643c89b8704 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Thu, 2 Apr 2015 06:16:33 +0200 Subject: ARM: dts: lpc18xx: add spifi node Add the NXP LPC1773 SPIFI (SPI Flash Interface) flash controller node to the dtsi for all lpc18xx/43xx devices. Signed-off-by: Joachim Eastwood diff --git a/arch/arm/boot/dts/lpc18xx.dtsi b/arch/arm/boot/dts/lpc18xx.dtsi index 29a62b6..a428a09 100644 --- a/arch/arm/boot/dts/lpc18xx.dtsi +++ b/arch/arm/boot/dts/lpc18xx.dtsi @@ -68,6 +68,17 @@ }; soc { + spifi: flash-controller@40003000 { + compatible = "nxp,lpc1773-spifi"; + reg = <0x40003000 0x1000>, <0x14000000 0x4000000>; + reg-names = "spifi", "flash"; + interrupts = <30>; + clocks = <&ccu1 CLK_SPIFI>, <&ccu1 CLK_CPU_SPIFI>; + clock-names = "spifi", "reg"; + resets = <&rgu 53>; + status = "disabled"; + }; + mmcsd: mmcsd@40004000 { compatible = "snps,dw-mshc"; reg = <0x40004000 0x1000>; -- cgit v0.10.2 From 5924007c7ec807c2dd478ada8db10df6ca519373 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Tue, 26 May 2015 20:59:32 +0200 Subject: ARM: dts: lpc18xx: add dmac node Add the ARM PL080 DMA controller node to the dtsi for all lpc18xx/43xx devices. Signed-off-by: Joachim Eastwood diff --git a/arch/arm/boot/dts/lpc18xx.dtsi b/arch/arm/boot/dts/lpc18xx.dtsi index a428a09..5516c3e 100644 --- a/arch/arm/boot/dts/lpc18xx.dtsi +++ b/arch/arm/boot/dts/lpc18xx.dtsi @@ -68,6 +68,25 @@ }; soc { + dmac: dma-controller@40002000 { + compatible = "arm,pl080", "arm,primecell"; + arm,primecell-periphid = <0x00041080>; + reg = <0x40002000 0x1000>; + interrupts = <2>; + clocks = <&ccu1 CLK_CPU_DMA>; + clock-names = "apb_pclk"; + resets = <&rgu 19>; + #dma-cells = <2>; + dma-channels = <8>; + dma-requests = <16>; + lli-bus-interface-ahb1; + lli-bus-interface-ahb2; + mem-bus-interface-ahb1; + mem-bus-interface-ahb2; + memcpy-burst-size = <256>; + memcpy-bus-width = <32>; + }; + spifi: flash-controller@40003000 { compatible = "nxp,lpc1773-spifi"; reg = <0x40003000 0x1000>, <0x14000000 0x4000000>; -- cgit v0.10.2 From 5913f5595e4fba648fd89afe85ad3c6dee0e7ec2 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Wed, 27 May 2015 00:04:20 +0200 Subject: ARM: dts: lpc18xx: add dmamux node Add node for the DMA multiplexer placed in front of the PL080 DMA controller on lpc18xx/43xx devices. Signed-off-by: Joachim Eastwood diff --git a/arch/arm/boot/dts/lpc18xx.dtsi b/arch/arm/boot/dts/lpc18xx.dtsi index 5516c3e..f0d1a09 100644 --- a/arch/arm/boot/dts/lpc18xx.dtsi +++ b/arch/arm/boot/dts/lpc18xx.dtsi @@ -171,6 +171,13 @@ clocks = <&ccu1 CLK_USB0>; #phy-cells = <0>; }; + + dmamux: dma-mux@11c { + compatible = "nxp,lpc1850-dmamux"; + #dma-cells = <3>; + dma-requests = <64>; + dma-masters = <&dmac>; + }; }; cgu: clock-controller@40050000 { -- cgit v0.10.2 From 40a4a5727f21a0e439d317aa99953e24467605eb Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 28 Sep 2015 08:35:34 +0200 Subject: drm/i915: Update DRIVER_DATE to 20150928 Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6c3ef9c..c20f2c7 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -57,7 +57,7 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20150911" +#define DRIVER_DATE "20150928" #undef WARN_ON /* Many gcc seem to no see through this and fall over :( */ -- cgit v0.10.2 From beff1084f1cab155feb3551d72d41ce48af4ae79 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 24 Sep 2015 17:23:53 +0200 Subject: ARM: dts: sun8i: Add sun8i-a33-q8-tablet.dts file This is a generic dts file for A33 based q8 formfactor tablets, this is intended to replace both sun8i-a33-ippo-q8h-v1.2.dts and sun8i-a33-et-q8-v1.6.dts (these can be fully dropped after a transition period). Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 5dbfcb9..75d8092 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -635,6 +635,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \ sun8i-a33-et-q8-v1.6.dtb \ sun8i-a33-ga10h-v1.1.dtb \ sun8i-a33-ippo-q8h-v1.2.dtb \ + sun8i-a33-q8-tablet.dtb \ sun8i-a33-sinlinx-sina33.dtb dtb-$(CONFIG_MACH_SUN9I) += \ sun9i-a80-optimus.dtb \ diff --git a/arch/arm/boot/dts/sun8i-a33-q8-tablet.dts b/arch/arm/boot/dts/sun8i-a33-q8-tablet.dts new file mode 100644 index 0000000..44b3229 --- /dev/null +++ b/arch/arm/boot/dts/sun8i-a33-q8-tablet.dts @@ -0,0 +1,65 @@ +/* + * Copyright 2015 Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun8i-a33.dtsi" +#include "sun8i-q8-common.dtsi" + +/ { + model = "Q8 A33 Tablet"; + compatible = "allwinner,q8-a33", "allwinner,sun8i-a33"; +}; + +/* + * FIXME for now we only support host mode and rely on u-boot to have + * turned on Vbus which is controlled by the axp223 pmic on the board. + * + * Once we have axp223 support we should switch to fully supporting otg. + */ +&usb_otg { + dr_mode = "host"; + status = "okay"; +}; + +&usbphy { + status = "okay"; +}; -- cgit v0.10.2 From 9f06c5309a140eab80a4289f08c35c2496c4d1d3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 24 Sep 2015 17:23:54 +0200 Subject: ARM: dts: sun8i: Make ippo-q8h-v1.2.dts a symlink to q8-tablet.dts A33 Q8 tablets with the ippo-q8h-v1.2 pcb will work fine with the generic q8-tablet.dts and given the many variants of PCBs found in Q8 tablets using such a specific dts name was a mistake in hindsight. We cannot just drop the ippo-q8h-v1.2.dtb as existing u-boot configs may very well point to it. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun8i-a33-ippo-q8h-v1.2.dts b/arch/arm/boot/dts/sun8i-a33-ippo-q8h-v1.2.dts deleted file mode 100644 index b8439cb..0000000 --- a/arch/arm/boot/dts/sun8i-a33-ippo-q8h-v1.2.dts +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2015 Hans de Goede - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -/dts-v1/; -#include "sun8i-a33.dtsi" -#include "sun8i-q8-common.dtsi" - -/ { - model = "Ippo Q8H Quad Core Tablet (v1.2)"; - compatible = "ippo,a33-q8h-v1.2", "allwinner,sun8i-a33"; -}; - -/* - * FIXME for now we only support host mode and rely on u-boot to have - * turned on Vbus which is controlled by the axp223 pmic on the board. - * - * Once we have axp223 support we should switch to fully supporting otg. - */ -&usb_otg { - dr_mode = "host"; - status = "okay"; -}; - -&usbphy { - status = "okay"; -}; diff --git a/arch/arm/boot/dts/sun8i-a33-ippo-q8h-v1.2.dts b/arch/arm/boot/dts/sun8i-a33-ippo-q8h-v1.2.dts new file mode 120000 index 0000000..4519fd7 --- /dev/null +++ b/arch/arm/boot/dts/sun8i-a33-ippo-q8h-v1.2.dts @@ -0,0 +1 @@ +sun8i-a33-q8-tablet.dts \ No newline at end of file -- cgit v0.10.2 From 80f390ea5afdf7073bba0757b1eeb8d4f833398f Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 14 May 2015 11:26:11 +0100 Subject: Documentation: add DT binding for ARM System Control and Power Interface(SCPI) protocol This patch adds devicetree binding for System Control and Power Interface (SCPI) Message Protocol used between the Application Cores(AP) and the System Control Processor(SCP). The MHU peripheral provides a mechanism for inter-processor communication between SCP's M3 processor and AP. SCP offers control and management of the core/cluster power states, various power domain DVFS including the core/cluster, certain system clocks configuration, thermal sensors and many others. Signed-off-by: Sudeep Holla Acked-by: Mark Rutland Cc: Rob Herring CC: Jassi Brar Cc: Liviu Dudau Cc: Lorenzo Pieralisi Cc: Jon Medhurst (Tixy) Cc: devicetree@vger.kernel.org diff --git a/Documentation/devicetree/bindings/arm/arm,scpi.txt b/Documentation/devicetree/bindings/arm/arm,scpi.txt new file mode 100644 index 0000000..f002460 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/arm,scpi.txt @@ -0,0 +1,150 @@ +System Control and Power Interface (SCPI) Message Protocol +---------------------------------------------------------- + +Firmware implementing the SCPI described in ARM document number ARM DUI 0922B +("ARM Compute Subsystem SCP: Message Interface Protocols")[0] can be used +by Linux to initiate various system control and power operations. + +Required properties: + +- compatible : should be "arm,scpi" +- mboxes: List of phandle and mailbox channel specifiers + All the channels reserved by remote SCP firmware for use by + SCPI message protocol should be specified in any order +- shmem : List of phandle pointing to the shared memory(SHM) area between the + processors using these mailboxes for IPC, one for each mailbox + SHM can be any memory reserved for the purpose of this communication + between the processors. + +See Documentation/devicetree/bindings/mailbox/mailbox.txt +for more details about the generic mailbox controller and +client driver bindings. + +Clock bindings for the clocks based on SCPI Message Protocol +------------------------------------------------------------ + +This binding uses the common clock binding[1]. + +Container Node +============== +Required properties: +- compatible : should be "arm,scpi-clocks" + All the clocks provided by SCP firmware via SCPI message + protocol much be listed as sub-nodes under this node. + +Sub-nodes +========= +Required properties: +- compatible : shall include one of the following + "arm,scpi-dvfs-clocks" - all the clocks that are variable and index based. + These clocks don't provide an entire range of values between the + limits but only discrete points within the range. The firmware + provides the mapping for each such operating frequency and the + index associated with it. The firmware also manages the + voltage scaling appropriately with the clock scaling. + "arm,scpi-variable-clocks" - all the clocks that are variable and provide full + range within the specified range. The firmware provides the + range of values within a specified range. + +Other required properties for all clocks(all from common clock binding): +- #clock-cells : Should be 1. Contains the Clock ID value used by SCPI commands. +- clock-output-names : shall be the corresponding names of the outputs. +- clock-indices: The identifying number for the clocks(i.e.clock_id) in the + node. It can be non linear and hence provide the mapping of identifiers + into the clock-output-names array. + +SRAM and Shared Memory for SCPI +------------------------------- + +A small area of SRAM is reserved for SCPI communication between application +processors and SCP. + +Required properties: +- compatible : should be "arm,juno-sram-ns" for Non-secure SRAM on Juno + +The rest of the properties should follow the generic mmio-sram description +found in ../../misc/sysram.txt + +Each sub-node represents the reserved area for SCPI. + +Required sub-node properties: +- reg : The base offset and size of the reserved area with the SRAM +- compatible : should be "arm,juno-scp-shmem" for Non-secure SRAM based + shared memory on Juno platforms + +[0] http://infocenter.arm.com/help/topic/com.arm.doc.dui0922b/index.html +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt + +Example: + +sram: sram@50000000 { + compatible = "arm,juno-sram-ns", "mmio-sram"; + reg = <0x0 0x50000000 0x0 0x10000>; + + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x0 0x50000000 0x10000>; + + cpu_scp_lpri: scp-shmem@0 { + compatible = "arm,juno-scp-shmem"; + reg = <0x0 0x200>; + }; + + cpu_scp_hpri: scp-shmem@200 { + compatible = "arm,juno-scp-shmem"; + reg = <0x200 0x200>; + }; +}; + +mailbox: mailbox0@40000000 { + .... + #mbox-cells = <1>; +}; + +scpi_protocol: scpi@2e000000 { + compatible = "arm,scpi"; + mboxes = <&mailbox 0 &mailbox 1>; + shmem = <&cpu_scp_lpri &cpu_scp_hpri>; + + clocks { + compatible = "arm,scpi-clocks"; + + scpi_dvfs: scpi_clocks@0 { + compatible = "arm,scpi-dvfs-clocks"; + #clock-cells = <1>; + clock-indices = <0>, <1>, <2>; + clock-output-names = "atlclk", "aplclk","gpuclk"; + }; + scpi_clk: scpi_clocks@3 { + compatible = "arm,scpi-variable-clocks"; + #clock-cells = <1>; + clock-indices = <3>, <4>; + clock-output-names = "pxlclk0", "pxlclk1"; + }; + }; +}; + +cpu@0 { + ... + reg = <0 0>; + clocks = <&scpi_dvfs 0>; +}; + +hdlcd@7ff60000 { + ... + reg = <0 0x7ff60000 0 0x1000>; + clocks = <&scpi_clk 4>; +}; + +In the above example, the #clock-cells is set to 1 as required. +scpi_dvfs has 3 output clocks namely: atlclk, aplclk, and gpuclk with 0, +1 and 2 as clock-indices. scpi_clk has 2 output clocks namely: pxlclk0 +and pxlclk1 with 3 and 4 as clock-indices. + +The first consumer in the example is cpu@0 and it has '0' as the clock +specifier which points to the first entry in the output clocks of +scpi_dvfs i.e. "atlclk". + +Similarly the second example is hdlcd@7ff60000 and it has pxlclk1 as input +clock. '4' in the clock specifier here points to the second entry +in the output clocks of scpi_clocks i.e. "pxlclk1" diff --git a/MAINTAINERS b/MAINTAINERS index 7ba7ab7..be7d5c1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9149,6 +9149,12 @@ W: http://www.sunplus.com S: Supported F: arch/score/ +SYSTEM CONTROL & POWER INTERFACE (SCPI) Message Protocol drivers +M: Sudeep Holla +L: linux-arm-kernel@lists.infradead.org +S: Maintained +F: Documentation/devicetree/bindings/arm/arm,scpi.txt + SCSI CDROM DRIVER M: Jens Axboe L: linux-scsi@vger.kernel.org -- cgit v0.10.2 From 8cb7cf56c9fe5412de238465b27ef35b4d2801aa Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 30 Mar 2015 10:59:52 +0100 Subject: firmware: add support for ARM System Control and Power Interface(SCPI) protocol This patch adds support for System Control and Power Interface (SCPI) Message Protocol used between the Application Cores(AP) and the System Control Processor(SCP). The MHU peripheral provides a mechanism for inter-processor communication between SCP's M3 processor and AP. SCP offers control and management of the core/cluster power states, various power domain DVFS including the core/cluster, certain system clocks configuration, thermal sensors and many others. This protocol driver provides interface for all the client drivers using SCPI to make use of the features offered by the SCP. Signed-off-by: Sudeep Holla Reviewed-by: Jon Medhurst (Tixy) Cc: Jassi Brar Cc: Liviu Dudau Cc: Lorenzo Pieralisi diff --git a/MAINTAINERS b/MAINTAINERS index be7d5c1..9598821 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9154,6 +9154,8 @@ M: Sudeep Holla L: linux-arm-kernel@lists.infradead.org S: Maintained F: Documentation/devicetree/bindings/arm/arm,scpi.txt +F: drivers/firmware/arm_scpi.c +F: include/linux/scpi_protocol.h SCSI CDROM DRIVER M: Jens Axboe diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index d8de6a8..800b743 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -8,6 +8,25 @@ menu "Firmware Drivers" config ARM_PSCI_FW bool +config ARM_SCPI_PROTOCOL + tristate "ARM System Control and Power Interface (SCPI) Message Protocol" + depends on ARM_MHU + help + System Control and Power Interface (SCPI) Message Protocol is + defined for the purpose of communication between the Application + Cores(AP) and the System Control Processor(SCP). The MHU peripheral + provides a mechanism for inter-processor communication between SCP + and AP. + + SCP controls most of the power managament on the Application + Processors. It offers control and management of: the core/cluster + power states, various power domain DVFS including the core/cluster, + certain system clocks configuration, thermal sensors and many + others. + + This protocol library provides interface for all the client drivers + making use of the features offered by the SCP. + config EDD tristate "BIOS Enhanced Disk Drive calls determine boot disk" depends on X86 diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 000830f..e4c3a3f 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -2,6 +2,7 @@ # Makefile for the linux kernel. # obj-$(CONFIG_ARM_PSCI_FW) += psci.o +obj-$(CONFIG_ARM_SCPI_PROTOCOL) += arm_scpi.o obj-$(CONFIG_DMI) += dmi_scan.o obj-$(CONFIG_DMI_SYSFS) += dmi-sysfs.o obj-$(CONFIG_EDD) += edd.o diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c new file mode 100644 index 0000000..cb75c75 --- /dev/null +++ b/drivers/firmware/arm_scpi.c @@ -0,0 +1,711 @@ +/* + * System Control and Power Interface (SCPI) Message Protocol driver + * + * SCPI Message Protocol is used between the System Control Processor(SCP) + * and the Application Processors(AP). The Message Handling Unit(MHU) + * provides a mechanism for inter-processor communication between SCP's + * Cortex M3 and AP. + * + * SCP offers control and management of the core/cluster power states, + * various power domain DVFS including the core/cluster, certain system + * clocks configuration, thermal sensors and many others. + * + * Copyright (C) 2015 ARM Ltd. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CMD_ID_SHIFT 0 +#define CMD_ID_MASK 0x7f +#define CMD_TOKEN_ID_SHIFT 8 +#define CMD_TOKEN_ID_MASK 0xff +#define CMD_DATA_SIZE_SHIFT 16 +#define CMD_DATA_SIZE_MASK 0x1ff +#define PACK_SCPI_CMD(cmd_id, tx_sz) \ + ((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) | \ + (((tx_sz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT)) +#define ADD_SCPI_TOKEN(cmd, token) \ + ((cmd) |= (((token) & CMD_TOKEN_ID_MASK) << CMD_TOKEN_ID_SHIFT)) + +#define CMD_SIZE(cmd) (((cmd) >> CMD_DATA_SIZE_SHIFT) & CMD_DATA_SIZE_MASK) +#define CMD_UNIQ_MASK (CMD_TOKEN_ID_MASK << CMD_TOKEN_ID_SHIFT | CMD_ID_MASK) +#define CMD_XTRACT_UNIQ(cmd) ((cmd) & CMD_UNIQ_MASK) + +#define SCPI_SLOT 0 + +#define MAX_DVFS_DOMAINS 8 +#define MAX_DVFS_OPPS 8 +#define DVFS_LATENCY(hdr) (le32_to_cpu(hdr) >> 16) +#define DVFS_OPP_COUNT(hdr) ((le32_to_cpu(hdr) >> 8) & 0xff) + +#define PROTOCOL_REV_MINOR_BITS 16 +#define PROTOCOL_REV_MINOR_MASK ((1U << PROTOCOL_REV_MINOR_BITS) - 1) +#define PROTOCOL_REV_MAJOR(x) ((x) >> PROTOCOL_REV_MINOR_BITS) +#define PROTOCOL_REV_MINOR(x) ((x) & PROTOCOL_REV_MINOR_MASK) + +#define FW_REV_MAJOR_BITS 24 +#define FW_REV_MINOR_BITS 16 +#define FW_REV_PATCH_MASK ((1U << FW_REV_MINOR_BITS) - 1) +#define FW_REV_MINOR_MASK ((1U << FW_REV_MAJOR_BITS) - 1) +#define FW_REV_MAJOR(x) ((x) >> FW_REV_MAJOR_BITS) +#define FW_REV_MINOR(x) (((x) & FW_REV_MINOR_MASK) >> FW_REV_MINOR_BITS) +#define FW_REV_PATCH(x) ((x) & FW_REV_PATCH_MASK) + +#define MAX_RX_TIMEOUT (msecs_to_jiffies(20)) + +enum scpi_error_codes { + SCPI_SUCCESS = 0, /* Success */ + SCPI_ERR_PARAM = 1, /* Invalid parameter(s) */ + SCPI_ERR_ALIGN = 2, /* Invalid alignment */ + SCPI_ERR_SIZE = 3, /* Invalid size */ + SCPI_ERR_HANDLER = 4, /* Invalid handler/callback */ + SCPI_ERR_ACCESS = 5, /* Invalid access/permission denied */ + SCPI_ERR_RANGE = 6, /* Value out of range */ + SCPI_ERR_TIMEOUT = 7, /* Timeout has occurred */ + SCPI_ERR_NOMEM = 8, /* Invalid memory area or pointer */ + SCPI_ERR_PWRSTATE = 9, /* Invalid power state */ + SCPI_ERR_SUPPORT = 10, /* Not supported or disabled */ + SCPI_ERR_DEVICE = 11, /* Device error */ + SCPI_ERR_BUSY = 12, /* Device busy */ + SCPI_ERR_MAX +}; + +enum scpi_std_cmd { + SCPI_CMD_INVALID = 0x00, + SCPI_CMD_SCPI_READY = 0x01, + SCPI_CMD_SCPI_CAPABILITIES = 0x02, + SCPI_CMD_SET_CSS_PWR_STATE = 0x03, + SCPI_CMD_GET_CSS_PWR_STATE = 0x04, + SCPI_CMD_SET_SYS_PWR_STATE = 0x05, + SCPI_CMD_SET_CPU_TIMER = 0x06, + SCPI_CMD_CANCEL_CPU_TIMER = 0x07, + SCPI_CMD_DVFS_CAPABILITIES = 0x08, + SCPI_CMD_GET_DVFS_INFO = 0x09, + SCPI_CMD_SET_DVFS = 0x0a, + SCPI_CMD_GET_DVFS = 0x0b, + SCPI_CMD_GET_DVFS_STAT = 0x0c, + SCPI_CMD_CLOCK_CAPABILITIES = 0x0d, + SCPI_CMD_GET_CLOCK_INFO = 0x0e, + SCPI_CMD_SET_CLOCK_VALUE = 0x0f, + SCPI_CMD_GET_CLOCK_VALUE = 0x10, + SCPI_CMD_PSU_CAPABILITIES = 0x11, + SCPI_CMD_GET_PSU_INFO = 0x12, + SCPI_CMD_SET_PSU = 0x13, + SCPI_CMD_GET_PSU = 0x14, + SCPI_CMD_SENSOR_CAPABILITIES = 0x15, + SCPI_CMD_SENSOR_INFO = 0x16, + SCPI_CMD_SENSOR_VALUE = 0x17, + SCPI_CMD_SENSOR_CFG_PERIODIC = 0x18, + SCPI_CMD_SENSOR_CFG_BOUNDS = 0x19, + SCPI_CMD_SENSOR_ASYNC_VALUE = 0x1a, + SCPI_CMD_SET_DEVICE_PWR_STATE = 0x1b, + SCPI_CMD_GET_DEVICE_PWR_STATE = 0x1c, + SCPI_CMD_COUNT +}; + +struct scpi_xfer { + u32 slot; /* has to be first element */ + u32 cmd; + u32 status; + const void *tx_buf; + void *rx_buf; + unsigned int tx_len; + unsigned int rx_len; + struct list_head node; + struct completion done; +}; + +struct scpi_chan { + struct mbox_client cl; + struct mbox_chan *chan; + void __iomem *tx_payload; + void __iomem *rx_payload; + struct list_head rx_pending; + struct list_head xfers_list; + struct scpi_xfer *xfers; + spinlock_t rx_lock; /* locking for the rx pending list */ + struct mutex xfers_lock; + u8 token; +}; + +struct scpi_drvinfo { + u32 protocol_version; + u32 firmware_version; + int num_chans; + atomic_t next_chan; + struct scpi_ops *scpi_ops; + struct scpi_chan *channels; + struct scpi_dvfs_info *dvfs[MAX_DVFS_DOMAINS]; +}; + +/* + * The SCP firmware only executes in little-endian mode, so any buffers + * shared through SCPI should have their contents converted to little-endian + */ +struct scpi_shared_mem { + __le32 command; + __le32 status; + u8 payload[0]; +} __packed; + +struct scp_capabilities { + __le32 protocol_version; + __le32 event_version; + __le32 platform_version; + __le32 commands[4]; +} __packed; + +struct clk_get_info { + __le16 id; + __le16 flags; + __le32 min_rate; + __le32 max_rate; + u8 name[20]; +} __packed; + +struct clk_get_value { + __le32 rate; +} __packed; + +struct clk_set_value { + __le16 id; + __le16 reserved; + __le32 rate; +} __packed; + +struct dvfs_info { + __le32 header; + struct { + __le32 freq; + __le32 m_volt; + } opps[MAX_DVFS_OPPS]; +} __packed; + +struct dvfs_get { + u8 index; +} __packed; + +struct dvfs_set { + u8 domain; + u8 index; +} __packed; + +static struct scpi_drvinfo *scpi_info; + +static int scpi_linux_errmap[SCPI_ERR_MAX] = { + /* better than switch case as long as return value is continuous */ + 0, /* SCPI_SUCCESS */ + -EINVAL, /* SCPI_ERR_PARAM */ + -ENOEXEC, /* SCPI_ERR_ALIGN */ + -EMSGSIZE, /* SCPI_ERR_SIZE */ + -EINVAL, /* SCPI_ERR_HANDLER */ + -EACCES, /* SCPI_ERR_ACCESS */ + -ERANGE, /* SCPI_ERR_RANGE */ + -ETIMEDOUT, /* SCPI_ERR_TIMEOUT */ + -ENOMEM, /* SCPI_ERR_NOMEM */ + -EINVAL, /* SCPI_ERR_PWRSTATE */ + -EOPNOTSUPP, /* SCPI_ERR_SUPPORT */ + -EIO, /* SCPI_ERR_DEVICE */ + -EBUSY, /* SCPI_ERR_BUSY */ +}; + +static inline int scpi_to_linux_errno(int errno) +{ + if (errno >= SCPI_SUCCESS && errno < SCPI_ERR_MAX) + return scpi_linux_errmap[errno]; + return -EIO; +} + +static void scpi_process_cmd(struct scpi_chan *ch, u32 cmd) +{ + unsigned long flags; + struct scpi_xfer *t, *match = NULL; + + spin_lock_irqsave(&ch->rx_lock, flags); + if (list_empty(&ch->rx_pending)) { + spin_unlock_irqrestore(&ch->rx_lock, flags); + return; + } + + list_for_each_entry(t, &ch->rx_pending, node) + if (CMD_XTRACT_UNIQ(t->cmd) == CMD_XTRACT_UNIQ(cmd)) { + list_del(&t->node); + match = t; + break; + } + /* check if wait_for_completion is in progress or timed-out */ + if (match && !completion_done(&match->done)) { + struct scpi_shared_mem *mem = ch->rx_payload; + unsigned int len = min(match->rx_len, CMD_SIZE(cmd)); + + match->status = le32_to_cpu(mem->status); + memcpy_fromio(match->rx_buf, mem->payload, len); + if (match->rx_len > len) + memset(match->rx_buf + len, 0, match->rx_len - len); + complete(&match->done); + } + spin_unlock_irqrestore(&ch->rx_lock, flags); +} + +static void scpi_handle_remote_msg(struct mbox_client *c, void *msg) +{ + struct scpi_chan *ch = container_of(c, struct scpi_chan, cl); + struct scpi_shared_mem *mem = ch->rx_payload; + u32 cmd = le32_to_cpu(mem->command); + + scpi_process_cmd(ch, cmd); +} + +static void scpi_tx_prepare(struct mbox_client *c, void *msg) +{ + unsigned long flags; + struct scpi_xfer *t = msg; + struct scpi_chan *ch = container_of(c, struct scpi_chan, cl); + struct scpi_shared_mem *mem = (struct scpi_shared_mem *)ch->tx_payload; + + if (t->tx_buf) + memcpy_toio(mem->payload, t->tx_buf, t->tx_len); + if (t->rx_buf) { + if (!(++ch->token)) + ++ch->token; + ADD_SCPI_TOKEN(t->cmd, ch->token); + spin_lock_irqsave(&ch->rx_lock, flags); + list_add_tail(&t->node, &ch->rx_pending); + spin_unlock_irqrestore(&ch->rx_lock, flags); + } + mem->command = cpu_to_le32(t->cmd); +} + +static struct scpi_xfer *get_scpi_xfer(struct scpi_chan *ch) +{ + struct scpi_xfer *t; + + mutex_lock(&ch->xfers_lock); + if (list_empty(&ch->xfers_list)) { + mutex_unlock(&ch->xfers_lock); + return NULL; + } + t = list_first_entry(&ch->xfers_list, struct scpi_xfer, node); + list_del(&t->node); + mutex_unlock(&ch->xfers_lock); + return t; +} + +static void put_scpi_xfer(struct scpi_xfer *t, struct scpi_chan *ch) +{ + mutex_lock(&ch->xfers_lock); + list_add_tail(&t->node, &ch->xfers_list); + mutex_unlock(&ch->xfers_lock); +} + +static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len, + void *rx_buf, unsigned int rx_len) +{ + int ret; + u8 chan; + struct scpi_xfer *msg; + struct scpi_chan *scpi_chan; + + chan = atomic_inc_return(&scpi_info->next_chan) % scpi_info->num_chans; + scpi_chan = scpi_info->channels + chan; + + msg = get_scpi_xfer(scpi_chan); + if (!msg) + return -ENOMEM; + + msg->slot = BIT(SCPI_SLOT); + msg->cmd = PACK_SCPI_CMD(cmd, tx_len); + msg->tx_buf = tx_buf; + msg->tx_len = tx_len; + msg->rx_buf = rx_buf; + msg->rx_len = rx_len; + init_completion(&msg->done); + + ret = mbox_send_message(scpi_chan->chan, msg); + if (ret < 0 || !rx_buf) + goto out; + + if (!wait_for_completion_timeout(&msg->done, MAX_RX_TIMEOUT)) + ret = -ETIMEDOUT; + else + /* first status word */ + ret = le32_to_cpu(msg->status); +out: + if (ret < 0 && rx_buf) /* remove entry from the list if timed-out */ + scpi_process_cmd(scpi_chan, msg->cmd); + + put_scpi_xfer(msg, scpi_chan); + /* SCPI error codes > 0, translate them to Linux scale*/ + return ret > 0 ? scpi_to_linux_errno(ret) : ret; +} + +static u32 scpi_get_version(void) +{ + return scpi_info->protocol_version; +} + +static int +scpi_clk_get_range(u16 clk_id, unsigned long *min, unsigned long *max) +{ + int ret; + struct clk_get_info clk; + __le16 le_clk_id = cpu_to_le16(clk_id); + + ret = scpi_send_message(SCPI_CMD_GET_CLOCK_INFO, &le_clk_id, + sizeof(le_clk_id), &clk, sizeof(clk)); + if (!ret) { + *min = le32_to_cpu(clk.min_rate); + *max = le32_to_cpu(clk.max_rate); + } + return ret; +} + +static unsigned long scpi_clk_get_val(u16 clk_id) +{ + int ret; + struct clk_get_value clk; + __le16 le_clk_id = cpu_to_le16(clk_id); + + ret = scpi_send_message(SCPI_CMD_GET_CLOCK_VALUE, &le_clk_id, + sizeof(le_clk_id), &clk, sizeof(clk)); + return ret ? ret : le32_to_cpu(clk.rate); +} + +static int scpi_clk_set_val(u16 clk_id, unsigned long rate) +{ + int stat; + struct clk_set_value clk = { + .id = cpu_to_le16(clk_id), + .rate = cpu_to_le32(rate) + }; + + return scpi_send_message(SCPI_CMD_SET_CLOCK_VALUE, &clk, sizeof(clk), + &stat, sizeof(stat)); +} + +static int scpi_dvfs_get_idx(u8 domain) +{ + int ret; + struct dvfs_get dvfs; + + ret = scpi_send_message(SCPI_CMD_GET_DVFS, &domain, sizeof(domain), + &dvfs, sizeof(dvfs)); + return ret ? ret : dvfs.index; +} + +static int scpi_dvfs_set_idx(u8 domain, u8 index) +{ + int stat; + struct dvfs_set dvfs = {domain, index}; + + return scpi_send_message(SCPI_CMD_SET_DVFS, &dvfs, sizeof(dvfs), + &stat, sizeof(stat)); +} + +static int opp_cmp_func(const void *opp1, const void *opp2) +{ + const struct scpi_opp *t1 = opp1, *t2 = opp2; + + return t1->freq - t2->freq; +} + +static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain) +{ + struct scpi_dvfs_info *info; + struct scpi_opp *opp; + struct dvfs_info buf; + int ret, i; + + if (domain >= MAX_DVFS_DOMAINS) + return ERR_PTR(-EINVAL); + + if (scpi_info->dvfs[domain]) /* data already populated */ + return scpi_info->dvfs[domain]; + + ret = scpi_send_message(SCPI_CMD_GET_DVFS_INFO, &domain, sizeof(domain), + &buf, sizeof(buf)); + + if (ret) + return ERR_PTR(ret); + + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return ERR_PTR(-ENOMEM); + + info->count = DVFS_OPP_COUNT(buf.header); + info->latency = DVFS_LATENCY(buf.header) * 1000; /* uS to nS */ + + info->opps = kcalloc(info->count, sizeof(*opp), GFP_KERNEL); + if (!info->opps) { + kfree(info); + return ERR_PTR(-ENOMEM); + } + + for (i = 0, opp = info->opps; i < info->count; i++, opp++) { + opp->freq = le32_to_cpu(buf.opps[i].freq); + opp->m_volt = le32_to_cpu(buf.opps[i].m_volt); + } + + sort(info->opps, info->count, sizeof(*opp), opp_cmp_func, NULL); + + scpi_info->dvfs[domain] = info; + return info; +} + +static struct scpi_ops scpi_ops = { + .get_version = scpi_get_version, + .clk_get_range = scpi_clk_get_range, + .clk_get_val = scpi_clk_get_val, + .clk_set_val = scpi_clk_set_val, + .dvfs_get_idx = scpi_dvfs_get_idx, + .dvfs_set_idx = scpi_dvfs_set_idx, + .dvfs_get_info = scpi_dvfs_get_info, +}; + +struct scpi_ops *get_scpi_ops(void) +{ + return scpi_info ? scpi_info->scpi_ops : NULL; +} +EXPORT_SYMBOL_GPL(get_scpi_ops); + +static int scpi_init_versions(struct scpi_drvinfo *info) +{ + int ret; + struct scp_capabilities caps; + + ret = scpi_send_message(SCPI_CMD_SCPI_CAPABILITIES, NULL, 0, + &caps, sizeof(caps)); + if (!ret) { + info->protocol_version = le32_to_cpu(caps.protocol_version); + info->firmware_version = le32_to_cpu(caps.platform_version); + } + return ret; +} + +static ssize_t protocol_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct scpi_drvinfo *scpi_info = dev_get_drvdata(dev); + + return sprintf(buf, "%d.%d\n", + PROTOCOL_REV_MAJOR(scpi_info->protocol_version), + PROTOCOL_REV_MINOR(scpi_info->protocol_version)); +} +static DEVICE_ATTR_RO(protocol_version); + +static ssize_t firmware_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct scpi_drvinfo *scpi_info = dev_get_drvdata(dev); + + return sprintf(buf, "%d.%d.%d\n", + FW_REV_MAJOR(scpi_info->firmware_version), + FW_REV_MINOR(scpi_info->firmware_version), + FW_REV_PATCH(scpi_info->firmware_version)); +} +static DEVICE_ATTR_RO(firmware_version); + +static struct attribute *versions_attrs[] = { + &dev_attr_firmware_version.attr, + &dev_attr_protocol_version.attr, + NULL, +}; +ATTRIBUTE_GROUPS(versions); + +static void +scpi_free_channels(struct device *dev, struct scpi_chan *pchan, int count) +{ + int i; + + for (i = 0; i < count && pchan->chan; i++, pchan++) { + mbox_free_channel(pchan->chan); + devm_kfree(dev, pchan->xfers); + devm_iounmap(dev, pchan->rx_payload); + } +} + +static int scpi_remove(struct platform_device *pdev) +{ + int i; + struct device *dev = &pdev->dev; + struct scpi_drvinfo *info = platform_get_drvdata(pdev); + + scpi_info = NULL; /* stop exporting SCPI ops through get_scpi_ops */ + + of_platform_depopulate(dev); + sysfs_remove_groups(&dev->kobj, versions_groups); + scpi_free_channels(dev, info->channels, info->num_chans); + platform_set_drvdata(pdev, NULL); + + for (i = 0; i < MAX_DVFS_DOMAINS && info->dvfs[i]; i++) { + kfree(info->dvfs[i]->opps); + kfree(info->dvfs[i]); + } + devm_kfree(dev, info->channels); + devm_kfree(dev, info); + + return 0; +} + +#define MAX_SCPI_XFERS 10 +static int scpi_alloc_xfer_list(struct device *dev, struct scpi_chan *ch) +{ + int i; + struct scpi_xfer *xfers; + + xfers = devm_kzalloc(dev, MAX_SCPI_XFERS * sizeof(*xfers), GFP_KERNEL); + if (!xfers) + return -ENOMEM; + + ch->xfers = xfers; + for (i = 0; i < MAX_SCPI_XFERS; i++, xfers++) + list_add_tail(&xfers->node, &ch->xfers_list); + return 0; +} + +static int scpi_probe(struct platform_device *pdev) +{ + int count, idx, ret; + struct resource res; + struct scpi_chan *scpi_chan; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + + scpi_info = devm_kzalloc(dev, sizeof(*scpi_info), GFP_KERNEL); + if (!scpi_info) + return -ENOMEM; + + count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells"); + if (count < 0) { + dev_err(dev, "no mboxes property in '%s'\n", np->full_name); + return -ENODEV; + } + + scpi_chan = devm_kcalloc(dev, count, sizeof(*scpi_chan), GFP_KERNEL); + if (!scpi_chan) + return -ENOMEM; + + for (idx = 0; idx < count; idx++) { + resource_size_t size; + struct scpi_chan *pchan = scpi_chan + idx; + struct mbox_client *cl = &pchan->cl; + struct device_node *shmem = of_parse_phandle(np, "shmem", idx); + + if (of_address_to_resource(shmem, 0, &res)) { + dev_err(dev, "failed to get SCPI payload mem resource\n"); + ret = -EINVAL; + goto err; + } + + size = resource_size(&res); + pchan->rx_payload = devm_ioremap(dev, res.start, size); + if (!pchan->rx_payload) { + dev_err(dev, "failed to ioremap SCPI payload\n"); + ret = -EADDRNOTAVAIL; + goto err; + } + pchan->tx_payload = pchan->rx_payload + (size >> 1); + + cl->dev = dev; + cl->rx_callback = scpi_handle_remote_msg; + cl->tx_prepare = scpi_tx_prepare; + cl->tx_block = true; + cl->tx_tout = 50; + cl->knows_txdone = false; /* controller can't ack */ + + INIT_LIST_HEAD(&pchan->rx_pending); + INIT_LIST_HEAD(&pchan->xfers_list); + spin_lock_init(&pchan->rx_lock); + mutex_init(&pchan->xfers_lock); + + ret = scpi_alloc_xfer_list(dev, pchan); + if (!ret) { + pchan->chan = mbox_request_channel(cl, idx); + if (!IS_ERR(pchan->chan)) + continue; + ret = PTR_ERR(pchan->chan); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get channel%d err %d\n", + idx, ret); + } +err: + scpi_free_channels(dev, scpi_chan, idx); + scpi_info = NULL; + return ret; + } + + scpi_info->channels = scpi_chan; + scpi_info->num_chans = count; + platform_set_drvdata(pdev, scpi_info); + + ret = scpi_init_versions(scpi_info); + if (ret) { + dev_err(dev, "incorrect or no SCP firmware found\n"); + scpi_remove(pdev); + return ret; + } + + _dev_info(dev, "SCP Protocol %d.%d Firmware %d.%d.%d version\n", + PROTOCOL_REV_MAJOR(scpi_info->protocol_version), + PROTOCOL_REV_MINOR(scpi_info->protocol_version), + FW_REV_MAJOR(scpi_info->firmware_version), + FW_REV_MINOR(scpi_info->firmware_version), + FW_REV_PATCH(scpi_info->firmware_version)); + scpi_info->scpi_ops = &scpi_ops; + + ret = sysfs_create_groups(&dev->kobj, versions_groups); + if (ret) + dev_err(dev, "unable to create sysfs version group\n"); + + return of_platform_populate(dev->of_node, NULL, NULL, dev); +} + +static const struct of_device_id scpi_of_match[] = { + {.compatible = "arm,scpi"}, + {}, +}; + +MODULE_DEVICE_TABLE(of, scpi_of_match); + +static struct platform_driver scpi_driver = { + .driver = { + .name = "scpi_protocol", + .of_match_table = scpi_of_match, + }, + .probe = scpi_probe, + .remove = scpi_remove, +}; +module_platform_driver(scpi_driver); + +MODULE_AUTHOR("Sudeep Holla "); +MODULE_DESCRIPTION("ARM SCPI mailbox protocol driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/scpi_protocol.h b/include/linux/scpi_protocol.h new file mode 100644 index 0000000..e7169cd --- /dev/null +++ b/include/linux/scpi_protocol.h @@ -0,0 +1,61 @@ +/* + * SCPI Message Protocol driver header + * + * Copyright (C) 2014 ARM Ltd. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ +#include + +struct scpi_opp { + u32 freq; + u32 m_volt; +} __packed; + +struct scpi_dvfs_info { + unsigned int count; + unsigned int latency; /* in nanoseconds */ + struct scpi_opp *opps; +}; + +/** + * struct scpi_ops - represents the various operations provided + * by SCP through SCPI message protocol + * @get_version: returns the major and minor revision on the SCPI + * message protocol + * @clk_get_range: gets clock range limit(min - max in Hz) + * @clk_get_val: gets clock value(in Hz) + * @clk_set_val: sets the clock value, setting to 0 will disable the + * clock (if supported) + * @dvfs_get_idx: gets the Operating Point of the given power domain. + * OPP is an index to the list return by @dvfs_get_info + * @dvfs_set_idx: sets the Operating Point of the given power domain. + * OPP is an index to the list return by @dvfs_get_info + * @dvfs_get_info: returns the DVFS capabilities of the given power + * domain. It includes the OPP list and the latency information + */ +struct scpi_ops { + u32 (*get_version)(void); + int (*clk_get_range)(u16, unsigned long *, unsigned long *); + unsigned long (*clk_get_val)(u16); + int (*clk_set_val)(u16, unsigned long); + int (*dvfs_get_idx)(u8); + int (*dvfs_set_idx)(u8, u8); + struct scpi_dvfs_info *(*dvfs_get_info)(u8); +}; + +#if IS_ENABLED(CONFIG_ARM_SCPI_PROTOCOL) +struct scpi_ops *get_scpi_ops(void); +#else +static inline struct scpi_ops *get_scpi_ops(void) { return NULL; } +#endif -- cgit v0.10.2 From cd52c2a4b5c43631e429d06dce12e08b0cab477f Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 30 Mar 2015 10:59:52 +0100 Subject: clk: add support for clocks provided by SCP(System Control Processor) On some ARM based systems, a separate Cortex-M based System Control Processor(SCP) provides the overall power, clock, reset and system control. System Control and Power Interface(SCPI) Message Protocol is defined for the communication between the Application Cores(AP) and the SCP. This patch adds support for the clocks provided by SCP using SCPI protocol. Signed-off-by: Sudeep Holla Reviewed-by: Stephen Boyd Cc: Mike Turquette Cc: Liviu Dudau Cc: Lorenzo Pieralisi Cc: Jon Medhurst (Tixy) Cc: linux-clk@vger.kernel.org diff --git a/MAINTAINERS b/MAINTAINERS index 9598821..613a116 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9154,6 +9154,7 @@ M: Sudeep Holla L: linux-arm-kernel@lists.infradead.org S: Maintained F: Documentation/devicetree/bindings/arm/arm,scpi.txt +F: drivers/clk/clk-scpi.c F: drivers/firmware/arm_scpi.c F: include/linux/scpi_protocol.h diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 42f7120..4aec54b 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -59,6 +59,16 @@ config COMMON_CLK_RK808 clocked at 32KHz each. Clkout1 is always on, Clkout2 can off by control register. +config COMMON_CLK_SCPI + tristate "Clock driver controlled via SCPI interface" + depends on ARM_SCPI_PROTOCOL || COMPILE_TEST + ---help--- + This driver provides support for clocks that are controlled + by firmware that implements the SCPI interface. + + This driver uses SCPI Message Protocol to interact with the + firmware providing all the clock controls. + config COMMON_CLK_SI5351 tristate "Clock driver for SiLabs 5351A/B/C" depends on I2C diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index d08b3e5..a381431 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_COMMON_CLK_PALMAS) += clk-palmas.o obj-$(CONFIG_CLK_QORIQ) += clk-qoriq.o obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o +obj-$(CONFIG_COMMON_CLK_SCPI) += clk-scpi.o obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o diff --git a/drivers/clk/clk-scpi.c b/drivers/clk/clk-scpi.c new file mode 100644 index 0000000..72f0486 --- /dev/null +++ b/drivers/clk/clk-scpi.c @@ -0,0 +1,312 @@ +/* + * System Control and Power Interface (SCPI) Protocol based clock driver + * + * Copyright (C) 2015 ARM Ltd. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct scpi_clk { + u32 id; + struct clk_hw hw; + struct scpi_dvfs_info *info; + struct scpi_ops *scpi_ops; +}; + +#define to_scpi_clk(clk) container_of(clk, struct scpi_clk, hw) + +static unsigned long scpi_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct scpi_clk *clk = to_scpi_clk(hw); + + return clk->scpi_ops->clk_get_val(clk->id); +} + +static long scpi_clk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + /* + * We can't figure out what rate it will be, so just return the + * rate back to the caller. scpi_clk_recalc_rate() will be called + * after the rate is set and we'll know what rate the clock is + * running at then. + */ + return rate; +} + +static int scpi_clk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct scpi_clk *clk = to_scpi_clk(hw); + + return clk->scpi_ops->clk_set_val(clk->id, rate); +} + +static const struct clk_ops scpi_clk_ops = { + .recalc_rate = scpi_clk_recalc_rate, + .round_rate = scpi_clk_round_rate, + .set_rate = scpi_clk_set_rate, +}; + +/* find closest match to given frequency in OPP table */ +static int __scpi_dvfs_round_rate(struct scpi_clk *clk, unsigned long rate) +{ + int idx; + u32 fmin = 0, fmax = ~0, ftmp; + const struct scpi_opp *opp = clk->info->opps; + + for (idx = 0; idx < clk->info->count; idx++, opp++) { + ftmp = opp->freq; + if (ftmp >= (u32)rate) { + if (ftmp <= fmax) + fmax = ftmp; + break; + } else if (ftmp >= fmin) { + fmin = ftmp; + } + } + return fmax != ~0 ? fmax : fmin; +} + +static unsigned long scpi_dvfs_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct scpi_clk *clk = to_scpi_clk(hw); + int idx = clk->scpi_ops->dvfs_get_idx(clk->id); + const struct scpi_opp *opp; + + if (idx < 0) + return 0; + + opp = clk->info->opps + idx; + return opp->freq; +} + +static long scpi_dvfs_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct scpi_clk *clk = to_scpi_clk(hw); + + return __scpi_dvfs_round_rate(clk, rate); +} + +static int __scpi_find_dvfs_index(struct scpi_clk *clk, unsigned long rate) +{ + int idx, max_opp = clk->info->count; + const struct scpi_opp *opp = clk->info->opps; + + for (idx = 0; idx < max_opp; idx++, opp++) + if (opp->freq == rate) + return idx; + return -EINVAL; +} + +static int scpi_dvfs_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct scpi_clk *clk = to_scpi_clk(hw); + int ret = __scpi_find_dvfs_index(clk, rate); + + if (ret < 0) + return ret; + return clk->scpi_ops->dvfs_set_idx(clk->id, (u8)ret); +} + +static const struct clk_ops scpi_dvfs_ops = { + .recalc_rate = scpi_dvfs_recalc_rate, + .round_rate = scpi_dvfs_round_rate, + .set_rate = scpi_dvfs_set_rate, +}; + +static const struct of_device_id scpi_clk_match[] = { + { .compatible = "arm,scpi-dvfs-clocks", .data = &scpi_dvfs_ops, }, + { .compatible = "arm,scpi-variable-clocks", .data = &scpi_clk_ops, }, + {} +}; + +static struct clk * +scpi_clk_ops_init(struct device *dev, const struct of_device_id *match, + struct scpi_clk *sclk, const char *name) +{ + struct clk_init_data init; + struct clk *clk; + unsigned long min = 0, max = 0; + + init.name = name; + init.flags = CLK_IS_ROOT; + init.num_parents = 0; + init.ops = match->data; + sclk->hw.init = &init; + sclk->scpi_ops = get_scpi_ops(); + + if (init.ops == &scpi_dvfs_ops) { + sclk->info = sclk->scpi_ops->dvfs_get_info(sclk->id); + if (IS_ERR(sclk->info)) + return NULL; + } else if (init.ops == &scpi_clk_ops) { + if (sclk->scpi_ops->clk_get_range(sclk->id, &min, &max) || !max) + return NULL; + } else { + return NULL; + } + + clk = devm_clk_register(dev, &sclk->hw); + if (!IS_ERR(clk) && max) + clk_hw_set_rate_range(&sclk->hw, min, max); + return clk; +} + +struct scpi_clk_data { + struct scpi_clk **clk; + unsigned int clk_num; +}; + +static struct clk * +scpi_of_clk_src_get(struct of_phandle_args *clkspec, void *data) +{ + struct scpi_clk *sclk; + struct scpi_clk_data *clk_data = data; + unsigned int idx = clkspec->args[0], count; + + for (count = 0; count < clk_data->clk_num; count++) { + sclk = clk_data->clk[count]; + if (idx == sclk->id) + return sclk->hw.clk; + } + + return ERR_PTR(-EINVAL); +} + +static int scpi_clk_add(struct device *dev, struct device_node *np, + const struct of_device_id *match) +{ + struct clk **clks; + int idx, count; + struct scpi_clk_data *clk_data; + + count = of_property_count_strings(np, "clock-output-names"); + if (count < 0) { + dev_err(dev, "%s: invalid clock output count\n", np->name); + return -EINVAL; + } + + clk_data = devm_kmalloc(dev, sizeof(*clk_data), GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + + clk_data->clk_num = count; + clk_data->clk = devm_kcalloc(dev, count, sizeof(*clk_data->clk), + GFP_KERNEL); + if (!clk_data->clk) + return -ENOMEM; + + clks = devm_kcalloc(dev, count, sizeof(*clks), GFP_KERNEL); + if (!clks) + return -ENOMEM; + + for (idx = 0; idx < count; idx++) { + struct scpi_clk *sclk; + const char *name; + u32 val; + + sclk = devm_kzalloc(dev, sizeof(*sclk), GFP_KERNEL); + if (!sclk) + return -ENOMEM; + + if (of_property_read_string_index(np, "clock-output-names", + idx, &name)) { + dev_err(dev, "invalid clock name @ %s\n", np->name); + return -EINVAL; + } + + if (of_property_read_u32_index(np, "clock-indices", + idx, &val)) { + dev_err(dev, "invalid clock index @ %s\n", np->name); + return -EINVAL; + } + + sclk->id = val; + + clks[idx] = scpi_clk_ops_init(dev, match, sclk, name); + if (IS_ERR_OR_NULL(clks[idx])) + dev_err(dev, "failed to register clock '%s'\n", name); + else + dev_dbg(dev, "Registered clock '%s'\n", name); + clk_data->clk[idx] = sclk; + } + + return of_clk_add_provider(np, scpi_of_clk_src_get, clk_data); +} + +static int scpi_clocks_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *child, *np = dev->of_node; + + for_each_available_child_of_node(np, child) + of_clk_del_provider(np); + return 0; +} + +static int scpi_clocks_probe(struct platform_device *pdev) +{ + int ret; + struct device *dev = &pdev->dev; + struct device_node *child, *np = dev->of_node; + const struct of_device_id *match; + + if (!get_scpi_ops()) + return -ENXIO; + + for_each_available_child_of_node(np, child) { + match = of_match_node(scpi_clk_match, child); + if (!match) + continue; + ret = scpi_clk_add(dev, child, match); + if (ret) { + scpi_clocks_remove(pdev); + return ret; + } + } + return 0; +} + +static const struct of_device_id scpi_clocks_ids[] = { + { .compatible = "arm,scpi-clocks", }, + {} +}; +MODULE_DEVICE_TABLE(of, scpi_clocks_ids); + +static struct platform_driver scpi_clocks_driver = { + .driver = { + .name = "scpi_clocks", + .of_match_table = scpi_clocks_ids, + }, + .probe = scpi_clocks_probe, + .remove = scpi_clocks_remove, +}; +module_platform_driver(scpi_clocks_driver); + +MODULE_AUTHOR("Sudeep Holla "); +MODULE_DESCRIPTION("ARM SCPI clock driver"); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 9490f01e247169a93262054074409ad73d71c4da Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 30 Mar 2015 10:59:52 +0100 Subject: clk: scpi: add support for cpufreq virtual device The clocks for the CPUs are provided by SCP and are managed by this clock driver. So the cpufreq device needs to be added only after the clock get registered and removed when this driver is unloaded. This patch manages the cpufreq virtual device based on the clock availability. Signed-off-by: Sudeep Holla Acked-by: Stephen Boyd Cc: Mike Turquette Cc: Liviu Dudau Cc: Lorenzo Pieralisi Cc: Jon Medhurst (Tixy) Cc: linux-clk@vger.kernel.org diff --git a/drivers/clk/clk-scpi.c b/drivers/clk/clk-scpi.c index 72f0486..0b501a9 100644 --- a/drivers/clk/clk-scpi.c +++ b/drivers/clk/clk-scpi.c @@ -34,6 +34,8 @@ struct scpi_clk { #define to_scpi_clk(clk) container_of(clk, struct scpi_clk, hw) +static struct platform_device *cpufreq_dev; + static unsigned long scpi_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { @@ -263,6 +265,11 @@ static int scpi_clocks_remove(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *child, *np = dev->of_node; + if (cpufreq_dev) { + platform_device_unregister(cpufreq_dev); + cpufreq_dev = NULL; + } + for_each_available_child_of_node(np, child) of_clk_del_provider(np); return 0; @@ -288,6 +295,12 @@ static int scpi_clocks_probe(struct platform_device *pdev) return ret; } } + /* Add the virtual cpufreq device */ + cpufreq_dev = platform_device_register_simple("scpi-cpufreq", + -1, NULL, 0); + if (!cpufreq_dev) + pr_warn("unable to register cpufreq device"); + return 0; } -- cgit v0.10.2 From 8def31034d033961a4e1f34a80f317fd7002faee Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 30 Mar 2015 10:59:52 +0100 Subject: cpufreq: arm_big_little: add SCPI interface driver On some ARM based systems, a separate Cortex-M based System Control Processor(SCP) provides the overall power, clock, reset and system control including CPU DVFS. SCPI Message Protocol is used to communicate with the SCPI. This patch adds a interface driver for adding OPPs and registering the arm_big_little cpufreq driver for such systems. Signed-off-by: Sudeep Holla Acked-by: Viresh Kumar Cc: "Rafael J. Wysocki" Cc: linux-pm@vger.kernel.org diff --git a/MAINTAINERS b/MAINTAINERS index 613a116..e39ae88 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9155,6 +9155,7 @@ L: linux-arm-kernel@lists.infradead.org S: Maintained F: Documentation/devicetree/bindings/arm/arm,scpi.txt F: drivers/clk/clk-scpi.c +F: drivers/cpufreq/scpi-cpufreq.c F: drivers/firmware/arm_scpi.c F: include/linux/scpi_protocol.h diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index cd0391e..c737f73 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -199,6 +199,16 @@ config ARM_SA1100_CPUFREQ config ARM_SA1110_CPUFREQ bool +config ARM_SCPI_CPUFREQ + tristate "SCPI based CPUfreq driver" + depends on ARM_BIG_LITTLE_CPUFREQ && ARM_SCPI_PROTOCOL + help + This adds the CPUfreq driver support for ARM big.LITTLE platforms + using SCPI protocol for CPU power management. + + This driver uses SCPI Message Protocol driver to interact with the + firmware providing the CPU DVFS functionality. + config ARM_SPEAR_CPUFREQ bool "SPEAr CPUFreq support" depends on PLAT_SPEAR diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 4134038..ccfaa4c 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -72,6 +72,7 @@ obj-$(CONFIG_ARM_S3C64XX_CPUFREQ) += s3c64xx-cpufreq.o obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o +obj-$(CONFIG_ARM_SCPI_CPUFREQ) += scpi-cpufreq.o obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o obj-$(CONFIG_ARM_TEGRA20_CPUFREQ) += tegra20-cpufreq.o obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c new file mode 100644 index 0000000..2c3b16f --- /dev/null +++ b/drivers/cpufreq/scpi-cpufreq.c @@ -0,0 +1,124 @@ +/* + * System Control and Power Interface (SCPI) based CPUFreq Interface driver + * + * It provides necessary ops to arm_big_little cpufreq driver. + * + * Copyright (C) 2015 ARM Ltd. + * Sudeep Holla + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include + +#include "arm_big_little.h" + +static struct scpi_ops *scpi_ops; + +static struct scpi_dvfs_info *scpi_get_dvfs_info(struct device *cpu_dev) +{ + u8 domain = topology_physical_package_id(cpu_dev->id); + + if (domain < 0) + return ERR_PTR(-EINVAL); + return scpi_ops->dvfs_get_info(domain); +} + +static int scpi_opp_table_ops(struct device *cpu_dev, bool remove) +{ + int idx, ret = 0; + struct scpi_opp *opp; + struct scpi_dvfs_info *info = scpi_get_dvfs_info(cpu_dev); + + if (IS_ERR(info)) + return PTR_ERR(info); + + if (!info->opps) + return -EIO; + + for (opp = info->opps, idx = 0; idx < info->count; idx++, opp++) { + if (remove) + dev_pm_opp_remove(cpu_dev, opp->freq); + else + ret = dev_pm_opp_add(cpu_dev, opp->freq, + opp->m_volt * 1000); + if (ret) { + dev_warn(cpu_dev, "failed to add opp %uHz %umV\n", + opp->freq, opp->m_volt); + while (idx-- > 0) + dev_pm_opp_remove(cpu_dev, (--opp)->freq); + return ret; + } + } + return ret; +} + +static int scpi_get_transition_latency(struct device *cpu_dev) +{ + struct scpi_dvfs_info *info = scpi_get_dvfs_info(cpu_dev); + + if (IS_ERR(info)) + return PTR_ERR(info); + return info->latency; +} + +static int scpi_init_opp_table(struct device *cpu_dev) +{ + return scpi_opp_table_ops(cpu_dev, false); +} + +static void scpi_free_opp_table(struct device *cpu_dev) +{ + scpi_opp_table_ops(cpu_dev, true); +} + +static struct cpufreq_arm_bL_ops scpi_cpufreq_ops = { + .name = "scpi", + .get_transition_latency = scpi_get_transition_latency, + .init_opp_table = scpi_init_opp_table, + .free_opp_table = scpi_free_opp_table, +}; + +static int scpi_cpufreq_probe(struct platform_device *pdev) +{ + scpi_ops = get_scpi_ops(); + if (!scpi_ops) + return -EIO; + + return bL_cpufreq_register(&scpi_cpufreq_ops); +} + +static int scpi_cpufreq_remove(struct platform_device *pdev) +{ + bL_cpufreq_unregister(&scpi_cpufreq_ops); + scpi_ops = NULL; + return 0; +} + +static struct platform_driver scpi_cpufreq_platdrv = { + .driver = { + .name = "scpi-cpufreq", + .owner = THIS_MODULE, + }, + .probe = scpi_cpufreq_probe, + .remove = scpi_cpufreq_remove, +}; +module_platform_driver(scpi_cpufreq_platdrv); + +MODULE_AUTHOR("Sudeep Holla "); +MODULE_DESCRIPTION("ARM SCPI CPUFreq interface driver"); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 470a55358186d0bb93558a87d13159dfbc989351 Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Tue, 22 Sep 2015 23:18:10 +0300 Subject: IB/core: Add support of checksum capability reporting for RC and RAW Two enum members IB_DEVICE_RC_IP_CSUM and IB_DEVICE_RAW_IP_CSUM are added to ib_device_cap_flags. Device should set these two flags if they support insertion of UDP and TCP checksum on outgoing IPv4 messages and can verify the validity of checksum for incoming IPv4 messages, for RC IPoIB and RAW over Ethernet respectively. They are similar to IB_DEVICE_UD_IP_CSUM. Signed-off-by: Bodong Wang Signed-off-by: Doug Ledford diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 7845fae..e1f65e2 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -137,6 +137,8 @@ enum ib_device_cap_flags { IB_DEVICE_BLOCK_MULTICAST_LOOPBACK = (1<<22), IB_DEVICE_MEM_WINDOW_TYPE_2A = (1<<23), IB_DEVICE_MEM_WINDOW_TYPE_2B = (1<<24), + IB_DEVICE_RC_IP_CSUM = (1<<25), + IB_DEVICE_RAW_IP_CSUM = (1<<26), IB_DEVICE_MANAGED_FLOW_STEERING = (1<<29), IB_DEVICE_SIGNATURE_HANDOVER = (1<<30), IB_DEVICE_ON_DEMAND_PAGING = (1<<31), @@ -873,7 +875,6 @@ enum ib_qp_create_flags { IB_QP_CREATE_RESERVED_END = 1 << 31, }; - /* * Note: users may not call ib_close_qp or ib_destroy_qp from the event_handler * callback to destroy the passed in QP. -- cgit v0.10.2 From 070b399723206a4ed80410358f801a7df68d08e6 Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Tue, 22 Sep 2015 23:18:11 +0300 Subject: IB/mlx4: Report checksum offload cap for RAW QP when query device Signed-off-by: Bodong Wang Signed-off-by: Doug Ledford diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index efecdf0..38be8dc 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -442,6 +442,8 @@ static int mlx4_ib_query_device(struct ib_device *ibdev, props->device_cap_flags |= IB_DEVICE_MANAGED_FLOW_STEERING; } + props->device_cap_flags |= IB_DEVICE_RAW_IP_CSUM; + props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) & 0xffffff; props->vendor_part_id = dev->dev->persist->pdev->device; -- cgit v0.10.2 From 6716f6c6b8ae69e2abbea5e9c0c3c274be57d927 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Fri, 25 Sep 2015 20:35:32 +0300 Subject: ARM: dts: Fix cpu compatible value for s3c2416 The change corrects cpu compatible property to a defined one, see Documentation/devicetree/bindings/arm/cpus.txt Signed-off-by: Vladimir Zapolskiy Cc: Kukjin Kim Cc: Krzysztof Kozlowski Signed-off-by: Krzysztof Kozlowski diff --git a/arch/arm/boot/dts/s3c2416.dtsi b/arch/arm/boot/dts/s3c2416.dtsi index a5184ff..80f0075 100644 --- a/arch/arm/boot/dts/s3c2416.dtsi +++ b/arch/arm/boot/dts/s3c2416.dtsi @@ -25,7 +25,7 @@ #size-cells = <0>; cpu { - compatible = "arm,arm926ejs"; + compatible = "arm,arm926ej-s"; }; }; -- cgit v0.10.2 From 4e33714eb46dfdb275893a4999b73f9b94e999f2 Mon Sep 17 00:00:00 2001 From: Tobias Jakobi Date: Mon, 21 Sep 2015 19:58:59 +0200 Subject: ARM: dts: Remove redundant pinctrl settings in exynos4412-odroid The pinctrl settings in i2c_0 and i2c_1 are already provided through the exynos4 dtsi. Signed-off-by: Tobias Jakobi Reviewed-by: Javier Martinez Canillas Signed-off-by: Krzysztof Kozlowski diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi index db52841..10b5a72 100644 --- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi @@ -199,8 +199,6 @@ }; &i2c_0 { - pinctrl-0 = <&i2c0_bus>; - pinctrl-names = "default"; samsung,i2c-sda-delay = <100>; samsung,i2c-max-bus-freq = <400000>; status = "okay"; @@ -424,8 +422,6 @@ }; &i2c_1 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_bus>; status = "okay"; max98090: max98090@10 { compatible = "maxim,max98090"; @@ -440,8 +436,6 @@ &i2c_2 { status = "okay"; - pinctrl-names = "default"; - pinctrl-0 = <&i2c2_bus>; }; &i2c_8 { -- cgit v0.10.2 From 00e5e8c47b6fb2da314b0221477b2b84bea0e224 Mon Sep 17 00:00:00 2001 From: Tobias Jakobi Date: Mon, 21 Sep 2015 19:59:00 +0200 Subject: ARM: dts: Unify voltage regulator style in exynos4412-odroid Use 'ldoN_reg: LDON' syntax and drop the deprecated 'regulator-compatible' property. Signed-off-by: Tobias Jakobi Reviewed-by: Javier Martinez Canillas Signed-off-by: Krzysztof Kozlowski diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi index 10b5a72..c3e978d 100644 --- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi @@ -274,15 +274,13 @@ regulator-always-on; }; - ldo8_reg: ldo@8 { - regulator-compatible = "LDO8"; + ldo8_reg: LDO8 { regulator-name = "VDD10_HDMI_1.0V"; regulator-min-microvolt = <1000000>; regulator-max-microvolt = <1000000>; }; - ldo10_reg: ldo@10 { - regulator-compatible = "LDO10"; + ldo10_reg: LDO10 { regulator-name = "VDDQ_MIPIHSI_1.8V"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; -- cgit v0.10.2 From 5b3abbee42562a7bcdc6b589a3d8f9b5752550ed Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 22 Sep 2015 15:36:00 +0200 Subject: ARM: dts: axp209: Add usb_power_supply child node to the ax209 node Add a node representing the usb power supply part of the axp209 pmic, note that the usb power supply and the (to be added later) ac power supply will each have their own child-node, so that they can be separately specified as power-supply for other nodes using a power-supply property with a phandle pointing to the right axp209 child-node. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/axp209.dtsi b/arch/arm/boot/dts/axp209.dtsi index 24c935c..051ab3b 100644 --- a/arch/arm/boot/dts/axp209.dtsi +++ b/arch/arm/boot/dts/axp209.dtsi @@ -89,4 +89,9 @@ regulator-name = "ldo5"; }; }; + + usb_power_supply: usb_power_supply { + compatible = "x-powers,axp202-usb-power-supply"; + status = "disabled"; + }; }; -- cgit v0.10.2 From 3ff427f02dc055fdede6051ba32efbd73f4b1f31 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 22 Sep 2015 15:36:02 +0200 Subject: ARM: dts: sun7i: Enable USB DRC on orangepi-mini Enable the otg/drc usb controller on the orangepi-mini. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts b/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts index 73cd81ee..4f65664 100644 --- a/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts +++ b/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts @@ -156,7 +156,18 @@ status = "okay"; }; +&otg_sram { + status = "okay"; +}; + &pio { + usb0_id_detect_pin: usb0_id_detect_pin@0 { + allwinner,pins = "PH4"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + mmc0_cd_pin_orangepi: mmc0_cd_pin@0 { allwinner,pins = "PH10"; allwinner,function = "gpio_in"; @@ -225,6 +236,10 @@ regulator-name = "avcc"; }; +®_usb0_vbus { + status = "okay"; +}; + ®_usb1_vbus { pinctrl-0 = <&usb1_vbus_pin_bananapro>; gpio = <&pio 7 26 GPIO_ACTIVE_HIGH>; /* PH26 */ @@ -243,7 +258,21 @@ status = "okay"; }; +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + +&usb_power_supply { + status = "okay"; +}; + &usbphy { + pinctrl-names = "default"; + pinctrl-0 = <&usb0_id_detect_pin>; + usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */ + usb0_vbus_power-supply = <&usb_power_supply>; + usb0_vbus-supply = <®_usb0_vbus>; usb1_vbus-supply = <®_usb1_vbus>; usb2_vbus-supply = <®_usb2_vbus>; status = "okay"; -- cgit v0.10.2 From 9324ef4b14fe4d16a0f9900bd46f26f0ad44ed91 Mon Sep 17 00:00:00 2001 From: Reinder de Haan Date: Tue, 22 Sep 2015 15:36:03 +0200 Subject: ARM: dts: sun7i: Enable USB DRC on the Orange pi Add usb otg support for Orange pi, based on Orange pi mini. Signed-off-by: Reinder de Haan Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun7i-a20-orangepi.dts b/arch/arm/boot/dts/sun7i-a20-orangepi.dts index 55a06ce..71125bf 100644 --- a/arch/arm/boot/dts/sun7i-a20-orangepi.dts +++ b/arch/arm/boot/dts/sun7i-a20-orangepi.dts @@ -141,7 +141,18 @@ status = "okay"; }; +&otg_sram { + status = "okay"; +}; + &pio { + usb0_id_detect_pin: usb0_id_detect_pin@0 { + allwinner,pins = "PH4"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + mmc0_cd_pin_orangepi: mmc0_cd_pin@0 { allwinner,pins = "PH10"; allwinner,function = "gpio_in"; @@ -203,6 +214,10 @@ regulator-name = "avcc"; }; +®_usb0_vbus { + status = "okay"; +}; + ®_usb1_vbus { pinctrl-0 = <&usb1_vbus_pin_bananapro>; gpio = <&pio 7 26 GPIO_ACTIVE_HIGH>; /* PH26 */ @@ -221,7 +236,21 @@ status = "okay"; }; +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + +&usb_power_supply { + status = "okay"; +}; + &usbphy { + pinctrl-names = "default"; + pinctrl-0 = <&usb0_id_detect_pin>; + usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */ + usb0_vbus_power-supply = <&usb_power_supply>; + usb0_vbus-supply = <®_usb0_vbus>; usb1_vbus-supply = <®_usb1_vbus>; usb2_vbus-supply = <®_usb2_vbus>; status = "okay"; -- cgit v0.10.2 From 47038677e52344135731ea0180bdd981a8ae4fae Mon Sep 17 00:00:00 2001 From: Aleksei Mamlin Date: Tue, 22 Sep 2015 15:36:04 +0200 Subject: ARM: dts: sun7i: Enable USB DRC on Wexler TAB7200 Enable the otg/drc usb controller on the Wexler TAB7200 tablet. Signed-off-by: Aleksei Mamlin Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun7i-a20-wexler-tab7200.dts b/arch/arm/boot/dts/sun7i-a20-wexler-tab7200.dts index 83c6d3f..78239ad 100644 --- a/arch/arm/boot/dts/sun7i-a20-wexler-tab7200.dts +++ b/arch/arm/boot/dts/sun7i-a20-wexler-tab7200.dts @@ -86,6 +86,8 @@ }; }; +#include "axp209.dtsi" + &i2c1 { pinctrl-names = "default"; pinctrl-0 = <&i2c1_pins_a>; @@ -135,7 +137,18 @@ status = "okay"; }; -#include "axp209.dtsi" +&otg_sram { + status = "okay"; +}; + +&pio { + usb0_id_detect_pin: usb0_id_detect_pin@0 { + allwinner,pins = "PH4"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; ®_dcdc2 { regulator-always-on; @@ -162,6 +175,10 @@ regulator-name = "avcc"; }; +®_usb0_vbus { + status = "okay"; +}; + ®_usb1_vbus { status = "okay"; }; @@ -176,7 +193,21 @@ status = "okay"; }; +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + +&usb_power_supply { + status = "okay"; +}; + &usbphy { + pinctrl-names = "default"; + pinctrl-0 = <&usb0_id_detect_pin>; + usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */ + usb0_vbus_power-supply = <&usb_power_supply>; + usb0_vbus-supply = <®_usb0_vbus>; usb1_vbus-supply = <®_usb1_vbus>; usb2_vbus-supply = <®_usb2_vbus>; status = "okay"; -- cgit v0.10.2 From b5cf0022450d2068e56b60cbbd0b5ff1430b7656 Mon Sep 17 00:00:00 2001 From: Jelle de Jong Date: Tue, 22 Sep 2015 15:36:05 +0200 Subject: ARM: dts: sun7i: Add dts file for Wits Pro A20 DKT The Wits Pro A20 DKT is an A20 Development KiT with 1G RAM, 4G NAND, sdio wifi, 1Gbit ethernet, 1024x768 lcd screen with ft5x_ts touchscreen and a ton of IO connectors. Note there seem to be multiple sdcard slots on the board (4 in total), but other then mmc0 none of these are hooked up by default, there is a ton of dip-switches which likely allow hooking some of these up, but the documentation of the board only describes the use of a fraction of them, so for now we only support mmc0. Signed-off-by: Jelle de Jong [hdegoede@redhat.com: Use pwrseq instead of a regulator for the wifi-en pin] [hdegoede@redhat.com: Add support for OOB irq for the sdio wifi] Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 75d8092..c7adaa8 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -626,7 +626,8 @@ dtb-$(CONFIG_MACH_SUN7I) += \ sun7i-a20-orangepi-mini.dtb \ sun7i-a20-pcduino3.dtb \ sun7i-a20-pcduino3-nano.dtb \ - sun7i-a20-wexler-tab7200.dtb + sun7i-a20-wexler-tab7200.dtb \ + sun7i-a20-wits-pro-a20-dkt.dtb dtb-$(CONFIG_MACH_SUN8I) += \ sun8i-a23-evb.dtb \ sun8i-a23-gt90h-v4.dtb \ diff --git a/arch/arm/boot/dts/sun7i-a20-wits-pro-a20-dkt.dts b/arch/arm/boot/dts/sun7i-a20-wits-pro-a20-dkt.dts new file mode 100644 index 0000000..85b500d --- /dev/null +++ b/arch/arm/boot/dts/sun7i-a20-wits-pro-a20-dkt.dts @@ -0,0 +1,226 @@ +/* + * Copyright 2015 Jelle de Jong + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun7i-a20.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include +#include +#include + +/ { + model = "Wits Pro A20 DKT"; + compatible = "wits,pro-a20-dkt", "allwinner,sun7i-a20"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + mmc3_pwrseq: mmc3_pwrseq { + compatible = "mmc-pwrseq-simple"; + pinctrl-names = "default"; + pinctrl-0 = <&vmmc3_pin_ap6xxx_wl_regon>; + reset-gpios = <&pio 7 9 GPIO_ACTIVE_LOW>; /* PH9 WIFI_EN */ + }; +}; + +&cpu0 { + cpu-supply = <®_dcdc2>; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; +}; + +#include "axp209.dtsi" + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; + +&mmc3 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc3_pins_a>; + vmmc-supply = <®_vcc3v3>; + mmc-pwrseq = <&mmc3_pwrseq>; + bus-width = <4>; + non-removable; + status = "okay"; + + brcmf: bcrmf@1 { + reg = <1>; + compatible = "brcm,bcm4329-fmac"; + interrupt-parent = <&pio>; + interrupts = <7 10 IRQ_TYPE_LEVEL_LOW>; /* PH10 / EINT10 */ + interrupt-names = "host-wake"; + }; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&otg_sram { + status = "okay"; +}; + +&pio { + vmmc3_pin_ap6xxx_wl_regon: vmmc3_pin@0 { + allwinner,pins = "PH9"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb0_id_detect_pin: usb0_id_detect_pin@0 { + allwinner,pins = "PH4"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_dcdc2 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1450000>; + regulator-name = "vdd-cpu"; +}; + +®_dcdc3 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-int-dll"; +}; + +®_ldo1 { + regulator-name = "vdd-rtc"; +}; + +®_ldo2 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "avcc"; +}; + +®_usb0_vbus { + status = "okay"; +}; + +®_usb1_vbus { + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + +&usb_power_supply { + status = "okay"; +}; + +&usbphy { + pinctrl-names = "default"; + pinctrl-0 = <&usb0_id_detect_pin>; + usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */ + usb0_vbus_power-supply = <&usb_power_supply>; + usb0_vbus-supply = <®_usb0_vbus>; + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; -- cgit v0.10.2 From 0220531a13b83d0049dcf1391a5a0cb10346962f Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 13 Sep 2015 14:15:01 +0200 Subject: pktcdvd: drop null test before destroy functions Remove unneeded NULL test. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ expression x; @@ -if (x != NULL) \(kmem_cache_destroy\|mempool_destroy\|dma_pool_destroy\)(x); // Signed-off-by: Julia Lawall Signed-off-by: Jiri Kosina diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 4c20c22..49375a4 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -2822,8 +2822,7 @@ out_new_dev: out_mem2: put_disk(disk); out_mem: - if (pd->rb_pool) - mempool_destroy(pd->rb_pool); + mempool_destroy(pd->rb_pool); kfree(pd); out_mutex: mutex_unlock(&ctl_mutex); -- cgit v0.10.2 From 061eebba3d3077186609da7d8029e0fd89f194e7 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 10 Aug 2015 12:02:09 +0100 Subject: UBI: Update comments to reflect UBI_METAONLY flag This patch trivially updates code comments to reflect the addition of the UBI_METAONLY flag - as discussed https://lkml.org/lkml/2014/10/29/764 Cc: Richard Weinberger Cc: trivial@kernel.org Signed-off-by: Andrew Murray Signed-off-by: Jiri Kosina diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c index b93807b..cb7c075 100644 --- a/drivers/mtd/ubi/gluebi.c +++ b/drivers/mtd/ubi/gluebi.c @@ -112,8 +112,8 @@ static int gluebi_get_device(struct mtd_info *mtd) * The MTD device is already referenced and this is just one * more reference. MTD allows many users to open the same * volume simultaneously and do not distinguish between - * readers/writers/exclusive openers as UBI does. So we do not - * open the UBI volume again - just increase the reference + * readers/writers/exclusive/meta openers as UBI does. So we do + * not open the UBI volume again - just increase the reference * counter and return. */ gluebi->refcnt += 1; -- cgit v0.10.2 From d9902d597ac54c8abc02e37492e2bc102f31e83f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 12 Aug 2015 15:59:41 +0530 Subject: drivers: misc: Drop unlikely before IS_ERR(_OR_NULL) IS_ERR(_OR_NULL) already contain an 'unlikely' compiler flag and there is no need to do that again from its callers. Drop it. Signed-off-by: Viresh Kumar Signed-off-by: Jiri Kosina diff --git a/drivers/misc/c2port/core.c b/drivers/misc/c2port/core.c index 464419b..cc8645b 100644 --- a/drivers/misc/c2port/core.c +++ b/drivers/misc/c2port/core.c @@ -926,7 +926,7 @@ struct c2port_device *c2port_device_register(char *name, c2dev->dev = device_create(c2port_class, NULL, 0, c2dev, "c2port%d", c2dev->id); - if (unlikely(IS_ERR(c2dev->dev))) { + if (IS_ERR(c2dev->dev)) { ret = PTR_ERR(c2dev->dev); goto error_device_create; } -- cgit v0.10.2 From bf69a3b60e4d892f8c1d7a6b18cf84aaa7acd43f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 12 Aug 2015 15:59:42 +0530 Subject: drivers: net: Drop unlikely before IS_ERR(_OR_NULL) IS_ERR(_OR_NULL) already contain an 'unlikely' compiler flag and there is no need to do that again from its callers. Drop it. Acked-by: Murali Karicheri Signed-off-by: Viresh Kumar Signed-off-by: Jiri Kosina diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c index 9749dfd..734a6c4 100644 --- a/drivers/net/ethernet/ti/netcp_core.c +++ b/drivers/net/ethernet/ti/netcp_core.c @@ -1016,7 +1016,7 @@ netcp_tx_map_skb(struct sk_buff *skb, struct netcp_intf *netcp) } desc = knav_pool_desc_get(netcp->tx_pool); - if (unlikely(IS_ERR_OR_NULL(desc))) { + if (IS_ERR_OR_NULL(desc)) { dev_err(netcp->ndev_dev, "out of TX desc\n"); dma_unmap_single(dev, dma_addr, pkt_len, DMA_TO_DEVICE); return NULL; @@ -1049,7 +1049,7 @@ netcp_tx_map_skb(struct sk_buff *skb, struct netcp_intf *netcp) } ndesc = knav_pool_desc_get(netcp->tx_pool); - if (unlikely(IS_ERR_OR_NULL(ndesc))) { + if (IS_ERR_OR_NULL(ndesc)) { dev_err(netcp->ndev_dev, "out of TX desc for frags\n"); dma_unmap_page(dev, dma_addr, buf_len, DMA_TO_DEVICE); goto free_descs; -- cgit v0.10.2 From a1c83681d52704c766d576bea2d7f2f99e8dde23 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 12 Aug 2015 15:59:44 +0530 Subject: fs: Drop unlikely before IS_ERR(_OR_NULL) IS_ERR(_OR_NULL) already contain an 'unlikely' compiler flag and there is no need to do that again from its callers. Drop it. Signed-off-by: Viresh Kumar Reviewed-by: Jeff Layton Reviewed-by: David Howells Reviewed-by: Steve French Signed-off-by: Jiri Kosina diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index b1eede3..0557c45 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -84,7 +84,7 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name, cifs_dbg(FYI, "%s: for %s\n", __func__, name->name); dentry = d_hash_and_lookup(parent, name); - if (unlikely(IS_ERR(dentry))) + if (IS_ERR(dentry)) return; if (dentry) { diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 3c4db11..e2e47ba 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -270,7 +270,7 @@ ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry, ecryptfs_inode = ecryptfs_do_create(directory_inode, ecryptfs_dentry, mode); - if (unlikely(IS_ERR(ecryptfs_inode))) { + if (IS_ERR(ecryptfs_inode)) { ecryptfs_printk(KERN_WARNING, "Failed to create file in" "lower filesystem\n"); rc = PTR_ERR(ecryptfs_inode); diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 2553aa8..799f017 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -899,7 +899,7 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block, bh = read_extent_tree_block(inode, path[ppos].p_block, --i, flags); - if (unlikely(IS_ERR(bh))) { + if (IS_ERR(bh)) { ret = PTR_ERR(bh); goto err; } @@ -5792,7 +5792,7 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1, int split = 0; path1 = ext4_find_extent(inode1, lblk1, NULL, EXT4_EX_NOCACHE); - if (unlikely(IS_ERR(path1))) { + if (IS_ERR(path1)) { *erp = PTR_ERR(path1); path1 = NULL; finish: @@ -5800,7 +5800,7 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1, goto repeat; } path2 = ext4_find_extent(inode2, lblk2, NULL, EXT4_EX_NOCACHE); - if (unlikely(IS_ERR(path2))) { + if (IS_ERR(path2)) { *erp = PTR_ERR(path2); path2 = NULL; goto finish; diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 011dcfb..0554e4b 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1429,7 +1429,7 @@ restart: } num++; bh = ext4_getblk(NULL, dir, b++, 0); - if (unlikely(IS_ERR(bh))) { + if (IS_ERR(bh)) { if (ra_max == 0) { ret = bh; goto cleanup_and_exit; diff --git a/fs/namei.c b/fs/namei.c index fbbcf09..d3f8406 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1942,7 +1942,7 @@ OK: if (err) { const char *s = get_link(nd); - if (unlikely(IS_ERR(s))) + if (IS_ERR(s)) return PTR_ERR(s); err = 0; if (unlikely(!s)) { @@ -3356,7 +3356,7 @@ struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt, return ERR_PTR(-ELOOP); filename = getname_kernel(name); - if (unlikely(IS_ERR(filename))) + if (IS_ERR(filename)) return ERR_CAST(filename); set_nameidata(&nd, -1, filename); diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index 93575e9..356816e 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c @@ -597,7 +597,7 @@ ncp_fill_cache(struct file *file, struct dir_context *ctx, qname.name = __name; newdent = d_hash_and_lookup(dentry, &qname); - if (unlikely(IS_ERR(newdent))) + if (IS_ERR(newdent)) goto end_advance; if (!newdent) { newdent = d_alloc(dentry, &qname); diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index 5aaed36..5c0c6b5 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c @@ -124,7 +124,7 @@ objio_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev, retry_lookup: od = osduld_info_lookup(&odi); - if (unlikely(IS_ERR(od))) { + if (IS_ERR(od)) { err = PTR_ERR(od); dprintk("%s: osduld_info_lookup => %d\n", __func__, err); if (err == -ENODEV && retry_flag) { diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index fdda62e..fe5b6e6 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -948,7 +948,7 @@ static struct ctl_dir *get_subdir(struct ctl_dir *dir, found: subdir->header.nreg++; failed: - if (unlikely(IS_ERR(subdir))) { + if (IS_ERR(subdir)) { pr_err("sysctl could not get directory: "); sysctl_print_dir(dir); pr_cont("/%*.*s %ld\n", -- cgit v0.10.2 From 18e8e5c7a9f9aef1b45e0729dc340989d5a954d0 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 12 Aug 2015 15:59:46 +0530 Subject: mm: Drop unlikely before IS_ERR(_OR_NULL) IS_ERR(_OR_NULL) already contain an 'unlikely' compiler flag and there is no need to do that again from its callers. Drop it. Acked-by: Kirill A. Shutemov Signed-off-by: Viresh Kumar Signed-off-by: Jiri Kosina diff --git a/mm/huge_memory.c b/mm/huge_memory.c index c107094..e146524 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -149,7 +149,7 @@ static int start_stop_khugepaged(void) if (!khugepaged_thread) khugepaged_thread = kthread_run(khugepaged, NULL, "khugepaged"); - if (unlikely(IS_ERR(khugepaged_thread))) { + if (IS_ERR(khugepaged_thread)) { pr_err("khugepaged: kthread_run(khugepaged) failed\n"); err = PTR_ERR(khugepaged_thread); khugepaged_thread = NULL; -- cgit v0.10.2 From b5ffe634425591db5692fa242da0bbe20d1f76a7 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 12 Aug 2015 15:59:47 +0530 Subject: net: Drop unlikely before IS_ERR(_OR_NULL) IS_ERR(_OR_NULL) already contain an 'unlikely' compiler flag and there is no need to do that again from its callers. Drop it. Acked-by: Neil Horman Signed-off-by: Viresh Kumar Signed-off-by: Jiri Kosina diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index ff8c4a4..01d6968 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -1143,7 +1143,7 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info) info, OVS_FLOW_CMD_NEW, false, ufid_flags); - if (unlikely(IS_ERR(reply))) { + if (IS_ERR(reply)) { error = PTR_ERR(reply); goto err_unlock_ovs; } diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 17bef01..897c01c 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -4475,7 +4475,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval } newfile = sock_alloc_file(newsock, 0, NULL); - if (unlikely(IS_ERR(newfile))) { + if (IS_ERR(newfile)) { put_unused_fd(retval); sock_release(newsock); return PTR_ERR(newfile); diff --git a/net/socket.c b/net/socket.c index 9963a0b..dd2c247 100644 --- a/net/socket.c +++ b/net/socket.c @@ -373,7 +373,7 @@ struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname) file = alloc_file(&path, FMODE_READ | FMODE_WRITE, &socket_file_ops); - if (unlikely(IS_ERR(file))) { + if (IS_ERR(file)) { /* drop dentry, keep inode */ ihold(d_inode(path.dentry)); path_put(&path); @@ -1303,7 +1303,7 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol, } newfile1 = sock_alloc_file(sock1, flags, NULL); - if (unlikely(IS_ERR(newfile1))) { + if (IS_ERR(newfile1)) { err = PTR_ERR(newfile1); goto out_put_unused_both; } @@ -1467,7 +1467,7 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, goto out_put; } newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name); - if (unlikely(IS_ERR(newfile))) { + if (IS_ERR(newfile)) { err = PTR_ERR(newfile); put_unused_fd(newfd); sock_release(newsock); -- cgit v0.10.2 From 636db7a96cbd95f7842246a3f5f842ba791cd393 Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Fri, 4 Sep 2015 01:54:22 +0200 Subject: debugfs: document that debugfs_remove*() accepts NULL and error values According to commit a59d6293e537 ("debugfs: change parameter check in debugfs_remove() functions"), this is meant to make cleanup easier for callers. In that case it ought to be documented. Signed-off-by: Ulf Magnusson Signed-off-by: Jiri Kosina diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index c711be8..5d8f35f 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -533,7 +533,8 @@ static int __debugfs_remove(struct dentry *dentry, struct dentry *parent) /** * debugfs_remove - removes a file or directory from the debugfs filesystem * @dentry: a pointer to a the dentry of the file or directory to be - * removed. + * removed. If this parameter is NULL or an error value, nothing + * will be done. * * This function removes a file or directory in debugfs that was previously * created with a call to another debugfs function (like @@ -565,7 +566,8 @@ EXPORT_SYMBOL_GPL(debugfs_remove); /** * debugfs_remove_recursive - recursively removes a directory - * @dentry: a pointer to a the dentry of the directory to be removed. + * @dentry: a pointer to a the dentry of the directory to be removed. If this + * parameter is NULL or an error value, nothing will be done. * * This function recursively removes a directory tree in debugfs that * was previously created with a call to another debugfs function -- cgit v0.10.2 From 1207775428d57508fd1b4c9403833463a6b632c2 Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Fri, 4 Sep 2015 20:49:14 +0200 Subject: class_find_device: fix reference to argument "match" There is no argument "fn". Signed-off-by: Rolf Eike Beer Signed-off-by: Jiri Kosina diff --git a/drivers/base/class.c b/drivers/base/class.c index 6e81088..71059e3 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -406,7 +406,7 @@ EXPORT_SYMBOL_GPL(class_for_each_device); * * Note, you will need to drop the reference with put_device() after use. * - * @fn is allowed to do anything including calling back into class + * @match is allowed to do anything including calling back into class * code. There's no locking restriction. */ struct device *class_find_device(struct class *class, struct device *start, -- cgit v0.10.2 From 0dec1474ab27f308c0d6ef542ef36100712dc81b Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Fri, 4 Sep 2015 20:52:45 +0200 Subject: Kconfig: remove comment about scsi_wait_scan module This module has been removed in commit 6072609d9bb91ff54aee3ef29304bd5b4fc88aae ([SCSI] Remove scsi_wait_scan module), so this module is gone since 3.6. Signed-off-by: Rolf Eike Beer Signed-off-by: Jiri Kosina diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 456e1567..ade5715 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -242,13 +242,6 @@ config SCSI_SCAN_ASYNC system continues booting, and even probe devices on different busses in parallel, leading to a significant speed-up. - If you have built SCSI as modules, enabling this option can - be a problem as the devices may not have been found by the - time your system expects them to have been. You can load the - scsi_wait_scan module to ensure that all scans have completed. - If you build your SCSI drivers into the kernel, then everything - will work fine if you say Y here. - You can override this choice by specifying "scsi_mod.scan=sync" or async on the kernel's command line. -- cgit v0.10.2 From 0c6cac7ab44435d8837931a561cc4d58530cc032 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Thu, 10 Sep 2015 14:46:40 +0200 Subject: hwmon: applesmc: fix comment typos s/ressources/resources/ Signed-off-by: Bastien Nocera Signed-off-by: Jiri Kosina diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 0af63da..1f5e956 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -1138,7 +1138,7 @@ out: return ret; } -/* Create accelerometer ressources */ +/* Create accelerometer resources */ static int applesmc_create_accelerometer(void) { struct input_dev *idev; @@ -1191,7 +1191,7 @@ out: return ret; } -/* Release all ressources used by the accelerometer */ +/* Release all resources used by the accelerometer */ static void applesmc_release_accelerometer(void) { if (!smcreg.has_accelerometer) -- cgit v0.10.2 From d492cccac28493f26bb70038385a9ef4df19bdee Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 8 Jul 2015 16:09:20 +0200 Subject: ARM: mvebu: add support to clear shared L2 bit on Armada XP For optimal performance, in a HW I/O coherency context such as the one used on Armada XP, the shared L2 bit of the CPU configuration register should be cleared. This commit adjusts the coherency fabric code used by Marvell EBU processors to clear this bit on Armada XP. Since it's a per-CPU register, it's cleared in set_cpu_coherent() for the boot CPU, and through a CPU notifier for the non-boot CPUs. [gregory.clement@free-electrons.com: rebasd on 4.3-rc1] Signed-off-by: Thomas Petazzoni Signed-off-by: Gregory CLEMENT diff --git a/Documentation/devicetree/bindings/arm/mvebu-cpu-config.txt b/Documentation/devicetree/bindings/arm/mvebu-cpu-config.txt new file mode 100644 index 0000000..2cdcd71 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/mvebu-cpu-config.txt @@ -0,0 +1,20 @@ +MVEBU CPU Config registers +-------------------------- + +MVEBU (Marvell SOCs: Armada 370/XP) + +Required properties: + +- compatible: one of: + - "marvell,armada-370-cpu-config" + - "marvell,armada-xp-cpu-config" + +- reg: Should contain CPU config registers location and length, in + their per-CPU variant + +Example: + + cpu-config@21000 { + compatible = "marvell,armada-xp-cpu-config"; + reg = <0x21000 0x8>; + }; diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index 44eedf3..55348ee 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c @@ -40,6 +40,7 @@ unsigned long coherency_phys_base; void __iomem *coherency_base; static void __iomem *coherency_cpu_base; +static void __iomem *cpu_config_base; /* Coherency fabric registers */ #define IO_SYNC_BARRIER_CTL_OFFSET 0x0 @@ -65,6 +66,31 @@ static const struct of_device_id of_coherency_table[] = { int ll_enable_coherency(void); void ll_add_cpu_to_smp_group(void); +#define CPU_CONFIG_SHARED_L2 BIT(16) + +/* + * Disable the "Shared L2 Present" bit in CPU Configuration register + * on Armada XP. + * + * The "Shared L2 Present" bit affects the "level of coherence" value + * in the clidr CP15 register. Cache operation functions such as + * "flush all" and "invalidate all" operate on all the cache levels + * that included in the defined level of coherence. When HW I/O + * coherency is used, this bit causes unnecessary flushes of the L2 + * cache. + */ +static void armada_xp_clear_shared_l2(void) +{ + u32 reg; + + if (!cpu_config_base) + return; + + reg = readl(cpu_config_base); + reg &= ~CPU_CONFIG_SHARED_L2; + writel(reg, cpu_config_base); +} + static int mvebu_hwcc_notifier(struct notifier_block *nb, unsigned long event, void *__dev) { @@ -85,9 +111,24 @@ static struct notifier_block mvebu_hwcc_pci_nb = { .notifier_call = mvebu_hwcc_notifier, }; +static int armada_xp_clear_shared_l2_notifier_func(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + if (action == CPU_STARTING || action == CPU_STARTING_FROZEN) + armada_xp_clear_shared_l2(); + + return NOTIFY_OK; +} + +static struct notifier_block armada_xp_clear_shared_l2_notifier = { + .notifier_call = armada_xp_clear_shared_l2_notifier_func, + .priority = 100, +}; + static void __init armada_370_coherency_init(struct device_node *np) { struct resource res; + struct device_node *cpu_config_np; of_address_to_resource(np, 0, &res); coherency_phys_base = res.start; @@ -100,6 +141,23 @@ static void __init armada_370_coherency_init(struct device_node *np) sync_cache_w(&coherency_phys_base); coherency_base = of_iomap(np, 0); coherency_cpu_base = of_iomap(np, 1); + + cpu_config_np = of_find_compatible_node(NULL, NULL, + "marvell,armada-xp-cpu-config"); + if (!cpu_config_np) + goto exit; + + cpu_config_base = of_iomap(cpu_config_np, 0); + if (!cpu_config_base) { + of_node_put(cpu_config_np); + goto exit; + } + + of_node_put(cpu_config_np); + + register_cpu_notifier(&armada_xp_clear_shared_l2_notifier); + +exit: set_cpu_coherent(); } @@ -204,6 +262,8 @@ int set_cpu_coherent(void) pr_warn("Coherency fabric is not initialized\n"); return 1; } + + armada_xp_clear_shared_l2(); ll_add_cpu_to_smp_group(); return ll_enable_coherency(); } -- cgit v0.10.2 From 97dd823e7e88d6c5a1aaf6dae5ecf5d0c43850ca Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 8 Jul 2015 16:09:21 +0200 Subject: ARM: mvebu: add CPU config registers in the Armada 370/XP Device Tree This commit adds the description of the CPU config registers in the Armada 370 and Armada XP Device Tree. Since the registers are in fact different between the two SoCs, a different compatible string is used. Note that the Armada 370 node is currently unused, but it is nonetheless added for consistency with the addition on the Armada XP side. Signed-off-by: Thomas Petazzoni Signed-off-by: Gregory CLEMENT diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi index 53a1a5a..45eff24 100644 --- a/arch/arm/boot/dts/armada-370.dtsi +++ b/arch/arm/boot/dts/armada-370.dtsi @@ -256,6 +256,11 @@ reg = <0x20800 0x8>; }; + cpu-config@21000 { + compatible = "marvell,armada-370-cpu-config"; + reg = <0x21000 0x8>; + }; + audio_controller: audio-controller@30000 { #sound-dai-cells = <1>; compatible = "marvell,armada370-audio"; diff --git a/arch/arm/boot/dts/armada-xp.dtsi b/arch/arm/boot/dts/armada-xp.dtsi index 3de9b76..1c64ac3 100644 --- a/arch/arm/boot/dts/armada-xp.dtsi +++ b/arch/arm/boot/dts/armada-xp.dtsi @@ -184,6 +184,11 @@ reg = <0x20800 0x20>; }; + cpu-config@21000 { + compatible = "marvell,armada-xp-cpu-config"; + reg = <0x21000 0x8>; + }; + eth2: ethernet@30000 { compatible = "marvell,armada-xp-neta"; reg = <0x30000 0x4000>; -- cgit v0.10.2 From b2ee6b7bd597f567dc40447bb2ca473604ce3b6a Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 18 Aug 2015 10:08:52 +0200 Subject: ARM: mvebu: add crypto related nodes to armada-xp.dtsi Add crypto related nodes to armada-xp.dtsi. Signed-off-by: Boris Brezillon Signed-off-by: Gregory CLEMENT diff --git a/arch/arm/boot/dts/armada-xp.dtsi b/arch/arm/boot/dts/armada-xp.dtsi index 1c64ac3..be23196 100644 --- a/arch/arm/boot/dts/armada-xp.dtsi +++ b/arch/arm/boot/dts/armada-xp.dtsi @@ -241,6 +241,18 @@ compatible = "marvell,armada-xp-neta"; }; + crypto@90000 { + compatible = "marvell,armada-xp-crypto"; + reg = <0x90000 0x10000>; + reg-names = "regs"; + interrupts = <48>, <49>; + clocks = <&gateclk 23>, <&gateclk 23>; + clock-names = "cesa0", "cesa1"; + marvell,crypto-srams = <&crypto_sram0>, + <&crypto_sram1>; + marvell,crypto-sram-size = <0x800>; + }; + xor@f0900 { compatible = "marvell,orion-xor"; reg = <0xF0900 0x100 @@ -261,6 +273,24 @@ }; }; }; + + crypto_sram0: sa-sram0 { + compatible = "mmio-sram"; + reg = ; + clocks = <&gateclk 23>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 MBUS_ID(0x09, 0x09) 0 0x800>; + }; + + crypto_sram1: sa-sram1 { + compatible = "mmio-sram"; + reg = ; + clocks = <&gateclk 23>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 MBUS_ID(0x09, 0x05) 0 0x800>; + }; }; clocks { -- cgit v0.10.2 From 8aa5f09df06f0c3a5a799c5fcf878acaf29db93f Mon Sep 17 00:00:00 2001 From: Maxime Coquelin Date: Wed, 23 Sep 2015 02:47:44 +0200 Subject: ARM: dts: stih407: Enable PWM nodes only board level The PWM may not be used on some boards, so enable them only the board file. Acked-by: Patrice Chotard Acked-by: Peter Griffin Signed-off-by: Maxime Coquelin diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi index ae05277..9975e8f 100644 --- a/arch/arm/boot/dts/stih407-family.dtsi +++ b/arch/arm/boot/dts/stih407-family.dtsi @@ -585,7 +585,6 @@ /* COMMS PWM Module */ pwm0: pwm@9810000 { compatible = "st,sti-pwm"; - status = "okay"; #pwm-cells = <2>; reg = <0x9810000 0x68>; pinctrl-names = "default"; @@ -593,12 +592,13 @@ clock-names = "pwm"; clocks = <&clk_sysin>; st,pwm-num-chan = <1>; + + status = "disabled"; }; /* SBC PWM Module */ pwm1: pwm@9510000 { compatible = "st,sti-pwm"; - status = "okay"; #pwm-cells = <2>; reg = <0x9510000 0x68>; pinctrl-names = "default"; @@ -609,6 +609,8 @@ clock-names = "pwm"; clocks = <&clk_sysin>; st,pwm-num-chan = <4>; + + status = "disabled"; }; }; }; diff --git a/arch/arm/boot/dts/stihxxx-b2120.dtsi b/arch/arm/boot/dts/stihxxx-b2120.dtsi index f589fe4..ab029f7 100644 --- a/arch/arm/boot/dts/stihxxx-b2120.dtsi +++ b/arch/arm/boot/dts/stihxxx-b2120.dtsi @@ -27,6 +27,14 @@ }; }; + pwm0: pwm@9810000 { + status = "okay"; + }; + + pwm1: pwm@9510000 { + status = "okay"; + }; + i2c@9842000 { status = "okay"; }; -- cgit v0.10.2 From 759742d13caa11acf24b0aef7daa8b56f244f231 Mon Sep 17 00:00:00 2001 From: Maxime Coquelin Date: Wed, 23 Sep 2015 03:04:24 +0200 Subject: ARM: dts: stih407/410: Tidy up display nodes The display nodes are common to both STiH407 and STiH410, move them to the family file. Acked-by: Patrice Chotard Acked-by: Peter Griffin Signed-off-by: Maxime Coquelin diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi index 9975e8f..5b454d9 100644 --- a/arch/arm/boot/dts/stih407-family.dtsi +++ b/arch/arm/boot/dts/stih407-family.dtsi @@ -152,6 +152,19 @@ ; }; + /* Display */ + vtg_main: sti-vtg-main@8d02800 { + compatible = "st,vtg"; + reg = <0x8d02800 0x200>; + interrupts = ; + }; + + vtg_aux: sti-vtg-aux@8d00200 { + compatible = "st,vtg"; + reg = <0x8d00200 0x100>; + interrupts = ; + }; + serial@9830000 { compatible = "st,asc"; reg = <0x9830000 0x2c>; diff --git a/arch/arm/boot/dts/stih407.dtsi b/arch/arm/boot/dts/stih407.dtsi index 3efa3b2..98c3468 100644 --- a/arch/arm/boot/dts/stih407.dtsi +++ b/arch/arm/boot/dts/stih407.dtsi @@ -10,19 +10,6 @@ #include "stih407-family.dtsi" / { soc { - /* Display */ - vtg_main: sti-vtg-main@8d02800 { - compatible = "st,vtg"; - reg = <0x8d02800 0x200>; - interrupts = ; - }; - - vtg_aux: sti-vtg-aux@8d00200 { - compatible = "st,vtg"; - reg = <0x8d00200 0x100>; - interrupts = ; - }; - sti-display-subsystem { compatible = "st,sti-display-subsystem"; #address-cells = <1>; diff --git a/arch/arm/boot/dts/stih410.dtsi b/arch/arm/boot/dts/stih410.dtsi index 6f40bc9..23f4a48e 100644 --- a/arch/arm/boot/dts/stih410.dtsi +++ b/arch/arm/boot/dts/stih410.dtsi @@ -85,19 +85,6 @@ phy-names = "usb"; }; - /* Display */ - vtg_main: sti-vtg-main@8d02800 { - compatible = "st,vtg"; - reg = <0x8d02800 0x200>; - interrupts = ; - }; - - vtg_aux: sti-vtg-aux@8d00200 { - compatible = "st,vtg"; - reg = <0x8d00200 0x100>; - interrupts = ; - }; - sti-display-subsystem { compatible = "st,sti-display-subsystem"; #address-cells = <1>; -- cgit v0.10.2 From c466d997bb160f7c3527f8bb204b1919cbb25259 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 18 Aug 2015 10:08:53 +0200 Subject: ARM: mvebu: define crypto SRAM ranges for all armada-xp boards Define the crypto SRAM ranges so that the resources referenced by the sa-sram node can be properly extracted from the DT. Signed-off-by: Boris Brezillon Signed-off-by: Gregory CLEMENT diff --git a/arch/arm/boot/dts/armada-xp-axpwifiap.dts b/arch/arm/boot/dts/armada-xp-axpwifiap.dts index 60bbfe3..23fc670 100644 --- a/arch/arm/boot/dts/armada-xp-axpwifiap.dts +++ b/arch/arm/boot/dts/armada-xp-axpwifiap.dts @@ -69,7 +69,9 @@ soc { ranges = ; + MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000 + MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000 + MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>; pcie-controller { status = "okay"; diff --git a/arch/arm/boot/dts/armada-xp-db.dts b/arch/arm/boot/dts/armada-xp-db.dts index 7dd900f..f774101 100644 --- a/arch/arm/boot/dts/armada-xp-db.dts +++ b/arch/arm/boot/dts/armada-xp-db.dts @@ -75,7 +75,9 @@ soc { ranges = ; + MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x1000000 + MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000 + MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>; devbus-bootcs { status = "okay"; diff --git a/arch/arm/boot/dts/armada-xp-gp.dts b/arch/arm/boot/dts/armada-xp-gp.dts index bf724ca..4878d73 100644 --- a/arch/arm/boot/dts/armada-xp-gp.dts +++ b/arch/arm/boot/dts/armada-xp-gp.dts @@ -94,7 +94,9 @@ soc { ranges = ; + MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x1000000 + MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000 + MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>; devbus-bootcs { status = "okay"; diff --git a/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts b/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts index 06a6a6c..58b5008 100644 --- a/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts +++ b/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts @@ -64,7 +64,9 @@ soc { ranges = ; + MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000 + MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000 + MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>; pcie-controller { status = "okay"; diff --git a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts index fdd187c..6e9820e 100644 --- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts @@ -69,7 +69,9 @@ soc { ranges = ; + MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000 + MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000 + MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>; pcie-controller { status = "okay"; diff --git a/arch/arm/boot/dts/armada-xp-matrix.dts b/arch/arm/boot/dts/armada-xp-matrix.dts index f894bc8..6ab3383 100644 --- a/arch/arm/boot/dts/armada-xp-matrix.dts +++ b/arch/arm/boot/dts/armada-xp-matrix.dts @@ -67,7 +67,9 @@ soc { ranges = ; + MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000 + MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000 + MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>; internal-regs { serial@12000 { diff --git a/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts b/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts index 1516fc2..979fae9 100644 --- a/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts +++ b/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts @@ -63,7 +63,9 @@ soc { ranges = ; + MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000 + MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000 + MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>; pcie-controller { status = "okay"; diff --git a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts index 990e8a2..a5db177 100644 --- a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts +++ b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts @@ -65,7 +65,9 @@ soc { ranges = ; + MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x8000000 + MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000 + MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>; devbus-bootcs { status = "okay"; diff --git a/arch/arm/boot/dts/armada-xp-synology-ds414.dts b/arch/arm/boot/dts/armada-xp-synology-ds414.dts index 20267ad..2391b11 100644 --- a/arch/arm/boot/dts/armada-xp-synology-ds414.dts +++ b/arch/arm/boot/dts/armada-xp-synology-ds414.dts @@ -77,7 +77,9 @@ soc { ranges = ; + MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000 + MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000 + MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>; pcie-controller { status = "okay"; -- cgit v0.10.2 From 2dbcdb11a6cfde6b54702c7550f5826f46c3c612 Mon Sep 17 00:00:00 2001 From: Arnaud Ebalard Date: Tue, 22 Sep 2015 11:20:06 +0200 Subject: ARM: mvebu: add crypto related nodes to armada 370 dtsi Add crypto related nodes in armada-370.dtsi. Signed-off-by: Arnaud Ebalard Signed-off-by: Boris Brezillon Signed-off-by: Gregory CLEMENT diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi index 45eff24..3b06aa8 100644 --- a/arch/arm/boot/dts/armada-370.dtsi +++ b/arch/arm/boot/dts/armada-370.dtsi @@ -324,6 +324,38 @@ ethernet@74000 { compatible = "marvell,armada-370-neta"; }; + + crypto@90000 { + compatible = "marvell,armada-370-crypto"; + reg = <0x90000 0x10000>; + reg-names = "regs"; + interrupts = <48>; + clocks = <&gateclk 23>; + clock-names = "cesa0"; + marvell,crypto-srams = <&crypto_sram>; + marvell,crypto-sram-size = <0x7e0>; + }; + }; + + crypto_sram: sa-sram { + compatible = "mmio-sram"; + reg = ; + reg-names = "sram"; + clocks = <&gateclk 23>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 MBUS_ID(0x09, 0x01) 0 0x800>; + + /* + * The Armada 370 has an erratum preventing the use of + * the standard workflow for CPU idle support (relying + * on the BootROM code to enter/exit idle state). + * Reserve some amount of the crypto SRAM to put the + * cpuidle workaround. + */ + idle-sram@0 { + reg = <0x0 0x20>; + }; }; }; }; -- cgit v0.10.2 From b416f1926eb6d0f21467b6782c8555af04c46082 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 18 Aug 2015 10:08:55 +0200 Subject: ARM: mvebu: define crypto SRAM ranges for all armada-370 boards Define the crypto SRAM ranges so that the resources referenced by the sa-sram node can be properly extracted from the DT. Signed-off-by: Boris Brezillon Signed-off-by: Gregory CLEMENT diff --git a/arch/arm/boot/dts/armada-370-db.dts b/arch/arm/boot/dts/armada-370-db.dts index 03542f7..bb280de 100644 --- a/arch/arm/boot/dts/armada-370-db.dts +++ b/arch/arm/boot/dts/armada-370-db.dts @@ -74,7 +74,8 @@ soc { ranges = ; + MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000 + MBUS_ID(0x09, 0x01) 0 0xf1100000 0x10000>; internal-regs { serial@12000 { diff --git a/arch/arm/boot/dts/armada-370-dlink-dns327l.dts b/arch/arm/boot/dts/armada-370-dlink-dns327l.dts index af4dc54..e2a363b 100644 --- a/arch/arm/boot/dts/armada-370-dlink-dns327l.dts +++ b/arch/arm/boot/dts/armada-370-dlink-dns327l.dts @@ -69,7 +69,8 @@ soc { ranges = ; + MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000 + MBUS_ID(0x09, 0x01) 0 0xf1100000 0x10000>; pcie-controller { status = "okay"; diff --git a/arch/arm/boot/dts/armada-370-mirabox.dts b/arch/arm/boot/dts/armada-370-mirabox.dts index 0f40d5d..3aa980a 100644 --- a/arch/arm/boot/dts/armada-370-mirabox.dts +++ b/arch/arm/boot/dts/armada-370-mirabox.dts @@ -61,7 +61,8 @@ soc { ranges = ; + MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000 + MBUS_ID(0x09, 0x01) 0 0xf1100000 0x10000>; pcie-controller { status = "okay"; @@ -138,6 +139,10 @@ phy-mode = "rgmii-id"; }; + crypto@90000 { + status = "okay"; + }; + mvsdio@d4000 { pinctrl-0 = <&sdio_pins3>; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/armada-370-netgear-rn102.dts b/arch/arm/boot/dts/armada-370-netgear-rn102.dts index a312078..f43ee4a 100644 --- a/arch/arm/boot/dts/armada-370-netgear-rn102.dts +++ b/arch/arm/boot/dts/armada-370-netgear-rn102.dts @@ -63,7 +63,8 @@ soc { ranges = ; + MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000 + MBUS_ID(0x09, 0x01) 0 0xf1100000 0x10000>; pcie-controller { status = "okay"; diff --git a/arch/arm/boot/dts/armada-370-netgear-rn104.dts b/arch/arm/boot/dts/armada-370-netgear-rn104.dts index 00540f2..4c240de 100644 --- a/arch/arm/boot/dts/armada-370-netgear-rn104.dts +++ b/arch/arm/boot/dts/armada-370-netgear-rn104.dts @@ -63,7 +63,8 @@ soc { ranges = ; + MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000 + MBUS_ID(0x09, 0x01) 0 0xf1100000 0x10000>; pcie-controller { status = "okay"; diff --git a/arch/arm/boot/dts/armada-370-rd.dts b/arch/arm/boot/dts/armada-370-rd.dts index 19475e6..fbef730 100644 --- a/arch/arm/boot/dts/armada-370-rd.dts +++ b/arch/arm/boot/dts/armada-370-rd.dts @@ -74,7 +74,8 @@ soc { ranges = ; + MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000 + MBUS_ID(0x09, 0x01) 0 0xf1100000 0x10000>; pcie-controller { status = "okay"; diff --git a/arch/arm/boot/dts/armada-370-synology-ds213j.dts b/arch/arm/boot/dts/armada-370-synology-ds213j.dts index 4f49243..836bcc0 100644 --- a/arch/arm/boot/dts/armada-370-synology-ds213j.dts +++ b/arch/arm/boot/dts/armada-370-synology-ds213j.dts @@ -77,7 +77,8 @@ soc { ranges = ; + MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000 + MBUS_ID(0x09, 0x01) 0 0xf1100000 0x10000>; internal-regs { -- cgit v0.10.2 From 35e5bb58dbf6c7b309387a83ffa04584d669ef8b Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 18 Aug 2015 10:08:56 +0200 Subject: ARM: mvebu: add crypto related nodes to armada 375 dtsi Add crypto related nodes in armada-375.dtsi. Signed-off-by: Boris Brezillon Signed-off-by: Gregory CLEMENT diff --git a/arch/arm/boot/dts/armada-375.dtsi b/arch/arm/boot/dts/armada-375.dtsi index e9a3817..7ccce75 100644 --- a/arch/arm/boot/dts/armada-375.dtsi +++ b/arch/arm/boot/dts/armada-375.dtsi @@ -513,6 +513,21 @@ }; }; + crypto@90000 { + compatible = "marvell,armada-375-crypto"; + reg = <0x90000 0x10000>; + reg-names = "regs"; + interrupts = , + ; + clocks = <&gateclk 30>, <&gateclk 31>, + <&gateclk 28>, <&gateclk 29>; + clock-names = "cesa0", "cesa1", + "cesaz0", "cesaz1"; + marvell,crypto-srams = <&crypto_sram0>, + <&crypto_sram1>; + marvell,crypto-sram-size = <0x800>; + }; + sata@a0000 { compatible = "marvell,orion-sata"; reg = <0xa0000 0x5000>; @@ -619,5 +634,23 @@ }; }; + + crypto_sram0: sa-sram0 { + compatible = "mmio-sram"; + reg = ; + clocks = <&gateclk 30>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 MBUS_ID(0x09, 0x09) 0 0x800>; + }; + + crypto_sram1: sa-sram1 { + compatible = "mmio-sram"; + reg = ; + clocks = <&gateclk 31>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 MBUS_ID(0x09, 0x05) 0 0x800>; + }; }; }; -- cgit v0.10.2 From 9a3ed1332fb93b3573a3f0ae99315e2dcc041967 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 18 Aug 2015 10:08:57 +0200 Subject: ARM: mvebu: define crypto SRAM ranges in armada-375-db.dts Define the crypto SRAM ranges so that the resources referenced by the sa-sram node can be properly extracted from the DT. Signed-off-by: Boris Brezillon Signed-off-by: Gregory CLEMENT diff --git a/arch/arm/boot/dts/armada-375-db.dts b/arch/arm/boot/dts/armada-375-db.dts index 5711b97..cded5f0 100644 --- a/arch/arm/boot/dts/armada-375-db.dts +++ b/arch/arm/boot/dts/armada-375-db.dts @@ -65,7 +65,9 @@ soc { ranges = ; + MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000 + MBUS_ID(0x09, 0x09) 0 0xf1100000 0x10000 + MBUS_ID(0x09, 0x05) 0 0xf1110000 0x10000>; internal-regs { spi@10600 { -- cgit v0.10.2 From b771ae27bc72c7be48993872396c8f1d9a72b12d Mon Sep 17 00:00:00 2001 From: Maxime Coquelin Date: Wed, 23 Sep 2015 19:53:58 +0200 Subject: ARM: dts: stih410: Enable USB2.0 and related PHY nodes at board level A board might not expose the USB2.0 ports, so disable them by default in SoC file, and enable them in b2120 board. Acked-by: Patrice Chotard Acked-by: Peter Griffin Signed-off-by: Maxime Coquelin diff --git a/arch/arm/boot/dts/stih410-b2120.dts b/arch/arm/boot/dts/stih410-b2120.dts index 16f02c5..8af1e73 100644 --- a/arch/arm/boot/dts/stih410-b2120.dts +++ b/arch/arm/boot/dts/stih410-b2120.dts @@ -35,5 +35,29 @@ sd-uhs-sdr104; sd-uhs-ddr50; }; + + usb2_picophy1: phy2 { + status = "okay"; + }; + + usb2_picophy2: phy3 { + status = "okay"; + }; + + ohci0: usb@9a03c00 { + status = "okay"; + }; + + ehci0: usb@9a03e00 { + status = "okay"; + }; + + ohci1: usb@9a83c00 { + status = "okay"; + }; + + ehci1: usb@9a83e00 { + status = "okay"; + }; }; }; diff --git a/arch/arm/boot/dts/stih410.dtsi b/arch/arm/boot/dts/stih410.dtsi index 23f4a48e..e3150e3 100644 --- a/arch/arm/boot/dts/stih410.dtsi +++ b/arch/arm/boot/dts/stih410.dtsi @@ -22,6 +22,8 @@ resets = <&softreset STIH407_PICOPHY_SOFTRESET>, <&picophyreset STIH407_PICOPHY0_RESET>; reset-names = "global", "port"; + + status = "disabled"; }; usb2_picophy2: phy3 { @@ -31,6 +33,8 @@ resets = <&softreset STIH407_PICOPHY_SOFTRESET>, <&picophyreset STIH407_PICOPHY1_RESET>; reset-names = "global", "port"; + + status = "disabled"; }; ohci0: usb@9a03c00 { @@ -43,6 +47,8 @@ reset-names = "power", "softreset"; phys = <&usb2_picophy1>; phy-names = "usb"; + + status = "disabled"; }; ehci0: usb@9a03e00 { @@ -57,6 +63,8 @@ reset-names = "power", "softreset"; phys = <&usb2_picophy1>; phy-names = "usb"; + + status = "disabled"; }; ohci1: usb@9a83c00 { @@ -69,6 +77,8 @@ reset-names = "power", "softreset"; phys = <&usb2_picophy2>; phy-names = "usb"; + + status = "disabled"; }; ehci1: usb@9a83e00 { @@ -83,6 +93,8 @@ reset-names = "power", "softreset"; phys = <&usb2_picophy2>; phy-names = "usb"; + + status = "disabled"; }; sti-display-subsystem { -- cgit v0.10.2 From 7ee20ff0072154d326c86223fbb88d23aa152b91 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Mon, 10 Aug 2015 15:47:51 +0200 Subject: ARM: mvebu: Use a CR_C constant instead of a hard-coded one Fix the armada_370_xp_pmsu_idle_enter() function to use a CR_C constant instead of a hard-coded constant in the assembly part. This clean-up was suggested by Russell King. Signed-off-by: Gregory CLEMENT diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c index e8fdb9c..9658b5a 100644 --- a/arch/arm/mach-mvebu/pmsu.c +++ b/arch/arm/mach-mvebu/pmsu.c @@ -296,11 +296,11 @@ int armada_370_xp_pmsu_idle_enter(unsigned long deepidle) /* Test the CR_C bit and set it if it was cleared */ asm volatile( "mrc p15, 0, r0, c1, c0, 0 \n\t" - "tst r0, #(1 << 2) \n\t" + "tst r0, %0 \n\t" "orreq r0, r0, #(1 << 2) \n\t" "mcreq p15, 0, r0, c1, c0, 0 \n\t" "isb " - : : : "r0"); + : : "Ir" (CR_C) : "r0"); pr_debug("Failed to suspend the system\n"); -- cgit v0.10.2 From 3d58e31888318ebd157ba0680fb24cdcd1bc3d6f Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 14 Aug 2015 11:13:50 +0100 Subject: drm/i2c: tda998x: remove DRM slave encoder support Remove the DRM slave encoder compatibility from the TDA998x driver. We now use the component helpers to manage the binding of DRM sub-drivers. Signed-off-by: Russell King diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 1c6fc24..883025d 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -23,7 +23,6 @@ #include #include -#include #include #include #include @@ -53,8 +52,6 @@ struct tda998x_priv { bool edid_delay_active; }; -#define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv) - /* The TDA9988 series of devices use a paged register scheme.. to simplify * things we encode the page # in upper bits of the register #. To read/ * write a given register, we need to make sure CURPAGE register is set @@ -1182,16 +1179,6 @@ static void tda998x_encoder_set_polling(struct tda998x_priv *priv, DRM_CONNECTOR_POLL_DISCONNECT; } -static int -tda998x_encoder_set_property(struct drm_encoder *encoder, - struct drm_connector *connector, - struct drm_property *property, - uint64_t val) -{ - DBG(""); - return 0; -} - static void tda998x_destroy(struct tda998x_priv *priv) { /* disable all IRQs and free the IRQ handler */ @@ -1207,78 +1194,6 @@ static void tda998x_destroy(struct tda998x_priv *priv) i2c_unregister_device(priv->cec); } -/* Slave encoder support */ - -static void -tda998x_encoder_slave_set_config(struct drm_encoder *encoder, void *params) -{ - tda998x_encoder_set_config(to_tda998x_priv(encoder), params); -} - -static void tda998x_encoder_slave_destroy(struct drm_encoder *encoder) -{ - struct tda998x_priv *priv = to_tda998x_priv(encoder); - - tda998x_destroy(priv); - drm_i2c_encoder_destroy(encoder); - kfree(priv); -} - -static void tda998x_encoder_slave_dpms(struct drm_encoder *encoder, int mode) -{ - tda998x_encoder_dpms(to_tda998x_priv(encoder), mode); -} - -static int tda998x_encoder_slave_mode_valid(struct drm_encoder *encoder, - struct drm_display_mode *mode) -{ - return tda998x_encoder_mode_valid(to_tda998x_priv(encoder), mode); -} - -static void -tda998x_encoder_slave_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - tda998x_encoder_mode_set(to_tda998x_priv(encoder), mode, adjusted_mode); -} - -static enum drm_connector_status -tda998x_encoder_slave_detect(struct drm_encoder *encoder, - struct drm_connector *connector) -{ - return tda998x_encoder_detect(to_tda998x_priv(encoder)); -} - -static int tda998x_encoder_slave_get_modes(struct drm_encoder *encoder, - struct drm_connector *connector) -{ - return tda998x_encoder_get_modes(to_tda998x_priv(encoder), connector); -} - -static int -tda998x_encoder_slave_create_resources(struct drm_encoder *encoder, - struct drm_connector *connector) -{ - tda998x_encoder_set_polling(to_tda998x_priv(encoder), connector); - return 0; -} - -static struct drm_encoder_slave_funcs tda998x_encoder_slave_funcs = { - .set_config = tda998x_encoder_slave_set_config, - .destroy = tda998x_encoder_slave_destroy, - .dpms = tda998x_encoder_slave_dpms, - .save = tda998x_encoder_save, - .restore = tda998x_encoder_restore, - .mode_fixup = tda998x_encoder_mode_fixup, - .mode_valid = tda998x_encoder_slave_mode_valid, - .mode_set = tda998x_encoder_slave_mode_set, - .detect = tda998x_encoder_slave_detect, - .get_modes = tda998x_encoder_slave_get_modes, - .create_resources = tda998x_encoder_slave_create_resources, - .set_property = tda998x_encoder_set_property, -}; - /* I2C driver functions */ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv) @@ -1413,31 +1328,6 @@ fail: return -ENXIO; } -static int tda998x_encoder_init(struct i2c_client *client, - struct drm_device *dev, - struct drm_encoder_slave *encoder_slave) -{ - struct tda998x_priv *priv; - int ret; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->encoder = &encoder_slave->base; - - ret = tda998x_create(client, priv); - if (ret) { - kfree(priv); - return ret; - } - - encoder_slave->slave_priv = priv; - encoder_slave->slave_funcs = &tda998x_encoder_slave_funcs; - - return 0; -} - struct tda998x_priv2 { struct tda998x_priv base; struct drm_encoder encoder; @@ -1659,38 +1549,18 @@ static struct i2c_device_id tda998x_ids[] = { }; MODULE_DEVICE_TABLE(i2c, tda998x_ids); -static struct drm_i2c_encoder_driver tda998x_driver = { - .i2c_driver = { - .probe = tda998x_probe, - .remove = tda998x_remove, - .driver = { - .name = "tda998x", - .of_match_table = of_match_ptr(tda998x_dt_ids), - }, - .id_table = tda998x_ids, +static struct i2c_driver tda998x_driver = { + .probe = tda998x_probe, + .remove = tda998x_remove, + .driver = { + .name = "tda998x", + .of_match_table = of_match_ptr(tda998x_dt_ids), }, - .encoder_init = tda998x_encoder_init, + .id_table = tda998x_ids, }; -/* Module initialization */ - -static int __init -tda998x_init(void) -{ - DBG(""); - return drm_i2c_encoder_register(THIS_MODULE, &tda998x_driver); -} - -static void __exit -tda998x_exit(void) -{ - DBG(""); - drm_i2c_encoder_unregister(&tda998x_driver); -} +module_i2c_driver(tda998x_driver); MODULE_AUTHOR("Rob Clark Date: Fri, 14 Aug 2015 11:17:12 +0100 Subject: drm/i2c: tda998x: remove encoder pointer Remove the encoder pointer from struct tda998x_priv, moving the encoder itself from struct tda998x_priv2 here. Signed-off-by: Russell King diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 883025d..e30a2a8 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -44,12 +44,13 @@ struct tda998x_priv { wait_queue_head_t wq_edid; volatile int wq_edid_wait; - struct drm_encoder *encoder; struct work_struct detect_work; struct timer_list edid_delay_timer; wait_queue_head_t edid_delay_waitq; bool edid_delay_active; + + struct drm_encoder encoder; }; /* The TDA9988 series of devices use a paged register scheme.. to simplify @@ -594,7 +595,7 @@ static void tda998x_detect_work(struct work_struct *work) { struct tda998x_priv *priv = container_of(work, struct tda998x_priv, detect_work); - struct drm_device *dev = priv->encoder->dev; + struct drm_device *dev = priv->encoder.dev; if (dev) drm_kms_helper_hotplug_event(dev); @@ -1330,7 +1331,6 @@ fail: struct tda998x_priv2 { struct tda998x_priv base; - struct drm_encoder encoder; struct drm_connector connector; }; @@ -1338,7 +1338,7 @@ struct tda998x_priv2 { container_of(x, struct tda998x_priv2, connector); #define enc_to_tda998x_priv2(x) \ - container_of(x, struct tda998x_priv2, encoder); + container_of(x, struct tda998x_priv2, base.encoder); static void tda998x_encoder2_dpms(struct drm_encoder *encoder, int mode) { @@ -1408,7 +1408,7 @@ tda998x_connector_best_encoder(struct drm_connector *connector) { struct tda998x_priv2 *priv = conn_to_tda998x_priv2(connector); - return &priv->encoder; + return &priv->base.encoder; } static @@ -1463,9 +1463,8 @@ static int tda998x_bind(struct device *dev, struct device *master, void *data) crtcs = 1 << 0; } - priv->base.encoder = &priv->encoder; priv->connector.interlace_allowed = 1; - priv->encoder.possible_crtcs = crtcs; + priv->base.encoder.possible_crtcs = crtcs; ret = tda998x_create(client, &priv->base); if (ret) @@ -1476,8 +1475,8 @@ static int tda998x_bind(struct device *dev, struct device *master, void *data) tda998x_encoder_set_polling(&priv->base, &priv->connector); - drm_encoder_helper_add(&priv->encoder, &tda998x_encoder_helper_funcs); - ret = drm_encoder_init(drm, &priv->encoder, &tda998x_encoder_funcs, + drm_encoder_helper_add(&priv->base.encoder, &tda998x_encoder_helper_funcs); + ret = drm_encoder_init(drm, &priv->base.encoder, &tda998x_encoder_funcs, DRM_MODE_ENCODER_TMDS); if (ret) goto err_encoder; @@ -1494,15 +1493,15 @@ static int tda998x_bind(struct device *dev, struct device *master, void *data) if (ret) goto err_sysfs; - priv->connector.encoder = &priv->encoder; - drm_mode_connector_attach_encoder(&priv->connector, &priv->encoder); + priv->connector.encoder = &priv->base.encoder; + drm_mode_connector_attach_encoder(&priv->connector, &priv->base.encoder); return 0; err_sysfs: drm_connector_cleanup(&priv->connector); err_connector: - drm_encoder_cleanup(&priv->encoder); + drm_encoder_cleanup(&priv->base.encoder); err_encoder: tda998x_destroy(&priv->base); return ret; @@ -1514,7 +1513,7 @@ static void tda998x_unbind(struct device *dev, struct device *master, struct tda998x_priv2 *priv = dev_get_drvdata(dev); drm_connector_cleanup(&priv->connector); - drm_encoder_cleanup(&priv->encoder); + drm_encoder_cleanup(&priv->base.encoder); tda998x_destroy(&priv->base); } -- cgit v0.10.2 From eed64b5963f1496be62ba41f536346b2186727a0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 14 Aug 2015 11:18:28 +0100 Subject: drm/i2c: tda998x: move connector into struct tda998x_priv Move the DRM connector structure into struct tda998x_priv from the old struct tda998x_priv2. Signed-off-by: Russell King diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index e30a2a8..a2a463c 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -51,6 +51,7 @@ struct tda998x_priv { bool edid_delay_active; struct drm_encoder encoder; + struct drm_connector connector; }; /* The TDA9988 series of devices use a paged register scheme.. to simplify @@ -1331,11 +1332,10 @@ fail: struct tda998x_priv2 { struct tda998x_priv base; - struct drm_connector connector; }; #define conn_to_tda998x_priv2(x) \ - container_of(x, struct tda998x_priv2, connector); + container_of(x, struct tda998x_priv2, base.connector); #define enc_to_tda998x_priv2(x) \ container_of(x, struct tda998x_priv2, base.encoder); @@ -1463,7 +1463,7 @@ static int tda998x_bind(struct device *dev, struct device *master, void *data) crtcs = 1 << 0; } - priv->connector.interlace_allowed = 1; + priv->base.connector.interlace_allowed = 1; priv->base.encoder.possible_crtcs = crtcs; ret = tda998x_create(client, &priv->base); @@ -1473,7 +1473,7 @@ static int tda998x_bind(struct device *dev, struct device *master, void *data) if (!dev->of_node && params) tda998x_encoder_set_config(&priv->base, params); - tda998x_encoder_set_polling(&priv->base, &priv->connector); + tda998x_encoder_set_polling(&priv->base, &priv->base.connector); drm_encoder_helper_add(&priv->base.encoder, &tda998x_encoder_helper_funcs); ret = drm_encoder_init(drm, &priv->base.encoder, &tda998x_encoder_funcs, @@ -1481,25 +1481,25 @@ static int tda998x_bind(struct device *dev, struct device *master, void *data) if (ret) goto err_encoder; - drm_connector_helper_add(&priv->connector, + drm_connector_helper_add(&priv->base.connector, &tda998x_connector_helper_funcs); - ret = drm_connector_init(drm, &priv->connector, + ret = drm_connector_init(drm, &priv->base.connector, &tda998x_connector_funcs, DRM_MODE_CONNECTOR_HDMIA); if (ret) goto err_connector; - ret = drm_connector_register(&priv->connector); + ret = drm_connector_register(&priv->base.connector); if (ret) goto err_sysfs; - priv->connector.encoder = &priv->base.encoder; - drm_mode_connector_attach_encoder(&priv->connector, &priv->base.encoder); + priv->base.connector.encoder = &priv->base.encoder; + drm_mode_connector_attach_encoder(&priv->base.connector, &priv->base.encoder); return 0; err_sysfs: - drm_connector_cleanup(&priv->connector); + drm_connector_cleanup(&priv->base.connector); err_connector: drm_encoder_cleanup(&priv->base.encoder); err_encoder: @@ -1512,7 +1512,7 @@ static void tda998x_unbind(struct device *dev, struct device *master, { struct tda998x_priv2 *priv = dev_get_drvdata(dev); - drm_connector_cleanup(&priv->connector); + drm_connector_cleanup(&priv->base.connector); drm_encoder_cleanup(&priv->base.encoder); tda998x_destroy(&priv->base); } -- cgit v0.10.2 From a3584f60f4898c9479931cdca1dc19f758af45fb Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 14 Aug 2015 11:22:50 +0100 Subject: drm/i2c: tda998x: kill struct tda998x_priv2 Kill the redundant tda998x_priv2 structure now that its only member is the struct tda998x_priv. Signed-off-by: Russell King diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index a2a463c..8bca9155 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -1330,21 +1330,17 @@ fail: return -ENXIO; } -struct tda998x_priv2 { - struct tda998x_priv base; -}; - -#define conn_to_tda998x_priv2(x) \ - container_of(x, struct tda998x_priv2, base.connector); +#define conn_to_tda998x_priv(x) \ + container_of(x, struct tda998x_priv, connector); -#define enc_to_tda998x_priv2(x) \ - container_of(x, struct tda998x_priv2, base.encoder); +#define enc_to_tda998x_priv(x) \ + container_of(x, struct tda998x_priv, encoder); static void tda998x_encoder2_dpms(struct drm_encoder *encoder, int mode) { - struct tda998x_priv2 *priv = enc_to_tda998x_priv2(encoder); + struct tda998x_priv *priv = enc_to_tda998x_priv(encoder); - tda998x_encoder_dpms(&priv->base, mode); + tda998x_encoder_dpms(priv, mode); } static void tda998x_encoder_prepare(struct drm_encoder *encoder) @@ -1361,9 +1357,9 @@ static void tda998x_encoder2_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { - struct tda998x_priv2 *priv = enc_to_tda998x_priv2(encoder); + struct tda998x_priv *priv = enc_to_tda998x_priv(encoder); - tda998x_encoder_mode_set(&priv->base, mode, adjusted_mode); + tda998x_encoder_mode_set(priv, mode, adjusted_mode); } static const struct drm_encoder_helper_funcs tda998x_encoder_helper_funcs = { @@ -1378,9 +1374,9 @@ static const struct drm_encoder_helper_funcs tda998x_encoder_helper_funcs = { static void tda998x_encoder_destroy(struct drm_encoder *encoder) { - struct tda998x_priv2 *priv = enc_to_tda998x_priv2(encoder); + struct tda998x_priv *priv = enc_to_tda998x_priv(encoder); - tda998x_destroy(&priv->base); + tda998x_destroy(priv); drm_encoder_cleanup(encoder); } @@ -1390,25 +1386,25 @@ static const struct drm_encoder_funcs tda998x_encoder_funcs = { static int tda998x_connector_get_modes(struct drm_connector *connector) { - struct tda998x_priv2 *priv = conn_to_tda998x_priv2(connector); + struct tda998x_priv *priv = conn_to_tda998x_priv(connector); - return tda998x_encoder_get_modes(&priv->base, connector); + return tda998x_encoder_get_modes(priv, connector); } static int tda998x_connector_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { - struct tda998x_priv2 *priv = conn_to_tda998x_priv2(connector); + struct tda998x_priv *priv = conn_to_tda998x_priv(connector); - return tda998x_encoder_mode_valid(&priv->base, mode); + return tda998x_encoder_mode_valid(priv, mode); } static struct drm_encoder * tda998x_connector_best_encoder(struct drm_connector *connector) { - struct tda998x_priv2 *priv = conn_to_tda998x_priv2(connector); + struct tda998x_priv *priv = conn_to_tda998x_priv(connector); - return &priv->base.encoder; + return &priv->encoder; } static @@ -1421,9 +1417,9 @@ const struct drm_connector_helper_funcs tda998x_connector_helper_funcs = { static enum drm_connector_status tda998x_connector_detect(struct drm_connector *connector, bool force) { - struct tda998x_priv2 *priv = conn_to_tda998x_priv2(connector); + struct tda998x_priv *priv = conn_to_tda998x_priv(connector); - return tda998x_encoder_detect(&priv->base); + return tda998x_encoder_detect(priv); } static void tda998x_connector_destroy(struct drm_connector *connector) @@ -1444,7 +1440,7 @@ static int tda998x_bind(struct device *dev, struct device *master, void *data) struct tda998x_encoder_params *params = dev->platform_data; struct i2c_client *client = to_i2c_client(dev); struct drm_device *drm = data; - struct tda998x_priv2 *priv; + struct tda998x_priv *priv; u32 crtcs = 0; int ret; @@ -1463,58 +1459,58 @@ static int tda998x_bind(struct device *dev, struct device *master, void *data) crtcs = 1 << 0; } - priv->base.connector.interlace_allowed = 1; - priv->base.encoder.possible_crtcs = crtcs; + priv->connector.interlace_allowed = 1; + priv->encoder.possible_crtcs = crtcs; - ret = tda998x_create(client, &priv->base); + ret = tda998x_create(client, priv); if (ret) return ret; if (!dev->of_node && params) - tda998x_encoder_set_config(&priv->base, params); + tda998x_encoder_set_config(priv, params); - tda998x_encoder_set_polling(&priv->base, &priv->base.connector); + tda998x_encoder_set_polling(priv, &priv->connector); - drm_encoder_helper_add(&priv->base.encoder, &tda998x_encoder_helper_funcs); - ret = drm_encoder_init(drm, &priv->base.encoder, &tda998x_encoder_funcs, + drm_encoder_helper_add(&priv->encoder, &tda998x_encoder_helper_funcs); + ret = drm_encoder_init(drm, &priv->encoder, &tda998x_encoder_funcs, DRM_MODE_ENCODER_TMDS); if (ret) goto err_encoder; - drm_connector_helper_add(&priv->base.connector, + drm_connector_helper_add(&priv->connector, &tda998x_connector_helper_funcs); - ret = drm_connector_init(drm, &priv->base.connector, + ret = drm_connector_init(drm, &priv->connector, &tda998x_connector_funcs, DRM_MODE_CONNECTOR_HDMIA); if (ret) goto err_connector; - ret = drm_connector_register(&priv->base.connector); + ret = drm_connector_register(&priv->connector); if (ret) goto err_sysfs; - priv->base.connector.encoder = &priv->base.encoder; - drm_mode_connector_attach_encoder(&priv->base.connector, &priv->base.encoder); + priv->connector.encoder = &priv->encoder; + drm_mode_connector_attach_encoder(&priv->connector, &priv->encoder); return 0; err_sysfs: - drm_connector_cleanup(&priv->base.connector); + drm_connector_cleanup(&priv->connector); err_connector: - drm_encoder_cleanup(&priv->base.encoder); + drm_encoder_cleanup(&priv->encoder); err_encoder: - tda998x_destroy(&priv->base); + tda998x_destroy(priv); return ret; } static void tda998x_unbind(struct device *dev, struct device *master, void *data) { - struct tda998x_priv2 *priv = dev_get_drvdata(dev); + struct tda998x_priv *priv = dev_get_drvdata(dev); - drm_connector_cleanup(&priv->base.connector); - drm_encoder_cleanup(&priv->base.encoder); - tda998x_destroy(&priv->base); + drm_connector_cleanup(&priv->connector); + drm_encoder_cleanup(&priv->encoder); + tda998x_destroy(priv); } static const struct component_ops tda998x_ops = { -- cgit v0.10.2 From 9525c4dd923f8ffe38818f86cee523a5f7b19617 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 14 Aug 2015 11:28:53 +0100 Subject: drm/i2c: tda998x: clean up after struct tda998x_priv2 removal We can now kill a number of glue functions which were sitting between the common tda998x code and the drm encoder/connector methods. This results in slightly cleaner code. Signed-off-by: Russell King diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 8bca9155..896b6aa 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -54,6 +54,12 @@ struct tda998x_priv { struct drm_connector connector; }; +#define conn_to_tda998x_priv(x) \ + container_of(x, struct tda998x_priv, connector) + +#define enc_to_tda998x_priv(x) \ + container_of(x, struct tda998x_priv, encoder) + /* The TDA9988 series of devices use a paged register scheme.. to simplify * things we encode the page # in upper bits of the register #. To read/ * write a given register, we need to make sure CURPAGE register is set @@ -562,7 +568,7 @@ tda998x_reset(struct tda998x_priv *priv) * trying to read EDID data. * * However, tda998x_encoder_get_modes() may be called at any moment - * after tda998x_encoder_detect() indicates that we are connected, so + * after tda998x_connector_detect() indicates that we are connected, so * we need to delay probing modes in tda998x_encoder_get_modes() after * we have seen a HPD inactive->active transition. This code implements * that delay. @@ -816,8 +822,10 @@ static void tda998x_encoder_set_config(struct tda998x_priv *priv, priv->params = *p; } -static void tda998x_encoder_dpms(struct tda998x_priv *priv, int mode) +static void tda998x_encoder_dpms(struct drm_encoder *encoder, int mode) { + struct tda998x_priv *priv = enc_to_tda998x_priv(encoder); + /* we only care about on or off: */ if (mode != DRM_MODE_DPMS_ON) mode = DRM_MODE_DPMS_OFF; @@ -867,8 +875,8 @@ tda998x_encoder_mode_fixup(struct drm_encoder *encoder, return true; } -static int tda998x_encoder_mode_valid(struct tda998x_priv *priv, - struct drm_display_mode *mode) +static int tda998x_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) { if (mode->clock > 150000) return MODE_CLOCK_HIGH; @@ -880,10 +888,11 @@ static int tda998x_encoder_mode_valid(struct tda998x_priv *priv, } static void -tda998x_encoder_mode_set(struct tda998x_priv *priv, +tda998x_encoder_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { + struct tda998x_priv *priv = enc_to_tda998x_priv(encoder); u16 ref_pix, ref_line, n_pix, n_line; u16 hs_pix_s, hs_pix_e; u16 vs1_pix_s, vs1_pix_e, vs1_line_s, vs1_line_e; @@ -1071,8 +1080,9 @@ tda998x_encoder_mode_set(struct tda998x_priv *priv, } static enum drm_connector_status -tda998x_encoder_detect(struct tda998x_priv *priv) +tda998x_connector_detect(struct drm_connector *connector, bool force) { + struct tda998x_priv *priv = conn_to_tda998x_priv(connector); u8 val = cec_read(priv, REG_CEC_RXSHPDLEV); return (val & CEC_RXSHPDLEV_HPD) ? connector_status_connected : @@ -1135,10 +1145,9 @@ static int read_edid_block(void *data, u8 *buf, unsigned int blk, size_t length) return 0; } -static int -tda998x_encoder_get_modes(struct tda998x_priv *priv, - struct drm_connector *connector) +static int tda998x_connector_get_modes(struct drm_connector *connector) { + struct tda998x_priv *priv = conn_to_tda998x_priv(connector); struct edid *edid; int n; @@ -1330,46 +1339,24 @@ fail: return -ENXIO; } -#define conn_to_tda998x_priv(x) \ - container_of(x, struct tda998x_priv, connector); - -#define enc_to_tda998x_priv(x) \ - container_of(x, struct tda998x_priv, encoder); - -static void tda998x_encoder2_dpms(struct drm_encoder *encoder, int mode) -{ - struct tda998x_priv *priv = enc_to_tda998x_priv(encoder); - - tda998x_encoder_dpms(priv, mode); -} - static void tda998x_encoder_prepare(struct drm_encoder *encoder) { - tda998x_encoder2_dpms(encoder, DRM_MODE_DPMS_OFF); + tda998x_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); } static void tda998x_encoder_commit(struct drm_encoder *encoder) { - tda998x_encoder2_dpms(encoder, DRM_MODE_DPMS_ON); -} - -static void tda998x_encoder2_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct tda998x_priv *priv = enc_to_tda998x_priv(encoder); - - tda998x_encoder_mode_set(priv, mode, adjusted_mode); + tda998x_encoder_dpms(encoder, DRM_MODE_DPMS_ON); } static const struct drm_encoder_helper_funcs tda998x_encoder_helper_funcs = { - .dpms = tda998x_encoder2_dpms, + .dpms = tda998x_encoder_dpms, .save = tda998x_encoder_save, .restore = tda998x_encoder_restore, .mode_fixup = tda998x_encoder_mode_fixup, .prepare = tda998x_encoder_prepare, .commit = tda998x_encoder_commit, - .mode_set = tda998x_encoder2_mode_set, + .mode_set = tda998x_encoder_mode_set, }; static void tda998x_encoder_destroy(struct drm_encoder *encoder) @@ -1384,21 +1371,6 @@ static const struct drm_encoder_funcs tda998x_encoder_funcs = { .destroy = tda998x_encoder_destroy, }; -static int tda998x_connector_get_modes(struct drm_connector *connector) -{ - struct tda998x_priv *priv = conn_to_tda998x_priv(connector); - - return tda998x_encoder_get_modes(priv, connector); -} - -static int tda998x_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - struct tda998x_priv *priv = conn_to_tda998x_priv(connector); - - return tda998x_encoder_mode_valid(priv, mode); -} - static struct drm_encoder * tda998x_connector_best_encoder(struct drm_connector *connector) { @@ -1414,14 +1386,6 @@ const struct drm_connector_helper_funcs tda998x_connector_helper_funcs = { .best_encoder = tda998x_connector_best_encoder, }; -static enum drm_connector_status -tda998x_connector_detect(struct drm_connector *connector, bool force) -{ - struct tda998x_priv *priv = conn_to_tda998x_priv(connector); - - return tda998x_encoder_detect(priv); -} - static void tda998x_connector_destroy(struct drm_connector *connector) { drm_connector_unregister(connector); -- cgit v0.10.2 From 5b32b1368ae532a2d06c931ba6356c39a9de63ac Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Mon, 28 Sep 2015 19:51:18 +0300 Subject: memory: pl172: correct MPMC peripheral ID register bits According to PL172 TRM read of bits [7:6] of MPMCPeriphID3 is undefined, so unmask them. Also the driver supports all currently present revisions of PL172, this allows to alleviate requirements to the revision version matched by the driver. Signed-off-by: Vladimir Zapolskiy Signed-off-by: Joachim Eastwood diff --git a/drivers/memory/pl172.c b/drivers/memory/pl172.c index b2ef607..95a4ad7 100644 --- a/drivers/memory/pl172.c +++ b/drivers/memory/pl172.c @@ -278,9 +278,10 @@ static int pl172_remove(struct amba_device *adev) } static const struct amba_id pl172_ids[] = { + /* PrimeCell MPMC PL172, EMC found on NXP LPC18xx and LPC43xx */ { - .id = 0x07341172, - .mask = 0xffffffff, + .id = 0x07041172, + .mask = 0x3f0fffff, }, { 0, 0 }, }; -- cgit v0.10.2 From b794df56cbb46e031c29922acb24617b72f8f5a7 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Mon, 28 Sep 2015 19:51:19 +0300 Subject: memory: pl172: add ARM PrimeCell PL175 MPMC support The change adds support of ARM PrimeCell PL175 MPMC, the controller is found on NXP LPC32xx SoC. PL175 MPMC is very similar to PL172 controller, so it is preferred to add its support into the existing driver. One of the differences between PL172 and PL175 is that the latter one supports up to 6 AHB ports, but still only 4 AHB ports can be assigned to a static memory device, also PL175 does not have write buffer enable control in static memory configuration register. Signed-off-by: Vladimir Zapolskiy Signed-off-by: Joachim Eastwood diff --git a/drivers/memory/pl172.c b/drivers/memory/pl172.c index 95a4ad7..cb6ebb8 100644 --- a/drivers/memory/pl172.c +++ b/drivers/memory/pl172.c @@ -118,7 +118,8 @@ static int pl172_setup_static(struct amba_device *adev, if (of_property_read_bool(np, "mpmc,extended-wait")) cfg |= MPMC_STATIC_CFG_EW; - if (of_property_read_bool(np, "mpmc,buffer-enable")) + if (amba_part(adev) == 0x172 && + of_property_read_bool(np, "mpmc,buffer-enable")) cfg |= MPMC_STATIC_CFG_B; if (of_property_read_bool(np, "mpmc,write-protect")) @@ -190,6 +191,7 @@ static int pl172_parse_cs_config(struct amba_device *adev, } static const char * const pl172_revisions[] = {"r1", "r2", "r2p3", "r2p4"}; +static const char * const pl175_revisions[] = {"r1"}; static int pl172_probe(struct amba_device *adev, const struct amba_id *id) { @@ -202,6 +204,9 @@ static int pl172_probe(struct amba_device *adev, const struct amba_id *id) if (amba_part(adev) == 0x172) { if (amba_rev(adev) < ARRAY_SIZE(pl172_revisions)) rev = pl172_revisions[amba_rev(adev)]; + } else if (amba_part(adev) == 0x175) { + if (amba_rev(adev) < ARRAY_SIZE(pl175_revisions)) + rev = pl175_revisions[amba_rev(adev)]; } dev_info(dev, "ARM PL%x revision %s\n", amba_part(adev), rev); @@ -283,6 +288,11 @@ static const struct amba_id pl172_ids[] = { .id = 0x07041172, .mask = 0x3f0fffff, }, + /* PrimeCell MPMC PL175, EMC found on NXP LPC32xx */ + { + .id = 0x07041175, + .mask = 0x3f0fffff, + }, { 0, 0 }, }; MODULE_DEVICE_TABLE(amba, pl172_ids); -- cgit v0.10.2 From f6d77beefd159f8c36b28c60d89e1557438a077e Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Mon, 28 Sep 2015 19:51:20 +0300 Subject: memory: pl172: add ARM PrimeCell PL176 MPMC support The change adds support of ARM PrimeCell PL176 MPMC. Static memory configuration of PL175 MPMC is very similar to one found on PL172 and PL175 controllers, so it is preferred to add its support into the existing driver. The difference is that PL176 supports up to 10 slave ports (but only 4 of them may be connected to static memory devices), AHB master bus width cab be 64-bit wide, also NAND devices can be interfaced. Similar to PL175 contoller, PL176 has no write buffer enable control in static memory configuration register, the rest of static memory configuration bits (with exception of NAND) is the same. Signed-off-by: Vladimir Zapolskiy Signed-off-by: Joachim Eastwood diff --git a/drivers/memory/pl172.c b/drivers/memory/pl172.c index cb6ebb8..ff57195 100644 --- a/drivers/memory/pl172.c +++ b/drivers/memory/pl172.c @@ -192,6 +192,7 @@ static int pl172_parse_cs_config(struct amba_device *adev, static const char * const pl172_revisions[] = {"r1", "r2", "r2p3", "r2p4"}; static const char * const pl175_revisions[] = {"r1"}; +static const char * const pl176_revisions[] = {"r0"}; static int pl172_probe(struct amba_device *adev, const struct amba_id *id) { @@ -207,6 +208,9 @@ static int pl172_probe(struct amba_device *adev, const struct amba_id *id) } else if (amba_part(adev) == 0x175) { if (amba_rev(adev) < ARRAY_SIZE(pl175_revisions)) rev = pl175_revisions[amba_rev(adev)]; + } else if (amba_part(adev) == 0x176) { + if (amba_rev(adev) < ARRAY_SIZE(pl176_revisions)) + rev = pl176_revisions[amba_rev(adev)]; } dev_info(dev, "ARM PL%x revision %s\n", amba_part(adev), rev); @@ -293,6 +297,11 @@ static const struct amba_id pl172_ids[] = { .id = 0x07041175, .mask = 0x3f0fffff, }, + /* PrimeCell MPMC PL176 */ + { + .id = 0x89041176, + .mask = 0xff0fffff, + }, { 0, 0 }, }; MODULE_DEVICE_TABLE(amba, pl172_ids); -- cgit v0.10.2 From 961a86d22e89428516fa7183b7750a4ba9866f4d Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Mon, 28 Sep 2015 19:51:21 +0300 Subject: doc: dt: arm,pl172: add description of PL175 and PL176 controllers Signed-off-by: Vladimir Zapolskiy Cc: Rob Herring Cc: Pawel Moll Cc: Mark Rutland Cc: devicetree@vger.kernel.org Signed-off-by: Joachim Eastwood diff --git a/Documentation/devicetree/bindings/memory-controllers/arm,pl172.txt b/Documentation/devicetree/bindings/memory-controllers/arm,pl172.txt index e6df32f..22b77ee 100644 --- a/Documentation/devicetree/bindings/memory-controllers/arm,pl172.txt +++ b/Documentation/devicetree/bindings/memory-controllers/arm,pl172.txt @@ -1,8 +1,9 @@ -* Device tree bindings for ARM PL172 MultiPort Memory Controller +* Device tree bindings for ARM PL172/PL175/PL176 MultiPort Memory Controller Required properties: -- compatible: "arm,pl172", "arm,primecell" +- compatible: Must be "arm,primecell" and exactly one from + "arm,pl172", "arm,pl175" or "arm,pl176". - reg: Must contains offset/length value for controller. @@ -56,7 +57,8 @@ Optional child cs node config properties: - mpmc,extended-wait: Enable extended wait. -- mpmc,buffer-enable: Enable write buffer. +- mpmc,buffer-enable: Enable write buffer, option is not supported by + PL175 and PL176 controllers. - mpmc,write-protect: Enable write protect. -- cgit v0.10.2 From 9c5c87e5936e792ddca5cb876d523b6e5d6042e6 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Thu, 2 Apr 2015 16:49:07 +0200 Subject: ti-soc-thermal: implement omap3 support This adds support for OMAP3 chips to ti-soc-thermal. As requested by TI people, it is marked unreliable and warning is printed. Signed-off-by: Pavel Machek Signed-off-by: Eduardo Valentin diff --git a/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt b/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt index 0c9222d..d9a1b54 100644 --- a/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt +++ b/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt @@ -10,6 +10,7 @@ to the silicon temperature. Required properties: - compatible : Should be: + - "ti,omap34xx-bandgap" : for OMAP34xx bandgap - "ti,omap4430-bandgap" : for OMAP4430 bandgap - "ti,omap4460-bandgap" : for OMAP4460 bandgap - "ti,omap4470-bandgap" : for OMAP4470 bandgap @@ -25,6 +26,12 @@ to each bandgap version, because the mapping may change from soc to soc, apart of depending on available features. Example: +OMAP34xx: +bandgap { + reg = <0x48002524 0x4>; + compatible = "ti,omap34xx-bandgap"; +}; + OMAP4430: bandgap { reg = <0x4a002260 0x4 0x4a00232C 0x4>; diff --git a/drivers/thermal/ti-soc-thermal/Kconfig b/drivers/thermal/ti-soc-thermal/Kconfig index cb6686f..ea8283f 100644 --- a/drivers/thermal/ti-soc-thermal/Kconfig +++ b/drivers/thermal/ti-soc-thermal/Kconfig @@ -19,6 +19,21 @@ config TI_THERMAL This includes trip points definitions, extrapolation rules and CPU cooling device bindings. +config OMAP3_THERMAL + bool "Texas Instruments OMAP3 thermal support" + depends on TI_SOC_THERMAL + depends on ARCH_OMAP3 || COMPILE_TEST + help + If you say yes here you get thermal support for the Texas Instruments + OMAP3 SoC family. The current chips supported are: + - OMAP3430 + + OMAP3 chips normally don't need thermal management, and sensors in + this generation are not accurate, nor they are very close to + the important hotspots. + + Say 'N' here. + config OMAP4_THERMAL bool "Texas Instruments OMAP4 thermal support" depends on TI_SOC_THERMAL diff --git a/drivers/thermal/ti-soc-thermal/Makefile b/drivers/thermal/ti-soc-thermal/Makefile index 1226b24..0f89bdf 100644 --- a/drivers/thermal/ti-soc-thermal/Makefile +++ b/drivers/thermal/ti-soc-thermal/Makefile @@ -2,5 +2,6 @@ obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal.o ti-soc-thermal-y := ti-bandgap.o ti-soc-thermal-$(CONFIG_TI_THERMAL) += ti-thermal-common.o ti-soc-thermal-$(CONFIG_DRA752_THERMAL) += dra752-thermal-data.o +ti-soc-thermal-$(CONFIG_OMAP3_THERMAL) += omap3-thermal-data.o ti-soc-thermal-$(CONFIG_OMAP4_THERMAL) += omap4-thermal-data.o ti-soc-thermal-$(CONFIG_OMAP5_THERMAL) += omap5-thermal-data.o diff --git a/drivers/thermal/ti-soc-thermal/omap3-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap3-thermal-data.c new file mode 100644 index 0000000..8470225 --- /dev/null +++ b/drivers/thermal/ti-soc-thermal/omap3-thermal-data.c @@ -0,0 +1,103 @@ +/* + * OMAP3 thermal driver. + * + * Copyright (C) 2011-2012 Texas Instruments Inc. + * Copyright (C) 2014 Pavel Machek + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Note + * http://www.ti.com/lit/er/sprz278f/sprz278f.pdf "Advisory + * 3.1.1.186 MMC OCP Clock Not Gated When Thermal Sensor Is Used" + * + * Also TI says: + * Just be careful when you try to make thermal policy like decisions + * based on this sensor. Placement of the sensor w.r.t the actual logic + * generating heat has to be a factor as well. If you are just looking + * for an approximation temperature (thermometerish kind), you might be + * ok with this. I am not sure we'd find any TI data around this.. just a + * heads up. + */ + +#include "ti-thermal.h" +#include "ti-bandgap.h" + +/* + * OMAP34XX has one instance of thermal sensor for MPU + * need to describe the individual bit fields + */ +static struct temp_sensor_registers +omap34xx_mpu_temp_sensor_registers = { + .temp_sensor_ctrl = 0, + .bgap_soc_mask = BIT(8), + .bgap_eocz_mask = BIT(7), + .bgap_dtemp_mask = 0x7f, + + .bgap_mode_ctrl = 0, + .mode_ctrl_mask = BIT(9), +}; + +/* Thresholds and limits for OMAP34XX MPU temperature sensor */ +static struct temp_sensor_data omap34xx_mpu_temp_sensor_data = { + .min_freq = 32768, + .max_freq = 32768, + .max_temp = 125000, + .min_temp = -40000, + .hyst_val = 5000, +}; + +/* + * Temperature values in milli degree celsius + */ +static const int +omap34xx_adc_to_temp[128] = { + -40000, -40000, -40000, -40000, -40000, -39000, -38000, -36000, + -34000, -32000, -31000, -29000, -28000, -26000, -25000, -24000, + -22000, -21000, -19000, -18000, -17000, -15000, -14000, -12000, + -11000, -9000, -8000, -7000, -5000, -4000, -2000, -1000, 0000, + 1000, 3000, 4000, 5000, 7000, 8000, 10000, 11000, 13000, 14000, + 15000, 17000, 18000, 20000, 21000, 22000, 24000, 25000, 27000, + 28000, 30000, 31000, 32000, 34000, 35000, 37000, 38000, 39000, + 41000, 42000, 44000, 45000, 47000, 48000, 49000, 51000, 52000, + 53000, 55000, 56000, 58000, 59000, 60000, 62000, 63000, 65000, + 66000, 67000, 69000, 70000, 72000, 73000, 74000, 76000, 77000, + 79000, 80000, 81000, 83000, 84000, 85000, 87000, 88000, 89000, + 91000, 92000, 94000, 95000, 96000, 98000, 99000, 100000, + 102000, 103000, 105000, 106000, 107000, 109000, 110000, 111000, + 113000, 114000, 116000, 117000, 118000, 120000, 121000, 122000, + 124000, 124000, 125000, 125000, 125000, 125000, 125000 +}; + +/* OMAP34XX data */ +const struct ti_bandgap_data omap34xx_data = { + .features = TI_BANDGAP_FEATURE_CLK_CTRL | TI_BANDGAP_FEATURE_UNRELIABLE, + .fclock_name = "ts_fck", + .div_ck_name = "ts_fck", + .conv_table = omap34xx_adc_to_temp, + .adc_start_val = 0, + .adc_end_val = 127, + .expose_sensor = ti_thermal_expose_sensor, + .remove_sensor = ti_thermal_remove_sensor, + + .sensors = { + { + .registers = &omap34xx_mpu_temp_sensor_registers, + .ts_data = &omap34xx_mpu_temp_sensor_data, + .domain = "cpu", + .slope = 0, + .constant = 20000, + .slope_pcb = 0, + .constant_pcb = 20000, + .register_cooling = NULL, + .unregister_cooling = NULL, + }, + }, + .sensor_count = 1, +}; diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c index 10c47c0..9f9ed72 100644 --- a/drivers/thermal/ti-soc-thermal/ti-bandgap.c +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c @@ -1274,6 +1274,10 @@ int ti_bandgap_probe(struct platform_device *pdev) } bgp->dev = &pdev->dev; + if (TI_BANDGAP_HAS(bgp, UNRELIABLE)) + dev_warn(&pdev->dev, + "This OMAP thermal sensor is unreliable. You've been warned\n"); + if (TI_BANDGAP_HAS(bgp, TSHUT)) { ret = ti_bandgap_tshut_init(bgp, pdev); if (ret) { @@ -1579,6 +1583,12 @@ static SIMPLE_DEV_PM_OPS(ti_bandgap_dev_pm_ops, ti_bandgap_suspend, #endif static const struct of_device_id of_ti_bandgap_match[] = { +#ifdef CONFIG_OMAP3_THERMAL + { + .compatible = "ti,omap34xx-bandgap", + .data = (void *)&omap34xx_data, + }, +#endif #ifdef CONFIG_OMAP4_THERMAL { .compatible = "ti,omap4430-bandgap", diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.h b/drivers/thermal/ti-soc-thermal/ti-bandgap.h index 0c52f7a..045f642 100644 --- a/drivers/thermal/ti-soc-thermal/ti-bandgap.h +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.h @@ -322,6 +322,8 @@ struct ti_temp_sensor { * has Errata 814 * TI_BANDGAP_FEATURE_ERRATA_813 - used to workaorund when the bandgap device * has Errata 813 + * TI_BANDGAP_FEATURE_UNRELIABLE - used when the sensor readings are too + * inaccurate. * TI_BANDGAP_HAS(b, f) - macro to check if a bandgap device is capable of a * specific feature (above) or not. Return non-zero, if yes. */ @@ -337,6 +339,7 @@ struct ti_temp_sensor { #define TI_BANDGAP_FEATURE_HISTORY_BUFFER BIT(9) #define TI_BANDGAP_FEATURE_ERRATA_814 BIT(10) #define TI_BANDGAP_FEATURE_ERRATA_813 BIT(11) +#define TI_BANDGAP_FEATURE_UNRELIABLE BIT(12) #define TI_BANDGAP_HAS(b, f) \ ((b)->conf->features & TI_BANDGAP_FEATURE_ ## f) @@ -390,6 +393,12 @@ int ti_bandgap_set_sensor_data(struct ti_bandgap *bgp, int id, void *data); void *ti_bandgap_get_sensor_data(struct ti_bandgap *bgp, int id); int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend); +#ifdef CONFIG_OMAP3_THERMAL +extern const struct ti_bandgap_data omap34xx_data; +#else +#define omap34xx_data NULL +#endif + #ifdef CONFIG_OMAP4_THERMAL extern const struct ti_bandgap_data omap4430_data; extern const struct ti_bandgap_data omap4460_data; -- cgit v0.10.2 From b840b6e65cbe2b84ec398bb286d121a9eb2597ee Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 21 Sep 2015 17:32:15 -0700 Subject: thermal: ti-soc-thermal: add OMAP36xx support Add OMAP36xx support to ti-soc-thermal driver. This chip is also unreliable. The data provided here is based on OMAP36xx TRM: http://www.ti.com/lit/ug/swpu177aa/swpu177aa.pdf Signed-off-by: Eduardo Valentin Signed-off-by: Eduardo Valentin diff --git a/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt b/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt index d9a1b54..6299dd8 100644 --- a/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt +++ b/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt @@ -11,6 +11,7 @@ to the silicon temperature. Required properties: - compatible : Should be: - "ti,omap34xx-bandgap" : for OMAP34xx bandgap + - "ti,omap36xx-bandgap" : for OMAP36xx bandgap - "ti,omap4430-bandgap" : for OMAP4430 bandgap - "ti,omap4460-bandgap" : for OMAP4460 bandgap - "ti,omap4470-bandgap" : for OMAP4470 bandgap @@ -32,6 +33,12 @@ bandgap { compatible = "ti,omap34xx-bandgap"; }; +OMAP36xx: +bandgap { + reg = <0x48002524 0x4>; + compatible = "ti,omap36xx-bandgap"; +}; + OMAP4430: bandgap { reg = <0x4a002260 0x4 0x4a00232C 0x4>; diff --git a/drivers/thermal/ti-soc-thermal/omap3-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap3-thermal-data.c index 8470225..3ee3434 100644 --- a/drivers/thermal/ti-soc-thermal/omap3-thermal-data.c +++ b/drivers/thermal/ti-soc-thermal/omap3-thermal-data.c @@ -101,3 +101,76 @@ const struct ti_bandgap_data omap34xx_data = { }, .sensor_count = 1, }; + +/* + * OMAP36XX has one instance of thermal sensor for MPU + * need to describe the individual bit fields + */ +static struct temp_sensor_registers +omap36xx_mpu_temp_sensor_registers = { + .temp_sensor_ctrl = 0, + .bgap_soc_mask = BIT(9), + .bgap_eocz_mask = BIT(8), + .bgap_dtemp_mask = 0xFF, + + .bgap_mode_ctrl = 0, + .mode_ctrl_mask = BIT(10), +}; + +/* Thresholds and limits for OMAP36XX MPU temperature sensor */ +static struct temp_sensor_data omap36xx_mpu_temp_sensor_data = { + .min_freq = 32768, + .max_freq = 32768, + .max_temp = 125000, + .min_temp = -40000, + .hyst_val = 5000, +}; + +/* + * Temperature values in milli degree celsius + */ +static const int +omap36xx_adc_to_temp[128] = { + -40000, -40000, -40000, -40000, -40000, -40000, -40000, -40000, + -40000, -40000, -40000, -40000, -40000, -38000, -35000, -34000, + -32000, -30000, -28000, -26000, -24000, -22000, -20000, -18500, + -17000, -15000, -13500, -12000, -10000, -8000, -6500, -5000, -3500, + -1500, 0, 2000, 3500, 5000, 6500, 8500, 10000, 12000, 13500, + 15000, 17000, 19000, 21000, 23000, 25000, 27000, 28500, 30000, + 32000, 33500, 35000, 37000, 38500, 40000, 42000, 43500, 45000, + 47000, 48500, 50000, 52000, 53500, 55000, 57000, 58500, 60000, + 62000, 64000, 66000, 68000, 70000, 71500, 73500, 75000, 77000, + 78500, 80000, 82000, 83500, 85000, 87000, 88500, 90000, 92000, + 93500, 95000, 97000, 98500, 100000, 102000, 103500, 105000, 107000, + 109000, 111000, 113000, 115000, 117000, 118500, 120000, 122000, + 123500, 125000, 125000, 125000, 125000, 125000, 125000, 125000, + 125000, 125000, 125000, 125000, 125000, 125000, 125000, 125000, + 125000, 125000, 125000, 125000, 125000, 125000, 125000 +}; + +/* OMAP36XX data */ +const struct ti_bandgap_data omap36xx_data = { + .features = TI_BANDGAP_FEATURE_CLK_CTRL | TI_BANDGAP_FEATURE_UNRELIABLE, + .fclock_name = "ts_fck", + .div_ck_name = "ts_fck", + .conv_table = omap36xx_adc_to_temp, + .adc_start_val = 0, + .adc_end_val = 127, + .expose_sensor = ti_thermal_expose_sensor, + .remove_sensor = ti_thermal_remove_sensor, + + .sensors = { + { + .registers = &omap36xx_mpu_temp_sensor_registers, + .ts_data = &omap36xx_mpu_temp_sensor_data, + .domain = "cpu", + .slope = 0, + .constant = 20000, + .slope_pcb = 0, + .constant_pcb = 20000, + .register_cooling = NULL, + .unregister_cooling = NULL, + }, + }, + .sensor_count = 1, +}; diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c index 9f9ed72..1e34a1e 100644 --- a/drivers/thermal/ti-soc-thermal/ti-bandgap.c +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c @@ -1588,6 +1588,10 @@ static const struct of_device_id of_ti_bandgap_match[] = { .compatible = "ti,omap34xx-bandgap", .data = (void *)&omap34xx_data, }, + { + .compatible = "ti,omap36xx-bandgap", + .data = (void *)&omap36xx_data, + }, #endif #ifdef CONFIG_OMAP4_THERMAL { diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.h b/drivers/thermal/ti-soc-thermal/ti-bandgap.h index 045f642..fe0adb8 100644 --- a/drivers/thermal/ti-soc-thermal/ti-bandgap.h +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.h @@ -395,8 +395,10 @@ int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend); #ifdef CONFIG_OMAP3_THERMAL extern const struct ti_bandgap_data omap34xx_data; +extern const struct ti_bandgap_data omap36xx_data; #else #define omap34xx_data NULL +#define omap36xx_data NULL #endif #ifdef CONFIG_OMAP4_THERMAL -- cgit v0.10.2 From ddfe4d0cce7828d79f3e3762c664342658c3f254 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Wed, 30 Sep 2015 12:06:36 +0530 Subject: dmaengine: edma: remove redundant conditions in edma_callback, driver was doing redundant check for desc, so remove that Reported-by: David Binderman Signed-off-by: Vinod Koul diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c index 3e5d4f1..558b0b4 100644 --- a/drivers/dma/edma.c +++ b/drivers/dma/edma.c @@ -726,7 +726,7 @@ static void edma_callback(unsigned ch_num, u16 ch_status, void *data) edesc = echan->edesc; /* Pause the channel for non-cyclic */ - if (!edesc || (edesc && !edesc->cyclic)) + if (!edesc || !edesc->cyclic) edma_pause(echan->ch_num); switch (ch_status) { -- cgit v0.10.2 From aff1e0cee36ab679552846a18d15dcb6d2e3fc4c Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Fri, 4 Sep 2015 16:12:30 +0300 Subject: dmaengine: acpi: Use ACPI_COMPANION() instead of acpi_bus_get_device() Get pointer to the struct acpi_device by using ACPI_COMPANION() macro. This is more efficient than using ACPI_HANDLE() and acpi_bus_get_device(). Signed-off-by: Jarkko Nikula Acked-by: Rafael J. Wysocki Signed-off-by: Vinod Koul diff --git a/drivers/dma/acpi-dma.c b/drivers/dma/acpi-dma.c index 5a63564..0425743 100644 --- a/drivers/dma/acpi-dma.c +++ b/drivers/dma/acpi-dma.c @@ -160,10 +160,8 @@ int acpi_dma_controller_register(struct device *dev, return -EINVAL; /* Check if the device was enumerated by ACPI */ - if (!ACPI_HANDLE(dev)) - return -EINVAL; - - if (acpi_bus_get_device(ACPI_HANDLE(dev), &adev)) + adev = ACPI_COMPANION(dev); + if (!adev) return -EINVAL; adma = kzalloc(sizeof(*adma), GFP_KERNEL); @@ -358,10 +356,11 @@ struct dma_chan *acpi_dma_request_slave_chan_by_index(struct device *dev, int found; /* Check if the device was enumerated by ACPI */ - if (!dev || !ACPI_HANDLE(dev)) + if (!dev) return ERR_PTR(-ENODEV); - if (acpi_bus_get_device(ACPI_HANDLE(dev), &adev)) + adev = ACPI_COMPANION(dev); + if (!adev) return ERR_PTR(-ENODEV); memset(&pdata, 0, sizeof(pdata)); -- cgit v0.10.2 From 6c6000c2ccfe69e5d17a2fba91954ce1e6f7df01 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 30 Sep 2015 15:53:55 +0900 Subject: ARM: dts: Add Exynos5250 Snow Rev5+ support on exynos5250-snow-rev5 There are 2 revisions of the Exynos5250 Snow Chromebook that were shipped: Rev4 and Rev5. The only difference between these 2 revisions is the codec, Rev4 has a max98095 codec while Rev5 has a max98090. Mainline only supports Rev4 so this patch moves the common device nodes to a DTSI file and adds a DTS for the Exynos5250 Snow Rev5. The Snow Rev5 DTS is based on the DTS found in the ChromiumOS 3.8 tree. Signed-off-by: Javier Martinez Canillas Tested-by: Mauro Carvalho Chehab Reviewed-by: Douglas Anderson Signed-off-by: Kukjin Kim diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 3d27fe3..bc6649d 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -115,6 +115,7 @@ dtb-$(CONFIG_ARCH_EXYNOS5) += \ exynos5250-arndale.dtb \ exynos5250-smdk5250.dtb \ exynos5250-snow.dtb \ + exynos5250-snow-rev5.dtb \ exynos5250-spring.dtb \ exynos5260-xyref5260.dtb \ exynos5410-smdk5410.dtb \ diff --git a/arch/arm/boot/dts/exynos5250-snow-common.dtsi b/arch/arm/boot/dts/exynos5250-snow-common.dtsi new file mode 100644 index 0000000..0a7f408 --- /dev/null +++ b/arch/arm/boot/dts/exynos5250-snow-common.dtsi @@ -0,0 +1,684 @@ +/* + * Google Snow board device tree source + * + * Copyright (c) 2012 Google, Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include "exynos5250.dtsi" + +/ { + aliases { + i2c104 = &i2c_104; + }; + + memory { + reg = <0x40000000 0x80000000>; + }; + + chosen { + bootargs = "console=tty1"; + stdout-path = "serial3:115200n8"; + }; + + gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&power_key_irq &lid_irq>; + + power { + label = "Power"; + gpios = <&gpx1 3 GPIO_ACTIVE_LOW>; + linux,code = ; + gpio-key,wakeup; + }; + + lid-switch { + label = "Lid"; + gpios = <&gpx3 5 GPIO_ACTIVE_LOW>; + linux,input-type = <5>; /* EV_SW */ + linux,code = <0>; /* SW_LID */ + debounce-interval = <1>; + gpio-key,wakeup; + }; + }; + + vbat: vbat-fixed-regulator { + compatible = "regulator-fixed"; + regulator-name = "vbat-supply"; + regulator-boot-on; + }; + + i2c-arbitrator { + compatible = "i2c-arb-gpio-challenge"; + #address-cells = <1>; + #size-cells = <0>; + + i2c-parent = <&{/i2c@12CA0000}>; + + our-claim-gpio = <&gpf0 3 GPIO_ACTIVE_LOW>; + their-claim-gpios = <&gpe0 4 GPIO_ACTIVE_LOW>; + slew-delay-us = <10>; + wait-retry-us = <3000>; + wait-free-us = <50000>; + + pinctrl-names = "default"; + pinctrl-0 = <&arb_our_claim &arb_their_claim>; + + /* Use ID 104 as a hint that we're on physical bus 4 */ + i2c_104: i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + battery: sbs-battery@b { + compatible = "sbs,sbs-battery"; + reg = <0xb>; + sbs,poll-retry-count = <1>; + }; + + cros_ec: embedded-controller { + compatible = "google,cros-ec-i2c"; + reg = <0x1e>; + interrupts = <6 IRQ_TYPE_NONE>; + interrupt-parent = <&gpx1>; + pinctrl-names = "default"; + pinctrl-0 = <&ec_irq>; + wakeup-source; + }; + + power-regulator { + compatible = "ti,tps65090"; + reg = <0x48>; + + /* + * Config irq to disable internal pulls + * even though we run in polling mode. + */ + pinctrl-names = "default"; + pinctrl-0 = <&tps65090_irq>; + + vsys1-supply = <&vbat>; + vsys2-supply = <&vbat>; + vsys3-supply = <&vbat>; + infet1-supply = <&vbat>; + infet2-supply = <&vbat>; + infet3-supply = <&vbat>; + infet4-supply = <&vbat>; + infet5-supply = <&vbat>; + infet6-supply = <&vbat>; + infet7-supply = <&vbat>; + vsys-l1-supply = <&vbat>; + vsys-l2-supply = <&vbat>; + + regulators { + dcdc1 { + ti,enable-ext-control; + }; + dcdc2 { + ti,enable-ext-control; + }; + dcdc3 { + ti,enable-ext-control; + }; + fet1: fet1 { + regulator-name = "vcd_led"; + ti,overcurrent-wait = <3>; + }; + tps65090_fet2: fet2 { + regulator-name = "video_mid"; + regulator-always-on; + ti,overcurrent-wait = <3>; + }; + fet3 { + regulator-name = "wwan_r"; + regulator-always-on; + ti,overcurrent-wait = <3>; + }; + fet4 { + regulator-name = "sdcard"; + ti,overcurrent-wait = <3>; + }; + fet5 { + regulator-name = "camout"; + regulator-always-on; + ti,overcurrent-wait = <3>; + }; + fet6: fet6 { + regulator-name = "lcd_vdd"; + ti,overcurrent-wait = <3>; + }; + tps65090_fet7: fet7 { + regulator-name = "video_mid_1a"; + regulator-always-on; + ti,overcurrent-wait = <3>; + }; + ldo1 { + }; + ldo2 { + }; + }; + + charger { + compatible = "ti,tps65090-charger"; + }; + }; + }; + }; + + sound { + samsung,i2s-controller = <&i2s0>; + }; + + usb3_vbus_reg: regulator-usb3 { + compatible = "regulator-fixed"; + regulator-name = "P5.0V_USB3CON"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpx2 7 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&usb3_vbus_en>; + enable-active-high; + }; + + fixed-rate-clocks { + xxti { + compatible = "samsung,clock-xxti"; + clock-frequency = <24000000>; + }; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm 0 1000000 0>; + brightness-levels = <0 100 500 1000 1500 2000 2500 2800>; + default-brightness-level = <7>; + enable-gpios = <&gpx3 0 GPIO_ACTIVE_HIGH>; + power-supply = <&fet1>; + pinctrl-0 = <&pwm0_out>; + pinctrl-names = "default"; + }; + + panel: panel { + compatible = "auo,b116xw03"; + power-supply = <&fet6>; + backlight = <&backlight>; + + port { + panel_in: endpoint { + remote-endpoint = <&bridge_out>; + }; + }; + }; + + mmc3_pwrseq: mmc3_pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&gpx0 2 GPIO_ACTIVE_LOW>, /* WIFI_RSTn */ + <&gpx0 1 GPIO_ACTIVE_LOW>; /* WIFI_EN */ + clocks = <&max77686 MAX77686_CLK_PMIC>; + clock-names = "ext_clock"; + }; +}; + +&cpu0 { + cpu0-supply = <&buck2_reg>; +}; + +&dp { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&dp_hpd>; + samsung,color-space = <0>; + samsung,dynamic-range = <0>; + samsung,ycbcr-coeff = <0>; + samsung,color-depth = <1>; + samsung,link-rate = <0x0a>; + samsung,lane-count = <2>; + samsung,hpd-gpio = <&gpx0 7 GPIO_ACTIVE_HIGH>; + + ports { + port@0 { + dp_out: endpoint { + remote-endpoint = <&bridge_in>; + }; + }; + }; +}; + +&ehci { + samsung,vbus-gpio = <&gpx1 1 GPIO_ACTIVE_HIGH>; +}; + +&fimd { + status = "okay"; + samsung,invert-vclk; +}; + +&hdmi { + hpd-gpio = <&gpx3 7 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_hpd_irq>; + phy = <&hdmiphy>; + ddc = <&i2c_2>; + hdmi-en-supply = <&tps65090_fet7>; + vdd-supply = <&ldo8_reg>; + vdd_osc-supply = <&ldo10_reg>; + vdd_pll-supply = <&ldo8_reg>; +}; + +&i2c_0 { + status = "okay"; + samsung,i2c-sda-delay = <100>; + samsung,i2c-max-bus-freq = <378000>; + + max77686: max77686@09 { + compatible = "maxim,max77686"; + interrupt-parent = <&gpx3>; + interrupts = <2 IRQ_TYPE_NONE>; + pinctrl-names = "default"; + pinctrl-0 = <&max77686_irq>; + wakeup-source; + reg = <0x09>; + #clock-cells = <1>; + + voltage-regulators { + ldo1_reg: LDO1 { + regulator-name = "P1.0V_LDO_OUT1"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + }; + + ldo2_reg: LDO2 { + regulator-name = "P1.8V_LDO_OUT2"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + ldo3_reg: LDO3 { + regulator-name = "P1.8V_LDO_OUT3"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + ldo7_reg: LDO7 { + regulator-name = "P1.1V_LDO_OUT7"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + }; + + ldo8_reg: LDO8 { + regulator-name = "P1.0V_LDO_OUT8"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + }; + + ldo10_reg: LDO10 { + regulator-name = "P1.8V_LDO_OUT10"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + ldo12_reg: LDO12 { + regulator-name = "P3.0V_LDO_OUT12"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + }; + + ldo14_reg: LDO14 { + regulator-name = "P1.8V_LDO_OUT14"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + ldo15_reg: LDO15 { + regulator-name = "P1.0V_LDO_OUT15"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + }; + + ldo16_reg: LDO16 { + regulator-name = "P1.8V_LDO_OUT16"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + buck1_reg: BUCK1 { + regulator-name = "vdd_mif"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1300000>; + regulator-always-on; + regulator-boot-on; + }; + + buck2_reg: BUCK2 { + regulator-name = "vdd_arm"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-boot-on; + }; + + buck3_reg: BUCK3 { + regulator-name = "vdd_int"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + regulator-boot-on; + }; + + buck4_reg: BUCK4 { + regulator-name = "vdd_g3d"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1300000>; + regulator-always-on; + regulator-boot-on; + }; + + buck5_reg: BUCK5 { + regulator-name = "P1.8V_BUCK_OUT5"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + buck6_reg: BUCK6 { + regulator-name = "P1.35V_BUCK_OUT6"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + }; + + buck7_reg: BUCK7 { + regulator-name = "P2.0V_BUCK_OUT7"; + regulator-min-microvolt = <2000000>; + regulator-max-microvolt = <2000000>; + regulator-always-on; + }; + + buck8_reg: BUCK8 { + regulator-name = "P2.85V_BUCK_OUT8"; + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + regulator-always-on; + }; + }; + }; +}; + +&i2c_1 { + status = "okay"; + samsung,i2c-sda-delay = <100>; + samsung,i2c-max-bus-freq = <378000>; + + trackpad { + reg = <0x67>; + compatible = "cypress,cyapa"; + interrupts = <2 IRQ_TYPE_NONE>; + interrupt-parent = <&gpx1>; + wakeup-source; + }; +}; + +/* + * Disabled pullups since external part has its own pullups and + * double-pulling gets us out of spec in some cases. + */ +&i2c2_bus { + samsung,pin-pud = <0>; +}; + +&i2c_2 { + status = "okay"; + samsung,i2c-sda-delay = <100>; + samsung,i2c-max-bus-freq = <66000>; + + hdmiddc@50 { + compatible = "samsung,exynos4210-hdmiddc"; + reg = <0x50>; + }; +}; + +&i2c_3 { + status = "okay"; + samsung,i2c-sda-delay = <100>; + samsung,i2c-max-bus-freq = <66000>; +}; + +&i2c_4 { + status = "okay"; + samsung,i2c-sda-delay = <100>; + samsung,i2c-max-bus-freq = <66000>; +}; + +&i2c_5 { + status = "okay"; + samsung,i2c-sda-delay = <100>; + samsung,i2c-max-bus-freq = <66000>; +}; + +&i2c_7 { + status = "okay"; + samsung,i2c-sda-delay = <100>; + samsung,i2c-max-bus-freq = <66000>; + + ptn3460: lvds-bridge@20 { + compatible = "nxp,ptn3460"; + reg = <0x20>; + powerdown-gpios = <&gpy2 5 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpx1 5 GPIO_ACTIVE_HIGH>; + edid-emulation = <5>; + + ports { + port@0 { + bridge_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; + + port@1 { + bridge_in: endpoint { + remote-endpoint = <&dp_out>; + }; + }; + }; + }; +}; + +&i2c_8 { + status = "okay"; + samsung,i2c-sda-delay = <100>; + samsung,i2c-max-bus-freq = <378000>; + + hdmiphy: hdmiphy@38 { + compatible = "samsung,exynos4212-hdmiphy"; + reg = <0x38>; + }; +}; + +&i2s0 { + status = "okay"; +}; + +&mmc_0 { + status = "okay"; + num-slots = <1>; + broken-cd; + card-detect-delay = <200>; + samsung,dw-mshc-ciu-div = <3>; + samsung,dw-mshc-sdr-timing = <2 3>; + samsung,dw-mshc-ddr-timing = <1 2>; + pinctrl-names = "default"; + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_cd &sd0_bus4 &sd0_bus8>; + bus-width = <8>; + cap-mmc-highspeed; +}; + +&mmc_2 { + status = "okay"; + num-slots = <1>; + card-detect-delay = <200>; + samsung,dw-mshc-ciu-div = <3>; + samsung,dw-mshc-sdr-timing = <2 3>; + samsung,dw-mshc-ddr-timing = <1 2>; + pinctrl-names = "default"; + pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>; + bus-width = <4>; + wp-gpios = <&gpc2 1 GPIO_ACTIVE_HIGH>; + cap-sd-highspeed; +}; + +/* + * On Snow we've got SIP WiFi and so can keep drive strengths low to + * reduce EMI. + */ +&mmc_3 { + status = "okay"; + num-slots = <1>; + broken-cd; + cap-sdio-irq; + keep-power-in-suspend; + card-detect-delay = <200>; + samsung,dw-mshc-ciu-div = <3>; + samsung,dw-mshc-sdr-timing = <2 3>; + samsung,dw-mshc-ddr-timing = <1 2>; + pinctrl-names = "default"; + pinctrl-0 = <&sd3_clk &sd3_cmd &sd3_bus4 &wifi_en &wifi_rst>; + bus-width = <4>; + cap-sd-highspeed; + mmc-pwrseq = <&mmc3_pwrseq>; +}; + +&pinctrl_0 { + wifi_en: wifi-en { + samsung,pins = "gpx0-1"; + samsung,pin-function = <1>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + wifi_rst: wifi-rst { + samsung,pins = "gpx0-2"; + samsung,pin-function = <1>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + power_key_irq: power-key-irq { + samsung,pins = "gpx1-3"; + samsung,pin-function = <0xf>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + ec_irq: ec-irq { + samsung,pins = "gpx1-6"; + samsung,pin-function = <0>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + tps65090_irq: tps65090-irq { + samsung,pins = "gpx2-6"; + samsung,pin-function = <0>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + usb3_vbus_en: usb3-vbus-en { + samsung,pins = "gpx2-7"; + samsung,pin-function = <1>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + max77686_irq: max77686-irq { + samsung,pins = "gpx3-2"; + samsung,pin-function = <0>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + lid_irq: lid-irq { + samsung,pins = "gpx3-5"; + samsung,pin-function = <0xf>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + hdmi_hpd_irq: hdmi-hpd-irq { + samsung,pins = "gpx3-7"; + samsung,pin-function = <0>; + samsung,pin-pud = <1>; + samsung,pin-drv = <0>; + }; +}; + +&pinctrl_1 { + arb_their_claim: arb-their-claim { + samsung,pins = "gpe0-4"; + samsung,pin-function = <0>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + arb_our_claim: arb-our-claim { + samsung,pins = "gpf0-3"; + samsung,pin-function = <1>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; +}; + +&rtc { + status = "okay"; + clocks = <&clock CLK_RTC>, <&max77686 MAX77686_CLK_AP>; + clock-names = "rtc", "rtc_src"; +}; + +&sd3_bus4 { + samsung,pin-drv = <0>; +}; + +&sd3_clk { + samsung,pin-drv = <0>; +}; + +&sd3_cmd { + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; +}; + +&spi_1 { + status = "okay"; + samsung,spi-src-clk = <0>; + num-cs = <1>; + cs-gpios = <&gpa2 5 GPIO_ACTIVE_HIGH>; +}; + +&usbdrd_dwc3 { + dr_mode = "host"; +}; + +&usbdrd_phy { + vbus-supply = <&usb3_vbus_reg>; +}; + +#include "cros-ec-keyboard.dtsi" diff --git a/arch/arm/boot/dts/exynos5250-snow-rev5.dts b/arch/arm/boot/dts/exynos5250-snow-rev5.dts new file mode 100644 index 0000000..f811dc8 --- /dev/null +++ b/arch/arm/boot/dts/exynos5250-snow-rev5.dts @@ -0,0 +1,47 @@ +/* + * Google Snow Rev 5+ board device tree source + * + * Copyright (c) 2012 Google, Inc + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/dts-v1/; +#include "exynos5250-snow-common.dtsi" + +/ { + model = "Google Snow Rev 5+"; + compatible = "google,snow-rev5", "samsung,exynos5250", + "samsung,exynos5"; + + sound { + compatible = "google,snow-audio-max98090"; + + samsung,model = "Snow-I2S-MAX98090"; + samsung,audio-codec = <&max98090>; + }; +}; + +&i2c_7 { + max98090: codec@10 { + compatible = "maxim,max98090"; + reg = <0x10>; + interrupts = <4 IRQ_TYPE_NONE>; + interrupt-parent = <&gpx0>; + pinctrl-names = "default"; + pinctrl-0 = <&max98090_irq>; + }; +}; + +&pinctrl_0 { + max98090_irq: max98090-irq { + samsung,pins = "gpx0-4"; + samsung,pin-function = <0>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; +}; diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/exynos5250-snow.dts index 0720caa..995c7ce 100644 --- a/arch/arm/boot/dts/exynos5250-snow.dts +++ b/arch/arm/boot/dts/exynos5250-snow.dts @@ -9,698 +9,35 @@ */ /dts-v1/; -#include -#include -#include -#include -#include "exynos5250.dtsi" +#include "exynos5250-snow-common.dtsi" / { model = "Google Snow"; - compatible = "google,snow", "samsung,exynos5250", "samsung,exynos5"; - - aliases { - i2c104 = &i2c_104; - }; - - memory { - reg = <0x40000000 0x80000000>; - }; - - chosen { - bootargs = "console=tty1"; - stdout-path = "serial3:115200n8"; - }; - - gpio-keys { - compatible = "gpio-keys"; - pinctrl-names = "default"; - pinctrl-0 = <&power_key_irq &lid_irq>; - - power { - label = "Power"; - gpios = <&gpx1 3 GPIO_ACTIVE_LOW>; - linux,code = ; - gpio-key,wakeup; - }; - - lid-switch { - label = "Lid"; - gpios = <&gpx3 5 GPIO_ACTIVE_LOW>; - linux,input-type = <5>; /* EV_SW */ - linux,code = <0>; /* SW_LID */ - debounce-interval = <1>; - gpio-key,wakeup; - }; - }; - - vbat: vbat-fixed-regulator { - compatible = "regulator-fixed"; - regulator-name = "vbat-supply"; - regulator-boot-on; - }; - - i2c-arbitrator { - compatible = "i2c-arb-gpio-challenge"; - #address-cells = <1>; - #size-cells = <0>; - - i2c-parent = <&{/i2c@12CA0000}>; - - our-claim-gpio = <&gpf0 3 GPIO_ACTIVE_LOW>; - their-claim-gpios = <&gpe0 4 GPIO_ACTIVE_LOW>; - slew-delay-us = <10>; - wait-retry-us = <3000>; - wait-free-us = <50000>; - - pinctrl-names = "default"; - pinctrl-0 = <&arb_our_claim &arb_their_claim>; - - /* Use ID 104 as a hint that we're on physical bus 4 */ - i2c_104: i2c@0 { - reg = <0>; - #address-cells = <1>; - #size-cells = <0>; - - battery: sbs-battery@b { - compatible = "sbs,sbs-battery"; - reg = <0xb>; - sbs,poll-retry-count = <1>; - }; - - cros_ec: embedded-controller { - compatible = "google,cros-ec-i2c"; - reg = <0x1e>; - interrupts = <6 IRQ_TYPE_NONE>; - interrupt-parent = <&gpx1>; - pinctrl-names = "default"; - pinctrl-0 = <&ec_irq>; - wakeup-source; - }; - - power-regulator { - compatible = "ti,tps65090"; - reg = <0x48>; - - /* - * Config irq to disable internal pulls - * even though we run in polling mode. - */ - pinctrl-names = "default"; - pinctrl-0 = <&tps65090_irq>; - - vsys1-supply = <&vbat>; - vsys2-supply = <&vbat>; - vsys3-supply = <&vbat>; - infet1-supply = <&vbat>; - infet2-supply = <&vbat>; - infet3-supply = <&vbat>; - infet4-supply = <&vbat>; - infet5-supply = <&vbat>; - infet6-supply = <&vbat>; - infet7-supply = <&vbat>; - vsys-l1-supply = <&vbat>; - vsys-l2-supply = <&vbat>; - - regulators { - dcdc1 { - ti,enable-ext-control; - }; - dcdc2 { - ti,enable-ext-control; - }; - dcdc3 { - ti,enable-ext-control; - }; - fet1: fet1 { - regulator-name = "vcd_led"; - ti,overcurrent-wait = <3>; - }; - tps65090_fet2: fet2 { - regulator-name = "video_mid"; - regulator-always-on; - ti,overcurrent-wait = <3>; - }; - fet3 { - regulator-name = "wwan_r"; - regulator-always-on; - ti,overcurrent-wait = <3>; - }; - fet4 { - regulator-name = "sdcard"; - ti,overcurrent-wait = <3>; - }; - fet5 { - regulator-name = "camout"; - regulator-always-on; - ti,overcurrent-wait = <3>; - }; - fet6: fet6 { - regulator-name = "lcd_vdd"; - ti,overcurrent-wait = <3>; - }; - tps65090_fet7: fet7 { - regulator-name = "video_mid_1a"; - regulator-always-on; - ti,overcurrent-wait = <3>; - }; - ldo1 { - }; - ldo2 { - }; - }; - - charger { - compatible = "ti,tps65090-charger"; - }; - }; - }; - }; + compatible = "google,snow-rev4", "google,snow", "samsung,exynos5250", + "samsung,exynos5"; sound { compatible = "google,snow-audio-max98095"; samsung,model = "Snow-I2S-MAX98095"; - samsung,i2s-controller = <&i2s0>; samsung,audio-codec = <&max98095>; }; - - usb3_vbus_reg: regulator-usb3 { - compatible = "regulator-fixed"; - regulator-name = "P5.0V_USB3CON"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - gpio = <&gpx2 7 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&usb3_vbus_en>; - enable-active-high; - }; - - fixed-rate-clocks { - xxti { - compatible = "samsung,clock-xxti"; - clock-frequency = <24000000>; - }; - }; - - backlight: backlight { - compatible = "pwm-backlight"; - pwms = <&pwm 0 1000000 0>; - brightness-levels = <0 100 500 1000 1500 2000 2500 2800>; - default-brightness-level = <7>; - enable-gpios = <&gpx3 0 GPIO_ACTIVE_HIGH>; - power-supply = <&fet1>; - pinctrl-0 = <&pwm0_out>; - pinctrl-names = "default"; - }; - - panel: panel { - compatible = "auo,b116xw03"; - power-supply = <&fet6>; - backlight = <&backlight>; - - port { - panel_in: endpoint { - remote-endpoint = <&bridge_out>; - }; - }; - }; - - mmc3_pwrseq: mmc3_pwrseq { - compatible = "mmc-pwrseq-simple"; - reset-gpios = <&gpx0 2 GPIO_ACTIVE_LOW>, /* WIFI_RSTn */ - <&gpx0 1 GPIO_ACTIVE_LOW>; /* WIFI_EN */ - clocks = <&max77686 MAX77686_CLK_PMIC>; - clock-names = "ext_clock"; - }; -}; - -&cpu0 { - cpu0-supply = <&buck2_reg>; -}; - -&dp { - status = "okay"; - pinctrl-names = "default"; - pinctrl-0 = <&dp_hpd>; - samsung,color-space = <0>; - samsung,dynamic-range = <0>; - samsung,ycbcr-coeff = <0>; - samsung,color-depth = <1>; - samsung,link-rate = <0x0a>; - samsung,lane-count = <2>; - samsung,hpd-gpio = <&gpx0 7 GPIO_ACTIVE_HIGH>; - - ports { - port@0 { - dp_out: endpoint { - remote-endpoint = <&bridge_in>; - }; - }; - }; -}; - -&ehci { - samsung,vbus-gpio = <&gpx1 1 GPIO_ACTIVE_HIGH>; -}; - -&fimd { - status = "okay"; - samsung,invert-vclk; -}; - -&hdmi { - hpd-gpio = <&gpx3 7 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&hdmi_hpd_irq>; - phy = <&hdmiphy>; - ddc = <&i2c_2>; - hdmi-en-supply = <&tps65090_fet7>; - vdd-supply = <&ldo8_reg>; - vdd_osc-supply = <&ldo10_reg>; - vdd_pll-supply = <&ldo8_reg>; -}; - -&i2c_0 { - status = "okay"; - samsung,i2c-sda-delay = <100>; - samsung,i2c-max-bus-freq = <378000>; - - max77686: max77686@09 { - compatible = "maxim,max77686"; - interrupt-parent = <&gpx3>; - interrupts = <2 IRQ_TYPE_NONE>; - pinctrl-names = "default"; - pinctrl-0 = <&max77686_irq>; - wakeup-source; - reg = <0x09>; - #clock-cells = <1>; - - voltage-regulators { - ldo1_reg: LDO1 { - regulator-name = "P1.0V_LDO_OUT1"; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1000000>; - regulator-always-on; - }; - - ldo2_reg: LDO2 { - regulator-name = "P1.8V_LDO_OUT2"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-always-on; - }; - - ldo3_reg: LDO3 { - regulator-name = "P1.8V_LDO_OUT3"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-always-on; - }; - - ldo7_reg: LDO7 { - regulator-name = "P1.1V_LDO_OUT7"; - regulator-min-microvolt = <1100000>; - regulator-max-microvolt = <1100000>; - regulator-always-on; - }; - - ldo8_reg: LDO8 { - regulator-name = "P1.0V_LDO_OUT8"; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1000000>; - regulator-always-on; - }; - - ldo10_reg: LDO10 { - regulator-name = "P1.8V_LDO_OUT10"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-always-on; - }; - - ldo12_reg: LDO12 { - regulator-name = "P3.0V_LDO_OUT12"; - regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <3000000>; - regulator-always-on; - }; - - ldo14_reg: LDO14 { - regulator-name = "P1.8V_LDO_OUT14"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-always-on; - }; - - ldo15_reg: LDO15 { - regulator-name = "P1.0V_LDO_OUT15"; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1000000>; - regulator-always-on; - }; - - ldo16_reg: LDO16 { - regulator-name = "P1.8V_LDO_OUT16"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-always-on; - }; - - buck1_reg: BUCK1 { - regulator-name = "vdd_mif"; - regulator-min-microvolt = <950000>; - regulator-max-microvolt = <1300000>; - regulator-always-on; - regulator-boot-on; - }; - - buck2_reg: BUCK2 { - regulator-name = "vdd_arm"; - regulator-min-microvolt = <850000>; - regulator-max-microvolt = <1350000>; - regulator-always-on; - regulator-boot-on; - }; - - buck3_reg: BUCK3 { - regulator-name = "vdd_int"; - regulator-min-microvolt = <900000>; - regulator-max-microvolt = <1200000>; - regulator-always-on; - regulator-boot-on; - }; - - buck4_reg: BUCK4 { - regulator-name = "vdd_g3d"; - regulator-min-microvolt = <850000>; - regulator-max-microvolt = <1300000>; - regulator-always-on; - regulator-boot-on; - }; - - buck5_reg: BUCK5 { - regulator-name = "P1.8V_BUCK_OUT5"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-always-on; - regulator-boot-on; - }; - - buck6_reg: BUCK6 { - regulator-name = "P1.35V_BUCK_OUT6"; - regulator-min-microvolt = <1350000>; - regulator-max-microvolt = <1350000>; - regulator-always-on; - }; - - buck7_reg: BUCK7 { - regulator-name = "P2.0V_BUCK_OUT7"; - regulator-min-microvolt = <2000000>; - regulator-max-microvolt = <2000000>; - regulator-always-on; - }; - - buck8_reg: BUCK8 { - regulator-name = "P2.85V_BUCK_OUT8"; - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2850000>; - regulator-always-on; - }; - }; - }; -}; - -&i2c_1 { - status = "okay"; - samsung,i2c-sda-delay = <100>; - samsung,i2c-max-bus-freq = <378000>; - - trackpad { - reg = <0x67>; - compatible = "cypress,cyapa"; - interrupts = <2 IRQ_TYPE_NONE>; - interrupt-parent = <&gpx1>; - wakeup-source; - }; -}; - -/* - * Disabled pullups since external part has its own pullups and - * double-pulling gets us out of spec in some cases. - */ -&i2c2_bus { - samsung,pin-pud = <0>; -}; - -&i2c_2 { - status = "okay"; - samsung,i2c-sda-delay = <100>; - samsung,i2c-max-bus-freq = <66000>; - - hdmiddc@50 { - compatible = "samsung,exynos4210-hdmiddc"; - reg = <0x50>; - }; -}; - -&i2c_3 { - status = "okay"; - samsung,i2c-sda-delay = <100>; - samsung,i2c-max-bus-freq = <66000>; -}; - -&i2c_4 { - status = "okay"; - samsung,i2c-sda-delay = <100>; - samsung,i2c-max-bus-freq = <66000>; -}; - -&i2c_5 { - status = "okay"; - samsung,i2c-sda-delay = <100>; - samsung,i2c-max-bus-freq = <66000>; }; &i2c_7 { - status = "okay"; - samsung,i2c-sda-delay = <100>; - samsung,i2c-max-bus-freq = <66000>; - - ptn3460: lvds-bridge@20 { - compatible = "nxp,ptn3460"; - reg = <0x20>; - powerdown-gpios = <&gpy2 5 GPIO_ACTIVE_HIGH>; - reset-gpios = <&gpx1 5 GPIO_ACTIVE_HIGH>; - edid-emulation = <5>; - - ports { - port@0 { - bridge_out: endpoint { - remote-endpoint = <&panel_in>; - }; - }; - - port@1 { - bridge_in: endpoint { - remote-endpoint = <&dp_out>; - }; - }; - }; - }; - max98095: codec@11 { compatible = "maxim,max98095"; reg = <0x11>; - pinctrl-0 = <&max98095_en>; pinctrl-names = "default"; + pinctrl-0 = <&max98095_en>; }; }; -&i2c_8 { - status = "okay"; - samsung,i2c-sda-delay = <100>; - samsung,i2c-max-bus-freq = <378000>; - - hdmiphy: hdmiphy@38 { - compatible = "samsung,exynos4212-hdmiphy"; - reg = <0x38>; - }; -}; - -&i2s0 { - status = "okay"; -}; - -&mmc_0 { - status = "okay"; - num-slots = <1>; - broken-cd; - card-detect-delay = <200>; - samsung,dw-mshc-ciu-div = <3>; - samsung,dw-mshc-sdr-timing = <2 3>; - samsung,dw-mshc-ddr-timing = <1 2>; - pinctrl-names = "default"; - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_cd &sd0_bus4 &sd0_bus8>; - bus-width = <8>; - cap-mmc-highspeed; -}; - -&mmc_2 { - status = "okay"; - num-slots = <1>; - card-detect-delay = <200>; - samsung,dw-mshc-ciu-div = <3>; - samsung,dw-mshc-sdr-timing = <2 3>; - samsung,dw-mshc-ddr-timing = <1 2>; - pinctrl-names = "default"; - pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>; - bus-width = <4>; - wp-gpios = <&gpc2 1 GPIO_ACTIVE_HIGH>; - cap-sd-highspeed; -}; - -/* - * On Snow we've got SIP WiFi and so can keep drive strengths low to - * reduce EMI. - */ -&mmc_3 { - status = "okay"; - num-slots = <1>; - broken-cd; - cap-sdio-irq; - keep-power-in-suspend; - card-detect-delay = <200>; - samsung,dw-mshc-ciu-div = <3>; - samsung,dw-mshc-sdr-timing = <2 3>; - samsung,dw-mshc-ddr-timing = <1 2>; - pinctrl-names = "default"; - pinctrl-0 = <&sd3_clk &sd3_cmd &sd3_bus4 &wifi_en &wifi_rst>; - bus-width = <4>; - cap-sd-highspeed; - mmc-pwrseq = <&mmc3_pwrseq>; -}; - &pinctrl_0 { - wifi_en: wifi-en { - samsung,pins = "gpx0-1"; - samsung,pin-function = <1>; - samsung,pin-pud = <0>; - samsung,pin-drv = <0>; - }; - - wifi_rst: wifi-rst { - samsung,pins = "gpx0-2"; - samsung,pin-function = <1>; - samsung,pin-pud = <0>; - samsung,pin-drv = <0>; - }; - - power_key_irq: power-key-irq { - samsung,pins = "gpx1-3"; - samsung,pin-function = <0xf>; - samsung,pin-pud = <0>; - samsung,pin-drv = <0>; - }; - - ec_irq: ec-irq { - samsung,pins = "gpx1-6"; - samsung,pin-function = <0>; - samsung,pin-pud = <0>; - samsung,pin-drv = <0>; - }; - max98095_en: max98095-en { samsung,pins = "gpx1-7"; samsung,pin-function = <0>; samsung,pin-pud = <3>; samsung,pin-drv = <0>; }; - - tps65090_irq: tps65090-irq { - samsung,pins = "gpx2-6"; - samsung,pin-function = <0>; - samsung,pin-pud = <0>; - samsung,pin-drv = <0>; - }; - - usb3_vbus_en: usb3-vbus-en { - samsung,pins = "gpx2-7"; - samsung,pin-function = <1>; - samsung,pin-pud = <0>; - samsung,pin-drv = <0>; - }; - - max77686_irq: max77686-irq { - samsung,pins = "gpx3-2"; - samsung,pin-function = <0>; - samsung,pin-pud = <0>; - samsung,pin-drv = <0>; - }; - - lid_irq: lid-irq { - samsung,pins = "gpx3-5"; - samsung,pin-function = <0xf>; - samsung,pin-pud = <0>; - samsung,pin-drv = <0>; - }; - - hdmi_hpd_irq: hdmi-hpd-irq { - samsung,pins = "gpx3-7"; - samsung,pin-function = <0>; - samsung,pin-pud = <1>; - samsung,pin-drv = <0>; - }; -}; - -&pinctrl_1 { - arb_their_claim: arb-their-claim { - samsung,pins = "gpe0-4"; - samsung,pin-function = <0>; - samsung,pin-pud = <3>; - samsung,pin-drv = <0>; - }; - - arb_our_claim: arb-our-claim { - samsung,pins = "gpf0-3"; - samsung,pin-function = <1>; - samsung,pin-pud = <0>; - samsung,pin-drv = <0>; - }; }; - -&rtc { - status = "okay"; - clocks = <&clock CLK_RTC>, <&max77686 MAX77686_CLK_AP>; - clock-names = "rtc", "rtc_src"; -}; - -&sd3_bus4 { - samsung,pin-drv = <0>; -}; - -&sd3_clk { - samsung,pin-drv = <0>; -}; - -&sd3_cmd { - samsung,pin-pud = <3>; - samsung,pin-drv = <0>; -}; - -&spi_1 { - status = "okay"; - samsung,spi-src-clk = <0>; - num-cs = <1>; - cs-gpios = <&gpa2 5 GPIO_ACTIVE_HIGH>; -}; - -&usbdrd_dwc3 { - dr_mode = "host"; -}; - -&usbdrd_phy { - vbus-supply = <&usb3_vbus_reg>; -}; - -#include "cros-ec-keyboard.dtsi" -- cgit v0.10.2 From ec90631c8a6861cdd752148fe19c20f775df47e7 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Fri, 25 Sep 2015 00:14:13 +0200 Subject: fb_ddc: Allow I2C adapters without SCL read capability i2c-algo-bit allows I2C adapters without SCL read capability to work but fb_ddc_read fails to work on them. Fix fb_ddc_read to work with I2C adapters not capable of reading SCL. Signed-off-by: Ondrej Zary Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/fbdev/core/fb_ddc.c b/drivers/video/fbdev/core/fb_ddc.c index 94322cc..8bf5f2f 100644 --- a/drivers/video/fbdev/core/fb_ddc.c +++ b/drivers/video/fbdev/core/fb_ddc.c @@ -67,13 +67,17 @@ unsigned char *fb_ddc_read(struct i2c_adapter *adapter) msleep(13); algo_data->setscl(algo_data->data, 1); - for (j = 0; j < 5; j++) { - msleep(10); - if (algo_data->getscl(algo_data->data)) - break; + if (algo_data->getscl) { + for (j = 0; j < 5; j++) { + msleep(10); + if (algo_data->getscl(algo_data->data)) + break; + } + if (j == 5) + continue; + } else { + udelay(algo_data->udelay); } - if (j == 5) - continue; algo_data->setsda(algo_data->data, 0); msleep(15); @@ -89,10 +93,14 @@ unsigned char *fb_ddc_read(struct i2c_adapter *adapter) msleep(15); algo_data->setscl(algo_data->data, 1); - for (j = 0; j < 10; j++) { - msleep(10); - if (algo_data->getscl(algo_data->data)) - break; + if (algo_data->getscl) { + for (j = 0; j < 10; j++) { + msleep(10); + if (algo_data->getscl(algo_data->data)) + break; + } + } else { + udelay(algo_data->udelay); } algo_data->setsda(algo_data->data, 1); -- cgit v0.10.2 From 6a5e3bd0c8bc1025bb5092f54d5aea38216c665e Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Fri, 25 Sep 2015 00:14:14 +0200 Subject: tridentfb: Add DDC support Add DDC support for Trident cards. Tested on TGUI9440, TGUI9680, 3DImage 9750, Blade3D 9880 and Blade XP. Signed-off-by: Ondrej Zary Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index 8b1d371..5d67226 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -1666,6 +1666,8 @@ config FB_TRIDENT select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select FB_DDC + select FB_MODE_HELPERS ---help--- This is the frame buffer device driver for Trident PCI/AGP chipsets. Supported chipset families are TGUI 9440/96XX, 3DImage, Blade3D diff --git a/drivers/video/fbdev/tridentfb.c b/drivers/video/fbdev/tridentfb.c index 7ed9a22..e5c9b14 100644 --- a/drivers/video/fbdev/tridentfb.c +++ b/drivers/video/fbdev/tridentfb.c @@ -25,6 +25,9 @@ #include