From cce0a62ba4087e70af8316b9ba78329352228e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Tue, 19 May 2015 13:31:50 +0200 Subject: [PATCH 1/3] BCM270x: Add vchiq device to platform file and Device Tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prepare to turn the vchiq module into a driver. Signed-off-by: Noralf Trønnes --- arch/arm/boot/dts/bcm2708_common.dtsi | 6 +++++ arch/arm/mach-bcm2708/bcm2708.c | 26 +++++++++++++++++++ arch/arm/mach-bcm2708/include/mach/platform.h | 1 + arch/arm/mach-bcm2709/bcm2709.c | 26 +++++++++++++++++++ arch/arm/mach-bcm2709/include/mach/platform.h | 1 + 5 files changed, 60 insertions(+) diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi index c5ed34bda2375..2d9bcd8ac97dc 100644 --- a/arch/arm/boot/dts/bcm2708_common.dtsi +++ b/arch/arm/boot/dts/bcm2708_common.dtsi @@ -114,6 +114,12 @@ compatible = "brcm,bcm2708-fb"; status = "disabled"; }; + + vchiq: vchiq { + compatible = "brcm,bcm2835-vchiq"; + reg = <0x7e00b840 0xf>; + interrupts = <0 2>; + }; }; clocks { diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c index cde2124566fe0..81cc9885de43b 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -437,6 +437,31 @@ static struct platform_device bcm2708_vcio_device = { }, }; +static struct resource bcm2708_vchiq_resources[] = { + { + .start = ARMCTRL_0_BELL_BASE, + .end = ARMCTRL_0_BELL_BASE + 16, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_ARM_DOORBELL_0, + .end = IRQ_ARM_DOORBELL_0, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 vchiq_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_vchiq_device = { + .name = "bcm2835_vchiq", + .id = -1, + .resource = bcm2708_vchiq_resources, + .num_resources = ARRAY_SIZE(bcm2708_vchiq_resources), + .dev = { + .dma_mask = &vchiq_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), + }, +}; + #ifdef CONFIG_BCM2708_GPIO #define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" @@ -909,6 +934,7 @@ void __init bcm2708_init(void) bcm_register_device_dt(&bcm2708_dmaengine_device); bcm_register_device_dt(&bcm2708_vcio_device); + bcm_register_device_dt(&bcm2708_vchiq_device); #ifdef CONFIG_BCM2708_GPIO bcm_register_device_dt(&bcm2708_gpio_device); #endif diff --git a/arch/arm/mach-bcm2708/include/mach/platform.h b/arch/arm/mach-bcm2708/include/mach/platform.h index bef3e5a62f117..69674e92fec51 100644 --- a/arch/arm/mach-bcm2708/include/mach/platform.h +++ b/arch/arm/mach-bcm2708/include/mach/platform.h @@ -81,6 +81,7 @@ #define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ #define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ +#define ARMCTRL_0_BELL_BASE (ARMCTRL_0_SBM_BASE + 0x40) /* User 0 (ARM)'s Doorbell */ #define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c index 95db41ff2601f..528bf6e18e5de 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -456,6 +456,31 @@ static struct platform_device bcm2708_vcio_device = { }, }; +static struct resource bcm2708_vchiq_resources[] = { + { + .start = ARMCTRL_0_BELL_BASE, + .end = ARMCTRL_0_BELL_BASE + 16, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_ARM_DOORBELL_0, + .end = IRQ_ARM_DOORBELL_0, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 vchiq_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_vchiq_device = { + .name = "bcm2835_vchiq", + .id = -1, + .resource = bcm2708_vchiq_resources, + .num_resources = ARRAY_SIZE(bcm2708_vchiq_resources), + .dev = { + .dma_mask = &vchiq_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), + }, +}; + #ifdef CONFIG_BCM2708_GPIO #define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" @@ -930,6 +955,7 @@ void __init bcm2709_init(void) bcm_register_device_dt(&bcm2708_dmaengine_device); bcm_register_device_dt(&bcm2708_vcio_device); + bcm_register_device_dt(&bcm2708_vchiq_device); #ifdef CONFIG_BCM2708_GPIO bcm_register_device_dt(&bcm2708_gpio_device); #endif diff --git a/arch/arm/mach-bcm2709/include/mach/platform.h b/arch/arm/mach-bcm2709/include/mach/platform.h index 5574bb5356ca0..be9973354c20f 100644 --- a/arch/arm/mach-bcm2709/include/mach/platform.h +++ b/arch/arm/mach-bcm2709/include/mach/platform.h @@ -81,6 +81,7 @@ #define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ #define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ +#define ARMCTRL_0_BELL_BASE (ARMCTRL_0_SBM_BASE + 0x40) /* User 0 (ARM)'s Doorbell */ #define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ From 6ca53d1e1366d7c2517697c6e14c984a55887354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Tue, 19 May 2015 13:32:34 +0200 Subject: [PATCH 2/3] bcm2708: vchiq: Add Device Tree support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turn vchiq into a driver and stop hardcoding resources. Use devm_* functions in probe path to simplify cleanup. A global variable is used to hold the register address. This is done to keep this patch as small as possible. Also make available on ARCH_BCM2835. Based on work by Lubomir Rintel. Signed-off-by: Noralf Trønnes --- drivers/misc/vc04_services/Kconfig | 2 +- .../interface/vchiq_arm/vchiq_2835_arm.c | 124 ++++++++---------- .../interface/vchiq_arm/vchiq_arm.c | 44 ++++--- .../interface/vchiq_arm/vchiq_arm.h | 7 +- 4 files changed, 79 insertions(+), 98 deletions(-) diff --git a/drivers/misc/vc04_services/Kconfig b/drivers/misc/vc04_services/Kconfig index b94e6cdcc833c..b4198c29b1ab3 100644 --- a/drivers/misc/vc04_services/Kconfig +++ b/drivers/misc/vc04_services/Kconfig @@ -1,6 +1,6 @@ config BCM2708_VCHIQ tristate "Videocore VCHIQ" - depends on MACH_BCM2708 || MACH_BCM2709 + depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 default y help Kernel to VideoCore communication interface for the diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c index 70e5086292e7b..660aad2c0ef2b 100644 --- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c @@ -35,22 +35,17 @@ #include #include #include -#include #include #include #include #include #include +#include #include #include -#include - -#include - #define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32) -#define VCHIQ_DOORBELL_IRQ IRQ_ARM_DOORBELL_0 #define VCHIQ_ARM_ADDRESS(x) ((void *)__virt_to_bus((unsigned)x)) #include "vchiq_arm.h" @@ -60,14 +55,15 @@ #define MAX_FRAGMENTS (VCHIQ_NUM_CURRENT_BULKS * 2) +#define BELL0 0x00 +#define BELL2 0x08 + typedef struct vchiq_2835_state_struct { int inited; VCHIQ_ARM_STATE_T arm_state; } VCHIQ_2835_ARM_STATE_T; -static char *g_slot_mem; -static int g_slot_mem_size; -dma_addr_t g_slot_phys; +static void __iomem *g_regs; static FRAGMENTS_T *g_fragments_base; static FRAGMENTS_T *g_free_fragments; struct semaphore g_free_fragments_sema; @@ -86,43 +82,40 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, static void free_pagelist(PAGELIST_T *pagelist, int actual); -int __init -vchiq_platform_init(VCHIQ_STATE_T *state) +int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) { + struct device *dev = &pdev->dev; VCHIQ_SLOT_ZERO_T *vchiq_slot_zero; - int frag_mem_size; - int err; - int i; + struct resource *res; + void *slot_mem; + dma_addr_t slot_phys; + int slot_mem_size, frag_mem_size; + int err, irq, i; /* Allocate space for the channels in coherent memory */ - g_slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE); + slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE); frag_mem_size = PAGE_ALIGN(sizeof(FRAGMENTS_T) * MAX_FRAGMENTS); - g_slot_mem = dma_alloc_coherent(NULL, g_slot_mem_size + frag_mem_size, - &g_slot_phys, GFP_KERNEL); - - if (!g_slot_mem) { - vchiq_log_error(vchiq_arm_log_level, - "Unable to allocate channel memory"); - err = -ENOMEM; - goto failed_alloc; + slot_mem = dmam_alloc_coherent(dev, slot_mem_size + frag_mem_size, + &slot_phys, GFP_KERNEL); + if (!slot_mem) { + dev_err(dev, "could not allocate DMA memory\n"); + return -ENOMEM; } - WARN_ON(((int)g_slot_mem & (PAGE_SIZE - 1)) != 0); + WARN_ON(((int)slot_mem & (PAGE_SIZE - 1)) != 0); - vchiq_slot_zero = vchiq_init_slots(g_slot_mem, g_slot_mem_size); - if (!vchiq_slot_zero) { - err = -EINVAL; - goto failed_init_slots; - } + vchiq_slot_zero = vchiq_init_slots(slot_mem, slot_mem_size); + if (!vchiq_slot_zero) + return -EINVAL; vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] = - (int)g_slot_phys + g_slot_mem_size; + (int)slot_phys + slot_mem_size; vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] = MAX_FRAGMENTS; - g_fragments_base = (FRAGMENTS_T *)(g_slot_mem + g_slot_mem_size); - g_slot_mem_size += frag_mem_size; + g_fragments_base = (FRAGMENTS_T *)(slot_mem + slot_mem_size); + slot_mem_size += frag_mem_size; g_free_fragments = g_fragments_base; for (i = 0; i < (MAX_FRAGMENTS - 1); i++) { @@ -132,54 +125,46 @@ vchiq_platform_init(VCHIQ_STATE_T *state) *(FRAGMENTS_T **)&g_fragments_base[i] = NULL; sema_init(&g_free_fragments_sema, MAX_FRAGMENTS); - if (vchiq_init_state(state, vchiq_slot_zero, 0/*slave*/) != - VCHIQ_SUCCESS) { - err = -EINVAL; - goto failed_vchiq_init; + if (vchiq_init_state(state, vchiq_slot_zero, 0) != VCHIQ_SUCCESS) + return -EINVAL; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + g_regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(g_regs)) + return PTR_ERR(g_regs); + + irq = platform_get_irq(pdev, 0); + if (irq <= 0) { + dev_err(dev, "failed to get IRQ\n"); + return irq; } - err = request_irq(VCHIQ_DOORBELL_IRQ, vchiq_doorbell_irq, - IRQF_IRQPOLL, "VCHIQ doorbell", - state); - if (err < 0) { - vchiq_log_error(vchiq_arm_log_level, "%s: failed to register " - "irq=%d err=%d", __func__, - VCHIQ_DOORBELL_IRQ, err); - goto failed_request_irq; + err = devm_request_irq(dev, irq, vchiq_doorbell_irq, IRQF_IRQPOLL, + "VCHIQ doorbell", state); + if (err) { + dev_err(dev, "failed to register irq=%d\n", irq); + return err; } /* Send the base address of the slots to VideoCore */ dsb(); /* Ensure all writes have completed */ - bcm_mailbox_write(MBOX_CHAN_VCHIQ, (unsigned int)g_slot_phys); + err = bcm_mailbox_write(MBOX_CHAN_VCHIQ, (unsigned int)slot_phys); + if (err) { + dev_err(dev, "mailbox write failed\n"); + return err; + } vchiq_log_info(vchiq_arm_log_level, - "vchiq_init - done (slots %x, phys %x)", - (unsigned int)vchiq_slot_zero, g_slot_phys); + "vchiq_init - done (slots %x, phys %pad)", + (unsigned int)vchiq_slot_zero, &slot_phys); - vchiq_call_connected_callbacks(); + vchiq_call_connected_callbacks(); return 0; - -failed_request_irq: -failed_vchiq_init: -failed_init_slots: - dma_free_coherent(NULL, g_slot_mem_size, g_slot_mem, g_slot_phys); - -failed_alloc: - return err; -} - -void __exit -vchiq_platform_exit(VCHIQ_STATE_T *state) -{ - free_irq(VCHIQ_DOORBELL_IRQ, state); - dma_free_coherent(NULL, g_slot_mem_size, - g_slot_mem, g_slot_phys); } - VCHIQ_STATUS_T vchiq_platform_init_state(VCHIQ_STATE_T *state) { @@ -213,11 +198,8 @@ remote_event_signal(REMOTE_EVENT_T *event) dsb(); /* data barrier operation */ - if (event->armed) { - /* trigger vc interrupt */ - - writel(0, __io_address(ARM_0_BELL2)); - } + if (event->armed) + writel(0, g_regs + BELL2); /* trigger vc interrupt */ } int @@ -341,7 +323,7 @@ vchiq_doorbell_irq(int irq, void *dev_id) unsigned int status; /* Read (and clear) the doorbell */ - status = readl(__io_address(ARM_0_BELL0)); + status = readl(g_regs + BELL0); if (status & 0x4) { /* Was the doorbell rung? */ remote_event_pollall(state); diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c index 0ad9656dbc5e8..31e2cba622432 100644 --- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -45,6 +45,7 @@ #include #include #include +#include #include "vchiq_core.h" #include "vchiq_ioctl.h" @@ -2790,15 +2791,7 @@ void vchiq_platform_conn_state_changed(VCHIQ_STATE_T *state, } } - -/**************************************************************************** -* -* vchiq_init - called when the module is loaded. -* -***************************************************************************/ - -static int __init -vchiq_init(void) +static int vchiq_probe(struct platform_device *pdev) { int err; void *ptr_err; @@ -2835,7 +2828,7 @@ vchiq_init(void) if (IS_ERR(ptr_err)) goto failed_device_create; - err = vchiq_platform_init(&g_state); + err = vchiq_platform_init(pdev, &g_state); if (err != 0) goto failed_platform_init; @@ -2862,23 +2855,32 @@ vchiq_init(void) return err; } -/**************************************************************************** -* -* vchiq_exit - called when the module is unloaded. -* -***************************************************************************/ - -static void __exit -vchiq_exit(void) +static int vchiq_remove(struct platform_device *pdev) { - vchiq_platform_exit(&g_state); device_destroy(vchiq_class, vchiq_devid); class_destroy(vchiq_class); cdev_del(&vchiq_cdev); unregister_chrdev_region(vchiq_devid, 1); + + return 0; } -module_init(vchiq_init); -module_exit(vchiq_exit); +static const struct of_device_id vchiq_of_match[] = { + { .compatible = "brcm,bcm2835-vchiq", }, + {}, +}; +MODULE_DEVICE_TABLE(of, vchiq_of_match); + +static struct platform_driver vchiq_driver = { + .driver = { + .name = "bcm2835_vchiq", + .owner = THIS_MODULE, + .of_match_table = vchiq_of_match, + }, + .probe = vchiq_probe, + .remove = vchiq_remove, +}; +module_platform_driver(vchiq_driver); + MODULE_LICENSE("GPL"); MODULE_AUTHOR("Broadcom Corporation"); diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h index d1e27413dbe84..9740e1afbc9dc 100644 --- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h +++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h @@ -36,6 +36,7 @@ #define VCHIQ_ARM_H #include +#include #include #include #include "vchiq_core.h" @@ -128,11 +129,7 @@ typedef struct vchiq_arm_state_struct { extern int vchiq_arm_log_level; extern int vchiq_susp_log_level; -extern int __init -vchiq_platform_init(VCHIQ_STATE_T *state); - -extern void __exit -vchiq_platform_exit(VCHIQ_STATE_T *state); +int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state); extern VCHIQ_STATE_T * vchiq_get_state(void); From 346c1e2b276eb71e982b79254e8ce81440a543a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Tue, 19 May 2015 13:32:50 +0200 Subject: [PATCH 3/3] bcm2835: Add bcm2835-vchiq to Device Tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add vchiq to Device Tree. There are no kernel users yet, but it's available to userspace (vcgencmd). Signed-off-by: Noralf Trønnes --- arch/arm/boot/dts/bcm2835.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi index f3ab9b3839722..72d03545a6575 100644 --- a/arch/arm/boot/dts/bcm2835.dtsi +++ b/arch/arm/boot/dts/bcm2835.dtsi @@ -164,6 +164,12 @@ compatible = "brcm,bcm2708-fb"; status = "disabled"; }; + + vchiq: vchiq { + compatible = "brcm,bcm2835-vchiq"; + reg = <0x7e00b840 0xf>; + interrupts = <0 2>; + }; }; clocks {