drivers/net/wireless/mediatek/mt76/mt7921/sdio.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/mediatek/mt76/mt7921/sdio.c
Extension
.c
Size
8562 bytes
Lines
338
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: BSD-3-Clause-Clear
/* Copyright (C) 2021 MediaTek Inc.
 *
 */

#include <linux/kernel.h>
#include <linux/iopoll.h>
#include <linux/module.h>

#include <linux/mmc/host.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/sdio_func.h>

#include "mt7921.h"
#include "../sdio.h"
#include "../mt76_connac2_mac.h"
#include "mcu.h"

static const struct sdio_device_id mt7921s_table[] = {
	{ SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, 0x7901),
		.driver_data = (kernel_ulong_t)MT7921_FIRMWARE_WM },
	{ SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, 0x7902),
		.driver_data = (kernel_ulong_t)MT7902_FIRMWARE_WM },
	{ }	/* Terminating entry */
};

static void mt7921s_txrx_worker(struct mt76_worker *w)
{
	struct mt76_sdio *sdio = container_of(w, struct mt76_sdio,
					      txrx_worker);
	struct mt76_dev *mdev = container_of(sdio, struct mt76_dev, sdio);
	struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);

	if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) {
		queue_work(mdev->wq, &dev->pm.wake_work);
		return;
	}

	mt76s_txrx_worker(sdio);
	mt76_connac_pm_unref(&dev->mphy, &dev->pm);
}

static void mt7921s_unregister_device(struct mt792x_dev *dev)
{
	struct mt76_connac_pm *pm = &dev->pm;

	cancel_work_sync(&dev->init_work);
	mt76_unregister_device(&dev->mt76);
	cancel_delayed_work_sync(&pm->ps_work);
	cancel_work_sync(&pm->wake_work);

	mt76s_deinit(&dev->mt76);
	mt7921s_wfsys_reset(dev);
	skb_queue_purge(&dev->mt76.mcu.res_q);

	mt76_free_device(&dev->mt76);
}

static int mt7921s_parse_intr(struct mt76_dev *dev, struct mt76s_intr *intr)
{
	struct mt76_sdio *sdio = &dev->sdio;
	struct mt7921_sdio_intr *irq_data = sdio->intr_data;
	int i, err;

	sdio_claim_host(sdio->func);
	err = sdio_readsb(sdio->func, irq_data, MCR_WHISR, sizeof(*irq_data));
	sdio_release_host(sdio->func);

	if (err < 0)
		return err;

	if (irq_data->rx.num[0] > 16 ||
	    irq_data->rx.num[1] > 128)
		return -EINVAL;

	intr->isr = irq_data->isr;
	intr->rec_mb = irq_data->rec_mb;
	intr->tx.wtqcr = irq_data->tx.wtqcr;
	intr->rx.num = irq_data->rx.num;
	for (i = 0; i < 2 ; i++) {
		if (!i)
			intr->rx.len[0] = irq_data->rx.len0;
		else
			intr->rx.len[1] = irq_data->rx.len1;
	}

	return 0;
}

static int mt7921s_probe(struct sdio_func *func,

Annotation

Implementation Notes