// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include "sw/device/lib/aes.h"

#include "sw/device/lib/common.h"

#include "aes_regs.h"  // Generated.
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"

#define AES0_BASE_ADDR TOP_EARLGREY_AES_BASE_ADDR
#define AES_NUM_REGS_KEY 8
#define AES_NUM_REGS_IV 4
#define AES_NUM_REGS_DATA 4

void aes_init(aes_cfg_t aes_cfg) {
  uint32_t cfg_val =
      (aes_cfg.operation << AES_CTRL_SHADOWED_OPERATION) |
      ((aes_cfg.mode & AES_CTRL_SHADOWED_MODE_MASK)
       << AES_CTRL_SHADOWED_MODE_OFFSET) |
      ((aes_cfg.key_len & AES_CTRL_SHADOWED_KEY_LEN_MASK)
       << AES_CTRL_SHADOWED_KEY_LEN_OFFSET) |
      (aes_cfg.manual_operation << AES_CTRL_SHADOWED_MANUAL_OPERATION);
  REG32(AES_CTRL_SHADOWED(0)) = cfg_val;
  REG32(AES_CTRL_SHADOWED(0)) = cfg_val;
};

void aes_key_put(const void *key, aes_key_len_t key_len) {
  // Determine how many key registers to use.
  size_t num_regs_key_used;
  if (key_len == kAes256) {
    num_regs_key_used = 8;
  } else if (key_len == kAes192) {
    num_regs_key_used = 6;
  } else {
    num_regs_key_used = 4;
  }

  // Write the used key registers.
  for (int i = 0; i < num_regs_key_used; ++i) {
    REG32(AES_KEY0(0) + i * sizeof(uint32_t)) = ((uint32_t *)key)[i];
  }
  // Write the unused key registers (the AES unit requires all key registers to
  // be written).
  for (int i = num_regs_key_used; i < AES_NUM_REGS_KEY; ++i) {
    REG32(AES_KEY0(0) + i * sizeof(uint32_t)) = 0x0;
  }
}

void aes_iv_put(const void *iv) {
  // Write the four initialization vector registers.
  for (int i = 0; i < AES_NUM_REGS_IV; ++i) {
    REG32(AES_IV0(0) + i * sizeof(uint32_t)) = ((uint32_t *)iv)[i];
  }
}

void aes_data_put_wait(const void *data) {
  // Wait for AES unit to be ready for new input data.
  while (!aes_data_ready()) {
  }

  // Provide the input data.
  aes_data_put(data);
}

void aes_data_put(const void *data) {
  // Write the four input data registers.
  for (int i = 0; i < AES_NUM_REGS_DATA; ++i) {
    REG32(AES_DATA_IN0(0) + i * sizeof(uint32_t)) = ((uint32_t *)data)[i];
  }
}

void aes_data_get_wait(void *data) {
  // Wait for AES unit to have valid output data.
  while (!aes_data_valid()) {
  }

  // Get the data.
  aes_data_get(data);
}

void aes_data_get(void *data) {
  // Read the four output data registers.
  for (int i = 0; i < AES_NUM_REGS_DATA; ++i) {
    ((uint32_t *)data)[i] = REG32(AES_DATA_OUT0(0) + i * sizeof(uint32_t));
  }
}

bool aes_data_ready(void) {
  return (REG32(AES_STATUS(0)) & (0x1u << AES_STATUS_INPUT_READY));
}

bool aes_data_valid(void) {
  return (REG32(AES_STATUS(0)) & (0x1u << AES_STATUS_OUTPUT_VALID));
}

bool aes_idle(void) {
  return (REG32(AES_STATUS(0)) & (0x1u << AES_STATUS_IDLE));
}

void aes_clear(void) {
  // Wait for AES unit to be idle.
  while (!aes_idle()) {
  }

  // Disable autostart
  uint32_t cfg_val = 0x1u << AES_CTRL_SHADOWED_MANUAL_OPERATION;
  REG32(AES_CTRL_SHADOWED(0)) = cfg_val;
  REG32(AES_CTRL_SHADOWED(0)) = cfg_val;

  // Clear internal key and output registers
  REG32(AES_TRIGGER(0)) = (0x1u << AES_TRIGGER_KEY_CLEAR) |
                          (0x1u << AES_TRIGGER_IV_CLEAR) |
                          (0x1u << AES_TRIGGER_DATA_IN_CLEAR) |
                          (0x1u << AES_TRIGGER_DATA_OUT_CLEAR);

  // Wait for output not valid, and input ready
  while (!(!aes_data_valid() && aes_data_ready())) {
  }
}
