diff options
Diffstat (limited to 'zephyr/drivers')
27 files changed, 0 insertions, 5439 deletions
diff --git a/zephyr/drivers/CMakeLists.txt b/zephyr/drivers/CMakeLists.txt deleted file mode 100644 index d246f31703..0000000000 --- a/zephyr/drivers/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright 2021 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -add_subdirectory(cros_cbi) -add_subdirectory(cros_flash) -add_subdirectory(cros_kb_raw) -add_subdirectory(cros_rtc) -add_subdirectory(cros_shi) -add_subdirectory(cros_system) diff --git a/zephyr/drivers/Kconfig b/zephyr/drivers/Kconfig deleted file mode 100644 index 041a6cf212..0000000000 --- a/zephyr/drivers/Kconfig +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright 2020 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -rsource "cros_flash/Kconfig" -rsource "cros_kb_raw/Kconfig" -rsource "cros_rtc/Kconfig" -rsource "cros_system/Kconfig" -rsource "cros_shi/Kconfig" diff --git a/zephyr/drivers/cros_cbi/CMakeLists.txt b/zephyr/drivers/cros_cbi/CMakeLists.txt deleted file mode 100644 index 644865ae77..0000000000 --- a/zephyr/drivers/cros_cbi/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_CBI_EEPROM cros_cbi.c) -zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_CBI_GPIO cros_cbi.c) diff --git a/zephyr/drivers/cros_cbi/cros_cbi.c b/zephyr/drivers/cros_cbi/cros_cbi.c deleted file mode 100644 index a36a4e9143..0000000000 --- a/zephyr/drivers/cros_cbi/cros_cbi.c +++ /dev/null @@ -1,218 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <drivers/cros_cbi.h> -#include "cros_board_info.h" -#include <logging/log.h> - -LOG_MODULE_REGISTER(cros_cbi, LOG_LEVEL_ERR); - -/* CBI SSFC part */ - -/* This part of the driver is about CBI SSFC part. - * Actually, two "compatible" values are handle here - - * named_cbi_ssfc_value and named_cbi_ssfc. named_cbi_ssfc_value nodes are - * grandchildren of the named_cbi_ssfc node. named_cbi_ssfc_value is introduced - * to iterate over grandchildren of the named_cbi_ssfc(macro - * DT_FOREACH_CHILD can not be nested) and it can be pointed by a sensor dts to - * indicate alternative usage. - */ -#define DT_DRV_COMPAT named_cbi_ssfc_value - -BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(named_cbi_ssfc) < 2, - "More than 1 CBI SSFS node"); -#define CBI_SSFC_NODE DT_INST(0, named_cbi_ssfc) - -#define CBI_SSFC_INIT_DEFAULT_ID(id) \ - do { \ - if (DT_PROP(id, default)) { \ - cached_ssfc.CBI_SSFC_UNION_ENTRY_NAME(DT_PARENT(id)) = \ - DT_PROP(id, value); \ - } \ - } while (0); - -#define CBI_SSFC_INIT_DEFAULT(inst) CBI_SSFC_INIT_DEFAULT_ID(DT_DRV_INST(inst)) - -#define CBI_SSFC_VALUE_ARRAY_ID(id) \ - [CBI_SSFC_VALUE_ID(id)] = DT_PROP(id, value), - -#define CBI_SSFC_VALUE_ARRAY(inst) CBI_SSFC_VALUE_ARRAY_ID(DT_DRV_INST(inst)) - -#define CBI_SSFC_VALUE_BUILD_ASSERT(inst) \ - BUILD_ASSERT(DT_INST_PROP(inst, value) <= UINT8_MAX, \ - "CBI SSFS value too big"); - -#define CBI_SSFC_PARENT_VALUE_CASE_GENERATE(value_id, value_parent) \ - case value_id: \ - return value_parent; - -#define CBI_SSFC_PARENT_VALUE_CASE_ID(id) \ - CBI_SSFC_PARENT_VALUE_CASE_GENERATE( \ - CBI_SSFC_VALUE_ID(id), \ - cached_ssfc.CBI_SSFC_UNION_ENTRY_NAME(DT_PARENT(id))) - -#define CBI_SSFC_PARENT_VALUE_CASE(inst) \ - CBI_SSFC_PARENT_VALUE_CASE_ID(DT_DRV_INST(inst)) - -#define CBI_SSFC_UNION_ENTRY_NAME(id) DT_CAT(cbi_ssfc_, id) -#define CBI_SSFC_UNION_ENTRY(id) \ - uint32_t CBI_SSFC_UNION_ENTRY_NAME(id) \ - : DT_PROP(id, size); - -#define CBI_SSFC_PLUS_FIELD_SIZE(id) +DT_PROP(id, size) -#define CBI_SSFC_FIELDS_SIZE \ - (0 COND_CODE_1( \ - DT_NODE_EXISTS(CBI_SSFC_NODE), \ - (DT_FOREACH_CHILD(CBI_SSFC_NODE, CBI_SSFC_PLUS_FIELD_SIZE)), \ - ())) - -BUILD_ASSERT(CBI_SSFC_FIELDS_SIZE <= 32, "CBI SSFS is bigger than 32 bits"); - -/* - * Define union bit fields based on the device tree entries. Example: - * cbi-ssfc { - * compatible = "named-cbi-ssfc"; - * - * base_sensor { - * enum-name = "BASE_SENSOR"; - * size = <3>; - * bmi160 { - * compatible = "named-cbi-ssfc-value"; - * status = "okay"; - * value = <1>; - * }; - * }; - * lid_sensor { - * enum-name = "LID_SENSOR"; - * size = <3>; - * bma255 { - * compatible = "named-cbi-ssfc-value"; - * status = "okay"; - * value = <1>; - * }; - * }; - * lightbar { - * enum-name = "LIGHTBAR"; - * size = <2>; - * 10_led { - * compatible = "named-cbi-ssfc-value"; - * status = "okay"; - * value = <1>; - * }; - * }; - * }; - * Should be converted into - * union cbi_ssfc { - * struct { - * uint32_t cbi_ssfc_DT_N_S_cbi_ssfc_S_base_sensor:3 - * uint32_t cbi_ssfc_DT_N_S_cbi_ssfc_S_lid_sensor:3 - * uint32_t cbi_ssfc_DT_N_S_cbi_ssfc_S_lightbar:2 - * uint32_t reserved : 24; - * }; - * uint32_t raw_value; - * }; - */ -union cbi_ssfc { - struct { -#if DT_NODE_EXISTS(CBI_SSFC_NODE) - DT_FOREACH_CHILD(CBI_SSFC_NODE, CBI_SSFC_UNION_ENTRY) - uint32_t reserved : (32 - CBI_SSFC_FIELDS_SIZE); -#endif - }; - uint32_t raw_value; -}; - -BUILD_ASSERT(sizeof(union cbi_ssfc) == sizeof(uint32_t), - "CBI SSFS structure exceedes 32 bits"); - -DT_INST_FOREACH_STATUS_OKAY(CBI_SSFC_VALUE_BUILD_ASSERT) - -static const uint8_t ssfc_values[] = { - DT_INST_FOREACH_STATUS_OKAY(CBI_SSFC_VALUE_ARRAY) -}; -static union cbi_ssfc cached_ssfc __attribute__((unused)); - -/* CBI SSFC part end */ - -/* Device config */ -struct cros_cbi_config { - /* SSFC values for specific configs */ - const uint8_t *ssfc_values; -}; - -/* Device data */ -struct cros_cbi_data { - /* Cached SSFC configs */ - union cbi_ssfc cached_ssfc; -}; - -/* CBI SSFC part */ - -static void cros_cbi_ssfc_init(const struct device *dev) -{ - struct cros_cbi_data *data = (struct cros_cbi_data *)(dev->data); - - if (cbi_get_ssfc(&data->cached_ssfc.raw_value) != EC_SUCCESS) { - DT_INST_FOREACH_STATUS_OKAY(CBI_SSFC_INIT_DEFAULT) - } - - LOG_INF("Read CBI SSFC : 0x%08X\n", data->cached_ssfc.raw_value); -} - -static uint32_t cros_cbi_ssfc_get_parent_field_value(union cbi_ssfc cached_ssfc, - enum cbi_ssfc_value_id value_id) -{ - switch (value_id) { - DT_INST_FOREACH_STATUS_OKAY(CBI_SSFC_PARENT_VALUE_CASE) - default: - LOG_ERR("CBI SSFC parent field value not found: %d\n", - value_id); - return 0; - } -} - -static int cros_cbi_ec_ssfc_check_match(const struct device *dev, - enum cbi_ssfc_value_id value_id) -{ - struct cros_cbi_data *data = (struct cros_cbi_data *)(dev->data); - struct cros_cbi_config *cfg = (struct cros_cbi_config *)(dev->config); - - return cros_cbi_ssfc_get_parent_field_value(data->cached_ssfc, - value_id) == - cfg->ssfc_values[value_id]; -} - -/* CBI SSFC part end */ -#undef DT_DRV_COMPAT - -static int cros_cbi_ec_init(const struct device *dev) -{ - cros_cbi_ssfc_init(dev); - - return 0; -} - -/* cros ec cbi driver registration */ -static const struct cros_cbi_driver_api cros_cbi_driver_api = { - .init = cros_cbi_ec_init, - .ssfc_check_match = cros_cbi_ec_ssfc_check_match, -}; - -static int cbi_init(const struct device *dev) -{ - ARG_UNUSED(dev); - - return 0; -} - -static const struct cros_cbi_config cros_cbi_cfg = { - .ssfc_values = ssfc_values, -}; - -static struct cros_cbi_data cros_cbi_data; - -DEVICE_DEFINE(cros_cbi, CROS_CBI_LABEL, cbi_init, NULL, &cros_cbi_data, - &cros_cbi_cfg, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, - &cros_cbi_driver_api); diff --git a/zephyr/drivers/cros_flash/CMakeLists.txt b/zephyr/drivers/cros_flash/CMakeLists.txt deleted file mode 100644 index 6611589ad4..0000000000 --- a/zephyr/drivers/cros_flash/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library_sources_ifdef(CONFIG_CROS_FLASH_IT8XXX2 cros_flash_it8xxx2.c) -zephyr_library_sources_ifdef(CONFIG_CROS_FLASH_NPCX cros_flash_npcx.c) diff --git a/zephyr/drivers/cros_flash/Kconfig b/zephyr/drivers/cros_flash/Kconfig deleted file mode 100644 index 1d100a6068..0000000000 --- a/zephyr/drivers/cros_flash/Kconfig +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2020 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -menuconfig CROS_FLASH_NPCX - bool "Nuvoton NPCX flash driver for the Zephyr shim" - depends on SOC_FAMILY_NPCX - default y if FLASH_SIZE > 0 - help - This option enables a flash unit interface (FIU) driver for the NPCX - chip. This is used instead of the flash memory interface so we can - continue to use most of the existing flash memory processing code in - ECOS. - -config CROS_FLASH_IT8XXX2 - bool "ITE IT81202 flash driver for the Zephyr shim" - depends on SOC_FAMILY_RISCV_ITE - default y - help - This option enables the flash driver for the it8xxx2 chip. We can - access the flash by read, write and erase. The it8xxx2 flash size - is 1M byte. diff --git a/zephyr/drivers/cros_flash/cros_flash_it8xxx2.c b/zephyr/drivers/cros_flash/cros_flash_it8xxx2.c deleted file mode 100644 index f238b1557b..0000000000 --- a/zephyr/drivers/cros_flash/cros_flash_it8xxx2.c +++ /dev/null @@ -1,327 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define DT_DRV_COMPAT ite_it8xxx2_cros_flash - -#include <drivers/cros_flash.h> -#include <drivers/flash.h> -#include <kernel.h> -#include <logging/log.h> -#include <soc.h> - -#include "flash.h" -#include "host_command.h" -#include "system.h" -#include "watchdog.h" - -LOG_MODULE_REGISTER(cros_flash, LOG_LEVEL_ERR); - -/* Device data */ -struct cros_flash_it8xxx2_data { - bool stuck_locked; - bool inconsistent_locked; - bool all_protected; -}; - -/* Driver convenience defines */ -#define DRV_DATA(dev) ((struct cros_flash_it8xxx2_data *)(dev)->data) - -#define FLASH_DEV_NAME DT_CHOSEN_ZEPHYR_FLASH_CONTROLLER_LABEL -static const struct device *flash_controller; - -#define FWP_REG(bank) (bank / 8) -#define FWP_MASK(bank) (1 << (bank % 8)) - -enum flash_wp_interface { - FLASH_WP_HOST = 0x01, - FLASH_WP_DBGR = 0x02, - FLASH_WP_EC = 0x04, -}; - -enum flash_wp_status { - FLASH_WP_STATUS_PROTECT_RO = EC_FLASH_PROTECT_RO_NOW, - FLASH_WP_STATUS_PROTECT_ALL = EC_FLASH_PROTECT_ALL_NOW, -}; - -/** - * Protect flash banks until reboot. - * - * @param start_bank Start bank to protect - * @param bank_count Number of banks to protect - */ -static void flash_protect_banks(int start_bank, int bank_count, - enum flash_wp_interface wp_if) -{ - int bank; - - for (bank = start_bank; bank < start_bank + bank_count; bank++) { - if (wp_if & FLASH_WP_EC) - IT83XX_GCTRL_EWPR0PFEC(FWP_REG(bank)) |= FWP_MASK(bank); - if (wp_if & FLASH_WP_HOST) - IT83XX_GCTRL_EWPR0PFH(FWP_REG(bank)) |= FWP_MASK(bank); - if (wp_if & FLASH_WP_DBGR) - IT83XX_GCTRL_EWPR0PFD(FWP_REG(bank)) |= FWP_MASK(bank); - } -} - -static enum flash_wp_status flash_check_wp(void) -{ - enum flash_wp_status wp_status; - int all_bank_count, bank; - - all_bank_count = CONFIG_FLASH_SIZE_BYTES / CONFIG_FLASH_BANK_SIZE; - - for (bank = 0; bank < all_bank_count; bank++) { - if (!(IT83XX_GCTRL_EWPR0PFEC(FWP_REG(bank)) & FWP_MASK(bank))) - break; - } - - if (bank == WP_BANK_COUNT) - wp_status = FLASH_WP_STATUS_PROTECT_RO; - else if (bank == (WP_BANK_COUNT + PSTATE_BANK_COUNT)) - wp_status = FLASH_WP_STATUS_PROTECT_RO; - else if (bank == all_bank_count) - wp_status = FLASH_WP_STATUS_PROTECT_ALL; - else - wp_status = 0; - - return wp_status; -} - -/* cros ec flash api functions */ -static int cros_flash_it8xxx2_init(const struct device *dev) -{ - struct cros_flash_it8xxx2_data *const data = DRV_DATA(dev); - int32_t reset_flags, prot_flags, unwanted_prot_flags; - - reset_flags = system_get_reset_flags(); - prot_flags = crec_flash_get_protect(); - unwanted_prot_flags = EC_FLASH_PROTECT_ALL_NOW | - EC_FLASH_PROTECT_ERROR_INCONSISTENT; - - /* - * If we have already jumped between images, an earlier image could - * have applied write protection. Nothing additional needs to be done. - */ - if (reset_flags & EC_RESET_FLAG_SYSJUMP) - return EC_SUCCESS; - - if (prot_flags & EC_FLASH_PROTECT_GPIO_ASSERTED) { - /* Protect the entire flash of host interface */ - flash_protect_banks(0, - CONFIG_FLASH_SIZE_BYTES / CONFIG_FLASH_BANK_SIZE, - FLASH_WP_HOST); - /* Protect the entire flash of DBGR interface */ - flash_protect_banks(0, - CONFIG_FLASH_SIZE_BYTES / CONFIG_FLASH_BANK_SIZE, - FLASH_WP_DBGR); - /* - * Write protect is asserted. If we want RO flash protected, - * protect it now. - */ - if ((prot_flags & EC_FLASH_PROTECT_RO_AT_BOOT) && - !(prot_flags & EC_FLASH_PROTECT_RO_NOW)) { - int rv = crec_flash_set_protect(EC_FLASH_PROTECT_RO_NOW, - EC_FLASH_PROTECT_RO_NOW); - if (rv) - return rv; - - /* Re-read flags */ - prot_flags = crec_flash_get_protect(); - } - } else { - /* Don't want RO flash protected */ - unwanted_prot_flags |= EC_FLASH_PROTECT_RO_NOW; - } - - /* If there are no unwanted flags, done */ - if (!(prot_flags & unwanted_prot_flags)) - return EC_SUCCESS; - - /* - * If the last reboot was a power-on reset, it should have cleared - * write-protect. If it didn't, then the flash write protect registers - * have been permanently committed and we can't fix that. - */ - if (reset_flags & EC_RESET_FLAG_POWER_ON) { - data->stuck_locked = 1; - return EC_ERROR_ACCESS_DENIED; - } else { - /* - * Set inconsistent flag, because there is no software - * reset can clear write-protect. - */ - data->inconsistent_locked = 1; - return EC_ERROR_ACCESS_DENIED; - } - - /* That doesn't return, so if we're still here that's an error */ - return EC_ERROR_UNKNOWN; -} - -static int cros_flash_it8xxx2_read(const struct device *dev, int offset, - int size, char *dst_data) -{ - ARG_UNUSED(dev); - - return flash_read(flash_controller, offset, dst_data, size); -} - -static int cros_flash_it8xxx2_write(const struct device *dev, int offset, - int size, const char *src_data) -{ - struct cros_flash_it8xxx2_data *const data = DRV_DATA(dev); - - if (data->all_protected) { - return -EACCES; - } - - /* - * If AP sends write flash command continuously, EC might not have - * chance to go back to hook task to touch watchdog. Reload watchdog - * on each flash write to prevent the reset. - */ - if (IS_ENABLED(CONFIG_PLATFORM_EC_WATCHDOG)) - watchdog_reload(); - - return flash_write(flash_controller, offset, src_data, size); -} - -static int cros_flash_it8xxx2_erase(const struct device *dev, int offset, - int size) -{ - struct cros_flash_it8xxx2_data *const data = DRV_DATA(dev); - int ret = 0; - - if (data->all_protected) { - return -EACCES; - } - /* - * Before the flash erasing, the interrupts should be disabled. In - * the flash erasing loop, the SHI interrupt should be enabled to - * handle AP's command, so irq_lock() is not used here. - */ - if (IS_ENABLED(CONFIG_ITE_IT8XXX2_INTC)) { - ite_intc_save_and_disable_interrupts(); - } - /* - * EC still need to handle AP's EC_CMD_GET_COMMS_STATUS command - * during erasing. - */ - if (IS_ENABLED(HAS_TASK_HOSTCMD) && - IS_ENABLED(CONFIG_HOST_COMMAND_STATUS)) { - irq_enable(DT_IRQN(DT_NODELABEL(shi))); - } - /* Always use sector erase command */ - for (; size > 0; size -= CONFIG_FLASH_ERASE_SIZE) { - ret = flash_erase(flash_controller, offset, - CONFIG_FLASH_ERASE_SIZE); - if (ret) - break; - - offset += CONFIG_FLASH_ERASE_SIZE; - /* - * If requested erase size is too large at one time on KGD - * flash, we need to reload watchdog to prevent the reset. - */ - if (IS_ENABLED(CONFIG_PLATFORM_EC_WATCHDOG) && (size > 0x10000)) - watchdog_reload(); - } - /* Restore interrupts */ - if (IS_ENABLED(CONFIG_ITE_IT8XXX2_INTC)) { - ite_intc_restore_interrupts(); - } - - return ret; -} - -static int cros_flash_it8xxx2_get_protect(const struct device *dev, int bank) -{ - ARG_UNUSED(dev); - - return IT83XX_GCTRL_EWPR0PFEC(FWP_REG(bank)) & FWP_MASK(bank); -} - -static uint32_t cros_flash_it8xxx2_get_protect_flags(const struct device *dev) -{ - struct cros_flash_it8xxx2_data *const data = DRV_DATA(dev); - uint32_t flags = 0; - - flags |= flash_check_wp(); - - if (data->all_protected) - flags |= EC_FLASH_PROTECT_ALL_NOW; - - /* Check if blocks were stuck locked at pre-init */ - if (data->stuck_locked) - flags |= EC_FLASH_PROTECT_ERROR_STUCK; - - /* Check if flash protection is in inconsistent state at pre-init */ - if (data->inconsistent_locked) - flags |= EC_FLASH_PROTECT_ERROR_INCONSISTENT; - - return flags; -} - -static int cros_flash_it8xxx2_protect_at_boot(const struct device *dev, - uint32_t new_flags) -{ - return -ENOTSUP; -} - -static int cros_flash_it8xxx2_protect_now(const struct device *dev, int all) -{ - struct cros_flash_it8xxx2_data *const data = DRV_DATA(dev); - - if (all) { - /* Protect the entire flash */ - flash_protect_banks(0, - CONFIG_FLASH_SIZE_BYTES / CONFIG_FLASH_BANK_SIZE, - FLASH_WP_EC); - data->all_protected = 1; - } else { - /* Protect the read-only section and persistent state */ - flash_protect_banks(WP_BANK_OFFSET, - WP_BANK_COUNT, FLASH_WP_EC); -#ifdef PSTATE_BANK - flash_protect_banks(PSTATE_BANK, - PSTATE_BANK_COUNT, FLASH_WP_EC); -#endif - } - - return EC_SUCCESS; -} - -/* cros ec flash driver registration */ -static const struct cros_flash_driver_api cros_flash_it8xxx2_driver_api = { - .init = cros_flash_it8xxx2_init, - .physical_read = cros_flash_it8xxx2_read, - .physical_write = cros_flash_it8xxx2_write, - .physical_erase = cros_flash_it8xxx2_erase, - .physical_get_protect = cros_flash_it8xxx2_get_protect, - .physical_get_protect_flags = cros_flash_it8xxx2_get_protect_flags, - .physical_protect_at_boot = cros_flash_it8xxx2_protect_at_boot, - .physical_protect_now = cros_flash_it8xxx2_protect_now, -}; - -static int flash_it8xxx2_init(const struct device *dev) -{ - ARG_UNUSED(dev); - - flash_controller = device_get_binding(FLASH_DEV_NAME); - if (!flash_controller) { - LOG_ERR("Fail to find %s", FLASH_DEV_NAME); - return -ENODEV; - } - - return 0; -} - -static struct cros_flash_it8xxx2_data cros_flash_data; - -DEVICE_DEFINE(cros_flash_it8xxx2_0, DT_INST_LABEL(0), flash_it8xxx2_init, NULL, - &cros_flash_data, NULL, PRE_KERNEL_1, - CONFIG_KERNEL_INIT_PRIORITY_DEVICE, - &cros_flash_it8xxx2_driver_api); diff --git a/zephyr/drivers/cros_flash/cros_flash_npcx.c b/zephyr/drivers/cros_flash/cros_flash_npcx.c deleted file mode 100644 index bb1bd12d89..0000000000 --- a/zephyr/drivers/cros_flash/cros_flash_npcx.c +++ /dev/null @@ -1,821 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define DT_DRV_COMPAT nuvoton_npcx_cros_flash - -#include <dt-bindings/clock/npcx_clock.h> -#include <drivers/cros_flash.h> -#include <drivers/clock_control.h> -#include <drivers/gpio.h> -#include <kernel.h> -#include <logging/log.h> -#include <soc.h> -#include <soc/nuvoton_npcx/reg_def_cros.h> -#include <sys/__assert.h> -#include "ec_tasks.h" -#include "flash.h" -#include "gpio.h" -#include "soc_miwu.h" -#include "spi_flash_reg.h" -#include "task.h" -#include "../drivers/flash/spi_nor.h" - -LOG_MODULE_REGISTER(cros_flash, LOG_LEVEL_ERR); - -static int all_protected; /* Has all-flash protection been requested? */ -static int addr_prot_start; -static int addr_prot_length; -static uint8_t flag_prot_inconsistent; -static uint8_t saved_sr1; -static uint8_t saved_sr2; - -#define CMD_READ_STATUS_REG 0x05 -#define CMD_READ_STATUS_REG2 0x35 - -/* Device config */ -struct cros_flash_npcx_config { - /* flash interface unit base address */ - uintptr_t base; - /* clock configuration */ - struct npcx_clk_cfg clk_cfg; - /* Flash size (Unit:bytes) */ - int size; - /* pinmux configuration */ - const uint8_t alts_size; - const struct npcx_alt *alts_list; -}; - -/* Device data */ -struct cros_flash_npcx_data { - /* flag of flash write protection */ - bool write_protectied; - /* mutex of flash interface controller */ - struct k_sem lock_sem; -}; - -/* TODO: Should we replace them with Kconfig variables */ -#define CONFIG_FLASH_WRITE_SIZE 0x1 /* minimum write size */ -#define CONFIG_FLASH_WRITE_IDEAL_SIZE 256 /* one page size for write */ - -/* TODO: It should be defined in the spi_nor.h in the zephyr repository */ -#define SPI_NOR_CMD_FAST_READ 0x0B - -/* Driver convenience defines */ -#define DRV_CONFIG(dev) ((const struct cros_flash_npcx_config *)(dev)->config) -#define DRV_DATA(dev) ((struct cros_flash_npcx_data *)(dev)->data) -#define HAL_INSTANCE(dev) (struct fiu_reg *)(DRV_CONFIG(dev)->base) - -/* cros ec flash local inline functions */ -static inline void cros_flash_npcx_mutex_lock(const struct device *dev) -{ - struct cros_flash_npcx_data *data = DRV_DATA(dev); - - k_sem_take(&data->lock_sem, K_FOREVER); -} - -static inline void cros_flash_npcx_mutex_unlock(const struct device *dev) -{ - struct cros_flash_npcx_data *data = DRV_DATA(dev); - - k_sem_give(&data->lock_sem); -} - -static inline void cros_flash_npcx_set_address(const struct device *dev, - uint32_t qspi_addr) -{ - struct fiu_reg *const inst = HAL_INSTANCE(dev); - uint8_t *addr = (uint8_t *)&qspi_addr; - - /* Write 3 bytes address to UMA registers */ - inst->UMA_AB2 = addr[2]; - inst->UMA_AB1 = addr[1]; - inst->UMA_AB0 = addr[0]; -} - -static inline void cros_flash_npcx_cs_level(const struct device *dev, int level) -{ - struct fiu_reg *const inst = HAL_INSTANCE(dev); - - /* Set chip select to high/low level */ - if (level == 0) - inst->UMA_ECTS &= ~BIT(NPCX_UMA_ECTS_SW_CS1); - else - inst->UMA_ECTS |= BIT(NPCX_UMA_ECTS_SW_CS1); -} - -static inline void cros_flash_npcx_exec_cmd(const struct device *dev, - uint8_t code, uint8_t cts) -{ - struct fiu_reg *const inst = HAL_INSTANCE(dev); - -#ifdef CONFIG_ASSERT - struct cros_flash_npcx_data *data = DRV_DATA(dev); - - /* Flash mutex must be held while executing UMA commands */ - __ASSERT((k_sem_count_get(&data->lock_sem) == 0), "UMA is not locked"); -#endif - - /* set UMA_CODE */ - inst->UMA_CODE = code; - /* execute UMA flash transaction */ - inst->UMA_CTS = cts; - while (IS_BIT_SET(inst->UMA_CTS, NPCX_UMA_CTS_EXEC_DONE)) - ; -} - -static inline void cros_flash_npcx_burst_read(const struct device *dev, - char *dst_data, int dst_size) -{ - struct fiu_reg *const inst = HAL_INSTANCE(dev); - - /* Burst read transaction */ - for (int idx = 0; idx < dst_size; idx++) { - /* 1101 0101 - EXEC, RD, NO CMD, NO ADDR, 4 bytes */ - inst->UMA_CTS = UMA_CODE_RD_BYTE(1); - /* wait for UMA to complete */ - while (IS_BIT_SET(inst->UMA_CTS, NPCX_UMA_CTS_EXEC_DONE)) - ; - /* Get read transaction results*/ - dst_data[idx] = inst->UMA_DB0; - } -} - -static inline int cros_flash_npcx_wait_busy_bit_clear(const struct device *dev) -{ - struct fiu_reg *const inst = HAL_INSTANCE(dev); - int wait_period = 10; /* 10 us period t0 check status register */ - int timeout = (10 * USEC_PER_SEC) / wait_period; /* 10 seconds */ - - do { - /* Read status register */ - inst->UMA_CTS = UMA_CODE_RD_BYTE(1); - while (IS_BIT_SET(inst->UMA_CTS, NPCX_UMA_CTS_EXEC_DONE)) - ; - /* Status bit is clear */ - if ((inst->UMA_DB0 & SPI_NOR_WIP_BIT) == 0) - break; - k_usleep(wait_period); - } while (--timeout); /* Wait for busy bit clear */ - - if (timeout) { - return 0; - } else { - return -ETIMEDOUT; - } -} - -/* cros ec flash local functions */ -static int cros_flash_npcx_wait_ready(const struct device *dev) -{ - int ret = 0; - - /* Drive CS to low */ - cros_flash_npcx_cs_level(dev, 0); - - /* Command for Read status register of flash */ - cros_flash_npcx_exec_cmd(dev, SPI_NOR_CMD_RDSR, UMA_CODE_CMD_ONLY); - /* Wait busy bit is clear */ - ret = cros_flash_npcx_wait_busy_bit_clear(dev); - /* Drive CS to low */ - cros_flash_npcx_cs_level(dev, 1); - - return ret; -} - -static int cros_flash_npcx_set_write_enable(const struct device *dev) -{ - struct fiu_reg *const inst = HAL_INSTANCE(dev); - int ret; - - /* Wait for previous operation to complete */ - ret = cros_flash_npcx_wait_ready(dev); - if (ret != 0) - return ret; - - /* Write enable command */ - cros_flash_npcx_exec_cmd(dev, SPI_NOR_CMD_WREN, UMA_CODE_CMD_ONLY); - - /* Wait for flash is not busy */ - ret = cros_flash_npcx_wait_ready(dev); - if (ret != 0) - return ret; - - if ((inst->UMA_DB0 & SPI_NOR_WEL_BIT) != 0) - return 0; - else - return -EINVAL; -} - -static void cros_flash_npcx_burst_write(const struct device *dev, - unsigned int dest_addr, - unsigned int bytes, - const char *src_data) -{ - /* Chip Select down */ - cros_flash_npcx_cs_level(dev, 0); - - /* Set write address */ - cros_flash_npcx_set_address(dev, dest_addr); - /* Start programming */ - cros_flash_npcx_exec_cmd(dev, SPI_NOR_CMD_PP, UMA_CODE_CMD_WR_ADR); - for (int i = 0; i < bytes; i++) { - cros_flash_npcx_exec_cmd(dev, *src_data, UMA_CODE_CMD_WR_ONLY); - src_data++; - } - - /* Chip Select up */ - cros_flash_npcx_cs_level(dev, 1); -} - -static int cros_flash_npcx_program_bytes(const struct device *dev, - uint32_t offset, uint32_t bytes, - const uint8_t *src_data) -{ - int write_size; - int ret = 0; - - while (bytes > 0) { - /* Write length can not go beyond the end of the flash page */ - write_size = MIN(bytes, - CONFIG_FLASH_WRITE_IDEAL_SIZE - - (offset & - (CONFIG_FLASH_WRITE_IDEAL_SIZE - 1))); - - /* Enable write */ - ret = cros_flash_npcx_set_write_enable(dev); - if (ret != 0) - return ret; - - /* Executr UMA burst write transaction */ - cros_flash_npcx_burst_write(dev, offset, write_size, src_data); - - /* Wait write completed */ - ret = cros_flash_npcx_wait_ready(dev); - if (ret != 0) - return ret; - - src_data += write_size; - offset += write_size; - bytes -= write_size; - } - - return ret; -} - -static int cros_flash_npcx_get_status_reg(const struct device *dev, - char cmd_code, char *data) -{ - int ret = 0; - struct fiu_reg *const inst = HAL_INSTANCE(dev); - - if (data == 0) { - return -EINVAL; - } - - /* Lock flash interface device during reading status register */ - cros_flash_npcx_mutex_lock(dev); - - cros_flash_npcx_exec_cmd(dev, cmd_code, UMA_CODE_CMD_RD_BYTE(1)); - *data = inst->UMA_DB0; - /* Unlock flash interface device */ - cros_flash_npcx_mutex_unlock(dev); - - return ret; -} - -static int cros_flash_npcx_set_status_reg(const struct device *dev, char *data) -{ - int ret = 0; - struct fiu_reg *const inst = HAL_INSTANCE(dev); - - /* Lock flash interface device */ - cros_flash_npcx_mutex_lock(dev); - /* Enable write */ - ret = cros_flash_npcx_set_write_enable(dev); - if (ret != 0) - return ret; - - inst->UMA_DB0 = data[0]; - inst->UMA_DB1 = data[1]; - /* Write status register 1/2 */ - cros_flash_npcx_exec_cmd(dev, SPI_NOR_CMD_WRSR, - UMA_CODE_CMD_WR_BYTE(2)); - /* Unlock flash interface device */ - cros_flash_npcx_mutex_unlock(dev); - - return ret; -} - -static int cros_flash_npcx_write_protection_set(const struct device *dev, - bool enable) -{ - int ret = 0; - - /* Write protection can be cleared only by core domain reset */ - if (!enable) { - LOG_ERR("WP can be disabled only via core domain reset "); - return -ENOTSUP; - } - /* Lock flash interface device */ - cros_flash_npcx_mutex_lock(dev); - ret = npcx_pinctrl_flash_write_protect_set(); - /* Unlock flash interface device */ - cros_flash_npcx_mutex_unlock(dev); - - return ret; -} - -static int cros_flash_npcx_write_protection_is_set(const struct device *dev) -{ - return npcx_pinctrl_flash_write_protect_is_set(); -} - -static int cros_flash_npcx_uma_lock(const struct device *dev, bool enable) -{ - struct fiu_reg *const inst = HAL_INSTANCE(dev); - - if (enable) { - inst->UMA_ECTS |= BIT(NPCX_UMA_ECTS_UMA_LOCK); - } else { - inst->UMA_ECTS &= ~BIT(NPCX_UMA_ECTS_UMA_LOCK); - } - - return 0; -} - -static int flash_get_status1(const struct device *dev) -{ - uint8_t reg; - - if (all_protected) - return saved_sr1; - - /* Lock physical flash operations */ - crec_flash_lock_mapped_storage(1); - - cros_flash_npcx_get_status_reg(dev, CMD_READ_STATUS_REG, ®); - - /* Unlock physical flash operations */ - crec_flash_lock_mapped_storage(0); - - return reg; -} - -static int flash_get_status2(const struct device *dev) -{ - uint8_t reg; - - if (all_protected) - return saved_sr1; - - /* Lock physical flash operations */ - crec_flash_lock_mapped_storage(1); - - cros_flash_npcx_get_status_reg(dev, CMD_READ_STATUS_REG2, ®); - - /* Unlock physical flash operations */ - crec_flash_lock_mapped_storage(0); - - return reg; -} - -static int flash_write_status_reg(const struct device *dev, uint8_t *data) -{ - return cros_flash_npcx_set_status_reg(dev, data); -} - -static int is_int_flash_protected(const struct device *dev) -{ - return cros_flash_npcx_write_protection_is_set(dev); -} - -static void flash_protect_int_flash(const struct device *dev, int enable) -{ - /* - * Please notice the type of WP_IF bit is R/W1S. Once it's set, - * only rebooting EC can clear it. - */ - if (enable) - cros_flash_npcx_write_protection_set(dev, enable); -} - -static void flash_uma_lock(const struct device *dev, int enable) -{ - if (enable && !all_protected) { - /* - * Store SR1 / SR2 for later use since we're about to lock - * out all access (including read access) to these regs. - */ - saved_sr1 = flash_get_status1(dev); - saved_sr2 = flash_get_status2(dev); - } - - cros_flash_npcx_uma_lock(dev, enable); - all_protected = enable; -} - -static int flash_set_status_for_prot(const struct device *dev, int reg1, - int reg2) -{ - uint8_t regs[2]; - - /* - * Writing SR regs will fail if our UMA lock is enabled. If WP - * is deasserted then remove the lock and allow the write. - */ - if (all_protected) { - if (is_int_flash_protected(dev)) - return EC_ERROR_ACCESS_DENIED; - - if (crec_flash_get_protect() & EC_FLASH_PROTECT_GPIO_ASSERTED) - return EC_ERROR_ACCESS_DENIED; - flash_uma_lock(dev, 0); - } - - /* - * If WP# is active and ec doesn't protect the status registers of - * internal spi-flash, protect it now before setting them. - */ -#ifdef CONFIG_WP_ACTIVE_HIGH - flash_protect_int_flash(dev, gpio_get_level(GPIO_WP)); -#else - flash_protect_int_flash(dev, !gpio_get_level(GPIO_WP_L)); -#endif /*_CONFIG_WP_ACTIVE_HIGH_*/ - - /* Lock physical flash operations */ - crec_flash_lock_mapped_storage(1); - - regs[0] = reg1; - regs[1] = reg2; - flash_write_status_reg(dev, regs); - - /* Unlock physical flash operations */ - crec_flash_lock_mapped_storage(0); - - spi_flash_reg_to_protect(reg1, reg2, &addr_prot_start, - &addr_prot_length); - - return EC_SUCCESS; -} - -static int flash_check_prot_reg(const struct device *dev, unsigned int offset, - unsigned int bytes) -{ - unsigned int start; - unsigned int len; - uint8_t sr1, sr2; - int rv = EC_SUCCESS; - - /* - * If WP# is active and ec doesn't protect the status registers of - * internal spi-flash, protect it now. - */ -#ifdef CONFIG_WP_ACTIVE_HIGH - flash_protect_int_flash(dev, gpio_get_level(GPIO_WP)); -#else - flash_protect_int_flash(dev, !gpio_get_level(GPIO_WP_L)); -#endif /* CONFIG_WP_ACTIVE_HIGH */ - - sr1 = flash_get_status1(dev); - sr2 = flash_get_status2(dev); - - /* Invalid value */ - if (offset + bytes > CONFIG_FLASH_SIZE_BYTES) - return EC_ERROR_INVAL; - - /* Compute current protect range */ - rv = spi_flash_reg_to_protect(sr1, sr2, &start, &len); - if (rv) - return rv; - - /* Check if ranges overlap */ - if (MAX(start, offset) < MIN(start + len, offset + bytes)) - return EC_ERROR_ACCESS_DENIED; - - return EC_SUCCESS; -} - -static int flash_write_prot_reg(const struct device *dev, unsigned int offset, - unsigned int bytes, int hw_protect) -{ - int rv; - uint8_t sr1 = flash_get_status1(dev); - uint8_t sr2 = flash_get_status2(dev); - - /* Invalid values */ - if (offset + bytes > CONFIG_FLASH_SIZE_BYTES) - return EC_ERROR_INVAL; - - /* Compute desired protect range */ - rv = spi_flash_protect_to_reg(offset, bytes, &sr1, &sr2); - if (rv) - return rv; - - if (hw_protect) - sr1 |= SPI_FLASH_SR1_SRP0; - - return flash_set_status_for_prot(dev, sr1, sr2); -} - -static int flash_check_prot_range(unsigned int offset, unsigned int bytes) -{ - /* Invalid value */ - if (offset + bytes > CONFIG_FLASH_SIZE_BYTES) - return EC_ERROR_INVAL; - - /* Check if ranges overlap */ - if (MAX(addr_prot_start, offset) < - MIN(addr_prot_start + addr_prot_length, offset + bytes)) - return EC_ERROR_ACCESS_DENIED; - - return EC_SUCCESS; -} - -/* cros ec flash api functions */ -static int cros_flash_npcx_init(const struct device *dev) -{ - const struct cros_flash_npcx_config *const config = DRV_CONFIG(dev); - struct cros_flash_npcx_data *data = DRV_DATA(dev); - - /* initialize mutux for flash interface controller */ - k_sem_init(&data->lock_sem, 1, 1); - - /* Configure pin-mux for FIU device */ - npcx_pinctrl_mux_configure(config->alts_list, config->alts_size, 1); - - /* - * Protect status registers of internal spi-flash if WP# is active - * during ec initialization. - */ -#ifdef CONFIG_WP_ACTIVE_HIGH - flash_protect_int_flash(dev, gpio_get_level(GPIO_WP)); -#else - flash_protect_int_flash(dev, !gpio_get_level(GPIO_WP_L)); -#endif /*CONFIG_WP_ACTIVE_HIGH */ - - /* Initialize UMA to unlocked */ - flash_uma_lock(dev, 0); - - return 0; -} - -static int cros_flash_npcx_read(const struct device *dev, int offset, int size, - char *dst_data) -{ - int ret = 0; - - /* Unlock flash interface device during reading flash */ - cros_flash_npcx_mutex_lock(dev); - - /* Chip Select down */ - cros_flash_npcx_cs_level(dev, 0); - - /* Set read address */ - cros_flash_npcx_set_address(dev, offset); - /* Start with fast read command (skip one dummy byte) */ - cros_flash_npcx_exec_cmd(dev, SPI_NOR_CMD_FAST_READ, - UMA_CODE_CMD_ADR_WR_BYTE(1)); - /* Execute burst read */ - cros_flash_npcx_burst_read(dev, dst_data, size); - - /* Chip Select up */ - cros_flash_npcx_cs_level(dev, 1); - - /* Unlock flash interface device */ - cros_flash_npcx_mutex_unlock(dev); - - return ret; -} - -static int cros_flash_npcx_write(const struct device *dev, int offset, int size, - const char *src_data) -{ - struct cros_flash_npcx_data *const data = DRV_DATA(dev); - int ret = 0; - - /* check protection */ - if (all_protected) - return EC_ERROR_ACCESS_DENIED; - - /* check protection */ - if (flash_check_prot_range(offset, size)) - return EC_ERROR_ACCESS_DENIED; - - /* Is write protection enabled? */ - if (data->write_protectied) { - return -EACCES; - } - - /* Invalid data pointer? */ - if (src_data == 0) { - return -EINVAL; - } - - /* Unlock flash interface device during writing flash */ - cros_flash_npcx_mutex_lock(dev); - - while (size > 0) { - /* First write multiples of 256, then (size % 256) last */ - int write_len = - ((size % CONFIG_FLASH_WRITE_IDEAL_SIZE) == size) ? - size : - CONFIG_FLASH_WRITE_IDEAL_SIZE; - - ret = cros_flash_npcx_program_bytes(dev, offset, write_len, - src_data); - if (ret != 0) - break; - - src_data += write_len; - offset += write_len; - size -= write_len; - } - - /* Unlock flash interface device */ - cros_flash_npcx_mutex_unlock(dev); - - return ret; -} - -static int cros_flash_npcx_erase(const struct device *dev, int offset, int size) -{ - const struct cros_flash_npcx_config *const config = DRV_CONFIG(dev); - struct cros_flash_npcx_data *const data = DRV_DATA(dev); - int ret = 0; - - /* check protection */ - if (all_protected) - return EC_ERROR_ACCESS_DENIED; - - /* check protection */ - if (flash_check_prot_range(offset, size)) - return EC_ERROR_ACCESS_DENIED; - - /* Is write protection enabled? */ - if (data->write_protectied) { - return -EACCES; - } - /* affected region should be within device */ - if (offset < 0 || (offset + size) > config->size) { - LOG_ERR("Flash erase address or size exceeds expected values. " - "Addr: 0x%lx size %zu", - (long)offset, size); - return -EINVAL; - } - - /* address must be aligned to erase size */ - if ((offset % CONFIG_FLASH_ERASE_SIZE) != 0) { - return -EINVAL; - } - - /* Erase size must be a non-zero multiple of sectors */ - if ((size == 0) || (size % CONFIG_FLASH_ERASE_SIZE) != 0) { - return -EINVAL; - } - - /* Unlock flash interface device during erasing flash */ - cros_flash_npcx_mutex_lock(dev); - - /* Alignment has been checked in upper layer */ - for (; size > 0; size -= CONFIG_FLASH_ERASE_SIZE, - offset += CONFIG_FLASH_ERASE_SIZE) { - - /* Enable write */ - ret = cros_flash_npcx_set_write_enable(dev); - if (ret != 0) - break; - - /* Set erase address */ - cros_flash_npcx_set_address(dev, offset); - /* Start erasing */ - cros_flash_npcx_exec_cmd(dev, SPI_NOR_CMD_BE, UMA_CODE_CMD_ADR); - - /* Wait erase completed */ - ret = cros_flash_npcx_wait_ready(dev); - if (ret != 0) { - break; - } - } - - /* Unlock flash interface device */ - cros_flash_npcx_mutex_unlock(dev); - - return ret; -} - -static int cros_flash_npcx_get_protect(const struct device *dev, int bank) -{ - uint32_t addr = bank * CONFIG_FLASH_BANK_SIZE; - - return flash_check_prot_reg(dev, addr, CONFIG_FLASH_BANK_SIZE); -} - -static uint32_t cros_flash_npcx_get_protect_flags(const struct device *dev) -{ - uint32_t flags = 0; - - /* Check if WP region is protected in status register */ - if (flash_check_prot_reg(dev, WP_BANK_OFFSET * CONFIG_FLASH_BANK_SIZE, - WP_BANK_COUNT * CONFIG_FLASH_BANK_SIZE)) - flags |= EC_FLASH_PROTECT_RO_AT_BOOT; - - /* - * TODO: If status register protects a range, but SRP0 is not set, - * flags should indicate EC_FLASH_PROTECT_ERROR_INCONSISTENT. - */ - if (flag_prot_inconsistent) - flags |= EC_FLASH_PROTECT_ERROR_INCONSISTENT; - - /* Read all-protected state from our shadow copy */ - if (all_protected) - flags |= EC_FLASH_PROTECT_ALL_NOW; - - return flags; -} - -static int cros_flash_npcx_protect_at_boot(const struct device *dev, - uint32_t new_flags) -{ - int ret; - - if ((new_flags & (EC_FLASH_PROTECT_RO_AT_BOOT | - EC_FLASH_PROTECT_ALL_AT_BOOT)) == 0) { - /* Clear protection bits in status register */ - return flash_set_status_for_prot(dev, 0, 0); - } - - ret = flash_write_prot_reg(dev, CONFIG_WP_STORAGE_OFF, - CONFIG_WP_STORAGE_SIZE, 1); - - /* - * Set UMA_LOCK bit for locking all UMA transaction. - * But we still can read directly from flash mapping address - */ - if (new_flags & EC_FLASH_PROTECT_ALL_AT_BOOT) - flash_uma_lock(dev, 1); - - return ret; -} - -static int cros_flash_npcx_protect_now(const struct device *dev, int all) -{ - if (all) { - /* - * Set UMA_LOCK bit for locking all UMA transaction. - * But we still can read directly from flash mapping address - */ - flash_uma_lock(dev, 1); - } else { - /* TODO: Implement RO "now" protection */ - } - - return EC_SUCCESS; -} - -/* cros ec flash driver registration */ -static const struct cros_flash_driver_api cros_flash_npcx_driver_api = { - .init = cros_flash_npcx_init, - .physical_read = cros_flash_npcx_read, - .physical_write = cros_flash_npcx_write, - .physical_erase = cros_flash_npcx_erase, - .physical_get_protect = cros_flash_npcx_get_protect, - .physical_get_protect_flags = cros_flash_npcx_get_protect_flags, - .physical_protect_at_boot = cros_flash_npcx_protect_at_boot, - .physical_protect_now = cros_flash_npcx_protect_now, -}; - -static int flash_npcx_init(const struct device *dev) -{ - const struct cros_flash_npcx_config *const config = DRV_CONFIG(dev); - const struct device *clk_dev = DEVICE_DT_GET(NPCX_CLK_CTRL_NODE); - - int ret; - - /* Turn on device clock first and get source clock freq. */ - ret = clock_control_on(clk_dev, - (clock_control_subsys_t *)&config->clk_cfg); - if (ret < 0) { - LOG_ERR("Turn on FIU clock fail %d", ret); - return ret; - } - - return ret; -} - -static const struct npcx_alt cros_flash_alts[] = NPCX_DT_ALT_ITEMS_LIST(0); -static const struct cros_flash_npcx_config cros_flash_cfg = { - .base = DT_INST_REG_ADDR(0), - .clk_cfg = NPCX_DT_CLK_CFG_ITEM(0), - .size = DT_INST_PROP(0, size), - .alts_size = ARRAY_SIZE(cros_flash_alts), - .alts_list = cros_flash_alts, -}; - -static struct cros_flash_npcx_data cros_flash_data; - -DEVICE_DT_INST_DEFINE(0, flash_npcx_init, NULL, &cros_flash_data, - &cros_flash_cfg, PRE_KERNEL_1, - CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, - &cros_flash_npcx_driver_api); diff --git a/zephyr/drivers/cros_kb_raw/CMakeLists.txt b/zephyr/drivers/cros_kb_raw/CMakeLists.txt deleted file mode 100644 index a9ef2b4bb2..0000000000 --- a/zephyr/drivers/cros_kb_raw/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library_sources_ifdef(CONFIG_CROS_KB_RAW_NPCX cros_kb_raw_npcx.c) -zephyr_library_sources_ifdef(CONFIG_CROS_KB_RAW_ITE cros_kb_raw_ite.c) diff --git a/zephyr/drivers/cros_kb_raw/Kconfig b/zephyr/drivers/cros_kb_raw/Kconfig deleted file mode 100644 index a037cdd451..0000000000 --- a/zephyr/drivers/cros_kb_raw/Kconfig +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2021 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -menuconfig CROS_KB_RAW_NPCX - bool "Nuvoton NPCX raw-keyboard-scan driver for the Zephyr shim" - depends on SOC_FAMILY_NPCX - default y - help - This option enables a driver for providing raw access to the - keyboard-scan peripheral in the chip. This is used instead of the - kscan interface so we can continue to use most of the existing - keyboard-scanning code in ECOS. - -if CROS_KB_RAW_NPCX - -config CROS_KB_RAW_NPCX_KSO_HIGH_DRIVE - bool "Enable quasi-bidirectional buffers for KSO pins" - help - This option enables quasi-bidirectional buffers for KSO pins. The - low-impedance high drive is active when ec changes the output data - buffers from 0 to 1, thereby reducing the low-to-high transition time. - -endif # CROS_KB_RAW_NPCX - -menuconfig CROS_KB_RAW_ITE - bool "ITE raw-keyboard-scan driver for the Zephyr shim" - depends on SOC_FAMILY_RISCV_ITE - default y - help - This option enables a driver for providing raw access to the - keyboard-scan peripheral in the chip. This is used instead of the - kscan interface so we can continue to use most of the existing - keyboard-scanning code in ECOS. diff --git a/zephyr/drivers/cros_kb_raw/cros_kb_raw_ite.c b/zephyr/drivers/cros_kb_raw/cros_kb_raw_ite.c deleted file mode 100644 index 85b2a1a8ee..0000000000 --- a/zephyr/drivers/cros_kb_raw/cros_kb_raw_ite.c +++ /dev/null @@ -1,187 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define DT_DRV_COMPAT ite_it8xxx2_cros_kb_raw - -#include <assert.h> -#include <drivers/cros_kb_raw.h> -#include <drivers/clock_control.h> -#include <drivers/gpio.h> -#include <kernel.h> -#include <soc.h> -#include <soc/ite_it8xxx2/reg_def_cros.h> - -#include "ec_tasks.h" -#include "keyboard_raw.h" -#include "task.h" - -#include <logging/log.h> -LOG_MODULE_REGISTER(cros_kb_raw, LOG_LEVEL_ERR); - -#define KSOH_PIN_MASK (((1 << (KEYBOARD_COLS_MAX - 8)) - 1) & 0xff) - -/* Device config */ -struct cros_kb_raw_ite_config { - /* keyboard scan controller base address */ - uintptr_t base; - /* Keyboard scan input (KSI) wake-up irq */ - int irq; -}; - -/* Driver convenience defines */ -#define DRV_CONFIG(dev) ((const struct cros_kb_raw_ite_config *)(dev)->config) -#define HAL_INSTANCE(dev) (struct kbs_reg *)(DRV_CONFIG(dev)->base) - -static int kb_raw_ite_init(const struct device *dev) -{ - ARG_UNUSED(dev); - - /* Clock default is on */ - return 0; -} - -/* Cros ec keyboard raw api functions */ -static int cros_kb_raw_ite_enable_interrupt(const struct device *dev, - int enable) -{ - const struct cros_kb_raw_ite_config *const config = DRV_CONFIG(dev); - - if (enable) { - ECREG(IT8XXX2_WUC_WUESR3) = 0xFF; - ite_intc_isr_clear(config->irq); - irq_enable(config->irq); - } else { - irq_disable(config->irq); - } - - return 0; -} - -static int cros_kb_raw_ite_read_row(const struct device *dev) -{ - struct kbs_reg *const inst = HAL_INSTANCE(dev); - - /* Bits are active-low, so invert returned levels */ - return ((inst->KBS_KSI) ^ 0xff); -} - -static int cros_kb_raw_ite_drive_column(const struct device *dev, int col) -{ - int mask; - unsigned int key; - struct kbs_reg *const inst = HAL_INSTANCE(dev); - - /* Tri-state all outputs */ - if (col == KEYBOARD_COLUMN_NONE) - mask = 0xffff; - /* Assert all outputs */ - else if (col == KEYBOARD_COLUMN_ALL) - mask = 0; - /* Assert a single output */ - else - mask = 0xffff ^ BIT(col); -#ifdef CONFIG_PLATFORM_EC_KEYBOARD_COL2_INVERTED - /* KSO[2] is inverted. */ - mask ^= BIT(2); -#endif - inst->KBS_KSOL = mask & 0xff; - /* critical section with interrupts off */ - key = irq_lock(); - /* - * Because IT8XXX2_KBS_KSOH1 register is shared by keyboard scan - * out and GPIO output mode, so we don't drive all KSOH pins - * here (this depends on how many keyboard matrix output pin - * we are using). - */ - inst->KBS_KSOH1 = ((inst->KBS_KSOH1) & ~KSOH_PIN_MASK) | - ((mask >> 8) & KSOH_PIN_MASK); - /* restore interrupts */ - irq_unlock(key); - - return 0; -} - -static void cros_kb_raw_ite_ksi_isr(const struct device *dev) -{ - ARG_UNUSED(dev); - - /* - * We clear IT8XXX2_IRQ_WKINTC irq status in - * ite_intc_irq_handler(), after interrupt was fired. - */ - /* W/C wakeup interrupt status for KSI[0-7] */ - ECREG(IT8XXX2_WUC_WUESR3) = 0xFF; - - /* Wake-up keyboard scan task */ - task_wake(TASK_ID_KEYSCAN); -} - -static int cros_kb_raw_ite_init(const struct device *dev) -{ - unsigned int key; - const struct cros_kb_raw_ite_config *const config = DRV_CONFIG(dev); - struct kbs_reg *const inst = HAL_INSTANCE(dev); - - /* Ensure top-level interrupt is disabled */ - cros_kb_raw_ite_enable_interrupt(dev, 0); - - /* - * bit2, Setting 1 enables the internal pull-up of the KSO[15:0] pins. - * To pull up KSO[17:16], set the GPCR registers of their - * corresponding GPIO ports. - * bit0, Setting 1 enables the open-drain mode of the KSO[17:0] pins. - */ - inst->KBS_KSOCTRL = (IT8XXX2_KBS_KSOPU | IT8XXX2_KBS_KSOOD); - /* bit2, 1 enables the internal pull-up of the KSI[7:0] pins. */ - inst->KBS_KSICTRL = IT8XXX2_KBS_KSIPU; -#ifdef CONFIG_PLATFORM_EC_KEYBOARD_COL2_INVERTED - /* KSO[2] output high, others output low. */ - inst->KBS_KSOL = BIT(2); - /* Enable KSO2's push-pull */ - inst->KBS_KSOLGCTRL |= IT8XXX2_KBS_KSO2GCTRL; - inst->KBS_KSOLGOEN |= IT8XXX2_KBS_KSO2GOEN; -#else - /* KSO[7:0] pins output low. */ - inst->KBS_KSOL = 0x00; -#endif - /* critical section with interrupts off */ - key = irq_lock(); - /* - * KSO[COLS_MAX:8] pins low. - * NOTE: KSO[15:8] pins can part be enabled for keyboard function and - * rest be configured as GPIO output mode. In this case that we - * disable the ISR in critical section to avoid race condition. - */ - inst->KBS_KSOH1 &= ~KSOH_PIN_MASK; - /* restore interrupts */ - irq_unlock(key); - /* Select falling-edge triggered of wakeup interrupt for KSI[0-7] */ - ECREG(IT8XXX2_WUC_WUEMR3) = 0xFF; - /* W/C wakeup interrupt status for KSI[0-7] */ - ECREG(IT8XXX2_WUC_WUESR3) = 0xFF; - ite_intc_isr_clear(config->irq); - /* Enable wakeup interrupt for KSI[0-7] */ - ECREG(IT8XXX2_WUC_WUENR3) = 0xFF; - - IRQ_CONNECT(DT_INST_IRQN(0), 0, cros_kb_raw_ite_ksi_isr, NULL, 0); - - return 0; -} - -static const struct cros_kb_raw_driver_api cros_kb_raw_ite_driver_api = { - .init = cros_kb_raw_ite_init, - .drive_colum = cros_kb_raw_ite_drive_column, - .read_rows = cros_kb_raw_ite_read_row, - .enable_interrupt = cros_kb_raw_ite_enable_interrupt, -}; - -static const struct cros_kb_raw_ite_config cros_kb_raw_cfg = { - .base = DT_INST_REG_ADDR(0), - .irq = DT_INST_IRQN(0), -}; - -DEVICE_DT_INST_DEFINE(0, kb_raw_ite_init, NULL, NULL, &cros_kb_raw_cfg, - PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, - &cros_kb_raw_ite_driver_api); diff --git a/zephyr/drivers/cros_kb_raw/cros_kb_raw_npcx.c b/zephyr/drivers/cros_kb_raw/cros_kb_raw_npcx.c deleted file mode 100644 index 00965b74ca..0000000000 --- a/zephyr/drivers/cros_kb_raw/cros_kb_raw_npcx.c +++ /dev/null @@ -1,241 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define DT_DRV_COMPAT nuvoton_npcx_cros_kb_raw - -#include <assert.h> -#include <dt-bindings/clock/npcx_clock.h> -#include <drivers/cros_kb_raw.h> -#include <drivers/clock_control.h> -#include <drivers/gpio.h> -#include <kernel.h> -#include <soc.h> -#include <soc/nuvoton_npcx/reg_def_cros.h> - -#include "ec_tasks.h" -#include "keyboard_raw.h" -#include "soc_miwu.h" -#include "task.h" - -#include <logging/log.h> -LOG_MODULE_REGISTER(cros_kb_raw, LOG_LEVEL_ERR); - -#define NPCX_MAX_KEY_COLS 18 /* Maximum rows of keyboard matrix */ -#define NPCX_MAX_KEY_ROWS 8 /* Maximum columns of keyboard matrix */ -#define NPCX_KB_ROW_MASK (BIT(NPCX_MAX_KEY_ROWS) - 1) - -/* Device config */ -struct cros_kb_raw_npcx_config { - /* keyboard scan controller base address */ - uintptr_t base; - /* clock configuration */ - struct npcx_clk_cfg clk_cfg; - /* pinmux configuration */ - const uint8_t alts_size; - const struct npcx_alt *alts_list; - /* Keyboard scan input (KSI) wake-up irq */ - int irq; - /* Size of keyboard inputs-wui mapping array */ - int wui_size; - /* Mapping table between keyboard inputs and wui */ - struct npcx_wui wui_maps[]; -}; - -/* Driver convenience defines */ -#define DRV_CONFIG(dev) ((const struct cros_kb_raw_npcx_config *)(dev)->config) -#define HAL_INSTANCE(dev) (struct kbs_reg *)(DRV_CONFIG(dev)->base) - -/* Keyboard Scan local functions */ -static struct miwu_dev_callback ksi_callback[NPCX_MAX_KEY_ROWS]; - -static void kb_raw_npcx_init_ksi_wui_callback( - const struct device *dev, struct miwu_dev_callback *callback, - const struct npcx_wui *wui, miwu_dev_callback_handler_t handler) -{ - /* KSI signal which has no wake-up input source */ - if (wui->table == NPCX_MIWU_TABLE_NONE) - return; - - /* Install callback function */ - npcx_miwu_init_dev_callback(callback, wui, handler, dev); - npcx_miwu_manage_dev_callback(callback, 1); - - /* Configure MIWU setting and enable its interrupt */ - npcx_miwu_interrupt_configure(wui, NPCX_MIWU_MODE_EDGE, - NPCX_MIWU_TRIG_BOTH); - npcx_miwu_irq_enable(wui); -} - -static int kb_raw_npcx_init(const struct device *dev) -{ - const struct cros_kb_raw_npcx_config *const config = DRV_CONFIG(dev); - const struct device *clk_dev = DEVICE_DT_GET(NPCX_CLK_CTRL_NODE); - int ret; - - /* Turn on device clock first and get source clock freq. */ - ret = clock_control_on(clk_dev, - (clock_control_subsys_t *)&config->clk_cfg); - if (ret < 0) { - LOG_ERR("Turn on KSCAN clock fail %d", ret); - return ret; - } - - return 0; -} - -/* Cros ec keyboard raw api functions */ -static int cros_kb_raw_npcx_enable_interrupt(const struct device *dev, - int enable) -{ - const struct cros_kb_raw_npcx_config *const config = DRV_CONFIG(dev); - - if (enable) - irq_enable(config->irq); - else - irq_disable(config->irq); - - return 0; -} - -static int cros_kb_raw_npcx_read_row(const struct device *dev) -{ - struct kbs_reg *const inst = HAL_INSTANCE(dev); - int val; - - val = inst->KBSIN; - LOG_DBG("rows raw %02x", val); - - /* 1 means key pressed, otherwise means key released. */ - return (~val & NPCX_KB_ROW_MASK); -} - -static int cros_kb_raw_npcx_drive_column(const struct device *dev, int col) -{ - struct kbs_reg *const inst = HAL_INSTANCE(dev); - - /* - * Nuvoton 'Keyboard Scan' module supports 18x8 matrix - * It also support automatic scan functionality. - */ - uint32_t mask, col_out; - - /* Add support for CONFIG_KEYBOARD_KSO_BASE shifting */ - col_out = col + CONFIG_KEYBOARD_KSO_BASE; - - /* Drive all lines to high. ie. Key detection is disabled. */ - if (col == KEYBOARD_COLUMN_NONE) { - mask = ~0; - if (IS_ENABLED(CONFIG_PLATFORM_EC_KEYBOARD_COL2_INVERTED)) { - gpio_set_level(GPIO_KBD_KSO2, 0); - } - } - /* Drive all lines to low for detection any key press */ - else if (col == KEYBOARD_COLUMN_ALL) { - mask = ~(BIT(keyboard_cols) - 1); - if (IS_ENABLED(CONFIG_PLATFORM_EC_KEYBOARD_COL2_INVERTED)) { - gpio_set_level(GPIO_KBD_KSO2, 1); - } - } - /* Drive one line to low for determining which key's state changed. */ - else { - if (IS_ENABLED(CONFIG_PLATFORM_EC_KEYBOARD_COL2_INVERTED)) { - if (col == 2) - gpio_set_level(GPIO_KBD_KSO2, 1); - else - gpio_set_level(GPIO_KBD_KSO2, 0); - } - mask = ~BIT(col_out); - } - - /* Set KBSOUT */ - inst->KBSOUT0 = (mask & 0xFFFF); - inst->KBSOUT1 = ((mask >> 16) & 0x03); - - return 0; -} - -static void cros_kb_raw_npcx_ksi_isr(const struct device *dev, - struct npcx_wui *wui) -{ - ARG_UNUSED(dev); - ARG_UNUSED(wui); - - LOG_DBG("%s: KSI%d is changed", __func__, wui->bit); - /* Wake-up keyboard scan task */ - task_wake(TASK_ID_KEYSCAN); -} - -static int cros_kb_raw_npcx_init(const struct device *dev) -{ - const struct cros_kb_raw_npcx_config *const config = DRV_CONFIG(dev); - struct kbs_reg *const inst = HAL_INSTANCE(dev); - - /* Pull-up KBSIN0-7 internally */ - inst->KBSINPU = 0xFF; - - /* - * Keyboard Scan Control Register - * - * [6:7] - KBHDRV KBSOUTn signals output buffers are open-drain. - * [3] - KBSINC Auto-increment of Buffer Data register is disabled - * [2] - KBSIEN Interrupt of Auto-Scan is disabled - * [1] - KBSMODE Key detection mechanism is implemented by firmware - * [0] - START Write 0 to this field is not affected - */ - inst->KBSCTL = 0x00; - - /* - * Select quasi-bidirectional buffers for KSO pins. It reduces the - * low-to-high transition time. This feature only supports in npcx7. - */ - if (IS_ENABLED(CONFIG_CROS_KB_RAW_NPCX_KSO_HIGH_DRIVE)) { - SET_FIELD(inst->KBSCTL, NPCX_KBSCTL_KBHDRV_FIELD, 0x01); - } - - /* Configure pin-mux for kscan device */ - npcx_pinctrl_mux_configure(config->alts_list, config->alts_size, 1); - - /* Drive all column lines to low for detection any key press */ - cros_kb_raw_npcx_drive_column(dev, KEYBOARD_COLUMN_ALL); - - /* Configure wake-up input and callback for keyboard input signal */ - for (int i = 0; i < ARRAY_SIZE(ksi_callback); i++) - kb_raw_npcx_init_ksi_wui_callback(dev, &ksi_callback[i], - &config->wui_maps[i], - cros_kb_raw_npcx_ksi_isr); - - return 0; -} - -static const struct cros_kb_raw_driver_api cros_kb_raw_npcx_driver_api = { - .init = cros_kb_raw_npcx_init, - .drive_colum = cros_kb_raw_npcx_drive_column, - .read_rows = cros_kb_raw_npcx_read_row, - .enable_interrupt = cros_kb_raw_npcx_enable_interrupt, -}; - -static const struct npcx_alt cros_kb_raw_alts[] = NPCX_DT_ALT_ITEMS_LIST(0); - -static const struct cros_kb_raw_npcx_config cros_kb_raw_cfg = { - .base = DT_INST_REG_ADDR(0), - .alts_size = ARRAY_SIZE(cros_kb_raw_alts), - .alts_list = cros_kb_raw_alts, - .clk_cfg = NPCX_DT_CLK_CFG_ITEM(0), - .irq = DT_INST_IRQN(0), - .wui_size = NPCX_DT_WUI_ITEMS_LEN(0), - .wui_maps = NPCX_DT_WUI_ITEMS_LIST(0), -}; - -/* Verify there's exactly 1 enabled cros,kb-raw-npcx node. */ -BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1); -DEVICE_DT_INST_DEFINE(0, kb_raw_npcx_init, NULL, NULL, &cros_kb_raw_cfg, - PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, - &cros_kb_raw_npcx_driver_api); - -/* KBS register structure check */ -NPCX_REG_SIZE_CHECK(kbs_reg, 0x010); -NPCX_REG_OFFSET_CHECK(kbs_reg, KBSIN, 0x004); -NPCX_REG_OFFSET_CHECK(kbs_reg, KBSOUT0, 0x006); -NPCX_REG_OFFSET_CHECK(kbs_reg, KBS_BUF_INDX, 0x00a); diff --git a/zephyr/drivers/cros_rtc/CMakeLists.txt b/zephyr/drivers/cros_rtc/CMakeLists.txt deleted file mode 100644 index f6ce9b6890..0000000000 --- a/zephyr/drivers/cros_rtc/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright 2021 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -zephyr_library_sources_ifdef(CONFIG_CROS_RTC_NPCX cros_rtc_npcx.c) -zephyr_library_sources_ifdef(CONFIG_CROS_RTC_NXP_PCF85063A - nxp_rtc_pcf85063a.c) -zephyr_library_sources_ifdef(CONFIG_CROS_RTC_RENESAS_IDT1337AG - renesas_rtc_idt1337ag.c) diff --git a/zephyr/drivers/cros_rtc/Kconfig b/zephyr/drivers/cros_rtc/Kconfig deleted file mode 100644 index 9abe8e27e0..0000000000 --- a/zephyr/drivers/cros_rtc/Kconfig +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright 2021 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -if PLATFORM_EC_RTC - -choice CROS_RTC_TYPE - prompt "Select the RTC to use" - default CROS_RTC_NPCX if SOC_FAMILY_NPCX - help - Select the RTC used on the board. - -config CROS_RTC_NPCX - bool "Nuvoton NPCX Real-Time Clock (RTC) driver for the Zephyr shim" - depends on SOC_FAMILY_NPCX - help - This option enables a driver for providing the support of Real-Time - Clock (RTC) on the NPCX chip. - -config CROS_RTC_NXP_PCF85063A - bool "NXP PCF85063A Real-Time Clock (RTC) driver for the Zephyr shim" - depends on PLATFORM_EC_I2C - help - This option enables a driver for providing the support of NXP - Real-Time Clock (RTC) on the the I2C bus. - -config CROS_RTC_RENESAS_IDT1337AG - bool "RENESAS IDT1337AG Real-Time Clock (RTC) driver for the Zephyr shim" - depends on PLATFORM_EC_I2C - help - This option enables a driver for providing the support of RENESAS - Real-Time Clock (RTC) on the the I2C bus. - -endchoice # RTC Select - -endif # PLATFORM_EC_RTC diff --git a/zephyr/drivers/cros_rtc/cros_rtc_npcx.c b/zephyr/drivers/cros_rtc/cros_rtc_npcx.c deleted file mode 100644 index 0ecbe5f47c..0000000000 --- a/zephyr/drivers/cros_rtc/cros_rtc_npcx.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT nuvoton_npcx_cros_mtc - -#include <assert.h> -#include <drivers/cros_rtc.h> -#include <drivers/gpio.h> -#include <kernel.h> -#include <soc.h> -#include <soc/nuvoton_npcx/reg_def_cros.h> - -#include "ec_tasks.h" -#include "soc_miwu.h" -#include "task.h" - -#include <logging/log.h> -LOG_MODULE_REGISTER(cros_rtc, LOG_LEVEL_ERR); - -#define NPCX_MTC_TTC_LOAD_DELAY_US 250 /* Delay after writing TTC */ -#define NPCX_MTC_ALARM_MASK GENMASK(24, 0) /* Valid field of alarm in WTC */ - -/* Driver config */ -struct cros_rtc_npcx_config { - /* Monotonic counter base address */ - uintptr_t base; - /* Monotonic counter wake-up input source configuration */ - const struct npcx_wui mtc_alarm; -}; - -/* Driver data */ -struct cros_rtc_npcx_data { - /* Monotonic counter wake-up callback object */ - struct miwu_dev_callback miwu_mtc_cb; - cros_rtc_alarm_callback_t alarm_callback; -}; - -/* Driver convenience defines */ -#define DRV_CONFIG(dev) ((const struct cros_rtc_npcx_config *)(dev)->config) - -#define DRV_DATA(dev) ((struct cros_rtc_npcx_data *)(dev)->data) - -#define HAL_INSTANCE(dev) (struct mtc_reg *)(DRV_CONFIG(dev)->base) - -/* Counter internal local functions */ -static uint32_t counter_npcx_get_val(const struct device *dev) -{ - struct mtc_reg *const inst = HAL_INSTANCE(dev); - - /* - * Get value of monotonic counter which keeps counting when VCC1 power - * domain exists (Unit:sec) - */ - return inst->TTC; -} - -static void counter_npcx_set_val(const struct device *dev, uint32_t val) -{ - struct mtc_reg *const inst = HAL_INSTANCE(dev); - - /* - * Set monotonic counter. Write it twice to ensure the value latch to - * TTC register. A delay (~250 us) is also needed before writing again. - */ - inst->TTC = val; - k_busy_wait(NPCX_MTC_TTC_LOAD_DELAY_US); - - inst->TTC = val; - k_busy_wait(NPCX_MTC_TTC_LOAD_DELAY_US); -} - -static uint32_t counter_npcx_get_alarm_val(const struct device *dev) -{ - struct mtc_reg *const inst = HAL_INSTANCE(dev); - - /* - * If alarm is not set or it is set and has already gone off, return - * zero directly. - */ - if (!IS_BIT_SET(inst->WTC, NPCX_WTC_WIE) || - IS_BIT_SET(inst->WTC, NPCX_WTC_PTO)) { - return 0; - } - - /* Return 25-bit alarm value */ - return inst->WTC & NPCX_MTC_ALARM_MASK; -} - -static void counter_npcx_set_alarm_val(const struct device *dev, uint32_t val) -{ - struct mtc_reg *const inst = HAL_INSTANCE(dev); - - /* Disable alarm interrupt */ - inst->WTC &= ~BIT(NPCX_WTC_WIE); - - /* Set new alarm value */ - inst->WTC = val & NPCX_MTC_ALARM_MASK; - - /* Enable alarm interrupt */ - inst->WTC |= BIT(NPCX_WTC_WIE); -} - -static void counter_npcx_reset_alarm(const struct device *dev) -{ - struct mtc_reg *const inst = HAL_INSTANCE(dev); - - /* Disable alarm interrupt first */ - if (IS_BIT_SET(inst->WTC, NPCX_WTC_WIE)) { - inst->WTC &= ~BIT(NPCX_WTC_WIE); - } - - /* Set alarm to maximum value and clear its pending bit */ - if (IS_BIT_SET(inst->WTC, NPCX_WTC_PTO)) { - inst->WTC = NPCX_MTC_ALARM_MASK; - inst->WTC |= BIT(NPCX_WTC_PTO); - } -} - -/* Counter local functions */ -static void counter_npcx_isr(const struct device *dev, struct npcx_wui *wui) -{ - struct cros_rtc_npcx_data *data = DRV_DATA(dev); - - LOG_DBG("%s", __func__); - - /* Alarm is one-shot, so reset alarm to default */ - counter_npcx_reset_alarm(dev); - - /* Call callback function */ - if (data->alarm_callback) { - data->alarm_callback(dev); - } -} - -/* cros ec RTC api functions */ -static int cros_rtc_npcx_configure(const struct device *dev, - cros_rtc_alarm_callback_t callback) -{ - struct cros_rtc_npcx_data *data = DRV_DATA(dev); - - if (callback == NULL) { - return -EINVAL; - } - - data->alarm_callback = callback; - return 0; -} - -static int cros_rtc_npcx_get_value(const struct device *dev, uint32_t *value) -{ - *value = counter_npcx_get_val(dev); - - return 0; -} - -static int cros_rtc_npcx_set_value(const struct device *dev, uint32_t value) -{ - counter_npcx_set_val(dev, value); - - return 0; -} -static int cros_rtc_npcx_get_alarm(const struct device *dev, uint32_t *seconds, - uint32_t *microseconds) -{ - *seconds = counter_npcx_get_alarm_val(dev); - *microseconds = 0; - - return 0; -} -static int cros_rtc_npcx_set_alarm(const struct device *dev, uint32_t seconds, - uint32_t microseconds) -{ - const struct cros_rtc_npcx_config *config = DRV_CONFIG(dev); - ARG_UNUSED(microseconds); - - /* Enable interrupt of the MTC alarm wake-up input source */ - npcx_miwu_irq_enable(&config->mtc_alarm); - - /* Make sure alarm restore to default state */ - counter_npcx_reset_alarm(dev); - counter_npcx_set_alarm_val(dev, seconds); - - return 0; -} - -static int cros_rtc_npcx_reset_alarm(const struct device *dev) -{ - const struct cros_rtc_npcx_config *config = DRV_CONFIG(dev); - - /* Disable interrupt of the MTC alarm wake-up input source */ - npcx_miwu_irq_disable(&config->mtc_alarm); - - counter_npcx_reset_alarm(dev); - - return 0; -} - -/* cros ec RTC driver registration */ -static const struct cros_rtc_driver_api cros_rtc_npcx_driver_api = { - .configure = cros_rtc_npcx_configure, - .get_value = cros_rtc_npcx_get_value, - .set_value = cros_rtc_npcx_set_value, - .get_alarm = cros_rtc_npcx_get_alarm, - .set_alarm = cros_rtc_npcx_set_alarm, - .reset_alarm = cros_rtc_npcx_reset_alarm, -}; - -static int cros_rtc_npcx_init(const struct device *dev) -{ - const struct cros_rtc_npcx_config *config = DRV_CONFIG(dev); - struct cros_rtc_npcx_data *data = DRV_DATA(dev); - - /* Initialize the miwu input and its callback for monotonic counter */ - npcx_miwu_init_dev_callback(&data->miwu_mtc_cb, &config->mtc_alarm, - counter_npcx_isr, dev); - npcx_miwu_manage_dev_callback(&data->miwu_mtc_cb, true); - - /* - * Configure the monotonic counter wake-up event triggered from a rising - * edge on its signal. - */ - npcx_miwu_interrupt_configure(&config->mtc_alarm, NPCX_MIWU_MODE_EDGE, - NPCX_MIWU_TRIG_HIGH); - - return 0; -} - -static const struct cros_rtc_npcx_config cros_rtc_npcx_cfg_0 = { - .base = DT_INST_REG_ADDR(0), - .mtc_alarm = NPCX_DT_WUI_ITEM_BY_NAME(0, mtc_alarm) -}; - -static struct cros_rtc_npcx_data cros_rtc_npcx_data_0; - -DEVICE_DT_INST_DEFINE(0, cros_rtc_npcx_init, /* pm_control_fn= */ NULL, - &cros_rtc_npcx_data_0, &cros_rtc_npcx_cfg_0, POST_KERNEL, - CONFIG_KERNEL_INIT_PRIORITY_DEVICE, - &cros_rtc_npcx_driver_api); diff --git a/zephyr/drivers/cros_rtc/nxp_rtc_pcf85063a.c b/zephyr/drivers/cros_rtc/nxp_rtc_pcf85063a.c deleted file mode 100644 index 94632947c6..0000000000 --- a/zephyr/drivers/cros_rtc/nxp_rtc_pcf85063a.c +++ /dev/null @@ -1,450 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define DT_DRV_COMPAT nxp_rtc_pcf85063a - -#include <assert.h> -#include <device.h> -#include <drivers/cros_rtc.h> -#include <drivers/gpio.h> -#include <drivers/i2c.h> -#include <kernel.h> -#include <rtc.h> -#include <soc.h> - -#include "nxp_rtc_pcf85063a.h" - -#include <logging/log.h> -LOG_MODULE_REGISTER(cros_rtc, LOG_LEVEL_ERR); - -/* Driver config */ -struct nxp_rtc_pcf85063a_config { - const struct device *bus; - const uint16_t i2c_addr_flags; - const struct gpio_dt_spec gpio_alert; -}; - -/* Driver data */ -struct nxp_rtc_pcf85063a_data { - const struct device *dev; - uint8_t time_reg[NUM_TIMER_REGS]; - struct gpio_callback gpio_cb; - cros_rtc_alarm_callback_t alarm_callback; -}; - -/* Driver convenience defines */ -#define DRV_CONFIG(dev) ((const struct nxp_rtc_pcf85063a_config *)(dev)->config) -#define DRV_DATA(dev) ((struct nxp_rtc_pcf85063a_data *)(dev)->data) - -/* - * is_alarm == true: Reads alarm registers SECONDS, MINUTES, HOURS, and DAYS - * is_alarm == false: Reads time registers SECONDS, MINUTES, HOURS, DAYS, and - * MONTHS, YEARS - */ -static int pcf85063a_read_time_regs(const struct device *dev, bool is_alarm) -{ - const struct nxp_rtc_pcf85063a_config *const config = DRV_CONFIG(dev); - struct nxp_rtc_pcf85063a_data *data = DRV_DATA(dev); - uint8_t start_reg; - uint8_t num_reg; - - if (is_alarm) { - start_reg = REG_SECOND_ALARM; - num_reg = NUM_ALARM_REGS; - } else { - start_reg = REG_SECONDS; - num_reg = NUM_TIMER_REGS; - } - - return i2c_burst_read(config->bus, - config->i2c_addr_flags, start_reg, data->time_reg, num_reg); -} - -static int pcf85063a_read_reg(const struct device *dev, - uint8_t reg, uint8_t *val) -{ - const struct nxp_rtc_pcf85063a_config *const config = DRV_CONFIG(dev); - - return i2c_reg_read_byte(config->bus, config->i2c_addr_flags, reg, val); -} - -/* - * is_alarm == true: Writes alarm registers SECONDS, MINUTES, HOURS, and DAYS - * is_alarm == false: Writes time registers SECONDS, MINUTES, HOURS, DAYS, and - * MONTHS, YEARS - */ -static int pcf85063a_write_time_regs(const struct device *dev, bool is_alarm) -{ - const struct nxp_rtc_pcf85063a_config *const config = DRV_CONFIG(dev); - struct nxp_rtc_pcf85063a_data *data = DRV_DATA(dev); - uint8_t tx_buf[NUM_TIMER_REGS]; - uint8_t start_reg; - uint8_t num_reg; - - if (is_alarm) { - start_reg = REG_SECOND_ALARM; - num_reg = NUM_ALARM_REGS; - } else { - start_reg = REG_SECONDS; - num_reg = NUM_TIMER_REGS; - } - - for (int i = 0; i < num_reg; i++) { - tx_buf[i] = data->time_reg[i]; - } - - return i2c_burst_write(config->bus, - config->i2c_addr_flags, start_reg, tx_buf, num_reg); -} - - -static int pcf85063a_write_reg(const struct device *dev, - uint8_t reg, uint8_t val) -{ - const struct nxp_rtc_pcf85063a_config *const config = DRV_CONFIG(dev); - uint8_t tx_buf[2]; - - tx_buf[0] = reg; - tx_buf[1] = val; - - return i2c_write(config->bus, - tx_buf, sizeof(tx_buf), config->i2c_addr_flags); -} - -/* - * val bits 7 to 4 - tens place - * val bits 3 to 0 - ones place - */ -static int bcd_to_dec(uint8_t val, enum bcd_mask mask) -{ - int tens = ((val & mask) >> 4) * 10; - int ones = (val & 0xf); - - return tens + ones; -} - -/* - * val bits 7 to 4 - tens place - * val bits 3 to 0 - ones place - */ -static uint8_t dec_to_bcd(uint32_t val, enum bcd_mask mask) -{ - int tens = val / 10; - int ones = val - (tens * 10); - - return ((tens << 4) & mask) | ones; -} - -static int nxp_rtc_pcf85063a_read_seconds(const struct device *dev, - uint32_t *value, bool is_alarm) -{ - struct nxp_rtc_pcf85063a_data *data = DRV_DATA(dev); - struct calendar_date time; - int ret; - - ret = pcf85063a_read_time_regs(dev, is_alarm); - - if (ret < 0) { - return ret; - } - - if (is_alarm) { - *value = (bcd_to_dec(data->time_reg[DAYS], DAYS_MASK) * - SECS_PER_DAY) + - (bcd_to_dec(data->time_reg[HOURS], HOURS24_MASK) * - SECS_PER_HOUR) + - (bcd_to_dec(data->time_reg[MINUTES], MINUTES_MASK) * - SECS_PER_MINUTE) + - bcd_to_dec(data->time_reg[SECONDS], SECONDS_MASK); - } else { - time.year = bcd_to_dec(data->time_reg[YEARS], YEARS_MASK); - time.month = - bcd_to_dec(data->time_reg[MONTHS], MONTHS_MASK); - time.day = bcd_to_dec(data->time_reg[DAYS], DAYS_MASK); - - *value = date_to_sec(time) - SECS_TILL_YEAR_2K + - (bcd_to_dec(data->time_reg[HOURS], HOURS24_MASK) * - SECS_PER_HOUR) + - (bcd_to_dec(data->time_reg[MINUTES], MINUTES_MASK) * - SECS_PER_MINUTE) + - bcd_to_dec(data->time_reg[SECONDS], SECONDS_MASK); - } - - return ret; -} - -static int nxp_rtc_pcf85063a_write_seconds(const struct device *dev, - uint32_t value, bool is_alarm) -{ - struct nxp_rtc_pcf85063a_data *data = DRV_DATA(dev); - struct calendar_date time; - uint32_t tmp_sec; - - time = sec_to_date(value + SECS_TILL_YEAR_2K); - - if (!is_alarm) { - data->time_reg[YEARS] = dec_to_bcd(time.year, YEARS_MASK); - data->time_reg[MONTHS] = - dec_to_bcd(time.month, MONTHS_MASK); - } - - data->time_reg[DAYS] = dec_to_bcd(time.day, DAYS_MASK); - - if (is_alarm && data->time_reg[DAYS] == 0) { - data->time_reg[DAYS] |= DISABLE_ALARM; - } - - value %= SECS_PER_DAY; - tmp_sec = value / SECS_PER_HOUR; - data->time_reg[HOURS] = dec_to_bcd(tmp_sec, HOURS24_MASK); - - if (is_alarm && data->time_reg[HOURS] == 0) { - data->time_reg[HOURS] |= DISABLE_ALARM; - } - - value -= (tmp_sec * SECS_PER_HOUR); - tmp_sec = value / SECS_PER_MINUTE; - data->time_reg[MINUTES] = dec_to_bcd(tmp_sec, MINUTES_MASK); - - if (is_alarm && data->time_reg[MINUTES] == 0) { - data->time_reg[MINUTES] |= DISABLE_ALARM; - } - - value -= (tmp_sec * SECS_PER_MINUTE); - data->time_reg[SECONDS] = dec_to_bcd(value, SECONDS_MASK); - - if (is_alarm && data->time_reg[SECONDS] == 0) { - data->time_reg[SECONDS] |= DISABLE_ALARM; - } - - return pcf85063a_write_time_regs(dev, is_alarm); -} - -static int nxp_rtc_pcf85063a_configure(const struct device *dev, - cros_rtc_alarm_callback_t callback) -{ - struct nxp_rtc_pcf85063a_data *data = DRV_DATA(dev); - - if (callback == NULL) { - return -EINVAL; - } - - data->alarm_callback = callback; - - return 0; -} - -static int nxp_rtc_pcf85063a_get_value(const struct device *dev, - uint32_t *value) -{ - return nxp_rtc_pcf85063a_read_seconds(dev, value, false); -} - -static int nxp_rtc_pcf85063a_set_value(const struct device *dev, uint32_t value) -{ - return nxp_rtc_pcf85063a_write_seconds(dev, value, false); -} - -static int nxp_rtc_pcf85063a_get_alarm(const struct device *dev, - uint32_t *seconds, uint32_t *microseconds) -{ - *microseconds = 0; - return nxp_rtc_pcf85063a_read_seconds(dev, seconds, true); -} - -static int nxp_rtc_pcf85063a_reset_alarm(const struct device *dev) -{ - struct nxp_rtc_pcf85063a_data *data = DRV_DATA(dev); - int ret; - - /* Disable alarm interrupt and clear pending alarm flag */ - ret = pcf85063a_write_reg(dev, REG_CONTROL_2, 0); - if (ret < 0) { - return ret; - } - - /* Clear and disable the alarm registers */ - data->time_reg[SECONDS] = DISABLE_ALARM; - data->time_reg[MINUTES] = DISABLE_ALARM; - data->time_reg[HOURS] = DISABLE_ALARM; - data->time_reg[DAYS] = DISABLE_ALARM; - - return pcf85063a_write_time_regs(dev, true); -} - -static int nxp_rtc_pcf85063a_set_alarm(const struct device *dev, - uint32_t seconds, uint32_t microseconds) -{ - int ret; - - ARG_UNUSED(microseconds); - - ret = nxp_rtc_pcf85063a_reset_alarm(dev); - - if (ret < 0) { - return ret; - } - - ret = nxp_rtc_pcf85063a_write_seconds(dev, seconds, true); - - if (ret < 0) { - return ret; - } - - return pcf85063a_write_reg(dev, REG_CONTROL_2, ENABLE_ALARM_INTERRUPT); -} - -static void nxp_pcf85063a_isr(const struct device *port, - struct gpio_callback *cb, uint32_t pin) -{ - struct nxp_rtc_pcf85063a_data *data = - CONTAINER_OF(cb, struct nxp_rtc_pcf85063a_data, gpio_cb); - const struct device *dev = (const struct device *)data->dev; - - ARG_UNUSED(port); - ARG_UNUSED(pin); - ARG_UNUSED(cb); - - LOG_DBG("%s", __func__); - - /* Call callback function */ - if (data->alarm_callback) { - data->alarm_callback(dev); - } -} - -static const struct cros_rtc_driver_api nxp_rtc_pcf85063a_driver_api = { - .configure = nxp_rtc_pcf85063a_configure, - .get_value = nxp_rtc_pcf85063a_get_value, - .set_value = nxp_rtc_pcf85063a_set_value, - .get_alarm = nxp_rtc_pcf85063a_get_alarm, - .set_alarm = nxp_rtc_pcf85063a_set_alarm, - .reset_alarm = nxp_rtc_pcf85063a_reset_alarm, -}; - -static int nxp_rtc_pcf85063a_init(const struct device *dev) -{ - const struct nxp_rtc_pcf85063a_config *const config = DRV_CONFIG(dev); - struct nxp_rtc_pcf85063a_data *data = DRV_DATA(dev); - uint8_t val; - int ret; - - if (!device_is_ready(config->bus)) { - LOG_ERR("Device %s is not ready", config->bus->name); - return -ENODEV; - } - - /* - * Read Control_1 register. For normal operation, - * the values should be as follows: - * Bit 7 (external clock test mode) : (0) normal mode - * Bit 6 (unused) : (0) - * Bit 5 (STOP bit) : (0) RTC clock runs - * BIT 4 (software reset) : (0) no software reset - * BIT 3 (unused) : (0) - * BIT 2 (correction interrupt enable) : (0) no correction - * interrupt generated - * BIT 1 (12 or 24-hour mode) : (0) 24-hour mode - * BIT 0 (internal oscillator capacitor: (0) 7pF - */ - ret = pcf85063a_read_reg(dev, REG_CONTROL_1, &val); - - if (ret < 0) { - return ret; - } - - if (val != CONTROL_1_DEFAULT_VALUE) { - /* PCF85063A is not initialized, so send soft reset */ - ret = pcf85063a_write_reg(dev, REG_CONTROL_1, SOFT_RESET); - - if (ret < 0) { - return ret; - } - } - - /* - * Read Seconds register and check if oscillator is stopped. - * If so, clear the bit. - */ - ret = pcf85063a_read_reg(dev, REG_SECONDS, &val); - - if (ret < 0) { - return ret; - } - - if (val & OS_BIT) { - /* Oscillator stop bit is set, clear it. */ - val &= ~OS_BIT; - ret = pcf85063a_write_reg(dev, REG_SECONDS, val); - - if (ret < 0) { - return ret; - } - } - - nxp_rtc_pcf85063a_reset_alarm(dev); - - /* Configure GPIO interrupt pin for PCF85063A alarm pin */ - - if (!device_is_ready(config->gpio_alert.port)) { - LOG_ERR("Alert GPIO device not ready"); - return -ENODEV; - } - - ret = gpio_pin_configure_dt(&config->gpio_alert, GPIO_INPUT); - - if (ret < 0) { - LOG_ERR("Could not configure RTC alert pin"); - return ret; - } - - gpio_init_callback(&data->gpio_cb, - nxp_pcf85063a_isr, BIT(config->gpio_alert.pin)); - - ret = gpio_add_callback(config->gpio_alert.port, &data->gpio_cb); - - if (ret < 0) { - LOG_ERR("Could not set RTC alert pin callback"); - return ret; - } - - data->dev = dev; - - return gpio_pin_interrupt_configure_dt(&config->gpio_alert, - GPIO_INT_EDGE_FALLING); -} - -#define PCF85063A_INT_GPIOS \ - DT_PHANDLE_BY_IDX(DT_NODELABEL(pcf85063a), int_gpios, 0) - -/* - * dt_flags is a uint8_t type. However, for platform/ec - * the GPIO flags in the devicetree are expanded past 8 bits - * to support the INPUT/OUTPUT and PULLUP/PULLDOWN properties. - * Cast back to a gpio_dt_flags to compile, discarding the bits - * that are not supported by the Zephyr GPIO API. - */ -#define CROS_EC_GPIO_DT_SPEC_GET_BY_IDX(node_id, prop, idx) \ - { \ - .port = \ - DEVICE_DT_GET(DT_GPIO_CTLR_BY_IDX(node_id, prop, idx)), \ - .pin = DT_GPIO_PIN_BY_IDX(node_id, prop, idx), \ - .dt_flags = \ - (gpio_dt_flags_t)DT_GPIO_FLAGS_BY_IDX(node_id, prop, idx), \ - } - -static const struct nxp_rtc_pcf85063a_config nxp_rtc_pcf85063a_cfg_0 = { - .bus = DEVICE_DT_GET(DT_INST_BUS(0)), - .i2c_addr_flags = DT_INST_REG_ADDR(0), - .gpio_alert = - CROS_EC_GPIO_DT_SPEC_GET_BY_IDX(PCF85063A_INT_GPIOS, gpios, 0) -}; - -static struct nxp_rtc_pcf85063a_data nxp_rtc_pcf85063a_data_0; - -DEVICE_DT_INST_DEFINE(0, nxp_rtc_pcf85063a_init, /* pm_control_fn= */ NULL, - &nxp_rtc_pcf85063a_data_0, &nxp_rtc_pcf85063a_cfg_0, - POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, - &nxp_rtc_pcf85063a_driver_api); diff --git a/zephyr/drivers/cros_rtc/nxp_rtc_pcf85063a.h b/zephyr/drivers/cros_rtc/nxp_rtc_pcf85063a.h deleted file mode 100644 index dc4fcd24fc..0000000000 --- a/zephyr/drivers/cros_rtc/nxp_rtc_pcf85063a.h +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __CROS_EC_RTC_PCF85063A_H -#define __CROS_EC_RTC_PCF85063A_H - -#define PCF85063A_REG_NUM 18 -#define SOFT_RESET 0x58 -#define CONTROL_1_DEFAULT_VALUE 0 -#define OS_BIT 0x80 -#define DISABLE_ALARM 0x80 -#define ENABLE_ALARM_INTERRUPT 0x80 -#define RTC_STOP_CLOCKS 0x20 -#define RTC_START_CLOCKS 0x00 - -#define NUM_TIMER_REGS 7 -#define NUM_ALARM_REGS 4 - -#define REG_CONTROL_1 0x00 -#define REG_CONTROL_2 0x01 -#define REG_OFFSET 0x02 -#define REG_RAM_BYTE 0x03 -#define REG_SECONDS 0x04 -#define REG_MINUTES 0x05 -#define REG_HOURS 0x06 -#define REG_DAYS 0x07 -#define REG_WEEKDAYS 0x08 -#define REG_MONTHS 0x09 -#define REG_YEARS 0x0a -#define REG_SECOND_ALARM 0x0b -#define REG_MINUTE_ALARM 0x0c -#define REG_HOUR_ALARM 0x0d -#define REG_DAY_ALARM 0x0e -#define REG_WEEKDAY_ALARM 0x0f -#define REG_TIMER_VALUE 0x10 -#define REG_TIMER_MODE 0x11 - -/* Macros for indexing time_reg buffer */ -#define SECONDS 0 -#define MINUTES 1 -#define HOURS 2 -#define DAYS 3 -#define WEEKDAYS 4 -#define MONTHS 5 -#define YEARS 6 - -enum bcd_mask { - SECONDS_MASK = 0x70, - MINUTES_MASK = 0x70, - HOURS24_MASK = 0x30, - DAYS_MASK = 0x30, - MONTHS_MASK = 0x10, - YEARS_MASK = 0xf0 -}; - -#endif /* __CROS_EC_RTC_PCF85063A_H */ diff --git a/zephyr/drivers/cros_rtc/renesas_rtc_idt1337ag.c b/zephyr/drivers/cros_rtc/renesas_rtc_idt1337ag.c deleted file mode 100644 index bbe76f5286..0000000000 --- a/zephyr/drivers/cros_rtc/renesas_rtc_idt1337ag.c +++ /dev/null @@ -1,480 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define DT_DRV_COMPAT renesas_rtc_idt1337ag - -#include <assert.h> -#include <device.h> -#include <drivers/cros_rtc.h> -#include <drivers/gpio.h> -#include <drivers/i2c.h> -#include <kernel.h> -#include <rtc.h> -#include <soc.h> - -#include "renesas_rtc_idt1337ag.h" - -#include <logging/log.h> -LOG_MODULE_REGISTER(cros_rtc, LOG_LEVEL_ERR); - -/* Driver config */ -struct renesas_rtc_idt1337ag_config { - const struct device *bus; - const uint16_t i2c_addr_flags; - const struct gpio_dt_spec gpio_alert; -}; - -/* Driver data */ -struct renesas_rtc_idt1337ag_data { - const struct device *dev; - struct gpio_callback gpio_cb; - cros_rtc_alarm_callback_t alarm_callback; -}; - -enum timer_type { - RTC_TIMER, - ALARM_TIMER, -}; - -/* - * type == ALARM_TIMER: Reads alarm registers SECONDS, MINUTES, HOURS, and DAYS - * type == RTC_TIMER: Reads time registers SECONDS, MINUTES, HOURS, DAYS, and - * MONTHS, YEARS - */ -static int idt1337ag_read_time_regs(const struct device *dev, - uint8_t *time_reg, enum timer_type type) -{ - const struct renesas_rtc_idt1337ag_config *const config = dev->config; - uint8_t start_reg; - uint8_t num_reg; - - if (type == ALARM_TIMER) { - start_reg = REG_SECOND_ALARM1; - num_reg = NUM_ALARM_REGS; - } else { - start_reg = REG_SECONDS; - num_reg = NUM_TIMER_REGS; - } - - return i2c_burst_read(config->bus, - config->i2c_addr_flags, start_reg, time_reg, num_reg); -} - -static int idt1337ag_read_reg(const struct device *dev, - uint8_t reg, uint8_t *val) -{ - const struct renesas_rtc_idt1337ag_config *const config = dev->config; - - return i2c_reg_read_byte(config->bus, config->i2c_addr_flags, reg, val); -} - -/* - * type == ALARM_TIMER: Writes alarm registers SECONDS, MINUTES, HOURS, and DAYS - * type == RTC_TIMER: Writes time registers SECONDS, MINUTES, HOURS, DAYS, and - * MONTHS, YEARS - */ -static int idt1337ag_write_time_regs(const struct device *dev, - uint8_t *time_reg, enum timer_type type) -{ - const struct renesas_rtc_idt1337ag_config *const config = dev->config; - uint8_t start_reg; - uint8_t num_reg; - - if (type == ALARM_TIMER) { - /* - * Register 0x0A bit 6 determines if the DAY(1b) or DATE(0b) - * alarm is selected. - * Select the DAY alarm - */ - time_reg[DAYS] |= SELECT_DAYS_ALARM; - - start_reg = REG_SECOND_ALARM1; - num_reg = NUM_ALARM_REGS; - } else { - start_reg = REG_SECONDS; - num_reg = NUM_TIMER_REGS; - } - - return i2c_burst_write(config->bus, - config->i2c_addr_flags, start_reg, time_reg, num_reg); -} - -static int idt1337ag_write_reg(const struct device *dev, - uint8_t reg, uint8_t val) -{ - const struct renesas_rtc_idt1337ag_config *const config = dev->config; - uint8_t tx_buf[2]; - - tx_buf[0] = reg; - tx_buf[1] = val; - - return i2c_write(config->bus, - tx_buf, sizeof(tx_buf), config->i2c_addr_flags); -} - -/* - * val bits 7 to 4 - tens place - * val bits 3 to 0 - ones place - */ -static int bcd_to_dec(uint8_t val, enum bcd_mask mask) -{ - int tens = ((val & mask) >> 4) * 10; - int ones = (val & 0xf); - - return tens + ones; -} - -/* - * val bits 7 to 4 - tens place - * val bits 3 to 0 - ones place - */ -static uint8_t dec_to_bcd(uint32_t val, enum bcd_mask mask) -{ - int tens = val / 10; - int ones = val - (tens * 10); - - return ((tens << 4) & mask) | ones; -} - -static int renesas_rtc_idt1337ag_read_seconds(const struct device *dev, - uint32_t *value, enum timer_type type) -{ - uint8_t time_reg[NUM_TIMER_REGS]; - struct calendar_date time; - int ret; - - ret = idt1337ag_read_time_regs(dev, time_reg, type); - - if (ret < 0) { - return ret; - } - - if (type == ALARM_TIMER) { - *value = (bcd_to_dec(time_reg[DAYS], DAYS_MASK) * - SECS_PER_DAY) + - (bcd_to_dec(time_reg[HOURS], HOURS24_MASK) * - SECS_PER_HOUR) + - (bcd_to_dec(time_reg[MINUTES], MINUTES_MASK) * - SECS_PER_MINUTE) + - bcd_to_dec(time_reg[SECONDS], SECONDS_MASK); - } else { - time.year = bcd_to_dec(time_reg[YEARS], YEARS_MASK); - time.month = bcd_to_dec(time_reg[MONTHS], MONTHS_MASK); - time.day = bcd_to_dec(time_reg[DAYS], DAYS_MASK); - - *value = date_to_sec(time) - SECS_TILL_YEAR_2K + - (bcd_to_dec(time_reg[HOURS], HOURS24_MASK) * - SECS_PER_HOUR) + - (bcd_to_dec(time_reg[MINUTES], MINUTES_MASK) * - SECS_PER_MINUTE) + - bcd_to_dec(time_reg[SECONDS], SECONDS_MASK); - } - - return ret; -} - -static int renesas_rtc_idt1337ag_write_seconds(const struct device *dev, - uint32_t value, enum timer_type type) -{ - uint8_t time_reg[NUM_TIMER_REGS]; - struct calendar_date time; - uint32_t tmp_sec; - - time = sec_to_date(value + SECS_TILL_YEAR_2K); - - if (type == RTC_TIMER) { - time_reg[YEARS] = dec_to_bcd(time.year, YEARS_MASK); - time_reg[MONTHS] = dec_to_bcd(time.month, MONTHS_MASK); - } - - time_reg[DAYS] = dec_to_bcd(time.day, DAYS_MASK); - - value %= SECS_PER_DAY; - tmp_sec = value / SECS_PER_HOUR; - time_reg[HOURS] = dec_to_bcd(tmp_sec, HOURS24_MASK); - - value -= (tmp_sec * SECS_PER_HOUR); - tmp_sec = value / SECS_PER_MINUTE; - time_reg[MINUTES] = dec_to_bcd(tmp_sec, MINUTES_MASK); - - value -= (tmp_sec * SECS_PER_MINUTE); - time_reg[SECONDS] = dec_to_bcd(value, SECONDS_MASK); - - return idt1337ag_write_time_regs(dev, time_reg, type); -} - -static int renesas_rtc_idt1337ag_configure(const struct device *dev, - cros_rtc_alarm_callback_t callback) -{ - struct renesas_rtc_idt1337ag_data *data = dev->data; - - if (callback == NULL) { - return -EINVAL; - } - - data->alarm_callback = callback; - - return 0; -} - -static int renesas_rtc_idt1337ag_get_value(const struct device *dev, - uint32_t *value) -{ - return renesas_rtc_idt1337ag_read_seconds(dev, value, RTC_TIMER); -} - -static int renesas_rtc_idt1337ag_set_value(const struct device *dev, - uint32_t value) -{ - return renesas_rtc_idt1337ag_write_seconds(dev, value, RTC_TIMER); -} - -static int renesas_rtc_idt1337ag_get_alarm(const struct device *dev, - uint32_t *seconds, uint32_t *microseconds) -{ - *microseconds = 0; - return renesas_rtc_idt1337ag_read_seconds(dev, seconds, ALARM_TIMER); -} - -static int renesas_rtc_idt1337ag_reset_alarm(const struct device *dev) -{ - uint8_t time_reg[NUM_ALARM_REGS]; - int ret; - uint8_t val; - - ret = idt1337ag_read_reg(dev, REG_CONTROL, &val); - - if (ret < 0) { - return ret; - } - - /* Disable alarm interrupt and clear pending alarm flag */ - val &= ~CONTROL_A1IE; - ret = idt1337ag_write_reg(dev, REG_CONTROL, val); - - if (ret < 0) { - return ret; - } - - /* Clear alarm1 flag if set */ - ret = idt1337ag_read_reg(dev, REG_STATUS, &val); - - if (ret < 0) { - return ret; - } - - /* Clear the alarm1 and alarm2 flag */ - val &= ~(STATUS_A1F | STATUS_A2F); - ret = idt1337ag_write_reg(dev, REG_STATUS, val); - - if (ret < 0) { - return ret; - } - - /* Clear and disable the alarm registers */ - time_reg[SECONDS] = DISABLE_ALARM; - time_reg[MINUTES] = DISABLE_ALARM; - time_reg[HOURS] = DISABLE_ALARM; - time_reg[DAYS] = DISABLE_ALARM; - - return idt1337ag_write_time_regs(dev, time_reg, ALARM_TIMER); -} - -static int renesas_rtc_idt1337ag_set_alarm(const struct device *dev, - uint32_t seconds, uint32_t microseconds) -{ - int ret; - uint8_t val; - - ARG_UNUSED(microseconds); - - ret = renesas_rtc_idt1337ag_reset_alarm(dev); - if (ret < 0) { - return ret; - } - - ret = renesas_rtc_idt1337ag_write_seconds(dev, seconds, ALARM_TIMER); - if (ret < 0) { - return ret; - } - - ret = idt1337ag_read_reg(dev, REG_CONTROL, &val); - if (ret < 0) { - return ret; - } - - val |= CONTROL_A1IE; - idt1337ag_write_reg(dev, REG_CONTROL, val); - - return 0; -} - -static void renesas_rtc_idt1337ag_isr(const struct device *port, - struct gpio_callback *cb, uint32_t pin) -{ - struct renesas_rtc_idt1337ag_data *data = - CONTAINER_OF(cb, struct renesas_rtc_idt1337ag_data, gpio_cb); - const struct device *dev = data->dev; - - ARG_UNUSED(port); - ARG_UNUSED(pin); - ARG_UNUSED(cb); - - LOG_DBG("%s", __func__); - - /* Call callback function */ - if (data->alarm_callback) { - data->alarm_callback(dev); - } -} - -static const struct cros_rtc_driver_api renesas_rtc_idt1337ag_driver_api = { - .configure = renesas_rtc_idt1337ag_configure, - .get_value = renesas_rtc_idt1337ag_get_value, - .set_value = renesas_rtc_idt1337ag_set_value, - .get_alarm = renesas_rtc_idt1337ag_get_alarm, - .set_alarm = renesas_rtc_idt1337ag_set_alarm, - .reset_alarm = renesas_rtc_idt1337ag_reset_alarm, -}; - -static int renesas_rtc_idt1337ag_init(const struct device *dev) -{ - const struct renesas_rtc_idt1337ag_config *const config = dev->config; - struct renesas_rtc_idt1337ag_data *data = dev->data; - uint8_t val; - int ret; - - if (!device_is_ready(config->bus)) { - LOG_ERR("Device %s is not ready", config->bus->name); - return -ENODEV; - } - - /* - * Read Control register. For normal operation, - * the values should be as follows: - * Bit 7 (enable oscillator) : (0) normal mode - * Bit 6 (unused) : (0) - * Bit 5 (unused) : (0) - * BIT 4 (RS2) : (0) Not used when INTCN == 1 - * BIT 3 (RS1) : (0) Not used when INTCN == 1 - * BIT 2 (INTCN) : (1) a match between the timekeeping - * registers and the alarm 1 - * registers activate the INTA pin - * BIT 1 (A2IE) : (0) Alarm 2 is not used - * BIT 0 (A1IE) : (1) Enables Alarm 1 - */ - ret = idt1337ag_read_reg(dev, REG_CONTROL, &val); - - if (ret < 0) { - return ret; - } - - /* Enable IDT1337AG oscillator */ - val &= ~CONTROL_EOSC; - - /* Disable Alarm 2 */ - val &= ~CONTROL_A2IE; - - /* Alarm 1 assert INTA pin */ - val |= CONTROL_INTCN; - - ret = idt1337ag_write_reg(dev, REG_CONTROL, val); - - if (ret < 0) { - return ret; - } - - /* Date register isn't used. Set it to zero */ - ret = idt1337ag_write_reg(dev, REG_DATE, 0); - - /* Make sure the oscillator is running */ - ret = idt1337ag_read_reg(dev, REG_STATUS, &val); - - if (ret < 0) { - return ret; - } - - /* Clear IDT1337AG oscillator not running flag */ - val &= ~STATUS_OSF; - - /* Clear Alarm 2 flag */ - val &= ~STATUS_A2F; - - ret = idt1337ag_write_reg(dev, REG_STATUS, val); - - if (ret < 0) { - return ret; - } - - renesas_rtc_idt1337ag_reset_alarm(dev); - - /* Disable Alarm2 */ - idt1337ag_write_reg(dev, REG_MINUTE_ALARM2, DISABLE_ALARM); - idt1337ag_write_reg(dev, REG_HOUR_ALARM2, DISABLE_ALARM); - idt1337ag_write_reg(dev, REG_DAY_ALARM2, DISABLE_ALARM); - - /* Configure GPIO interrupt pin for IDT1337AG alarm pin */ - - if (!device_is_ready(config->gpio_alert.port)) { - LOG_ERR("Alert GPIO device not ready"); - return -ENODEV; - } - - ret = gpio_pin_configure_dt(&config->gpio_alert, GPIO_INPUT); - - if (ret < 0) { - LOG_ERR("Could not configure RTC alert pin"); - return ret; - } - - gpio_init_callback(&data->gpio_cb, - renesas_rtc_idt1337ag_isr, BIT(config->gpio_alert.pin)); - - ret = gpio_add_callback(config->gpio_alert.port, &data->gpio_cb); - - if (ret < 0) { - LOG_ERR("Could not set RTC alert pin callback"); - return ret; - } - - data->dev = dev; - - return gpio_pin_interrupt_configure_dt(&config->gpio_alert, - GPIO_INT_EDGE_FALLING); -} - -#define IDT1337AG_INT_GPIOS \ - DT_PHANDLE_BY_IDX(DT_NODELABEL(idt1337ag), int_gpios, 0) - -/* - * dt_flags is a uint8_t type. However, for platform/ec - * the GPIO flags in the devicetree are expanded past 8 bits - * to support the INPUT/OUTPUT and PULLUP/PULLDOWN properties. - * Cast back to a gpio_dt_flags to compile, discarding the bits - * that are not supported by the Zephyr GPIO API. - */ -#define CROS_EC_GPIO_DT_SPEC_GET_BY_IDX(node_id, prop, idx) \ - { \ - .port = \ - DEVICE_DT_GET(DT_GPIO_CTLR_BY_IDX(node_id, prop, idx)), \ - .pin = DT_GPIO_PIN_BY_IDX(node_id, prop, idx), \ - .dt_flags = \ - (gpio_dt_flags_t)DT_GPIO_FLAGS_BY_IDX(node_id, prop, idx), \ - } - -static const struct renesas_rtc_idt1337ag_config renesas_rtc_idt1337ag_cfg_0 = { - .bus = DEVICE_DT_GET(DT_INST_BUS(0)), - .i2c_addr_flags = DT_INST_REG_ADDR(0), - .gpio_alert = - CROS_EC_GPIO_DT_SPEC_GET_BY_IDX(IDT1337AG_INT_GPIOS, gpios, 0) -}; - -static struct renesas_rtc_idt1337ag_data renesas_rtc_idt1337ag_data_0; - -DEVICE_DT_INST_DEFINE(0, renesas_rtc_idt1337ag_init, /* pm_control_fn= */ NULL, - &renesas_rtc_idt1337ag_data_0, - &renesas_rtc_idt1337ag_cfg_0, - POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, - &renesas_rtc_idt1337ag_driver_api); diff --git a/zephyr/drivers/cros_rtc/renesas_rtc_idt1337ag.h b/zephyr/drivers/cros_rtc/renesas_rtc_idt1337ag.h deleted file mode 100644 index 3296f80992..0000000000 --- a/zephyr/drivers/cros_rtc/renesas_rtc_idt1337ag.h +++ /dev/null @@ -1,60 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __CROS_EC_RTC_IDT1337AG_H -#define __CROS_EC_RTC_IDT1337AG_H - -/* Setting bit 6 of register 0Ah selects the DAY as alarm source */ -#define SELECT_DAYS_ALARM 0x40 -#define DISABLE_ALARM 0x80 - -#define CONTROL_A1IE BIT(0) -#define CONTROL_A2IE BIT(1) -#define CONTROL_INTCN BIT(2) -#define CONTROL_EOSC BIT(7) - -#define STATUS_A1F BIT(0) -#define STATUS_A2F BIT(1) -#define STATUS_OSF BIT(7) - -#define NUM_TIMER_REGS 7 -#define NUM_ALARM_REGS 4 - -#define REG_SECONDS 0x00 -#define REG_MINUTES 0x01 -#define REG_HOURS 0x02 -#define REG_DAYS 0x03 -#define REG_DATE 0x04 -#define REG_MONTHS 0x05 -#define REG_YEARS 0x06 -#define REG_SECOND_ALARM1 0x07 -#define REG_MINUTE_ALARM1 0x08 -#define REG_HOUR_ALARM1 0x09 -#define REG_DAY_ALARM1 0x0a -#define REG_MINUTE_ALARM2 0x0b -#define REG_HOUR_ALARM2 0x0c -#define REG_DAY_ALARM2 0x0d -#define REG_CONTROL 0x0e -#define REG_STATUS 0x0f - -/* Macros for indexing time_reg buffer */ -#define SECONDS 0 -#define MINUTES 1 -#define HOURS 2 -#define DAYS 3 -#define DATE 4 -#define MONTHS 5 -#define YEARS 6 - -enum bcd_mask { - SECONDS_MASK = 0x70, - MINUTES_MASK = 0x70, - HOURS24_MASK = 0x30, - DAYS_MASK = 0x00, - MONTHS_MASK = 0x10, - YEARS_MASK = 0xf0 -}; - -#endif /* __CROS_EC_RTC_IDT1337AG_H */ diff --git a/zephyr/drivers/cros_shi/CMakeLists.txt b/zephyr/drivers/cros_shi/CMakeLists.txt deleted file mode 100644 index f0b3c8bb5a..0000000000 --- a/zephyr/drivers/cros_shi/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# Copyright 2021 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -zephyr_library_sources_ifdef(CONFIG_CROS_SHI_IT8XXX2 cros_shi_it8xxx2.c) -zephyr_library_sources_ifdef(CONFIG_CROS_SHI_NPCX cros_shi_npcx.c) diff --git a/zephyr/drivers/cros_shi/Kconfig b/zephyr/drivers/cros_shi/Kconfig deleted file mode 100644 index 0baa8a5d80..0000000000 --- a/zephyr/drivers/cros_shi/Kconfig +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright 2021 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -menuconfig CROS_SHI_NPCX - bool "Nuvoton NPCX Serial Host Interface driver for the Zephyr shim" - depends on SOC_FAMILY_NPCX - help - This option enables Serial Host Interface driver for the NPCX family - of processors. This is used for host-command communication on the - platform which AP is ARM-based SoC. - -if CROS_SHI_NPCX -config CROS_SHI_MAX_REQUEST - hex "Max data size for the version 3 request packet" - default 0x220 - help - This option indicates maximum data size for a version 3 request - packet. This must be big enough to handle a request header of host - command, flash write offset/size, and 512 bytes of flash data. - -config CROS_SHI_MAX_RESPONSE - hex "Max data size for the version 3 response packet" - default 0x220 - help - This option indicates maximum data size for a version 3 response - packet. This must be big enough to handle a response header of host - command, flash read offset/size, and 512 bytes of flash data. - -config CROS_SHI_NPCX_DEBUG - bool "Enable SHI debug" - help - print the debug messages for SHI module - -endif # CROS_SHI_NPCX - -config CROS_SHI_IT8XXX2 - bool "ITE it81202 spi host interface driver for Zephyr" - depends on SOC_FAMILY_RISCV_ITE && AP_ARM - default y if PLATFORM_EC_HOSTCMD - help - This option enables spi host interface driver which is required to - communicate with the EC when the CPU is the ARM processor. - -if CROS_SHI_IT8XXX2 - -config CROS_SHI_IT8XXX2_INIT_PRIORITY - int "cros_shi it8xxx2 initialization priority" - default 52 - help - This sets the it8xxx2 cros_shi driver initialization priority. - In the GPIO shim, the alt function of SHI will be configured - as GPIO input pin. So the priority of cros_shi driver must be - lower than CONFIG_PLATFORM_EC_GPIO_INIT_PRIORITY, and - configuration these pins to alt function of SHI. - -endif # CROS_SHI_IT8XXX2 diff --git a/zephyr/drivers/cros_shi/cros_shi_it8xxx2.c b/zephyr/drivers/cros_shi/cros_shi_it8xxx2.c deleted file mode 100644 index 522d48ff09..0000000000 --- a/zephyr/drivers/cros_shi/cros_shi_it8xxx2.c +++ /dev/null @@ -1,407 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define DT_DRV_COMPAT ite_it8xxx2_cros_shi - -#include <device.h> -#include <errno.h> -#include <init.h> -#include <kernel.h> -#include <logging/log.h> -#include <soc.h> -#include <soc_dt.h> -#include <drivers/pinmux.h> -#include <dt-bindings/pinctrl/it8xxx2-pinctrl.h> - -#include "chipset.h" -#include "console.h" -#include "host_command.h" - -/* Console output macros */ -#define CPRINTS(format, args...) cprints(CC_SPI, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SPI, format, ## args) - -LOG_MODULE_REGISTER(cros_shi, LOG_LEVEL_ERR); - -#define DRV_CONFIG(dev) ((struct cros_shi_it8xxx2_cfg * const)(dev)->config) - -/* - * Strcture cros_shi_it8xxx2_cfg is about the setting of SHI, - * this config will be used at initial time - */ -struct cros_shi_it8xxx2_cfg { - /* Pinmux control group */ - const struct device *pinctrls; - /* GPIO pin */ - uint8_t pin; - /* Alternate function */ - uint8_t alt_fun; -}; - -#define SPI_RX_MAX_FIFO_SIZE 256 -#define SPI_TX_MAX_FIFO_SIZE 256 - -#define EC_SPI_PREAMBLE_LENGTH 4 -#define EC_SPI_PAST_END_LENGTH 4 - -/* Max data size for a version 3 request/response packet. */ -#define SPI_MAX_REQUEST_SIZE SPI_RX_MAX_FIFO_SIZE -#define SPI_MAX_RESPONSE_SIZE (SPI_TX_MAX_FIFO_SIZE - \ - EC_SPI_PREAMBLE_LENGTH - EC_SPI_PAST_END_LENGTH) - -static const uint8_t out_preamble[EC_SPI_PREAMBLE_LENGTH] = { - EC_SPI_PROCESSING, - EC_SPI_PROCESSING, - EC_SPI_PROCESSING, - /* This is the byte which matters */ - EC_SPI_FRAME_START, -}; - -/* Store read and write data buffer */ -static uint8_t in_msg[SPI_RX_MAX_FIFO_SIZE] __aligned(4); -static uint8_t out_msg[SPI_TX_MAX_FIFO_SIZE] __aligned(4); - -/* Parameters used by host protocols */ -static struct host_packet spi_packet; - -enum shi_state_machine { - /* Ready to receive next request */ - SPI_STATE_READY_TO_RECV, - /* Receiving request */ - SPI_STATE_RECEIVING, - /* Processing request */ - SPI_STATE_PROCESSING, - /* Received bad data */ - SPI_STATE_RX_BAD, - - SPI_STATE_COUNT, -}; - -static enum shi_state_machine shi_state; - -static const int spi_response_state[] = { - [SPI_STATE_READY_TO_RECV] = EC_SPI_OLD_READY, - [SPI_STATE_RECEIVING] = EC_SPI_RECEIVING, - [SPI_STATE_PROCESSING] = EC_SPI_PROCESSING, - [SPI_STATE_RX_BAD] = EC_SPI_RX_BAD_DATA, -}; -BUILD_ASSERT(ARRAY_SIZE(spi_response_state) == SPI_STATE_COUNT); - -static void spi_set_state(int state) -{ - /* SPI slave state machine */ - shi_state = state; - /* Response spi slave state */ - IT83XX_SPI_SPISRDR = spi_response_state[state]; -} - -static void reset_rx_fifo(void) -{ - /* End Rx FIFO access */ - IT83XX_SPI_TXRXFAR = 0x00; - /* Rx FIFO reset and count monitor reset */ - IT83XX_SPI_FCR = IT83XX_SPI_RXFR | IT83XX_SPI_RXFCMR; -} - -/* This routine handles spi received unexcepted data */ -static void spi_bad_received_data(int count) -{ - /* State machine mismatch, timeout, or protocol we can't handle. */ - spi_set_state(SPI_STATE_RX_BAD); - /* End CPU access Rx FIFO, so it can clock in bytes from AP again. */ - IT83XX_SPI_TXRXFAR = 0; - - CPRINTS("SPI rx bad data"); - CPRINTF("in_msg=["); - for (int i = 0; i < count; i++) - CPRINTF("%02x ", in_msg[i]); - CPRINTF("]\n"); -} - -static void spi_response_host_data(uint8_t *out_msg_addr, int tx_size) -{ - /* - * Protect sequence of filling response packet for host. - * This will ensure CPU access FIFO is disabled at SPI end interrupt no - * matter the interrupt is triggered before or after the sequence. - */ - unsigned int key = irq_lock(); - - if (shi_state == SPI_STATE_PROCESSING) { - /* Tx FIFO reset and count monitor reset */ - IT83XX_SPI_TXFCR = IT83XX_SPI_TXFR | IT83XX_SPI_TXFCMR; - /* CPU Tx FIFO1 and FIFO2 access */ - IT83XX_SPI_TXRXFAR = IT83XX_SPI_CPUTFA; - - for (int i = 0; i < tx_size; i += 4) { - /* Write response data from out_msg buffer to Tx FIFO */ - IT83XX_SPI_CPUWTFDB0 = *(uint32_t *)(out_msg_addr + i); - } - - /* - * After writing data to Tx FIFO is finished, this bit will - * be to indicate the SPI slave controller. - */ - IT83XX_SPI_TXFCR = IT83XX_SPI_TXFS; - /* End Tx FIFO access */ - IT83XX_SPI_TXRXFAR = 0; - /* SPI slave read Tx FIFO */ - IT83XX_SPI_FCR = IT83XX_SPI_SPISRTXF; - } - - irq_unlock(key); -} - -/* - * Called to send a response back to the host. - * - * Some commands can continue for a while. This function is called by - * host_command when it completes. - * - */ -static void spi_send_response_packet(struct host_packet *pkt) -{ - int tx_size; - - if (shi_state != SPI_STATE_PROCESSING) { - CPRINTS("The request data is not processing."); - return; - } - - /* Append our past-end byte, which we reserved space for. */ - for (int i = 0; i < EC_SPI_PAST_END_LENGTH; i++) { - ((uint8_t *)pkt->response)[pkt->response_size + i] - = EC_SPI_PAST_END; - } - - tx_size = pkt->response_size + EC_SPI_PREAMBLE_LENGTH + - EC_SPI_PAST_END_LENGTH; - - /* Transmit the reply */ - spi_response_host_data(out_msg, tx_size); -} - -/* Store request data from Rx FIFO to in_msg buffer */ -static void spi_host_request_data(uint8_t *in_msg_addr, int count) -{ - /* CPU Rx FIFO1 access */ - IT83XX_SPI_TXRXFAR = IT83XX_SPI_CPURXF1A; - /* - * In spi_parse_header, the request data will separate to - * write in_msg buffer so we cannot set CPU to end accessing - * Rx FIFO in this function. We will set IT83XX_SPI_TXRXFAR = 0 - * in reset_rx_fifo. - */ - - for (int i = 0; i < count; i += 4) { - /* Get data from master to buffer */ - *(uint32_t *)(in_msg_addr + i) = IT83XX_SPI_RXFRDRB0; - } -} - -/* Parse header for version of spi-protocol */ -static void spi_parse_header(void) -{ - struct ec_host_request *r = (struct ec_host_request *)in_msg; - - /* Store request data from Rx FIFO to in_msg buffer */ - spi_host_request_data(in_msg, sizeof(*r)); - - /* Protocol version 3 */ - if (in_msg[0] == EC_HOST_REQUEST_VERSION) { - int pkt_size; - - /* Check how big the packet should be */ - pkt_size = host_request_expected_size(r); - - if (pkt_size == 0 || pkt_size > sizeof(in_msg)) { - spi_bad_received_data(pkt_size); - return; - } - - /* Store request data from Rx FIFO to in_msg buffer */ - spi_host_request_data(in_msg + sizeof(*r), - pkt_size - sizeof(*r)); - - /* Set up parameters for host request */ - spi_packet.send_response = spi_send_response_packet; - spi_packet.request = in_msg; - spi_packet.request_temp = NULL; - spi_packet.request_max = sizeof(in_msg); - spi_packet.request_size = pkt_size; - - /* Response must start with the preamble */ - memcpy(out_msg, out_preamble, sizeof(out_preamble)); - - spi_packet.response = out_msg + EC_SPI_PREAMBLE_LENGTH; - /* Reserve space for frame start and trailing past-end byte */ - spi_packet.response_max = SPI_MAX_RESPONSE_SIZE; - spi_packet.response_size = 0; - spi_packet.driver_result = EC_RES_SUCCESS; - - /* Go to common-layer to handle request */ - host_packet_receive(&spi_packet); - } else { - /* Invalid version number */ - CPRINTS("Invalid version number"); - spi_bad_received_data(1); - } -} - -static void shi_ite_int_handler(const void *arg) -{ - /* - * The status of SPI end detection interrupt bit is set, it - * means that host command parse has been completed and AP - * has received the last byte which is EC_SPI_PAST_END from - * EC responded data, then AP ended the transaction. - */ - if (IT83XX_SPI_ISR & IT83XX_SPI_ENDDETECTINT) { - /* Disable CPU access Rx FIFO to clock in data from AP again */ - IT83XX_SPI_TXRXFAR = 0; - /* Ready to receive */ - spi_set_state(SPI_STATE_READY_TO_RECV); - /* - * Once there is no SPI active, enable idle task deep - * sleep bit of SPI in S3 or lower. - * TODO(b:185176098): enable_sleep(SLEEP_MASK_SPI); - */ - - /* CS# is deasserted, so write clear all slave status */ - IT83XX_SPI_ISR = 0xff; - } - /* - * The status of Rx valid length interrupt bit is set that - * indicates reached target count(IT83XX_SPI_FTCB1R, - * IT83XX_SPI_FTCB0R) and the length field of the host - * requested data. - */ - if (IT83XX_SPI_RX_VLISR & IT83XX_SPI_RVLI) { - /* write clear slave status */ - IT83XX_SPI_RX_VLISR = IT83XX_SPI_RVLI; - /* Move to processing state */ - spi_set_state(SPI_STATE_PROCESSING); - /* Parse header for version of spi-protocol */ - spi_parse_header(); - } -} - -void spi_event(enum gpio_signal signal) -{ - if (chipset_in_state(CHIPSET_STATE_ON)) { - /* Move to processing state */ - spi_set_state(SPI_STATE_PROCESSING); - /* Disable idle task deep sleep bit of SPI in S0. */ - /* TODO(b:185176098): disable_sleep(SLEEP_MASK_SPI); */ - } -} - -/* - * SHI init priority is behind CONFIG_PLATFORM_EC_GPIO_INIT_PRIORITY to - * overwrite GPIO_INPUT setting of spi chip select pin. - */ -static int cros_shi_ite_init(const struct device *dev) -{ - const struct cros_shi_it8xxx2_cfg *const config = DRV_CONFIG(dev); - /* Set FIFO data target count */ - struct ec_host_request cmd_head; - - /* - * Target count means the size of host request. - * And plus extra 4 bytes because the CPU accesses FIFO base on - * word. If host requested data length is one byte, we need to - * align the data length to 4 bytes. - */ - int target_count = sizeof(cmd_head) + 4; - /* Offset of data_len member of host request. */ - int offset = (char *)&cmd_head.data_len - (char *)&cmd_head; - - IT83XX_SPI_FTCB1R = (target_count >> 8) & 0xff; - IT83XX_SPI_FTCB0R = target_count & 0xff; - /* - * The register setting can capture the length field of host - * request. - */ - IT83XX_SPI_TCCB1 = (offset >> 8) & 0xff; - IT83XX_SPI_TCCB0 = offset & 0xff; - - /* - * Memory controller configuration register 3. - * bit6 : SPI pin function select (0b:Enable, 1b:Mask) - */ - IT83XX_GCTRL_MCCR3 |= IT83XX_GCTRL_SPISLVPFE; - /* Set unused blocked byte */ - IT83XX_SPI_HPR2 = 0x00; - /* Rx valid length interrupt enabled */ - IT83XX_SPI_RX_VLISMR &= ~IT83XX_SPI_RVLIM; - /* - * General control register2 - * bit4 : Rx FIFO2 will not be overwrited once it's full. - * bit3 : Rx FIFO1 will not be overwrited once it's full. - * bit0 : Rx FIFO1/FIFO2 will reset after each CS_N goes high. - */ - IT83XX_SPI_GCR2 = IT83XX_SPI_RXF2OC | IT83XX_SPI_RXF1OC - | IT83XX_SPI_RXFAR; - /* - * Interrupt mask register (0b:Enable, 1b:Mask) - * bit5 : Rx byte reach interrupt mask - * bit2 : SPI end detection interrupt mask - */ - IT83XX_SPI_IMR &= ~IT83XX_SPI_EDIM; - /* Reset fifo and prepare to for next transaction */ - reset_rx_fifo(); - /* Ready to receive */ - spi_set_state(SPI_STATE_READY_TO_RECV); - /* Interrupt status register(write one to clear) */ - IT83XX_SPI_ISR = 0xff; - /* SPI slave controller enable (after settings are ready) */ - IT83XX_SPI_SPISGCR = IT83XX_SPI_SPISCEN; - - /* Ensure spi chip select alt function is enabled. */ - for (int i = 0; i < DT_INST_PROP_LEN(0, pinctrl_0); i++) { - pinmux_pin_set(config[i].pinctrls, config[i].pin, - config[i].alt_fun); - } - - /* Enable SPI slave interrupt */ - IRQ_CONNECT(DT_INST_IRQN(0), 0, shi_ite_int_handler, 0, 0); - irq_enable(DT_INST_IRQN(0)); - - /* Enable SPI chip select pin interrupt */ - gpio_enable_interrupt(GPIO_SPI0_CS); - - return 0; -} - -static const struct cros_shi_it8xxx2_cfg cros_shi_cfg[] = - IT8XXX2_DT_ALT_ITEMS_LIST(0); - -#if CONFIG_CROS_SHI_IT8XXX2_INIT_PRIORITY <= \ - CONFIG_PLATFORM_EC_GPIO_INIT_PRIORITY -#error "CROS_SHI must initialize after the GPIOs initialization" -#endif -DEVICE_DT_INST_DEFINE(0, cros_shi_ite_init, NULL, - NULL, &cros_shi_cfg, POST_KERNEL, - CONFIG_CROS_SHI_IT8XXX2_INIT_PRIORITY, - NULL); - -/* Get protocol information */ -enum ec_status spi_get_protocol_info(struct host_cmd_handler_args *args) -{ - struct ec_response_get_protocol_info *r = args->response; - - memset(r, 0, sizeof(*r)); - r->protocol_versions = BIT(3); - r->max_request_packet_size = SPI_MAX_REQUEST_SIZE; - r->max_response_packet_size = SPI_MAX_RESPONSE_SIZE; - r->flags = EC_PROTOCOL_INFO_IN_PROGRESS_SUPPORTED; - - args->response_size = sizeof(*r); - - return EC_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, - spi_get_protocol_info, - EC_VER_MASK(0)); diff --git a/zephyr/drivers/cros_shi/cros_shi_npcx.c b/zephyr/drivers/cros_shi/cros_shi_npcx.c deleted file mode 100644 index a290e320fc..0000000000 --- a/zephyr/drivers/cros_shi/cros_shi_npcx.c +++ /dev/null @@ -1,899 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define DT_DRV_COMPAT nuvoton_npcx_cros_shi - -#include <arch/arm/aarch32/cortex_m/cmsis.h> -#include <assert.h> -#include <dt-bindings/clock/npcx_clock.h> -#include <drivers/clock_control.h> -#include <drivers/cros_shi.h> -#include <drivers/gpio.h> -#include <logging/log.h> -#include <kernel.h> -#include <soc.h> -#include <soc/nuvoton_npcx/reg_def_cros.h> - -#include "host_command.h" -#include "soc_miwu.h" -#include "system.h" - -#ifdef CONFIG_CROS_SHI_NPCX_DEBUG -#define DEBUG_CPRINTS(format, args...) cprints(CC_SPI, format, ##args) -#define DEBUG_CPRINTF(format, args...) cprintf(CC_SPI, format, ##args) -#else -#define DEBUG_CPRINTS(...) -#define DEBUG_CPRINTF(...) -#endif - -LOG_MODULE_REGISTER(cros_shi, LOG_LEVEL_DBG); - -#define SHI_NODE DT_NODELABEL(shi) -#define SHI_VER_CTRL_PH DT_PHANDLE_BY_IDX(SHI_NODE, ver_ctrl, 0) -#define SHI_VER_CTRL_ALT_FILED(f) DT_PHA_BY_IDX(SHI_VER_CTRL_PH, alts, 0, f) - -/* Full output buffer size */ -#define SHI_OBUF_FULL_SIZE 128 -/* Full input buffer size */ -#define SHI_IBUF_FULL_SIZE 128 -/* Configure the IBUFLVL2 = the size of V3 protocol header */ -#define SHI_IBUFLVL2_THRESHOLD (sizeof(struct ec_host_request)) -/* Half output buffer size */ -#define SHI_OBUF_HALF_SIZE (SHI_OBUF_FULL_SIZE / 2) -/* Half input buffer size */ -#define SHI_IBUF_HALF_SIZE (SHI_IBUF_FULL_SIZE / 2) - -/* - * Timeout to wait for SHI request packet - * - * This affects the slowest SPI clock we can support. A delay of 8192 us - * permits a 512-byte request at 500 KHz, assuming the SPI controller starts - * sending bytes as soon as it asserts chip select. That's as slow as we would - * practically want to run the SHI interface, since running it slower - * significantly impacts firmware update times. - */ -#define SHI_CMD_RX_TIMEOUT_MS 9 - -/* - * The AP blindly clocks back bytes over the SPI interface looking for a - * framing byte. So this preamble must always precede the actual response - * packet. - */ -#define SHI_OUT_PREAMBLE_LENGTH 2 - -/* - * Space allocation of the past-end status byte (EC_SPI_PAST_END) in the out_msg - * buffer. - */ -#define EC_SPI_PAST_END_LENGTH 1 -/* - * Space allocation of the frame status byte (EC_SPI_FRAME_START) in the out_msg - * buffer. - */ -#define EC_SPI_FRAME_START_LENGTH 1 - -/* - * Offset of output parameters needs to account for pad and framing bytes and - * one last past-end byte at the end so any additional bytes clocked out by - * the AP will have a known and identifiable value. - */ -#define SHI_PROTO3_OVERHEAD (EC_SPI_PAST_END_LENGTH + EC_SPI_FRAME_START_LENGTH) - -/* - * Max data size for a version 3 request/response packet. This is big enough - * to handle a request/response header, flash write offset/size, and 512 bytes - * of flash data: - * sizeof(ec_host_request): 8 - * sizeof(ec_params_flash_write): 8 - * payload 512 - */ -#define SHI_MAX_REQUEST_SIZE CONFIG_CROS_SHI_MAX_REQUEST -#define SHI_MAX_RESPONSE_SIZE CONFIG_CROS_SHI_MAX_RESPONSE - -/* - * Our input and output msg buffers. These must be large enough for our largest - * message, including protocol overhead. The pointers after the protocol - * overhead, as passed to the host command handler, must be 32-bit aligned. - */ -#define SHI_OUT_START_PAD (4 * (EC_SPI_FRAME_START_LENGTH / 4 + 1)) -#define SHI_OUT_END_PAD (4 * (EC_SPI_PAST_END_LENGTH / 4 + 1)) -static uint8_t out_msg_padded[SHI_OUT_START_PAD + SHI_MAX_RESPONSE_SIZE + - SHI_OUT_END_PAD] __aligned(4); -static uint8_t *const out_msg = - out_msg_padded + SHI_OUT_START_PAD - EC_SPI_FRAME_START_LENGTH; -static uint8_t in_msg[SHI_MAX_REQUEST_SIZE] __aligned(4); - -/* Parameters used by host protocols */ -static struct host_packet shi_packet; - -enum cros_shi_npcx_state { - SHI_STATE_NONE = -1, - /* SHI not enabled (initial state, and when chipset is off) */ - SHI_STATE_DISABLED = 0, - /* Ready to receive next request */ - SHI_STATE_READY_TO_RECV, - /* Receiving request */ - SHI_STATE_RECEIVING, - /* Processing request */ - SHI_STATE_PROCESSING, - /* Canceling response since CS deasserted and output NOT_READY byte */ - SHI_STATE_CNL_RESP_NOT_RDY, - /* Sending response */ - SHI_STATE_SENDING, - /* Received data is invalid */ - SHI_STATE_BAD_RECEIVED_DATA, -}; - -static enum cros_shi_npcx_state state; - -/* Device config */ -struct cros_shi_npcx_config { - /* Serial Host Interface (SHI) base address */ - uintptr_t base; - /* clock configuration */ - struct npcx_clk_cfg clk_cfg; - /* pinmux configuration */ - const uint8_t alts_size; - const struct npcx_alt *alts_list; - /* SHI IRQ */ - int irq; - struct npcx_wui shi_cs_wui; -}; - -/* SHI bus parameters */ -struct shi_bus_parameters { - uint8_t *rx_msg; /* Entry pointer of msg rx buffer */ - uint8_t *tx_msg; /* Entry pointer of msg tx buffer */ - volatile uint8_t *rx_buf; /* Entry pointer of receive buffer */ - volatile uint8_t *tx_buf; /* Entry pointer of transmit buffer */ - uint16_t sz_received; /* Size of received data in bytes */ - uint16_t sz_sending; /* Size of sending data in bytes */ - uint16_t sz_request; /* request bytes need to receive */ - uint16_t sz_response; /* response bytes need to receive */ - uint64_t rx_deadline; /* deadline of receiving */ -} shi_params; - -static const struct npcx_alt cros_shi_alts[] = NPCX_DT_ALT_ITEMS_LIST(0); - -static const struct cros_shi_npcx_config cros_shi_cfg = { - .base = DT_INST_REG_ADDR(0), - .clk_cfg = NPCX_DT_CLK_CFG_ITEM(0), - .alts_size = ARRAY_SIZE(cros_shi_alts), - .alts_list = cros_shi_alts, - .irq = DT_INST_IRQN(0), - .shi_cs_wui = NPCX_DT_WUI_ITEM_BY_NAME(0, shi_cs_wui), -}; - -struct cros_shi_npcx_data { - struct host_packet shi_packet; - sys_slist_t callbacks; -}; - -/* Driver convenience defines */ -#define DRV_CONFIG(dev) ((const struct cros_shi_npcx_config *)(dev)->config) -#define DRV_DATA(dev) ((struct cros_shi_npcx_data *)(dev)->data) -#define HAL_INSTANCE(dev) (struct shi_reg *)(DRV_CONFIG(dev)->base) - -/* Forward declaration */ -static void cros_shi_npcx_reset_prepare(struct shi_reg *const inst); - -/* Read pointer of input or output buffer by consecutive reading */ -static uint32_t shi_read_buf_pointer(struct shi_reg *const inst) -{ - uint8_t stat; - - /* Wait for two consecutive equal values are read */ - do { - stat = inst->IBUFSTAT; - } while (stat != inst->IBUFSTAT); - - return (uint32_t)stat; -} - -/* - * Valid offset of SHI output buffer to write. - * When SIMUL bit is set, IBUFPTR can be used instead of OBUFPTR - */ -static uint32_t shi_valid_obuf_offset(struct shi_reg *const inst) -{ - return (shi_read_buf_pointer(inst) + SHI_OUT_PREAMBLE_LENGTH) % - SHI_OBUF_FULL_SIZE; -} - -/* - * This routine write SHI next half output buffer from msg buffer - */ -static void shi_write_half_outbuf(void) -{ - const uint32_t size = - MIN(SHI_OBUF_HALF_SIZE, - shi_params.sz_response - shi_params.sz_sending); - uint8_t *obuf_ptr = (uint8_t *)shi_params.tx_buf; - const uint8_t *obuf_end = obuf_ptr + size; - uint8_t *msg_ptr = shi_params.tx_msg; - - /* Fill half output buffer */ - while (obuf_ptr != obuf_end) - *obuf_ptr++ = *msg_ptr++; - - shi_params.sz_sending += size; - shi_params.tx_buf = obuf_ptr; - shi_params.tx_msg = msg_ptr; -} - -/* - * This routine read SHI input buffer to msg buffer until - * we have received a certain number of bytes - */ -static int shi_read_inbuf_wait(struct shi_reg *const inst, uint32_t szbytes) -{ - /* Copy data to msg buffer from input buffer */ - for (uint32_t i = 0; i < szbytes; i++, shi_params.sz_received++) { - /* - * If input buffer pointer equals pointer which wants to read, - * it means data is not ready. - */ - while (shi_params.rx_buf == - inst->IBUF + shi_read_buf_pointer(inst)) { - if (k_uptime_get() > shi_params.rx_deadline) { - return 0; - } - } - /* Restore data to msg buffer */ - *shi_params.rx_msg++ = *shi_params.rx_buf++; - } - return 1; -} - -/* This routine fills out all SHI output buffer with status byte */ -static void shi_fill_out_status(struct shi_reg *const inst, uint8_t status) -{ - uint8_t start, end; - volatile uint8_t *fill_ptr; - volatile uint8_t *fill_end; - volatile uint8_t *obuf_end; - - /* - * Disable interrupts in case the interfere by the other interrupts. - * Use __disable_irq/__enable_irq instead of using irq_lock/irq_unlock - * here because irq_lock/irq_unlock leave some system exceptions (like - * SVC, NMI, and faults) still enabled. - */ - __disable_irq(); - - /* - * Fill out output buffer with status byte and leave a gap for PREAMBLE. - * The gap guarantees the synchronization. The critical section should - * be done within this gap. No racing happens. - */ - start = shi_valid_obuf_offset(inst); - end = (start + SHI_OBUF_FULL_SIZE - SHI_OUT_PREAMBLE_LENGTH) % - SHI_OBUF_FULL_SIZE; - - fill_ptr = inst->OBUF + start; - fill_end = inst->OBUF + end; - obuf_end = inst->OBUF + SHI_OBUF_FULL_SIZE; - while (fill_ptr != fill_end) { - *fill_ptr++ = status; - if (fill_ptr == obuf_end) - fill_ptr = inst->OBUF; - } - - /* End of critical section */ - __enable_irq(); -} - -/* This routine handles shi received unexpected data */ -static void shi_bad_received_data(struct shi_reg *const inst) -{ - /* State machine mismatch, timeout, or protocol we can't handle. */ - shi_fill_out_status(inst, EC_SPI_RX_BAD_DATA); - state = SHI_STATE_BAD_RECEIVED_DATA; - - DEBUG_CPRINTF("BAD-"); - DEBUG_CPRINTF("in_msg=["); - for (uint32_t i = 0; i < shi_params.sz_received; i++) - DEBUG_CPRINTF("%02x ", in_msg[i]); - DEBUG_CPRINTF("]\n"); - - /* Reset shi's state machine for error recovery */ - cros_shi_npcx_reset_prepare(inst); - - DEBUG_CPRINTF("END\n"); -} - -/* - * This routine write SHI output buffer from msg buffer over halt of it. - * It make sure we have enough time to handle next operations. - */ -static void shi_write_first_pkg_outbuf(struct shi_reg *const inst, - uint16_t szbytes) -{ - uint8_t size, offset; - volatile uint8_t *obuf_ptr; - volatile uint8_t *obuf_end; - uint8_t *msg_ptr; - uint32_t half_buf_remain; /* Remains in half buffer are free to write */ - - /* Start writing at our current OBUF position */ - offset = shi_valid_obuf_offset(inst); - obuf_ptr = inst->OBUF + offset; - msg_ptr = shi_params.tx_msg; - - /* Fill up to OBUF mid point, or OBUF end */ - half_buf_remain = SHI_OBUF_HALF_SIZE - (offset % SHI_OBUF_HALF_SIZE); - size = MIN(half_buf_remain, szbytes - shi_params.sz_sending); - obuf_end = obuf_ptr + size; - while (obuf_ptr != obuf_end) - *obuf_ptr++ = *msg_ptr++; - - /* Track bytes sent for later accounting */ - shi_params.sz_sending += size; - - /* Write data to beginning of OBUF if we've reached the end */ - if (obuf_ptr == inst->OBUF + SHI_IBUF_FULL_SIZE) - obuf_ptr = inst->OBUF; - - /* Fill next half output buffer */ - size = MIN(SHI_OBUF_HALF_SIZE, szbytes - shi_params.sz_sending); - obuf_end = obuf_ptr + size; - while (obuf_ptr != obuf_end) - *obuf_ptr++ = *msg_ptr++; - - /* Track bytes sent / last OBUF position written for later accounting */ - shi_params.sz_sending += size; - shi_params.tx_buf = obuf_ptr; - shi_params.tx_msg = msg_ptr; -} - -/** - * Called to send a response back to the host. - * - * Some commands can continue for a while. This function is called by - * host_command task after processing request is completed. It fills up the - * FIFOs with response package and the remaining data is handled in shi's ISR. - */ -static void shi_send_response_packet(struct host_packet *pkt) -{ - struct shi_reg *const inst = (struct shi_reg *)(cros_shi_cfg.base); - - /* - * Disable interrupts. This routine is not called from interrupt - * context and buffer underrun will likely occur if it is - * preempted after writing its initial reply byte. Also, we must be - * sure our state doesn't unexpectedly change, in case we're expected - * to take RESP_NOT_RDY actions. - */ - __disable_irq(); - - if (state == SHI_STATE_PROCESSING) { - /* Append our past-end byte, which we reserved space for. */ - ((uint8_t *)pkt->response)[pkt->response_size] = - EC_SPI_PAST_END; - - /* Computing sending bytes of response */ - shi_params.sz_response = - pkt->response_size + SHI_PROTO3_OVERHEAD; - - /* Start to fill output buffer with msg buffer */ - shi_write_first_pkg_outbuf(inst, shi_params.sz_response); - /* Transmit the reply */ - state = SHI_STATE_SENDING; - DEBUG_CPRINTF("SND-"); - } else if (state == SHI_STATE_CNL_RESP_NOT_RDY) { - /* - * If we're not processing, then the AP has already terminated - * the transaction, and won't be listening for a response. - * Reset state machine for next transaction. - */ - cros_shi_npcx_reset_prepare(inst); - DEBUG_CPRINTF("END\n"); - } else - DEBUG_CPRINTS("Unexpected state %d in response handler", state); - - __enable_irq(); -} - -void shi_handle_host_package(struct shi_reg *const inst) -{ - uint32_t sz_inbuf_int = shi_params.sz_request / SHI_IBUF_HALF_SIZE; - uint32_t cnt_inbuf_int = shi_params.sz_received / SHI_IBUF_HALF_SIZE; - - if (sz_inbuf_int - cnt_inbuf_int) - /* Need to receive data from buffer */ - return; - uint32_t remain_bytes = shi_params.sz_request - shi_params.sz_received; - - /* Read remaining bytes from input buffer */ - if (!shi_read_inbuf_wait(inst, remain_bytes)) - return shi_bad_received_data(inst); - - /* Move to processing state */ - state = SHI_STATE_PROCESSING; - DEBUG_CPRINTF("PRC-"); - - /* Fill output buffer to indicate we`re processing request */ - shi_fill_out_status(inst, EC_SPI_PROCESSING); - - /* Set up parameters for host request */ - shi_packet.send_response = shi_send_response_packet; - - shi_packet.request = in_msg; - shi_packet.request_temp = NULL; - shi_packet.request_max = sizeof(in_msg); - shi_packet.request_size = shi_params.sz_request; - - /* Put FRAME_START in first byte */ - out_msg[0] = EC_SPI_FRAME_START; - shi_packet.response = out_msg + EC_SPI_FRAME_START_LENGTH; - - /* Reserve space for frame start and trailing past-end byte */ - shi_packet.response_max = SHI_MAX_RESPONSE_SIZE; - shi_packet.response_size = 0; - shi_packet.driver_result = EC_RES_SUCCESS; - - /* Go to common layer to handle request */ - host_packet_receive(&shi_packet); -} - -static void shi_parse_header(struct shi_reg *const inst) -{ - /* We're now inside a transaction */ - state = SHI_STATE_RECEIVING; - DEBUG_CPRINTF("RV-"); - - /* Setup deadline time for receiving */ - shi_params.rx_deadline = k_uptime_get() + SHI_CMD_RX_TIMEOUT_MS; - - /* Wait for version, command, length bytes */ - if (!shi_read_inbuf_wait(inst, 3)) - return shi_bad_received_data(inst); - - if (in_msg[0] == EC_HOST_REQUEST_VERSION) { - /* Protocol version 3 */ - struct ec_host_request *r = (struct ec_host_request *)in_msg; - int pkt_size; - /* - * If request is over half of input buffer, - * we need to modified the algorithm again. - */ - __ASSERT_NO_MSG(sizeof(*r) < SHI_IBUF_HALF_SIZE); - - /* Wait for the rest of the command header */ - if (!shi_read_inbuf_wait(inst, sizeof(*r) - 3)) - return shi_bad_received_data(inst); - - /* Check how big the packet should be */ - pkt_size = host_request_expected_size(r); - if (pkt_size == 0 || pkt_size > sizeof(in_msg)) - return shi_bad_received_data(inst); - - /* Computing total bytes need to receive */ - shi_params.sz_request = pkt_size; - - shi_handle_host_package(inst); - } else { - /* Invalid version number */ - return shi_bad_received_data(inst); - } -} - -static void shi_sec_ibf_int_enable(struct shi_reg *const inst, int enable) -{ - if (enable) { - /* Setup IBUFLVL2 threshold and enable it */ - inst->SHICFG5 |= BIT(NPCX_SHICFG5_IBUFLVL2DIS); - SET_FIELD(inst->SHICFG5, NPCX_SHICFG5_IBUFLVL2, - SHI_IBUFLVL2_THRESHOLD); - inst->SHICFG5 &= ~BIT(NPCX_SHICFG5_IBUFLVL2DIS); - /* Enable IBHF2 event */ - inst->EVENABLE2 |= BIT(NPCX_EVENABLE2_IBHF2EN); - } else { - /* Disable IBHF2 event first */ - inst->EVENABLE2 &= ~BIT(NPCX_EVENABLE2_IBHF2EN); - /* Disable IBUFLVL2 and set threshold back to zero */ - inst->SHICFG5 |= BIT(NPCX_SHICFG5_IBUFLVL2DIS); - SET_FIELD(inst->SHICFG5, NPCX_SHICFG5_IBUFLVL2, 0); - } -} - -/* This routine copies SHI half input buffer data to msg buffer */ -static void shi_read_half_inbuf(void) -{ - /* - * Copy to read buffer until reaching middle/top address of - * input buffer or completing receiving data - */ - do { - /* Restore data to msg buffer */ - *shi_params.rx_msg++ = *shi_params.rx_buf++; - shi_params.sz_received++; - } while (shi_params.sz_received % SHI_IBUF_HALF_SIZE && - shi_params.sz_received != shi_params.sz_request); -} - -/* - * Avoid spamming the console with prints every IBF / IBHF interrupt, if - * we find ourselves in an unexpected state. - */ -static enum cros_shi_npcx_state last_error_state = SHI_STATE_NONE; - -static void log_unexpected_state(char *isr_name) -{ - if (state != last_error_state) - DEBUG_CPRINTF("Unexpected state %d in %s ISR", state, isr_name); - last_error_state = state; -} - -static void shi_handle_cs_assert(struct shi_reg *const inst) -{ - /* If not enabled, ignore glitches on SHI_CS_L */ - if (state == SHI_STATE_DISABLED) - return; - - /* NOT_READY should be sent and there're no spi transaction now. */ - if (state == SHI_STATE_CNL_RESP_NOT_RDY) - return; - - /* Chip select is low = asserted */ - if (state != SHI_STATE_READY_TO_RECV) { - /* State machine should be reset in EVSTAT_EOR ISR */ - DEBUG_CPRINTF("Unexpected state %d in CS ISR", state); - return; - } - - DEBUG_CPRINTF("CSL-"); - - /* - * Clear possible EOR event from previous transaction since it's - * irrelevant now that CS is re-asserted. - */ - inst->EVSTAT = BIT(NPCX_EVSTAT_EOR); - - /* Do not deep sleep during SHI transaction */ - disable_sleep(SLEEP_MASK_SPI); -} - -static void shi_handle_cs_deassert(struct shi_reg *const inst) -{ - /* - * If the buffer is still used by the host command. - * Change state machine for response handler. - */ - if (state == SHI_STATE_PROCESSING) { - /* - * Mark not ready to prevent the other - * transaction immediately - */ - shi_fill_out_status(inst, EC_SPI_NOT_READY); - - state = SHI_STATE_CNL_RESP_NOT_RDY; - - /* - * Disable SHI interrupt, it will remain disabled - * until shi_send_response_packet() is called and - * CS is asserted for a new transaction. - */ - irq_disable(DT_INST_IRQN(0)); - - DEBUG_CPRINTF("CNL-"); - return; - /* Next transaction but we're not ready */ - } else if (state == SHI_STATE_CNL_RESP_NOT_RDY) { - return; - } - - /* Error state for checking*/ - if (state != SHI_STATE_SENDING) { - log_unexpected_state("CSNRE"); - } - /* reset SHI and prepare to next transaction again */ - cros_shi_npcx_reset_prepare(inst); - DEBUG_CPRINTF("END\n"); -} - -static void shi_handle_input_buf_half_full(struct shi_reg *const inst) -{ - if (state == SHI_STATE_RECEIVING) { - /* Read data from input to msg buffer */ - shi_read_half_inbuf(); - return shi_handle_host_package(inst); - } else if (state == SHI_STATE_SENDING) { - /* Write data from msg buffer to output buffer */ - if (shi_params.tx_buf == inst->OBUF + SHI_OBUF_FULL_SIZE) { - /* Write data from bottom address again */ - shi_params.tx_buf = inst->OBUF; - return shi_write_half_outbuf(); - } else /* ignore it */ - return; - } else if (state == SHI_STATE_PROCESSING) { - /* Wait for host to handle request */ - } else { - /* Unexpected status */ - log_unexpected_state("IBHF"); - } -} - -static void shi_handle_input_buf_full(struct shi_reg *const inst) -{ - if (state == SHI_STATE_RECEIVING) { - /* read data from input to msg buffer */ - shi_read_half_inbuf(); - /* Read to bottom address again */ - shi_params.rx_buf = inst->IBUF; - return shi_handle_host_package(inst); - } else if (state == SHI_STATE_SENDING) { - /* Write data from msg buffer to output buffer */ - if (shi_params.tx_buf == inst->OBUF + SHI_OBUF_HALF_SIZE) - return shi_write_half_outbuf(); - else /* ignore it */ - return; - } else if (state == SHI_STATE_PROCESSING) { - /* Wait for host to handle request */ - return; - } - /* Unexpected status */ - log_unexpected_state("IBF"); -} - -static void cros_shi_npcx_isr(const struct device *dev) -{ - uint8_t stat; - uint8_t stat2; - struct shi_reg *const inst = HAL_INSTANCE(dev); - - /* Read status register and clear interrupt status early */ - stat = inst->EVSTAT; - inst->EVSTAT = stat; - stat2 = inst->EVSTAT2; - - /* SHI CS pin is asserted in EVSTAT2 */ - if (IS_BIT_SET(stat2, NPCX_EVSTAT2_CSNFE)) { - /* Clear pending bit of CSNFE */ - inst->EVSTAT2 = BIT(NPCX_EVSTAT2_CSNFE); - DEBUG_CPRINTF("CSNFE-"); - /* - * BUSY bit is set when SHI_CS is asserted. If not, leave it for - * SHI_CS de-asserted event. - */ - if (!IS_BIT_SET(inst->SHICFG2, NPCX_SHICFG2_BUSY)) { - DEBUG_CPRINTF("CSNB-"); - return; - } - shi_handle_cs_assert(inst); - } - - /* - * End of data for read/write transaction. i.e. SHI_CS is deasserted. - * Host completed or aborted transaction - * - * EOR has the limitation that it will not be set even if the SHI_CS is - * deasserted without SPI clocks. The new SHI module introduce the - * CSNRE bit which will be set when SHI_CS is deasserted regardless of - * SPI clocks. - */ - if (IS_BIT_SET(stat2, NPCX_EVSTAT2_CSNRE)) { - /* Clear pending bit of CSNRE */ - inst->EVSTAT2 = BIT(NPCX_EVSTAT2_CSNRE); - /* - * We're not in proper state. - * Mark not ready to abort next transaction - */ - DEBUG_CPRINTF("CSH-"); - return shi_handle_cs_deassert(inst); - } - - /* - * The number of bytes received reaches the size of - * protocol V3 header(=8) after CS asserted. - */ - if (IS_BIT_SET(stat2, NPCX_EVSTAT2_IBHF2)) { - /* Clear IBHF2 */ - inst->EVSTAT2 = BIT(NPCX_EVSTAT2_IBHF2); - DEBUG_CPRINTF("HDR-"); - /* Disable second IBF interrupt and start to parse header */ - shi_sec_ibf_int_enable(inst, 0); - shi_parse_header(inst); - } - - /* - * Indicate input/output buffer pointer reaches the half buffer size. - * Transaction is processing. - */ - if (IS_BIT_SET(stat, NPCX_EVSTAT_IBHF)) { - return shi_handle_input_buf_half_full(inst); - } - - /* - * Indicate input/output buffer pointer reaches the full buffer size. - * Transaction is processing. - */ - if (IS_BIT_SET(stat, NPCX_EVSTAT_IBF)) { - return shi_handle_input_buf_full(inst); - } -} - -static void cros_shi_npcx_reset_prepare(struct shi_reg *const inst) -{ - uint32_t i; - - state = SHI_STATE_DISABLED; - - irq_disable(DT_INST_IRQN(0)); - - /* Disable SHI unit to clear all status bits */ - inst->SHICFG1 &= ~BIT(NPCX_SHICFG1_EN); - - /* Initialize parameters of next transaction */ - shi_params.rx_msg = in_msg; - shi_params.tx_msg = out_msg; - shi_params.rx_buf = inst->IBUF; - shi_params.tx_buf = inst->IBUF + SHI_OBUF_HALF_SIZE; - shi_params.sz_received = 0; - shi_params.sz_sending = 0; - shi_params.sz_request = 0; - shi_params.sz_response = 0; - - /* - * Fill output buffer to indicate we`re - * ready to receive next transaction. - */ - for (i = 1; i < SHI_OBUF_FULL_SIZE; i++) - inst->OBUF[i] = EC_SPI_RECEIVING; - inst->OBUF[0] = EC_SPI_OLD_READY; - - /* SHI/Host Write/input buffer wrap-around enable */ - inst->SHICFG1 = BIT(NPCX_SHICFG1_IWRAP) | BIT(NPCX_SHICFG1_WEN) | - BIT(NPCX_SHICFG1_EN); - - state = SHI_STATE_READY_TO_RECV; - last_error_state = SHI_STATE_NONE; - - shi_sec_ibf_int_enable(inst, 1); - irq_enable(DT_INST_IRQN(0)); - - /* Allow deep sleep at the end of SHI transaction */ - enable_sleep(SLEEP_MASK_SPI); - - DEBUG_CPRINTF("RDY-"); -} - -static int cros_shi_npcx_enable(const struct device *dev) -{ - const struct cros_shi_npcx_config *const config = DRV_CONFIG(dev); - struct shi_reg *const inst = HAL_INSTANCE(dev); - - cros_shi_npcx_reset_prepare(inst); - npcx_miwu_irq_disable(&config->shi_cs_wui); - - /* Configure pin-mux from GPIO to SHI. */ - npcx_pinctrl_mux_configure(config->alts_list, config->alts_size, 1); - - NVIC_ClearPendingIRQ(DT_INST_IRQN(0)); - npcx_miwu_irq_enable(&config->shi_cs_wui); - irq_enable(DT_INST_IRQN(0)); - - return 0; -} - -static int cros_shi_npcx_disable(const struct device *dev) -{ - const struct cros_shi_npcx_config *const config = DRV_CONFIG(dev); - - state = SHI_STATE_DISABLED; - - irq_disable(DT_INST_IRQN(0)); - npcx_miwu_irq_disable(&config->shi_cs_wui); - - /* Configure pin-mux from SHI to GPIO. */ - npcx_pinctrl_mux_configure(config->alts_list, config->alts_size, 0); - - /* - * Allow deep sleep again in case CS dropped before ec was - * informed in hook function and turn off SHI's interrupt in time. - */ - enable_sleep(SLEEP_MASK_SPI); - - return 0; -} - -static int shi_npcx_init(const struct device *dev) -{ - int ret; - const struct cros_shi_npcx_config *const config = DRV_CONFIG(dev); - struct shi_reg *const inst = HAL_INSTANCE(dev); - const struct device *clk_dev = DEVICE_DT_GET(NPCX_CLK_CTRL_NODE); - - /* Turn on shi device clock first */ - ret = clock_control_on(clk_dev, - (clock_control_subsys_t *)&config->clk_cfg); - if (ret < 0) { - DEBUG_CPRINTF("Turn on SHI clock fail %d", ret); - return ret; - } - - /* If booter doesn't set the host interface type */ - if (!NPCX_BOOTER_IS_HIF_TYPE_SET()) { - npcx_host_interface_sel(NPCX_HIF_TYPE_ESPI_SHI); - } - - /* - * SHICFG1 (SHI Configuration 1) setting - * [7] - IWRAP = 1: Wrap input buffer to the first address - * [6] - CPOL = 0: Sampling on rising edge and output on falling edge - * [5] - DAS = 0: return STATUS reg data after Status command - * [4] - AUTOBE = 0: Automatically update the OBES bit in STATUS reg - * [3] - AUTIBF = 0: Automatically update the IBFS bit in STATUS reg - * [2] - WEN = 0: Enable host write to input buffer - * [1] - Reserved 0 - * [0] - ENABLE = 0: Disable SHI at the beginning - */ - inst->SHICFG1 = 0x80; - - /* - * SHICFG2 (SHI Configuration 2) setting - * [7] - Reserved 0 - * [6] - REEVEN = 0: Restart events are not used - * [5] - Reserved 0 - * [4] - REEN = 0: Restart transactions are not used - * [3] - SLWU = 0: Seem-less wake-up is enabled by default - * [2] - ONESHOT= 0: WEN is cleared at the end of a write transaction - * [1] - BUSY = 0: SHI bus is busy 0: idle. - * [0] - SIMUL = 1: Turn on simultaneous Read/Write - */ - inst->SHICFG2 = 0x01; - - /* - * EVENABLE (Event Enable) setting - * [7] - IBOREN = 0: Input buffer overrun interrupt enable - * [6] - STSREN = 0: status read interrupt disable - * [5] - EOWEN = 0: End-of-Data for Write Transaction Interrupt Enable - * [4] - EOREN = 1: End-of-Data for Read Transaction Interrupt Enable - * [3] - IBHFEN = 1: Input Buffer Half Full Interrupt Enable - * [2] - IBFEN = 1: Input Buffer Full Interrupt Enable - * [1] - OBHEEN = 0: Output Buffer Half Empty Interrupt Enable - * [0] - OBEEN = 0: Output Buffer Empty Interrupt Enable - */ - inst->EVENABLE = 0x1C; - - /* - * EVENABLE2 (Event Enable 2) setting - * [2] - CSNFEEN = 1: SHI_CS Falling Edge Interrupt Enable - * [1] - CSNREEN = 1: SHI_CS Rising Edge Interrupt Enable - * [0] - IBHF2EN = 0: Input Buffer Half Full 2 Interrupt Enable - */ - inst->EVENABLE2 = 0x06; - - /* Clear SHI events status register */ - inst->EVSTAT = 0xff; - - npcx_miwu_interrupt_configure(&config->shi_cs_wui, NPCX_MIWU_MODE_EDGE, - NPCX_MIWU_TRIG_LOW); - /* SHI interrupt installation */ - IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), - cros_shi_npcx_isr, DEVICE_DT_INST_GET(0), 0); - - return ret; -} - -static const struct cros_shi_driver_api cros_shi_npcx_driver_api = { - .enable = cros_shi_npcx_enable, - .disable = cros_shi_npcx_disable, -}; - -static struct cros_shi_npcx_data cros_shi_data; -DEVICE_DT_INST_DEFINE(0, shi_npcx_init, /* pm_control_fn= */ NULL, - &cros_shi_data, &cros_shi_cfg, PRE_KERNEL_1, - CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, - &cros_shi_npcx_driver_api); - -/* KBS register structure check */ -NPCX_REG_SIZE_CHECK(shi_reg, 0x120); -NPCX_REG_OFFSET_CHECK(shi_reg, SHICFG1, 0x001); -NPCX_REG_OFFSET_CHECK(shi_reg, EVENABLE, 0x005); -NPCX_REG_OFFSET_CHECK(shi_reg, IBUFSTAT, 0x00a); -NPCX_REG_OFFSET_CHECK(shi_reg, EVENABLE2, 0x010); -NPCX_REG_OFFSET_CHECK(shi_reg, OBUF, 0x020); -NPCX_REG_OFFSET_CHECK(shi_reg, IBUF, 0x0A0); diff --git a/zephyr/drivers/cros_system/CMakeLists.txt b/zephyr/drivers/cros_system/CMakeLists.txt deleted file mode 100644 index 733b8be450..0000000000 --- a/zephyr/drivers/cros_system/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# Copyright 2021 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -zephyr_library_sources_ifdef(CONFIG_CROS_SYSTEM_IT8XXX2 cros_system_it8xxx2.c) -zephyr_library_sources_ifdef(CONFIG_CROS_SYSTEM_NPCX cros_system_npcx.c) diff --git a/zephyr/drivers/cros_system/Kconfig b/zephyr/drivers/cros_system/Kconfig deleted file mode 100644 index c5d98b6081..0000000000 --- a/zephyr/drivers/cros_system/Kconfig +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright 2021 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -menuconfig CROS_SYSTEM_NPCX - bool "Nuvoton NPCX cros system driver" - depends on SOC_FAMILY_NPCX - default y - help - This option enables the cros system driver for the NPCX family of - processors. Currently, Zephyr doesn't provide the system related API. - The cros system driver provides the low-level driver related to - chromium ec system functionality. - -if CROS_SYSTEM_NPCX - -config CROS_SYSTEM_NPCX_INIT_PRIORITY - int "cros_system npcx initialization priority" - default 10 - range 10 19 - help - This sets the npcx cros_system driver initialization priority. The - cros_system driver provides access to the NPCX reset cause and must be - higher priority than CONFIG_SYSTEM_PRE_INIT_PRIORITY. - -endif # CROS_SYSTEM_NPCX - -config CROS_SYSTEM_IT8XXX2 - bool "ITE IT8XXX2 cros system driver" - depends on SOC_FAMILY_RISCV_ITE - default y - help - This option enables the cros system driver for the it8xxx2 family of - processors. - -if CROS_SYSTEM_IT8XXX2 - -config CROS_SYSTEM_IT8XXX2_INIT_PRIORITY - int "cros_system it8xxx2 initialization priority" - default 10 - help - This sets the it8xxx2 cros_system driver initialization priority. - The cros_system driver provides access to the it8xxx2 reset cause - and must be higher priority than - CONFIG_PLATFORM_EC_SYSTEM_PRE_INIT_PRIORITY. - -endif # CROS_SYSTEM_IT8XXX2 diff --git a/zephyr/drivers/cros_system/cros_system_it8xxx2.c b/zephyr/drivers/cros_system/cros_system_it8xxx2.c deleted file mode 100644 index 5731dcf984..0000000000 --- a/zephyr/drivers/cros_system/cros_system_it8xxx2.c +++ /dev/null @@ -1,246 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define DT_DRV_COMPAT ite_it8xxx2_gctrl - -#include <device.h> -#include <drivers/cros_system.h> -#include <logging/log.h> -#include <soc.h> -#include <soc/ite_it8xxx2/reg_def_cros.h> - -#include "gpio.h" -#include "system.h" -#include "util.h" - -LOG_MODULE_REGISTER(cros_system, LOG_LEVEL_ERR); - -#define GCTRL_IT8XXX2_REG_BASE \ - ((struct gctrl_it8xxx2_regs *)DT_INST_REG_ADDR(0)) - -#define WDT_IT8XXX2_REG_BASE \ - ((struct wdt_it8xxx2_regs *)DT_REG_ADDR(DT_NODELABEL(twd0))) - -static const char *cros_system_it8xxx2_get_chip_vendor(const struct device *dev) -{ - ARG_UNUSED(dev); - - return "ite"; -} - -static uint32_t system_get_chip_id(void) -{ - struct gctrl_it8xxx2_regs *const gctrl_base = GCTRL_IT8XXX2_REG_BASE; - - return (gctrl_base->GCTRL_ECHIPID1 << 16) | - (gctrl_base->GCTRL_ECHIPID2 << 8) | - gctrl_base->GCTRL_ECHIPID3; -} - -static uint8_t system_get_chip_version(void) -{ - struct gctrl_it8xxx2_regs *const gctrl_base = GCTRL_IT8XXX2_REG_BASE; - - /* bit[3-0], chip version */ - return gctrl_base->GCTRL_ECHIPVER & 0x0F; -} - -static const char *cros_system_it8xxx2_get_chip_name(const struct device *dev) -{ - ARG_UNUSED(dev); - - static char buf[8] = {'i', 't'}; - uint32_t chip_id = system_get_chip_id(); - int num = 4; - - for (int n = 2; num >= 0; n++, num--) - snprintf(buf+n, (sizeof(buf)-n), "%x", - chip_id >> (num * 4) & 0xF); - - return buf; -} - -static const char *cros_system_it8xxx2_get_chip_revision(const struct device - *dev) -{ - ARG_UNUSED(dev); - - static char buf[3]; - uint8_t rev = system_get_chip_version(); - - snprintf(buf, sizeof(buf), "%1xx", rev+0xa); - - return buf; -} - -static int cros_system_it8xxx2_get_reset_cause(const struct device *dev) -{ - ARG_UNUSED(dev); - struct gctrl_it8xxx2_regs *const gctrl_base = GCTRL_IT8XXX2_REG_BASE; - /* system reset flag */ - uint32_t system_flags = chip_read_reset_flags(); - int chip_reset_cause = 0; - uint8_t raw_reset_cause = gctrl_base->GCTRL_RSTS & IT8XXX2_GCTRL_LRS; - uint8_t raw_reset_cause2 = gctrl_base->GCTRL_SPCTRL4 & - (IT8XXX2_GCTRL_LRSIWR | IT8XXX2_GCTRL_LRSIPWRSWTR | - IT8XXX2_GCTRL_LRSIPGWR); - - /* Clear reset cause. */ - gctrl_base->GCTRL_RSTS |= IT8XXX2_GCTRL_LRS; - gctrl_base->GCTRL_SPCTRL4 |= (IT8XXX2_GCTRL_LRSIWR | - IT8XXX2_GCTRL_LRSIPWRSWTR | IT8XXX2_GCTRL_LRSIPGWR); - - /* Determine if watchdog reset or power on reset. */ - if (raw_reset_cause & IT8XXX2_GCTRL_IWDTR) { - system_flags |= EC_RESET_FLAG_WATCHDOG; - chip_reset_cause = WATCHDOG_RST; - } else if (raw_reset_cause < 2) { - system_flags |= EC_RESET_FLAG_POWER_ON; - chip_reset_cause = POWERUP; - } - /* Determine reset-pin reset. */ - if (raw_reset_cause2 & IT8XXX2_GCTRL_LRSIWR) { - system_flags |= EC_RESET_FLAG_RESET_PIN; - chip_reset_cause = VCC1_RST_PIN; - } - - /* watchdog module triggers these reset */ - if (system_flags & (EC_RESET_FLAG_HARD | EC_RESET_FLAG_SOFT)) - system_flags &= ~EC_RESET_FLAG_WATCHDOG; - - /* Set the system reset flags. */ - system_set_reset_flags(system_flags); - - return chip_reset_cause; -} - -static int cros_system_it8xxx2_init(const struct device *dev) -{ - struct gctrl_it8xxx2_regs *const gctrl_base = GCTRL_IT8XXX2_REG_BASE; - - /* System triggers a soft reset by default (command: reboot). */ - gctrl_base->GCTRL_ETWDUARTCR &= ~IT8XXX2_GCTRL_ETWD_HW_RST_EN; - - return 0; -} - -static int cros_system_it8xxx2_soc_reset(const struct device *dev) -{ - struct gctrl_it8xxx2_regs *const gctrl_base = GCTRL_IT8XXX2_REG_BASE; - struct wdt_it8xxx2_regs *const wdt_base = WDT_IT8XXX2_REG_BASE; - uint32_t chip_reset_flags = chip_read_reset_flags(); - - /* Disable interrupts to avoid task swaps during reboot. */ - interrupt_disable_all(); - - if (chip_reset_flags & (EC_RESET_FLAG_HARD | EC_RESET_FLAG_HIBERNATE)) - gctrl_base->GCTRL_ETWDUARTCR |= IT8XXX2_GCTRL_ETWD_HW_RST_EN; - - /* - * Writing invalid key to watchdog module triggers a soft or hardware - * reset. It depends on the setting of bit0 at ETWDUARTCR register. - */ - wdt_base->ETWCFG |= IT8XXX2_WDT_EWDKEYEN; - wdt_base->EWDKEYR = 0x00; - - /* Spin and wait for reboot */ - while (1) - ; - - /* Should never return */ - return 0; -} - -static int cros_system_it8xxx2_hibernate(const struct device *dev, - uint32_t seconds, - uint32_t microseconds) -{ - struct wdt_it8xxx2_regs *const wdt_base = WDT_IT8XXX2_REG_BASE; - - /* Disable all interrupts. */ - interrupt_disable_all(); - - /* Save and disable interrupts */ - if (IS_ENABLED(CONFIG_ITE_IT8XXX2_INTC)) - ite_intc_save_and_disable_interrupts(); - - /* bit5: watchdog is disabled. */ - wdt_base->ETWCTRL |= IT8XXX2_WDT_EWDSCEN; - - /* - * Setup GPIOs for hibernate. On some boards, it's possible that this - * may not return at all. On those boards, power to the EC is likely - * being turn off entirely. - */ - if (board_hibernate_late) { - /* - * Set reset flag in case board_hibernate_late() doesn't - * return. - */ - chip_save_reset_flags(EC_RESET_FLAG_HIBERNATE); - board_hibernate_late(); - } - - if (seconds || microseconds) { - /* - * Convert milliseconds(or at least 1 ms) to 32 Hz - * free run timer count for hibernate. - */ - uint32_t c = (seconds * 1000 + microseconds / 1000 + 1) * - 32 / 1000; - - /* Enable a 32-bit timer and clock source is 32 Hz */ - /* Disable external timer x */ - IT8XXX2_EXT_CTRLX(FREE_RUN_TIMER) &= ~IT8XXX2_EXT_ETXEN; - irq_disable(FREE_RUN_TIMER_IRQ); - IT8XXX2_EXT_PSRX(FREE_RUN_TIMER) = EXT_PSR_32; - IT8XXX2_EXT_CNTX(FREE_RUN_TIMER) = c & FREE_RUN_TIMER_MAX_CNT; - /* Enable and re-start external timer x */ - IT8XXX2_EXT_CTRLX(FREE_RUN_TIMER) |= - (IT8XXX2_EXT_ETXEN | IT8XXX2_EXT_ETXRST); - irq_enable(FREE_RUN_TIMER_IRQ); - } - - static const int wakeup_pin_list[] = { -#if DT_NODE_EXISTS(SYSTEM_DT_NODE_HIBERNATE_CONFIG) - UTIL_LISTIFY(SYSTEM_DT_NODE_WAKEUP_PIN_LEN, - SYSTEM_DT_WAKEUP_GPIO_ENUM_BY_IDX, _) -#endif - }; - - /* Reconfigure wake-up GPIOs */ - for (int i = 0; i < ARRAY_SIZE(wakeup_pin_list); i++) - /* Re-enable interrupt for wake-up inputs */ - gpio_enable_interrupt(wakeup_pin_list[i]); - - /* EC sleep mode */ - chip_pll_ctrl(CHIP_PLL_SLEEP); - - /* Chip sleep and wait timer wake it up */ - __asm__ volatile ("wfi"); - - /* Reset EC when wake up from sleep mode (system hibernate) */ - system_reset(SYSTEM_RESET_HIBERNATE); - - return 0; -} - -static const struct cros_system_driver_api cros_system_driver_it8xxx2_api = { - .get_reset_cause = cros_system_it8xxx2_get_reset_cause, - .soc_reset = cros_system_it8xxx2_soc_reset, - .hibernate = cros_system_it8xxx2_hibernate, - .chip_vendor = cros_system_it8xxx2_get_chip_vendor, - .chip_name = cros_system_it8xxx2_get_chip_name, - .chip_revision = cros_system_it8xxx2_get_chip_revision, -}; - -#if CONFIG_CROS_SYSTEM_IT8XXX2_INIT_PRIORITY >= \ - CONFIG_PLATFORM_EC_SYSTEM_PRE_INIT_PRIORITY -#error "CROS_SYSTEM must initialize before the SYSTEM_PRE initialization" -#endif -DEVICE_DEFINE(cros_system_it8xxx2_0, "CROS_SYSTEM", cros_system_it8xxx2_init, - NULL, NULL, NULL, PRE_KERNEL_1, - CONFIG_CROS_SYSTEM_IT8XXX2_INIT_PRIORITY, - &cros_system_driver_it8xxx2_api); diff --git a/zephyr/drivers/cros_system/cros_system_npcx.c b/zephyr/drivers/cros_system/cros_system_npcx.c deleted file mode 100644 index e3d3bc29b2..0000000000 --- a/zephyr/drivers/cros_system/cros_system_npcx.c +++ /dev/null @@ -1,556 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <arch/arm/aarch32/cortex_m/cmsis.h> -#include <drivers/cros_system.h> -#include <drivers/gpio.h> -#include <drivers/watchdog.h> -#include <logging/log.h> -#include <soc.h> -#include <soc/nuvoton_npcx/reg_def_cros.h> -#include <sys/util.h> - -#include "gpio.h" -#include "rom_chip.h" -#include "soc_gpio.h" -#include "soc_miwu.h" -#include "system.h" - -LOG_MODULE_REGISTER(cros_system, LOG_LEVEL_ERR); - -/* Driver config */ -struct cros_system_npcx_config { - /* hardware module base address */ - uintptr_t base_scfg; - uintptr_t base_twd; - uintptr_t base_mswc; -}; - -/* Driver data */ -struct cros_system_npcx_data { - int reset; /* reset cause */ -}; - -/* Driver convenience defines */ -#define DRV_CONFIG(dev) ((const struct cros_system_npcx_config *)(dev)->config) - -#define HAL_SCFG_INST(dev) (struct scfg_reg *)(DRV_CONFIG(dev)->base_scfg) -#define HAL_TWD_INST(dev) (struct twd_reg *)(DRV_CONFIG(dev)->base_twd) -#define HAL_MSWC_INST(dev) (struct mswc_reg *)(DRV_CONFIG(dev)->base_mswc) - -#define DRV_DATA(dev) ((struct cros_system_npcx_data *)(dev)->data) - -#define SYSTEM_DT_NODE_SOC_ID_CONFIG DT_INST(0, nuvoton_npcx_soc_id) - -/* Chip info devicetree data */ -#define NPCX_FAMILY_ID DT_PROP(SYSTEM_DT_NODE_SOC_ID_CONFIG, family_id) - -#define NPCX_CHIP_ID DT_PROP(SYSTEM_DT_NODE_SOC_ID_CONFIG, chip_id) - -#define NPCX_DEVICE_ID DT_PROP(SYSTEM_DT_NODE_SOC_ID_CONFIG, device_id) - -#define NPCX_REVISION_ADDR \ - DT_PROP_BY_IDX(SYSTEM_DT_NODE_SOC_ID_CONFIG, revision_reg, 0) -#define NPCX_REVISION_LEN \ - DT_PROP_BY_IDX(SYSTEM_DT_NODE_SOC_ID_CONFIG, revision_reg, 1) - -/* RAM block size in npcx family (Unit: bytes) */ -#define NPCX_RAM_BLOCK_SIZE (32 * 1024) -/* RAM block number in npcx7 series */ - -/* Calculate the number of RAM blocks: - * total RAM size = code ram + data ram + extra 2K for ROM functions - * divided by the block size 32k. - */ -#define DATA_RAM_SIZE DT_REG_SIZE(DT_NODELABEL(sram0)) -#define CODE_RAM_SIZE DT_REG_SIZE(DT_NODELABEL(flash0)) -#define NPCX_RAM_BLOCK_COUNT \ - ((DATA_RAM_SIZE + CODE_RAM_SIZE + KB(2)) / NPCX_RAM_BLOCK_SIZE) - -/* Valid bit-depth of RAM block Power-Down control (RAM_PD) registers. Use its - * mask to power down all unnecessary RAM blocks before hibernating. - */ -#define NPCX_RAM_PD_DEPTH DT_PROP(DT_NODELABEL(pcc), ram_pd_depth) -#define NPCX_RAM_BLOCK_PD_MASK (BIT(NPCX_RAM_PD_DEPTH) - 1) - -/* Get saved reset flag address in battery-backed ram */ -#define BBRAM_SAVED_RESET_FLAG_ADDR \ - (DT_REG_ADDR(DT_INST(0, nuvoton_npcx_bbram)) + \ - DT_PROP(DT_PATH(named_bbram_regions, saved_reset_flags), offset)) - -/* Soc specific system local functions */ -static int system_npcx_watchdog_stop(void) -{ - if (IS_ENABLED(CONFIG_WATCHDOG)) { - const struct device *wdt_dev = DEVICE_DT_GET( - DT_NODELABEL(twd0)); - if (!device_is_ready(wdt_dev)) { - LOG_ERR("Error: device %s is not ready", wdt_dev->name); - return -ENODEV; - } - - wdt_disable(wdt_dev); - } - - return 0; -} - -static void system_npcx_set_flash_pins_tri_state(const struct device *dev) -{ - struct scfg_reg *const inst_scfg = HAL_SCFG_INST(dev); - - inst_scfg->DEVCNT |= BIT(NPCX_DEVCNT_F_SPI_TRIS); -} - -static void system_npcx_init_watchdog_reset(const struct device *dev) -{ - struct twd_reg *const inst_twd = HAL_TWD_INST(dev); - - /* Enable early touch */ - inst_twd->T0CSR &= ~BIT(NPCX_T0CSR_TESDIS); - /* watchdog touched by writing 5Ch to WDSDM */ - inst_twd->TWCFG |= BIT(NPCX_TWCFG_WDSDME); -} - -static void system_npcx_turn_off_adc(void) -{ - struct adc_reg *const inst_adc = - (struct adc_reg *)(DT_REG_ADDR(DT_INST(0, nuvoton_npcx_adc))); - - inst_adc->ADCCNF = 0; - /* Wait for 1000 us to make sure conversion is completed. */ - k_busy_wait(1000); -} - -static void system_npcx_turn_off_kernel_timer(void) -{ - static struct itim32_reg *const evt_tmr = - (struct itim32_reg *)DT_REG_ADDR_BY_NAME( - DT_INST(0, nuvoton_npcx_itim_timer), evt_itim); - - evt_tmr->ITCTS32 &= ~BIT(NPCX_ITCTSXX_ITEN); -} - -static void system_npcx_disable_instant_wakeup(void) -{ - struct pmc_reg *const inst_pmc = (struct pmc_reg *)(DT_REG_ADDR_BY_NAME( - DT_INST(0, nuvoton_npcx_pcc), pmc)); - - inst_pmc->ENIDL_CTL &= ~BIT(NPCX_ENIDL_CTL_LP_WK_CTL); -} - -static void system_npcx_set_wakeup_gpios_before_hibernate(void) -{ - const uintptr_t miwu_base[] = { - DT_REG_ADDR(DT_INST(0, nuvoton_npcx_miwu)), - DT_REG_ADDR(DT_INST(1, nuvoton_npcx_miwu)), - DT_REG_ADDR(DT_INST(2, nuvoton_npcx_miwu)), - }; - - /* Disable all MIWU inputs before entering hibernate */ - for (int table = 0; table < ARRAY_SIZE(miwu_base); table++) { - for (int group = 0; group < NPCX_MIWU_GROUP_COUNT; group++) { - /* Disable all wake-ups */ - NPCX_WKEN(miwu_base[table], group) = 0x00; - /* Clear all pending bits of wake-ups */ - NPCX_WKPCL(miwu_base[table], group) = 0xFF; - /* - * Disable all inputs of wake-ups to prevent leakage - * caused by input floating. - */ - NPCX_WKINEN(miwu_base[table], group) = 0x00; - } - } - - static const int wakeup_pin_list[] = { -#if DT_NODE_EXISTS(SYSTEM_DT_NODE_HIBERNATE_CONFIG) - UTIL_LISTIFY(SYSTEM_DT_NODE_WAKEUP_PIN_LEN, - SYSTEM_DT_WAKEUP_GPIO_ENUM_BY_IDX, _) -#endif - }; - - /* Reconfigure wake-up GPIOs */ - for (int i = 0; i < ARRAY_SIZE(wakeup_pin_list); i++) { - gpio_reset(wakeup_pin_list[i]); - /* Re-enable interrupt for wake-up inputs */ - gpio_enable_interrupt(wakeup_pin_list[i]); - } -} - -/* - * Hibernate function locates in the last 32K ram block in npcx7 series. - * Do not use global variables or call functions since we have turned off - * the other ram blocks. - */ -noreturn void __keep __attribute__((section(".lfw.hiber"))) -system_npcx_hibernate_by_lfw_in_last_ram(const struct device *dev, - uint32_t pd_ram_mask) -{ - /* Modules used for hibernating */ - struct twd_reg *const inst_twd = HAL_TWD_INST(dev); - struct mtc_reg *const inst_mtc = (struct mtc_reg *)(DT_REG_ADDR( - DT_INST(0, nuvoton_npcx_cros_mtc))); - struct pmc_reg *const inst_pmc = (struct pmc_reg *)(DT_REG_ADDR_BY_NAME( - DT_INST(0, nuvoton_npcx_pcc), pmc)); - uint32_t reset_flags; - volatile uint8_t *saved_reset_flags = - (volatile uint8_t *)BBRAM_SAVED_RESET_FLAG_ADDR; - - /* Turn off all blocks except last one for better power consumption */ - inst_pmc->RAM_PD[0] = (uint8_t)pd_ram_mask; - inst_pmc->RAM_PD[1] = (uint8_t)(pd_ram_mask >> 8); - - /* Set deep idle mode */ - inst_pmc->PMCSR = BIT(NPCX_PMCSR_IDLE) | BIT(NPCX_PMCSR_DHF); - - /* Enter system sleep mode */ - __asm__ volatile("wfi"); - - /* - * Mark wake-up reason for hibernate. Do not call bbram utilities - * directly since the other ram blocks are power down. - */ - if (IS_BIT_SET(inst_mtc->WTC, NPCX_WTC_PTO)) { - /* Save wake-up reason as RTC alarm. */ - reset_flags = EC_RESET_FLAG_RTC_ALARM; - } else { - /* Otherwise, we treat it as GPIOs wake-up */ - reset_flags = EC_RESET_FLAG_WAKE_PIN; - } - - saved_reset_flags[0] |= reset_flags; - saved_reset_flags[1] |= reset_flags >> 8; - saved_reset_flags[2] |= reset_flags >> 16; - saved_reset_flags[3] |= reset_flags >> 24; - - /* - * The trigger of a watchdog event by a "too early service" condition. - * When the watchdog is written more than once during three watchdog - * clock cycle. - */ - inst_twd->WDSDM = 0x5C; - inst_twd->WDSDM = 0x5C; - - /* Spin and wait for reboot; should never return */ - while (1) - continue; -} - -static inline int system_npcx_get_ram_blk_by_lfw_addr(char *address) -{ - return NPCX_RAM_BLOCK_COUNT - - ceiling_fraction((uint32_t)address - - CONFIG_CROS_EC_PROGRAM_MEMORY_BASE, - NPCX_RAM_BLOCK_SIZE); -} - -static void system_npcx_hibernate_by_disable_ram(const struct device *dev, - uint32_t seconds, - uint32_t microseconds) -{ - /* Get 32kb ram block order of lfw function */ - extern char __lfw_text_start[], __lfw_text_end[]; - int lfw_block = system_npcx_get_ram_blk_by_lfw_addr(__lfw_text_start); - uint32_t pd_ram_mask = ~BIT(lfw_block) & NPCX_RAM_BLOCK_PD_MASK; - - if (lfw_block != system_npcx_get_ram_blk_by_lfw_addr(__lfw_text_end)) { - LOG_ERR("LFW cannot cross ram blocks!"); - return; - } - - /* - * Set status of pins which connect to flash to tri-state in case - * the leakage current. - */ - system_npcx_set_flash_pins_tri_state(dev); - - /* Initialize watchdog for reset after wake-up from hibernating */ - system_npcx_init_watchdog_reset(dev); - - /* Disable ADC and wait for 1000 us to make sure conversion is done */ - if (IS_ENABLED(CONFIG_ADC)) - system_npcx_turn_off_adc(); - - /* Disable kernel timer */ - system_npcx_turn_off_kernel_timer(); - - /* Disable instant wake up mode for better power consumption */ - system_npcx_disable_instant_wakeup(); - - /* - * Set wake-up input GPIOs and turn off the other sources for better - * power consumption before entering hibernate mode. - */ - system_npcx_set_wakeup_gpios_before_hibernate(); - - /* - * Give the board a chance to do any late stage hibernation work. This - * is likely going to configure GPIOs for hibernation. On some boards, - * it's possible that this may not return at all. On those boards, - * power to the EC is likely being turn off entirely. - */ - if (board_hibernate_late) { - board_hibernate_late(); - } - - /* Setup a RTC alarm if needed */ - if (IS_ENABLED(CONFIG_RTC) && (seconds || microseconds)) { - system_set_rtc_alarm(seconds, microseconds); - } - - /* Clear all pending IRQs in case wake-up immediately after sleeping */ - for (int i = 0; i < CONFIG_NUM_IRQS; i++) { - NVIC_ClearPendingIRQ(i); - } - - /* Execute hibernate by lfw which locates in last 32K block ram */ - system_npcx_hibernate_by_lfw_in_last_ram(dev, pd_ram_mask); -} - -static const char *cros_system_npcx_get_chip_vendor(const struct device *dev) -{ - struct mswc_reg *const inst_mswc = HAL_MSWC_INST(dev); - static char str[11] = "Unknown-XX"; - char *p = str + 8; - uint8_t fam_id = inst_mswc->SID_CR; - -#if DT_NODE_EXISTS(SYSTEM_DT_NODE_SOC_ID_CONFIG) - if (fam_id == NPCX_FAMILY_ID) { - return "Nuvoton"; - } -#endif - - hex2char(fam_id >> 4, p++); - hex2char(fam_id & 0xf, p); - return str; -} - -static const char *cros_system_npcx_get_chip_name(const struct device *dev) -{ - struct mswc_reg *const inst_mswc = HAL_MSWC_INST(dev); - static char str[13] = "Unknown-XXXX"; - char *p = str + 8; - uint8_t chip_id = inst_mswc->SRID_CR; - uint8_t device_id = inst_mswc->DEVICE_ID_CR; - -#if DT_NODE_EXISTS(SYSTEM_DT_NODE_SOC_ID_CONFIG) - if (chip_id == NPCX_CHIP_ID && device_id == NPCX_DEVICE_ID) { - return CONFIG_SOC; - } -#endif - - hex2char(chip_id >> 4, p++); - hex2char(chip_id & 0xf, p++); - hex2char(device_id >> 4, p++); - hex2char(device_id & 0xf, p); - return str; -} - -static const char *cros_system_npcx_get_chip_revision(const struct device *dev) -{ - ARG_UNUSED(dev); -#if DT_NODE_EXISTS(SYSTEM_DT_NODE_SOC_ID_CONFIG) - static char rev[NPCX_REVISION_LEN * 2 + 1]; -#else - static char rev[1]; -#endif - char *p = rev; - -#if DT_NODE_EXISTS(SYSTEM_DT_NODE_SOC_ID_CONFIG) - /* - * For NPCX7, the revision number is 1 byte. - * For NPCX9 and later chips, the revision number is 4 bytes. - */ - for (int s = NPCX_REVISION_ADDR + NPCX_REVISION_LEN - 1; - s >= NPCX_REVISION_ADDR; s--) { - uint8_t r = *((volatile uint8_t *)s); - hex2char(r >> 4, p++); - hex2char(r & 0xf, p++); - } -#endif - *p = '\0'; - - return rev; -} - -static void system_npcx_hibernate_by_psl(const struct device *dev, - uint32_t seconds, - uint32_t microseconds) -{ - ARG_UNUSED(dev); - /* - * TODO(b/178230662): RTC wake-up in PSL mode only support in npcx9 - * series. Nuvoton will introduce CLs for it later. - */ - ARG_UNUSED(seconds); - ARG_UNUSED(microseconds); - - /* - * Configure PSL input pads from "psl-in-pads" property in device tree - * file. - */ - npcx_pinctrl_psl_input_configure(); - - /* - * Give the board a chance to do any late stage hibernation work. This - * is likely going to configure GPIOs for hibernation. On some boards, - * it's possible that this may not return at all. On those boards, - * power to the EC is likely being turn off entirely. - */ - if (board_hibernate_late) - board_hibernate_late(); - - /* Turn off VCC1 to enter ultra-low-power mode for hibernating */ - npcx_pinctrl_psl_output_set_inactive(); -} - -static int cros_system_npcx_get_reset_cause(const struct device *dev) -{ - struct cros_system_npcx_data *data = DRV_DATA(dev); - - return data->reset; -} - -static int cros_system_npcx_init(const struct device *dev) -{ - struct scfg_reg *const inst_scfg = HAL_SCFG_INST(dev); - struct twd_reg *const inst_twd = HAL_TWD_INST(dev); - struct cros_system_npcx_data *data = DRV_DATA(dev); - - /* check reset cause */ - if (IS_BIT_SET(inst_twd->T0CSR, NPCX_T0CSR_WDRST_STS)) { - data->reset = WATCHDOG_RST; - inst_twd->T0CSR |= BIT(NPCX_T0CSR_WDRST_STS); - } else if (IS_BIT_SET(inst_scfg->RSTCTL, NPCX_RSTCTL_DBGRST_STS)) { - data->reset = DEBUG_RST; - inst_scfg->RSTCTL |= BIT(NPCX_RSTCTL_DBGRST_STS); - } else if (IS_BIT_SET(inst_scfg->RSTCTL, NPCX_RSTCTL_VCC1_RST_STS)) { - data->reset = VCC1_RST_PIN; - } else { - data->reset = POWERUP; - } - - return 0; -} - -static int cros_system_npcx_soc_reset(const struct device *dev) -{ - struct twd_reg *const inst_twd = HAL_TWD_INST(dev); - - /* Disable interrupts to avoid task swaps during reboot */ - interrupt_disable_all(); - - /* - * NPCX chip doesn't have the specific system reset functionality. Use - * watchdog reset as a system reset. - */ - - /* Stop the watchdog */ - system_npcx_watchdog_stop(); - - /* Initialize watchdog for reset */ - system_npcx_init_watchdog_reset(dev); - - /* - * The trigger of a watchdog event by a "too early service" condition. - * When the watchdog is written more than once during three watchdog - * clock cycle. - */ - inst_twd->WDSDM = 0x5C; - inst_twd->WDSDM = 0x5C; - - /* Wait for the soc reset. */ - while (1) { - ; - } - - /* should never return */ - return 0; -} - -static int cros_system_npcx_hibernate(const struct device *dev, - uint32_t seconds, uint32_t microseconds) -{ - /* Disable interrupt first */ - interrupt_disable_all(); - - /* Stop the watchdog */ - system_npcx_watchdog_stop(); - - /* Enter hibernate mode */ - if (IS_ENABLED(CONFIG_PLATFORM_EC_HIBERNATE_PSL)) { - system_npcx_hibernate_by_psl(dev, seconds, microseconds); - } else { - system_npcx_hibernate_by_disable_ram(dev, seconds, - microseconds); - } - - return 0; -} - -__maybe_unused static uint64_t -cros_system_npcx_deep_sleep_ticks(const struct device *dev) -{ - return npcx_clock_get_sleep_ticks(); -} - -static struct cros_system_npcx_data cros_system_npcx_dev_data; - -static const struct cros_system_npcx_config cros_system_dev_cfg = { - .base_scfg = DT_REG_ADDR(DT_INST(0, nuvoton_npcx_scfg)), - .base_twd = DT_REG_ADDR(DT_INST(0, nuvoton_npcx_watchdog)), - .base_mswc = - DT_REG_ADDR_BY_NAME(DT_INST(0, nuvoton_npcx_host_sub), mswc), -}; - -static const struct cros_system_driver_api cros_system_driver_npcx_api = { - .get_reset_cause = cros_system_npcx_get_reset_cause, - .soc_reset = cros_system_npcx_soc_reset, - .hibernate = cros_system_npcx_hibernate, - .chip_vendor = cros_system_npcx_get_chip_vendor, - .chip_name = cros_system_npcx_get_chip_name, - .chip_revision = cros_system_npcx_get_chip_revision, -#ifdef CONFIG_SOC_POWER_MANAGEMENT_TRACE - .deep_sleep_ticks = cros_system_npcx_deep_sleep_ticks, -#endif -}; - -DEVICE_DEFINE(cros_system_npcx_0, "CROS_SYSTEM", cros_system_npcx_init, NULL, - &cros_system_npcx_dev_data, &cros_system_dev_cfg, PRE_KERNEL_1, - CONFIG_CROS_SYSTEM_NPCX_INIT_PRIORITY, - &cros_system_driver_npcx_api); - -#if DT_NODE_EXISTS(DT_NODELABEL(dbg)) -#define HAL_DBG_REG_BASE_ADDR \ - ((struct dbg_reg *)DT_REG_ADDR(DT_INST(0, nuvoton_npcx_cros_dbg))) - -#define DBG_NODE DT_NODELABEL(dbg) -#define DBG_PINCTRL_PH DT_PHANDLE_BY_IDX(DBG_NODE, pinctrl_0, 0) -#define DBG_ALT_FILED(f) DT_PHA_BY_IDX(DBG_PINCTRL_PH, alts, 0, f) - -static int jtag_init(const struct device *dev) -{ - ARG_UNUSED(dev); - struct dbg_reg *const dbg_reg_base = HAL_DBG_REG_BASE_ADDR; - const struct npcx_alt jtag_alts[] = { - { - .group = DBG_ALT_FILED(group), - .bit = DBG_ALT_FILED(bit), - .inverted = DBG_ALT_FILED(inv) - } - }; - - dbg_reg_base->DBGCTRL = 0x04; - dbg_reg_base->DBGFRZEN3 &= ~BIT(NPCX_DBGFRZEN3_GLBL_FRZ_DIS); - if (DT_NODE_HAS_STATUS(DT_NODELABEL(dbg), okay)) - npcx_pinctrl_mux_configure(jtag_alts, 1, 1); - - return 0; -} -#if CONFIG_KERNEL_INIT_PRIORITY_DEFAULT >= 41 -#error "jtag_init must be called after default kernel init" -#endif -SYS_INIT(jtag_init, PRE_KERNEL_1, 41); -#endif /* DT_NODE_EXISTS(DT_NODELABEL(dbg)) */ |