xref: /linux/drivers/net/wireless/morsemicro/mm81x/core.c (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2017-2026 Morse Micro
4  */
5 #include <linux/module.h>
6 #include "core.h"
7 #include "bus.h"
8 #include "hif.h"
9 #include "mac.h"
10 
mm81x_core_attach_regs(struct mm81x * mors)11 static int mm81x_core_attach_regs(struct mm81x *mors)
12 {
13 	int ret = 0;
14 
15 	mm81x_claim_bus(mors);
16 	ret = mm81x_reg32_read(mors, MM8108_REG_CHIP_ID, &mors->chip_id);
17 	mm81x_release_bus(mors);
18 
19 	if (ret < 0) {
20 		dev_err(mors->dev, "failed to read chip id %d", ret);
21 		return ret;
22 	}
23 
24 	switch (mors->chip_id) {
25 	case (CHIP_ID_MM8108):
26 		mors->regs = &mm8108_regs;
27 		mors->hif.ops = &mm81x_yaps_ops;
28 		break;
29 	default:
30 		return -ENODEV;
31 	}
32 
33 	return ret;
34 }
35 
mm81x_core_init_mac_addr(struct mm81x * mors)36 static void mm81x_core_init_mac_addr(struct mm81x *mors)
37 {
38 	int ret = mm81x_hw_otp_get_mac_addr(mors);
39 
40 	if (ret || !is_valid_ether_addr(mors->macaddr))
41 		eth_random_addr(mors->macaddr);
42 }
43 
mm81x_core_get_fw_path(u32 chip_id,u32 fw_ver)44 char *mm81x_core_get_fw_path(u32 chip_id, u32 fw_ver)
45 {
46 	const char *fw_base;
47 
48 	switch (chip_id) {
49 	case CHIP_ID_MM8108:
50 		fw_base = MM8108_FW_BASE;
51 		break;
52 	default:
53 		return NULL;
54 	}
55 
56 	return kasprintf(GFP_KERNEL, MM81X_FW_DIR "/v%u/%s" MM81X_FW_EXT,
57 			 fw_ver, fw_base);
58 }
59 EXPORT_SYMBOL_GPL(mm81x_core_get_fw_path);
60 
mm81x_core_alloc(size_t priv_size,struct device * dev)61 struct mm81x *mm81x_core_alloc(size_t priv_size, struct device *dev)
62 {
63 	return mm81x_mac_alloc(priv_size, dev);
64 }
65 EXPORT_SYMBOL_GPL(mm81x_core_alloc);
66 
mm81x_core_init(struct mm81x * mors)67 int mm81x_core_init(struct mm81x *mors)
68 {
69 	int ret;
70 
71 	set_bit(MM81X_STATE_CHIP_UNRESPONSIVE, &mors->state_flags);
72 	set_bit(MM81X_STATE_RELOAD_FW_AFTER_START, &mors->state_flags);
73 
74 	mm81x_core_init_mac_addr(mors);
75 
76 	ret = mm81x_core_attach_regs(mors);
77 	if (ret)
78 		return ret;
79 
80 	mors->chip_wq = create_singlethread_workqueue("chip_wq");
81 	if (!mors->chip_wq)
82 		return -ENOMEM;
83 
84 	mors->net_wq = create_singlethread_workqueue("net_wq");
85 	if (!mors->net_wq) {
86 		ret = -ENOMEM;
87 		goto err_chip_wq;
88 	}
89 
90 	ret = mm81x_hif_init(mors);
91 	if (ret)
92 		goto err_wqs;
93 
94 	return 0;
95 
96 err_wqs:
97 	flush_workqueue(mors->net_wq);
98 	destroy_workqueue(mors->net_wq);
99 
100 err_chip_wq:
101 	flush_workqueue(mors->chip_wq);
102 	destroy_workqueue(mors->chip_wq);
103 
104 	return ret;
105 }
106 EXPORT_SYMBOL_GPL(mm81x_core_init);
107 
mm81x_core_register(struct mm81x * mors)108 int mm81x_core_register(struct mm81x *mors)
109 {
110 	return mm81x_mac_register(mors);
111 }
112 EXPORT_SYMBOL_GPL(mm81x_core_register);
113 
mm81x_core_unregister(struct mm81x * mors)114 void mm81x_core_unregister(struct mm81x *mors)
115 {
116 	mm81x_mac_unregister(mors);
117 }
118 EXPORT_SYMBOL_GPL(mm81x_core_unregister);
119 
mm81x_core_deinit(struct mm81x * mors)120 void mm81x_core_deinit(struct mm81x *mors)
121 {
122 	mm81x_hif_finish(mors);
123 	flush_workqueue(mors->net_wq);
124 	destroy_workqueue(mors->net_wq);
125 	flush_workqueue(mors->chip_wq);
126 	destroy_workqueue(mors->chip_wq);
127 }
128 EXPORT_SYMBOL_GPL(mm81x_core_deinit);
129 
mm81x_core_free(struct mm81x * mors)130 void mm81x_core_free(struct mm81x *mors)
131 {
132 	mm81x_mac_free(mors);
133 }
134 EXPORT_SYMBOL_GPL(mm81x_core_free);
135 
136 MODULE_AUTHOR("Morse Micro");
137 MODULE_DESCRIPTION("Driver support for Morse Micro MM81X core");
138 MODULE_LICENSE("Dual BSD/GPL");
139