From 252457d4b21f46889eebad61d4c0a65331919cec Mon Sep 17 00:00:00 2001 From: Jack Rosenthal Date: Thu, 4 Nov 2021 12:11:58 -0600 Subject: ish: Trim down the release branch In the interest of making long-term branch maintenance incur as little technical debt on us as possible, we should not maintain any files on the branch we are not actually using. This has the added effect of making it extremely clear when merging CLs from the main branch when changes have the possibility to affect us. The follow-on CL adds a convenience script to actually pull updates from the main branch and generate a CL for the update. BUG=b:204206272 BRANCH=ish TEST=make BOARD=arcada_ish && make BOARD=drallion_ish Signed-off-by: Jack Rosenthal Change-Id: I17e4694c38219b5a0823e0a3e55a28d1348f4b18 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3262038 Reviewed-by: Jett Rink Reviewed-by: Tom Hughes --- zephyr/drivers/CMakeLists.txt | 10 - zephyr/drivers/Kconfig | 9 - zephyr/drivers/cros_cbi/CMakeLists.txt | 4 - zephyr/drivers/cros_cbi/cros_cbi.c | 218 ------ zephyr/drivers/cros_flash/CMakeLists.txt | 4 - zephyr/drivers/cros_flash/Kconfig | 22 - zephyr/drivers/cros_flash/cros_flash_it8xxx2.c | 327 --------- zephyr/drivers/cros_flash/cros_flash_npcx.c | 821 --------------------- zephyr/drivers/cros_kb_raw/CMakeLists.txt | 4 - zephyr/drivers/cros_kb_raw/Kconfig | 34 - zephyr/drivers/cros_kb_raw/cros_kb_raw_ite.c | 187 ----- zephyr/drivers/cros_kb_raw/cros_kb_raw_npcx.c | 241 ------ zephyr/drivers/cros_rtc/CMakeLists.txt | 9 - zephyr/drivers/cros_rtc/Kconfig | 36 - zephyr/drivers/cros_rtc/cros_rtc_npcx.c | 241 ------ zephyr/drivers/cros_rtc/nxp_rtc_pcf85063a.c | 450 ------------ zephyr/drivers/cros_rtc/nxp_rtc_pcf85063a.h | 58 -- zephyr/drivers/cros_rtc/renesas_rtc_idt1337ag.c | 480 ------------ zephyr/drivers/cros_rtc/renesas_rtc_idt1337ag.h | 60 -- zephyr/drivers/cros_shi/CMakeLists.txt | 6 - zephyr/drivers/cros_shi/Kconfig | 57 -- zephyr/drivers/cros_shi/cros_shi_it8xxx2.c | 407 ---------- zephyr/drivers/cros_shi/cros_shi_npcx.c | 899 ----------------------- zephyr/drivers/cros_system/CMakeLists.txt | 6 - zephyr/drivers/cros_system/Kconfig | 47 -- zephyr/drivers/cros_system/cros_system_it8xxx2.c | 246 ------- zephyr/drivers/cros_system/cros_system_npcx.c | 556 -------------- 27 files changed, 5439 deletions(-) delete mode 100644 zephyr/drivers/CMakeLists.txt delete mode 100644 zephyr/drivers/Kconfig delete mode 100644 zephyr/drivers/cros_cbi/CMakeLists.txt delete mode 100644 zephyr/drivers/cros_cbi/cros_cbi.c delete mode 100644 zephyr/drivers/cros_flash/CMakeLists.txt delete mode 100644 zephyr/drivers/cros_flash/Kconfig delete mode 100644 zephyr/drivers/cros_flash/cros_flash_it8xxx2.c delete mode 100644 zephyr/drivers/cros_flash/cros_flash_npcx.c delete mode 100644 zephyr/drivers/cros_kb_raw/CMakeLists.txt delete mode 100644 zephyr/drivers/cros_kb_raw/Kconfig delete mode 100644 zephyr/drivers/cros_kb_raw/cros_kb_raw_ite.c delete mode 100644 zephyr/drivers/cros_kb_raw/cros_kb_raw_npcx.c delete mode 100644 zephyr/drivers/cros_rtc/CMakeLists.txt delete mode 100644 zephyr/drivers/cros_rtc/Kconfig delete mode 100644 zephyr/drivers/cros_rtc/cros_rtc_npcx.c delete mode 100644 zephyr/drivers/cros_rtc/nxp_rtc_pcf85063a.c delete mode 100644 zephyr/drivers/cros_rtc/nxp_rtc_pcf85063a.h delete mode 100644 zephyr/drivers/cros_rtc/renesas_rtc_idt1337ag.c delete mode 100644 zephyr/drivers/cros_rtc/renesas_rtc_idt1337ag.h delete mode 100644 zephyr/drivers/cros_shi/CMakeLists.txt delete mode 100644 zephyr/drivers/cros_shi/Kconfig delete mode 100644 zephyr/drivers/cros_shi/cros_shi_it8xxx2.c delete mode 100644 zephyr/drivers/cros_shi/cros_shi_npcx.c delete mode 100644 zephyr/drivers/cros_system/CMakeLists.txt delete mode 100644 zephyr/drivers/cros_system/Kconfig delete mode 100644 zephyr/drivers/cros_system/cros_system_it8xxx2.c delete mode 100644 zephyr/drivers/cros_system/cros_system_npcx.c (limited to 'zephyr/drivers') 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 -#include "cros_board_info.h" -#include - -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 -#include -#include -#include -#include - -#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 -#include -#include -#include -#include -#include -#include -#include -#include -#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 -#include -#include -#include -#include -#include -#include - -#include "ec_tasks.h" -#include "keyboard_raw.h" -#include "task.h" - -#include -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 -#include -#include -#include -#include -#include -#include -#include - -#include "ec_tasks.h" -#include "keyboard_raw.h" -#include "soc_miwu.h" -#include "task.h" - -#include -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 -#include -#include -#include -#include -#include - -#include "ec_tasks.h" -#include "soc_miwu.h" -#include "task.h" - -#include -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 -#include -#include -#include -#include -#include -#include -#include - -#include "nxp_rtc_pcf85063a.h" - -#include -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 -#include -#include -#include -#include -#include -#include -#include - -#include "renesas_rtc_idt1337ag.h" - -#include -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 -#include -#include -#include -#include -#include -#include -#include -#include - -#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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 -#include -#include -#include -#include - -#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 -#include -#include -#include -#include -#include -#include -#include - -#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)) */ -- cgit v1.2.1