[PATCH 7/9] drm/vc4: Add support for drawing 3D frames.
The user submission is basically a pointer to a command list and a pointer to uniforms. We copy those in to the kernel, validate and relocate them, and store the result in a GPU BO which we queue for execution. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/Makefile | 7 + drivers/gpu/drm/vc4/vc4_drv.c | 15 +- drivers/gpu/drm/vc4/vc4_drv.h | 192 +++ drivers/gpu/drm/vc4/vc4_gem.c | 640 ++ drivers/gpu/drm/vc4/vc4_irq.c | 210 drivers/gpu/drm/vc4/vc4_packet.h | 399 ++ drivers/gpu/drm/vc4/vc4_render_cl.c| 631 ++ drivers/gpu/drm/vc4/vc4_trace.h| 63 +++ drivers/gpu/drm/vc4/vc4_trace_points.c | 14 + drivers/gpu/drm/vc4/vc4_v3d.c | 37 ++ drivers/gpu/drm/vc4/vc4_validate.c | 955 + include/uapi/drm/vc4_drm.h | 141 + 12 files changed, 3303 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/vc4/vc4_gem.c create mode 100644 drivers/gpu/drm/vc4/vc4_irq.c create mode 100644 drivers/gpu/drm/vc4/vc4_packet.h create mode 100644 drivers/gpu/drm/vc4/vc4_render_cl.c create mode 100644 drivers/gpu/drm/vc4/vc4_trace.h create mode 100644 drivers/gpu/drm/vc4/vc4_trace_points.c create mode 100644 drivers/gpu/drm/vc4/vc4_validate.c diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile index e87a6f2..4c6a99f 100644 --- a/drivers/gpu/drm/vc4/Makefile +++ b/drivers/gpu/drm/vc4/Makefile @@ -8,12 +8,19 @@ vc4-y := \ vc4_crtc.o \ vc4_drv.o \ vc4_kms.o \ + vc4_gem.o \ vc4_hdmi.o \ vc4_hvs.o \ + vc4_irq.o \ vc4_plane.o \ + vc4_render_cl.o \ + vc4_trace_points.o \ vc4_v3d.o \ + vc4_validate.o \ vc4_validate_shaders.o vc4-$(CONFIG_DEBUG_FS) += vc4_debugfs.o obj-$(CONFIG_DRM_VC4) += vc4.o + +CFLAGS_vc4_trace_points.o := -I$(src) diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index db58d74..2cfee59 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -74,6 +74,9 @@ static const struct file_operations vc4_drm_fops = { }; static const struct drm_ioctl_desc vc4_drm_ioctls[] = { + DRM_IOCTL_DEF_DRV(VC4_SUBMIT_CL, vc4_submit_cl_ioctl, 0), + DRM_IOCTL_DEF_DRV(VC4_WAIT_SEQNO, vc4_wait_seqno_ioctl, 0), + DRM_IOCTL_DEF_DRV(VC4_WAIT_BO, vc4_wait_bo_ioctl, 0), DRM_IOCTL_DEF_DRV(VC4_CREATE_BO, vc4_create_bo_ioctl, 0), DRM_IOCTL_DEF_DRV(VC4_MMAP_BO, vc4_mmap_bo_ioctl, 0), DRM_IOCTL_DEF_DRV(VC4_CREATE_SHADER_BO, vc4_create_shader_bo_ioctl, 0), @@ -83,10 +86,16 @@ static struct drm_driver vc4_drm_driver = { .driver_features = (DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_GEM | + DRIVER_HAVE_IRQ | DRIVER_PRIME), .lastclose = vc4_lastclose, .preclose = vc4_drm_preclose, + .irq_handler = vc4_irq, + .irq_preinstall = vc4_irq_preinstall, + .irq_postinstall = vc4_irq_postinstall, + .irq_uninstall = vc4_irq_uninstall, + .enable_vblank = vc4_enable_vblank, .disable_vblank = vc4_disable_vblank, .get_vblank_counter = drm_vblank_count, @@ -181,9 +190,11 @@ static int vc4_drm_bind(struct device *dev) if (ret) goto unref; + vc4_gem_init(drm); + ret = component_bind_all(dev, drm); if (ret) - goto unref; + goto gem_destroy; ret = drm_dev_register(drm, 0); if (ret < 0) @@ -207,6 +218,8 @@ unregister: drm_dev_unregister(drm); unbind_all: component_unbind_all(dev, drm); +gem_destroy: + vc4_gem_destroy(drm); unref: drm_dev_unref(drm); vc4_bo_cache_destroy(drm); diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 8945463..a3dbfee 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -49,6 +49,48 @@ struct vc4_dev { /* Protects bo_cache and the BO stats. */ struct mutex bo_lock; + + /* Sequence number for the last job queued in job_list. +* Starts at 0 (no jobs emitted). +*/ + uint64_t emit_seqno; + + /* Sequence number for the last completed job on the GPU. +* Starts at 0 (no jobs completed). +*/ + uint64_t finished_seqno; + + /* List of all struct vc4_exec_info for jobs to be executed. +* The first job in the list is the one currently programmed +* into ct0ca/ct1ca for execution. +*/ + struct list_head job_list; + /* List of the finished vc4_exec_infos waiting to be freed by +* job_done_work. +*/ + struct list_head job_done_list; + /* Spinlock used to synchronize the job_list and seqno +* accesses between the
[PATCH 5/9] drm/vc4: Fix a typo in a V3D debug register.
Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_regs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index 9e4e904..4e52a0a 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -154,7 +154,7 @@ #define V3D_PCTRS14 0x006f4 #define V3D_PCTR15 0x006f8 #define V3D_PCTRS15 0x006fc -#define V3D_BGE 0x00f00 +#define V3D_DBGE 0x00f00 #define V3D_FDBGO0x00f04 #define V3D_FDBGB0x00f08 #define V3D_FDBGR0x00f0c -- 2.6.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 3/9] drm/vc4: Add create and map BO ioctls.
While there exist dumb APIs for creating and mapping BOs, one of the rules is that drivers doing 3D acceleration have to provide their own APIs for buffer allocation (besides, the pitch/height parameters of the dumb alloc don't really make sense for a lot of 3D allocations). Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_bo.c | 41 ++ drivers/gpu/drm/vc4/vc4_drv.c | 3 ++ drivers/gpu/drm/vc4/vc4_drv.h | 4 +++ include/uapi/drm/Kbuild | 1 + include/uapi/drm/vc4_drm.h| 68 +++ 5 files changed, 117 insertions(+) create mode 100644 include/uapi/drm/vc4_drm.h diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index 18faa5b..06cba26 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -19,6 +19,7 @@ */ #include "vc4_drv.h" +#include "uapi/drm/vc4_drm.h" static void vc4_bo_stats_dump(struct vc4_dev *vc4) { @@ -346,6 +347,46 @@ static void vc4_bo_cache_time_timer(unsigned long data) schedule_work(&vc4->bo_cache.time_work); } +int vc4_create_bo_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_vc4_create_bo *args = data; + struct vc4_bo *bo = NULL; + int ret; + + /* +* We can't allocate from the BO cache, because the BOs don't +* get zeroed, and that might leak data between users. +*/ + bo = vc4_bo_create(dev, args->size, false); + if (!bo) + return -ENOMEM; + + ret = drm_gem_handle_create(file_priv, &bo->base.base, &args->handle); + drm_gem_object_unreference_unlocked(&bo->base.base); + + return ret; +} + +int vc4_mmap_bo_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_vc4_mmap_bo *args = data; + struct drm_gem_object *gem_obj; + + gem_obj = drm_gem_object_lookup(dev, file_priv, args->handle); + if (!gem_obj) { + DRM_ERROR("Failed to look up GEM BO %d\n", args->handle); + return -EINVAL; + } + + /* The mmap offset was set up at BO allocation time. */ + args->offset = drm_vma_node_offset_addr(&gem_obj->vma_node); + + drm_gem_object_unreference_unlocked(gem_obj); + return 0; +} + void vc4_bo_cache_init(struct drm_device *dev) { struct vc4_dev *vc4 = to_vc4_dev(dev); diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index da041fa..5fa4688 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -16,6 +16,7 @@ #include #include "drm_fb_cma_helper.h" +#include "uapi/drm/vc4_drm.h" #include "vc4_drv.h" #include "vc4_regs.h" @@ -73,6 +74,8 @@ static const struct file_operations vc4_drm_fops = { }; static const struct drm_ioctl_desc vc4_drm_ioctls[] = { + DRM_IOCTL_DEF_DRV(VC4_CREATE_BO, vc4_create_bo_ioctl, 0), + DRM_IOCTL_DEF_DRV(VC4_MMAP_BO, vc4_mmap_bo_ioctl, 0), }; static struct drm_driver vc4_drm_driver = { diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 39a1ff5..fddb0a0 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -155,6 +155,10 @@ int vc4_dumb_create(struct drm_file *file_priv, struct drm_mode_create_dumb *args); struct dma_buf *vc4_prime_export(struct drm_device *dev, struct drm_gem_object *obj, int flags); +int vc4_create_bo_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int vc4_mmap_bo_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); void vc4_bo_cache_init(struct drm_device *dev); void vc4_bo_cache_destroy(struct drm_device *dev); int vc4_bo_stats_debugfs(struct seq_file *m, void *arg); diff --git a/include/uapi/drm/Kbuild b/include/uapi/drm/Kbuild index 38d4370..974fcd5 100644 --- a/include/uapi/drm/Kbuild +++ b/include/uapi/drm/Kbuild @@ -17,4 +17,5 @@ header-y += tegra_drm.h header-y += via_drm.h header-y += vmwgfx_drm.h header-y += msm_drm.h +header-y += vc4_drm.h header-y += virtgpu_drm.h diff --git a/include/uapi/drm/vc4_drm.h b/include/uapi/drm/vc4_drm.h new file mode 100644 index 000..068aab9 --- /dev/null +++ b/include/uapi/drm/vc4_drm.h @@ -0,0 +1,68 @@ +/* + * Copyright © 2014-2015 Broadcom + * + * 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
[PATCH 2/9] drm/vc4: Add a BO cache.
We need to allocate new BOs in the kernel as part of each frame, but the CMA allocator is way too slow for that. As an optimization, keep track of recently-freed BOs and reuse them, with a 1 second timeout to fully free them back to the system. This improves 3D performance by about 15%. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_bo.c | 336 +- drivers/gpu/drm/vc4/vc4_debugfs.c | 1 + drivers/gpu/drm/vc4/vc4_drv.c | 6 +- drivers/gpu/drm/vc4/vc4_drv.h | 49 +- 4 files changed, 384 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index ab9f510..18faa5b 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -12,19 +12,229 @@ * access to system memory with no MMU in between. To support it, we * use the GEM CMA helper functions to allocate contiguous ranges of * physical memory for our BOs. + * + * Since the CMA allocator is very slow, we keep a cache of recently + * freed BOs around so that the kernel's allocation of objects for 3D + * rendering can return quickly. */ #include "vc4_drv.h" -struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t size) +static void vc4_bo_stats_dump(struct vc4_dev *vc4) +{ + DRM_INFO("num bos allocated: %d\n", +vc4->bo_stats.num_allocated); + DRM_INFO("size bos allocated: %dkb\n", +vc4->bo_stats.size_allocated / 1024); + DRM_INFO("num bos used: %d\n", +vc4->bo_stats.num_allocated - vc4->bo_stats.num_cached); + DRM_INFO("size bos used: %dkb\n", +(vc4->bo_stats.size_allocated - + vc4->bo_stats.size_cached) / 1024); + DRM_INFO("num bos cached: %d\n", +vc4->bo_stats.num_cached); + DRM_INFO("size bos cached: %dkb\n", +vc4->bo_stats.size_cached / 1024); +} + +#ifdef CONFIG_DEBUG_FS +int vc4_bo_stats_debugfs(struct seq_file *m, void *unused) +{ + struct drm_info_node *node = (struct drm_info_node *)m->private; + struct drm_device *dev = node->minor->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_bo_stats stats; + + /* Take a snapshot of the current stats with the lock held. */ + mutex_lock(&vc4->bo_lock); + stats = vc4->bo_stats; + mutex_unlock(&vc4->bo_lock); + + seq_printf(m, "num bos allocated: %d\n", + stats.num_allocated); + seq_printf(m, "size bos allocated: %dkb\n", + stats.size_allocated / 1024); + seq_printf(m, "num bos used: %d\n", + stats.num_allocated - stats.num_cached); + seq_printf(m, "size bos used: %dkb\n", + (stats.size_allocated - stats.size_cached) / 1024); + seq_printf(m, "num bos cached: %d\n", + stats.num_cached); + seq_printf(m, "size bos cached: %dkb\n", + stats.size_cached / 1024); + + return 0; +} +#endif + +static uint32_t bo_page_index(size_t size) +{ + return (size / PAGE_SIZE) - 1; +} + +/* Must be called with bo_lock held. */ +static void vc4_bo_destroy(struct vc4_bo *bo) { + struct drm_gem_object *obj = &bo->base.base; + struct vc4_dev *vc4 = to_vc4_dev(obj->dev); + + vc4->bo_stats.num_allocated--; + vc4->bo_stats.size_allocated -= obj->size; + drm_gem_cma_free_object(obj); +} + +/* Must be called with bo_lock held. */ +static void vc4_bo_remove_from_cache(struct vc4_bo *bo) +{ + struct drm_gem_object *obj = &bo->base.base; + struct vc4_dev *vc4 = to_vc4_dev(obj->dev); + + vc4->bo_stats.num_cached--; + vc4->bo_stats.size_cached -= obj->size; + + list_del(&bo->unref_head); + list_del(&bo->size_head); +} + +static struct list_head *vc4_get_cache_list_for_size(struct drm_device *dev, +size_t size) +{ + struct vc4_dev *vc4 = to_vc4_dev(dev); + uint32_t page_index = bo_page_index(size); + + if (vc4->bo_cache.size_list_size <= page_index) { + uint32_t new_size = max(vc4->bo_cache.size_list_size * 2, + page_index + 1); + struct list_head *new_list; + uint32_t i; + + new_list = kmalloc_array(new_size, sizeof(struct list_head), +GFP_KERNEL); + if (!new_list) + return NULL; + + /* Rebase the old cached BO lists to their new list +* head locations. +*/ + for (i = 0; i < vc4->bo_cache.size_list_size; i++) { +
[PATCH 4/9] drm/vc4: Add an API for creating GPU shaders in GEM BOs.
Since we have no MMU, the kernel needs to validate that the submitted shader code won't make any accesses to memory that the user doesn't control, which involves banning some operations (general purpose DMA writes), and tracking where we need to write out pointers for other operations (texture sampling). Once it's validated, we return a GEM BO containing the shader, which doesn't allow mapping for write or exporting to other subsystems. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/Makefile | 3 +- drivers/gpu/drm/vc4/vc4_bo.c | 140 drivers/gpu/drm/vc4/vc4_drv.c | 9 +- drivers/gpu/drm/vc4/vc4_drv.h | 50 +++ drivers/gpu/drm/vc4/vc4_qpu_defines.h | 264 +++ drivers/gpu/drm/vc4/vc4_validate_shaders.c | 513 + include/uapi/drm/vc4_drm.h | 25 ++ 7 files changed, 999 insertions(+), 5 deletions(-) create mode 100644 drivers/gpu/drm/vc4/vc4_qpu_defines.h create mode 100644 drivers/gpu/drm/vc4/vc4_validate_shaders.c diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile index 32b4f9c..eb776a6 100644 --- a/drivers/gpu/drm/vc4/Makefile +++ b/drivers/gpu/drm/vc4/Makefile @@ -10,7 +10,8 @@ vc4-y := \ vc4_kms.o \ vc4_hdmi.o \ vc4_hvs.o \ - vc4_plane.o + vc4_plane.o \ + vc4_validate_shaders.o vc4-$(CONFIG_DEBUG_FS) += vc4_debugfs.o diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index 06cba26..18dfe3e 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -79,6 +79,12 @@ static void vc4_bo_destroy(struct vc4_bo *bo) struct drm_gem_object *obj = &bo->base.base; struct vc4_dev *vc4 = to_vc4_dev(obj->dev); + if (bo->validated_shader) { + kfree(bo->validated_shader->texture_samples); + kfree(bo->validated_shader); + bo->validated_shader = NULL; + } + vc4->bo_stats.num_allocated--; vc4->bo_stats.size_allocated -= obj->size; drm_gem_cma_free_object(obj); @@ -315,6 +321,12 @@ void vc4_free_object(struct drm_gem_object *gem_bo) goto out; } + if (bo->validated_shader) { + kfree(bo->validated_shader->texture_samples); + kfree(bo->validated_shader); + bo->validated_shader = NULL; + } + bo->free_time = jiffies; list_add(&bo->size_head, cache_list); list_add(&bo->unref_head, &vc4->bo_cache.time_list); @@ -347,6 +359,78 @@ static void vc4_bo_cache_time_timer(unsigned long data) schedule_work(&vc4->bo_cache.time_work); } +struct dma_buf * +vc4_prime_export(struct drm_device *dev, struct drm_gem_object *obj, int flags) +{ + struct vc4_bo *bo = to_vc4_bo(obj); + + if (bo->validated_shader) { + DRM_ERROR("Attempting to export shader BO\n"); + return ERR_PTR(-EINVAL); + } + + return drm_gem_prime_export(dev, obj, flags); +} + +int vc4_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct drm_gem_object *gem_obj; + struct vc4_bo *bo; + int ret; + + ret = drm_gem_mmap(filp, vma); + if (ret) + return ret; + + gem_obj = vma->vm_private_data; + bo = to_vc4_bo(gem_obj); + + if (bo->validated_shader && (vma->vm_flags & VM_WRITE)) { + DRM_ERROR("mmaping of shader BOs for writing not allowed.\n"); + return -EINVAL; + } + + /* +* Clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and set the +* vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want to map +* the whole buffer. +*/ + vma->vm_flags &= ~VM_PFNMAP; + vma->vm_pgoff = 0; + + ret = dma_mmap_writecombine(bo->base.base.dev->dev, vma, + bo->base.vaddr, bo->base.paddr, + vma->vm_end - vma->vm_start); + if (ret) + drm_gem_vm_close(vma); + + return ret; +} + +int vc4_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) +{ + struct vc4_bo *bo = to_vc4_bo(obj); + + if (bo->validated_shader && (vma->vm_flags & VM_WRITE)) { + DRM_ERROR("mmaping of shader BOs for writing not allowed.\n"); + return -EINVAL; + } + + return drm_gem_cma_prime_mmap(obj, vma); +} + +void *vc4_prime_vmap(struct drm_gem_object *obj) +{ + struct vc4_bo *bo = to_vc4_bo(obj); + + if (bo->validated_shader) { + DRM_ERROR("mmaping of shader BOs not allowed.\n"); + return ERR_PTR(-EINVAL); + } + + return drm_gem_cma_pr
[PATCH 9/9] drm/vc4: Add an interface for capturing the GPU state after a hang.
This can be parsed with vc4-gpu-tools tools for trying to figure out what was going on. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_drv.c | 2 + drivers/gpu/drm/vc4/vc4_drv.h | 4 + drivers/gpu/drm/vc4/vc4_gem.c | 185 ++ include/uapi/drm/vc4_drm.h| 45 ++ 4 files changed, 236 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 2cfee59..97226b6 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -80,6 +80,8 @@ static const struct drm_ioctl_desc vc4_drm_ioctls[] = { DRM_IOCTL_DEF_DRV(VC4_CREATE_BO, vc4_create_bo_ioctl, 0), DRM_IOCTL_DEF_DRV(VC4_MMAP_BO, vc4_mmap_bo_ioctl, 0), DRM_IOCTL_DEF_DRV(VC4_CREATE_SHADER_BO, vc4_create_shader_bo_ioctl, 0), + DRM_IOCTL_DEF_DRV(VC4_GET_HANG_STATE, vc4_get_hang_state_ioctl, + DRM_ROOT_ONLY), }; static struct drm_driver vc4_drm_driver = { diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 9a8ee23..cd3e243 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -19,6 +19,8 @@ struct vc4_dev { struct drm_fbdev_cma *fbdev; + struct vc4_hang_state *hang_state; + /* The kernel-space BO cache. Tracks buffers that have been * unreferenced by all other users (refcounts of 0!) but not * yet freed, so we can do cheap allocations. @@ -369,6 +371,8 @@ int vc4_create_shader_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int vc4_mmap_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +int vc4_get_hang_state_ioctl(struct drm_device *dev, void *data, +struct drm_file *file_priv); int vc4_mmap(struct file *filp, struct vm_area_struct *vma); int vc4_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); void *vc4_prime_vmap(struct drm_gem_object *obj); diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index a62ca68..fb0b92d 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -40,6 +40,186 @@ vc4_queue_hangcheck(struct drm_device *dev) round_jiffies_up(jiffies + msecs_to_jiffies(100))); } +struct vc4_hang_state { + struct drm_vc4_get_hang_state user_state; + + u32 bo_count; + struct drm_gem_object **bo; +}; + +static void +vc4_free_hang_state(struct drm_device *dev, struct vc4_hang_state *state) +{ + unsigned int i; + + mutex_lock(&dev->struct_mutex); + for (i = 0; i < state->user_state.bo_count; i++) + drm_gem_object_unreference(state->bo[i]); + mutex_unlock(&dev->struct_mutex); + + kfree(state); +} + +int +vc4_get_hang_state_ioctl(struct drm_device *dev, void *data, +struct drm_file *file_priv) +{ + struct drm_vc4_get_hang_state *get_state = data; + struct drm_vc4_get_hang_state_bo *bo_state; + struct vc4_hang_state *kernel_state; + struct drm_vc4_get_hang_state *state; + struct vc4_dev *vc4 = to_vc4_dev(dev); + unsigned long irqflags; + u32 i; + int ret; + + spin_lock_irqsave(&vc4->job_lock, irqflags); + kernel_state = vc4->hang_state; + if (!kernel_state) { + spin_unlock_irqrestore(&vc4->job_lock, irqflags); + return -ENOENT; + } + state = &kernel_state->user_state; + + /* If the user's array isn't big enough, just return the +* required array size. +*/ + if (get_state->bo_count < state->bo_count) { + get_state->bo_count = state->bo_count; + spin_unlock_irqrestore(&vc4->job_lock, irqflags); + return 0; + } + + vc4->hang_state = NULL; + spin_unlock_irqrestore(&vc4->job_lock, irqflags); + + /* Save the user's BO pointer, so we don't stomp it with the memcpy. */ + state->bo = get_state->bo; + memcpy(get_state, state, sizeof(*state)); + + bo_state = kcalloc(state->bo_count, sizeof(*bo_state), GFP_KERNEL); + if (!bo_state) { + ret = -ENOMEM; + goto err_free; + } + + for (i = 0; i < state->bo_count; i++) { + struct vc4_bo *vc4_bo = to_vc4_bo(kernel_state->bo[i]); + u32 handle; + + ret = drm_gem_handle_create(file_priv, kernel_state->bo[i], + &handle); + + if (ret) { + state->bo_count = i - 1; + goto err; + } + bo_state[i].handle = handle; + bo_state[i].paddr = vc4_bo->base.paddr; +
[PATCH 6/9] drm/vc4: Bind and initialize the V3D engine.
This is the component of the GPU that does 3D rendering. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/Makefile | 1 + drivers/gpu/drm/vc4/vc4_debugfs.c | 2 + drivers/gpu/drm/vc4/vc4_drv.c | 1 + drivers/gpu/drm/vc4/vc4_drv.h | 13 +++ drivers/gpu/drm/vc4/vc4_v3d.c | 225 ++ 5 files changed, 242 insertions(+) create mode 100644 drivers/gpu/drm/vc4/vc4_v3d.c diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile index eb776a6..e87a6f2 100644 --- a/drivers/gpu/drm/vc4/Makefile +++ b/drivers/gpu/drm/vc4/Makefile @@ -11,6 +11,7 @@ vc4-y := \ vc4_hdmi.o \ vc4_hvs.o \ vc4_plane.o \ + vc4_v3d.o \ vc4_validate_shaders.o vc4-$(CONFIG_DEBUG_FS) += vc4_debugfs.o diff --git a/drivers/gpu/drm/vc4/vc4_debugfs.c b/drivers/gpu/drm/vc4/vc4_debugfs.c index 6bcf96e..d76ad10 100644 --- a/drivers/gpu/drm/vc4/vc4_debugfs.c +++ b/drivers/gpu/drm/vc4/vc4_debugfs.c @@ -22,6 +22,8 @@ static const struct drm_info_list vc4_debugfs_list[] = { {"crtc0_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)0}, {"crtc1_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)1}, {"crtc2_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)2}, + {"v3d_ident", vc4_v3d_debugfs_ident, 0}, + {"v3d_regs", vc4_v3d_debugfs_regs, 0}, }; #define VC4_DEBUGFS_ENTRIES ARRAY_SIZE(vc4_debugfs_list) diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index da4be9c..db58d74 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -236,6 +236,7 @@ static struct platform_driver *const component_drivers[] = { &vc4_hdmi_driver, &vc4_crtc_driver, &vc4_hvs_driver, + &vc4_v3d_driver, }; static int vc4_platform_drm_probe(struct platform_device *pdev) diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index bd77d55..8945463 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -15,6 +15,7 @@ struct vc4_dev { struct vc4_hdmi *hdmi; struct vc4_hvs *hvs; struct vc4_crtc *crtc[3]; + struct vc4_v3d *v3d; struct drm_fbdev_cma *fbdev; @@ -82,6 +83,11 @@ to_vc4_bo(struct drm_gem_object *bo) return (struct vc4_bo *)bo; } +struct vc4_v3d { + struct platform_device *pdev; + void __iomem *regs; +}; + struct vc4_hvs { struct platform_device *pdev; void __iomem *regs; @@ -119,6 +125,8 @@ to_vc4_encoder(struct drm_encoder *encoder) return container_of(encoder, struct vc4_encoder, base); } +#define V3D_READ(offset) readl(vc4->v3d->regs + offset) +#define V3D_WRITE(offset, val) writel(val, vc4->v3d->regs + offset) #define HVS_READ(offset) readl(vc4->hvs->regs + offset) #define HVS_WRITE(offset, val) writel(val, vc4->hvs->regs + offset) @@ -241,6 +249,11 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist); u32 vc4_plane_dlist_size(struct drm_plane_state *state); +/* vc4_v3d.c */ +extern struct platform_driver vc4_v3d_driver; +int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused); +int vc4_v3d_debugfs_regs(struct seq_file *m, void *unused); + /* vc4_validate_shader.c */ struct vc4_validated_shader_info * vc4_validate_shader(struct drm_gem_cma_object *shader_obj); diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c new file mode 100644 index 000..040ad0d --- /dev/null +++ b/drivers/gpu/drm/vc4/vc4_v3d.c @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * Copyright (C) 2013 Red Hat + * Author: Rob Clark + * + * 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. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "linux/component.h" +#include "vc4_drv.h" +#include "vc4_regs.h" + +#ifdef CONFIG_DEBUG_FS +#define REGDEF(reg) { reg, #reg } +static const struct { + uint32_t reg; + const char *name; +} vc4_reg_defs[] = { + REGDEF(V3D_IDENT0), + REGDEF(V3D_IDENT1), + REGDEF(V3D_IDENT2), + REGDEF(V3D_SCRATCH), + REGDEF(V3D_L2CACTL), + REGDEF(V3D_SLCACTL), + REGDEF(V3D_INTCTL), + REGDEF(V3D_INTENA), + REGDEF(V3D_INTDIS), + REGDEF(V3D_CT0CS), +
Re: [PATCH 4/9] drm/vc4: Add an API for creating GPU shaders in GEM BOs.
Emil Velikov writes: > Hi Eric, > > On 1 December 2015 at 20:35, Eric Anholt wrote: >> Since we have no MMU, the kernel needs to validate that the submitted >> shader code won't make any accesses to memory that the user doesn't >> control, which involves banning some operations (general purpose DMA >> writes), and tracking where we need to write out pointers for other >> operations (texture sampling). Once it's validated, we return a GEM >> BO containing the shader, which doesn't allow mapping for write or >> exporting to other subsystems. >> >> Signed-off-by: Eric Anholt >> --- >> drivers/gpu/drm/vc4/Makefile | 3 +- >> drivers/gpu/drm/vc4/vc4_bo.c | 140 >> drivers/gpu/drm/vc4/vc4_drv.c | 9 +- >> drivers/gpu/drm/vc4/vc4_drv.h | 50 +++ >> drivers/gpu/drm/vc4/vc4_qpu_defines.h | 264 +++ > > May I suggest that one 'exports' the header to something like > libdrm_vc4 ? There are patches in flight for nouveau which in similar > fashion, allow userspare to reuse existing api/abi. I'll be putting this header in libdrm for use by Mesa and vc4-gpu-tools. It will still have to live in the kernel as well, though. signature.asc Description: PGP signature
Re: [PATCH 7/9] drm/vc4: Add support for drawing 3D frames.
Emil Velikov writes: > Hi Eric, > > On 1 December 2015 at 20:35, Eric Anholt wrote: >> The user submission is basically a pointer to a command list and a >> pointer to uniforms. We copy those in to the kernel, validate and >> relocate them, and store the result in a GPU BO which we queue for >> execution. >> >> Signed-off-by: Eric Anholt >> --- >> drivers/gpu/drm/vc4/Makefile | 7 + >> drivers/gpu/drm/vc4/vc4_drv.c | 15 +- >> drivers/gpu/drm/vc4/vc4_drv.h | 192 +++ >> drivers/gpu/drm/vc4/vc4_gem.c | 640 ++ >> drivers/gpu/drm/vc4/vc4_irq.c | 210 >> drivers/gpu/drm/vc4/vc4_packet.h | 399 ++ >> drivers/gpu/drm/vc4/vc4_render_cl.c| 631 ++ >> drivers/gpu/drm/vc4/vc4_trace.h| 63 +++ >> drivers/gpu/drm/vc4/vc4_trace_points.c | 14 + >> drivers/gpu/drm/vc4/vc4_v3d.c | 37 ++ >> drivers/gpu/drm/vc4/vc4_validate.c | 955 >> + >> include/uapi/drm/vc4_drm.h | 141 + >> 12 files changed, 3303 insertions(+), 1 deletion(-) > > Am I assuming correct that the above are the exact same ones copied in > mesa (and used only then simulator is used) ? In the short term > keeping the two in sync would be fine, although wondering if you have > plans to reshuffle things in the long term ? This code is not exactly synced with Mesa, but I do sync between them on a regular basis. The in-Mesa copy is secondary, and just a way for me to get testing done faster (in the simulation environment with gdb) than I can in the kernel with printfs. signature.asc Description: PGP signature
Re: [PATCH 9/9] drm/vc4: Add an interface for capturing the GPU state after a hang.
Emil Velikov writes: > On 1 December 2015 at 20:35, Eric Anholt wrote: >> This can be parsed with vc4-gpu-tools tools for trying to figure out >> what was going on. >> > I might be pushing my luck here ... have you thought about basing > (forking) vc4-gpu-tools of intel-gpu-tools ? I'd imagine that the > macros and helpers will come in handy, despite that some are quite > intel specific. > > On a related note - with the above project in place I'd imagine you > have (re)considered about having libdrm-vc4 ? Copying hunks around > might lead to interesting moments (as you have already noticed :-P) > > On that note I'll stop now with beating the libdrm drum :-) The headers and code that I copy between the two userspace locations will go in libdrm when I have a kernel ABI, but vc4_drm.h can't go in until merging to the kernel, and there's not a whole lot of point without that. Yes, I have thought about basing vc4-gpu-tools off of intel-gpu-tools. I've actually tried to build and use the kms testing stuff on vc4, and it was a total bust. Someone needs to do a lot of work to make igt useful for non-intel. If you'd like me to build my vc4 testing inside of igt, I'd someone to demo one of my tests building inside of igt, with the test runner working and none of the intel-specific tests reporting failure, and get me permission to just push code to that repository (It's hard enough getting piglit tests reviewed, vc4-specific tests and tools would never get review). signature.asc Description: PGP signature
Re: [PATCH v2 1/3] clk: bcm2835: Always round up clock divisor
Remi Pommarel writes: > Hi, > > On Wed, Nov 18, 2015 at 10:25:45AM -0800, Eric Anholt wrote: >> Remi Pommarel writes: >> >> > Make bcm2835_clock_choose_div always round up the chosen MASH divisor so >> > that >> > the resulting average rate will not be higher than the requested one. >> > >> > Signed-off-by: Remi Pommarel >> > --- >> > drivers/clk/bcm/clk-bcm2835.c | 15 --- >> > 1 file changed, 8 insertions(+), 7 deletions(-) >> > >> > diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c >> > index 39bf582..1237716 100644 >> > --- a/drivers/clk/bcm/clk-bcm2835.c >> > +++ b/drivers/clk/bcm/clk-bcm2835.c >> > @@ -1152,18 +1152,19 @@ static u32 bcm2835_clock_choose_div(struct clk_hw >> > *hw, >> > { >> >struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); >> >const struct bcm2835_clock_data *data = clock->data; >> > - u32 unused_frac_mask = GENMASK(CM_DIV_FRAC_BITS - data->frac_bits, 0); >> > + u32 unused_frac_mask = >> > + GENMASK(CM_DIV_FRAC_BITS - data->frac_bits, 0) >> 1; >> >u64 temp = (u64)parent_rate << CM_DIV_FRAC_BITS; >> > + u64 rem; >> >u32 div; >> > >> > - do_div(temp, rate); >> > + rem = do_div(temp, rate); >> >div = temp; >> > >> > - /* Round and mask off the unused bits */ >> > - if (unused_frac_mask != 0) { >> > - div += unused_frac_mask >> 1; >> > - div &= ~unused_frac_mask; >> > - } >> > + /* Round up and mask off the unused bits */ >> > + if ((div & unused_frac_mask) != 0 || rem != 0) >> > + div += unused_frac_mask + 1; >> > + div &= ~unused_frac_mask; >> >> Suppose we've got 8 of our 12 frac bits populated. You've added a ">> >> 1" to the unused_frac_mask, so it's only 0x7 instead of 0xf. When you >> say "round up", you add 0x8 (the high bit of the unused mask") then and >> with ~0x7. If you started with 0x1 in the low bits of div, you'd end up >> with 0x8, so you've set an unused bit instead of actually rounding up. >> >> Did my logic work, here? I think you just want to drop the ">>1" in >> unused_frac_mask. > > I don't think so. > > If we have 8 of our 12 frac bits populated GENMASK(12 - 8, 0) will be 0x1f > because GENMASK(4, 0) generates a mask from bit at position 0 to bit at > position 4 inclusively (which is the fifth bit). So GENMASK(4, 0) >> 1 will > be 0xf which is what we want here. Oh, that was an existing bug you were fixing! You're right. I even got the GENMASK call right at the end of the function, I'd just botched this one. Reviewed-by: Eric Anholt signature.asc Description: PGP signature
Re: [PATCH v2 2/3] clk: bcm2835: Support for clock parent selection
Remi Pommarel writes: > On Wed, Nov 18, 2015 at 10:30:17AM -0800, Eric Anholt wrote: > > [...] > >> > +static int bcm2835_clock_determine_rate(struct clk_hw *hw, >> > + struct clk_rate_request *req) >> > +{ >> > + struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); >> > + struct clk_hw *parent, *best_parent = NULL; >> > + struct clk_rate_request parent_req; >> > + unsigned long rate, best_rate = 0; >> > + unsigned long prate, best_prate = 0; >> > + size_t i; >> > + u32 div; >> > + >> > + /* >> > + * Select parent clock that results in the closest but lower rate >> > + */ >> > + for (i = 0; i < clk_hw_get_num_parents(hw); ++i) { >> > + parent = clk_hw_get_parent_by_index(hw, i); >> > + if (!parent) >> > + continue; >> > + parent_req = *req; >> >> parent_req appears dead, so it should be removed. > > Yes, will do thanks. > >> > + prate = clk_hw_get_rate(parent); >> > + div = bcm2835_clock_choose_div(hw, req->rate, prate); >> > + rate = bcm2835_clock_rate_from_divisor(clock, prate, div); >> > + if (rate > best_rate && rate <= req->rate) { >> > + best_parent = parent; >> > + best_prate = prate; >> > + best_rate = rate; >> > + } >> > + } >> > + >> > + if (!best_parent) >> > + return -EINVAL; >> > + >> > + req->best_parent_hw = best_parent; >> > + req->best_parent_rate = best_prate; >> >> I think you're supposed to req->rate = best_rate, here, too. With these >> two fixes, > > I did not set req->rate to best_rate in order to avoid rounding down > twice the actual clock rate. > > Indeed with patch 1 from this patchset bcm2835_clock_choose_div() > chooses a divisor that produces a rate lower or equal to the requested > one. As we call bcm2835_clock_choose_div() twice when using > clk_set_rate() (once with ->determine_rate() and once with ->set_rate()), > if I set req->rate in bcm2835_clock_determine_rate to the rounded down > one, the final rate will likely be again rounded down in > bcm2835_clock_set_rate(). If we pass bcm2835_clock_rate_from_divisor(bcm2835_clock_choose_div()), to bcm2835_clock_choose_div(), will it actually give a different divisor than the first call? (That seems like an unfortunate problem in our implementation, if so). I'd be willing to go along with this, but if so I'd like a comment explaining why we aren't setting the field that we should pretty obviously be setting. signature.asc Description: PGP signature
Re: [PATCH 8/9] drm/vc4: Add support for async pageflips.
Daniel Stone writes: > Hi, > > On 1 December 2015 at 20:35, Eric Anholt wrote: >> An async pageflip stores the modeset to be done and executes it once >> the BOs are ready to be displayed. This gets us about 3x performance >> in full screen rendering with pageflipping. > > Looks good, but you're missing a preclose callback to reap dead events, a la: > https://git.collabora.com/cgit/user/daniels/linux.git/commit/?h=wip/4.4.x/rockchip-drm-fixes&id=d14f21bcd7e7a1b9ca129c411a9da9c911037965 > > (and parent commit to wire that through to core DRM preclose) We've already got a preclose callback that reaps crtc->event -- see vc4_cancel_page_flip(). signature.asc Description: PGP signature
[PATCH] drm: Use the driver's gem_object_free function from CMA helpers.
VC4 wraps the CMA objects in its own structures, so it needs to do its own teardown (waiting for GPU to finish, updating bo_stats tracking). The other CMA drivers are using drm_gem_cma_free_object as their gem_free_object, so this should be a no-op for them. Signed-off-by: Eric Anholt --- drivers/gpu/drm/drm_fb_cma_helper.c | 6 +++--- drivers/gpu/drm/drm_gem_cma_helper.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index 5c1aca4..99b5673 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -279,7 +279,7 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper, if (!fbi) { dev_err(dev->dev, "Failed to allocate framebuffer info.\n"); ret = -ENOMEM; - goto err_drm_gem_cma_free_object; + goto err_gem_free_object; } fbdev_cma->fb = drm_fb_cma_alloc(dev, &mode_cmd, &obj, 1); @@ -322,8 +322,8 @@ err_drm_fb_cma_destroy: drm_fb_cma_destroy(fb); err_framebuffer_release: framebuffer_release(fbi); -err_drm_gem_cma_free_object: - drm_gem_cma_free_object(&obj->base); +err_gem_free_object: + dev->driver->gem_free_object(&obj->base); return ret; } diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c index 7dcb43f..b409123 100644 --- a/drivers/gpu/drm/drm_gem_cma_helper.c +++ b/drivers/gpu/drm/drm_gem_cma_helper.c @@ -121,7 +121,7 @@ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm, return cma_obj; error: - drm_gem_cma_free_object(&cma_obj->base); + drm->driver->gem_free_object(&cma_obj->base); return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(drm_gem_cma_create); @@ -171,7 +171,7 @@ drm_gem_cma_create_with_handle(struct drm_file *file_priv, return cma_obj; err_handle_create: - drm_gem_cma_free_object(gem_obj); + drm->driver->gem_free_object(gem_obj); return ERR_PTR(ret); } -- 2.6.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] drm: Use the driver's gem_object_free function from CMA helpers.
Daniel Vetter writes: > On Mon, Dec 14, 2015 at 04:26:26PM -0800, Eric Anholt wrote: >> VC4 wraps the CMA objects in its own structures, so it needs to do its >> own teardown (waiting for GPU to finish, updating bo_stats tracking). >> The other CMA drivers are using drm_gem_cma_free_object as their >> gem_free_object, so this should be a no-op for them. >> >> Signed-off-by: Eric Anholt > > Reviewed-by: Daniel Vetter > > Since vc4 landed already I'll pull this into drm-misc. Sounds good to me. Thanks! signature.asc Description: PGP signature
[PATCH v3 4/4] ARM: bcm2835: Add the Raspberry Pi power domain driver to the DT.
From: Alexander Aring This connects the USB driver to the USB power domain, so that USB can actually be turned on at boot if the bootloader didn't do it for us. Signed-off-by: Alexander Aring Signed-off-by: Eric Anholt --- arch/arm/boot/dts/bcm2835-rpi.dtsi | 11 +++ arch/arm/boot/dts/bcm2835.dtsi | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi index 3572f03..f828202 100644 --- a/arch/arm/boot/dts/bcm2835-rpi.dtsi +++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi @@ -1,3 +1,4 @@ +#include #include "bcm2835.dtsi" / { @@ -20,6 +21,12 @@ compatible = "raspberrypi,bcm2835-firmware"; mboxes = <&mailbox>; }; + + power: power { + compatible = "raspberrypi,bcm2835-power"; + firmware = <&firmware>; + #power-domain-cells = <1>; + }; }; }; @@ -60,3 +67,7 @@ status = "okay"; bus-width = <4>; }; + +&usb { + power-domains = <&power RPI_POWER_DOMAIN_USB>; +}; diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi index aef64de..6d62af0 100644 --- a/arch/arm/boot/dts/bcm2835.dtsi +++ b/arch/arm/boot/dts/bcm2835.dtsi @@ -177,7 +177,7 @@ status = "disabled"; }; - usb@7e98 { + usb: usb@7e98 { compatible = "brcm,bcm2835-usb"; reg = <0x7e98 0x1>; interrupts = <1 9>; -- 2.6.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3 0/4] Raspberry Pi power domains
Since the pm_genpd_exit() patch is still going through review, and other drivers in the tree just ignore the error cases, Ulf offered to merge the series as a builtin driver not depending on that interface. We still avoid dangling pointer references, by just continuing with probing if of_genpd_add_provider_onecell() fails. We can easily go back and update the driver when a pm_genpd_exit() lands. Alexander Aring (3): ARM: bcm2835: add rpi power domain driver dt-bindings: add rpi power domain driver bindings ARM: bcm2835: Add the Raspberry Pi power domain driver to the DT. Eric Anholt (1): ARM: bcm2835: Define two new packets from the latest firmware. .../bindings/arm/bcm/raspberrypi,bcm2835-power.txt | 47 arch/arm/boot/dts/bcm2835-rpi.dtsi | 11 + arch/arm/boot/dts/bcm2835.dtsi | 2 +- arch/arm/mach-bcm/Kconfig | 10 + arch/arm/mach-bcm/Makefile | 1 + arch/arm/mach-bcm/raspberrypi-power.c | 247 + include/dt-bindings/arm/raspberrypi-power.h| 41 include/soc/bcm2835/raspberrypi-firmware.h | 2 + 8 files changed, 360 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-power.txt create mode 100644 arch/arm/mach-bcm/raspberrypi-power.c create mode 100644 include/dt-bindings/arm/raspberrypi-power.h -- 2.6.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3 1/4] ARM: bcm2835: Define two new packets from the latest firmware.
These packets give us direct access to the firmware's power management code, as opposed to GET/SET_POWER_STATE packets that only had a couple of domains implemented. Signed-off-by: Eric Anholt --- include/soc/bcm2835/raspberrypi-firmware.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h index c07d74a..3fb3571 100644 --- a/include/soc/bcm2835/raspberrypi-firmware.h +++ b/include/soc/bcm2835/raspberrypi-firmware.h @@ -72,10 +72,12 @@ enum rpi_firmware_property_tag { RPI_FIRMWARE_SET_ENABLE_QPU = 0x00030012, RPI_FIRMWARE_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014, RPI_FIRMWARE_GET_EDID_BLOCK = 0x00030020, + RPI_FIRMWARE_GET_DOMAIN_STATE = 0x00030030, RPI_FIRMWARE_SET_CLOCK_STATE =0x00038001, RPI_FIRMWARE_SET_CLOCK_RATE = 0x00038002, RPI_FIRMWARE_SET_VOLTAGE =0x00038003, RPI_FIRMWARE_SET_TURBO = 0x00038009, + RPI_FIRMWARE_SET_DOMAIN_STATE = 0x00038030, /* Dispmanx TAGS */ RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE = 0x00040001, -- 2.6.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3 2/4] ARM: bcm2835: add rpi power domain driver
From: Alexander Aring This patch adds support for several power domains on Raspberry Pi, including USB (so it can be enabled even if the bootloader didn't do it), and graphics. This patch is the combined work of Eric Anholt (who wrote USB support inside of the Raspberry Pi firmware driver, and wrote the non-USB domain support) and Alexander Aring (who separated the original USB work out from the firmware driver). Signed-off-by: Alexander Aring Signed-off-by: Eric Anholt --- v2: Add support for power domains other than USB, using the new firmware interface, reword commit message (changes by Eric) v3: Restructure as a builtin driver, and drop of_genpd_add_provider_onecell error handling to avoid pm_genpd_exit() dependency until that API can be settled. Clean up copyright header, add missing ISP initialization, and fix typo in transposer's name. arch/arm/mach-bcm/Kconfig | 10 ++ arch/arm/mach-bcm/Makefile | 1 + arch/arm/mach-bcm/raspberrypi-power.c | 247 include/dt-bindings/arm/raspberrypi-power.h | 41 + 4 files changed, 299 insertions(+) create mode 100644 arch/arm/mach-bcm/raspberrypi-power.c create mode 100644 include/dt-bindings/arm/raspberrypi-power.h diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig index 8c53c55..0f23bad 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -134,6 +134,16 @@ config ARCH_BCM2835 This enables support for the Broadcom BCM2835 SoC. This SoC is used in the Raspberry Pi and Roku 2 devices. +config RASPBERRYPI_POWER + bool "Raspberry Pi power domain driver" + depends on ARCH_BCM2835 || COMPILE_TEST + depends on RASPBERRYPI_FIRMWARE + select PM_GENERIC_DOMAINS if PM + select PM_GENERIC_DOMAINS_OF if PM + help + This enables support for the RPi power domains which can be enabled + or disabled via the RPi firmware. + config ARCH_BCM_63XX bool "Broadcom BCM63xx DSL SoC" if ARCH_MULTI_V7 depends on MMU diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile index 892261f..fec2d6b 100644 --- a/arch/arm/mach-bcm/Makefile +++ b/arch/arm/mach-bcm/Makefile @@ -36,6 +36,7 @@ endif # BCM2835 obj-$(CONFIG_ARCH_BCM2835) += board_bcm2835.o +obj-$(CONFIG_RASPBERRYPI_POWER)+= raspberrypi-power.o # BCM5301X obj-$(CONFIG_ARCH_BCM_5301X) += bcm_5301x.o diff --git a/arch/arm/mach-bcm/raspberrypi-power.c b/arch/arm/mach-bcm/raspberrypi-power.c new file mode 100644 index 000..9dc8b43 --- /dev/null +++ b/arch/arm/mach-bcm/raspberrypi-power.c @@ -0,0 +1,247 @@ +/* (C) 2015 Pengutronix, Alexander Aring + * + * 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. + * + * Authors: + * Alexander Aring + * Eric Anholt + */ + +#include +#include +#include +#include +#include +#include + +/* + * Firmware indices for the old power domains interface. Only a few + * of them were actually implemented. + */ +#define RPI_OLD_POWER_DOMAIN_USB 3 +#define RPI_OLD_POWER_DOMAIN_V3D 10 + +struct rpi_power_domain { + u32 domain; + bool enabled; + bool old_interface; + struct generic_pm_domain base; + struct rpi_firmware *fw; +}; + +struct rpi_power_domains { + bool has_new_interface; + struct genpd_onecell_data xlate; + struct rpi_firmware *fw; + struct rpi_power_domain domains[RPI_POWER_DOMAIN_COUNT]; +}; + +/* + * Packet definition used by RPI_FIRMWARE_SET_POWER_STATE and + * RPI_FIRMWARE_SET_DOMAIN_STATE + */ +struct rpi_power_domain_packet { + u32 domain; + u32 on; +} __packet; + +/* + * Asks the firmware to enable or disable power on a specific power + * domain. + */ +static int rpi_firmware_set_power(struct rpi_power_domain *rpi_domain, bool on) +{ + struct rpi_power_domain_packet packet; + + packet.domain = rpi_domain->domain; + packet.on = on; + return rpi_firmware_property(rpi_domain->fw, +rpi_domain->old_interface ? +RPI_FIRMWARE_SET_POWER_STATE : +RPI_FIRMWARE_SET_DOMAIN_STATE, +&packet, sizeof(packet)); +} + +static int rpi_domain_off(struct generic_pm_domain *domain) +{ + struct rpi_power_domain *rpi_domain = + container_of(domain, struct rpi_power_domain, base); + + return rpi_firmware_set_power(rpi_domain, false); +} + +static int rpi_domain_on(struct generic_pm_domain *domain) +{ + struct rpi_power_domain *rpi_domain = + container_of(domain, struct rpi_power_domain, base); + + return rpi_firmware_set_power(rpi_domain, true); +}
[PATCH v3 3/4] dt-bindings: add rpi power domain driver bindings
From: Alexander Aring This patch adds devicetree tree bindings for the Raspberry Pi power domain driver. Signed-off-by: Alexander Aring Acked-by: Rob Herring Signed-off-by: Eric Anholt --- v2: Add the new domains present in v2 to the list. .../bindings/arm/bcm/raspberrypi,bcm2835-power.txt | 47 ++ 1 file changed, 47 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-power.txt diff --git a/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-power.txt b/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-power.txt new file mode 100644 index 000..30942cf --- /dev/null +++ b/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-power.txt @@ -0,0 +1,47 @@ +Raspberry Pi power domain driver + +Required properties: + +- compatible: Should be "raspberrypi,bcm2835-power". +- firmware:Reference to the RPi firmware device node. +- #power-domain-cells: Should be <1>, we providing multiple power domains. + +The valid defines for power domain are: + + RPI_POWER_DOMAIN_I2C0 + RPI_POWER_DOMAIN_I2C1 + RPI_POWER_DOMAIN_I2C2 + RPI_POWER_DOMAIN_VIDEO_SCALER + RPI_POWER_DOMAIN_VPU1 + RPI_POWER_DOMAIN_HDMI + RPI_POWER_DOMAIN_USB + RPI_POWER_DOMAIN_VEC + RPI_POWER_DOMAIN_JPEG + RPI_POWER_DOMAIN_H264 + RPI_POWER_DOMAIN_V3D + RPI_POWER_DOMAIN_ISP + RPI_POWER_DOMAIN_UNICAM0 + RPI_POWER_DOMAIN_UNICAM1 + RPI_POWER_DOMAIN_CCP2RX + RPI_POWER_DOMAIN_CSI2 + RPI_POWER_DOMAIN_CPI + RPI_POWER_DOMAIN_DSI0 + RPI_POWER_DOMAIN_DSI1 + RPI_POWER_DOMAIN_TRANSPOSER + RPI_POWER_DOMAIN_CCP2TX + RPI_POWER_DOMAIN_CDP + RPI_POWER_DOMAIN_ARM + +Example: + +power: power { + compatible = "raspberrypi,bcm2835-power"; + firmware = <&firmware>; + #power-domain-cells = <1>; +}; + +Example for using power domain: + +&usb { + power-domains = <&power RPI_POWER_DOMAIN_USB>; +}; -- 2.6.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 3/4] clk: bcm2835: Add support for programming the audio domain clocks.
Eric Anholt writes: > This adds support for enabling, disabling, and setting the rate of the > audio domain clocks. It will be necessary for setting the pixel clock > for HDMI in the VC4 driver and let us write a cpufreq driver. It will > also improve compatibility with user changes to the firmware's > config.txt, since our previous fixed clocks are unaware of it. > > The firmware also has support for configuring the clocks through the > mailbox channel, but the pixel clock setup by the firmware doesn't > work, and it's Raspberry Pi specific anyway. The only conflicts we > should have with the firmware would be if we made firmware calls that > result in clock management (like opening firmware V3D or ISP access, > which we don't support in upstream), or on hardware over-thermal or > under-voltage (when the firmware would rewrite PLLB to take the ARM > out of overclock). If that happens, our cached .recalc_rate() results > would be incorrect, but that's no worse than our current state where > we used fixed clocks. > > The existing fixed clocks in the code are left in place to provide > backwards compatibility with old device tree files. > > Signed-off-by: Eric Anholt > --- > + onecell->clk_num = BCM2835_CLOCK_COUNT; > + onecell->clks = kzalloc(sizeof(*onecell->clks), GFP_KERNEL); Review of another clock driver I wrote pointed out that I missed the multiply by BCM2835_CLOCK_COUNT here. I'll send an updated version. signature.asc Description: PGP signature
[PATCH v2 1/4] clk: bcm2835: Move under bcm/ with other Broadcom SoC clk drivers.
clk-bcm2835.c predates the drivers under bcm/, but all the new BCM drivers are going in there so let's follow them. Signed-off-by: Eric Anholt --- drivers/clk/Makefile| 1 - drivers/clk/bcm/Makefile| 1 + drivers/clk/{ => bcm}/clk-bcm2835.c | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename drivers/clk/{ => bcm}/clk-bcm2835.c (100%) diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index c4cf075..1bdbe9b 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -19,7 +19,6 @@ endif obj-$(CONFIG_MACH_ASM9260) += clk-asm9260.o obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN)+= clk-axi-clkgen.o obj-$(CONFIG_ARCH_AXXIA) += clk-axm5516.o -obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o obj-$(CONFIG_COMMON_CLK_CDCE706) += clk-cdce706.o obj-$(CONFIG_ARCH_CLPS711X)+= clk-clps711x.o obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile index 8a7a477..ee2349b 100644 --- a/drivers/clk/bcm/Makefile +++ b/drivers/clk/bcm/Makefile @@ -3,4 +3,5 @@ obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o obj-$(CONFIG_COMMON_CLK_IPROC) += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o +obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o obj-$(CONFIG_ARCH_BCM_CYGNUS) += clk-cygnus.o diff --git a/drivers/clk/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c similarity index 100% rename from drivers/clk/clk-bcm2835.c rename to drivers/clk/bcm/clk-bcm2835.c -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 4/4] ARM: bcm2835: Switch to using the new clock driver support.
This will give us the ability to set the pixel and HDMI state machine clocks for the VC4 KMS driver, change the CPU frequency, and potentially gate clocks in the future (once we also write a power domain driver). It also gives the uart an explicit clock reference, so that we don't need to change the physical addresses of the old fixed clk_bcm2835.c clocks for Raspberry Pi 2 port. Two clocks get their frequencies updated as a result of this. One is uart's apb_pclk, which was previously accidentally grabbing the fixed uart0_pclk due to the apb_pclk not having clk_register_clkdev() called. The uart doesn't seem to do anything with apb_pclk other than make sure it's on, so that appears safe (also, as far as I can see, the apb clock is actually the same as the VPU clock). The other is EMMC, which according to the docs was supposed to be in the 50-100Mhz range, but it turns out the firmware needed to change to running it at the 250Mhz core clock speed to avoid a bug in clock domain crossing. Additionally, anything using BCM2835_CLOCK_VPU will now have a correct clock rate if the user configures the boot-time core clock speed using config.txt. Signed-off-by: Eric Anholt --- arch/arm/boot/dts/bcm2835.dtsi | 52 +++--- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi index 301c73f..a6a55b7 100644 --- a/arch/arm/boot/dts/bcm2835.dtsi +++ b/arch/arm/boot/dts/bcm2835.dtsi @@ -1,4 +1,5 @@ #include +#include #include "skeleton.dtsi" / { @@ -21,6 +22,10 @@ compatible = "brcm,bcm2835-system-timer"; reg = <0x7e003000 0x1000>; interrupts = <1 0>, <1 1>, <1 2>, <1 3>; + /* This could be a reference to BCM2835_CLOCK_TIMER, +* but we don't have the driver using the common clock +* support yet. +*/ clock-frequency = <100>; }; @@ -57,6 +62,17 @@ reg = <0x7e10 0x28>; }; + clocks: cprman@7e101000 { + compatible = "brcm,bcm2835-cprman"; + #clock-cells = <1>; + reg = <0x7e101000 0x2000>; + + /* CPRMAN derives everything from the platform's +* oscillator. +*/ + clocks = <&clk_osc>; + }; + rng@7e104000 { compatible = "brcm,bcm2835-rng"; reg = <0x7e104000 0x10>; @@ -96,7 +112,9 @@ compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell"; reg = <0x7e201000 0x1000>; interrupts = <2 25>; - clock-frequency = <300>; + clocks = <&clocks BCM2835_CLOCK_UART>, +<&clocks BCM2835_CLOCK_VPU>; + clock-names = "uartclk", "apb_pclk"; arm,primecell-periphid = <0x00241011>; }; @@ -115,7 +133,7 @@ compatible = "brcm,bcm2835-spi"; reg = <0x7e204000 0x1000>; interrupts = <2 22>; - clocks = <&clk_spi>; + clocks = <&clocks BCM2835_CLOCK_VPU>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -125,7 +143,7 @@ compatible = "brcm,bcm2835-i2c"; reg = <0x7e205000 0x1000>; interrupts = <2 21>; - clocks = <&clk_i2c>; + clocks = <&clocks BCM2835_CLOCK_VPU>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -135,7 +153,7 @@ compatible = "brcm,bcm2835-sdhci"; reg = <0x7e30 0x100>; interrupts = <2 30>; - clocks = <&clk_mmc>; + clocks = <&clocks BCM2835_CLOCK_EMMC>; status = "disabled"; }; @@ -143,7 +161,7 @@ compatible = "brcm,bcm2835-i2c"; reg = <0x7e804000 0x1000>;
[PATCH v2 3/4] clk: bcm2835: Add support for programming the audio domain clocks.
This adds support for enabling, disabling, and setting the rate of the audio domain clocks. It will be necessary for setting the pixel clock for HDMI in the VC4 driver and let us write a cpufreq driver. It will also improve compatibility with user changes to the firmware's config.txt, since our previous fixed clocks are unaware of it. The firmware also has support for configuring the clocks through the mailbox channel, but the pixel clock setup by the firmware doesn't work, and it's Raspberry Pi specific anyway. The only conflicts we should have with the firmware would be if we made firmware calls that result in clock management (like opening firmware V3D or ISP access, which we don't support in upstream), or on hardware over-thermal or under-voltage (when the firmware would rewrite PLLB to take the ARM out of overclock). If that happens, our cached .recalc_rate() results would be incorrect, but that's no worse than our current state where we used fixed clocks. The existing fixed clocks in the code are left in place to provide backwards compatibility with old device tree files. Signed-off-by: Eric Anholt --- v2: Fix onecell->clks[] allocation size. drivers/clk/bcm/clk-bcm2835.c | 1424 - 1 file changed, 1423 insertions(+), 1 deletion(-) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index 6b950ca..fe4be50 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Broadcom + * Copyright (C) 2010,2015 Broadcom * Copyright (C) 2012 Stephen Warren * * This program is free software; you can redistribute it and/or modify @@ -17,10 +17,267 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/** + * DOC: BCM2835 CPRMAN (clock manager for the "audio" domain) + * + * The clock tree on the 2835 has several levels. There's a root + * oscillator running at 19.2Mhz. After the oscillator there are 4 + * PLLs, roughly divided as "camera", "ARM", "core", "DSI displays", + * and "HDMI displays". Those 5 PLLs each can divide their output to + * produce up to 4 channels. Finally, there is the level of clocks to + * be consumed by other hardware components (like "H264" or "HDMI + * state machine"), which divide off of some subset of the PLL + * channels. + * + * All of the clocks in the tree are exposed in the DT, because the DT + * may want to make assignments of the final layer of clocks to the + * PLL channels, and some components of the hardware will actually + * skip layers of the tree (for example, the pixel clock comes + * directly from the PLLH PIX channel without using a CM_*CTL clock + * generator). + */ + #include #include #include +#include #include +#include +#include +#include + +#define CM_PASSWORD0x5a00 + +#define CM_GNRICCTL0x000 +#define CM_GNRICDIV0x004 +# define CM_DIV_FRAC_BITS 12 + +#define CM_VPUCTL 0x008 +#define CM_VPUDIV 0x00c +#define CM_SYSCTL 0x010 +#define CM_SYSDIV 0x014 +#define CM_PERIACTL0x018 +#define CM_PERIADIV0x01c +#define CM_PERIICTL0x020 +#define CM_PERIIDIV0x024 +#define CM_H264CTL 0x028 +#define CM_H264DIV 0x02c +#define CM_ISPCTL 0x030 +#define CM_ISPDIV 0x034 +#define CM_V3DCTL 0x038 +#define CM_V3DDIV 0x03c +#define CM_CAM0CTL 0x040 +#define CM_CAM0DIV 0x044 +#define CM_CAM1CTL 0x048 +#define CM_CAM1DIV 0x04c +#define CM_CCP2CTL 0x050 +#define CM_CCP2DIV 0x054 +#define CM_DSI0ECTL0x058 +#define CM_DSI0EDIV0x05c +#define CM_DSI0PCTL0x060 +#define CM_DSI0PDIV0x064 +#define CM_DPICTL 0x068 +#define CM_DPIDIV 0x06c +#define CM_GP0CTL 0x070 +#define CM_GP0DIV 0x074 +#define CM_GP1CTL 0x078 +#define CM_GP1DIV 0x07c +#define CM_GP2CTL 0x080 +#define CM_GP2DIV 0x084 +#define CM_HSMCTL 0x088 +#define CM_HSMDIV 0x08c +#define CM_OTPCTL 0x090 +#define CM_OTPDIV 0x094 +#define CM_PWMCTL 0x0a0 +#define CM_PWMDIV 0x0a4 +#define CM_SMICTL 0x0b0 +#define CM_SMIDIV 0x0b4 +#define CM_TSENSCTL0x0e0 +#define CM_TSENSDIV0x0e4 +#define CM_TIMERCTL0x0e8 +#define CM_TIMERDIV0x0ec +#define CM_UARTCTL 0x0f0 +#define CM_UARTDIV 0x0f4 +#define CM_VECCTL 0x0f8 +#define CM_VECDIV 0x0fc +#define CM_PULSECTL0x190 +#define CM_PULSEDIV0x194
[PATCH v2 2/4] clk: bcm2835: Add binding docs for the new platform clock driver.
Previously we've only supported a few fixed clocks based on assumptions about how the firmware sets up the clocks, but this binding will let us control the actual (audio power domain) clock manager. Signed-off-by: Eric Anholt --- .../bindings/clock/brcm,bcm2835-cprman.txt | 45 + include/dt-bindings/clock/bcm2835.h| 47 ++ 2 files changed, 92 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt create mode 100644 include/dt-bindings/clock/bcm2835.h diff --git a/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt b/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt new file mode 100644 index 000..e56a1df --- /dev/null +++ b/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt @@ -0,0 +1,45 @@ +Broadcom BCM2835 CPRMAN clocks + +This binding uses the common clock binding: +Documentation/devicetree/bindings/clock/clock-bindings.txt + +The CPRMAN clock controller generates clocks in the audio power domain +of the BCM2835. There is a level of PLLs deriving from an external +oscillator, a level of PLL dividers that produce channels off of the +few PLLs, and a level of mostly-generic clock generators sourcing from +the PLL channels. Most other hardware components source from the +clock generators, but a few (like the ARM or HDMI) will source from +the PLL dividers directly. + +Required properties: +- compatible: Should be "brcm,bcm2835-cprman" +- #clock-cells:Should be <1>. The permitted clock-specifier values can be + found in include/dt-bindings/clock/bcm2835.h +- reg: Specifies base physical address and size of the registers +- clocks: The external oscillator clock phandle + +Example: + + clk_osc: clock@3 { + compatible = "fixed-clock"; + reg = <3>; + #clock-cells = <0>; + clock-output-names = "osc"; + clock-frequency = <1920>; + }; + + clocks: cprman@7e101000 { + compatible = "brcm,bcm2835-cprman"; + #clock-cells = <1>; + reg = <0x7e101000 0x2000>; + clocks = <&clk_osc>; + }; + + i2c0: i2c@7e205000 { + compatible = "brcm,bcm2835-i2c"; + reg = <0x7e205000 0x1000>; + interrupts = <2 21>; + clocks = <&clocks BCM2835_CLOCK_VPU>; + #address-cells = <1>; + #size-cells = <0>; + }; diff --git a/include/dt-bindings/clock/bcm2835.h b/include/dt-bindings/clock/bcm2835.h new file mode 100644 index 000..d323efa --- /dev/null +++ b/include/dt-bindings/clock/bcm2835.h @@ -0,0 +1,47 @@ +/* + * 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. + */ + +#define BCM2835_PLLA 0 +#define BCM2835_PLLB 1 +#define BCM2835_PLLC 2 +#define BCM2835_PLLD 3 +#define BCM2835_PLLH 4 + +#define BCM2835_PLLA_CORE 5 +#define BCM2835_PLLA_PER 6 +#define BCM2835_PLLB_ARM 7 +#define BCM2835_PLLC_CORE0 8 +#define BCM2835_PLLC_CORE1 9 +#define BCM2835_PLLC_CORE2 10 +#define BCM2835_PLLC_PER 11 +#define BCM2835_PLLD_CORE 12 +#define BCM2835_PLLD_PER 13 +#define BCM2835_PLLH_RCAL 14 +#define BCM2835_PLLH_AUX 15 +#define BCM2835_PLLH_PIX 16 + +#define BCM2835_CLOCK_TIMER17 +#define BCM2835_CLOCK_OTP 18 +#define BCM2835_CLOCK_UART 19 +#define BCM2835_CLOCK_VPU 20 +#define BCM2835_CLOCK_V3D 21 +#define BCM2835_CLOCK_ISP 22 +#define BCM2835_CLOCK_H264 23 +#define BCM2835_CLOCK_VEC 24 +#define BCM2835_CLOCK_HSM 25 +#define BCM2835_CLOCK_SDRAM26 +#define BCM2835_CLOCK_TSENS27 +#define BCM2835_CLOCK_EMMC 28 +#define BCM2835_CLOCK_PERI_IMAGE 29 + +#define BCM2835_CLOCK_COUNT30 -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
BCM2835 auxiliary peripheral clocks.
This is a followup to the main audio domain clocks series I just posted. There's a clock gate register controlling the clocks for a few extra peripherals, and Martin Sperl has been working on the SPI driver for 2/3 of them (the other is a simple UART). This gives those drivers the clock gate enable they need to access their registers. The full series is available for testing at: https://github.com/anholt/linux/tree/bcm2385-clock-aux -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2/3] clk: bcm2835: Add a driver for the auxiliary peripheral clock gates.
There are a pair of SPI masters and a mini UART that were last minute additions. As a result, they didn't get integrated in the same way as the other gates off of the VPU clock in CPRMAN. Signed-off-by: Eric Anholt --- drivers/clk/bcm/Makefile | 1 + drivers/clk/bcm/clk-bcm2835-aux.c | 80 +++ 2 files changed, 81 insertions(+) create mode 100644 drivers/clk/bcm/clk-bcm2835-aux.c diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile index ee2349b..3082d68 100644 --- a/drivers/clk/bcm/Makefile +++ b/drivers/clk/bcm/Makefile @@ -4,4 +4,5 @@ obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o obj-$(CONFIG_COMMON_CLK_IPROC) += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o +obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835-aux.o obj-$(CONFIG_ARCH_BCM_CYGNUS) += clk-cygnus.o diff --git a/drivers/clk/bcm/clk-bcm2835-aux.c b/drivers/clk/bcm/clk-bcm2835-aux.c new file mode 100644 index 000..1efa6fb --- /dev/null +++ b/drivers/clk/bcm/clk-bcm2835-aux.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2015 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 + +static int bcm2835_aux_clk_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct clk_onecell_data *onecell; + const char *parent; + struct clk *parent_clk; + void __iomem *reg; + + parent_clk = of_clk_get(dev->of_node, 0); + if (IS_ERR(parent_clk)) + return PTR_ERR(parent_clk); + parent = __clk_get_name(parent_clk); + + reg = of_iomap(dev->of_node, 0); + if (!reg) + return -ENODEV; + + onecell = kmalloc(sizeof(*onecell), GFP_KERNEL); + if (!onecell) + return -ENOMEM; + onecell->clk_num = BCM2835_AUX_CLOCK_COUNT; + onecell->clks = kzalloc(sizeof(*onecell->clks) * + BCM2835_AUX_CLOCK_COUNT, GFP_KERNEL); + if (!onecell->clks) + return -ENOMEM; + + onecell->clks[BCM2835_AUX_CLOCK_UART] = + clk_register_gate(dev, "aux_uart", parent, 0, reg, 0, 0, NULL); + + onecell->clks[BCM2835_AUX_CLOCK_SPI1] = + clk_register_gate(dev, "aux_spi1", parent, 0, reg, 1, 0, NULL); + + onecell->clks[BCM2835_AUX_CLOCK_SPI2] = + clk_register_gate(dev, "aux_spi2", parent, 0, reg, 2, 0, NULL); + + return of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get, + onecell); +} + +static const struct of_device_id bcm2835_aux_clk_of_match[] = { + { .compatible = "brcm,bcm2835-aux-clock", }, + {}, +}; +MODULE_DEVICE_TABLE(of, bcm2835_aux_clk_of_match); + +static struct platform_driver bcm2835_aux_clk_driver = { + .driver = { + .name = "bcm2835-aux-clk", + .of_match_table = bcm2835_aux_clk_of_match, + }, + .probe = bcm2835_aux_clk_probe, +}; +builtin_platform_driver(bcm2835_aux_clk_driver); + +MODULE_AUTHOR("Eric Anholt "); +MODULE_DESCRIPTION("BCM2835 auxiliary peripheral clock driver"); +MODULE_LICENSE("GPL v2"); -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/3] clk: bcm2835: Add bindings for the auxiliary peripheral clock gates.
These will be used for enabling UART1, SPI1, and SPI2. Signed-off-by: Eric Anholt --- .../bindings/clock/brcm,bcm2835-aux-clock.txt | 30 ++ include/dt-bindings/clock/bcm2835-aux.h| 17 2 files changed, 47 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/brcm,bcm2835-aux-clock.txt create mode 100644 include/dt-bindings/clock/bcm2835-aux.h diff --git a/Documentation/devicetree/bindings/clock/brcm,bcm2835-aux-clock.txt b/Documentation/devicetree/bindings/clock/brcm,bcm2835-aux-clock.txt new file mode 100644 index 000..f5ce80a --- /dev/null +++ b/Documentation/devicetree/bindings/clock/brcm,bcm2835-aux-clock.txt @@ -0,0 +1,30 @@ +Broadcom BCM2835 auxiliary peripheral clocks + +This binding uses the common clock binding: +Documentation/devicetree/bindings/clock/clock-bindings.txt + +This controls the clock gating for the BCM2835 auxiliary peripherals +(UART, SPI1, and SPI2). + +Required properties: +- compatible: Should be "brcm,bcm2835-aux-clock" +- #clock-cells:Should be <1>. The permitted clock-specifier values can be + found in include/dt-bindings/clock/bcm2835-aux.h +- reg: Specifies base physical address and size of the gate register +- clocks: The parent clock phandle + +Example: + + clocks: cprman@7e101000 { + compatible = "brcm,bcm2835-cprman"; + #clock-cells = <1>; + reg = <0x7e101000 0x2000>; + clocks = <&clk_osc>; + }; + + aux_clocks: aux-clocks@0x7e215004 { + compatible = "brcm,bcm2835-aux-clock"; + #clock-cells = <1>; + reg = <0x7e215004 0x4>; + clocks = <&clocks BCM2835_CLOCK_VPU>; + }; diff --git a/include/dt-bindings/clock/bcm2835-aux.h b/include/dt-bindings/clock/bcm2835-aux.h new file mode 100644 index 000..d91156e --- /dev/null +++ b/include/dt-bindings/clock/bcm2835-aux.h @@ -0,0 +1,17 @@ +/* + * 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. + */ + +#define BCM2835_AUX_CLOCK_UART 0 +#define BCM2835_AUX_CLOCK_SPI1 1 +#define BCM2835_AUX_CLOCK_SPI2 2 +#define BCM2835_AUX_CLOCK_COUNT3 -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 3/3] ARM: bcm2835: Add the auxiliary clocks to the device tree.
These will be used for enabling UART1, SPI1, and SPI2. Signed-off-by: Eric Anholt --- arch/arm/boot/dts/bcm2835.dtsi | 7 +++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi index a6a55b7..7c37956 100644 --- a/arch/arm/boot/dts/bcm2835.dtsi +++ b/arch/arm/boot/dts/bcm2835.dtsi @@ -73,6 +73,13 @@ clocks = <&clk_osc>; }; + aux_clocks: aux-clocks@0x7e215004 { + compatible = "brcm,bcm2835-aux-clock"; + #clock-cells = <1>; + reg = <0x7e215004 0x4>; + clocks = <&clocks BCM2835_CLOCK_VPU>; + }; + rng@7e104000 { compatible = "brcm,bcm2835-rng"; reg = <0x7e104000 0x10>; -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] dmaengine: bcm2835-dma: Convert to use DMA pool
Peter Ujfalusi writes: > f93178291712 dmaengine: bcm2835-dma: Fix memory leak when stopping a >running transfer > > Fixed the memleak, but introduced another issue: the terminate_all callback > might be called with interrupts disabled and the dma_free_coherent() is > not allowed to be called when IRQs are disabled. > Convert the driver to use dma_pool_* for managing the list of control > blocks for the transfer. > > Fixes: f93178291712 ("dmaengine: bcm2835-dma: Fix memory leak when stopping a > running transfer") > Signed-off-by: Peter Ujfalusi It sounds like you got positive testing feedback. Using the DMA pool for our bcm2835_dma_cbs makes sense to me, too. Reviewed-by: Eric Anholt signature.asc Description: PGP signature
Re: [PATCH 3/9] drm/vc4: Add create and map BO ioctls.
Michel Dänzer writes: > On 08.12.2015 10:16, Eric Anholt wrote: >> Emil Velikov writes: >> >>> Hi Eric, >>> >>> A couple of suggestions/requests on the UAPI header side >>> >>> On 1 December 2015 at 20:35, Eric Anholt wrote: >>> >>>> --- /dev/null >>>> +++ b/include/uapi/drm/vc4_drm.h >>> >>>> +#include >>>> + >>> Can we make this a "drm.h" ? >> >> Nope. >> >> include/uapi/drm/vc4_drm.h:27:17: fatal error: drm.h: No such file or >> directory > > What happened to include/uapi/drm/drm.h in that tree? Looks like it's just versus "drm.h" failure. I've changed over to "drm.h" signature.asc Description: PGP signature
Re: [PATCH v3 4/4] clk: bcm2835: Add PWM clock support to the device tree
Stefan Wahren writes: > Hi Remi, > > Am 07.12.2015 um 19:17 schrieb Remi Pommarel: >> Hi Stefan, >> >> On Sun, Dec 06, 2015 at 10:16:25PM +0100, Stefan Wahren wrote: >>> Hi Remi, >>> >>> please send this patch to devicet...@vger.kernel.org. >> >> Ok, just to be sure I understand the process here. I should resend a new >> version of the whole patchset including the devicetree mailing list as >> recipent. Then the first 3 patches will eventually get pushed by a clock >> subsystem maintainer. And finally this last patch will be pushed by a >> devicetree maintainer. >> >> Am I right here ? > > sorry for the confusion. I mean that you send a copy to > devicet...@vger.kernel.org so subscribers have a chance to review. > > I'm not sure but according to your subject you suggest that this dts > patch should go through clock subsystem which isn't optimal. This should > be better applied by Stephen or Eric. It would be applied by me, but that's for me to worry about, not the patch submitter. The subject prefix would be "ARM: bcm2835: ", but that's trivial for me to fix when applying, not the kind of thing worth asking for a respin for. signature.asc Description: PGP signature
[PATCH v2 0/9] VC4 3D rendering support.
Updated version of the patch series for Emil's comments about vc4_drm.h. I also pulled in some improvements to the validation code which I'd written in Mesa and failed to propagate to this branch. The series can be found at: https://github.com/anholt/linux/tree/vc4-kms-v3d-squash-2 and a version for booting and testing can be found at: https://github.com/anholt/linux/tree/vc4-kms-v3d-squash-2-boot Eric Anholt (9): drm: Create a driver hook for allocating GEM object structs. drm/vc4: Add a BO cache. drm/vc4: Add create and map BO ioctls. drm/vc4: Add an API for creating GPU shaders in GEM BOs. drm/vc4: Fix a typo in a V3D debug register. drm/vc4: Bind and initialize the V3D engine. drm/vc4: Add support for drawing 3D frames. drm/vc4: Add support for async pageflips. drm/vc4: Add an interface for capturing the GPU state after a hang. drivers/gpu/drm/drm_gem_cma_helper.c | 10 +- drivers/gpu/drm/vc4/Makefile | 11 +- drivers/gpu/drm/vc4/vc4_bo.c | 517 - drivers/gpu/drm/vc4/vc4_crtc.c | 99 +++- drivers/gpu/drm/vc4/vc4_debugfs.c | 3 + drivers/gpu/drm/vc4/vc4_drv.c | 36 +- drivers/gpu/drm/vc4/vc4_drv.h | 318 +- drivers/gpu/drm/vc4/vc4_gem.c | 867 +++ drivers/gpu/drm/vc4/vc4_irq.c | 210 +++ drivers/gpu/drm/vc4/vc4_kms.c | 149 - drivers/gpu/drm/vc4/vc4_packet.h | 399 + drivers/gpu/drm/vc4/vc4_plane.c| 40 ++ drivers/gpu/drm/vc4/vc4_qpu_defines.h | 264 + drivers/gpu/drm/vc4/vc4_regs.h | 2 +- drivers/gpu/drm/vc4/vc4_render_cl.c| 634 drivers/gpu/drm/vc4/vc4_trace.h| 63 ++ drivers/gpu/drm/vc4/vc4_trace_points.c | 14 + drivers/gpu/drm/vc4/vc4_v3d.c | 262 + drivers/gpu/drm/vc4/vc4_validate.c | 900 + drivers/gpu/drm/vc4/vc4_validate_shaders.c | 513 include/drm/drmP.h | 7 + include/uapi/drm/Kbuild| 1 + include/uapi/drm/vc4_drm.h | 279 + 23 files changed, 5577 insertions(+), 21 deletions(-) create mode 100644 drivers/gpu/drm/vc4/vc4_gem.c create mode 100644 drivers/gpu/drm/vc4/vc4_irq.c create mode 100644 drivers/gpu/drm/vc4/vc4_packet.h create mode 100644 drivers/gpu/drm/vc4/vc4_qpu_defines.h create mode 100644 drivers/gpu/drm/vc4/vc4_render_cl.c create mode 100644 drivers/gpu/drm/vc4/vc4_trace.h create mode 100644 drivers/gpu/drm/vc4/vc4_trace_points.c create mode 100644 drivers/gpu/drm/vc4/vc4_v3d.c create mode 100644 drivers/gpu/drm/vc4/vc4_validate.c create mode 100644 drivers/gpu/drm/vc4/vc4_validate_shaders.c create mode 100644 include/uapi/drm/vc4_drm.h -- 2.6.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 1/9] drm: Create a driver hook for allocating GEM object structs.
The CMA helpers had no way for a driver to extend the struct with its own fields. Since the CMA helpers are mostly "Allocate a drm_gem_cma_object, then fill in a few fields", it's hard to write as pure helpers without passing in a driver callback for the allocate step. Signed-off-by: Eric Anholt Reviewed-by: Daniel Vetter --- drivers/gpu/drm/drm_gem_cma_helper.c | 10 ++ include/drm/drmP.h | 7 +++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c index e109b49..0f7b00ba 100644 --- a/drivers/gpu/drm/drm_gem_cma_helper.c +++ b/drivers/gpu/drm/drm_gem_cma_helper.c @@ -59,11 +59,13 @@ __drm_gem_cma_create(struct drm_device *drm, size_t size) struct drm_gem_object *gem_obj; int ret; - cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL); - if (!cma_obj) + if (drm->driver->gem_create_object) + gem_obj = drm->driver->gem_create_object(drm, size); + else + gem_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL); + if (!gem_obj) return ERR_PTR(-ENOMEM); - - gem_obj = &cma_obj->base; + cma_obj = container_of(gem_obj, struct drm_gem_cma_object, base); ret = drm_gem_object_init(drm, gem_obj, size); if (ret) diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 0b921ae..22ff162 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -580,6 +580,13 @@ struct drm_driver { int (*gem_open_object) (struct drm_gem_object *, struct drm_file *); void (*gem_close_object) (struct drm_gem_object *, struct drm_file *); + /** +* Hook for allocating the GEM object struct, for use by core +* helpers. +*/ + struct drm_gem_object *(*gem_create_object)(struct drm_device *dev, + size_t size); + /* prime: */ /* export handle -> fd (see drm_gem_prime_handle_to_fd() helper) */ int (*prime_handle_to_fd)(struct drm_device *dev, struct drm_file *file_priv, -- 2.6.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 2/9] drm/vc4: Add a BO cache.
We need to allocate new BOs in the kernel as part of each frame, but the CMA allocator is way too slow for that. As an optimization, keep track of recently-freed BOs and reuse them, with a 1 second timeout to fully free them back to the system. This improves 3D performance by about 15%. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_bo.c | 336 +- drivers/gpu/drm/vc4/vc4_debugfs.c | 1 + drivers/gpu/drm/vc4/vc4_drv.c | 6 +- drivers/gpu/drm/vc4/vc4_drv.h | 49 +- 4 files changed, 384 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index ab9f510..18faa5b 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -12,19 +12,229 @@ * access to system memory with no MMU in between. To support it, we * use the GEM CMA helper functions to allocate contiguous ranges of * physical memory for our BOs. + * + * Since the CMA allocator is very slow, we keep a cache of recently + * freed BOs around so that the kernel's allocation of objects for 3D + * rendering can return quickly. */ #include "vc4_drv.h" -struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t size) +static void vc4_bo_stats_dump(struct vc4_dev *vc4) +{ + DRM_INFO("num bos allocated: %d\n", +vc4->bo_stats.num_allocated); + DRM_INFO("size bos allocated: %dkb\n", +vc4->bo_stats.size_allocated / 1024); + DRM_INFO("num bos used: %d\n", +vc4->bo_stats.num_allocated - vc4->bo_stats.num_cached); + DRM_INFO("size bos used: %dkb\n", +(vc4->bo_stats.size_allocated - + vc4->bo_stats.size_cached) / 1024); + DRM_INFO("num bos cached: %d\n", +vc4->bo_stats.num_cached); + DRM_INFO("size bos cached: %dkb\n", +vc4->bo_stats.size_cached / 1024); +} + +#ifdef CONFIG_DEBUG_FS +int vc4_bo_stats_debugfs(struct seq_file *m, void *unused) +{ + struct drm_info_node *node = (struct drm_info_node *)m->private; + struct drm_device *dev = node->minor->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_bo_stats stats; + + /* Take a snapshot of the current stats with the lock held. */ + mutex_lock(&vc4->bo_lock); + stats = vc4->bo_stats; + mutex_unlock(&vc4->bo_lock); + + seq_printf(m, "num bos allocated: %d\n", + stats.num_allocated); + seq_printf(m, "size bos allocated: %dkb\n", + stats.size_allocated / 1024); + seq_printf(m, "num bos used: %d\n", + stats.num_allocated - stats.num_cached); + seq_printf(m, "size bos used: %dkb\n", + (stats.size_allocated - stats.size_cached) / 1024); + seq_printf(m, "num bos cached: %d\n", + stats.num_cached); + seq_printf(m, "size bos cached: %dkb\n", + stats.size_cached / 1024); + + return 0; +} +#endif + +static uint32_t bo_page_index(size_t size) +{ + return (size / PAGE_SIZE) - 1; +} + +/* Must be called with bo_lock held. */ +static void vc4_bo_destroy(struct vc4_bo *bo) { + struct drm_gem_object *obj = &bo->base.base; + struct vc4_dev *vc4 = to_vc4_dev(obj->dev); + + vc4->bo_stats.num_allocated--; + vc4->bo_stats.size_allocated -= obj->size; + drm_gem_cma_free_object(obj); +} + +/* Must be called with bo_lock held. */ +static void vc4_bo_remove_from_cache(struct vc4_bo *bo) +{ + struct drm_gem_object *obj = &bo->base.base; + struct vc4_dev *vc4 = to_vc4_dev(obj->dev); + + vc4->bo_stats.num_cached--; + vc4->bo_stats.size_cached -= obj->size; + + list_del(&bo->unref_head); + list_del(&bo->size_head); +} + +static struct list_head *vc4_get_cache_list_for_size(struct drm_device *dev, +size_t size) +{ + struct vc4_dev *vc4 = to_vc4_dev(dev); + uint32_t page_index = bo_page_index(size); + + if (vc4->bo_cache.size_list_size <= page_index) { + uint32_t new_size = max(vc4->bo_cache.size_list_size * 2, + page_index + 1); + struct list_head *new_list; + uint32_t i; + + new_list = kmalloc_array(new_size, sizeof(struct list_head), +GFP_KERNEL); + if (!new_list) + return NULL; + + /* Rebase the old cached BO lists to their new list +* head locations. +*/ + for (i = 0; i < vc4->bo_cache.size_list_size; i++) { +
[PATCH v2 3/9] drm/vc4: Add create and map BO ioctls.
While there exist dumb APIs for creating and mapping BOs, one of the rules is that drivers doing 3D acceleration have to provide their own APIs for buffer allocation (besides, the pitch/height parameters of the dumb alloc don't really make sense for a lot of 3D allocations). Signed-off-by: Eric Anholt --- v2: Use __u32-style types, use "drm.h" instead of . drivers/gpu/drm/vc4/vc4_bo.c | 41 ++ drivers/gpu/drm/vc4/vc4_drv.c | 3 ++ drivers/gpu/drm/vc4/vc4_drv.h | 4 +++ include/uapi/drm/Kbuild | 1 + include/uapi/drm/vc4_drm.h| 68 +++ 5 files changed, 117 insertions(+) create mode 100644 include/uapi/drm/vc4_drm.h diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index 18faa5b..06cba26 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -19,6 +19,7 @@ */ #include "vc4_drv.h" +#include "uapi/drm/vc4_drm.h" static void vc4_bo_stats_dump(struct vc4_dev *vc4) { @@ -346,6 +347,46 @@ static void vc4_bo_cache_time_timer(unsigned long data) schedule_work(&vc4->bo_cache.time_work); } +int vc4_create_bo_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_vc4_create_bo *args = data; + struct vc4_bo *bo = NULL; + int ret; + + /* +* We can't allocate from the BO cache, because the BOs don't +* get zeroed, and that might leak data between users. +*/ + bo = vc4_bo_create(dev, args->size, false); + if (!bo) + return -ENOMEM; + + ret = drm_gem_handle_create(file_priv, &bo->base.base, &args->handle); + drm_gem_object_unreference_unlocked(&bo->base.base); + + return ret; +} + +int vc4_mmap_bo_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_vc4_mmap_bo *args = data; + struct drm_gem_object *gem_obj; + + gem_obj = drm_gem_object_lookup(dev, file_priv, args->handle); + if (!gem_obj) { + DRM_ERROR("Failed to look up GEM BO %d\n", args->handle); + return -EINVAL; + } + + /* The mmap offset was set up at BO allocation time. */ + args->offset = drm_vma_node_offset_addr(&gem_obj->vma_node); + + drm_gem_object_unreference_unlocked(gem_obj); + return 0; +} + void vc4_bo_cache_init(struct drm_device *dev) { struct vc4_dev *vc4 = to_vc4_dev(dev); diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index da041fa..5fa4688 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -16,6 +16,7 @@ #include #include "drm_fb_cma_helper.h" +#include "uapi/drm/vc4_drm.h" #include "vc4_drv.h" #include "vc4_regs.h" @@ -73,6 +74,8 @@ static const struct file_operations vc4_drm_fops = { }; static const struct drm_ioctl_desc vc4_drm_ioctls[] = { + DRM_IOCTL_DEF_DRV(VC4_CREATE_BO, vc4_create_bo_ioctl, 0), + DRM_IOCTL_DEF_DRV(VC4_MMAP_BO, vc4_mmap_bo_ioctl, 0), }; static struct drm_driver vc4_drm_driver = { diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 39a1ff5..fddb0a0 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -155,6 +155,10 @@ int vc4_dumb_create(struct drm_file *file_priv, struct drm_mode_create_dumb *args); struct dma_buf *vc4_prime_export(struct drm_device *dev, struct drm_gem_object *obj, int flags); +int vc4_create_bo_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int vc4_mmap_bo_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); void vc4_bo_cache_init(struct drm_device *dev); void vc4_bo_cache_destroy(struct drm_device *dev); int vc4_bo_stats_debugfs(struct seq_file *m, void *arg); diff --git a/include/uapi/drm/Kbuild b/include/uapi/drm/Kbuild index 38d4370..974fcd5 100644 --- a/include/uapi/drm/Kbuild +++ b/include/uapi/drm/Kbuild @@ -17,4 +17,5 @@ header-y += tegra_drm.h header-y += via_drm.h header-y += vmwgfx_drm.h header-y += msm_drm.h +header-y += vc4_drm.h header-y += virtgpu_drm.h diff --git a/include/uapi/drm/vc4_drm.h b/include/uapi/drm/vc4_drm.h new file mode 100644 index 000..219d34c --- /dev/null +++ b/include/uapi/drm/vc4_drm.h @@ -0,0 +1,68 @@ +/* + * Copyright © 2014-2015 Broadcom + * + * 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
[PATCH v2 5/9] drm/vc4: Fix a typo in a V3D debug register.
Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_regs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index 9e4e904..4e52a0a 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -154,7 +154,7 @@ #define V3D_PCTRS14 0x006f4 #define V3D_PCTR15 0x006f8 #define V3D_PCTRS15 0x006fc -#define V3D_BGE 0x00f00 +#define V3D_DBGE 0x00f00 #define V3D_FDBGO0x00f04 #define V3D_FDBGB0x00f08 #define V3D_FDBGR0x00f0c -- 2.6.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 4/9] drm/vc4: Add an API for creating GPU shaders in GEM BOs.
Since we have no MMU, the kernel needs to validate that the submitted shader code won't make any accesses to memory that the user doesn't control, which involves banning some operations (general purpose DMA writes), and tracking where we need to write out pointers for other operations (texture sampling). Once it's validated, we return a GEM BO containing the shader, which doesn't allow mapping for write or exporting to other subsystems. Signed-off-by: Eric Anholt --- v2: Use __u32-style types. drivers/gpu/drm/vc4/Makefile | 3 +- drivers/gpu/drm/vc4/vc4_bo.c | 140 drivers/gpu/drm/vc4/vc4_drv.c | 9 +- drivers/gpu/drm/vc4/vc4_drv.h | 50 +++ drivers/gpu/drm/vc4/vc4_qpu_defines.h | 264 +++ drivers/gpu/drm/vc4/vc4_validate_shaders.c | 513 + include/uapi/drm/vc4_drm.h | 25 ++ 7 files changed, 999 insertions(+), 5 deletions(-) create mode 100644 drivers/gpu/drm/vc4/vc4_qpu_defines.h create mode 100644 drivers/gpu/drm/vc4/vc4_validate_shaders.c diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile index 32b4f9c..eb776a6 100644 --- a/drivers/gpu/drm/vc4/Makefile +++ b/drivers/gpu/drm/vc4/Makefile @@ -10,7 +10,8 @@ vc4-y := \ vc4_kms.o \ vc4_hdmi.o \ vc4_hvs.o \ - vc4_plane.o + vc4_plane.o \ + vc4_validate_shaders.o vc4-$(CONFIG_DEBUG_FS) += vc4_debugfs.o diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index 06cba26..18dfe3e 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -79,6 +79,12 @@ static void vc4_bo_destroy(struct vc4_bo *bo) struct drm_gem_object *obj = &bo->base.base; struct vc4_dev *vc4 = to_vc4_dev(obj->dev); + if (bo->validated_shader) { + kfree(bo->validated_shader->texture_samples); + kfree(bo->validated_shader); + bo->validated_shader = NULL; + } + vc4->bo_stats.num_allocated--; vc4->bo_stats.size_allocated -= obj->size; drm_gem_cma_free_object(obj); @@ -315,6 +321,12 @@ void vc4_free_object(struct drm_gem_object *gem_bo) goto out; } + if (bo->validated_shader) { + kfree(bo->validated_shader->texture_samples); + kfree(bo->validated_shader); + bo->validated_shader = NULL; + } + bo->free_time = jiffies; list_add(&bo->size_head, cache_list); list_add(&bo->unref_head, &vc4->bo_cache.time_list); @@ -347,6 +359,78 @@ static void vc4_bo_cache_time_timer(unsigned long data) schedule_work(&vc4->bo_cache.time_work); } +struct dma_buf * +vc4_prime_export(struct drm_device *dev, struct drm_gem_object *obj, int flags) +{ + struct vc4_bo *bo = to_vc4_bo(obj); + + if (bo->validated_shader) { + DRM_ERROR("Attempting to export shader BO\n"); + return ERR_PTR(-EINVAL); + } + + return drm_gem_prime_export(dev, obj, flags); +} + +int vc4_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct drm_gem_object *gem_obj; + struct vc4_bo *bo; + int ret; + + ret = drm_gem_mmap(filp, vma); + if (ret) + return ret; + + gem_obj = vma->vm_private_data; + bo = to_vc4_bo(gem_obj); + + if (bo->validated_shader && (vma->vm_flags & VM_WRITE)) { + DRM_ERROR("mmaping of shader BOs for writing not allowed.\n"); + return -EINVAL; + } + + /* +* Clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and set the +* vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want to map +* the whole buffer. +*/ + vma->vm_flags &= ~VM_PFNMAP; + vma->vm_pgoff = 0; + + ret = dma_mmap_writecombine(bo->base.base.dev->dev, vma, + bo->base.vaddr, bo->base.paddr, + vma->vm_end - vma->vm_start); + if (ret) + drm_gem_vm_close(vma); + + return ret; +} + +int vc4_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) +{ + struct vc4_bo *bo = to_vc4_bo(obj); + + if (bo->validated_shader && (vma->vm_flags & VM_WRITE)) { + DRM_ERROR("mmaping of shader BOs for writing not allowed.\n"); + return -EINVAL; + } + + return drm_gem_cma_prime_mmap(obj, vma); +} + +void *vc4_prime_vmap(struct drm_gem_object *obj) +{ + struct vc4_bo *bo = to_vc4_bo(obj); + + if (bo->validated_shader) { + DRM_ERROR("mmaping of shader BOs not allowed.\n"); + return ERR_PTR(-EINVAL); + } + +
[PATCH v2 9/9] drm/vc4: Add an interface for capturing the GPU state after a hang.
This can be parsed with vc4-gpu-tools tools for trying to figure out what was going on. Signed-off-by: Eric Anholt --- v2: Use __u32-style types. drivers/gpu/drm/vc4/vc4_drv.c | 2 + drivers/gpu/drm/vc4/vc4_drv.h | 4 + drivers/gpu/drm/vc4/vc4_gem.c | 185 ++ include/uapi/drm/vc4_drm.h| 45 ++ 4 files changed, 236 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 2cfee59..97226b6 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -80,6 +80,8 @@ static const struct drm_ioctl_desc vc4_drm_ioctls[] = { DRM_IOCTL_DEF_DRV(VC4_CREATE_BO, vc4_create_bo_ioctl, 0), DRM_IOCTL_DEF_DRV(VC4_MMAP_BO, vc4_mmap_bo_ioctl, 0), DRM_IOCTL_DEF_DRV(VC4_CREATE_SHADER_BO, vc4_create_shader_bo_ioctl, 0), + DRM_IOCTL_DEF_DRV(VC4_GET_HANG_STATE, vc4_get_hang_state_ioctl, + DRM_ROOT_ONLY), }; static struct drm_driver vc4_drm_driver = { diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index f9927d8..080865e 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -19,6 +19,8 @@ struct vc4_dev { struct drm_fbdev_cma *fbdev; + struct vc4_hang_state *hang_state; + /* The kernel-space BO cache. Tracks buffers that have been * unreferenced by all other users (refcounts of 0!) but not * yet freed, so we can do cheap allocations. @@ -361,6 +363,8 @@ int vc4_create_shader_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int vc4_mmap_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +int vc4_get_hang_state_ioctl(struct drm_device *dev, void *data, +struct drm_file *file_priv); int vc4_mmap(struct file *filp, struct vm_area_struct *vma); int vc4_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); void *vc4_prime_vmap(struct drm_gem_object *obj); diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 5fb0556..39f29e7 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -40,6 +40,186 @@ vc4_queue_hangcheck(struct drm_device *dev) round_jiffies_up(jiffies + msecs_to_jiffies(100))); } +struct vc4_hang_state { + struct drm_vc4_get_hang_state user_state; + + u32 bo_count; + struct drm_gem_object **bo; +}; + +static void +vc4_free_hang_state(struct drm_device *dev, struct vc4_hang_state *state) +{ + unsigned int i; + + mutex_lock(&dev->struct_mutex); + for (i = 0; i < state->user_state.bo_count; i++) + drm_gem_object_unreference(state->bo[i]); + mutex_unlock(&dev->struct_mutex); + + kfree(state); +} + +int +vc4_get_hang_state_ioctl(struct drm_device *dev, void *data, +struct drm_file *file_priv) +{ + struct drm_vc4_get_hang_state *get_state = data; + struct drm_vc4_get_hang_state_bo *bo_state; + struct vc4_hang_state *kernel_state; + struct drm_vc4_get_hang_state *state; + struct vc4_dev *vc4 = to_vc4_dev(dev); + unsigned long irqflags; + u32 i; + int ret; + + spin_lock_irqsave(&vc4->job_lock, irqflags); + kernel_state = vc4->hang_state; + if (!kernel_state) { + spin_unlock_irqrestore(&vc4->job_lock, irqflags); + return -ENOENT; + } + state = &kernel_state->user_state; + + /* If the user's array isn't big enough, just return the +* required array size. +*/ + if (get_state->bo_count < state->bo_count) { + get_state->bo_count = state->bo_count; + spin_unlock_irqrestore(&vc4->job_lock, irqflags); + return 0; + } + + vc4->hang_state = NULL; + spin_unlock_irqrestore(&vc4->job_lock, irqflags); + + /* Save the user's BO pointer, so we don't stomp it with the memcpy. */ + state->bo = get_state->bo; + memcpy(get_state, state, sizeof(*state)); + + bo_state = kcalloc(state->bo_count, sizeof(*bo_state), GFP_KERNEL); + if (!bo_state) { + ret = -ENOMEM; + goto err_free; + } + + for (i = 0; i < state->bo_count; i++) { + struct vc4_bo *vc4_bo = to_vc4_bo(kernel_state->bo[i]); + u32 handle; + + ret = drm_gem_handle_create(file_priv, kernel_state->bo[i], + &handle); + + if (ret) { + state->bo_count = i - 1; + goto err; + } + bo_state[i].handle = handle; + bo_state[i].paddr = vc4_bo->base.paddr; +
[PATCH v2 6/9] drm/vc4: Bind and initialize the V3D engine.
This is the component of the GPU that does 3D rendering. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/Makefile | 1 + drivers/gpu/drm/vc4/vc4_debugfs.c | 2 + drivers/gpu/drm/vc4/vc4_drv.c | 1 + drivers/gpu/drm/vc4/vc4_drv.h | 13 +++ drivers/gpu/drm/vc4/vc4_v3d.c | 225 ++ 5 files changed, 242 insertions(+) create mode 100644 drivers/gpu/drm/vc4/vc4_v3d.c diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile index eb776a6..e87a6f2 100644 --- a/drivers/gpu/drm/vc4/Makefile +++ b/drivers/gpu/drm/vc4/Makefile @@ -11,6 +11,7 @@ vc4-y := \ vc4_hdmi.o \ vc4_hvs.o \ vc4_plane.o \ + vc4_v3d.o \ vc4_validate_shaders.o vc4-$(CONFIG_DEBUG_FS) += vc4_debugfs.o diff --git a/drivers/gpu/drm/vc4/vc4_debugfs.c b/drivers/gpu/drm/vc4/vc4_debugfs.c index 6bcf96e..d76ad10 100644 --- a/drivers/gpu/drm/vc4/vc4_debugfs.c +++ b/drivers/gpu/drm/vc4/vc4_debugfs.c @@ -22,6 +22,8 @@ static const struct drm_info_list vc4_debugfs_list[] = { {"crtc0_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)0}, {"crtc1_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)1}, {"crtc2_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)2}, + {"v3d_ident", vc4_v3d_debugfs_ident, 0}, + {"v3d_regs", vc4_v3d_debugfs_regs, 0}, }; #define VC4_DEBUGFS_ENTRIES ARRAY_SIZE(vc4_debugfs_list) diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index da4be9c..db58d74 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -236,6 +236,7 @@ static struct platform_driver *const component_drivers[] = { &vc4_hdmi_driver, &vc4_crtc_driver, &vc4_hvs_driver, + &vc4_v3d_driver, }; static int vc4_platform_drm_probe(struct platform_device *pdev) diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index bd77d55..8945463 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -15,6 +15,7 @@ struct vc4_dev { struct vc4_hdmi *hdmi; struct vc4_hvs *hvs; struct vc4_crtc *crtc[3]; + struct vc4_v3d *v3d; struct drm_fbdev_cma *fbdev; @@ -82,6 +83,11 @@ to_vc4_bo(struct drm_gem_object *bo) return (struct vc4_bo *)bo; } +struct vc4_v3d { + struct platform_device *pdev; + void __iomem *regs; +}; + struct vc4_hvs { struct platform_device *pdev; void __iomem *regs; @@ -119,6 +125,8 @@ to_vc4_encoder(struct drm_encoder *encoder) return container_of(encoder, struct vc4_encoder, base); } +#define V3D_READ(offset) readl(vc4->v3d->regs + offset) +#define V3D_WRITE(offset, val) writel(val, vc4->v3d->regs + offset) #define HVS_READ(offset) readl(vc4->hvs->regs + offset) #define HVS_WRITE(offset, val) writel(val, vc4->hvs->regs + offset) @@ -241,6 +249,11 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist); u32 vc4_plane_dlist_size(struct drm_plane_state *state); +/* vc4_v3d.c */ +extern struct platform_driver vc4_v3d_driver; +int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused); +int vc4_v3d_debugfs_regs(struct seq_file *m, void *unused); + /* vc4_validate_shader.c */ struct vc4_validated_shader_info * vc4_validate_shader(struct drm_gem_cma_object *shader_obj); diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c new file mode 100644 index 000..040ad0d --- /dev/null +++ b/drivers/gpu/drm/vc4/vc4_v3d.c @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * Copyright (C) 2013 Red Hat + * Author: Rob Clark + * + * 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. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "linux/component.h" +#include "vc4_drv.h" +#include "vc4_regs.h" + +#ifdef CONFIG_DEBUG_FS +#define REGDEF(reg) { reg, #reg } +static const struct { + uint32_t reg; + const char *name; +} vc4_reg_defs[] = { + REGDEF(V3D_IDENT0), + REGDEF(V3D_IDENT1), + REGDEF(V3D_IDENT2), + REGDEF(V3D_SCRATCH), + REGDEF(V3D_L2CACTL), + REGDEF(V3D_SLCACTL), + REGDEF(V3D_INTCTL), + REGDEF(V3D_INTENA), + REGDEF(V3D_INTDIS), + REGDEF(V3D_CT0CS), +
[PATCH v2 8/9] drm/vc4: Add support for async pageflips.
An async pageflip stores the modeset to be done and executes it once the BOs are ready to be displayed. This gets us about 3x performance in full screen rendering with pageflipping. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_crtc.c | 99 +- drivers/gpu/drm/vc4/vc4_drv.h | 16 + drivers/gpu/drm/vc4/vc4_gem.c | 40 +++ drivers/gpu/drm/vc4/vc4_kms.c | 149 +++- drivers/gpu/drm/vc4/vc4_plane.c | 40 +++ 5 files changed, 342 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 7a9f476..a319332 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -35,6 +35,7 @@ #include "drm_atomic_helper.h" #include "drm_crtc_helper.h" #include "linux/clk.h" +#include "drm_fb_cma_helper.h" #include "linux/component.h" #include "linux/of_device.h" #include "vc4_drv.h" @@ -475,10 +476,106 @@ static irqreturn_t vc4_crtc_irq_handler(int irq, void *data) return ret; } +struct vc4_async_flip_state { + struct drm_crtc *crtc; + struct drm_framebuffer *fb; + struct drm_pending_vblank_event *event; + + struct vc4_seqno_cb cb; +}; + +/* Called when the V3D execution for the BO being flipped to is done, so that + * we can actually update the plane's address to point to it. + */ +static void +vc4_async_page_flip_complete(struct vc4_seqno_cb *cb) +{ + struct vc4_async_flip_state *flip_state = + container_of(cb, struct vc4_async_flip_state, cb); + struct drm_crtc *crtc = flip_state->crtc; + struct drm_device *dev = crtc->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct drm_plane *plane = crtc->primary; + + vc4_plane_async_set_fb(plane, flip_state->fb); + if (flip_state->event) { + unsigned long flags; + + spin_lock_irqsave(&dev->event_lock, flags); + drm_crtc_send_vblank_event(crtc, flip_state->event); + spin_unlock_irqrestore(&dev->event_lock, flags); + } + + drm_framebuffer_unreference(flip_state->fb); + kfree(flip_state); + + up(&vc4->async_modeset); +} + +/* Implements async (non-vblank-synced) page flips. + * + * The page flip ioctl needs to return immediately, so we grab the + * modeset semaphore on the pipe, and queue the address update for + * when V3D is done with the BO being flipped to. + */ +static int vc4_async_page_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event, + uint32_t flags) +{ + struct drm_device *dev = crtc->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct drm_plane *plane = crtc->primary; + int ret = 0; + struct vc4_async_flip_state *flip_state; + struct drm_gem_cma_object *cma_bo = drm_fb_cma_get_gem_obj(fb, 0); + struct vc4_bo *bo = to_vc4_bo(&cma_bo->base); + + flip_state = kzalloc(sizeof(*flip_state), GFP_KERNEL); + if (!flip_state) + return -ENOMEM; + + drm_framebuffer_reference(fb); + flip_state->fb = fb; + flip_state->crtc = crtc; + flip_state->event = event; + + /* Make sure all other async modesetes have landed. */ + ret = down_interruptible(&vc4->async_modeset); + if (ret) { + kfree(flip_state); + return ret; + } + + /* Immediately update the plane's legacy fb pointer, so that later +* modeset prep sees the state that will be present when the semaphore +* is released. +*/ + drm_atomic_set_fb_for_plane(plane->state, fb); + plane->fb = fb; + + vc4_queue_seqno_cb(dev, &flip_state->cb, bo->seqno, + vc4_async_page_flip_complete); + + /* Driver takes ownership of state on successful async commit. */ + return 0; +} + +static int vc4_page_flip(struct drm_crtc *crtc, +struct drm_framebuffer *fb, +struct drm_pending_vblank_event *event, +uint32_t flags) +{ + if (flags & DRM_MODE_PAGE_FLIP_ASYNC) + return vc4_async_page_flip(crtc, fb, event, flags); + else + return drm_atomic_helper_page_flip(crtc, fb, event, flags); +} + static const struct drm_crtc_funcs vc4_crtc_funcs = { .set_config = drm_atomic_helper_set_config, .destroy = vc4_crtc_destroy, - .page_flip = drm_atomic_helper_page_flip, + .page_flip = vc4_page_flip, .set_property = NULL, .cursor_set = NULL, /* handled by drm_mode_cursor_universal */ .cursor_move = NULL, /* handled by drm_mode_cur
[PATCH v2 7/9] drm/vc4: Add support for drawing 3D frames.
The user submission is basically a pointer to a command list and a pointer to uniforms. We copy those in to the kernel, validate and relocate them, and store the result in a GPU BO which we queue for execution. Signed-off-by: Eric Anholt --- v2: Drop support for NV shader recs (not necessary for GL), simplify vc4_use_bo(), improve bin flush/semaphore checks, use __u32 style types. drivers/gpu/drm/vc4/Makefile | 7 + drivers/gpu/drm/vc4/vc4_drv.c | 15 +- drivers/gpu/drm/vc4/vc4_drv.h | 182 +++ drivers/gpu/drm/vc4/vc4_gem.c | 642 +++ drivers/gpu/drm/vc4/vc4_irq.c | 210 drivers/gpu/drm/vc4/vc4_packet.h | 399 +++ drivers/gpu/drm/vc4/vc4_render_cl.c| 634 +++ drivers/gpu/drm/vc4/vc4_trace.h| 63 +++ drivers/gpu/drm/vc4/vc4_trace_points.c | 14 + drivers/gpu/drm/vc4/vc4_v3d.c | 37 ++ drivers/gpu/drm/vc4/vc4_validate.c | 900 + include/uapi/drm/vc4_drm.h | 141 ++ 12 files changed, 3243 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/vc4/vc4_gem.c create mode 100644 drivers/gpu/drm/vc4/vc4_irq.c create mode 100644 drivers/gpu/drm/vc4/vc4_packet.h create mode 100644 drivers/gpu/drm/vc4/vc4_render_cl.c create mode 100644 drivers/gpu/drm/vc4/vc4_trace.h create mode 100644 drivers/gpu/drm/vc4/vc4_trace_points.c create mode 100644 drivers/gpu/drm/vc4/vc4_validate.c diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile index e87a6f2..4c6a99f 100644 --- a/drivers/gpu/drm/vc4/Makefile +++ b/drivers/gpu/drm/vc4/Makefile @@ -8,12 +8,19 @@ vc4-y := \ vc4_crtc.o \ vc4_drv.o \ vc4_kms.o \ + vc4_gem.o \ vc4_hdmi.o \ vc4_hvs.o \ + vc4_irq.o \ vc4_plane.o \ + vc4_render_cl.o \ + vc4_trace_points.o \ vc4_v3d.o \ + vc4_validate.o \ vc4_validate_shaders.o vc4-$(CONFIG_DEBUG_FS) += vc4_debugfs.o obj-$(CONFIG_DRM_VC4) += vc4.o + +CFLAGS_vc4_trace_points.o := -I$(src) diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index db58d74..2cfee59 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -74,6 +74,9 @@ static const struct file_operations vc4_drm_fops = { }; static const struct drm_ioctl_desc vc4_drm_ioctls[] = { + DRM_IOCTL_DEF_DRV(VC4_SUBMIT_CL, vc4_submit_cl_ioctl, 0), + DRM_IOCTL_DEF_DRV(VC4_WAIT_SEQNO, vc4_wait_seqno_ioctl, 0), + DRM_IOCTL_DEF_DRV(VC4_WAIT_BO, vc4_wait_bo_ioctl, 0), DRM_IOCTL_DEF_DRV(VC4_CREATE_BO, vc4_create_bo_ioctl, 0), DRM_IOCTL_DEF_DRV(VC4_MMAP_BO, vc4_mmap_bo_ioctl, 0), DRM_IOCTL_DEF_DRV(VC4_CREATE_SHADER_BO, vc4_create_shader_bo_ioctl, 0), @@ -83,10 +86,16 @@ static struct drm_driver vc4_drm_driver = { .driver_features = (DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_GEM | + DRIVER_HAVE_IRQ | DRIVER_PRIME), .lastclose = vc4_lastclose, .preclose = vc4_drm_preclose, + .irq_handler = vc4_irq, + .irq_preinstall = vc4_irq_preinstall, + .irq_postinstall = vc4_irq_postinstall, + .irq_uninstall = vc4_irq_uninstall, + .enable_vblank = vc4_enable_vblank, .disable_vblank = vc4_disable_vblank, .get_vblank_counter = drm_vblank_count, @@ -181,9 +190,11 @@ static int vc4_drm_bind(struct device *dev) if (ret) goto unref; + vc4_gem_init(drm); + ret = component_bind_all(dev, drm); if (ret) - goto unref; + goto gem_destroy; ret = drm_dev_register(drm, 0); if (ret < 0) @@ -207,6 +218,8 @@ unregister: drm_dev_unregister(drm); unbind_all: component_unbind_all(dev, drm); +gem_destroy: + vc4_gem_destroy(drm); unref: drm_dev_unref(drm); vc4_bo_cache_destroy(drm); diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 8945463..0bc8c57 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -49,6 +49,48 @@ struct vc4_dev { /* Protects bo_cache and the BO stats. */ struct mutex bo_lock; + + /* Sequence number for the last job queued in job_list. +* Starts at 0 (no jobs emitted). +*/ + uint64_t emit_seqno; + + /* Sequence number for the last completed job on the GPU. +* Starts at 0 (no jobs completed). +*/ + uint64_t finished_seqno; + + /* List of all struct vc4_exec_info for jobs to be executed. +* The first job in the list is the one currently programmed +* into ct0ca/ct1ca for execution. +*/ + struct list_head job_list; + /* List of the finished vc4_exec_infos waiting to be freed
[PATCH v4 1/8] clk: bcm2835: Add binding docs for the Raspberry Pi clock provider
The hardware clocks are not controllable by the ARM, so we have to make requests to the firmware to do so from the VPU side. This will let us replace fixed clocks in our DT with actual clock control (and correct frequency information). Signed-off-by: Eric Anholt Acked-by: Stephen Warren Acked-by: Lee Jones --- v2: Include the dt-bindings header in this commit instead of the next one. Make the clock indices match the firmware clock IDs. Rename the binding's compat string. Move the firmware phandle to be under a vendor-specific namespace. v4: Mention 'clk' in the subject instead of the more generic dt/bindings. .../clock/raspberrypi,bcm2835-firmware-clocks.txt | 25 ++ include/dt-bindings/clk/raspberrypi.h | 23 2 files changed, 48 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/raspberrypi,bcm2835-firmware-clocks.txt create mode 100644 include/dt-bindings/clk/raspberrypi.h diff --git a/Documentation/devicetree/bindings/clock/raspberrypi,bcm2835-firmware-clocks.txt b/Documentation/devicetree/bindings/clock/raspberrypi,bcm2835-firmware-clocks.txt new file mode 100644 index 000..0972602 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/raspberrypi,bcm2835-firmware-clocks.txt @@ -0,0 +1,25 @@ +Raspberry Pi firmware clock provider. + +The Raspberry Pi architecture doesn't provide direct access to the +CLOCKMAN peripheral from the ARM side, so Linux has to make requests +to the VPU firmware to program them. + +This binding uses the common clock binding: +Documentation/devicetree/bindings/clock/clock-bindings.txt + +Required properties: +- compatible: Should be "raspberrypi,bcm2835-firmware-clocks" + +- #clock-cells:Shall have value <1>. The permitted clock-specifier + values can be found in + include/dt-bindings/clk/raspberrypi.h. + +- raspberrypi,firmware:Phandle to the firmware driver node. + +Example: + +firmware_clocks: firmware-clocks { + compatible = "raspberrypi,bcm2835-firmware-clocks"; + #clock-cells = <1>; + raspberrypi,firmware = <&firmware>; +}; diff --git a/include/dt-bindings/clk/raspberrypi.h b/include/dt-bindings/clk/raspberrypi.h new file mode 100644 index 000..ceec90f --- /dev/null +++ b/include/dt-bindings/clk/raspberrypi.h @@ -0,0 +1,23 @@ +#/* + * Copyright ?? 2015 Broadcom + * + * 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 _DT_BINDINGS_CLK_RASPBERRYPI_H +#define _DT_BINDINGS_CLK_RASPBERRYPI_H + +#define RPI_CLOCK_EMMC 1 +#define RPI_CLOCK_UART02 +#define RPI_CLOCK_ARM 3 +#define RPI_CLOCK_CORE 4 +#define RPI_CLOCK_V3D 5 +#define RPI_CLOCK_H264 6 +#define RPI_CLOCK_ISP 7 +#define RPI_CLOCK_SDRAM8 +#define RPI_CLOCK_PIXEL9 +#define RPI_CLOCK_PWM 10 + +#endif -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 0/8] Raspberry Pi clock support
This is a respin of my rpi-dt-clocks series (also available at https://github.com/anholt/linux/tree/rpi-dt-clocks). New in this version is mentioning the clk subsystem for drivers/clk/* patches, some better documentation of behavior in clk-raspberrypi.c, and a new patch at the tail of the series for updating the EMMC clock. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 6/8] ARM: bcm2835: Use the RPi firmware clocks for uart.
This gets us a correct apb_pclk, which previously was accidentally using the "20201000.uart" clock from clk-bcm2835.c, due to the fallback clk_get_sys() path. Signed-off-by: Eric Anholt Acked-by: Stephen Warren --- arch/arm/boot/dts/bcm2835-rpi.dtsi | 7 +++ arch/arm/boot/dts/bcm2835.dtsi | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi index 7cc47fb..9549eb8 100644 --- a/arch/arm/boot/dts/bcm2835-rpi.dtsi +++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi @@ -1,3 +1,4 @@ +#include #include "bcm2835.dtsi" / { @@ -62,3 +63,9 @@ status = "okay"; bus-width = <4>; }; + +&uart0 { + clocks = <&firmware_clocks RPI_CLOCK_UART0>, +<&firmware_clocks RPI_CLOCK_CORE>; + clock-names = "uartclk", "apb_pclk"; +}; diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi index 32f5830..5be2862 100644 --- a/arch/arm/boot/dts/bcm2835.dtsi +++ b/arch/arm/boot/dts/bcm2835.dtsi @@ -92,7 +92,7 @@ #interrupt-cells = <2>; }; - uart@7e201000 { + uart0: uart@7e201000 { compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell"; reg = <0x7e201000 0x1000>; interrupts = <2 25>; -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 3/8] ARM: bcm2835: Add DT for the firmware clocks driver.
Signed-off-by: Eric Anholt Acked-by: Stephen Warren --- v2: Rename our compat string to mention bcm2835, and make our firmware phandle be under a vendor-namespaced property. arch/arm/boot/dts/bcm2835-rpi.dtsi | 6 ++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi index ab5474e..7cc47fb 100644 --- a/arch/arm/boot/dts/bcm2835-rpi.dtsi +++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi @@ -20,6 +20,12 @@ compatible = "raspberrypi,bcm2835-firmware"; mboxes = <&mailbox>; }; + + firmware_clocks: firmware-clocks { + compatible = "raspberrypi,bcm2835-firmware-clocks"; + #clock-cells = <1>; + raspberrypi,firmware = <&firmware>; + }; }; }; -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 4/8] ARM: bcm2835: Drop never-used clock-frequency property of uart0.
This appears to have been copy-and-paste from another serial driver's DT. The driver has never used this value -- instead, the pl011 driver is getting the fixed 20201000.uart clock from clk-bcm2835.c. Signed-off-by: Eric Anholt Acked-by: Stephen Warren --- arch/arm/boot/dts/bcm2835.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi index 301c73f..32f5830 100644 --- a/arch/arm/boot/dts/bcm2835.dtsi +++ b/arch/arm/boot/dts/bcm2835.dtsi @@ -96,7 +96,6 @@ compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell"; reg = <0x7e201000 0x1000>; interrupts = <2 25>; - clock-frequency = <300>; arm,primecell-periphid = <0x00241011>; }; -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 7/8] ARM: bcm2835: Tie SPI clock to the core clock rate.
We were previously using a fixed clock declared in the 2835 DT, but it's actually the core clock, and it might not be the same if you had adjusted it using the firmware's config.txt. Signed-off-by: Eric Anholt Acked-by: Stephen Warren --- arch/arm/boot/dts/bcm2835-rpi.dtsi | 4 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi index 9549eb8..0a32123 100644 --- a/arch/arm/boot/dts/bcm2835-rpi.dtsi +++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi @@ -69,3 +69,7 @@ <&firmware_clocks RPI_CLOCK_CORE>; clock-names = "uartclk", "apb_pclk"; }; + +&spi { + clocks = <&firmware_clocks RPI_CLOCK_CORE>; +}; -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 2/8] clk: Add a Raspberry Pi-specific clock driver.
Unfortunately, the clock manager's registers are not accessible by the ARM, so we have to request that the firmware modify our clocks for us. This driver only registers the clocks at the point they are requested by a client driver. This is partially to support returning -EPROBE_DEFER when the firmware driver isn't supported yet, but it also avoids issues with disabling "unused" clocks due to them not yet being connected to their consumers in the DT. Signed-off-by: Eric Anholt Acked-by: Stephen Warren --- v2: Declare the mutex static (from review by Baruch Siach), merge description and copyright comments. v3: Update for new rpi firmware API. Update the compatible string. Make the firmware handle be under a vendor-namespaced property. Make the DT indices match the firmware clock IDs. Move the driver under the firmware driver's Kconfig, since it requires it. Move a container_of() from 2 callers into the callee. v4: Update commit message to mention subsystem. Add #defines for a couple of bitfield checks, and use the bitfield check for rpi_clk_is_on(). Return an error when appropriate in rpi_clk_is_on(), and return specific rpi_firmware_property() errors in other places when we were only returning -EINVAL. Add some comment text describing how return values work from the firmware. drivers/clk/Makefile | 1 + drivers/clk/clk-raspberrypi.c | 259 ++ 2 files changed, 260 insertions(+) create mode 100644 drivers/clk/clk-raspberrypi.c diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index c4cf075..ad0a4a5 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_MACH_ASM9260)+= clk-asm9260.o obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN)+= clk-axi-clkgen.o obj-$(CONFIG_ARCH_AXXIA) += clk-axm5516.o obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o +obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += clk-raspberrypi.o obj-$(CONFIG_COMMON_CLK_CDCE706) += clk-cdce706.o obj-$(CONFIG_ARCH_CLPS711X)+= clk-clps711x.o obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o diff --git a/drivers/clk/clk-raspberrypi.c b/drivers/clk/clk-raspberrypi.c new file mode 100644 index 000..ae35804 --- /dev/null +++ b/drivers/clk/clk-raspberrypi.c @@ -0,0 +1,259 @@ +/* + * Implements a clock provider for the clocks controlled by the + * firmware on Raspberry Pi. + * + * These clocks are controlled by the CLOCKMAN peripheral in the + * hardware, but the ARM doesn't have access to the registers for + * them. As a result, we have to call into the firmware to get it to + * enable, disable, and set their frequencies. + * + * We don't have an interface for getting the set of frequencies + * available from the hardware. We can request a min/max, but other + * than that we have to request a frequency and take what it gives us. + * + * Copyright ?? 2015 Broadcom + * + * 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 + +#define RPI_FIRMWARE_CLOCK_STATE_ENABLED (1 << 0) +#define RPI_FIRMWARE_CLOCK_STATE_ERROR (1 << 1) +#define RPI_FIRMWARE_SET_CLOCK_RATE_ERROR 0 + +struct rpi_firmware_clock { + /* Clock definitions in our static struct. */ + const char *name; + + /* The rest are filled in at init time. */ + struct clk_hw hw; + struct device *dev; + struct rpi_firmware *firmware; +}; + +static struct rpi_firmware_clock rpi_clocks[] = { + [RPI_CLOCK_EMMC] = { "emmc" }, + [RPI_CLOCK_UART0] = { "uart0" }, + [RPI_CLOCK_ARM] = { "arm" }, + [RPI_CLOCK_CORE] = { "core" }, + [RPI_CLOCK_V3D] = { "v3d" }, + [RPI_CLOCK_H264] = { "h264" }, + [RPI_CLOCK_ISP] = { "isp" }, + [RPI_CLOCK_SDRAM] = { "sdram" }, + [RPI_CLOCK_PIXEL] = { "pixel" }, + [RPI_CLOCK_PWM] = { "pwm" }, +}; + +static int rpi_clock_id(struct rpi_firmware_clock *rpi_clk) +{ + return rpi_clk - rpi_clocks; +} + +static int rpi_clk_is_on(struct clk_hw *hw) +{ + struct rpi_firmware_clock *rpi_clk = + container_of(hw, struct rpi_firmware_clock, hw); + u32 packet[2]; + int ret; + + packet[0] = rpi_clock_id(rpi_clk); + packet[1] = 0; + ret = rpi_firmware_property(rpi_clk->firmware, + RPI_FIRMWARE_GET_CLOCK_STATE, + &packet, sizeof(packet)); + /* The second packet field has the new clock state returned in +* the low bit, or an error flag in the second bit. +*/ + if (ret || (packe
[PATCH v4 5/8] clk: bcm2835: Drop the fixed sys_pclk.
Nothing uses it, and I can't find any evidence that anything ever has. Its role is now filled by the core clock in the firmware driver. Signed-off-by: Eric Anholt Acked-by: Stephen Warren --- drivers/clk/clk-bcm2835.c | 5 - 1 file changed, 5 deletions(-) diff --git a/drivers/clk/clk-bcm2835.c b/drivers/clk/clk-bcm2835.c index 6b950ca..dd295e4 100644 --- a/drivers/clk/clk-bcm2835.c +++ b/drivers/clk/clk-bcm2835.c @@ -32,11 +32,6 @@ void __init bcm2835_init_clocks(void) struct clk *clk; int ret; - clk = clk_register_fixed_rate(NULL, "sys_pclk", NULL, CLK_IS_ROOT, - 25000); - if (IS_ERR(clk)) - pr_err("sys_pclk not registered\n"); - clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 12600); if (IS_ERR(clk)) -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 8/8] ARM: bcm2835: Use the firmware on rpi to get the EMMC clock.
This updates the MMC frequency from 100Mhz to 250Mhz. Signed-off-by: Eric Anholt --- arch/arm/boot/dts/bcm2835-rpi.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi index 0a32123..5d370cb 100644 --- a/arch/arm/boot/dts/bcm2835-rpi.dtsi +++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi @@ -62,6 +62,7 @@ &sdhci { status = "okay"; bus-width = <4>; + clocks = <&firmware_clocks RPI_CLOCK_EMMC>; }; &uart0 { -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2 1/3] clk: bcm2835: Add bindings for the auxiliary peripheral clock gates.
Michael Turquette writes: > Hi Arnd, > > Quoting Arnd Bergmann (2015-12-30 01:29:02) >> It's also ok to merge the header file and binding with either the dts file >> changes or the driver and then do the other part the following release. >> >> In the past, we've worked around the issue by merging the driver through >> arm-soc, or by merging the dts changes through a driver tree, with the >> appropriate Acks in each case. Both of those approaches work of course, >> but the former always feels awkward to me as we are not using the right >> maintainer path, and the latter approach tends to cause merge conflicts, >> especially when multiple headers for different subsystems get added or >> the dts files are added at the same time. >> >> Having a shared branch for the header file is another way to do it, and >> we can do that in some cases, but I'd prefer not to make it the default. > > Well, I'm thinking that an immutable branch isn't such a bad idea given > that both you and Rob are OK with subsystems merging headers and binding > descriptions. > > A while back Stephen Boyd and I started to use topic branches for every > driver, all based on -rc1 and merging those into clk-next. This makes it > trivial for us to push a shareable branch with minimal dependencies. > > So at least for the clk tree, how do you feel about us merging driver + > header + binding description and then sharing our topic branch as-needed > with arm-soc? We could even push our topic branches by default to cut > down on coordinating over email back-and-forth. > > As an example, patch #1 from the Hi3519 series[0] includes the clk > driver, binding description and a shared header. Any objection to me > taking that patch as-is, based on -rc1, and pushing out that topic > branch as clk-hi3519 to the clk git tree with the expectation that > you'll just merge that if you need to? > > You can let me know if you've pulled it in, and then I won't rebase > without consulting with the arm-soc folks first. > > Does this workflow agreement Solve All the Problems? > > (Note that the patch I referenced is still under review so the branch > name I mentioned above doesn't exist yet. It is just an example) For what it's worth, this is a nice workflow for me as a driver developer. I have a couple of .dts patches that ended up waiting this cycle because I didn't have the shareable branches necessary. signature.asc Description: PGP signature
Re: [PATCH v5 01/13] mmc: sdhci-bcm2835: use sdhci_pltfm_init for private allocation
Jisheng Zhang writes: > Commit 0e748234293f ("mmc: sdhci: Add size for caller in init+register") > allows users of sdhci_pltfm to allocate private space in calls to > sdhci_pltfm_init+sdhci_pltfm_register. This patch migrates sdhci-bcm2835 > to this allocation. > > Signed-off-by: Jisheng Zhang > Acked-by: Arnd Bergmann > Acked-by: Adrian Hunter Acked-by: Eric Anholt signature.asc Description: PGP signature
Re: [PATCH 2/3] drm/vc4: Enable runtime PM.
Eric Anholt writes: > +#ifdef CONFIG_PM_SLEEP > +static int vc4_v3d_runtime_suspend(struct device *dev) > +{ > + struct vc4_v3d *v3d = dev_get_drvdata(dev); > + struct vc4_dev *vc4 = v3d->vc4; > + > + vc4_irq_uninstall(vc4->dev); > + > + return 0; > +} > + > +static int vc4_v3d_runtime_resume(struct device *dev) > +{ > + struct vc4_v3d *v3d = dev_get_drvdata(dev); > + struct vc4_dev *vc4 = v3d->vc4; > + > + vc4_v3d_init_hw(vc4->dev); > + vc4_irq_postinstall(vc4->dev); > + > + return 0; > +} > +#endif kbuild test robot caught that this #ifdef should have been CONFIG_PM, not CONFIG_PM_SLEEP. Fixed in v2. signature.asc Description: PGP signature
[PATCH 3/6] drm/vc4: Add another reg to HDMI debug dumping.
This is also involved in the HDMI setup sequence so it's nice to see it. Signed-off-by: Eric Anholt --- This patch and the next one I'd target for -next, since they aren't functional fixes. drivers/gpu/drm/vc4/vc4_hdmi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index d189906..b4e7b8a 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -95,6 +95,7 @@ static const struct { HDMI_REG(VC4_HDMI_SW_RESET_CONTROL), HDMI_REG(VC4_HDMI_HOTPLUG_INT), HDMI_REG(VC4_HDMI_HOTPLUG), + HDMI_REG(VC4_HDMI_RAM_PACKET_CONFIG), HDMI_REG(VC4_HDMI_HORZA), HDMI_REG(VC4_HDMI_HORZB), HDMI_REG(VC4_HDMI_FIFO_CTL), -- 2.7.0
[PATCH 4/6] drm/vc4: Fix the name of the VSYNCD_EVEN register.
It's used for delaying vsync in interlaced mode. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_crtc.c | 2 +- drivers/gpu/drm/vc4/vc4_regs.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index bb74cb9..5daa824 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -88,7 +88,7 @@ static const struct { } crtc_regs[] = { CRTC_REG(PV_CONTROL), CRTC_REG(PV_V_CONTROL), - CRTC_REG(PV_VSYNCD), + CRTC_REG(PV_VSYNCD_EVEN), CRTC_REG(PV_HORZA), CRTC_REG(PV_HORZB), CRTC_REG(PV_VERTA), diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index 31042a4..58d4cb3 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -187,7 +187,7 @@ # define PV_VCONTROL_CONTINUOUSBIT(1) # define PV_VCONTROL_VIDEN BIT(0) -#define PV_VSYNCD 0x08 +#define PV_VSYNCD_EVEN 0x08 #define PV_HORZA 0x0c # define PV_HORZA_HBP_MASK VC4_MASK(31, 16) -- 2.7.0
drm/vc4: Modesetting fixes
This series fixes the highest priority problems reported from the driver getting enabled in Raspbian: modesetting on HDMI was broken if you weren't at the same resolution that the firmware had set up, or if the firmware hadn't set up HDMI at all.
[PATCH 2/6] drm/vc4: Bring HDMI up from power off if necessary.
If the firmware hadn't brought up HDMI for us, we need to do its power-on reset sequence (reset HD and and clear its STANDBY bits, reset HDMI, and leave the PHY disabled). Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_hdmi.c | 29 - drivers/gpu/drm/vc4/vc4_regs.h | 2 ++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index c49cb44..d189906 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -497,6 +497,16 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) goto err_put_i2c; } + /* This is the rate that is set by the firmware. The number +* needs to be a bit higher than the pixel clock rate +* (generally 148.5Mhz). +*/ + ret = clk_set_rate(hdmi->hsm_clock, 163682864); + if (ret) { + DRM_ERROR("Failed to set HSM clock rate: %d\n", ret); + goto err_unprepare_pix; + } + ret = clk_prepare_enable(hdmi->hsm_clock); if (ret) { DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n", @@ -518,7 +528,24 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) vc4->hdmi = hdmi; /* HDMI core must be enabled. */ - WARN_ON_ONCE((HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE) == 0); + if (!(HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE)) { + HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_SW_RST); + udelay(1); + HD_WRITE(VC4_HD_M_CTL, 0); + + HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_ENABLE); + + HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL, + VC4_HDMI_SW_RESET_HDMI | + VC4_HDMI_SW_RESET_FORMAT_DETECT); + + HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL, 0); + + /* PHY should be in reset, like +* vc4_hdmi_encoder_disable() does. +*/ + HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16); + } drm_encoder_init(drm, hdmi->encoder, &vc4_hdmi_encoder_funcs, DRM_MODE_ENCODER_TMDS, NULL); diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index 25df20e..31042a4 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -456,6 +456,8 @@ #define VC4_HDMI_TX_PHY_RESET_CTL 0x2c0 #define VC4_HD_M_CTL 0x00c +# define VC4_HD_M_REGISTER_FILE_STANDBY(3 << 6) +# define VC4_HD_M_RAM_STANDBY (3 << 4) # define VC4_HD_M_SW_RST BIT(2) # define VC4_HD_M_ENABLE BIT(0) -- 2.7.0
[PATCH 6/6] drm/vc4: Initialize scaler DISPBKGND on modeset.
We weren't updating the interlaced bit, so we'd scan out incorrectly if the firmware had brought up the TV encoder and we were switching to HDMI. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_crtc.c | 6 ++ drivers/gpu/drm/vc4/vc4_regs.h | 14 ++ 2 files changed, 20 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 89562904..66499e3 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -188,6 +188,8 @@ static int vc4_get_clock_select(struct drm_crtc *crtc) static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) { + struct drm_device *dev = crtc->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); struct drm_crtc_state *state = crtc->state; struct drm_display_mode *mode = &state->adjusted_mode; @@ -256,6 +258,10 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) PV_CONTROL_FIFO_CLR | PV_CONTROL_EN); + HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel), + SCALER_DISPBKGND_AUTOHS | + (interlace ? SCALER_DISPBKGND_INTERLACE : 0)); + if (debug_dump_regs) { DRM_INFO("CRTC %d regs after:\n", drm_crtc_index(crtc)); vc4_crtc_dump_regs(vc4_crtc); diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index 58d4cb3..bf42a8e 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -350,6 +350,17 @@ # define SCALER_DISPCTRLX_HEIGHT_SHIFT 0 #define SCALER_DISPBKGND0 0x0044 +# define SCALER_DISPBKGND_AUTOHS BIT(31) +# define SCALER_DISPBKGND_INTERLACEBIT(30) +# define SCALER_DISPBKGND_GAMMABIT(29) +# define SCALER_DISPBKGND_TESTMODE_MASKVC4_MASK(28, 25) +# define SCALER_DISPBKGND_TESTMODE_SHIFT 25 +/* Enables filling the scaler line with the RGB value in the low 24 + * bits before compositing. Costs cycles, so should be skipped if + * opaque display planes will cover everything. + */ +# define SCALER_DISPBKGND_FILL BIT(24) + #define SCALER_DISPSTAT00x0048 #define SCALER_DISPBASE00x004c # define SCALER_DISPSTATX_MODE_MASKVC4_MASK(31, 30) @@ -362,6 +373,9 @@ # define SCALER_DISPSTATX_EMPTYBIT(28) #define SCALER_DISPCTRL10x0050 #define SCALER_DISPBKGND1 0x0054 +#define SCALER_DISPBKGNDX(x) (SCALER_DISPBKGND0 +\ +(x) * (SCALER_DISPBKGND1 - \ + SCALER_DISPBKGND0)) #define SCALER_DISPSTAT10x0058 #define SCALER_DISPSTATX(x)(SCALER_DISPSTAT0 +\ (x) * (SCALER_DISPSTAT1 - \ -- 2.7.0
[PATCH 5/6] drm/vc4: Fix setting of vertical timings in the CRTC.
It looks like when I went to add the interlaced bits, I just took the existing PV_VERT* block and indented it, instead of copy and pasting it first. Without this, changing resolution never worked. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_crtc.c | 10 ++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 5daa824..89562904 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -217,6 +217,16 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) PV_HORZB_HFP) | VC4_SET_FIELD(mode->hdisplay, PV_HORZB_HACTIVE)); + CRTC_WRITE(PV_VERTA, + VC4_SET_FIELD(mode->vtotal - mode->vsync_end, +PV_VERTA_VBP) | + VC4_SET_FIELD(mode->vsync_end - mode->vsync_start, +PV_VERTA_VSYNC)); + CRTC_WRITE(PV_VERTB, + VC4_SET_FIELD(mode->vsync_start - mode->vdisplay, +PV_VERTB_VFP) | + VC4_SET_FIELD(vactive, PV_VERTB_VACTIVE)); + if (interlace) { CRTC_WRITE(PV_VERTA_EVEN, VC4_SET_FIELD(mode->vtotal - mode->vsync_end - 1, -- 2.7.0
[PATCH 1/6] drm/vc4: Fix a framebuffer reference leak on async flip interrupt.
We'd need X to queue up an async pageflip while another is outstanding, and then take a SIGIO. I think X actually avoids sending out the next pageflip while one's already queued, but I'm not sure. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_crtc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 68227cc..bb74cb9 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -527,6 +527,7 @@ static int vc4_async_page_flip(struct drm_crtc *crtc, /* Make sure all other async modesetes have landed. */ ret = down_interruptible(&vc4->async_modeset); if (ret) { + drm_framebuffer_unreference(fb); kfree(flip_state); return ret; } -- 2.7.0
[GIT PULL 2/2] bcm2835 changes to DT for 4.6
The following changes since commit 92e963f50fc74041b5e9e744c330dca48e04f08d: Linux 4.5-rc1 (2016-01-24 13:06:47 -0800) are available in the git repository at: g...@github.com:anholt/linux.git bcm2835-dt-next-2016-02-17 for you to fetch changes up to 1305141d1a7254b53b35303ee84f4c4948007bd0: ARM: bcm2835: add bcm2835-aux-uart support to DT (2016-02-17 11:01:00 -0800) This pull request covers mostly DT changes that didn't make it into 4.5 because required header files went through other trees, plus the AUX uart support this time around. Alexander Aring (1): ARM: bcm2835: Add the Raspberry Pi power domain driver to the DT. Lubomir Rintel (1): ARM: bcm2835: dt: Add Raspberry Pi Model A Martin Sperl (3): ARM: bcm2835: add the auxiliary spi1 and spi2 to the device tree ARM: bcm2835: follow dt uart node-naming convention ARM: bcm2835: add bcm2835-aux-uart support to DT Remi Pommarel (1): ARM: bcm2835: Add PWM clock support to the device tree arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/bcm2835-rpi-a.dts | 24 + arch/arm/boot/dts/bcm2835-rpi.dtsi | 16 ++ arch/arm/boot/dts/bcm283x.dtsi | 43 +++-- 4 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 arch/arm/boot/dts/bcm2835-rpi-a.dts
Re: [GIT PULL] bcm2835 DT changes for 4.6
Florian Fainelli writes: > On 12/02/2016 16:53, Eric Anholt wrote: >> Florian Fainelli writes: >> >>> On 10/02/2016 10:51, Eric Anholt wrote: >>>> Martin Sperl writes: >>>> >>>>>> On 09.02.2016, at 01:32, Eric Anholt wrote: >>>>>> >>>>>> Hi Florian. Here's the first set of patches for bcm2835 for 4.6. >>>>>> We've got more DT patches that are going to happen for new boards, >>>>>> too, but they're still getting polished. >>>>>> >>>>>> The following changes since commit >>>>>> 92e963f50fc74041b5e9e744c330dca48e04f08d: >>>>>> >>>>>> Linux 4.5-rc1 (2016-01-24 13:06:47 -0800) >>>>>> >>>>>> are available in the git repository at: >>>>>> >>>>>> g...@github.com:anholt/linux.git tags/bcm2835-dt-next-2016-02-04 >>>>>> >>>>>> for you to fetch changes up to 5ec6f2cd8ec4bcd38ba199ea8711a5ec906d85e7: >>>>>> >>>>>> ARM: bcm2835: Add the Raspberry Pi power domain driver to the DT. >>>>>> (2016-02-02 20:02:45 -0800) >>>>>> >>>>>> >>>>>> This pull request covers mostly DT changes that didn't make it into >>>>>> 4.5 because required header files went through other trees. >>>>>> >>>>>> >>>>>> Alexander Aring (1): >>>>>> ARM: bcm2835: Add the Raspberry Pi power domain driver to the DT. >>>>>> >>>>>> Lubomir Rintel (1): >>>>>> ARM: bcm2835: dt: Add Raspberry Pi Model A >>>>>> >>>>>> Martin Sperl (2): >>>>>> ARM: bcm2835: add the auxiliary spi1 and spi2 to the device tree >>>>>> ARM: bcm2835: follow dt uart node-naming convention >>>>> >>>>> Do you want me to resend a rebased version of: >>>>> ARM: bcm2835: add bcm2835-aux-uart support to default DT >>>>> >>>>> The corresponding driver has been added to tty/tty-next. >>>> >>>> It hadn't landed last time I checked. A rebased version that you've >>>> tested would be great! >>> >>> OK, please submit this in the next week or so at most, so we can get >>> this pull request merged, thanks! >>> >>> Eric, do you have other changes outside of Device Tree? >> >> We've got bcm2835_defconfig changes that I need to test and tag. > > Ok, so that one needs to be a pull request. > >> >> There are also the multi_v7_defconfig updates to enable bcm2835. Would >> I be pulling those, or someone above me? > > This one could too, or it could be an individual patch that the arm-soc > maintainers take directly, either way is fine AFAIR. All right, I included it in my pull request. Thanks! signature.asc Description: PGP signature
[GIT PULL 1/2] bcm2835 changes to defconfigs for 4.6
The following changes since commit 92e963f50fc74041b5e9e744c330dca48e04f08d: Linux 4.5-rc1 (2016-01-24 13:06:47 -0800) are available in the git repository at: g...@github.com:anholt/linux.git bcm2835-defconfig-next-2016-02-17 for you to fetch changes up to 0a05d3b71ada526ef93019fb3fbd6a95561a8a5f: ARM: multi_v7_defconfig: Enable BCM283x (2016-02-17 11:18:05 -0800) This pull request brings in defconfig changes to enable bcm2836 in the 2835 and multi_v7 defconfigs. Daniel Stone (1): ARM: multi_v7_defconfig: Enable BCM283x Stefan Wahren (2): ARM: bcm2835_defconfig: Enable RPi firmware driver ARM: bcm2835_defconfig: Enable RPi power domain driver Stephen Warren (3): ARM: bcm2835_defconfig: rebuild on next-20160205 ARM: bcm2835_defconfig: disable DEBUG_LL ARM: bcm2835_defconfig: enable ARMv7 support arch/arm/configs/bcm2835_defconfig | 11 +-- arch/arm/configs/multi_v7_defconfig | 12 2 files changed, 17 insertions(+), 6 deletions(-)
[GIT PULL] drm/vc4: changes for drm-next.
These changes have been on the list for just under 2 weeks (and sitting under a lot of the other development I've been doing), so I think they're ready to go for -next. They're also a big deal for getting multiple encoders going, which I'm hoping will happen soon. The following changes since commit 5443ce86fa37e7d3cc63d2067d05e3388fdeec17: drm: virtio-gpu: set atomic flag (2016-02-11 08:56:23 +1000) are available in the git repository at: g...@github.com:anholt/linux.git tags/drm-vc4-next-2016-02-17 for you to fetch changes up to fc04023fafecf19ebd09278d8d67dc5ed1f68b46: drm/vc4: Add support for YUV planes. (2016-02-16 11:24:08 -0800) This pull request brings in overlay plane support for vc4. ---- Eric Anholt (10): drm/vc4: Improve comments on vc4_plane_state members. drm/vc4: Add missing __iomem annotation to hw_dlist. drm/vc4: Move the plane clipping/scaling setup to a separate function. drm/vc4: Add a proper short-circut path for legacy cursor updates. drm/vc4: Make the CRTCs cooperate on allocating display lists. drm/vc4: Add more display planes to each CRTC. drm/vc4: Fix which value is being used for source image size. drm/vc4: Add support for scaling of display planes. drm/vc4: Add support a few more RGB display plane formats. drm/vc4: Add support for YUV planes. drivers/gpu/drm/vc4/vc4_crtc.c | 171 +++- drivers/gpu/drm/vc4/vc4_drv.h | 12 +- drivers/gpu/drm/vc4/vc4_hvs.c | 97 +++ drivers/gpu/drm/vc4/vc4_kms.c | 9 + drivers/gpu/drm/vc4/vc4_plane.c | 603 drivers/gpu/drm/vc4/vc4_regs.h | 102 ++- 6 files changed, 872 insertions(+), 122 deletions(-)
[GIT PULL] drm/vc4: changes for drm-fixes
These changes have been on the list for over a week without comment, so I think it might be an appropriate time to pull (without an active development community, getting review will probably be hard). I'm also curious when your window for taking fixes would close -- the modesetting series I sent yesterday covers what most users have been running into. The following changes since commit 388f7b1d6e8ca06762e2454d28d6c3c55ad0fe95: Linux 4.5-rc3 (2016-02-07 15:38:30 -0800) are available in the git repository at: g...@github.com:anholt/linux.git tags/drm-vc4-fixes-2016-02-17 for you to fetch changes up to 36cb6253f9383fd9a59ee7b8458c6232ef48577c: drm/vc4: Use runtime PM to power cycle the device when the GPU hangs. (2016-02-16 12:21:01 -0800) This pull request fixes GPU reset (which was disabled shortly after V3D integration due to build breakage) and waits for idle in the presence of signals (which X likes to do a lot). Eric Anholt (8): drm/vc4: Validate that WAIT_BO padding is cleared. drm/vc4: Fix the clear color for the first tile rendered. drm/vc4: Return an ERR_PTR from BO creation instead of NULL. drm/vc4: Fix -ERESTARTSYS error return from BO waits. drm/vc4: Drop error message on seqno wait timeouts. drm/vc4: Fix spurious GPU resets due to BO reuse. drm/vc4: Enable runtime PM. drm/vc4: Use runtime PM to power cycle the device when the GPU hangs. drivers/gpu/drm/vc4/vc4_bo.c| 16 - drivers/gpu/drm/vc4/vc4_drv.h | 13 ++-- drivers/gpu/drm/vc4/vc4_gem.c | 65 - drivers/gpu/drm/vc4/vc4_irq.c | 2 +- drivers/gpu/drm/vc4/vc4_render_cl.c | 22 ++--- drivers/gpu/drm/vc4/vc4_v3d.c | 48 --- drivers/gpu/drm/vc4/vc4_validate.c | 4 +-- 7 files changed, 118 insertions(+), 52 deletions(-)
[PATCH] i2c: bcm2835: Don't complain on -EPROBE_DEFER from getting our clock
Fixes dmesg spam when we just need to wait a moment for the clock driver to probe. Signed-off-by: Eric Anholt --- drivers/i2c/busses/i2c-bcm2835.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c index 818b051..d4f3239 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -253,7 +253,8 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) i2c_dev->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(i2c_dev->clk)) { - dev_err(&pdev->dev, "Could not get clock\n"); + if (PTR_ERR(i2c_dev->clk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Could not get clock\n"); return PTR_ERR(i2c_dev->clk); } -- 2.7.0
[PATCH 3/3] drm/vc4: Use runtime PM to power cycle the device when the GPU hangs.
This gets us functional GPU reset again, like we had until a refactor at merge time. Tested with a little patch to stuff in a broken binner job every 100 frames. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_drv.h | 6 +- drivers/gpu/drm/vc4/vc4_gem.c | 26 +- drivers/gpu/drm/vc4/vc4_v3d.c | 12 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index b65e785..83db0b7 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -91,6 +91,11 @@ struct vc4_dev { struct vc4_bo *overflow_mem; struct work_struct overflow_mem_work; + int power_refcount; + + /* Mutex controlling the power refcount. */ + struct mutex power_lock; + struct { struct timer_list timer; struct work_struct reset_work; @@ -449,7 +454,6 @@ void vc4_plane_async_set_fb(struct drm_plane *plane, extern struct platform_driver vc4_v3d_driver; int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused); int vc4_v3d_debugfs_regs(struct seq_file *m, void *unused); -int vc4_v3d_set_power(struct vc4_dev *vc4, bool on); /* vc4_validate.c */ int diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 440ad03..5df46d6 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -229,8 +229,16 @@ vc4_reset(struct drm_device *dev) struct vc4_dev *vc4 = to_vc4_dev(dev); DRM_INFO("Resetting GPU.\n"); - vc4_v3d_set_power(vc4, false); - vc4_v3d_set_power(vc4, true); + + mutex_lock(&vc4->power_lock); + if (vc4->power_refcount) { + /* Power the device off and back on the by dropping the +* reference on runtime PM. +*/ + pm_runtime_put_sync_suspend(&vc4->v3d->pdev->dev); + pm_runtime_get_sync(&vc4->v3d->pdev->dev); + } + mutex_unlock(&vc4->power_lock); vc4_irq_reset(dev); @@ -646,7 +654,10 @@ vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec) } mutex_unlock(&dev->struct_mutex); - pm_runtime_put(&vc4->v3d->pdev->dev); + mutex_lock(&vc4->power_lock); + if (--vc4->power_refcount == 0) + pm_runtime_put(&vc4->v3d->pdev->dev); + mutex_unlock(&vc4->power_lock); kfree(exec); } @@ -785,7 +796,7 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data, struct vc4_dev *vc4 = to_vc4_dev(dev); struct drm_vc4_submit_cl *args = data; struct vc4_exec_info *exec; - int ret; + int ret = 0; if ((args->flags & ~VC4_SUBMIT_CL_USE_CLEAR_COLOR) != 0) { DRM_ERROR("Unknown flags: 0x%02x\n", args->flags); @@ -798,7 +809,10 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data, return -ENOMEM; } - ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev); + mutex_lock(&vc4->power_lock); + if (vc4->power_refcount++ == 0) + ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev); + mutex_unlock(&vc4->power_lock); if (ret < 0) { kfree(exec); return ret; @@ -858,6 +872,8 @@ vc4_gem_init(struct drm_device *dev) (unsigned long)dev); INIT_WORK(&vc4->job_done_work, vc4_job_done_work); + + mutex_init(&vc4->power_lock); } void diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c index 930851f..7b11e21 100644 --- a/drivers/gpu/drm/vc4/vc4_v3d.c +++ b/drivers/gpu/drm/vc4/vc4_v3d.c @@ -145,18 +145,6 @@ int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused) } #endif /* CONFIG_DEBUG_FS */ -int -vc4_v3d_set_power(struct vc4_dev *vc4, bool on) -{ - /* XXX: This interface is needed for GPU reset, and the way to -* do it is to turn our power domain off and back on. We -* can't just reset from within the driver, because the reset -* bits are in the power domain's register area, and get set -* during the poweron process. -*/ - return 0; -} - static void vc4_v3d_init_hw(struct drm_device *dev) { struct vc4_dev *vc4 = to_vc4_dev(dev); -- 2.7.0
[PATCH 0/3] vc4: Runtime PM and GPU reset.
Here's a series to re-add GPU reset, which I cut out of the driver in 8483d152db61c5baf5452b844ef65b96ee9a6cfb to deal with a build regression. Along the way, I found a bug in hang detection that seemed to be exacerbated by runtime PM. My preference would be to get this in -fixes, since without GPU reset we can end up with a totally wedged desktop (and we do still have some known GPU hangs). If not, I'm fine with the first patch to -fixes and the other two to -next. Eric Anholt (3): drm/vc4: Fix spurious GPU resets due to BO reuse. drm/vc4: Enable runtime PM. drm/vc4: Use runtime PM to power cycle the device when the GPU hangs. drivers/gpu/drm/vc4/vc4_drv.h | 13 +-- drivers/gpu/drm/vc4/vc4_gem.c | 51 --- drivers/gpu/drm/vc4/vc4_v3d.c | 48 ++-- 3 files changed, 90 insertions(+), 22 deletions(-) -- 2.7.0
[PATCH 1/3] drm/vc4: Fix spurious GPU resets due to BO reuse.
We were tracking the "where are the head pointers pointing" globally, so if another job reused the same BOs and execution was at the same point as last time we checked, we'd stop and trigger a reset even though the GPU had made progress. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_drv.h | 6 +- drivers/gpu/drm/vc4/vc4_gem.c | 19 ++- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index a7fea77..b4a26fd 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -92,7 +92,6 @@ struct vc4_dev { struct work_struct overflow_mem_work; struct { - uint32_t last_ct0ca, last_ct1ca; struct timer_list timer; struct work_struct reset_work; } hangcheck; @@ -202,6 +201,11 @@ struct vc4_exec_info { /* Sequence number for this bin/render job. */ uint64_t seqno; + /* Last current addresses the hardware was processing when the +* hangcheck timer checked on us. +*/ + uint32_t last_ct0ca, last_ct1ca; + /* Kernel-space copy of the ioctl arguments */ struct drm_vc4_submit_cl *args; diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 48ce30a..1b7adf1 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -257,10 +257,17 @@ vc4_hangcheck_elapsed(unsigned long data) struct drm_device *dev = (struct drm_device *)data; struct vc4_dev *vc4 = to_vc4_dev(dev); uint32_t ct0ca, ct1ca; + unsigned long irqflags; + struct vc4_exec_info *exec; + + spin_lock_irqsave(&vc4->job_lock, irqflags); + exec = vc4_first_job(vc4); /* If idle, we can stop watching for hangs. */ - if (list_empty(&vc4->job_list)) + if (!exec) { + spin_unlock_irqrestore(&vc4->job_lock, irqflags); return; + } ct0ca = V3D_READ(V3D_CTNCA(0)); ct1ca = V3D_READ(V3D_CTNCA(1)); @@ -268,14 +275,16 @@ vc4_hangcheck_elapsed(unsigned long data) /* If we've made any progress in execution, rearm the timer * and wait. */ - if (ct0ca != vc4->hangcheck.last_ct0ca || - ct1ca != vc4->hangcheck.last_ct1ca) { - vc4->hangcheck.last_ct0ca = ct0ca; - vc4->hangcheck.last_ct1ca = ct1ca; + if (ct0ca != exec->last_ct0ca || ct1ca != exec->last_ct1ca) { + exec->last_ct0ca = ct0ca; + exec->last_ct1ca = ct1ca; + spin_unlock_irqrestore(&vc4->job_lock, irqflags); vc4_queue_hangcheck(dev); return; } + spin_unlock_irqrestore(&vc4->job_lock, irqflags); + /* We've gone too long with no progress, reset. This has to * be done from a work struct, since resetting can sleep and * this timer hook isn't allowed to. -- 2.7.0
[PATCH 2/3] drm/vc4: Enable runtime PM.
This may actually get us a feature that the closed driver didn't have: turning off the GPU in between rendering jobs, while the V3D device is still opened by the client. There may be some tuning to be applied here to use autosuspend so that we don't bounce the device's power so much, but in steady-state GPU-bound rendering we keep the power on (since we keep multiple jobs outstanding) and even if we power cycle on every job we can still manage at least 680 fps. More importantly, though, runtime PM will allow us to power off the device to do a GPU reset. Signed-off-by: Eric Anholt --- I'm not 100% sure about the closed driver comparison -- the equivalent of the kernel side for the closed driver keeps the power on as far as I can see, but their userspace equivalent may open/close the kernel more frequenctly than I expect. drivers/gpu/drm/vc4/vc4_drv.h | 1 + drivers/gpu/drm/vc4/vc4_gem.c | 10 ++ drivers/gpu/drm/vc4/vc4_v3d.c | 36 3 files changed, 47 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index b4a26fd..b65e785 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -141,6 +141,7 @@ struct vc4_seqno_cb { }; struct vc4_v3d { + struct vc4_dev *vc4; struct platform_device *pdev; void __iomem *regs; }; diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 1b7adf1..440ad03 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -626,6 +627,7 @@ fail: static void vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec) { + struct vc4_dev *vc4 = to_vc4_dev(dev); unsigned i; /* Need the struct lock for drm_gem_object_unreference(). */ @@ -644,6 +646,8 @@ vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec) } mutex_unlock(&dev->struct_mutex); + pm_runtime_put(&vc4->v3d->pdev->dev); + kfree(exec); } @@ -794,6 +798,12 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data, return -ENOMEM; } + ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev); + if (ret < 0) { + kfree(exec); + return ret; + } + exec->args = args; INIT_LIST_HEAD(&exec->unref_list); diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c index 314ff71..930851f 100644 --- a/drivers/gpu/drm/vc4/vc4_v3d.c +++ b/drivers/gpu/drm/vc4/vc4_v3d.c @@ -17,6 +17,7 @@ */ #include "linux/component.h" +#include "linux/pm_runtime.h" #include "vc4_drv.h" #include "vc4_regs.h" @@ -167,6 +168,29 @@ static void vc4_v3d_init_hw(struct drm_device *dev) V3D_WRITE(V3D_VPMBASE, 0); } +#ifdef CONFIG_PM_SLEEP +static int vc4_v3d_runtime_suspend(struct device *dev) +{ + struct vc4_v3d *v3d = dev_get_drvdata(dev); + struct vc4_dev *vc4 = v3d->vc4; + + vc4_irq_uninstall(vc4->dev); + + return 0; +} + +static int vc4_v3d_runtime_resume(struct device *dev) +{ + struct vc4_v3d *v3d = dev_get_drvdata(dev); + struct vc4_dev *vc4 = v3d->vc4; + + vc4_v3d_init_hw(vc4->dev); + vc4_irq_postinstall(vc4->dev); + + return 0; +} +#endif + static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) { struct platform_device *pdev = to_platform_device(dev); @@ -179,6 +203,8 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) if (!v3d) return -ENOMEM; + dev_set_drvdata(dev, v3d); + v3d->pdev = pdev; v3d->regs = vc4_ioremap_regs(pdev, 0); @@ -186,6 +212,7 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) return PTR_ERR(v3d->regs); vc4->v3d = v3d; + v3d->vc4 = vc4; if (V3D_READ(V3D_IDENT0) != V3D_EXPECTED_IDENT0) { DRM_ERROR("V3D_IDENT0 read 0x%08x instead of 0x%08x\n", @@ -207,6 +234,8 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) return ret; } + pm_runtime_enable(dev); + return 0; } @@ -216,6 +245,8 @@ static void vc4_v3d_unbind(struct device *dev, struct device *master, struct drm_device *drm = dev_get_drvdata(master); struct vc4_dev *vc4 = to_vc4_dev(drm); + pm_runtime_disable(dev); + drm_irq_uninstall(drm); /* Disable the binner's overflow memory address, so the next @@ -228,6 +259,10 @@ static void vc4_v3d_unbind(struct device *dev, struct device *master, vc4->v3d = NULL; } +static const struct dev_pm_ops vc4_v3d_pm_ops = { + SET_RUNTIME_PM_OPS(vc4_v3
[GIT PULL] bcm2835 DT changes for 4.6
Hi Florian. Here's the first set of patches for bcm2835 for 4.6. We've got more DT patches that are going to happen for new boards, too, but they're still getting polished. The following changes since commit 92e963f50fc74041b5e9e744c330dca48e04f08d: Linux 4.5-rc1 (2016-01-24 13:06:47 -0800) are available in the git repository at: g...@github.com:anholt/linux.git tags/bcm2835-dt-next-2016-02-04 for you to fetch changes up to 5ec6f2cd8ec4bcd38ba199ea8711a5ec906d85e7: ARM: bcm2835: Add the Raspberry Pi power domain driver to the DT. (2016-02-02 20:02:45 -0800) This pull request covers mostly DT changes that didn't make it into 4.5 because required header files went through other trees. Alexander Aring (1): ARM: bcm2835: Add the Raspberry Pi power domain driver to the DT. Lubomir Rintel (1): ARM: bcm2835: dt: Add Raspberry Pi Model A Martin Sperl (2): ARM: bcm2835: add the auxiliary spi1 and spi2 to the device tree ARM: bcm2835: follow dt uart node-naming convention Remi Pommarel (1): ARM: bcm2835: Add PWM clock support to the device tree arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/bcm2835-rpi-a.dts | 24 arch/arm/boot/dts/bcm2835-rpi.dtsi | 16 arch/arm/boot/dts/bcm283x.dtsi | 35 +-- 4 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 arch/arm/boot/dts/bcm2835-rpi-a.dts
[PATCH 1/5] ARM: bcm2835: Define standard pinctrl groups in the gpio node.
The BCM2835-ARM-Peripherals.pdf documentation specifies what the function selects do for the pins, and there are a bunch of obvious groupings to be made. With these created, we'll be able to replace bcm2835-rpi.dtsi's main "set all of these pins to alt0" with references to specific groups we want enabled. Signed-off-by: Eric Anholt --- arch/arm/boot/dts/bcm283x.dtsi | 170 + 1 file changed, 170 insertions(+) diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi index 8aaf193..e91198e 100644 --- a/arch/arm/boot/dts/bcm283x.dtsi +++ b/arch/arm/boot/dts/bcm283x.dtsi @@ -110,6 +110,176 @@ interrupt-controller; #interrupt-cells = <2>; + + /* Defines pin muxing groups according to +* BCM2835-ARM-Peripherals.pdf page 102. +* +* While each pin can have its mux selected +* for various functions individually, some +* groups only make sense to switch to a +* particular function together. +*/ + i2c0_gpio0: i2c0_gpio0 { + brcm,pins = <0 1>; + brcm,function = ; + }; + i2c1_gpio2: i2c1_gpio2 { + brcm,pins = <2 3>; + brcm,function = ; + }; + gpclk0_gpio4: gpclk0_gpio4 { + brcm,pins = <4>; + brcm,function = ; + }; + gpclk1_gpio5: gpclk1_gpio5 { + brcm,pins = <5>; + brcm,function = ; + }; + gpclk2_gpio6: gpclk2_gpio6 { + brcm,pins = <6>; + brcm,function = ; + }; + spi0_gpio7: spi0_gpio7 { + brcm,pins = <7 8 9 10 11>; + brcm,function = ; + }; + pwm0_gpio12: pwm0_gpio12 { + brcm,pins = <12>; + brcm,function = ; + }; + pwm1_gpio13: pwm1_gpio13 { + brcm,pins = <13>; + brcm,function = ; + }; + uart0_gpio14: uart0_gpio14 { + brcm,pins = <14 15>; + brcm,function = ; + }; + pcm_gpio18: pcm_gpio18 { + brcm,pins = <18 19 20 21>; + brcm,function = ; + }; + i2c0_gpio32: i2c0_gpio32 { + brcm,pins = <32 34>; + brcm,function = ; + }; + spio0_gpio35: spio0_gpio35 { + brcm,pins = <35 36 37 38 39>; + brcm,function = ; + }; + pwm0_gpio40: pwm0_gpio40 { + brcm,pins = <40>; + brcm,function = ; + }; + pwm1_gpio41: pwm1_gpio41 { + brcm,pins = <41>; + brcm,function = ; + }; + gpclk1_gpio42: gpclk1_gpio42 { + brcm,pins = <42>; + brcm,function = ; + }; + gpclk2_gpio43: gpclk2_gpio43 { + brcm,pins = <43>; + brcm,function = ; + }; + gpclk1_gpio44: gpclk1_gpio44 { + brcm,pins = <44>; + brcm,function = ; + }; + pwm1_gpio45: pwm1_gpio45 { + brcm,pins = <45>; + brcm,function = ; + }; + i2c0_gpio44: i2c0_gpio44 { + brcm,pins = <44 45>; + brcm,function = ; + }; + pcm_gpio28: pcm_gpio28 { + brcm,pins = <28 29 30 31>; + brcm,function = ; + }; +
[PATCH 5/5] ARM: bcm2835: Move most RPi default pin groups to their devices.
This way we can get the duplicated pin group definitions out of each RPi board file, and just leave the i2s variations in them. Signed-off-by: Eric Anholt --- arch/arm/boot/dts/bcm2835-rpi-a-plus.dts | 14 +++--- arch/arm/boot/dts/bcm2835-rpi-a.dts | 14 +++--- arch/arm/boot/dts/bcm2835-rpi-b-plus.dts | 14 +++--- arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts | 14 +++--- arch/arm/boot/dts/bcm2835-rpi-b.dts | 12 arch/arm/boot/dts/bcm2835-rpi.dtsi | 20 arch/arm/boot/dts/bcm2836-rpi-2-b.dts| 14 +++--- 7 files changed, 35 insertions(+), 67 deletions(-) diff --git a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts index 1db6835..a00cbbe 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts @@ -20,15 +20,7 @@ }; }; -&gpio { - pinctrl-0 = <&i2c0_gpio0 -&i2c1_gpio2 -&gpclk0_gpio4 -&gpclk1_gpio5 -&spi0_gpio7 -&pcm_gpio18 -&pwm0_gpio40 -&pwm1_gpio45 -&emmc_gpio48 -&gpioout>; +&i2s { + pinctrl-names = "default"; + pinctrl-0 = <&pcm_gpio18>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi-a.dts b/arch/arm/boot/dts/bcm2835-rpi-a.dts index 25d2114..23e6b6f 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-a.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-a.dts @@ -13,15 +13,7 @@ }; }; -&gpio { - pinctrl-0 = <&i2c0_gpio0 -&i2c1_gpio2 -&gpclk0_gpio4 -&gpclk1_gpio5 -&spi0_gpio7 -&pcm_gpio28 -&pwm0_gpio40 -&pwm1_gpio45 -&emmc_gpio48 -&gpioout>; +&i2s { + pinctrl-names = "default"; + pinctrl-0 = <&pcm_gpio28>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts index d8057b8..029b589 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts @@ -20,15 +20,7 @@ }; }; -&gpio { - pinctrl-0 = <&i2c0_gpio0 -&i2c1_gpio2 -&gpclk0_gpio4 -&gpclk1_gpio5 -&spi0_gpio7 -&pcm_gpio18 -&pwm0_gpio40 -&pwm1_gpio45 -&emmc_gpio48 -&gpioout>; +&i2s { + pinctrl-names = "default"; + pinctrl-0 = <&pcm_gpio18>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts index e7dbff4..da1bc27 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts @@ -13,15 +13,7 @@ }; }; -&gpio { - pinctrl-0 = <&i2c0_gpio0 -&i2c1_gpio2 -&gpclk0_gpio4 -&gpclk1_gpio5 -&spi0_gpio7 -&pcm_gpio28 -&pwm0_gpio40 -&pwm1_gpio45 -&emmc_gpio48 -&gpioout>; +&i2s { + pinctrl-names = "default"; + pinctrl-0 = <&pcm_gpio28>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts index d154049..df275d4 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts @@ -12,15 +12,3 @@ }; }; }; - -&gpio { - pinctrl-0 = <&i2c0_gpio0 -&i2c1_gpio2 -&gpclk0_gpio4 -&gpclk1_gpio5 -&spi0_gpio7 -&pwm0_gpio40 -&pwm1_gpio45 -&emmc_gpio48 -&gpioout>; -}; diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi index eff27b0..b8efd41 100644 --- a/arch/arm/boot/dts/bcm2835-rpi.dtsi +++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi @@ -31,6 +31,9 @@ &gpio { pinctrl-names = "default"; + pinctrl-0 = <&gpclk0_gpio4 +&gpclk1_gpio5 +&gpioout>; gpioout: gpioout { brcm,pins = <6>; @@ -39,11 +42,17 @@ }; &i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_gpio0>; + status = "okay"; clock-frequency = <10>; }; &i2c1 { +
[PATCH 2/5] ARM: bcm2835: Replace alt0/i2s_alt[02] with standard groups.
Since all of these pins were documented, we can use their names to explain what's going on. Signed-off-by: Eric Anholt --- arch/arm/boot/dts/bcm2835-rpi-a-plus.dts | 17 ++--- arch/arm/boot/dts/bcm2835-rpi-a.dts | 17 ++--- arch/arm/boot/dts/bcm2835-rpi-b-plus.dts | 17 ++--- arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts | 17 ++--- arch/arm/boot/dts/bcm2835-rpi-b.dts | 10 +- arch/arm/boot/dts/bcm2835-rpi.dtsi | 5 - arch/arm/boot/dts/bcm2836-rpi-2-b.dts| 17 ++--- 7 files changed, 59 insertions(+), 41 deletions(-) diff --git a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts index 228614f..0a8b92e 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts @@ -21,11 +21,14 @@ }; &gpio { - pinctrl-0 = <&gpioout &alt0 &i2s_alt0 &alt3>; - - /* I2S interface */ - i2s_alt0: i2s_alt0 { - brcm,pins = <18 19 20 21>; - brcm,function = ; - }; + pinctrl-0 = <&i2c0_gpio0 +&i2c1_gpio2 +&gpclk0_gpio4 +&gpclk1_gpio5 +&spi0_gpio7 +&pcm_gpio18 +&pwm0_gpio40 +&pwm1_gpio45 +&gpioout +&alt3>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi-a.dts b/arch/arm/boot/dts/bcm2835-rpi-a.dts index ddd..d093407 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-a.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-a.dts @@ -14,11 +14,14 @@ }; &gpio { - pinctrl-0 = <&gpioout &alt0 &i2s_alt2 &alt3>; - - /* I2S interface */ - i2s_alt2: i2s_alt2 { - brcm,pins = <28 29 30 31>; - brcm,function = ; - }; + pinctrl-0 = <&i2c0_gpio0 +&i2c1_gpio2 +&gpclk0_gpio4 +&gpclk1_gpio5 +&spi0_gpio7 +&pcm_gpio28 +&pwm0_gpio40 +&pwm1_gpio45 +&gpioout +&alt3>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts index ef54050..c26b81d 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts @@ -21,11 +21,14 @@ }; &gpio { - pinctrl-0 = <&gpioout &alt0 &i2s_alt0 &alt3>; - - /* I2S interface */ - i2s_alt0: i2s_alt0 { - brcm,pins = <18 19 20 21>; - brcm,function = ; - }; + pinctrl-0 = <&i2c0_gpio0 +&i2c1_gpio2 +&gpclk0_gpio4 +&gpclk1_gpio5 +&spi0_gpio7 +&pcm_gpio18 +&pwm0_gpio40 +&pwm1_gpio45 +&gpioout +&alt3>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts index 86f1f2f..a5b606e 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts @@ -14,11 +14,14 @@ }; &gpio { - pinctrl-0 = <&gpioout &alt0 &i2s_alt2 &alt3>; - - /* I2S interface */ - i2s_alt2: i2s_alt2 { - brcm,pins = <28 29 30 31>; - brcm,function = ; - }; + pinctrl-0 = <&i2c0_gpio0 +&i2c1_gpio2 +&gpclk0_gpio4 +&gpclk1_gpio5 +&spi0_gpio7 +&pcm_gpio28 +&pwm0_gpio40 +&pwm1_gpio45 +&gpioout +&alt3>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts index 4859e9d..97e3c2f 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts @@ -14,5 +14,13 @@ }; &gpio { - pinctrl-0 = <&gpioout &alt0 &alt3>; + pinctrl-0 = <&i2c0_gpio0 +&i2c1_gpio2 +&gpclk0_gpio4 +&gpclk1_gpio5 +&spi0_gpio7 +&pwm0_gpio40 +&pwm1_gpio45 +&gpioout +&alt3>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi index 76bdbca..141b18c 100644 --- a/arch/arm/boot/dts/bcm2835-rpi.dtsi +++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi @@ -37,11 +37,6 @@ brcm,function = ; }; - alt0: a
[PATCH 4/5] ARM: bcm2835: Add a group for mapping pins 48-53 to sdhost.
This pin group definition comes from downstream. We don't have a driver for sdhost integrated yet, but they've been experimenting with it and it sounds useful to bring over. Signed-off-by: Eric Anholt --- arch/arm/boot/dts/bcm283x.dtsi | 4 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi index 70a6814..0bb32cc 100644 --- a/arch/arm/boot/dts/bcm283x.dtsi +++ b/arch/arm/boot/dts/bcm283x.dtsi @@ -191,6 +191,10 @@ brcm,pins = <45>; brcm,function = ; }; + sdhost_gpio48: sdhost_gpio48 { + brcm,pins = <48 49 50 51 52 53>; + brcm,function = ; + }; i2c0_gpio44: i2c0_gpio44 { brcm,pins = <44 45>; brcm,function = ; -- 2.7.0
[PATCH 3/5] ARM: bcm2835: Move the emmc pin group to bcm283x.dtsi.
While it's not documented in the public PDF, it is internally. This is a standard pin group for the 283x, not rpi-specific. Signed-off-by: Eric Anholt --- arch/arm/boot/dts/bcm2835-rpi-a-plus.dts | 4 ++-- arch/arm/boot/dts/bcm2835-rpi-a.dts | 4 ++-- arch/arm/boot/dts/bcm2835-rpi-b-plus.dts | 4 ++-- arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts | 4 ++-- arch/arm/boot/dts/bcm2835-rpi-b.dts | 4 ++-- arch/arm/boot/dts/bcm2835-rpi.dtsi | 5 - arch/arm/boot/dts/bcm2836-rpi-2-b.dts| 4 ++-- arch/arm/boot/dts/bcm283x.dtsi | 4 8 files changed, 16 insertions(+), 17 deletions(-) diff --git a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts index 0a8b92e..1db6835 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts @@ -29,6 +29,6 @@ &pcm_gpio18 &pwm0_gpio40 &pwm1_gpio45 -&gpioout -&alt3>; +&emmc_gpio48 +&gpioout>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi-a.dts b/arch/arm/boot/dts/bcm2835-rpi-a.dts index d093407..25d2114 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-a.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-a.dts @@ -22,6 +22,6 @@ &pcm_gpio28 &pwm0_gpio40 &pwm1_gpio45 -&gpioout -&alt3>; +&emmc_gpio48 +&gpioout>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts index c26b81d..d8057b8 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts @@ -29,6 +29,6 @@ &pcm_gpio18 &pwm0_gpio40 &pwm1_gpio45 -&gpioout -&alt3>; +&emmc_gpio48 +&gpioout>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts index a5b606e..e7dbff4 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts @@ -22,6 +22,6 @@ &pcm_gpio28 &pwm0_gpio40 &pwm1_gpio45 -&gpioout -&alt3>; +&emmc_gpio48 +&gpioout>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts index 97e3c2f..d154049 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts @@ -21,6 +21,6 @@ &spi0_gpio7 &pwm0_gpio40 &pwm1_gpio45 -&gpioout -&alt3>; +&emmc_gpio48 +&gpioout>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi index 141b18c..eff27b0 100644 --- a/arch/arm/boot/dts/bcm2835-rpi.dtsi +++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi @@ -36,11 +36,6 @@ brcm,pins = <6>; brcm,function = ; }; - - alt3: alt3 { - brcm,pins = <48 49 50 51 52 53>; - brcm,function = ; - }; }; &i2c0 { diff --git a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts index 52798ca..3e9226f 100644 --- a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts +++ b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts @@ -33,6 +33,6 @@ &pcm_gpio18 &pwm0_gpio40 &pwm1_gpio45 -&gpioout -&alt3>; +&emmc_gpio48 +&gpioout>; }; diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi index e91198e..70a6814 100644 --- a/arch/arm/boot/dts/bcm283x.dtsi +++ b/arch/arm/boot/dts/bcm283x.dtsi @@ -232,6 +232,10 @@ brcm,pins = <32 33>; brcm,function = ; }; + emmc_gpio48: emmc_gpio48 { + brcm,pins = <48 49 50 51 52 53>; + brcm,function = ; + }; spi1_gpio16: spi1_gpio16 { brcm,pins = <16 17 18 19 20 21>; brcm,function = ; -- 2.7.0
[PATCH 0/5] BCM2835 pinctrl DT rework (resend)
Here's a series for cleaning up the pinctrl groups on BCM2835 (Raspberry Pi). This was partially inspired by Stefan Wahren's patches for the EMMC SDHCI controller, but really triggered by needing to switch pinmuxes to enable the SDHOST SD controller (which gives me a 60% read speed improvement). Patches for adding that driver will follow. I think this is more or less how pinctrl is expected to be used for a platform like this. It certainly cleans up the board files. This is a resend because only 3 came through last time. My former SMTP relay decided to start rejecting half my mails this week. I've now swapped systems. Eric Anholt (5): ARM: bcm2835: Define standard pinctrl groups in the gpio node. ARM: bcm2835: Replace alt0/i2s_alt[02] with standard groups. ARM: bcm2835: Move the emmc pin group to bcm283x.dtsi. ARM: bcm2835: Add a group for mapping pins 48-53 to sdhost. ARM: bcm2835: Move most RPi default pin groups to their devices. arch/arm/boot/dts/bcm2835-rpi-a-plus.dts | 11 +- arch/arm/boot/dts/bcm2835-rpi-a.dts | 11 +- arch/arm/boot/dts/bcm2835-rpi-b-plus.dts | 11 +- arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts | 11 +- arch/arm/boot/dts/bcm2835-rpi-b.dts | 4 - arch/arm/boot/dts/bcm2835-rpi.dtsi | 30 -- arch/arm/boot/dts/bcm2836-rpi-2-b.dts| 11 +- arch/arm/boot/dts/bcm283x.dtsi | 178 +++ 8 files changed, 213 insertions(+), 54 deletions(-) -- 2.7.0
[PATCH 1/4] dt-bindings: Add binding for brcm,bcm2835-sdhost.
This is the other SD controller on the platform, which can be swapped to the role of SD card host using pin muxing. Signed-off-by: Eric Anholt --- .../bindings/mmc/brcm,bcm2835-sdhost.txt | 25 ++ 1 file changed, 25 insertions(+) create mode 100644 Documentation/devicetree/bindings/mmc/brcm,bcm2835-sdhost.txt diff --git a/Documentation/devicetree/bindings/mmc/brcm,bcm2835-sdhost.txt b/Documentation/devicetree/bindings/mmc/brcm,bcm2835-sdhost.txt new file mode 100644 index 000..f55c446 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/brcm,bcm2835-sdhost.txt @@ -0,0 +1,25 @@ +Broadcom BCM2835 SDHOST controller + +This file documents differences between the core properties described +by mmc.txt and the properties that represent the BCM2835 SDHOST controller. + +Required properties: +- compatible: Must be "brcm,bcm2835-sdhost" +- clocks: The phandle for the clock feeding the SDHOST controller + +Optional properties: +- dmas:DMA channel phandles for read and write +- dma-names: DMA channel names for read and write, must be "rx" and "tx" + See Documentation/devicetree/bindings/dma/dma.txt for details + +Example: + +sdhost: sdhost@7e202000 { + compatible = "brcm,bcm2835-sdhost"; + reg = <0x7e202000 0x100>; + interrupts = <2 24>; + clocks = <&clocks BCM2835_CLOCK_VPU>; + dmas = <&dma 13>, + <&dma 13>; + dma-names = "tx", "rx"; +}; -- 2.7.0
[PATCH 0/4] bcm2835 SDHOST controller
Here's a series to enable the SDHOST controller. It gives us better performance than our old sdhci-bcm2835.c. The downstream Raspberry Pi kernel appears to be using this controller by default at this point. I've tried to do some testing on it (mounting filesystem, reading/writing files, speed tests), but I'm not sure what a good testing regimen for storage drivers would be. Eric Anholt (4): dt-bindings: Add binding for brcm,bcm2835-sdhost. mmc: bcm2835-sdhost: Add new driver for the internal SD controller. ARM: bcm2835: Include SDHOST in the device tree. ARM: bcm2835: Enable SDHOST by default. .../bindings/mmc/brcm,bcm2835-sdhost.txt | 25 + arch/arm/boot/dts/bcm2835-rpi.dtsi | 10 +- arch/arm/boot/dts/bcm283x.dtsi |8 + drivers/mmc/host/Kconfig |9 + drivers/mmc/host/Makefile |1 + drivers/mmc/host/bcm2835-sdhost.c | 1652 6 files changed, 1704 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/mmc/brcm,bcm2835-sdhost.txt create mode 100644 drivers/mmc/host/bcm2835-sdhost.c -- 2.7.0
[PATCH 2/4] mmc: bcm2835-sdhost: Add new driver for the internal SD controller.
The 2835 has two SD controllers: The Arasan SDHCI controller that we currently use, and a custom SD controller. The custom one runs faster at 16.7MB/sec reads on PIO (according to hdparm -t on a Pi 2B) instead of 10.15MB/sec, and up to 18.45MB/sec with DMA enabled. The code was originally written by Phil Elwell in the downstream Rasbperry Pi tree, and I did a major cleanup on it (+319, -721 lines out of the original 2055) for inclusion. Signed-off-by: Eric Anholt --- drivers/mmc/host/Kconfig |9 + drivers/mmc/host/Makefile |1 + drivers/mmc/host/bcm2835-sdhost.c | 1652 + 3 files changed, 1662 insertions(+) create mode 100644 drivers/mmc/host/bcm2835-sdhost.c diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 1526b8a..b991a21 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -778,6 +778,15 @@ config MMC_TOSHIBA_PCI depends on PCI help +config MMC_BCM2835_SDHOST + tristate "platform support for the BCM2835 SDHOST MMC Controller" + depends on ARCH_BCM2835 || COMPILE_TEST + help + This selects the BCM2835 SDHOST MMC controller. If you have a BCM2835 + platform with SD or MMC devices, say Y or M here. + + If unsure, say N. + config MMC_MTK tristate "MediaTek SD/MMC Card Interface support" depends on HAS_DMA diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 3595f83..b31b994 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -57,6 +57,7 @@ obj-$(CONFIG_MMC_MOXART) += moxart-mmc.o obj-$(CONFIG_MMC_SUNXI)+= sunxi-mmc.o obj-$(CONFIG_MMC_USDHI6ROL0) += usdhi6rol0.o obj-$(CONFIG_MMC_TOSHIBA_PCI) += toshsd.o +obj-$(CONFIG_MMC_BCM2835_SDHOST) += bcm2835-sdhost.o obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o obj-$(CONFIG_MMC_REALTEK_USB) += rtsx_usb_sdmmc.o diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c new file mode 100644 index 000..a84f675 --- /dev/null +++ b/drivers/mmc/host/bcm2835-sdhost.c @@ -0,0 +1,1652 @@ +/* + * BCM2835 SD host driver. + * + * Author: Phil Elwell + * Copyright (C) 2015-2016 Raspberry Pi (Trading) Ltd. + * + * Based on + * mmc-bcm2835.c by Gellert Weisz + * which is, in turn, based on + * sdhci-bcm2708.c by Broadcom + * sdhci-bcm2835.c by Stephen Warren and Oleksandr Tymoshenko + * sdhci.c and sdhci-pci.c by Pierre Ossman + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SDCMD 0x00 /* Command to SD card - 16 R/W */ +#define SDARG 0x04 /* Argument to SD card - 32 R/W */ +#define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */ +#define SDCDIV 0x0c /* Start value for clock divider - 11 R/W */ +#define SDRSP0 0x10 /* SD card response (31:0) - 32 R */ +#define SDRSP1 0x14 /* SD card response (63:32)- 32 R */ +#define SDRSP2 0x18 /* SD card response (95:64)- 32 R */ +#define SDRSP3 0x1c /* SD card response (127:96) - 32 R */ +#define SDHSTS 0x20 /* SD host status - 11 R */ +#define SDVDD 0x30 /* SD card power control - 1 R/W */ +#define SDEDM 0x34 /* Emergency Debug Mode- 13 R/W */ +#define SDHCFG 0x38 /* Host configuration - 2 R/W */ +#define SDHBCT 0x3c /* Host byte count (debug) - 32 R/W */ +#define SDDATA 0x40 /* Data to/from SD card- 32 R/W */ +#define SDHBLC 0x50 /* Host block count (SDIO/SDHC)- 9 R/W */ + +#define SDCMD_NEW_FLAG 0x8000 +#define SDCMD_FAIL_FLAG 0x4000 +#define SDCMD_BUSYWAIT 0x800 +#define SDCMD_NO_RESPONSE 0x400 +#define SDCMD_LONG_RESPONSE 0x200 +#define SDCMD_WRITE_CMD 0x80 +#define SDCMD_READ_CMD 0x40 +#define SDCMD_CMD_MASK 0x3f + +#define SDCDIV_MAX_CDIV 0x7ff + +#define SDHSTS_BUSY_IRPT0x400 +#define SDHSTS_BLOCK_IRPT 0x200 +#define SDHSTS_SDIO_IRPT0x100 +#define SDHSTS_REW_TIME_OUT 0x80 +#
[PATCH 3/4] ARM: bcm2835: Include SDHOST in the device tree.
It's disabled by default, and will be enabled by a particular board's DT. The DMA channels are also currently left out, because our DMA engine support doesn't yet include slave SG, and there doesn't appear to be a clean way to include "does slave SG" in the channel request/config process. Signed-off-by: Eric Anholt --- arch/arm/boot/dts/bcm283x.dtsi | 8 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi index 597a78f..7b2721b 100644 --- a/arch/arm/boot/dts/bcm283x.dtsi +++ b/arch/arm/boot/dts/bcm283x.dtsi @@ -366,6 +366,14 @@ status = "disabled"; }; + sdhost: sdhost@7e202000 { + compatible = "brcm,bcm2835-sdhost"; + reg = <0x7e202000 0x100>; + interrupts = <2 24>; + clocks = <&clocks BCM2835_CLOCK_VPU>; + status = "disabled"; + }; + pwm: pwm@7e20c000 { compatible = "brcm,bcm2835-pwm"; reg = <0x7e20c000 0x28>; -- 2.7.0
[PATCH 4/4] ARM: bcm2835: Enable SDHOST by default.
This improves read speed on my SD card (as reported by hdparm -t) from 10.15MB/sec to 16.70MB/sec. Once we add slave DMA, we can get to 18.45MB/sec. Signed-off-by: Eric Anholt --- arch/arm/boot/dts/bcm2835-rpi.dtsi | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi index b8efd41..65d3594 100644 --- a/arch/arm/boot/dts/bcm2835-rpi.dtsi +++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi @@ -65,10 +65,18 @@ pinctrl-names = "default"; pinctrl-0 = <&emmc_gpio48>; - status = "okay"; bus-width = <4>; }; +&sdhost { + pinctrl-names = "default"; + pinctrl-0 = <&sdhost_gpio48>; + + bus-width = <4>; + + status = "okay"; +}; + &pwm { pinctrl-names = "default"; pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio45>; -- 2.7.0
[PATCH] pinctrl-bcm2835: Fix cut-and-paste error in "pull" parsing
From: Phil Elwell The DT bindings for pinctrl-bcm2835 allow both the function and pull to contain either one entry or one per pin. However, an error in the DT parsing can cause failures if the number of pulls differs from the number of functions. Signed-off-by: Eric Anholt Cc: sta...@vger.kernel.org --- Yes, the s-o-b differs from the author of the commit, but this falls under part b) of the process. Phil, any chance you could start putting Signed-off-by lines on your kernel commits? drivers/pinctrl/bcm/pinctrl-bcm2835.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index 0f5997c..08b1d93 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -779,7 +779,7 @@ static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, } if (num_pulls) { err = of_property_read_u32_index(np, "brcm,pull", - (num_funcs > 1) ? i : 0, &pull); + (num_pulls > 1) ? i : 0, &pull); if (err) goto out; err = bcm2835_pctl_dt_node_to_map_pull(pc, np, pin, -- 2.7.0
[PATCH 1/2] drm/vc4: Let gpiolib know that we're OK with sleeping for HPD.
Fixes an error thrown every few seconds when we poll HPD when it's on a I2C to GPIO expander. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index c69c046..709ed57 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -165,7 +165,7 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) struct vc4_dev *vc4 = to_vc4_dev(dev); if (vc4->hdmi->hpd_gpio) { - if (gpio_get_value(vc4->hdmi->hpd_gpio)) + if (gpio_get_value_cansleep(vc4->hdmi->hpd_gpio)) return connector_status_connected; else return connector_status_disconnected; -- 2.7.0
[PATCH 0/2] drm/vc4: Fixes for Raspberry Pi 3
These are for fixing the vc4 driver on the Pi 3. Note that patch 2 will also be necessary for fixing HPD on the Pi2, which we've been carrying downstream patches to work around until now. Eric Anholt (2): drm/vc4: Let gpiolib know that we're OK with sleeping for HPD. drm/vc4: Respect GPIO_ACTIVE_LOW on HDMI HPD if set in the devicetree. drivers/gpu/drm/vc4/vc4_hdmi.c | 12 ++-- 1 file changed, 10 insertions(+), 2 deletions(-) -- 2.7.0
[PATCH 2/2] drm/vc4: Respect GPIO_ACTIVE_LOW on HDMI HPD if set in the devicetree.
The original Raspberry Pi had the GPIO active high, but the later models are active low. The DT GPIO bindings allow specifying the active flag, except that it doesn't get propagated to the gpiodesc, so you have to handle it yourself. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_hdmi.c | 12 ++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 709ed57..dc60485 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -47,6 +47,7 @@ struct vc4_hdmi { void __iomem *hdmicore_regs; void __iomem *hd_regs; int hpd_gpio; + bool hpd_active_low; struct clk *pixel_clock; struct clk *hsm_clock; @@ -165,7 +166,8 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) struct vc4_dev *vc4 = to_vc4_dev(dev); if (vc4->hdmi->hpd_gpio) { - if (gpio_get_value_cansleep(vc4->hdmi->hpd_gpio)) + if (gpio_get_value_cansleep(vc4->hdmi->hpd_gpio) ^ + vc4->hdmi->hpd_active_low) return connector_status_connected; else return connector_status_disconnected; @@ -506,11 +508,17 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) * we'll use the HDMI core's register. */ if (of_find_property(dev->of_node, "hpd-gpios", &value)) { - hdmi->hpd_gpio = of_get_named_gpio(dev->of_node, "hpd-gpios", 0); + enum of_gpio_flags hpd_gpio_flags; + + hdmi->hpd_gpio = of_get_named_gpio_flags(dev->of_node, +"hpd-gpios", 0, +&hpd_gpio_flags); if (hdmi->hpd_gpio < 0) { ret = hdmi->hpd_gpio; goto err_unprepare_hsm; } + + hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW; } vc4->hdmi = hdmi; -- 2.7.0
[PATCH 2/2] clk: bcm2835: Reuse CLK_DIVIDER_MAX_AT_ZERO for recalc_rate()
We were rolling this ourselves, but clk-divider can do it now. Signed-off-by: Eric Anholt --- drivers/clk/bcm/clk-bcm2835.c | 13 ++--- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index 9f4df8f..353e438 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -1060,16 +1060,7 @@ static long bcm2835_pll_divider_round_rate(struct clk_hw *hw, static unsigned long bcm2835_pll_divider_get_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw); - struct bcm2835_cprman *cprman = divider->cprman; - const struct bcm2835_pll_divider_data *data = divider->data; - u32 div = cprman_read(cprman, data->a2w_reg); - - div &= (1 << A2W_PLL_DIV_BITS) - 1; - if (div == 0) - div = 256; - - return parent_rate / div; + return clk_divider_ops.recalc_rate(hw, parent_rate); } static void bcm2835_pll_divider_off(struct clk_hw *hw) @@ -1430,7 +1421,7 @@ bcm2835_register_pll_divider(struct bcm2835_cprman *cprman, divider->div.reg = cprman->regs + data->a2w_reg; divider->div.shift = A2W_PLL_DIV_SHIFT; divider->div.width = A2W_PLL_DIV_BITS; - divider->div.flags = 0; + divider->div.flags = CLK_DIVIDER_MAX_AT_ZERO; divider->div.lock = &cprman->regs_lock; divider->div.hw.init = &init; divider->div.table = NULL; -- 2.7.0
[PATCH 1/2] clk: bcm2835: Fix setting of PLL divider clock rates
Our dividers weren't being set successfully because CM_PASSWORD wasn't included in the register write. It looks easier to just compute the divider to write ourselves than to update clk-divider for the ability to OR in some arbitrary bits on write. Fixes about half of the video modes on my HDMI monitor (everything except 720x400). Cc: sta...@vger.kernel.org Signed-off-by: Eric Anholt --- drivers/clk/bcm/clk-bcm2835.c | 12 +++- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index 015e687..9f4df8f 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -1107,13 +1107,15 @@ static int bcm2835_pll_divider_set_rate(struct clk_hw *hw, struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw); struct bcm2835_cprman *cprman = divider->cprman; const struct bcm2835_pll_divider_data *data = divider->data; - u32 cm; - int ret; + u32 cm, div, max_div = 1 << A2W_PLL_DIV_BITS; - ret = clk_divider_ops.set_rate(hw, rate, parent_rate); - if (ret) - return ret; + div = DIV_ROUND_UP_ULL(parent_rate, rate); + + div = min(div, max_div); + if (div == max_div) + div = 0; + cprman_write(cprman, data->a2w_reg, div); cm = cprman_read(cprman, data->cm_reg); cprman_write(cprman, data->cm_reg, cm | data->load_mask); cprman_write(cprman, data->cm_reg, cm & ~data->load_mask); -- 2.7.0
[PATCH 2/5] ARM: bcm2835: Replace alt0/i2s_alt[02] with standard groups.
Since all of these pins were documented, we can use their names to explain what's going on. Signed-off-by: Eric Anholt --- arch/arm/boot/dts/bcm2835-rpi-a-plus.dts | 17 ++--- arch/arm/boot/dts/bcm2835-rpi-a.dts | 17 ++--- arch/arm/boot/dts/bcm2835-rpi-b-plus.dts | 17 ++--- arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts | 17 ++--- arch/arm/boot/dts/bcm2835-rpi-b.dts | 10 +- arch/arm/boot/dts/bcm2835-rpi.dtsi | 5 - arch/arm/boot/dts/bcm2836-rpi-2-b.dts| 17 ++--- 7 files changed, 59 insertions(+), 41 deletions(-) diff --git a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts index 228614f..0a8b92e 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts @@ -21,11 +21,14 @@ }; &gpio { - pinctrl-0 = <&gpioout &alt0 &i2s_alt0 &alt3>; - - /* I2S interface */ - i2s_alt0: i2s_alt0 { - brcm,pins = <18 19 20 21>; - brcm,function = ; - }; + pinctrl-0 = <&i2c0_gpio0 +&i2c1_gpio2 +&gpclk0_gpio4 +&gpclk1_gpio5 +&spi0_gpio7 +&pcm_gpio18 +&pwm0_gpio40 +&pwm1_gpio45 +&gpioout +&alt3>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi-a.dts b/arch/arm/boot/dts/bcm2835-rpi-a.dts index ddd..d093407 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-a.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-a.dts @@ -14,11 +14,14 @@ }; &gpio { - pinctrl-0 = <&gpioout &alt0 &i2s_alt2 &alt3>; - - /* I2S interface */ - i2s_alt2: i2s_alt2 { - brcm,pins = <28 29 30 31>; - brcm,function = ; - }; + pinctrl-0 = <&i2c0_gpio0 +&i2c1_gpio2 +&gpclk0_gpio4 +&gpclk1_gpio5 +&spi0_gpio7 +&pcm_gpio28 +&pwm0_gpio40 +&pwm1_gpio45 +&gpioout +&alt3>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts index ef54050..c26b81d 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts @@ -21,11 +21,14 @@ }; &gpio { - pinctrl-0 = <&gpioout &alt0 &i2s_alt0 &alt3>; - - /* I2S interface */ - i2s_alt0: i2s_alt0 { - brcm,pins = <18 19 20 21>; - brcm,function = ; - }; + pinctrl-0 = <&i2c0_gpio0 +&i2c1_gpio2 +&gpclk0_gpio4 +&gpclk1_gpio5 +&spi0_gpio7 +&pcm_gpio18 +&pwm0_gpio40 +&pwm1_gpio45 +&gpioout +&alt3>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts index 86f1f2f..a5b606e 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts @@ -14,11 +14,14 @@ }; &gpio { - pinctrl-0 = <&gpioout &alt0 &i2s_alt2 &alt3>; - - /* I2S interface */ - i2s_alt2: i2s_alt2 { - brcm,pins = <28 29 30 31>; - brcm,function = ; - }; + pinctrl-0 = <&i2c0_gpio0 +&i2c1_gpio2 +&gpclk0_gpio4 +&gpclk1_gpio5 +&spi0_gpio7 +&pcm_gpio28 +&pwm0_gpio40 +&pwm1_gpio45 +&gpioout +&alt3>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts index 4859e9d..97e3c2f 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts @@ -14,5 +14,13 @@ }; &gpio { - pinctrl-0 = <&gpioout &alt0 &alt3>; + pinctrl-0 = <&i2c0_gpio0 +&i2c1_gpio2 +&gpclk0_gpio4 +&gpclk1_gpio5 +&spi0_gpio7 +&pwm0_gpio40 +&pwm1_gpio45 +&gpioout +&alt3>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi index 76bdbca..141b18c 100644 --- a/arch/arm/boot/dts/bcm2835-rpi.dtsi +++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi @@ -37,11 +37,6 @@ brcm,function = ; }; - alt0: a
[PATCH 5/5] ARM: bcm2835: Move most RPi default pin groups to their devices.
This way we can get the duplicated pin group definitions out of each RPi board file, and just leave the i2s variations in them. Signed-off-by: Eric Anholt --- arch/arm/boot/dts/bcm2835-rpi-a-plus.dts | 14 +++--- arch/arm/boot/dts/bcm2835-rpi-a.dts | 14 +++--- arch/arm/boot/dts/bcm2835-rpi-b-plus.dts | 14 +++--- arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts | 14 +++--- arch/arm/boot/dts/bcm2835-rpi-b.dts | 12 arch/arm/boot/dts/bcm2835-rpi.dtsi | 20 arch/arm/boot/dts/bcm2836-rpi-2-b.dts| 14 +++--- 7 files changed, 35 insertions(+), 67 deletions(-) diff --git a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts index 1db6835..a00cbbe 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts @@ -20,15 +20,7 @@ }; }; -&gpio { - pinctrl-0 = <&i2c0_gpio0 -&i2c1_gpio2 -&gpclk0_gpio4 -&gpclk1_gpio5 -&spi0_gpio7 -&pcm_gpio18 -&pwm0_gpio40 -&pwm1_gpio45 -&emmc_gpio48 -&gpioout>; +&i2s { + pinctrl-names = "default"; + pinctrl-0 = <&pcm_gpio18>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi-a.dts b/arch/arm/boot/dts/bcm2835-rpi-a.dts index 25d2114..23e6b6f 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-a.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-a.dts @@ -13,15 +13,7 @@ }; }; -&gpio { - pinctrl-0 = <&i2c0_gpio0 -&i2c1_gpio2 -&gpclk0_gpio4 -&gpclk1_gpio5 -&spi0_gpio7 -&pcm_gpio28 -&pwm0_gpio40 -&pwm1_gpio45 -&emmc_gpio48 -&gpioout>; +&i2s { + pinctrl-names = "default"; + pinctrl-0 = <&pcm_gpio28>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts index d8057b8..029b589 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts @@ -20,15 +20,7 @@ }; }; -&gpio { - pinctrl-0 = <&i2c0_gpio0 -&i2c1_gpio2 -&gpclk0_gpio4 -&gpclk1_gpio5 -&spi0_gpio7 -&pcm_gpio18 -&pwm0_gpio40 -&pwm1_gpio45 -&emmc_gpio48 -&gpioout>; +&i2s { + pinctrl-names = "default"; + pinctrl-0 = <&pcm_gpio18>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts index e7dbff4..da1bc27 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts @@ -13,15 +13,7 @@ }; }; -&gpio { - pinctrl-0 = <&i2c0_gpio0 -&i2c1_gpio2 -&gpclk0_gpio4 -&gpclk1_gpio5 -&spi0_gpio7 -&pcm_gpio28 -&pwm0_gpio40 -&pwm1_gpio45 -&emmc_gpio48 -&gpioout>; +&i2s { + pinctrl-names = "default"; + pinctrl-0 = <&pcm_gpio28>; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts index d154049..df275d4 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts @@ -12,15 +12,3 @@ }; }; }; - -&gpio { - pinctrl-0 = <&i2c0_gpio0 -&i2c1_gpio2 -&gpclk0_gpio4 -&gpclk1_gpio5 -&spi0_gpio7 -&pwm0_gpio40 -&pwm1_gpio45 -&emmc_gpio48 -&gpioout>; -}; diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi index eff27b0..b8efd41 100644 --- a/arch/arm/boot/dts/bcm2835-rpi.dtsi +++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi @@ -31,6 +31,9 @@ &gpio { pinctrl-names = "default"; + pinctrl-0 = <&gpclk0_gpio4 +&gpclk1_gpio5 +&gpioout>; gpioout: gpioout { brcm,pins = <6>; @@ -39,11 +42,17 @@ }; &i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_gpio0>; + status = "okay"; clock-frequency = <10>; }; &i2c1 { +
[PATCH 1/5] ARM: bcm2835: Define standard pinctrl groups in the gpio node.
The BCM2835-ARM-Peripherals.pdf documentation specifies what the function selects do for the pins, and there are a bunch of obvious groupings to be made. With these created, we'll be able to replace bcm2835-rpi.dtsi's main "set all of these pins to alt0" with references to specific groups we want enabled. Signed-off-by: Eric Anholt --- arch/arm/boot/dts/bcm283x.dtsi | 170 + 1 file changed, 170 insertions(+) diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi index 8aaf193..e91198e 100644 --- a/arch/arm/boot/dts/bcm283x.dtsi +++ b/arch/arm/boot/dts/bcm283x.dtsi @@ -110,6 +110,176 @@ interrupt-controller; #interrupt-cells = <2>; + + /* Defines pin muxing groups according to +* BCM2835-ARM-Peripherals.pdf page 102. +* +* While each pin can have its mux selected +* for various functions individually, some +* groups only make sense to switch to a +* particular function together. +*/ + i2c0_gpio0: i2c0_gpio0 { + brcm,pins = <0 1>; + brcm,function = ; + }; + i2c1_gpio2: i2c1_gpio2 { + brcm,pins = <2 3>; + brcm,function = ; + }; + gpclk0_gpio4: gpclk0_gpio4 { + brcm,pins = <4>; + brcm,function = ; + }; + gpclk1_gpio5: gpclk1_gpio5 { + brcm,pins = <5>; + brcm,function = ; + }; + gpclk2_gpio6: gpclk2_gpio6 { + brcm,pins = <6>; + brcm,function = ; + }; + spi0_gpio7: spi0_gpio7 { + brcm,pins = <7 8 9 10 11>; + brcm,function = ; + }; + pwm0_gpio12: pwm0_gpio12 { + brcm,pins = <12>; + brcm,function = ; + }; + pwm1_gpio13: pwm1_gpio13 { + brcm,pins = <13>; + brcm,function = ; + }; + uart0_gpio14: uart0_gpio14 { + brcm,pins = <14 15>; + brcm,function = ; + }; + pcm_gpio18: pcm_gpio18 { + brcm,pins = <18 19 20 21>; + brcm,function = ; + }; + i2c0_gpio32: i2c0_gpio32 { + brcm,pins = <32 34>; + brcm,function = ; + }; + spio0_gpio35: spio0_gpio35 { + brcm,pins = <35 36 37 38 39>; + brcm,function = ; + }; + pwm0_gpio40: pwm0_gpio40 { + brcm,pins = <40>; + brcm,function = ; + }; + pwm1_gpio41: pwm1_gpio41 { + brcm,pins = <41>; + brcm,function = ; + }; + gpclk1_gpio42: gpclk1_gpio42 { + brcm,pins = <42>; + brcm,function = ; + }; + gpclk2_gpio43: gpclk2_gpio43 { + brcm,pins = <43>; + brcm,function = ; + }; + gpclk1_gpio44: gpclk1_gpio44 { + brcm,pins = <44>; + brcm,function = ; + }; + pwm1_gpio45: pwm1_gpio45 { + brcm,pins = <45>; + brcm,function = ; + }; + i2c0_gpio44: i2c0_gpio44 { + brcm,pins = <44 45>; + brcm,function = ; + }; + pcm_gpio28: pcm_gpio28 { + brcm,pins = <28 29 30 31>; + brcm,function = ; + }; +
[PATCH 4/5] ARM: bcm2835: Add a group for mapping pins 48-53 to sdhost.
This pin group definition comes from downstream. We don't have a driver for sdhost integrated yet, but they've been experimenting with it and it sounds useful to bring over. Signed-off-by: Eric Anholt --- arch/arm/boot/dts/bcm283x.dtsi | 4 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi index 70a6814..0bb32cc 100644 --- a/arch/arm/boot/dts/bcm283x.dtsi +++ b/arch/arm/boot/dts/bcm283x.dtsi @@ -191,6 +191,10 @@ brcm,pins = <45>; brcm,function = ; }; + sdhost_gpio48: sdhost_gpio48 { + brcm,pins = <48 49 50 51 52 53>; + brcm,function = ; + }; i2c0_gpio44: i2c0_gpio44 { brcm,pins = <44 45>; brcm,function = ; -- 2.7.0
Re: [PATCH 1/5] ARM: bcm2835: Define standard pinctrl groups in the gpio node.
Eric Anholt writes: > The BCM2835-ARM-Peripherals.pdf documentation specifies what the > function selects do for the pins, and there are a bunch of obvious > groupings to be made. With these created, we'll be able to replace > bcm2835-rpi.dtsi's main "set all of these pins to alt0" with > references to specific groups we want enabled. Sigh. The host I've been using for relaying SMTP apparently decided this week that it doesn't like half my mail. I'll be off fixing this, so for now if anyone wants to look at the series it's just in my repo: https://github.com/anholt/linux/tree/bcm2835-dt-gpio signature.asc Description: PGP signature
Re: [PATCH 2/3 v8] mailbox: Enable BCM2835 mailbox support
Noralf Trønnes writes: > Den 05.05.2015 22:27, skrev Eric Anholt: >> From: Lubomir Rintel >> >> This mailbox driver provides a single mailbox channel to write 32-bit >> values to the VPU and get a 32-bit response. The Raspberry Pi >> firmware uses this mailbox channel to implement firmware calls, while >> Roku 2 (despite being derived from the same firmware tree) doesn't. >> >> The driver was originally submitted by Lubomir, based on the >> out-of-tree 2708 mailbox driver. Eric Anholt fixed it up for >> upstreaming, with the major functional change being that it now has no >> notion of multiple channels (since that is a firmware-dependent >> concept) and instead the raspberrypi-firmware driver will do that >> bit-twiddling in its own messages. > ... >> +static struct platform_driver bcm2835_mbox_driver = { >> +.driver = { >> +.name = "bcm2835-mbox", >> +.owner = THIS_MODULE, >> +.of_match_table = bcm2835_mbox_of_match, >> +}, >> +.probe = bcm2835_mbox_probe, >> +.remove = bcm2835_mbox_remove, >> +}; >> +module_platform_driver(bcm2835_mbox_driver); > > I have tested this driver and the firmware driver booting directly > from the VideoCore bootloader (no uboot). > The mailbox driver loads too late to turn on USB power: Yeah, I have a patch on my branches that returns -EPROBE_DEFER when trying to get a power domain and not finding the provider. It was rejected by the maintainers in favor of a proposed solution whose description I didn't quite follow. > This silences the warning: > struct raspberrypi_power_domain raspberrypi_power_domain_usb = { > .base = { > .power_on_latency_ns = 6, Oh, nice. Thanks! signature.asc Description: PGP signature
Re: Re: [PATCH 2/3 v8] mailbox: Enable BCM2835 mailbox support
Alexander Stein writes: > On Thursday 07 May 2015, 12:54:20 wrote Eric Anholt: >> Noralf Trønnes writes: >> >> > Den 05.05.2015 22:27, skrev Eric Anholt: >> >> From: Lubomir Rintel >> >> >> >> This mailbox driver provides a single mailbox channel to write 32-bit >> >> values to the VPU and get a 32-bit response. The Raspberry Pi >> >> firmware uses this mailbox channel to implement firmware calls, while >> >> Roku 2 (despite being derived from the same firmware tree) doesn't. >> >> >> >> The driver was originally submitted by Lubomir, based on the >> >> out-of-tree 2708 mailbox driver. Eric Anholt fixed it up for >> >> upstreaming, with the major functional change being that it now has no >> >> notion of multiple channels (since that is a firmware-dependent >> >> concept) and instead the raspberrypi-firmware driver will do that >> >> bit-twiddling in its own messages. >> > ... >> >> +static struct platform_driver bcm2835_mbox_driver = { >> >> + .driver = { >> >> + .name = "bcm2835-mbox", >> >> + .owner = THIS_MODULE, >> >> + .of_match_table = bcm2835_mbox_of_match, >> >> + }, >> >> + .probe = bcm2835_mbox_probe, >> >> + .remove = bcm2835_mbox_remove, >> >> +}; >> >> +module_platform_driver(bcm2835_mbox_driver); >> > >> > I have tested this driver and the firmware driver booting directly >> > from the VideoCore bootloader (no uboot). >> > The mailbox driver loads too late to turn on USB power: >> >> Yeah, I have a patch on my branches that returns -EPROBE_DEFER when >> trying to get a power domain and not finding the provider. It was >> rejected by the maintainers in favor of a proposed solution whose >> description I didn't quite follow. > > Do you have a link for this thread? https://lkml.org/lkml/2015/3/11/483 signature.asc Description: PGP signature
[PATCH] ARM: bcm2835: Use 0x4 prefix for DMA bus addresses to SDRAM.
There exists a tiny MMU, configurable only by the VC (running the closed firmware), which maps from the ARM's physical addresses to bus addresses. These bus addresses determine the caching behavior in the VC's L1/L2 (note: separate from the ARM's L1/L2) according to the top 2 bits. The bits in the bus address mean: >From the VideoCore processor: 0x0... L1 and L2 cache allocating and coherent 0x4... L1 non-allocating, but coherent. L2 allocating and coherent 0x8... L1 non-allocating, but coherent. L2 non-allocating, but coherent 0xc... SDRAM alias. Cache is bypassed. Not L1 or L2 allocating or coherent >From the GPU peripherals (note: all peripherals bypass the L1 cache. The ARM will see this view once through the VC MMU): 0x0... Do not use 0x4... L1 non-allocating, and incoherent. L2 allocating and coherent. 0x8... L1 non-allocating, and incoherent. L2 non-allocating, but coherent 0xc... SDRAM alias. Cache is bypassed. Not L1 or L2 allocating or coherent The 2835 firmware always configures the MMU to turn ARM physical addresses with 0x0 top bits to 0x4, meaning present in L2 but incoherent with L1. However, any bus addresses we were generating in the kernel to be passed to a device had 0x0 bits. That would be a reserved (possibly totally incoherent) value if sent to a GPU peripheral like USB, or L1 allocating if sent to the VC (like a firmware property request). By setting dma-ranges, all of the devices below it get a dev->dma_pfn_offset, so that dma_alloc_coherent() and friends return addresses with 0x4 bits and avoid cache incoherency. This matches the behavior in the downstream 2708 kernel (see BUS_OFFSET in arch/arm/mach-bcm2708/include/mach/memory.h). Signed-off-by: Eric Anholt Cc: popcorn...@gmail.com --- arch/arm/boot/dts/bcm2835.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi index 5734650..2df1b5c 100644 --- a/arch/arm/boot/dts/bcm2835.dtsi +++ b/arch/arm/boot/dts/bcm2835.dtsi @@ -15,6 +15,7 @@ #address-cells = <1>; #size-cells = <1>; ranges = <0x7e00 0x2000 0x0200>; + dma-ranges = <0x4000 0x 0x1f00>; timer@7e003000 { compatible = "brcm,bcm2835-system-timer"; -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] ARM: bcm2835: Use 0x4 prefix for DMA bus addresses to SDRAM.
Noralf Trønnes writes: > Den 04.05.2015 21:33, skrev Eric Anholt: >> There exists a tiny MMU, configurable only by the VC (running the >> closed firmware), which maps from the ARM's physical addresses to bus >> addresses. These bus addresses determine the caching behavior in the >> VC's L1/L2 (note: separate from the ARM's L1/L2) according to the top >> 2 bits. The bits in the bus address mean: >> >> From the VideoCore processor: >> 0x0... L1 and L2 cache allocating and coherent >> 0x4... L1 non-allocating, but coherent. L2 allocating and coherent >> 0x8... L1 non-allocating, but coherent. L2 non-allocating, but coherent >> 0xc... SDRAM alias. Cache is bypassed. Not L1 or L2 allocating or coherent >> >> From the GPU peripherals (note: all peripherals bypass the L1 >> cache. The ARM will see this view once through the VC MMU): >> 0x0... Do not use >> 0x4... L1 non-allocating, and incoherent. L2 allocating and coherent. >> 0x8... L1 non-allocating, and incoherent. L2 non-allocating, but coherent >> 0xc... SDRAM alias. Cache is bypassed. Not L1 or L2 allocating or coherent >> >> The 2835 firmware always configures the MMU to turn ARM physical >> addresses with 0x0 top bits to 0x4, meaning present in L2 but >> incoherent with L1. However, any bus addresses we were generating in >> the kernel to be passed to a device had 0x0 bits. That would be a >> reserved (possibly totally incoherent) value if sent to a GPU >> peripheral like USB, or L1 allocating if sent to the VC (like a >> firmware property request). By setting dma-ranges, all of the devices >> below it get a dev->dma_pfn_offset, so that dma_alloc_coherent() and >> friends return addresses with 0x4 bits and avoid cache incoherency. >> >> This matches the behavior in the downstream 2708 kernel (see >> BUS_OFFSET in arch/arm/mach-bcm2708/include/mach/memory.h). >> >> Signed-off-by: Eric Anholt >> Cc: popcorn...@gmail.com >> --- >> arch/arm/boot/dts/bcm2835.dtsi | 1 + >> 1 file changed, 1 insertion(+) >> >> diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi >> index 5734650..2df1b5c 100644 >> --- a/arch/arm/boot/dts/bcm2835.dtsi >> +++ b/arch/arm/boot/dts/bcm2835.dtsi >> @@ -15,6 +15,7 @@ >> #address-cells = <1>; >> #size-cells = <1>; >> ranges = <0x7e00 0x2000 0x0200>; >> +dma-ranges = <0x4000 0x 0x1f00>; >> >> timer@7e003000 { >> compatible = "brcm,bcm2835-system-timer"; > > This was quite a coincidence. I discovered the need for 'dma-ranges' > yesterday while trying to get the downstream bcm2708_fb driver to > work with ARCH_BCM2835. The driver is using the mailbox to get info > about the framebuffer from the firmware. When it failed I discovered > that the bus address was wrong. > > What I don't understand, is that mmc and spi works fine with a "wrong" > bus address. It's only the framebuffer driver and the vchiq driver > when using mailbox that fails. > > Tested-by: Noralf Trønnes Yeah, it was the mailbox driver I've been trying to merge, on pi2, that made me get this patch together. I'm suspicious that 0x0 works the same as 0x4 for GPU peripherals (mmc, spi, vc4) on pi1, though I've had occasional instability (something like 3 events per ~5000 tests) that I sure hope is due to this. signature.asc Description: PGP signature
Re: [PATCH] ARM: bcm2835: Use 0x4 prefix for DMA bus addresses to SDRAM.
Stephen Warren writes: > On 05/04/2015 01:33 PM, Eric Anholt wrote: >> There exists a tiny MMU, configurable only by the VC (running the >> closed firmware), which maps from the ARM's physical addresses to bus >> addresses. These bus addresses determine the caching behavior in the >> VC's L1/L2 (note: separate from the ARM's L1/L2) according to the top >> 2 bits. The bits in the bus address mean: >> >> From the VideoCore processor: >> 0x0... L1 and L2 cache allocating and coherent >> 0x4... L1 non-allocating, but coherent. L2 allocating and coherent >> 0x8... L1 non-allocating, but coherent. L2 non-allocating, but coherent >> 0xc... SDRAM alias. Cache is bypassed. Not L1 or L2 allocating or coherent >> >> From the GPU peripherals (note: all peripherals bypass the L1 >> cache. The ARM will see this view once through the VC MMU): >> 0x0... Do not use >> 0x4... L1 non-allocating, and incoherent. L2 allocating and coherent. >> 0x8... L1 non-allocating, and incoherent. L2 non-allocating, but coherent >> 0xc... SDRAM alias. Cache is bypassed. Not L1 or L2 allocating or coherent >> >> The 2835 firmware always configures the MMU to turn ARM physical >> addresses with 0x0 top bits to 0x4, meaning present in L2 but >> incoherent with L1. However, any bus addresses we were generating in >> the kernel to be passed to a device had 0x0 bits. That would be a >> reserved (possibly totally incoherent) value if sent to a GPU >> peripheral like USB, or L1 allocating if sent to the VC (like a >> firmware property request). By setting dma-ranges, all of the devices >> below it get a dev->dma_pfn_offset, so that dma_alloc_coherent() and >> friends return addresses with 0x4 bits and avoid cache incoherency. >> >> This matches the behavior in the downstream 2708 kernel (see >> BUS_OFFSET in arch/arm/mach-bcm2708/include/mach/memory.h). > >> diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi > >> #address-cells = <1>; >> #size-cells = <1>; >> ranges = <0x7e00 0x2000 0x0200>; >> +dma-ranges = <0x4000 0x 0x1f00>; > > Oh well that's a nice and simple patch; I had been avoiding looking into > fixing the kernel for this since I was worried it'd be rather complex! > > I'm puzzled why the length cell of ranges and dma-ranges differs though? > Assuming there's a good explanation for that, Nope, you're right, it should be 0x2000. '0x1f' came from going back from the '0x3f' on the pi2, but pi2 just has a chunk lost to the bus mapping. signature.asc Description: PGP signature
[PATCH v2] ARM: bcm2835: Use 0x4 prefix for DMA bus addresses to SDRAM.
There exists a tiny MMU, configurable only by the VC (running the closed firmware), which maps from the ARM's physical addresses to bus addresses. These bus addresses determine the caching behavior in the VC's L1/L2 (note: separate from the ARM's L1/L2) according to the top 2 bits. The bits in the bus address mean: >From the VideoCore processor: 0x0... L1 and L2 cache allocating and coherent 0x4... L1 non-allocating, but coherent. L2 allocating and coherent 0x8... L1 non-allocating, but coherent. L2 non-allocating, but coherent 0xc... SDRAM alias. Cache is bypassed. Not L1 or L2 allocating or coherent >From the GPU peripherals (note: all peripherals bypass the L1 cache. The ARM will see this view once through the VC MMU): 0x0... Do not use 0x4... L1 non-allocating, and incoherent. L2 allocating and coherent. 0x8... L1 non-allocating, and incoherent. L2 non-allocating, but coherent 0xc... SDRAM alias. Cache is bypassed. Not L1 or L2 allocating or coherent The 2835 firmware always configures the MMU to turn ARM physical addresses with 0x0 top bits to 0x4, meaning present in L2 but incoherent with L1. However, any bus addresses we were generating in the kernel to be passed to a device had 0x0 bits. That would be a reserved (possibly totally incoherent) value if sent to a GPU peripheral like USB, or L1 allocating if sent to the VC (like a firmware property request). By setting dma-ranges, all of the devices below it get a dev->dma_pfn_offset, so that dma_alloc_coherent() and friends return addresses with 0x4 bits and avoid cache incoherency. This matches the behavior in the downstream 2708 kernel (see BUS_OFFSET in arch/arm/mach-bcm2708/include/mach/memory.h). Signed-off-by: Eric Anholt Tested-by: Noralf Trønnes Acked-by: Stephen Warren Cc: popcorn...@gmail.com --- v2: Fix length of the range from 0x1f00 to 0x2000, fixing the translation for the last 16MB. arch/arm/boot/dts/bcm2835.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi index eb33a8c..3c899b3 100644 --- a/arch/arm/boot/dts/bcm2835.dtsi +++ b/arch/arm/boot/dts/bcm2835.dtsi @@ -15,6 +15,7 @@ #address-cells = <1>; #size-cells = <1>; ranges = <0x7e00 0x2000 0x0200>; + dma-ranges = <0x4000 0x 0x2000>; timer@7e003000 { compatible = "brcm,bcm2835-system-timer"; -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/