File Index
Files and directories
Sign in
FILE

rt2800soc.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/ralink/rt2x00/rt2800soc.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*	Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
  3 *	Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
  4 *	Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
  5 *	Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
  6 *	Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
  7 *	Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
  8 *	Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
  9 *	Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com>
 10 *	<http://rt2x00.serialmonkey.com>
 11 */
 12
 13/*	Module: rt2800soc
 14 *	Abstract: rt2800 WiSoC specific routines.
 15 */
 16
 17#include <linux/etherdevice.h>
 18#include <linux/init.h>
 19#include <linux/kernel.h>
 20#include <linux/module.h>
 21#include <linux/of.h>
 22#include <linux/platform_device.h>
 23
 24#include "rt2x00.h"
 25#include "rt2x00mmio.h"
 26#include "rt2800.h"
 27#include "rt2800lib.h"
 28#include "rt2800mmio.h"
 29
 30/* Allow hardware encryption to be disabled. */
 31static bool modparam_nohwcrypt;
 32module_param_named(nohwcrypt, modparam_nohwcrypt, bool, 0444);
 33MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
 34
 35static bool rt2800soc_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev)
 36{
 37	return modparam_nohwcrypt;
 38}
 39
 40static void rt2800soc_disable_radio(struct rt2x00_dev *rt2x00dev)
 41{
 42	u32 reg;
 43
 44	rt2800_disable_radio(rt2x00dev);
 45	rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0);
 46
 47	reg = 0;
 48	if (rt2x00_rt(rt2x00dev, RT3883))
 49		rt2x00_set_field32(&reg, TX_PIN_CFG_RFTR_EN, 1);
 50
 51	rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, reg);
 52}
 53
 54static int rt2800soc_set_device_state(struct rt2x00_dev *rt2x00dev,
 55				      enum dev_state state)
 56{
 57	int retval = 0;
 58
 59	switch (state) {
 60	case STATE_RADIO_ON:
 61		retval = rt2800mmio_enable_radio(rt2x00dev);
 62		break;
 63
 64	case STATE_RADIO_OFF:
 65		rt2800soc_disable_radio(rt2x00dev);
 66		break;
 67
 68	case STATE_RADIO_IRQ_ON:
 69	case STATE_RADIO_IRQ_OFF:
 70		rt2800mmio_toggle_irq(rt2x00dev, state);
 71		break;
 72
 73	case STATE_DEEP_SLEEP:
 74	case STATE_SLEEP:
 75	case STATE_STANDBY:
 76	case STATE_AWAKE:
 77		/* These states are not supported, but don't report an error */
 78		retval = 0;
 79		break;
 80
 81	default:
 82		retval = -ENOTSUPP;
 83		break;
 84	}
 85
 86	if (unlikely(retval))
 87		rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
 88			   state, retval);
 89
 90	return retval;
 91}
 92
 93static int rt2800soc_read_eeprom(struct rt2x00_dev *rt2x00dev)
 94{
 95	void __iomem *base_addr;
 96
 97	if (!rt2800_read_eeprom_nvmem(rt2x00dev))
 98		return 0;
 99
100	base_addr = ioremap(0x1F040000, EEPROM_SIZE);
101	if (!base_addr)
102		return -ENOMEM;
103
104	memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE);
105
106	iounmap(base_addr);
107	return 0;
108}
109
110/* Firmware functions */
111static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev)
112{
113	WARN_ON_ONCE(1);
114	return NULL;
115}
116
117static int rt2800soc_load_firmware(struct rt2x00_dev *rt2x00dev,
118				   const u8 *data, const size_t len)
119{
120	WARN_ON_ONCE(1);
121	return 0;
122}
123
124static int rt2800soc_check_firmware(struct rt2x00_dev *rt2x00dev,
125				    const u8 *data, const size_t len)
126{
127	WARN_ON_ONCE(1);
128	return 0;
129}
130
131static int rt2800soc_write_firmware(struct rt2x00_dev *rt2x00dev,
132				    const u8 *data, const size_t len)
133{
134	WARN_ON_ONCE(1);
135	return 0;
136}
137
138#ifdef CONFIG_PM
139static int rt2800soc_suspend(struct platform_device *pdev, pm_message_t state)
140{
141	struct ieee80211_hw *hw = platform_get_drvdata(pdev);
142	struct rt2x00_dev *rt2x00dev = hw->priv;
143
144	return rt2x00lib_suspend(rt2x00dev);
145}
146
147static int rt2800soc_resume(struct platform_device *pdev)
148{
149	struct ieee80211_hw *hw = platform_get_drvdata(pdev);
150	struct rt2x00_dev *rt2x00dev = hw->priv;
151
152	return rt2x00lib_resume(rt2x00dev);
153}
154#endif /* CONFIG_PM */
155
156static const struct ieee80211_ops rt2800soc_mac80211_ops = {
157	.add_chanctx = ieee80211_emulate_add_chanctx,
158	.remove_chanctx = ieee80211_emulate_remove_chanctx,
159	.change_chanctx = ieee80211_emulate_change_chanctx,
160	.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
161	.tx			= rt2x00mac_tx,
162	.wake_tx_queue		= ieee80211_handle_wake_tx_queue,
163	.start			= rt2x00mac_start,
164	.stop			= rt2x00mac_stop,
165	.add_interface		= rt2x00mac_add_interface,
166	.remove_interface	= rt2x00mac_remove_interface,
167	.config			= rt2x00mac_config,
168	.configure_filter	= rt2x00mac_configure_filter,
169	.set_key		= rt2x00mac_set_key,
170	.sw_scan_start		= rt2x00mac_sw_scan_start,
171	.sw_scan_complete	= rt2x00mac_sw_scan_complete,
172	.get_stats		= rt2x00mac_get_stats,
173	.get_key_seq		= rt2800_get_key_seq,
174	.set_rts_threshold	= rt2800_set_rts_threshold,
175	.sta_add		= rt2800_sta_add,
176	.sta_remove		= rt2800_sta_remove,
177	.bss_info_changed	= rt2x00mac_bss_info_changed,
178	.conf_tx		= rt2800_conf_tx,
179	.get_tsf		= rt2800_get_tsf,
180	.rfkill_poll		= rt2x00mac_rfkill_poll,
181	.ampdu_action		= rt2800_ampdu_action,
182	.flush			= rt2x00mac_flush,
183	.get_survey		= rt2800_get_survey,
184	.get_ringparam		= rt2x00mac_get_ringparam,
185	.tx_frames_pending	= rt2x00mac_tx_frames_pending,
186	.reconfig_complete	= rt2x00mac_reconfig_complete,
187};
188
189static const struct rt2800_ops rt2800soc_rt2800_ops = {
190	.register_read		= rt2x00mmio_register_read,
191	.register_read_lock	= rt2x00mmio_register_read, /* same for SoCs */
192	.register_write		= rt2x00mmio_register_write,
193	.register_write_lock	= rt2x00mmio_register_write, /* same for SoCs */
194	.register_multiread	= rt2x00mmio_register_multiread,
195	.register_multiwrite	= rt2x00mmio_register_multiwrite,
196	.regbusy_read		= rt2x00mmio_regbusy_read,
197	.read_eeprom		= rt2800soc_read_eeprom,
198	.hwcrypt_disabled	= rt2800soc_hwcrypt_disabled,
199	.drv_write_firmware	= rt2800soc_write_firmware,
200	.drv_init_registers	= rt2800mmio_init_registers,
201	.drv_get_txwi		= rt2800mmio_get_txwi,
202	.drv_get_dma_done	= rt2800mmio_get_dma_done,
203};
204
205static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = {
206	.irq_handler		= rt2800mmio_interrupt,
207	.txstatus_tasklet	= rt2800mmio_txstatus_tasklet,
208	.pretbtt_tasklet	= rt2800mmio_pretbtt_tasklet,
209	.tbtt_tasklet		= rt2800mmio_tbtt_tasklet,
210	.rxdone_tasklet		= rt2800mmio_rxdone_tasklet,
211	.autowake_tasklet	= rt2800mmio_autowake_tasklet,
212	.probe_hw		= rt2800mmio_probe_hw,
213	.get_firmware_name	= rt2800soc_get_firmware_name,
214	.check_firmware		= rt2800soc_check_firmware,
215	.load_firmware		= rt2800soc_load_firmware,
216	.initialize		= rt2x00mmio_initialize,
217	.uninitialize		= rt2x00mmio_uninitialize,
218	.get_entry_state	= rt2800mmio_get_entry_state,
219	.clear_entry		= rt2800mmio_clear_entry,
220	.set_device_state	= rt2800soc_set_device_state,
221	.rfkill_poll		= rt2800_rfkill_poll,
222	.link_stats		= rt2800_link_stats,
223	.reset_tuner		= rt2800_reset_tuner,
224	.link_tuner		= rt2800_link_tuner,
225	.gain_calibration	= rt2800_gain_calibration,
226	.vco_calibration	= rt2800_vco_calibration,
227	.watchdog		= rt2800_watchdog,
228	.start_queue		= rt2800mmio_start_queue,
229	.kick_queue		= rt2800mmio_kick_queue,
230	.stop_queue		= rt2800mmio_stop_queue,
231	.flush_queue		= rt2800mmio_flush_queue,
232	.write_tx_desc		= rt2800mmio_write_tx_desc,
233	.write_tx_data		= rt2800_write_tx_data,
234	.write_beacon		= rt2800_write_beacon,
235	.clear_beacon		= rt2800_clear_beacon,
236	.fill_rxdone		= rt2800mmio_fill_rxdone,
237	.config_shared_key	= rt2800_config_shared_key,
238	.config_pairwise_key	= rt2800_config_pairwise_key,
239	.config_filter		= rt2800_config_filter,
240	.config_intf		= rt2800_config_intf,
241	.config_erp		= rt2800_config_erp,
242	.config_ant		= rt2800_config_ant,
243	.config			= rt2800_config,
244	.pre_reset_hw		= rt2800_pre_reset_hw,
245};
246
247static const struct rt2x00_ops rt2800soc_ops = {
248	.name			= KBUILD_MODNAME,
249	.drv_data_size		= sizeof(struct rt2800_drv_data),
250	.max_ap_intf		= 8,
251	.eeprom_size		= EEPROM_SIZE,
252	.rf_size		= RF_SIZE,
253	.tx_queues		= NUM_TX_QUEUES,
254	.queue_init		= rt2800mmio_queue_init,
255	.lib			= &rt2800soc_rt2x00_ops,
256	.drv			= &rt2800soc_rt2800_ops,
257	.hw			= &rt2800soc_mac80211_ops,
258#ifdef CONFIG_RT2X00_LIB_DEBUGFS
259	.debugfs		= &rt2800_rt2x00debug,
260#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
261};
262
263static int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops)
264{
265	struct rt2x00_dev *rt2x00dev;
266	struct ieee80211_hw *hw;
267	void __iomem *mem;
268	struct clk *clk;
269	__le16 *eeprom;
270	int retval;
271	u32 *rf;
272	int irq;
273
274	mem = devm_platform_ioremap_resource(pdev, 0);
275	if (IS_ERR(mem))
276		return PTR_ERR(mem);
277
278	irq = platform_get_irq(pdev, 0);
279	if (irq < 0)
280		return irq;
281
282	clk = devm_clk_get_optional(&pdev->dev, NULL);
283	if (IS_ERR(clk))
284		return PTR_ERR(clk);
285
286	eeprom = devm_kzalloc(&pdev->dev, ops->eeprom_size, GFP_KERNEL);
287	if (!eeprom)
288		return -ENOMEM;
289
290	rf = devm_kzalloc(&pdev->dev, ops->rf_size, GFP_KERNEL);
291	if (!rf)
292		return -ENOMEM;
293
294	hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
295	if (!hw)
296		return dev_err_probe(&pdev->dev, -ENOMEM, "Failed to allocate hardware");
297
298	platform_set_drvdata(pdev, hw);
299
300	rt2x00dev = hw->priv;
301	rt2x00dev->dev = &pdev->dev;
302	rt2x00dev->ops = ops;
303	rt2x00dev->hw = hw;
304	rt2x00dev->irq = irq;
305	rt2x00dev->clk = clk;
306	rt2x00dev->eeprom = eeprom;
307	rt2x00dev->rf = rf;
308	rt2x00dev->name = pdev->dev.driver->name;
309	rt2x00dev->csr.base = mem;
310
311	rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC);
312
313	retval = rt2x00lib_probe_dev(rt2x00dev);
314	if (retval)
315		goto exit_free_device;
316
317	return 0;
318
319exit_free_device:
320	ieee80211_free_hw(hw);
321
322	return retval;
323}
324
325static int rt2800soc_probe(struct platform_device *pdev)
326{
327	return rt2x00soc_probe(pdev, &rt2800soc_ops);
328}
329
330static void rt2800soc_remove(struct platform_device *pdev)
331{
332	struct ieee80211_hw *hw = platform_get_drvdata(pdev);
333	struct rt2x00_dev *rt2x00dev = hw->priv;
334
335	/*
336	 * Free all allocated data.
337	 */
338	rt2x00lib_remove_dev(rt2x00dev);
339	ieee80211_free_hw(hw);
340}
341
342static const struct of_device_id rt2880_wmac_match[] = {
343	{ .compatible = "ralink,rt2880-wifi" },
344	{},
345};
346MODULE_DEVICE_TABLE(of, rt2880_wmac_match);
347
348static struct platform_driver rt2800soc_driver = {
349	.driver		= {
350		.name		= "rt2800_wmac",
351		.of_match_table = rt2880_wmac_match,
352	},
353	.probe		= rt2800soc_probe,
354	.remove		= rt2800soc_remove,
355#ifdef CONFIG_PM
356	.suspend	= rt2800soc_suspend,
357	.resume		= rt2800soc_resume,
358#endif
359};
360
361module_platform_driver(rt2800soc_driver);
362
363MODULE_AUTHOR(DRV_PROJECT);
364MODULE_VERSION(DRV_VERSION);
365MODULE_DESCRIPTION("Ralink WiSoC Wireless LAN driver.");
366MODULE_LICENSE("GPL");
~/ Read-only file preview.