1 // SPDX-License-Identifier: GPL-2.0+
6 static unsigned char intf_mem_inb(const struct si_sm_io
*io
,
9 return readb((io
->addr
)+(offset
* io
->regspacing
));
12 static void intf_mem_outb(const struct si_sm_io
*io
, unsigned int offset
,
15 writeb(b
, (io
->addr
)+(offset
* io
->regspacing
));
18 static unsigned char intf_mem_inw(const struct si_sm_io
*io
,
21 return (readw((io
->addr
)+(offset
* io
->regspacing
)) >> io
->regshift
)
25 static void intf_mem_outw(const struct si_sm_io
*io
, unsigned int offset
,
28 writeb(b
<< io
->regshift
, (io
->addr
)+(offset
* io
->regspacing
));
31 static unsigned char intf_mem_inl(const struct si_sm_io
*io
,
34 return (readl((io
->addr
)+(offset
* io
->regspacing
)) >> io
->regshift
)
38 static void intf_mem_outl(const struct si_sm_io
*io
, unsigned int offset
,
41 writel(b
<< io
->regshift
, (io
->addr
)+(offset
* io
->regspacing
));
45 static unsigned char mem_inq(const struct si_sm_io
*io
, unsigned int offset
)
47 return (readq((io
->addr
)+(offset
* io
->regspacing
)) >> io
->regshift
)
51 static void mem_outq(const struct si_sm_io
*io
, unsigned int offset
,
54 writeq((u64
)b
<< io
->regshift
, (io
->addr
)+(offset
* io
->regspacing
));
58 static void mem_region_cleanup(struct si_sm_io
*io
, int num
)
60 unsigned long addr
= io
->addr_data
;
63 for (idx
= 0; idx
< num
; idx
++)
64 release_mem_region(addr
+ idx
* io
->regspacing
,
68 static void mem_cleanup(struct si_sm_io
*io
)
72 mem_region_cleanup(io
, io
->io_size
);
76 int ipmi_si_mem_setup(struct si_sm_io
*io
)
78 unsigned long addr
= io
->addr_data
;
85 * Figure out the actual readb/readw/readl/etc routine to use based
86 * upon the register size.
88 switch (io
->regsize
) {
90 io
->inputb
= intf_mem_inb
;
91 io
->outputb
= intf_mem_outb
;
94 io
->inputb
= intf_mem_inw
;
95 io
->outputb
= intf_mem_outw
;
98 io
->inputb
= intf_mem_inl
;
99 io
->outputb
= intf_mem_outl
;
103 io
->inputb
= mem_inq
;
104 io
->outputb
= mem_outq
;
108 dev_warn(io
->dev
, "Invalid register size: %d\n",
114 * Some BIOSes reserve disjoint memory regions in their ACPI
115 * tables. This causes problems when trying to request the
116 * entire region. Therefore we must request each register
119 for (idx
= 0; idx
< io
->io_size
; idx
++) {
120 if (request_mem_region(addr
+ idx
* io
->regspacing
,
121 io
->regsize
, DEVICE_NAME
) == NULL
) {
122 /* Undo allocations */
123 mem_region_cleanup(io
, idx
);
129 * Calculate the total amount of memory to claim. This is an
130 * unusual looking calculation, but it avoids claiming any
131 * more memory than it has to. It will claim everything
132 * between the first address to the end of the last full
135 mapsize
= ((io
->io_size
* io
->regspacing
)
136 - (io
->regspacing
- io
->regsize
));
137 io
->addr
= ioremap(addr
, mapsize
);
138 if (io
->addr
== NULL
) {
139 mem_region_cleanup(io
, io
->io_size
);
143 io
->io_cleanup
= mem_cleanup
;