1 // SPDX-License-Identifier: BSD-3-Clause-Clear
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 val = readl(dev->mmio.regs + offset);
15 trace_reg_rr(dev, offset, val);
16
17 return val;
18 }
19
mt76_mmio_wr(struct mt76_dev * dev,u32 offset,u32 val)20 static void mt76_mmio_wr(struct mt76_dev *dev, u32 offset, u32 val)
21 {
22 trace_reg_wr(dev, offset, val);
23 writel(val, dev->mmio.regs + offset);
24 }
25
mt76_mmio_rmw(struct mt76_dev * dev,u32 offset,u32 mask,u32 val)26 static u32 mt76_mmio_rmw(struct mt76_dev *dev, u32 offset, u32 mask, u32 val)
27 {
28 val |= mt76_mmio_rr(dev, offset) & ~mask;
29 mt76_mmio_wr(dev, offset, val);
30 return val;
31 }
32
mt76_mmio_write_copy(struct mt76_dev * dev,u32 offset,const void * data,int len)33 static void mt76_mmio_write_copy(struct mt76_dev *dev, u32 offset,
34 const void *data, int len)
35 {
36 int i;
37
38 for (i = 0; i + 4 <= len; i += 4)
39 writel(get_unaligned_le32(data + i),
40 dev->mmio.regs + offset + i);
41
42 if (i < len) {
43 u8 tmp[4] = {};
44
45 memcpy(tmp, data + i, len - i);
46 writel(get_unaligned_le32(tmp), dev->mmio.regs + offset + i);
47 }
48 }
49
mt76_mmio_read_copy(struct mt76_dev * dev,u32 offset,void * data,int len)50 static void mt76_mmio_read_copy(struct mt76_dev *dev, u32 offset,
51 void *data, int len)
52 {
53 int i;
54
55 for (i = 0; i + 4 <= len; i += 4)
56 put_unaligned_le32(readl(dev->mmio.regs + offset + i),
57 data + i);
58
59 if (i < len) {
60 u8 tmp[4];
61
62 put_unaligned_le32(readl(dev->mmio.regs + offset + i), tmp);
63 memcpy(data + i, tmp, len - i);
64 }
65 }
66
mt76_mmio_wr_rp(struct mt76_dev * dev,u32 base,const struct mt76_reg_pair * data,int len)67 static int mt76_mmio_wr_rp(struct mt76_dev *dev, u32 base,
68 const struct mt76_reg_pair *data, int len)
69 {
70 while (len > 0) {
71 mt76_mmio_wr(dev, data->reg, data->value);
72 data++;
73 len--;
74 }
75
76 return 0;
77 }
78
mt76_mmio_rd_rp(struct mt76_dev * dev,u32 base,struct mt76_reg_pair * data,int len)79 static int mt76_mmio_rd_rp(struct mt76_dev *dev, u32 base,
80 struct mt76_reg_pair *data, int len)
81 {
82 while (len > 0) {
83 data->value = mt76_mmio_rr(dev, data->reg);
84 data++;
85 len--;
86 }
87
88 return 0;
89 }
90
mt76_set_irq_mask(struct mt76_dev * dev,u32 addr,u32 clear,u32 set)91 void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr,
92 u32 clear, u32 set)
93 {
94 unsigned long flags;
95
96 spin_lock_irqsave(&dev->mmio.irq_lock, flags);
97 dev->mmio.irqmask &= ~clear;
98 dev->mmio.irqmask |= set;
99 if (addr) {
100 if (mtk_wed_device_active(&dev->mmio.wed))
101 mtk_wed_device_irq_set_mask(&dev->mmio.wed,
102 dev->mmio.irqmask);
103 else
104 mt76_mmio_wr(dev, addr, dev->mmio.irqmask);
105 }
106 spin_unlock_irqrestore(&dev->mmio.irq_lock, flags);
107 }
108 EXPORT_SYMBOL_GPL(mt76_set_irq_mask);
109
mt76_mmio_init(struct mt76_dev * dev,void __iomem * regs)110 void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs)
111 {
112 static const struct mt76_bus_ops mt76_mmio_ops = {
113 .rr = mt76_mmio_rr,
114 .rmw = mt76_mmio_rmw,
115 .wr = mt76_mmio_wr,
116 .write_copy = mt76_mmio_write_copy,
117 .read_copy = mt76_mmio_read_copy,
118 .wr_rp = mt76_mmio_wr_rp,
119 .rd_rp = mt76_mmio_rd_rp,
120 .type = MT76_BUS_MMIO,
121 };
122
123 dev->bus = &mt76_mmio_ops;
124 dev->mmio.regs = regs;
125
126 spin_lock_init(&dev->mmio.irq_lock);
127 }
128 EXPORT_SYMBOL_GPL(mt76_mmio_init);
129