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 | |
10 | static u32 mt76_mmio_rr(struct mt76_dev *dev, u32 offset) |
11 | { |
12 | u32 val; |
13 | |
14 | val = readl(addr: dev->mmio.regs + offset); |
15 | trace_reg_rr(dev, reg: offset, val); |
16 | |
17 | return val; |
18 | } |
19 | |
20 | static void mt76_mmio_wr(struct mt76_dev *dev, u32 offset, u32 val) |
21 | { |
22 | trace_reg_wr(dev, reg: offset, val); |
23 | writel(val, addr: dev->mmio.regs + offset); |
24 | } |
25 | |
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 | |
33 | static void mt76_mmio_write_copy(struct mt76_dev *dev, u32 offset, |
34 | const void *data, int len) |
35 | { |
36 | __iowrite32_copy(to: dev->mmio.regs + offset, from: data, DIV_ROUND_UP(len, 4)); |
37 | } |
38 | |
39 | static void mt76_mmio_read_copy(struct mt76_dev *dev, u32 offset, |
40 | void *data, int len) |
41 | { |
42 | __ioread32_copy(to: data, from: dev->mmio.regs + offset, DIV_ROUND_UP(len, 4)); |
43 | } |
44 | |
45 | static int mt76_mmio_wr_rp(struct mt76_dev *dev, u32 base, |
46 | const struct mt76_reg_pair *data, int len) |
47 | { |
48 | while (len > 0) { |
49 | mt76_mmio_wr(dev, offset: data->reg, val: data->value); |
50 | data++; |
51 | len--; |
52 | } |
53 | |
54 | return 0; |
55 | } |
56 | |
57 | static int mt76_mmio_rd_rp(struct mt76_dev *dev, u32 base, |
58 | struct mt76_reg_pair *data, int len) |
59 | { |
60 | while (len > 0) { |
61 | data->value = mt76_mmio_rr(dev, offset: data->reg); |
62 | data++; |
63 | len--; |
64 | } |
65 | |
66 | return 0; |
67 | } |
68 | |
69 | void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr, |
70 | u32 clear, u32 set) |
71 | { |
72 | unsigned long flags; |
73 | |
74 | spin_lock_irqsave(&dev->mmio.irq_lock, flags); |
75 | dev->mmio.irqmask &= ~clear; |
76 | dev->mmio.irqmask |= set; |
77 | if (addr) { |
78 | if (mtk_wed_device_active(&dev->mmio.wed)) |
79 | mtk_wed_device_irq_set_mask(&dev->mmio.wed, |
80 | dev->mmio.irqmask); |
81 | else |
82 | mt76_mmio_wr(dev, offset: addr, val: dev->mmio.irqmask); |
83 | } |
84 | spin_unlock_irqrestore(lock: &dev->mmio.irq_lock, flags); |
85 | } |
86 | EXPORT_SYMBOL_GPL(mt76_set_irq_mask); |
87 | |
88 | void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs) |
89 | { |
90 | static const struct mt76_bus_ops mt76_mmio_ops = { |
91 | .rr = mt76_mmio_rr, |
92 | .rmw = mt76_mmio_rmw, |
93 | .wr = mt76_mmio_wr, |
94 | .write_copy = mt76_mmio_write_copy, |
95 | .read_copy = mt76_mmio_read_copy, |
96 | .wr_rp = mt76_mmio_wr_rp, |
97 | .rd_rp = mt76_mmio_rd_rp, |
98 | .type = MT76_BUS_MMIO, |
99 | }; |
100 | |
101 | dev->bus = &mt76_mmio_ops; |
102 | dev->mmio.regs = regs; |
103 | |
104 | spin_lock_init(&dev->mmio.irq_lock); |
105 | } |
106 | EXPORT_SYMBOL_GPL(mt76_mmio_init); |
107 | |