// 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 "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

#define REG32(add) *((volatile uint32_t *)(add))

void aes_init(aes_cfg_t aes_cfg) {
  uint32_t cfg_val =
      (aes_cfg.operation << AES_CTRL_SHADOWED_OPERATION_BIT) |
      ((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_BIT);
  REG32(AES0_BASE_ADDR + AES_CTRL_SHADOWED_REG_OFFSET) = cfg_val;
  REG32(AES0_BASE_ADDR + AES_CTRL_SHADOWED_REG_OFFSET) = cfg_val;
};

void aes_key_put(const void *key_share0, const void *key_share1,
                 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(AES0_BASE_ADDR + AES_KEY_SHARE0_0_REG_OFFSET + i * sizeof(uint32_t)) =
        ((uint32_t *)key_share0)[i];
    REG32(AES0_BASE_ADDR + AES_KEY_SHARE1_0_REG_OFFSET + i * sizeof(uint32_t)) =
        ((uint32_t *)key_share1)[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(AES0_BASE_ADDR + AES_KEY_SHARE0_0_REG_OFFSET + i * sizeof(uint32_t)) =
        0x0;
    REG32(AES0_BASE_ADDR + AES_KEY_SHARE1_0_REG_OFFSET + 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(AES0_BASE_ADDR + AES_IV_0_REG_OFFSET + 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(AES0_BASE_ADDR + AES_DATA_IN_0_REG_OFFSET + 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(AES0_BASE_ADDR + AES_DATA_OUT_0_REG_OFFSET +
                                  i * sizeof(uint32_t));
  }
}

bool aes_data_ready(void) {
  return (REG32(AES0_BASE_ADDR + AES_STATUS_REG_OFFSET) &
          (0x1u << AES_STATUS_INPUT_READY_BIT));
}

bool aes_data_valid(void) {
  return (REG32(AES0_BASE_ADDR + AES_STATUS_REG_OFFSET) &
          (0x1u << AES_STATUS_OUTPUT_VALID_BIT));
}

bool aes_idle(void) {
  return (REG32(AES0_BASE_ADDR + AES_STATUS_REG_OFFSET) &
          (0x1u << AES_STATUS_IDLE_BIT));
}

void aes_manual_trigger(void) {
  REG32(AES0_BASE_ADDR + AES_TRIGGER_REG_OFFSET) = 0x1u
                                                   << AES_TRIGGER_START_BIT;
}

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_BIT;
  REG32(AES0_BASE_ADDR + AES_CTRL_SHADOWED_REG_OFFSET) = cfg_val;
  REG32(AES0_BASE_ADDR + AES_CTRL_SHADOWED_REG_OFFSET) = cfg_val;

  // Clear internal key and output registers
  REG32(AES0_BASE_ADDR + AES_TRIGGER_REG_OFFSET) =
      (0x1u << AES_TRIGGER_KEY_CLEAR_BIT) | (0x1u << AES_TRIGGER_IV_CLEAR_BIT) |
      (0x1u << AES_TRIGGER_DATA_IN_CLEAR_BIT) |
      (0x1u << AES_TRIGGER_DATA_OUT_CLEAR_BIT);

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