/** * remoteproc_resource_init * * Initializes resources for remoteproc remote configuration. Only * remoteproc remote applications are allowed to call this function. * * @param rsc_info - pointer to resource table info control * block * @param channel_created - callback function for channel creation * @param channel_destroyed - callback function for channel deletion * @param default_cb - default callback for channel I/O * @param rproc_handle - pointer to new remoteproc instance * * @param returns - status of function execution * */ int remoteproc_resource_init(struct rsc_table_info *rsc_info, rpmsg_chnl_cb_t channel_created, rpmsg_chnl_cb_t channel_destroyed, rpmsg_rx_cb_t default_cb, struct remote_proc** rproc_handle) { struct remote_proc *rproc; int status; if(!rsc_info) { return RPROC_ERR_PARAM; } /* Initialize environment component */ status = env_init(); if (status != RPROC_SUCCESS) { return status; } rproc = env_allocate_memory(sizeof(struct remote_proc)); if (rproc) { env_memset(rproc, 0x00, sizeof(struct remote_proc)); /* There can be only one master for remote configuration so use the * rsvd cpu id for creating hil proc */ rproc->proc = hil_create_proc(HIL_RSVD_CPU_ID); if (rproc->proc) { /* Parse resource table */ status = handle_rsc_table(rproc, rsc_info->rsc_tab, rsc_info->size); if (status == RPROC_SUCCESS) { /* Initialize RPMSG "messaging" component */ *rproc_handle = rproc; status = rpmsg_init(rproc->proc->cpu_id, &rproc->rdev, channel_created, channel_destroyed, default_cb, RPMSG_MASTER); } else { status = RPROC_ERR_NO_RSC_TABLE; } } else { status = RPROC_ERR_CPU_ID; } } else { status = RPROC_ERR_NO_MEM; } /* Cleanup in case of error */ if (status != RPROC_SUCCESS) { *rproc_handle = 0; (void) remoteproc_resource_deinit(rproc); return status; } return status; }
/** * remoteproc_init * * Initializes resources for remoteproc master configuration. Only * remoteproc master applications are allowed to call this function. * * @param fw_name - name of frimware * @param channel_created - callback function for channel creation * @param channel_destroyed - callback function for channel deletion * @param default_cb - default callback for channel I/O * @param rproc_handle - pointer to new remoteproc instance * * @param returns - status of function execution * */ int remoteproc_init(char *fw_name, rpmsg_chnl_cb_t channel_created, rpmsg_chnl_cb_t channel_destroyed, rpmsg_rx_cb_t default_cb, struct remote_proc** rproc_handle) { struct remote_proc *rproc; struct resource_table *rsc_table; unsigned int fw_addr, fw_size, rsc_size; int status, cpu_id; if (!fw_name) { return RPROC_ERR_PARAM; } /* Initialize environment component */ status = env_init(); if (status != RPROC_SUCCESS) { return status; } rproc = env_allocate_memory(sizeof(struct remote_proc)); if (rproc) { env_memset((void *) rproc, 0x00, sizeof(struct remote_proc)); /* Get CPU ID for the given firmware name */ cpu_id = hil_get_cpuforfw(fw_name); if (cpu_id >= 0) { /* Create proc instance */ rproc->proc = hil_create_proc(cpu_id); if (rproc->proc) { /* Retrieve firmware attributes */ status = hil_get_firmware(fw_name, &fw_addr, &fw_size); if (!status) { /* Initialize ELF loader - currently only ELF format is supported */ rproc->loader = remoteproc_loader_init(ELF_LOADER); if (rproc->loader) { /* Attach the given firmware with the ELF parser/loader */ status = remoteproc_loader_attach_firmware( rproc->loader, (void *) fw_addr); } else { status = RPROC_ERR_LOADER; } } } else { status = RPROC_ERR_NO_MEM; } } else { status = RPROC_ERR_INVLD_FW; } } else { status = RPROC_ERR_NO_MEM; } if (!status) { rproc->role = RPROC_MASTER; /* Get resource table from firmware */ rsc_table = remoteproc_loader_retrieve_resource_section(rproc->loader, &rsc_size); if (rsc_table) { /* Parse resource table */ status = handle_rsc_table(rproc, rsc_table, rsc_size); } else { status = RPROC_ERR_NO_RSC_TABLE; } } /* Cleanup in case of error */ if (status != RPROC_SUCCESS) { (void) remoteproc_deinit(rproc); return status; } rproc->channel_created = channel_created; rproc->channel_destroyed = channel_destroyed; rproc->default_cb = default_cb; *rproc_handle = rproc; return status; }
/** * rpmsg_rdev_init * * This function creates and initializes the remote device. The remote device * encapsulates virtio device. * * @param rdev - pointer to newly created remote device * @param dev-id - ID of device to create , remote cpu id * @param role - role of the other device, Master or Remote * @param channel_created - callback function for channel creation * @param channel_destroyed - callback function for channel deletion * @param default_cb - default callback for channel * * @return - status of function execution * */ int rpmsg_rdev_init(struct remote_device **rdev, int dev_id, int role, rpmsg_chnl_cb_t channel_created, rpmsg_chnl_cb_t channel_destroyed, rpmsg_rx_cb_t default_cb) { struct remote_device *rdev_loc; struct virtio_device *virt_dev; struct hil_proc *proc; struct proc_shm *shm; int status; /* Initialize HIL data structures for given device */ proc = hil_create_proc(dev_id); if (!proc) { return RPMSG_ERR_DEV_ID; } /* Create software representation of remote processor. */ rdev_loc = (struct remote_device *) env_allocate_memory(sizeof(struct remote_device)); if (!rdev_loc) { return RPMSG_ERR_NO_MEM; } env_memset(rdev_loc, 0x00, sizeof(struct remote_device)); status = env_create_mutex(&rdev_loc->lock, 1); if (status != RPMSG_SUCCESS) { /* Cleanup required in case of error is performed by caller */ return status; } rdev_loc->proc = proc; rdev_loc->role = role; rdev_loc->channel_created = channel_created; rdev_loc->channel_destroyed = channel_destroyed; rdev_loc->default_cb = default_cb; /* Restrict the ept address - zero address can't be assigned */ rdev_loc->bitmap[0] = 1; /* Initialize the virtio device */ virt_dev = &rdev_loc->virt_dev; virt_dev->device = proc; virt_dev->func = &rpmsg_rdev_config_ops; if (virt_dev->func->set_features != RPMSG_NULL) { virt_dev->func->set_features(virt_dev, proc->vdev.dfeatures); } if (rdev_loc->role == RPMSG_REMOTE) { /* * Since device is RPMSG Remote so we need to manage the * shared buffers. Create shared memory pool to handle buffers. */ shm = hil_get_shm_info(proc); rdev_loc->mem_pool = sh_mem_create_pool(shm->start_addr, shm->size, RPMSG_BUFFER_SIZE); if (!rdev_loc->mem_pool) { return RPMSG_ERR_NO_MEM; } } /* Initialize channels for RPMSG Remote */ status = rpmsg_rdev_init_channels(rdev_loc); if (status != RPMSG_SUCCESS) { return status; } *rdev = rdev_loc; return RPMSG_SUCCESS; }