muc_uart: add firmware upload

Add function to upload the firmware to the
muc on a packetbus request to do so.

Change-Id: I53d7444735ae95a945e6194b2e81eb3cd100f18e
Signed-off-by: Ryan Lattrel <ryanl@motorola.com>
Reviewed-on: https://gerrit.mot.com/1256019
SME-Granted: SME Approvals Granted
SLTApproved: Slta Waiver
Tested-by: Jira Key
Reviewed-by: Ling Jin <lingjin@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
Ryan Lattrel 2018-10-15 17:13:01 -05:00
commit 86b35199c3
2 changed files with 126 additions and 1 deletions

View file

@ -21,6 +21,17 @@ struct mmi_uart_hdr_t {
} __packed;
/* Followed by CRC16 (Poly8005) */
struct mmi_uart_fw_t {
uint16_t port_id;
uint16_t sn;
uint8_t payload[];
} __packed;
struct mmi_uart_pb_hdr_t {
uint16_t port_id;
uint16_t cmd;
} __packed;
#define MSG_MAGIC 0xA1A1
#define MSG_META_DATA_SIZE (sizeof(struct mmi_uart_hdr_t) + sizeof(uint16_t))
@ -42,6 +53,14 @@ struct mmi_uart_hdr_t {
#define MOD_ATTACH_GPIO 36
#define FORCE_USB_BOOT_GPIO 136
/* Packetbus update command */
#define PACKETBUS_PORT_MUC_FW 0x0007
#define BOLT_MSG_GET_MUC_FW 0x0000
/* TODO put in dev tree? */
#define MUC_FIRMWARE_NAME "muc_firmware.zip"
#define MUC_FW_PAYLOAD_SIZE 1022
enum { NORMAL = 0, BP_TOOLS, FACTORY, QCOM, };
struct boot_mode_t {
uint8_t boot_mode; /* androidboot.mode */

View file

@ -25,6 +25,7 @@
#include <linux/mutex.h>
#include <linux/uaccess.h>
#include <linux/ipc_logging.h>
#include <linux/firmware.h>
#include <soc/qcom/mmi_boot_info.h>
#include "muc_uart.h"
#include "mmi_uart.h"
@ -887,6 +888,108 @@ static int muc_uart_pb_put_q(struct mod_muc_data_t *mm_data,
return 0;
}
static int muc_uart_send_firmware(struct mod_muc_data_t *mm_data)
{
struct mmi_uart_fw_t *fw_pkt;
const struct firmware *fw = NULL;
int fw_data_remaining;
int fw_data_offset = 0;
uint16_t fw_pkt_sn = 1;
uint16_t fw_pkt_len;
uint16_t fw_payload_len;
MUC_LOG("Updating muc firmware\n");
if (request_firmware(&fw, MUC_FIRMWARE_NAME, &mm_data->pdev->dev)) {
MUC_ERR("Unable to locate firmware %s!\n", MUC_FIRMWARE_NAME);
goto err;
}
MUC_LOG("Firmware size is %zd bytes\n", fw->size);
MUC_LOG("Queuing %zd messages for upload\n",
(fw->size % MUC_FW_PAYLOAD_SIZE) > 0 ?
(fw->size / MUC_FW_PAYLOAD_SIZE) + 2 :
(fw->size / MUC_FW_PAYLOAD_SIZE) + 1);
fw_pkt = kmalloc(sizeof(struct mmi_uart_fw_t) +
MUC_FW_PAYLOAD_SIZE, GFP_KERNEL);
if (!fw_pkt) {
MUC_ERR("Unable allocate firmware packet\n");
goto err_mem;
}
fw_pkt->port_id = PACKETBUS_PORT_MUC_FW;
fw_data_remaining = fw->size;
while (fw_data_remaining > 0) {
if (fw_data_remaining >= MUC_FW_PAYLOAD_SIZE)
fw_payload_len = MUC_FW_PAYLOAD_SIZE;
else
fw_payload_len = fw_data_remaining;
memcpy(fw_pkt->payload,
fw->data + fw_data_offset,
fw_payload_len);
fw_pkt_len = sizeof(struct mmi_uart_fw_t) + fw_payload_len;
fw_pkt->sn = fw_pkt_sn++;
if (muc_uart_queue_send(mm_data,
PACKETBUS_PROT_MSG,
(uint8_t *)fw_pkt,
fw_pkt_len) != fw_pkt_len)
goto err_pkt;
fw_data_offset += fw_payload_len;
fw_data_remaining -= fw_payload_len;
}
/* Last packet empty payload to indicate EOF */
fw_pkt_len = sizeof(struct mmi_uart_fw_t);
fw_pkt->sn = fw_pkt_sn;
if (muc_uart_queue_send(mm_data,
PACKETBUS_PROT_MSG,
(uint8_t *)fw_pkt,
fw_pkt_len) != fw_pkt_len)
goto err_pkt;
kfree(fw_pkt);
release_firmware(fw);
return 0;
err_pkt:
kfree(fw_pkt);
err_mem:
release_firmware(fw);
err:
return 1;
}
static int muc_uart_check_update(struct mod_muc_data_t *mm_data,
size_t payload_len,
uint8_t *payload)
{
struct mmi_uart_pb_hdr_t *pb_hdr;
/* Check if this message was for us instead of userspace */
if (payload_len < sizeof(struct mmi_uart_pb_hdr_t))
return 1;
pb_hdr = (struct mmi_uart_pb_hdr_t *)payload;
if (pb_hdr->port_id != PACKETBUS_PORT_MUC_FW)
return 1;
if (pb_hdr->cmd != BOLT_MSG_GET_MUC_FW)
return 1;
if (muc_uart_send_firmware(mm_data))
MUC_ERR("Failed to send firmware to muc\n");
return 0;
}
int muc_uart_pb_write(struct platform_device *pdev,
const char __user *buf,
size_t count)
@ -951,7 +1054,10 @@ static void muc_uart_handle_message(struct mod_muc_data_t *mm_data,
break;
}
case PACKETBUS_PROT_MSG: {
if (!muc_uart_pb_put_q(mm_data,
if (!muc_uart_check_update(mm_data,
payload_len,
payload) ||
!muc_uart_pb_put_q(mm_data,
payload_len,
payload)) {
muc_uart_send(mm_data,