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