summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Elwell <pelwell@users.noreply.github.com>2015-05-19 14:18:12 +0100
committerPhil Elwell <pelwell@users.noreply.github.com>2015-05-19 14:18:12 +0100
commite72ad4baf37e44f32adda600b20f443c56130bcf (patch)
tree75470de2099486137a716501006ce310a17c32e8
parent1dd8cb48a6157ef50a0ae385fc4b10fd5c5bb93f (diff)
parent346c1e2b276eb71e982b79254e8ce81440a543a1 (diff)
downloadlinux-e72ad4baf37e44f32adda600b20f443c56130bcf.tar.gz
Merge pull request #973 from notro/vchiq
Enable vchiq on ARCH_BCM2835
-rw-r--r--arch/arm/boot/dts/bcm2708_common.dtsi6
-rw-r--r--arch/arm/boot/dts/bcm2835.dtsi6
-rw-r--r--arch/arm/mach-bcm2708/bcm2708.c26
-rw-r--r--arch/arm/mach-bcm2708/include/mach/platform.h1
-rw-r--r--arch/arm/mach-bcm2709/bcm2709.c26
-rw-r--r--arch/arm/mach-bcm2709/include/mach/platform.h1
-rw-r--r--drivers/misc/vc04_services/Kconfig2
-rw-r--r--drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c124
-rw-r--r--drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c44
-rw-r--r--drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h7
10 files changed, 145 insertions, 98 deletions
diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi
index c5ed34bda237..2d9bcd8ac97d 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/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi
index f3ab9b383972..72d03545a657 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 {
diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c
index cde2124566fe..81cc9885de43 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 bef3e5a62f11..69674e92fec5 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 95db41ff2601..528bf6e18e5d 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 5574bb5356ca..be9973354c20 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 */
diff --git a/drivers/misc/vc04_services/Kconfig b/drivers/misc/vc04_services/Kconfig
index b94e6cdcc833..b4198c29b1ab 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 70e5086292e7..660aad2c0ef2 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 <linux/types.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
-#include <linux/irq.h>
#include <linux/pagemap.h>
#include <linux/dma-mapping.h>
#include <linux/version.h>
#include <linux/io.h>
#include <linux/platform_data/mailbox-bcm2708.h>
+#include <linux/platform_device.h>
#include <linux/uaccess.h>
#include <asm/pgtable.h>
-#include <mach/irqs.h>
-
-#include <mach/platform.h>
-
#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 0ad9656dbc5e..31e2cba62243 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 <linux/bug.h>
#include <linux/semaphore.h>
#include <linux/list.h>
+#include <linux/platform_device.h>
#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 @@ failed_debugfs_init:
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 d1e27413dbe8..9740e1afbc9d 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 <linux/mutex.h>
+#include <linux/platform_device.h>
#include <linux/semaphore.h>
#include <linux/atomic.h>
#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);