18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: ISC 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include "mt76.h" 78c2ecf20Sopenharmony_ci#include "trace.h" 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_cistatic u32 mt76_mmio_rr(struct mt76_dev *dev, u32 offset) 108c2ecf20Sopenharmony_ci{ 118c2ecf20Sopenharmony_ci u32 val; 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci val = readl(dev->mmio.regs + offset); 148c2ecf20Sopenharmony_ci trace_reg_rr(dev, offset, val); 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci return val; 178c2ecf20Sopenharmony_ci} 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistatic void mt76_mmio_wr(struct mt76_dev *dev, u32 offset, u32 val) 208c2ecf20Sopenharmony_ci{ 218c2ecf20Sopenharmony_ci trace_reg_wr(dev, offset, val); 228c2ecf20Sopenharmony_ci writel(val, dev->mmio.regs + offset); 238c2ecf20Sopenharmony_ci} 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistatic u32 mt76_mmio_rmw(struct mt76_dev *dev, u32 offset, u32 mask, u32 val) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci val |= mt76_mmio_rr(dev, offset) & ~mask; 288c2ecf20Sopenharmony_ci mt76_mmio_wr(dev, offset, val); 298c2ecf20Sopenharmony_ci return val; 308c2ecf20Sopenharmony_ci} 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistatic void mt76_mmio_write_copy(struct mt76_dev *dev, u32 offset, 338c2ecf20Sopenharmony_ci const void *data, int len) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci __iowrite32_copy(dev->mmio.regs + offset, data, DIV_ROUND_UP(len, 4)); 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic void mt76_mmio_read_copy(struct mt76_dev *dev, u32 offset, 398c2ecf20Sopenharmony_ci void *data, int len) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci __ioread32_copy(data, dev->mmio.regs + offset, DIV_ROUND_UP(len, 4)); 428c2ecf20Sopenharmony_ci} 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cistatic int mt76_mmio_wr_rp(struct mt76_dev *dev, u32 base, 458c2ecf20Sopenharmony_ci const struct mt76_reg_pair *data, int len) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci while (len > 0) { 488c2ecf20Sopenharmony_ci mt76_mmio_wr(dev, data->reg, data->value); 498c2ecf20Sopenharmony_ci data++; 508c2ecf20Sopenharmony_ci len--; 518c2ecf20Sopenharmony_ci } 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci return 0; 548c2ecf20Sopenharmony_ci} 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cistatic int mt76_mmio_rd_rp(struct mt76_dev *dev, u32 base, 578c2ecf20Sopenharmony_ci struct mt76_reg_pair *data, int len) 588c2ecf20Sopenharmony_ci{ 598c2ecf20Sopenharmony_ci while (len > 0) { 608c2ecf20Sopenharmony_ci data->value = mt76_mmio_rr(dev, data->reg); 618c2ecf20Sopenharmony_ci data++; 628c2ecf20Sopenharmony_ci len--; 638c2ecf20Sopenharmony_ci } 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci return 0; 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_civoid mt76_set_irq_mask(struct mt76_dev *dev, u32 addr, 698c2ecf20Sopenharmony_ci u32 clear, u32 set) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci unsigned long flags; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci spin_lock_irqsave(&dev->mmio.irq_lock, flags); 748c2ecf20Sopenharmony_ci dev->mmio.irqmask &= ~clear; 758c2ecf20Sopenharmony_ci dev->mmio.irqmask |= set; 768c2ecf20Sopenharmony_ci if (addr) 778c2ecf20Sopenharmony_ci mt76_mmio_wr(dev, addr, dev->mmio.irqmask); 788c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&dev->mmio.irq_lock, flags); 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(mt76_set_irq_mask); 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_civoid mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs) 838c2ecf20Sopenharmony_ci{ 848c2ecf20Sopenharmony_ci static const struct mt76_bus_ops mt76_mmio_ops = { 858c2ecf20Sopenharmony_ci .rr = mt76_mmio_rr, 868c2ecf20Sopenharmony_ci .rmw = mt76_mmio_rmw, 878c2ecf20Sopenharmony_ci .wr = mt76_mmio_wr, 888c2ecf20Sopenharmony_ci .write_copy = mt76_mmio_write_copy, 898c2ecf20Sopenharmony_ci .read_copy = mt76_mmio_read_copy, 908c2ecf20Sopenharmony_ci .wr_rp = mt76_mmio_wr_rp, 918c2ecf20Sopenharmony_ci .rd_rp = mt76_mmio_rd_rp, 928c2ecf20Sopenharmony_ci .type = MT76_BUS_MMIO, 938c2ecf20Sopenharmony_ci }; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci dev->bus = &mt76_mmio_ops; 968c2ecf20Sopenharmony_ci dev->mmio.regs = regs; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci spin_lock_init(&dev->mmio.irq_lock); 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(mt76_mmio_init); 101