mirror of
https://github.com/outbackdingo/mt76.git
synced 2026-10-24 13:26:48 +00:00
mt76: sdio: move common code in mt76_sdio module
Move sdio common code in mt76_sdio module. This is a preliminary patch to support mt7921s devices. Co-developed-by: Sean Wang <[email protected]> Signed-off-by: Sean Wang <[email protected]> Signed-off-by: Lorenzo Bianconi <[email protected]> Signed-off-by: Felix Fietkau <[email protected]>
This commit is contained in:
committed by
Felix Fietkau
parent
f0dedcf6aa
commit
5079d5b0b1
@@ -16,6 +16,271 @@
|
||||
#include <linux/kthread.h>
|
||||
|
||||
#include "mt76.h"
|
||||
#include "sdio.h"
|
||||
|
||||
static u32 mt76s_read_whisr(struct mt76_dev *dev)
|
||||
{
|
||||
return sdio_readl(dev->sdio.func, MCR_WHISR, NULL);
|
||||
}
|
||||
|
||||
u32 mt76s_read_pcr(struct mt76_dev *dev)
|
||||
{
|
||||
struct mt76_sdio *sdio = &dev->sdio;
|
||||
|
||||
return sdio_readl(sdio->func, MCR_WHLPCR, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76s_read_pcr);
|
||||
|
||||
static u32 mt76s_read_mailbox(struct mt76_dev *dev, u32 offset)
|
||||
{
|
||||
struct sdio_func *func = dev->sdio.func;
|
||||
u32 val = ~0, status;
|
||||
int err;
|
||||
|
||||
sdio_claim_host(func);
|
||||
|
||||
sdio_writel(func, offset, MCR_H2DSM0R, &err);
|
||||
if (err < 0) {
|
||||
dev_err(dev->dev, "failed setting address [err=%d]\n", err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
sdio_writel(func, H2D_SW_INT_READ, MCR_WSICR, &err);
|
||||
if (err < 0) {
|
||||
dev_err(dev->dev, "failed setting read mode [err=%d]\n", err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = readx_poll_timeout(mt76s_read_whisr, dev, status,
|
||||
status & H2D_SW_INT_READ, 0, 1000000);
|
||||
if (err < 0) {
|
||||
dev_err(dev->dev, "query whisr timeout\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
sdio_writel(func, H2D_SW_INT_READ, MCR_WHISR, &err);
|
||||
if (err < 0) {
|
||||
dev_err(dev->dev, "failed setting read mode [err=%d]\n", err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
val = sdio_readl(func, MCR_H2DSM0R, &err);
|
||||
if (err < 0) {
|
||||
dev_err(dev->dev, "failed reading h2dsm0r [err=%d]\n", err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (val != offset) {
|
||||
dev_err(dev->dev, "register mismatch\n");
|
||||
val = ~0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
val = sdio_readl(func, MCR_D2HRM1R, &err);
|
||||
if (err < 0)
|
||||
dev_err(dev->dev, "failed reading d2hrm1r [err=%d]\n", err);
|
||||
|
||||
out:
|
||||
sdio_release_host(func);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void mt76s_write_mailbox(struct mt76_dev *dev, u32 offset, u32 val)
|
||||
{
|
||||
struct sdio_func *func = dev->sdio.func;
|
||||
u32 status;
|
||||
int err;
|
||||
|
||||
sdio_claim_host(func);
|
||||
|
||||
sdio_writel(func, offset, MCR_H2DSM0R, &err);
|
||||
if (err < 0) {
|
||||
dev_err(dev->dev, "failed setting address [err=%d]\n", err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
sdio_writel(func, val, MCR_H2DSM1R, &err);
|
||||
if (err < 0) {
|
||||
dev_err(dev->dev,
|
||||
"failed setting write value [err=%d]\n", err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
sdio_writel(func, H2D_SW_INT_WRITE, MCR_WSICR, &err);
|
||||
if (err < 0) {
|
||||
dev_err(dev->dev, "failed setting write mode [err=%d]\n", err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = readx_poll_timeout(mt76s_read_whisr, dev, status,
|
||||
status & H2D_SW_INT_WRITE, 0, 1000000);
|
||||
if (err < 0) {
|
||||
dev_err(dev->dev, "query whisr timeout\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
sdio_writel(func, H2D_SW_INT_WRITE, MCR_WHISR, &err);
|
||||
if (err < 0) {
|
||||
dev_err(dev->dev, "failed setting write mode [err=%d]\n", err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
val = sdio_readl(func, MCR_H2DSM0R, &err);
|
||||
if (err < 0) {
|
||||
dev_err(dev->dev, "failed reading h2dsm0r [err=%d]\n", err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (val != offset)
|
||||
dev_err(dev->dev, "register mismatch\n");
|
||||
|
||||
out:
|
||||
sdio_release_host(func);
|
||||
}
|
||||
|
||||
u32 mt76s_rr(struct mt76_dev *dev, u32 offset)
|
||||
{
|
||||
if (test_bit(MT76_STATE_MCU_RUNNING, &dev->phy.state))
|
||||
return dev->mcu_ops->mcu_rr(dev, offset);
|
||||
else
|
||||
return mt76s_read_mailbox(dev, offset);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76s_rr);
|
||||
|
||||
void mt76s_wr(struct mt76_dev *dev, u32 offset, u32 val)
|
||||
{
|
||||
if (test_bit(MT76_STATE_MCU_RUNNING, &dev->phy.state))
|
||||
dev->mcu_ops->mcu_wr(dev, offset, val);
|
||||
else
|
||||
mt76s_write_mailbox(dev, offset, val);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76s_wr);
|
||||
|
||||
u32 mt76s_rmw(struct mt76_dev *dev, u32 offset, u32 mask, u32 val)
|
||||
{
|
||||
val |= mt76s_rr(dev, offset) & ~mask;
|
||||
mt76s_wr(dev, offset, val);
|
||||
|
||||
return val;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76s_rmw);
|
||||
|
||||
void mt76s_write_copy(struct mt76_dev *dev, u32 offset,
|
||||
const void *data, int len)
|
||||
{
|
||||
const u32 *val = data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len / sizeof(u32); i++) {
|
||||
mt76s_wr(dev, offset, val[i]);
|
||||
offset += sizeof(u32);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76s_write_copy);
|
||||
|
||||
void mt76s_read_copy(struct mt76_dev *dev, u32 offset,
|
||||
void *data, int len)
|
||||
{
|
||||
u32 *val = data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len / sizeof(u32); i++) {
|
||||
val[i] = mt76s_rr(dev, offset);
|
||||
offset += sizeof(u32);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76s_read_copy);
|
||||
|
||||
int mt76s_wr_rp(struct mt76_dev *dev, u32 base,
|
||||
const struct mt76_reg_pair *data,
|
||||
int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
mt76s_wr(dev, data->reg, data->value);
|
||||
data++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76s_wr_rp);
|
||||
|
||||
int mt76s_rd_rp(struct mt76_dev *dev, u32 base,
|
||||
struct mt76_reg_pair *data, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
data->value = mt76s_rr(dev, data->reg);
|
||||
data++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76s_rd_rp);
|
||||
|
||||
int mt76s_hw_init(struct mt76_dev *dev, struct sdio_func *func)
|
||||
{
|
||||
u32 status, ctrl;
|
||||
int ret;
|
||||
|
||||
sdio_claim_host(func);
|
||||
|
||||
ret = sdio_enable_func(func);
|
||||
if (ret < 0)
|
||||
goto release;
|
||||
|
||||
/* Get ownership from the device */
|
||||
sdio_writel(func, WHLPCR_INT_EN_CLR | WHLPCR_FW_OWN_REQ_CLR,
|
||||
MCR_WHLPCR, &ret);
|
||||
if (ret < 0)
|
||||
goto disable_func;
|
||||
|
||||
ret = readx_poll_timeout(mt76s_read_pcr, dev, status,
|
||||
status & WHLPCR_IS_DRIVER_OWN, 2000, 1000000);
|
||||
if (ret < 0) {
|
||||
dev_err(dev->dev, "Cannot get ownership from device");
|
||||
goto disable_func;
|
||||
}
|
||||
|
||||
ret = sdio_set_block_size(func, 512);
|
||||
if (ret < 0)
|
||||
goto disable_func;
|
||||
|
||||
/* Enable interrupt */
|
||||
sdio_writel(func, WHLPCR_INT_EN_SET, MCR_WHLPCR, &ret);
|
||||
if (ret < 0)
|
||||
goto disable_func;
|
||||
|
||||
ctrl = WHIER_RX0_DONE_INT_EN | WHIER_TX_DONE_INT_EN;
|
||||
sdio_writel(func, ctrl, MCR_WHIER, &ret);
|
||||
if (ret < 0)
|
||||
goto disable_func;
|
||||
|
||||
/* set WHISR as read clear and Rx aggregation number as 16 */
|
||||
ctrl = FIELD_PREP(MAX_HIF_RX_LEN_NUM, 16);
|
||||
sdio_writel(func, ctrl, MCR_WHCR, &ret);
|
||||
if (ret < 0)
|
||||
goto disable_func;
|
||||
|
||||
ret = sdio_claim_irq(func, mt76s_sdio_irq);
|
||||
if (ret < 0)
|
||||
goto disable_func;
|
||||
|
||||
sdio_release_host(func);
|
||||
|
||||
return 0;
|
||||
|
||||
disable_func:
|
||||
sdio_disable_func(func);
|
||||
release:
|
||||
sdio_release_host(func);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76s_hw_init);
|
||||
|
||||
int mt76s_alloc_rx_queue(struct mt76_dev *dev, enum mt76_rxq_id qid)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user