/* * The es2 chip doesn't have VID/PID programmed into the hardware and we need to * hack that up to distinguish different modules and their firmware blobs. * * This fetches VID/PID (over bootrom protocol) for es2 chip only, when VID/PID * already sent during hotplug are 0. * * Otherwise, we keep intf->vendor_id/product_id same as what's passed * during hotplug. */ static void bootrom_es2_fixup_vid_pid(struct gb_bootrom *bootrom) { struct gb_bootrom_get_vid_pid_response response; struct gb_connection *connection = bootrom->connection; struct gb_interface *intf = connection->bundle->intf; int ret; if (!(intf->quirks & GB_INTERFACE_QUIRK_NO_GMP_IDS)) return; ret = gb_operation_sync(connection, GB_BOOTROM_TYPE_GET_VID_PID, NULL, 0, &response, sizeof(response)); if (ret) { dev_err(&connection->bundle->dev, "Bootrom get vid/pid operation failed (%d)\n", ret); return; } /* * NOTE: This is hacked, so that the same values of VID/PID can be used * by next firmware level as well. The uevent for bootrom will still * have VID/PID as 0, though after this point the sysfs files will start * showing the updated values. But yeah, that's a bit racy as the same * sysfs files would be showing 0 before this point. */ intf->vendor_id = le32_to_cpu(response.vendor_id); intf->product_id = le32_to_cpu(response.product_id); dev_dbg(&connection->bundle->dev, "Bootrom got vid (0x%x)/pid (0x%x)\n", intf->vendor_id, intf->product_id); }
int gb_i2s_mgmt_get_supported_configurations( struct gb_connection *connection, struct gb_i2s_mgmt_get_supported_configurations_response *get_cfg, size_t size) { return gb_operation_sync(connection, GB_I2S_MGMT_TYPE_GET_SUPPORTED_CONFIGURATIONS, NULL, 0, get_cfg, size); }
static int gb_gpio_line_count_operation(struct gb_gpio_controller *ggc) { struct gb_gpio_line_count_response response; int ret; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_LINE_COUNT, NULL, 0, &response, sizeof(response)); if (!ret) ggc->line_max = response.count; return ret; }
int gb_i2s_mgmt_deactivate_cport(struct gb_connection *connection, uint16_t cport) { struct gb_i2s_mgmt_deactivate_cport_request request; memset(&request, 0, sizeof(request)); request.cport = cpu_to_le16(cport); return gb_operation_sync(connection, GB_I2S_MGMT_TYPE_DEACTIVATE_CPORT, &request, sizeof(request), NULL, 0); }
static int gb_gpio_activate_operation(struct gb_gpio_controller *ggc, u8 which) { struct gb_gpio_activate_request request; int ret; request.which = which; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_ACTIVATE, &request, sizeof(request), NULL, 0); if (!ret) ggc->lines[which].active = true; return ret; }
static int turn_off(struct gb_vibrator_device *vib) { struct gb_bundle *bundle = vib->connection->bundle; int ret; ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_OFF, NULL, 0, NULL, 0); gb_pm_runtime_put_autosuspend(bundle); return ret; }
static int gb_blink_set(struct led_classdev *cdev, unsigned long *delay_on, unsigned long *delay_off) { struct gb_channel *channel = get_channel_from_cdev(cdev); struct gb_connection *connection = get_conn_from_channel(channel); struct gb_bundle *bundle = connection->bundle; struct gb_lights_blink_request req; bool old_active; int ret; if (channel->releasing) return -ESHUTDOWN; mutex_lock(&channel->lock); ret = gb_pm_runtime_get_sync(bundle); if (ret < 0) goto out_unlock; old_active = channel->active; req.light_id = channel->light->id; req.channel_id = channel->id; req.time_on_ms = cpu_to_le16(*delay_on); req.time_off_ms = cpu_to_le16(*delay_off); ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BLINK, &req, sizeof(req), NULL, 0); if (ret < 0) goto out_pm_put; if (delay_on) channel->active = true; else channel->active = false; /* we need to keep module alive when turning to active state */ if (!old_active && channel->active) goto out_unlock; /* * on the other hand if going to inactive we still hold a reference and * need to put it, so we could go to suspend. */ if (old_active && !channel->active) gb_pm_runtime_put_autosuspend(bundle); out_pm_put: gb_pm_runtime_put_autosuspend(bundle); out_unlock: mutex_unlock(&channel->lock); return ret; }
static int gb_gpio_direction_in_operation(struct gb_gpio_controller *ggc, u8 which) { struct gb_gpio_direction_in_request request; int ret; request.which = which; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DIRECTION_IN, &request, sizeof(request), NULL, 0); if (!ret) ggc->lines[which].direction = 1; return ret; }
static void _gb_gpio_irq_unmask(struct gb_gpio_controller *ggc, u8 hwirq) { struct device *dev = &ggc->gbphy_dev->dev; struct gb_gpio_irq_unmask_request request; int ret; request.which = hwirq; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_IRQ_UNMASK, &request, sizeof(request), NULL, 0); if (ret) dev_err(dev, "failed to unmask irq: %d\n", ret); }
int gb_i2s_mgmt_set_samples_per_message( struct gb_connection *connection, uint16_t samples_per_message) { struct gb_i2s_mgmt_set_samples_per_message_request request; memset(&request, 0, sizeof(request)); request.samples_per_message = cpu_to_le16(samples_per_message); return gb_operation_sync(connection, GB_I2S_MGMT_TYPE_SET_SAMPLES_PER_MESSAGE, &request, sizeof(request), NULL, 0); }
static int gb_gpio_direction_out_operation(struct gb_gpio_controller *ggc, u8 which, bool value_high) { struct gb_gpio_direction_out_request request; int ret; request.which = which; request.value = value_high ? 1 : 0; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DIRECTION_OUT, &request, sizeof(request), NULL, 0); if (!ret) ggc->lines[which].direction = 0; return ret; }
static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *ggc, u8 which, u16 debounce_usec) { struct gb_gpio_set_debounce_request request; int ret; request.which = which; request.usec = cpu_to_le16(debounce_usec); ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_SET_DEBOUNCE, &request, sizeof(request), NULL, 0); if (!ret) ggc->lines[which].debounce_usec = debounce_usec; return ret; }
static void _gb_gpio_irq_set_type(struct gb_gpio_controller *ggc, u8 hwirq, u8 type) { struct device *dev = &ggc->gbphy_dev->dev; struct gb_gpio_irq_type_request request; int ret; request.which = hwirq; request.type = type; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_IRQ_TYPE, &request, sizeof(request), NULL, 0); if (ret) dev_err(dev, "failed to set irq type: %d\n", ret); }
static int __gb_lights_led_brightness_set(struct gb_channel *channel) { struct gb_lights_set_brightness_request req; struct gb_connection *connection = get_conn_from_channel(channel); struct gb_bundle *bundle = connection->bundle; bool old_active; int ret; mutex_lock(&channel->lock); ret = gb_pm_runtime_get_sync(bundle); if (ret < 0) goto out_unlock; old_active = channel->active; req.light_id = channel->light->id; req.channel_id = channel->id; req.brightness = (u8)channel->led->brightness; ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BRIGHTNESS, &req, sizeof(req), NULL, 0); if (ret < 0) goto out_pm_put; if (channel->led->brightness) channel->active = true; else channel->active = false; /* we need to keep module alive when turning to active state */ if (!old_active && channel->active) goto out_unlock; /* * on the other hand if going to inactive we still hold a reference and * need to put it, so we could go to suspend. */ if (old_active && !channel->active) gb_pm_runtime_put_autosuspend(bundle); out_pm_put: gb_pm_runtime_put_autosuspend(bundle); out_unlock: mutex_unlock(&channel->lock); return ret; }
static void gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc, u8 which) { struct device *dev = &ggc->connection->bundle->dev; struct gb_gpio_deactivate_request request; int ret; request.which = which; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DEACTIVATE, &request, sizeof(request), NULL, 0); if (ret) { dev_err(dev, "failed to deactivate gpio %u\n", which); return; } ggc->lines[which].active = false; }
static int gb_lights_get_count(struct gb_lights *glights) { struct gb_lights_get_lights_response resp; int ret; ret = gb_operation_sync(glights->connection, GB_LIGHTS_TYPE_GET_LIGHTS, NULL, 0, &resp, sizeof(resp)); if (ret < 0) return ret; if (!resp.lights_count) return -EINVAL; glights->lights_count = resp.lights_count; return 0; }
static int gb_lights_light_config(struct gb_lights *glights, u8 id) { struct gb_light *light = &glights->lights[id]; struct gb_lights_get_light_config_request req; struct gb_lights_get_light_config_response conf; int ret; int i; light->glights = glights; light->id = id; req.id = id; ret = gb_operation_sync(glights->connection, GB_LIGHTS_TYPE_GET_LIGHT_CONFIG, &req, sizeof(req), &conf, sizeof(conf)); if (ret < 0) return ret; if (!conf.channel_count) return -EINVAL; if (!strlen(conf.name)) return -EINVAL; light->channels_count = conf.channel_count; light->name = kstrndup(conf.name, NAMES_MAX, GFP_KERNEL); light->channels = kzalloc(light->channels_count * sizeof(struct gb_channel), GFP_KERNEL); if (!light->channels) return -ENOMEM; /* First we collect all the configurations for all channels */ for (i = 0; i < light->channels_count; i++) { light->channels[i].id = i; ret = gb_lights_channel_config(light, &light->channels[i]); if (ret < 0) return ret; } return 0; }
static int gb_lights_channel_flash_config(struct gb_channel *channel) { struct gb_connection *connection = get_conn_from_channel(channel); struct gb_lights_get_channel_flash_config_request req; struct gb_lights_get_channel_flash_config_response conf; struct led_flash_setting *fset; int ret; req.light_id = channel->light->id; req.channel_id = channel->id; ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_GET_CHANNEL_FLASH_CONFIG, &req, sizeof(req), &conf, sizeof(conf)); if (ret < 0) return ret; /* * Intensity constraints for flash related modes: flash, torch, * indicator. They will be needed for v4l2 registration. */ fset = &channel->intensity_uA; fset->min = le32_to_cpu(conf.intensity_min_uA); fset->max = le32_to_cpu(conf.intensity_max_uA); fset->step = le32_to_cpu(conf.intensity_step_uA); /* * On flash type, max brightness is set as the number of intensity steps * available. */ channel->led->max_brightness = (fset->max - fset->min) / fset->step; /* Only the flash mode have the timeout constraints settings */ if (channel->mode & GB_CHANNEL_MODE_FLASH) { fset = &channel->timeout_us; fset->min = le32_to_cpu(conf.timeout_min_us); fset->max = le32_to_cpu(conf.timeout_max_us); fset->step = le32_to_cpu(conf.timeout_step_us); } return 0; }
static void gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc, u8 which) { struct gbphy_device *gbphy_dev = ggc->gbphy_dev; struct device *dev = &gbphy_dev->dev; struct gb_gpio_deactivate_request request; int ret; request.which = which; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DEACTIVATE, &request, sizeof(request), NULL, 0); if (ret) { dev_err(dev, "failed to deactivate gpio %u\n", which); goto out_pm_put; } ggc->lines[which].active = false; out_pm_put: gbphy_runtime_put_autosuspend(gbphy_dev); }
static int gb_gpio_activate_operation(struct gb_gpio_controller *ggc, u8 which) { struct gb_gpio_activate_request request; struct gbphy_device *gbphy_dev = ggc->gbphy_dev; int ret; ret = gbphy_runtime_get_sync(gbphy_dev); if (ret) return ret; request.which = which; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_ACTIVATE, &request, sizeof(request), NULL, 0); if (ret) { gbphy_runtime_put_autosuspend(gbphy_dev); return ret; } ggc->lines[which].active = true; return 0; }
int gb_i2s_send_data(struct gb_connection *connection, void *req_buf, void *source_addr, size_t len, int sample_num) { struct gb_i2s_send_data_request *gb_req; int ret; gb_req = req_buf; gb_req->sample_number = cpu_to_le32(sample_num); memcpy((void *)&gb_req->data[0], source_addr, len); if (len < MAX_SEND_DATA_LEN) for (; len < MAX_SEND_DATA_LEN; len++) gb_req->data[len] = gb_req->data[len - SAMPLE_SIZE]; gb_req->size = cpu_to_le32(len); ret = gb_operation_sync(connection, GB_I2S_DATA_TYPE_SEND_DATA, (void *) gb_req, SEND_DATA_BUF_LEN, NULL, 0); return ret; }
/* * The es2 chip doesn't have VID/PID programmed into the hardware and we need to * hack that up to distinguish different modules and their firmware blobs. * * This fetches VID/PID (over firmware protocol) for es2 chip only, when VID/PID * already sent during hotplug are 0. * * Otherwise, we keep intf->vendor_id/product_id same as what's passed * during hotplug. */ static void firmware_es2_fixup_vid_pid(struct gb_firmware *firmware) { struct gb_firmware_get_vid_pid_response response; struct gb_connection *connection = firmware->connection; struct gb_interface *intf = connection->bundle->intf; int ret; /* * Use VID/PID specified at hotplug if: * - Bridge ASIC chip isn't ES2 * - Received non-zero Vendor/Product ids */ if (intf->ddbl1_manufacturer_id != ES2_DDBL1_MFR_ID || intf->ddbl1_product_id != ES2_DDBL1_PROD_ID || intf->vendor_id != 0 || intf->product_id != 0) return; ret = gb_operation_sync(connection, GB_FIRMWARE_TYPE_GET_VID_PID, NULL, 0, &response, sizeof(response)); if (ret) { dev_err(&connection->bundle->dev, "Firmware get vid/pid operation failed (%d)\n", ret); return; } /* * NOTE: This is hacked, so that the same values of VID/PID can be used * by next firmware level as well. The uevent for bootrom will still * have VID/PID as 0, though after this point the sysfs files will start * showing the updated values. But yeah, that's a bit racy as the same * sysfs files would be showing 0 before this point. */ intf->vendor_id = le32_to_cpu(response.vendor_id); intf->product_id = le32_to_cpu(response.product_id); dev_dbg(&connection->bundle->dev, "Firmware got vid (0x%x)/pid (0x%x)\n", intf->vendor_id, intf->product_id); }
static int gb_lights_color_set(struct gb_channel *channel, u32 color) { struct gb_connection *connection = get_conn_from_channel(channel); struct gb_bundle *bundle = connection->bundle; struct gb_lights_set_color_request req; int ret; if (channel->releasing) return -ESHUTDOWN; ret = gb_pm_runtime_get_sync(bundle); if (ret < 0) return ret; req.light_id = channel->light->id; req.channel_id = channel->id; req.color = cpu_to_le32(color); ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_COLOR, &req, sizeof(req), NULL, 0); gb_pm_runtime_put_autosuspend(bundle); return ret; }
static int gb_firmware_get_version(struct gb_firmware *firmware) { struct gb_bundle *bundle = firmware->connection->bundle; struct gb_firmware_version_request request; struct gb_firmware_version_response response; int ret; request.major = GB_FIRMWARE_VERSION_MAJOR; request.minor = GB_FIRMWARE_VERSION_MINOR; ret = gb_operation_sync(firmware->connection, GB_FIRMWARE_TYPE_VERSION, &request, sizeof(request), &response, sizeof(response)); if (ret) { dev_err(&bundle->dev, "failed to get protocol version: %d\n", ret); return ret; } if (response.major > request.major) { dev_err(&bundle->dev, "unsupported major protocol version (%u > %u)\n", response.major, request.major); return -ENOTSUPP; } firmware->protocol_major = response.major; firmware->protocol_minor = response.minor; dev_dbg(&bundle->dev, "%s - %u.%u\n", __func__, response.major, response.minor); return 0; }
static void gb_gpio_set_value_operation(struct gb_gpio_controller *ggc, u8 which, bool value_high) { struct device *dev = &ggc->gbphy_dev->dev; struct gb_gpio_set_value_request request; int ret; if (ggc->lines[which].direction == 1) { dev_warn(dev, "refusing to set value of input gpio %u\n", which); return; } request.which = which; request.value = value_high ? 1 : 0; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_SET_VALUE, &request, sizeof(request), NULL, 0); if (ret) { dev_err(dev, "failed to set value of gpio %u\n", which); return; } ggc->lines[which].value = request.value; }
static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms) { struct gb_bundle *bundle = vib->connection->bundle; int ret; ret = gb_pm_runtime_get_sync(bundle); if (ret) return ret; /* Vibrator was switched ON earlier */ if (cancel_delayed_work_sync(&vib->delayed_work)) turn_off(vib); ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_ON, NULL, 0, NULL, 0); if (ret) { gb_pm_runtime_put_autosuspend(bundle); return ret; } schedule_delayed_work(&vib->delayed_work, msecs_to_jiffies(timeout_ms)); return 0; }
static int gb_gpio_get_direction_operation(struct gb_gpio_controller *ggc, u8 which) { struct device *dev = &ggc->gbphy_dev->dev; struct gb_gpio_get_direction_request request; struct gb_gpio_get_direction_response response; int ret; u8 direction; request.which = which; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_GET_DIRECTION, &request, sizeof(request), &response, sizeof(response)); if (ret) return ret; direction = response.direction; if (direction && direction != 1) { dev_warn(dev, "gpio %u direction was %u (should be 0 or 1)\n", which, direction); } ggc->lines[which].direction = direction ? 1 : 0; return 0; }
static int gb_bootrom_probe(struct gb_bundle *bundle, const struct greybus_bundle_id *id) { struct greybus_descriptor_cport *cport_desc; struct gb_connection *connection; struct gb_bootrom *bootrom; int ret; if (bundle->num_cports != 1) return -ENODEV; cport_desc = &bundle->cport_desc[0]; if (cport_desc->protocol_id != GREYBUS_PROTOCOL_BOOTROM) return -ENODEV; bootrom = kzalloc(sizeof(*bootrom), GFP_KERNEL); if (!bootrom) return -ENOMEM; connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), gb_bootrom_request_handler); if (IS_ERR(connection)) { ret = PTR_ERR(connection); goto err_free_bootrom; } gb_connection_set_data(connection, bootrom); bootrom->connection = connection; mutex_init(&bootrom->mutex); INIT_DELAYED_WORK(&bootrom->dwork, gb_bootrom_timedout); greybus_set_drvdata(bundle, bootrom); ret = gb_connection_enable_tx(connection); if (ret) goto err_connection_destroy; ret = gb_bootrom_get_version(bootrom); if (ret) goto err_connection_disable; bootrom_es2_fixup_vid_pid(bootrom); ret = gb_connection_enable(connection); if (ret) goto err_connection_disable; /* Refresh timeout */ gb_bootrom_set_timeout(bootrom, NEXT_REQ_FIRMWARE_SIZE, NEXT_REQ_TIMEOUT_MS); /* Tell bootrom we're ready. */ ret = gb_operation_sync(connection, GB_BOOTROM_TYPE_AP_READY, NULL, 0, NULL, 0); if (ret) { dev_err(&connection->bundle->dev, "failed to send AP READY: %d\n", ret); goto err_cancel_timeout; } dev_dbg(&bundle->dev, "AP_READY sent\n"); return 0; err_cancel_timeout: gb_bootrom_cancel_timeout(bootrom); err_connection_disable: gb_connection_disable(connection); err_connection_destroy: gb_connection_destroy(connection); err_free_bootrom: kfree(bootrom); return ret; }
int gb_i2s_mgmt_set_configuration(struct gb_connection *connection, struct gb_i2s_mgmt_set_configuration_request *set_cfg) { return gb_operation_sync(connection, GB_I2S_MGMT_TYPE_SET_CONFIGURATION, set_cfg, sizeof(*set_cfg), NULL, 0); }
static int gb_firmware_probe(struct gb_bundle *bundle, const struct greybus_bundle_id *id) { struct greybus_descriptor_cport *cport_desc; struct gb_connection *connection; struct gb_firmware *firmware; int ret; if (bundle->num_cports != 1) return -ENODEV; cport_desc = &bundle->cport_desc[0]; if (cport_desc->protocol_id != GREYBUS_PROTOCOL_FIRMWARE) return -ENODEV; firmware = kzalloc(sizeof(*firmware), GFP_KERNEL); if (!firmware) return -ENOMEM; connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), gb_firmware_request_handler); if (IS_ERR(connection)) { ret = PTR_ERR(connection); goto err_free_firmware; } gb_connection_set_data(connection, firmware); firmware->connection = connection; greybus_set_drvdata(bundle, firmware); ret = gb_connection_enable_tx(connection); if (ret) goto err_connection_destroy; ret = gb_firmware_get_version(firmware); if (ret) goto err_connection_disable; firmware_es2_fixup_vid_pid(firmware); ret = gb_connection_enable(connection); if (ret) goto err_connection_disable; /* Tell bootrom we're ready. */ ret = gb_operation_sync(connection, GB_FIRMWARE_TYPE_AP_READY, NULL, 0, NULL, 0); if (ret) { dev_err(&connection->bundle->dev, "failed to send AP READY: %d\n", ret); goto err_connection_disable; } dev_dbg(&bundle->dev, "AP_READY sent\n"); return 0; err_connection_disable: gb_connection_disable(connection); err_connection_destroy: gb_connection_destroy(connection); err_free_firmware: kfree(firmware); return ret; }