linux/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
<<
>>
Prefs
   1// SPDX-License-Identifier: ISC
   2/* Copyright (C) 2020 MediaTek Inc.
   3 *
   4 * Author: Felix Fietkau <nbd@nbd.name>
   5 *         Lorenzo Bianconi <lorenzo@kernel.org>
   6 *         Sean Wang <sean.wang@mediatek.com>
   7 */
   8
   9#include <linux/kernel.h>
  10#include <linux/iopoll.h>
  11#include <linux/module.h>
  12
  13#include <linux/mmc/host.h>
  14#include <linux/mmc/sdio_ids.h>
  15#include <linux/mmc/sdio_func.h>
  16
  17#include "mt7615.h"
  18#include "sdio.h"
  19#include "mac.h"
  20#include "mcu.h"
  21
  22static const struct sdio_device_id mt7663s_table[] = {
  23        { SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, 0x7603) },
  24        { }     /* Terminating entry */
  25};
  26
  27static u32 mt7663s_read_whisr(struct mt76_dev *dev)
  28{
  29        return sdio_readl(dev->sdio.func, MCR_WHISR, NULL);
  30}
  31
  32u32 mt7663s_read_pcr(struct mt7615_dev *dev)
  33{
  34        struct mt76_sdio *sdio = &dev->mt76.sdio;
  35
  36        return sdio_readl(sdio->func, MCR_WHLPCR, NULL);
  37}
  38
  39static u32 mt7663s_read_mailbox(struct mt76_dev *dev, u32 offset)
  40{
  41        struct sdio_func *func = dev->sdio.func;
  42        u32 val = ~0, status;
  43        int err;
  44
  45        sdio_claim_host(func);
  46
  47        sdio_writel(func, offset, MCR_H2DSM0R, &err);
  48        if (err < 0) {
  49                dev_err(dev->dev, "failed setting address [err=%d]\n", err);
  50                goto out;
  51        }
  52
  53        sdio_writel(func, H2D_SW_INT_READ, MCR_WSICR, &err);
  54        if (err < 0) {
  55                dev_err(dev->dev, "failed setting read mode [err=%d]\n", err);
  56                goto out;
  57        }
  58
  59        err = readx_poll_timeout(mt7663s_read_whisr, dev, status,
  60                                 status & H2D_SW_INT_READ, 0, 1000000);
  61        if (err < 0) {
  62                dev_err(dev->dev, "query whisr timeout\n");
  63                goto out;
  64        }
  65
  66        sdio_writel(func, H2D_SW_INT_READ, MCR_WHISR, &err);
  67        if (err < 0) {
  68                dev_err(dev->dev, "failed setting read mode [err=%d]\n", err);
  69                goto out;
  70        }
  71
  72        val = sdio_readl(func, MCR_H2DSM0R, &err);
  73        if (err < 0) {
  74                dev_err(dev->dev, "failed reading h2dsm0r [err=%d]\n", err);
  75                goto out;
  76        }
  77
  78        if (val != offset) {
  79                dev_err(dev->dev, "register mismatch\n");
  80                val = ~0;
  81                goto out;
  82        }
  83
  84        val = sdio_readl(func, MCR_D2HRM1R, &err);
  85        if (err < 0)
  86                dev_err(dev->dev, "failed reading d2hrm1r [err=%d]\n", err);
  87
  88out:
  89        sdio_release_host(func);
  90
  91        return val;
  92}
  93
  94static void mt7663s_write_mailbox(struct mt76_dev *dev, u32 offset, u32 val)
  95{
  96        struct sdio_func *func = dev->sdio.func;
  97        u32 status;
  98        int err;
  99
 100        sdio_claim_host(func);
 101
 102        sdio_writel(func, offset, MCR_H2DSM0R, &err);
 103        if (err < 0) {
 104                dev_err(dev->dev, "failed setting address [err=%d]\n", err);
 105                goto out;
 106        }
 107
 108        sdio_writel(func, val, MCR_H2DSM1R, &err);
 109        if (err < 0) {
 110                dev_err(dev->dev,
 111                        "failed setting write value [err=%d]\n", err);
 112                goto out;
 113        }
 114
 115        sdio_writel(func, H2D_SW_INT_WRITE, MCR_WSICR, &err);
 116        if (err < 0) {
 117                dev_err(dev->dev, "failed setting write mode [err=%d]\n", err);
 118                goto out;
 119        }
 120
 121        err = readx_poll_timeout(mt7663s_read_whisr, dev, status,
 122                                 status & H2D_SW_INT_WRITE, 0, 1000000);
 123        if (err < 0) {
 124                dev_err(dev->dev, "query whisr timeout\n");
 125                goto out;
 126        }
 127
 128        sdio_writel(func, H2D_SW_INT_WRITE, MCR_WHISR, &err);
 129        if (err < 0) {
 130                dev_err(dev->dev, "failed setting write mode [err=%d]\n", err);
 131                goto out;
 132        }
 133
 134        val = sdio_readl(func, MCR_H2DSM0R, &err);
 135        if (err < 0) {
 136                dev_err(dev->dev, "failed reading h2dsm0r [err=%d]\n", err);
 137                goto out;
 138        }
 139
 140        if (val != offset)
 141                dev_err(dev->dev, "register mismatch\n");
 142
 143out:
 144        sdio_release_host(func);
 145}
 146
 147static u32 mt7663s_rr(struct mt76_dev *dev, u32 offset)
 148{
 149        if (test_bit(MT76_STATE_MCU_RUNNING, &dev->phy.state))
 150                return dev->mcu_ops->mcu_rr(dev, offset);
 151        else
 152                return mt7663s_read_mailbox(dev, offset);
 153}
 154
 155static void mt7663s_wr(struct mt76_dev *dev, u32 offset, u32 val)
 156{
 157        if (test_bit(MT76_STATE_MCU_RUNNING, &dev->phy.state))
 158                dev->mcu_ops->mcu_wr(dev, offset, val);
 159        else
 160                mt7663s_write_mailbox(dev, offset, val);
 161}
 162
 163static u32 mt7663s_rmw(struct mt76_dev *dev, u32 offset, u32 mask, u32 val)
 164{
 165        val |= mt7663s_rr(dev, offset) & ~mask;
 166        mt7663s_wr(dev, offset, val);
 167
 168        return val;
 169}
 170
 171static void mt7663s_write_copy(struct mt76_dev *dev, u32 offset,
 172                               const void *data, int len)
 173{
 174        const u32 *val = data;
 175        int i;
 176
 177        for (i = 0; i < len / sizeof(u32); i++) {
 178                mt7663s_wr(dev, offset, val[i]);
 179                offset += sizeof(u32);
 180        }
 181}
 182
 183static void mt7663s_read_copy(struct mt76_dev *dev, u32 offset,
 184                              void *data, int len)
 185{
 186        u32 *val = data;
 187        int i;
 188
 189        for (i = 0; i < len / sizeof(u32); i++) {
 190                val[i] = mt7663s_rr(dev, offset);
 191                offset += sizeof(u32);
 192        }
 193}
 194
 195static int mt7663s_wr_rp(struct mt76_dev *dev, u32 base,
 196                         const struct mt76_reg_pair *data,
 197                         int len)
 198{
 199        int i;
 200
 201        for (i = 0; i < len; i++) {
 202                mt7663s_wr(dev, data->reg, data->value);
 203                data++;
 204        }
 205
 206        return 0;
 207}
 208
 209static int mt7663s_rd_rp(struct mt76_dev *dev, u32 base,
 210                         struct mt76_reg_pair *data,
 211                         int len)
 212{
 213        int i;
 214
 215        for (i = 0; i < len; i++) {
 216                data->value = mt7663s_rr(dev, data->reg);
 217                data++;
 218        }
 219
 220        return 0;
 221}
 222
 223static void mt7663s_init_work(struct work_struct *work)
 224{
 225        struct mt7615_dev *dev;
 226
 227        dev = container_of(work, struct mt7615_dev, mcu_work);
 228        if (mt7663s_mcu_init(dev))
 229                return;
 230
 231        mt7615_init_work(dev);
 232}
 233
 234static int mt7663s_hw_init(struct mt7615_dev *dev, struct sdio_func *func)
 235{
 236        u32 status, ctrl;
 237        int ret;
 238
 239        sdio_claim_host(func);
 240
 241        ret = sdio_enable_func(func);
 242        if (ret < 0)
 243                goto release;
 244
 245        /* Get ownership from the device */
 246        sdio_writel(func, WHLPCR_INT_EN_CLR | WHLPCR_FW_OWN_REQ_CLR,
 247                    MCR_WHLPCR, &ret);
 248        if (ret < 0)
 249                goto disable_func;
 250
 251        ret = readx_poll_timeout(mt7663s_read_pcr, dev, status,
 252                                 status & WHLPCR_IS_DRIVER_OWN, 2000, 1000000);
 253        if (ret < 0) {
 254                dev_err(dev->mt76.dev, "Cannot get ownership from device");
 255                goto disable_func;
 256        }
 257
 258        ret = sdio_set_block_size(func, 512);
 259        if (ret < 0)
 260                goto disable_func;
 261
 262        /* Enable interrupt */
 263        sdio_writel(func, WHLPCR_INT_EN_SET, MCR_WHLPCR, &ret);
 264        if (ret < 0)
 265                goto disable_func;
 266
 267        ctrl = WHIER_RX0_DONE_INT_EN | WHIER_TX_DONE_INT_EN;
 268        sdio_writel(func, ctrl, MCR_WHIER, &ret);
 269        if (ret < 0)
 270                goto disable_func;
 271
 272        /* set WHISR as read clear and Rx aggregation number as 16 */
 273        ctrl = FIELD_PREP(MAX_HIF_RX_LEN_NUM, 16);
 274        sdio_writel(func, ctrl, MCR_WHCR, &ret);
 275        if (ret < 0)
 276                goto disable_func;
 277
 278        ret = sdio_claim_irq(func, mt7663s_sdio_irq);
 279        if (ret < 0)
 280                goto disable_func;
 281
 282        sdio_release_host(func);
 283
 284        return 0;
 285
 286disable_func:
 287        sdio_disable_func(func);
 288release:
 289        sdio_release_host(func);
 290
 291        return ret;
 292}
 293
 294static int mt7663s_probe(struct sdio_func *func,
 295                         const struct sdio_device_id *id)
 296{
 297        static const struct mt76_driver_ops drv_ops = {
 298                .txwi_size = MT_USB_TXD_SIZE,
 299                .drv_flags = MT_DRV_RX_DMA_HDR,
 300                .tx_prepare_skb = mt7663_usb_sdio_tx_prepare_skb,
 301                .tx_complete_skb = mt7663_usb_sdio_tx_complete_skb,
 302                .tx_status_data = mt7663_usb_sdio_tx_status_data,
 303                .rx_skb = mt7615_queue_rx_skb,
 304                .sta_ps = mt7615_sta_ps,
 305                .sta_add = mt7615_mac_sta_add,
 306                .sta_remove = mt7615_mac_sta_remove,
 307                .update_survey = mt7615_update_channel,
 308        };
 309        static const struct mt76_bus_ops mt7663s_ops = {
 310                .rr = mt7663s_rr,
 311                .rmw = mt7663s_rmw,
 312                .wr = mt7663s_wr,
 313                .write_copy = mt7663s_write_copy,
 314                .read_copy = mt7663s_read_copy,
 315                .wr_rp = mt7663s_wr_rp,
 316                .rd_rp = mt7663s_rd_rp,
 317                .type = MT76_BUS_SDIO,
 318        };
 319        struct ieee80211_ops *ops;
 320        struct mt7615_dev *dev;
 321        struct mt76_dev *mdev;
 322        int i, ret;
 323
 324        ops = devm_kmemdup(&func->dev, &mt7615_ops, sizeof(mt7615_ops),
 325                           GFP_KERNEL);
 326        if (!ops)
 327                return -ENOMEM;
 328
 329        mdev = mt76_alloc_device(&func->dev, sizeof(*dev), ops, &drv_ops);
 330        if (!mdev)
 331                return -ENOMEM;
 332
 333        dev = container_of(mdev, struct mt7615_dev, mt76);
 334
 335        INIT_WORK(&dev->mcu_work, mt7663s_init_work);
 336        dev->reg_map = mt7663_usb_sdio_reg_map;
 337        dev->ops = ops;
 338        sdio_set_drvdata(func, dev);
 339
 340        ret = mt76s_init(mdev, func, &mt7663s_ops);
 341        if (ret < 0)
 342                goto error;
 343
 344        ret = mt7663s_hw_init(dev, func);
 345        if (ret)
 346                goto error;
 347
 348        mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
 349                    (mt76_rr(dev, MT_HW_REV) & 0xff);
 350        dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
 351
 352        mdev->sdio.intr_data = devm_kmalloc(mdev->dev,
 353                                            sizeof(struct mt76s_intr),
 354                                            GFP_KERNEL);
 355        if (!mdev->sdio.intr_data) {
 356                ret = -ENOMEM;
 357                goto error;
 358        }
 359
 360        for (i = 0; i < ARRAY_SIZE(mdev->sdio.xmit_buf); i++) {
 361                mdev->sdio.xmit_buf[i] = devm_kmalloc(mdev->dev,
 362                                                      MT76S_XMIT_BUF_SZ,
 363                                                      GFP_KERNEL);
 364                if (!mdev->sdio.xmit_buf[i]) {
 365                        ret = -ENOMEM;
 366                        goto error;
 367                }
 368        }
 369
 370        ret = mt76s_alloc_queues(&dev->mt76);
 371        if (ret)
 372                goto error;
 373
 374        ret = mt76_worker_setup(mt76_hw(dev), &mdev->sdio.txrx_worker,
 375                                mt7663s_txrx_worker, "sdio-txrx");
 376        if (ret)
 377                goto error;
 378
 379        sched_set_fifo_low(mdev->sdio.txrx_worker.task);
 380
 381        ret = mt7663_usb_sdio_register_device(dev);
 382        if (ret)
 383                goto error;
 384
 385        return 0;
 386
 387error:
 388        mt76s_deinit(&dev->mt76);
 389        mt76_free_device(&dev->mt76);
 390
 391        return ret;
 392}
 393
 394static void mt7663s_remove(struct sdio_func *func)
 395{
 396        struct mt7615_dev *dev = sdio_get_drvdata(func);
 397
 398        if (!test_and_clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
 399                return;
 400
 401        ieee80211_unregister_hw(dev->mt76.hw);
 402        mt76s_deinit(&dev->mt76);
 403        mt76_free_device(&dev->mt76);
 404}
 405
 406#ifdef CONFIG_PM
 407static int mt7663s_suspend(struct device *dev)
 408{
 409        struct sdio_func *func = dev_to_sdio_func(dev);
 410        struct mt7615_dev *mdev = sdio_get_drvdata(func);
 411        int err;
 412
 413        if (!test_bit(MT76_STATE_SUSPEND, &mdev->mphy.state) &&
 414            mt7615_firmware_offload(mdev)) {
 415                int err;
 416
 417                err = mt76_connac_mcu_set_hif_suspend(&mdev->mt76, true);
 418                if (err < 0)
 419                        return err;
 420        }
 421
 422        sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
 423
 424        err = mt7615_mcu_set_fw_ctrl(mdev);
 425        if (err)
 426                return err;
 427
 428        mt76_worker_disable(&mdev->mt76.sdio.txrx_worker);
 429        mt76_worker_disable(&mdev->mt76.sdio.status_worker);
 430        mt76_worker_disable(&mdev->mt76.sdio.net_worker);
 431
 432        cancel_work_sync(&mdev->mt76.sdio.stat_work);
 433        clear_bit(MT76_READING_STATS, &mdev->mphy.state);
 434
 435        mt76_tx_status_check(&mdev->mt76, NULL, true);
 436
 437        return 0;
 438}
 439
 440static int mt7663s_resume(struct device *dev)
 441{
 442        struct sdio_func *func = dev_to_sdio_func(dev);
 443        struct mt7615_dev *mdev = sdio_get_drvdata(func);
 444        int err;
 445
 446        mt76_worker_enable(&mdev->mt76.sdio.txrx_worker);
 447        mt76_worker_enable(&mdev->mt76.sdio.status_worker);
 448        mt76_worker_enable(&mdev->mt76.sdio.net_worker);
 449
 450        err = mt7615_mcu_set_drv_ctrl(mdev);
 451        if (err)
 452                return err;
 453
 454        if (!test_bit(MT76_STATE_SUSPEND, &mdev->mphy.state) &&
 455            mt7615_firmware_offload(mdev))
 456                err = mt76_connac_mcu_set_hif_suspend(&mdev->mt76, false);
 457
 458        return err;
 459}
 460
 461static const struct dev_pm_ops mt7663s_pm_ops = {
 462        .suspend = mt7663s_suspend,
 463        .resume = mt7663s_resume,
 464};
 465#endif
 466
 467MODULE_DEVICE_TABLE(sdio, mt7663s_table);
 468MODULE_FIRMWARE(MT7663_OFFLOAD_FIRMWARE_N9);
 469MODULE_FIRMWARE(MT7663_OFFLOAD_ROM_PATCH);
 470MODULE_FIRMWARE(MT7663_FIRMWARE_N9);
 471MODULE_FIRMWARE(MT7663_ROM_PATCH);
 472
 473static struct sdio_driver mt7663s_driver = {
 474        .name           = KBUILD_MODNAME,
 475        .probe          = mt7663s_probe,
 476        .remove         = mt7663s_remove,
 477        .id_table       = mt7663s_table,
 478#ifdef CONFIG_PM
 479        .drv = {
 480                .pm = &mt7663s_pm_ops,
 481        }
 482#endif
 483};
 484module_sdio_driver(mt7663s_driver);
 485
 486MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
 487MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
 488MODULE_LICENSE("Dual BSD/GPL");
 489