xref: /freebsd/sys/contrib/dev/mediatek/mt76/mmio.c (revision 8ba4d145d351db26e07695b8e90697398c5dfec2)
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