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
;
72 * Figure out the actual inb/inw/inl/etc routine to use based
73 * upon the register size.
75 switch (io
->regsize
) {
77 io
->inputb
= port_inb
;
78 io
->outputb
= port_outb
;
81 io
->inputb
= port_inw
;
82 io
->outputb
= port_outw
;
85 io
->inputb
= port_inl
;
86 io
->outputb
= port_outl
;
89 dev_warn(io
->dev
, "Invalid register size: %d\n",
95 * Some BIOSes reserve disjoint I/O regions in their ACPI
96 * tables. This causes problems when trying to register the
97 * entire I/O region. Therefore we must register each I/O
100 for (idx
= 0; idx
< io
->io_size
; idx
++) {
101 if (request_region(addr
+ idx
* io
->regspacing
,
102 io
->regsize
, SI_DEVICE_NAME
) == NULL
) {
103 /* Undo allocations */
105 release_region(addr
+ idx
* io
->regspacing
,
111 io
->io_cleanup
= port_cleanup
;