extern int bcm_mailbox_property(void *data, int size) { uint32_t success; dma_addr_t mem_bus; /* the memory address accessed from videocore */ void *mem_kern; /* the memory address accessed from driver */ int s = 0; /* allocate some memory for the messages communicating with GPU */ mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, GFP_ATOMIC); if (mem_kern) { /* create the message */ memcpy(mem_kern, data, size); /* send the message */ wmb(); s = bcm_mailbox_write(MBOX_CHAN_PROPERTY, (uint32_t)mem_bus); if (s == 0) { s = bcm_mailbox_read(MBOX_CHAN_PROPERTY, &success); } if (s == 0) { /* copy the response */ rmb(); memcpy(data, mem_kern, size); } dma_free_coherent(NULL, PAGE_ALIGN(size), mem_kern, mem_bus); } else { s = -ENOMEM; } if (s != 0) printk(KERN_ERR DRIVER_NAME ": %s failed (%d)\n", __func__, s); return s; }
int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request) { int rc = 0; DPRINTK("bcm_power_request(%d, %x)\n", handle, request); if ((handle < BCM_POWER_MAXCLIENTS) && (g_state.client_request[handle] != BCM_POWER_NOCLIENT)) { if (down_interruptible(&g_state.mutex) != 0) { DPRINTK("bcm_power_request -> interrupted\n"); return -EINTR; } if (request != g_state.client_request[handle]) { uint32_t others_request = 0; uint32_t global_request; BCM_POWER_HANDLE_T i; for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { if (i != handle) others_request |= g_state.client_request[i]; } others_request &= ~BCM_POWER_NOCLIENT; global_request = request | others_request; if (global_request != g_state.global_request) { uint32_t actual; /* Send a request to VideoCore */ bcm_mailbox_write(MBOX_CHAN_POWER, global_request << 4); /* Wait for a response during power-up */ if (global_request & ~g_state.global_request) { rc = bcm_mailbox_read(MBOX_CHAN_POWER, &actual); DPRINTK ("bcm_mailbox_read -> %08x, %d\n", actual, rc); actual >>= 4; } else {
int __init vchiq_platform_init(VCHIQ_STATE_T *state) { VCHIQ_SLOT_ZERO_T *vchiq_slot_zero; int frag_mem_size; int err; int i; /* Allocate space for the channels in coherent memory */ g_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_ATOMIC); if (!g_slot_mem) { vchiq_log_error(vchiq_arm_log_level, "Unable to allocate channel memory"); err = -ENOMEM; goto failed_alloc; } WARN_ON(((int)g_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->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] = (int)g_slot_phys + g_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_free_fragments = g_fragments_base; for (i = 0; i < (MAX_FRAGMENTS - 1); i++) { *(FRAGMENTS_T **)&g_fragments_base[i] = &g_fragments_base[i + 1]; } *(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; } 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; } /* 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); vchiq_log_info(vchiq_arm_log_level, "vchiq_init - done (slots %x, phys %x)", (unsigned int)vchiq_slot_zero, g_slot_phys); 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; }
int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) { struct device *dev = &pdev->dev; VCHIQ_SLOT_ZERO_T *vchiq_slot_zero; struct resource *res; void *slot_mem; dma_addr_t slot_phys; int slot_mem_size, frag_mem_size; int err, irq, i; g_virt_to_bus_offset = virt_to_dma(dev, (void *)0); /* Allocate space for the channels in coherent memory */ slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE); frag_mem_size = PAGE_ALIGN(sizeof(FRAGMENTS_T) * MAX_FRAGMENTS); 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)slot_mem & (PAGE_SIZE - 1)) != 0); 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)slot_phys + slot_mem_size; vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] = MAX_FRAGMENTS; 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++) { *(FRAGMENTS_T **)&g_fragments_base[i] = &g_fragments_base[i + 1]; } *(FRAGMENTS_T **)&g_fragments_base[i] = NULL; sema_init(&g_free_fragments_sema, MAX_FRAGMENTS); 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 = 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 */ 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 %pad)", (unsigned int)vchiq_slot_zero, &slot_phys); vchiq_call_connected_callbacks(); return 0; }