1 // SPDX-License-Identifier: ISC
2 /*
3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
4 */
5
6 #include "mt76.h"
7 #include "dma.h"
8 #include "trace.h"
9
mt76_mmio_rr(struct mt76_dev * dev,u32 offset)10 static u32 mt76_mmio_rr(struct mt76_dev *dev, u32 offset)
11 {
12 u32 val;
13
14 #if defined(__linux__)
15 val = readl(dev->mmio.regs + offset);
16 #elif defined(__FreeBSD__)
17 val = readl((u8 *)dev->mmio.regs + offset);
18 #endif
19 trace_reg_rr(dev, offset, val);
20
21 return val;
22 }
23
mt76_mmio_wr(struct mt76_dev * dev,u32 offset,u32 val)24 static void mt76_mmio_wr(struct mt76_dev *dev, u32 offset, u32 val)
25 {
26 trace_reg_wr(dev, offset, val);
27 #if defined(__linux__)
28 writel(val, dev->mmio.regs + offset);
29 #elif defined(__FreeBSD__)
30 writel(val, (u8 *)dev->mmio.regs + offset);
31 #endif
32 }
33
mt76_mmio_rmw(struct mt76_dev * dev,u32 offset,u32 mask,u32 val)34 static u32 mt76_mmio_rmw(struct mt76_dev *dev, u32 offset, u32 mask, u32 val)
35 {
36 val |= mt76_mmio_rr(dev, offset) & ~mask;
37 mt76_mmio_wr(dev, offset, val);
38 return val;
39 }
40
mt76_mmio_write_copy(struct mt76_dev * dev,u32 offset,const void * data,int len)41 static void mt76_mmio_write_copy(struct mt76_dev *dev, u32 offset,
42 const void *data, int len)
43 {
44 #if defined(__linux__)
45 __iowrite32_copy(dev->mmio.regs + offset, data, DIV_ROUND_UP(len, 4));
46 #elif defined(__FreeBSD__)
47 __iowrite32_copy((u8 *)dev->mmio.regs + offset, data, DIV_ROUND_UP(len, 4));
48 #endif
49 }
50
mt76_mmio_read_copy(struct mt76_dev * dev,u32 offset,void * data,int len)51 static void mt76_mmio_read_copy(struct mt76_dev *dev, u32 offset,
52 void *data, int len)
53 {
54 #if defined(__linux__)
55 __ioread32_copy(data, dev->mmio.regs + offset, DIV_ROUND_UP(len, 4));
56 #elif defined(__FreeBSD__)
57 __ioread32_copy(data, (u8 *)dev->mmio.regs + offset, DIV_ROUND_UP(len, 4));
58 #endif
59 }
60
mt76_mmio_wr_rp(struct mt76_dev * dev,u32 base,const struct mt76_reg_pair * data,int len)61 static int mt76_mmio_wr_rp(struct mt76_dev *dev, u32 base,
62 const struct mt76_reg_pair *data, int len)
63 {
64 while (len > 0) {
65 mt76_mmio_wr(dev, data->reg, data->value);
66 data++;
67 len--;
68 }
69
70 return 0;
71 }
72
mt76_mmio_rd_rp(struct mt76_dev * dev,u32 base,struct mt76_reg_pair * data,int len)73 static int mt76_mmio_rd_rp(struct mt76_dev *dev, u32 base,
74 struct mt76_reg_pair *data, int len)
75 {
76 while (len > 0) {
77 data->value = mt76_mmio_rr(dev, data->reg);
78 data++;
79 len--;
80 }
81
82 return 0;
83 }
84
mt76_set_irq_mask(struct mt76_dev * dev,u32 addr,u32 clear,u32 set)85 void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr,
86 u32 clear, u32 set)
87 {
88 unsigned long flags;
89
90 spin_lock_irqsave(&dev->mmio.irq_lock, flags);
91 dev->mmio.irqmask &= ~clear;
92 dev->mmio.irqmask |= set;
93 if (addr) {
94 if (mtk_wed_device_active(&dev->mmio.wed))
95 mtk_wed_device_irq_set_mask(&dev->mmio.wed,
96 dev->mmio.irqmask);
97 else
98 mt76_mmio_wr(dev, addr, dev->mmio.irqmask);
99 }
100 spin_unlock_irqrestore(&dev->mmio.irq_lock, flags);
101 }
102 EXPORT_SYMBOL_GPL(mt76_set_irq_mask);
103
mt76_mmio_init(struct mt76_dev * dev,void __iomem * regs)104 void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs)
105 {
106 static const struct mt76_bus_ops mt76_mmio_ops = {
107 .rr = mt76_mmio_rr,
108 .rmw = mt76_mmio_rmw,
109 .wr = mt76_mmio_wr,
110 .write_copy = mt76_mmio_write_copy,
111 .read_copy = mt76_mmio_read_copy,
112 .wr_rp = mt76_mmio_wr_rp,
113 .rd_rp = mt76_mmio_rd_rp,
114 .type = MT76_BUS_MMIO,
115 };
116
117 dev->bus = &mt76_mmio_ops;
118 dev->mmio.regs = regs;
119
120 spin_lock_init(&dev->mmio.irq_lock);
121 }
122 EXPORT_SYMBOL_GPL(mt76_mmio_init);
123