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_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 298                           struct ieee80211_sta *sta)
 299{
 300        struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
 301        struct mt76_sdio *sdio = &mdev->sdio;
 302        u32 pse, ple;
 303        int err;
 304
 305        err = mt7615_mac_sta_add(mdev, vif, sta);
 306        if (err < 0)
 307                return err;
 308
 309        /* init sched data quota */
 310        pse = mt76_get_field(dev, MT_PSE_PG_HIF0_GROUP, MT_HIF0_MIN_QUOTA);
 311        ple = mt76_get_field(dev, MT_PLE_PG_HIF0_GROUP, MT_HIF0_MIN_QUOTA);
 312
 313        mutex_lock(&sdio->sched.lock);
 314        sdio->sched.pse_data_quota = pse;
 315        sdio->sched.ple_data_quota = ple;
 316        mutex_unlock(&sdio->sched.lock);
 317
 318        return 0;
 319}
 320
 321static int mt7663s_probe(struct sdio_func *func,
 322                         const struct sdio_device_id *id)
 323{
 324        static const struct mt76_driver_ops drv_ops = {
 325                .txwi_size = MT_USB_TXD_SIZE,
 326                .drv_flags = MT_DRV_RX_DMA_HDR | MT_DRV_HW_MGMT_TXQ,
 327                .tx_prepare_skb = mt7663_usb_sdio_tx_prepare_skb,
 328                .tx_complete_skb = mt7663_usb_sdio_tx_complete_skb,
 329                .tx_status_data = mt7663_usb_sdio_tx_status_data,
 330                .rx_skb = mt7615_queue_rx_skb,
 331                .sta_ps = mt7615_sta_ps,
 332                .sta_add = mt7663s_sta_add,
 333                .sta_remove = mt7615_mac_sta_remove,
 334                .update_survey = mt7615_update_channel,
 335        };
 336        static const struct mt76_bus_ops mt7663s_ops = {
 337                .rr = mt7663s_rr,
 338                .rmw = mt7663s_rmw,
 339                .wr = mt7663s_wr,
 340                .write_copy = mt7663s_write_copy,
 341                .read_copy = mt7663s_read_copy,
 342                .wr_rp = mt7663s_wr_rp,
 343                .rd_rp = mt7663s_rd_rp,
 344                .type = MT76_BUS_SDIO,
 345        };
 346        struct ieee80211_ops *ops;
 347        struct mt7615_dev *dev;
 348        struct mt76_dev *mdev;
 349        int ret;
 350
 351        ops = devm_kmemdup(&func->dev, &mt7615_ops, sizeof(mt7615_ops),
 352                           GFP_KERNEL);
 353        if (!ops)
 354                return -ENOMEM;
 355
 356        mdev = mt76_alloc_device(&func->dev, sizeof(*dev), ops, &drv_ops);
 357        if (!mdev)
 358                return -ENOMEM;
 359
 360        dev = container_of(mdev, struct mt7615_dev, mt76);
 361
 362        INIT_WORK(&dev->mcu_work, mt7663s_init_work);
 363        dev->reg_map = mt7663_usb_sdio_reg_map;
 364        dev->ops = ops;
 365        sdio_set_drvdata(func, dev);
 366
 367        mdev->sdio.tx_kthread = kthread_create(mt7663s_kthread_run, dev,
 368                                               "mt7663s_tx");
 369        if (IS_ERR(mdev->sdio.tx_kthread))
 370                return PTR_ERR(mdev->sdio.tx_kthread);
 371
 372        ret = mt76s_init(mdev, func, &mt7663s_ops);
 373        if (ret < 0)
 374                goto err_free;
 375
 376        ret = mt7663s_hw_init(dev, func);
 377        if (ret)
 378                goto err_free;
 379
 380        mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
 381                    (mt76_rr(dev, MT_HW_REV) & 0xff);
 382        dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
 383
 384        ret = mt76s_alloc_queues(&dev->mt76);
 385        if (ret)
 386                goto err_deinit;
 387
 388        ret = mt7663_usb_sdio_register_device(dev);
 389        if (ret)
 390                goto err_deinit;
 391
 392        return 0;
 393
 394err_deinit:
 395        mt76s_deinit(&dev->mt76);
 396err_free:
 397        mt76_free_device(&dev->mt76);
 398
 399        return ret;
 400}
 401
 402static void mt7663s_remove(struct sdio_func *func)
 403{
 404        struct mt7615_dev *dev = sdio_get_drvdata(func);
 405
 406        if (!test_and_clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
 407                return;
 408
 409        ieee80211_unregister_hw(dev->mt76.hw);
 410        mt76s_deinit(&dev->mt76);
 411        mt76_free_device(&dev->mt76);
 412}
 413
 414#ifdef CONFIG_PM
 415static int mt7663s_suspend(struct device *dev)
 416{
 417        struct sdio_func *func = dev_to_sdio_func(dev);
 418        struct mt7615_dev *mdev = sdio_get_drvdata(func);
 419
 420        if (!test_bit(MT76_STATE_SUSPEND, &mdev->mphy.state) &&
 421            mt7615_firmware_offload(mdev)) {
 422                int err;
 423
 424                err = mt7615_mcu_set_hif_suspend(mdev, true);
 425                if (err < 0)
 426                        return err;
 427        }
 428
 429        mt76s_stop_txrx(&mdev->mt76);
 430
 431        return mt7663s_firmware_own(mdev);
 432}
 433
 434static int mt7663s_resume(struct device *dev)
 435{
 436        struct sdio_func *func = dev_to_sdio_func(dev);
 437        struct mt7615_dev *mdev = sdio_get_drvdata(func);
 438        int err;
 439
 440        err = mt7663s_driver_own(mdev);
 441        if (err)
 442                return err;
 443
 444        if (!test_bit(MT76_STATE_SUSPEND, &mdev->mphy.state) &&
 445            mt7615_firmware_offload(mdev))
 446                err = mt7615_mcu_set_hif_suspend(mdev, false);
 447
 448        return err;
 449}
 450
 451static const struct dev_pm_ops mt7663s_pm_ops = {
 452        .suspend = mt7663s_suspend,
 453        .resume = mt7663s_resume,
 454};
 455#endif
 456
 457MODULE_DEVICE_TABLE(sdio, mt7663s_table);
 458MODULE_FIRMWARE(MT7663_OFFLOAD_FIRMWARE_N9);
 459MODULE_FIRMWARE(MT7663_OFFLOAD_ROM_PATCH);
 460MODULE_FIRMWARE(MT7663_FIRMWARE_N9);
 461MODULE_FIRMWARE(MT7663_ROM_PATCH);
 462
 463static struct sdio_driver mt7663s_driver = {
 464        .name           = KBUILD_MODNAME,
 465        .probe          = mt7663s_probe,
 466        .remove         = mt7663s_remove,
 467        .id_table       = mt7663s_table,
 468#ifdef CONFIG_PM
 469        .drv = {
 470                .pm = &mt7663s_pm_ops,
 471        }
 472#endif
 473};
 474module_sdio_driver(mt7663s_driver);
 475
 476MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
 477MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
 478MODULE_LICENSE("Dual BSD/GPL");
 479