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, SI_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;