brintos

brintos / linux-shallow public Read only

0
0
Text · 13.3 KiB · d4d86b3 Raw
527 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * BOOTROM Greybus driver.4 *5 * Copyright 2016 Google Inc.6 * Copyright 2016 Linaro Ltd.7 */8 9#include <linux/firmware.h>10#include <linux/jiffies.h>11#include <linux/mutex.h>12#include <linux/workqueue.h>13#include <linux/greybus.h>14 15#include "firmware.h"16 17/* Timeout, in jiffies, within which the next request must be received */18#define NEXT_REQ_TIMEOUT_MS	100019 20/*21 * FIXME: Reduce this timeout once svc core handles parallel processing of22 * events from the SVC, which are handled sequentially today.23 */24#define MODE_SWITCH_TIMEOUT_MS	1000025 26enum next_request_type {27	NEXT_REQ_FIRMWARE_SIZE,28	NEXT_REQ_GET_FIRMWARE,29	NEXT_REQ_READY_TO_BOOT,30	NEXT_REQ_MODE_SWITCH,31};32 33struct gb_bootrom {34	struct gb_connection	*connection;35	const struct firmware	*fw;36	u8			protocol_major;37	u8			protocol_minor;38	enum next_request_type	next_request;39	struct delayed_work	dwork;40	struct mutex		mutex; /* Protects bootrom->fw */41};42 43static void free_firmware(struct gb_bootrom *bootrom)44{45	if (!bootrom->fw)46		return;47 48	release_firmware(bootrom->fw);49	bootrom->fw = NULL;50}51 52static void gb_bootrom_timedout(struct work_struct *work)53{54	struct delayed_work *dwork = to_delayed_work(work);55	struct gb_bootrom *bootrom = container_of(dwork,56						  struct gb_bootrom, dwork);57	struct device *dev = &bootrom->connection->bundle->dev;58	const char *reason;59 60	switch (bootrom->next_request) {61	case NEXT_REQ_FIRMWARE_SIZE:62		reason = "Firmware Size Request";63		break;64	case NEXT_REQ_GET_FIRMWARE:65		reason = "Get Firmware Request";66		break;67	case NEXT_REQ_READY_TO_BOOT:68		reason = "Ready to Boot Request";69		break;70	case NEXT_REQ_MODE_SWITCH:71		reason = "Interface Mode Switch";72		break;73	default:74		reason = NULL;75		dev_err(dev, "Invalid next-request: %u", bootrom->next_request);76		break;77	}78 79	dev_err(dev, "Timed out waiting for %s from the Module\n", reason);80 81	mutex_lock(&bootrom->mutex);82	free_firmware(bootrom);83	mutex_unlock(&bootrom->mutex);84 85	/* TODO: Power-off Module ? */86}87 88static void gb_bootrom_set_timeout(struct gb_bootrom *bootrom,89				   enum next_request_type next,90				   unsigned long timeout)91{92	bootrom->next_request = next;93	schedule_delayed_work(&bootrom->dwork, msecs_to_jiffies(timeout));94}95 96static void gb_bootrom_cancel_timeout(struct gb_bootrom *bootrom)97{98	cancel_delayed_work_sync(&bootrom->dwork);99}100 101/*102 * The es2 chip doesn't have VID/PID programmed into the hardware and we need to103 * hack that up to distinguish different modules and their firmware blobs.104 *105 * This fetches VID/PID (over bootrom protocol) for es2 chip only, when VID/PID106 * already sent during hotplug are 0.107 *108 * Otherwise, we keep intf->vendor_id/product_id same as what's passed109 * during hotplug.110 */111static void bootrom_es2_fixup_vid_pid(struct gb_bootrom *bootrom)112{113	struct gb_bootrom_get_vid_pid_response response;114	struct gb_connection *connection = bootrom->connection;115	struct gb_interface *intf = connection->bundle->intf;116	int ret;117 118	if (!(intf->quirks & GB_INTERFACE_QUIRK_NO_GMP_IDS))119		return;120 121	ret = gb_operation_sync(connection, GB_BOOTROM_TYPE_GET_VID_PID,122				NULL, 0, &response, sizeof(response));123	if (ret) {124		dev_err(&connection->bundle->dev,125			"Bootrom get vid/pid operation failed (%d)\n", ret);126		return;127	}128 129	/*130	 * NOTE: This is hacked, so that the same values of VID/PID can be used131	 * by next firmware level as well. The uevent for bootrom will still132	 * have VID/PID as 0, though after this point the sysfs files will start133	 * showing the updated values. But yeah, that's a bit racy as the same134	 * sysfs files would be showing 0 before this point.135	 */136	intf->vendor_id = le32_to_cpu(response.vendor_id);137	intf->product_id = le32_to_cpu(response.product_id);138 139	dev_dbg(&connection->bundle->dev, "Bootrom got vid (0x%x)/pid (0x%x)\n",140		intf->vendor_id, intf->product_id);141}142 143/* This returns path of the firmware blob on the disk */144static int find_firmware(struct gb_bootrom *bootrom, u8 stage)145{146	struct gb_connection *connection = bootrom->connection;147	struct gb_interface *intf = connection->bundle->intf;148	char firmware_name[49];149	int rc;150 151	/* Already have a firmware, free it */152	free_firmware(bootrom);153 154	/* Bootrom protocol is only supported for loading Stage 2 firmware */155	if (stage != 2) {156		dev_err(&connection->bundle->dev, "Invalid boot stage: %u\n",157			stage);158		return -EINVAL;159	}160 161	/*162	 * Create firmware name163	 *164	 * XXX Name it properly..165	 */166	snprintf(firmware_name, sizeof(firmware_name),167		 FW_NAME_PREFIX "%08x_%08x_%08x_%08x_s2l.tftf",168		 intf->ddbl1_manufacturer_id, intf->ddbl1_product_id,169		 intf->vendor_id, intf->product_id);170 171	// FIXME:172	// Turn to dev_dbg later after everyone has valid bootloaders with good173	// ids, but leave this as dev_info for now to make it easier to track174	// down "empty" vid/pid modules.175	dev_info(&connection->bundle->dev, "Firmware file '%s' requested\n",176		 firmware_name);177 178	rc = request_firmware(&bootrom->fw, firmware_name,179			      &connection->bundle->dev);180	if (rc) {181		dev_err(&connection->bundle->dev,182			"failed to find %s firmware (%d)\n", firmware_name, rc);183	}184 185	return rc;186}187 188static int gb_bootrom_firmware_size_request(struct gb_operation *op)189{190	struct gb_bootrom *bootrom = gb_connection_get_data(op->connection);191	struct gb_bootrom_firmware_size_request *size_request =192		op->request->payload;193	struct gb_bootrom_firmware_size_response *size_response;194	struct device *dev = &op->connection->bundle->dev;195	int ret;196 197	/* Disable timeouts */198	gb_bootrom_cancel_timeout(bootrom);199 200	if (op->request->payload_size != sizeof(*size_request)) {201		dev_err(dev, "%s: illegal size of firmware size request (%zu != %zu)\n",202			__func__, op->request->payload_size,203			sizeof(*size_request));204		ret = -EINVAL;205		goto queue_work;206	}207 208	mutex_lock(&bootrom->mutex);209 210	ret = find_firmware(bootrom, size_request->stage);211	if (ret)212		goto unlock;213 214	if (!gb_operation_response_alloc(op, sizeof(*size_response),215					 GFP_KERNEL)) {216		dev_err(dev, "%s: error allocating response\n", __func__);217		free_firmware(bootrom);218		ret = -ENOMEM;219		goto unlock;220	}221 222	size_response = op->response->payload;223	size_response->size = cpu_to_le32(bootrom->fw->size);224 225	dev_dbg(dev, "%s: firmware size %d bytes\n",226		__func__, size_response->size);227 228unlock:229	mutex_unlock(&bootrom->mutex);230 231queue_work:232	if (!ret) {233		/* Refresh timeout */234		gb_bootrom_set_timeout(bootrom, NEXT_REQ_GET_FIRMWARE,235				       NEXT_REQ_TIMEOUT_MS);236	}237 238	return ret;239}240 241static int gb_bootrom_get_firmware(struct gb_operation *op)242{243	struct gb_bootrom *bootrom = gb_connection_get_data(op->connection);244	const struct firmware *fw;245	struct gb_bootrom_get_firmware_request *firmware_request;246	struct device *dev = &op->connection->bundle->dev;247	unsigned int offset, size;248	enum next_request_type next_request;249	u8 *firmware_response;250	int ret = 0;251 252	/* Disable timeouts */253	gb_bootrom_cancel_timeout(bootrom);254 255	if (op->request->payload_size != sizeof(*firmware_request)) {256		dev_err(dev, "%s: Illegal size of get firmware request (%zu %zu)\n",257			__func__, op->request->payload_size,258			sizeof(*firmware_request));259		ret = -EINVAL;260		goto queue_work;261	}262 263	mutex_lock(&bootrom->mutex);264 265	fw = bootrom->fw;266	if (!fw) {267		dev_err(dev, "%s: firmware not available\n", __func__);268		ret = -EINVAL;269		goto unlock;270	}271 272	firmware_request = op->request->payload;273	offset = le32_to_cpu(firmware_request->offset);274	size = le32_to_cpu(firmware_request->size);275 276	if (offset >= fw->size || size > fw->size - offset) {277		dev_warn(dev, "bad firmware request (offs = %u, size = %u)\n",278			 offset, size);279		ret = -EINVAL;280		goto unlock;281	}282 283	/* gb_bootrom_get_firmware_response contains only a byte array */284	if (!gb_operation_response_alloc(op, size, GFP_KERNEL)) {285		dev_err(dev, "%s: error allocating response\n", __func__);286		ret = -ENOMEM;287		goto unlock;288	}289 290	firmware_response = op->response->payload;291	memcpy(firmware_response, fw->data + offset, size);292 293	dev_dbg(dev, "responding with firmware (offs = %u, size = %u)\n",294		offset, size);295 296unlock:297	mutex_unlock(&bootrom->mutex);298 299queue_work:300	/* Refresh timeout */301	if (!ret && (offset + size == fw->size))302		next_request = NEXT_REQ_READY_TO_BOOT;303	else304		next_request = NEXT_REQ_GET_FIRMWARE;305 306	gb_bootrom_set_timeout(bootrom, next_request, NEXT_REQ_TIMEOUT_MS);307 308	return ret;309}310 311static int gb_bootrom_ready_to_boot(struct gb_operation *op)312{313	struct gb_connection *connection = op->connection;314	struct gb_bootrom *bootrom = gb_connection_get_data(connection);315	struct gb_bootrom_ready_to_boot_request *rtb_request;316	struct device *dev = &connection->bundle->dev;317	u8 status;318	int ret = 0;319 320	/* Disable timeouts */321	gb_bootrom_cancel_timeout(bootrom);322 323	if (op->request->payload_size != sizeof(*rtb_request)) {324		dev_err(dev, "%s: Illegal size of ready to boot request (%zu %zu)\n",325			__func__, op->request->payload_size,326			sizeof(*rtb_request));327		ret = -EINVAL;328		goto queue_work;329	}330 331	rtb_request = op->request->payload;332	status = rtb_request->status;333 334	/* Return error if the blob was invalid */335	if (status == GB_BOOTROM_BOOT_STATUS_INVALID) {336		ret = -EINVAL;337		goto queue_work;338	}339 340	/*341	 * XXX Should we return error for insecure firmware?342	 */343	dev_dbg(dev, "ready to boot: 0x%x, 0\n", status);344 345queue_work:346	/*347	 * Refresh timeout, the Interface shall load the new personality and348	 * send a new hotplug request, which shall get rid of the bootrom349	 * connection. As that can take some time, increase the timeout a bit.350	 */351	gb_bootrom_set_timeout(bootrom, NEXT_REQ_MODE_SWITCH,352			       MODE_SWITCH_TIMEOUT_MS);353 354	return ret;355}356 357static int gb_bootrom_request_handler(struct gb_operation *op)358{359	u8 type = op->type;360 361	switch (type) {362	case GB_BOOTROM_TYPE_FIRMWARE_SIZE:363		return gb_bootrom_firmware_size_request(op);364	case GB_BOOTROM_TYPE_GET_FIRMWARE:365		return gb_bootrom_get_firmware(op);366	case GB_BOOTROM_TYPE_READY_TO_BOOT:367		return gb_bootrom_ready_to_boot(op);368	default:369		dev_err(&op->connection->bundle->dev,370			"unsupported request: %u\n", type);371		return -EINVAL;372	}373}374 375static int gb_bootrom_get_version(struct gb_bootrom *bootrom)376{377	struct gb_bundle *bundle = bootrom->connection->bundle;378	struct gb_bootrom_version_request request;379	struct gb_bootrom_version_response response;380	int ret;381 382	request.major = GB_BOOTROM_VERSION_MAJOR;383	request.minor = GB_BOOTROM_VERSION_MINOR;384 385	ret = gb_operation_sync(bootrom->connection,386				GB_BOOTROM_TYPE_VERSION,387				&request, sizeof(request), &response,388				sizeof(response));389	if (ret) {390		dev_err(&bundle->dev,391			"failed to get protocol version: %d\n",392			ret);393		return ret;394	}395 396	if (response.major > request.major) {397		dev_err(&bundle->dev,398			"unsupported major protocol version (%u > %u)\n",399			response.major, request.major);400		return -ENOTSUPP;401	}402 403	bootrom->protocol_major = response.major;404	bootrom->protocol_minor = response.minor;405 406	dev_dbg(&bundle->dev, "%s - %u.%u\n", __func__, response.major,407		response.minor);408 409	return 0;410}411 412static int gb_bootrom_probe(struct gb_bundle *bundle,413			    const struct greybus_bundle_id *id)414{415	struct greybus_descriptor_cport *cport_desc;416	struct gb_connection *connection;417	struct gb_bootrom *bootrom;418	int ret;419 420	if (bundle->num_cports != 1)421		return -ENODEV;422 423	cport_desc = &bundle->cport_desc[0];424	if (cport_desc->protocol_id != GREYBUS_PROTOCOL_BOOTROM)425		return -ENODEV;426 427	bootrom = kzalloc(sizeof(*bootrom), GFP_KERNEL);428	if (!bootrom)429		return -ENOMEM;430 431	connection = gb_connection_create(bundle,432					  le16_to_cpu(cport_desc->id),433					  gb_bootrom_request_handler);434	if (IS_ERR(connection)) {435		ret = PTR_ERR(connection);436		goto err_free_bootrom;437	}438 439	gb_connection_set_data(connection, bootrom);440 441	bootrom->connection = connection;442 443	mutex_init(&bootrom->mutex);444	INIT_DELAYED_WORK(&bootrom->dwork, gb_bootrom_timedout);445	greybus_set_drvdata(bundle, bootrom);446 447	ret = gb_connection_enable_tx(connection);448	if (ret)449		goto err_connection_destroy;450 451	ret = gb_bootrom_get_version(bootrom);452	if (ret)453		goto err_connection_disable;454 455	bootrom_es2_fixup_vid_pid(bootrom);456 457	ret = gb_connection_enable(connection);458	if (ret)459		goto err_connection_disable;460 461	/* Refresh timeout */462	gb_bootrom_set_timeout(bootrom, NEXT_REQ_FIRMWARE_SIZE,463			       NEXT_REQ_TIMEOUT_MS);464 465	/* Tell bootrom we're ready. */466	ret = gb_operation_sync(connection, GB_BOOTROM_TYPE_AP_READY, NULL, 0,467				NULL, 0);468	if (ret) {469		dev_err(&connection->bundle->dev,470			"failed to send AP READY: %d\n", ret);471		goto err_cancel_timeout;472	}473 474	dev_dbg(&bundle->dev, "AP_READY sent\n");475 476	return 0;477 478err_cancel_timeout:479	gb_bootrom_cancel_timeout(bootrom);480err_connection_disable:481	gb_connection_disable(connection);482err_connection_destroy:483	gb_connection_destroy(connection);484err_free_bootrom:485	kfree(bootrom);486 487	return ret;488}489 490static void gb_bootrom_disconnect(struct gb_bundle *bundle)491{492	struct gb_bootrom *bootrom = greybus_get_drvdata(bundle);493 494	gb_connection_disable(bootrom->connection);495 496	/* Disable timeouts */497	gb_bootrom_cancel_timeout(bootrom);498 499	/*500	 * Release firmware:501	 *502	 * As the connection and the delayed work are already disabled, we don't503	 * need to lock access to bootrom->fw here.504	 */505	free_firmware(bootrom);506 507	gb_connection_destroy(bootrom->connection);508	kfree(bootrom);509}510 511static const struct greybus_bundle_id gb_bootrom_id_table[] = {512	{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_BOOTROM) },513	{ }514};515 516static struct greybus_driver gb_bootrom_driver = {517	.name		= "bootrom",518	.probe		= gb_bootrom_probe,519	.disconnect	= gb_bootrom_disconnect,520	.id_table	= gb_bootrom_id_table,521};522 523module_greybus_driver(gb_bootrom_driver);524 525MODULE_DESCRIPTION("BOOTROM Greybus driver");526MODULE_LICENSE("GPL v2");527