1 // SPDX-License-Identifier: GPL-2.0+
6 static unsigned char port_inb(const struct si_sm_io
*io
, unsigned int offset
)
8 unsigned int addr
= io
->addr_data
;
10 return inb(addr
+ (offset
* io
->regspacing
));
13 static void port_outb(const struct si_sm_io
*io
, unsigned int offset
,
16 unsigned int addr
= io
->addr_data
;
18 outb(b
, addr
+ (offset
* io
->regspacing
));
21 static unsigned char port_inw(const struct si_sm_io
*io
, unsigned int offset
)
23 unsigned int addr
= io
->addr_data
;
25 return (inw(addr
+ (offset
* io
->regspacing
)) >> io
->regshift
) & 0xff;
28 static void port_outw(const struct si_sm_io
*io
, unsigned int offset
,
31 unsigned int addr
= io
->addr_data
;
33 outw(b
<< io
->regshift
, addr
+ (offset
* io
->regspacing
));
36 static unsigned char port_inl(const struct si_sm_io
*io
, unsigned int offset
)
38 unsigned int addr
= io
->addr_data
;
40 return (inl(addr
+ (offset
* io
->regspacing
)) >> io
->regshift
) & 0xff;
43 static void port_outl(const struct si_sm_io
*io
, unsigned int offset
,
46 unsigned int addr
= io
->addr_data
;
48 outl(b
<< io
->regshift
, addr
+(offset
* io
->regspacing
));
51 static void port_cleanup(struct si_sm_io
*io
)
53 unsigned int addr
= io
->addr_data
;
57 for (idx
= 0; idx
< io
->io_size
; idx
++)
58 release_region(addr
+ idx
* io
->regspacing
,
63 int ipmi_si_port_setup(struct si_sm_io
*io
)
65 unsigned int addr
= io
->addr_data
;
71 io
->io_cleanup
= port_cleanup
;
74 * Figure out the actual inb/inw/inl/etc routine to use based
75 * upon the register size.
77 switch (io
->regsize
) {
79 io
->inputb
= port_inb
;
80 io
->outputb
= port_outb
;
83 io
->inputb
= port_inw
;
84 io
->outputb
= port_outw
;
87 io
->inputb
= port_inl
;
88 io
->outputb
= port_outl
;
91 dev_warn(io
->dev
, "Invalid register size: %d\n",
97 * Some BIOSes reserve disjoint I/O regions in their ACPI
98 * tables. This causes problems when trying to register the
99 * entire I/O region. Therefore we must register each I/O
102 for (idx
= 0; idx
< io
->io_size
; idx
++) {
103 if (request_region(addr
+ idx
* io
->regspacing
,
104 io
->regsize
, DEVICE_NAME
) == NULL
) {
105 /* Undo allocations */
107 release_region(addr
+ idx
* io
->regspacing
,