// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2026 Morse Micro */ #include #include "core.h" #include "bus.h" #include "hif.h" #include "mac.h" static int mm81x_core_attach_regs(struct mm81x *mors) { int ret = 0; mm81x_claim_bus(mors); ret = mm81x_reg32_read(mors, MM8108_REG_CHIP_ID, &mors->chip_id); mm81x_release_bus(mors); if (ret < 0) { dev_err(mors->dev, "failed to read chip id %d", ret); return ret; } switch (mors->chip_id) { case (CHIP_ID_MM8108): mors->regs = &mm8108_regs; mors->hif.ops = &mm81x_yaps_ops; break; default: return -ENODEV; } return ret; } static void mm81x_core_init_mac_addr(struct mm81x *mors) { int ret = mm81x_hw_otp_get_mac_addr(mors); if (ret || !is_valid_ether_addr(mors->macaddr)) eth_random_addr(mors->macaddr); } char *mm81x_core_get_fw_path(u32 chip_id, u32 fw_ver) { const char *fw_base; switch (chip_id) { case CHIP_ID_MM8108: fw_base = MM8108_FW_BASE; break; default: return NULL; } return kasprintf(GFP_KERNEL, MM81X_FW_DIR "/v%u/%s" MM81X_FW_EXT, fw_ver, fw_base); } EXPORT_SYMBOL_GPL(mm81x_core_get_fw_path); struct mm81x *mm81x_core_alloc(size_t priv_size, struct device *dev) { return mm81x_mac_alloc(priv_size, dev); } EXPORT_SYMBOL_GPL(mm81x_core_alloc); int mm81x_core_init(struct mm81x *mors) { int ret; set_bit(MM81X_STATE_CHIP_UNRESPONSIVE, &mors->state_flags); set_bit(MM81X_STATE_RELOAD_FW_AFTER_START, &mors->state_flags); mm81x_core_init_mac_addr(mors); ret = mm81x_core_attach_regs(mors); if (ret) return ret; mors->chip_wq = create_singlethread_workqueue("chip_wq"); if (!mors->chip_wq) return -ENOMEM; mors->net_wq = create_singlethread_workqueue("net_wq"); if (!mors->net_wq) { ret = -ENOMEM; goto err_chip_wq; } ret = mm81x_hif_init(mors); if (ret) goto err_wqs; return 0; err_wqs: flush_workqueue(mors->net_wq); destroy_workqueue(mors->net_wq); err_chip_wq: flush_workqueue(mors->chip_wq); destroy_workqueue(mors->chip_wq); return ret; } EXPORT_SYMBOL_GPL(mm81x_core_init); int mm81x_core_register(struct mm81x *mors) { return mm81x_mac_register(mors); } EXPORT_SYMBOL_GPL(mm81x_core_register); void mm81x_core_unregister(struct mm81x *mors) { mm81x_mac_unregister(mors); } EXPORT_SYMBOL_GPL(mm81x_core_unregister); void mm81x_core_deinit(struct mm81x *mors) { mm81x_hif_finish(mors); flush_workqueue(mors->net_wq); destroy_workqueue(mors->net_wq); flush_workqueue(mors->chip_wq); destroy_workqueue(mors->chip_wq); } EXPORT_SYMBOL_GPL(mm81x_core_deinit); void mm81x_core_free(struct mm81x *mors) { mm81x_mac_free(mors); } EXPORT_SYMBOL_GPL(mm81x_core_free); MODULE_AUTHOR("Morse Micro"); MODULE_DESCRIPTION("Driver support for Morse Micro MM81X core"); MODULE_LICENSE("Dual BSD/GPL");