blob: 770a640963bad0dad0b57d937f1160e3283dc5be [file] [log] [blame]
Eric Biederman9b4336c2003-07-19 04:28:22 +00001#ifndef DEVICE_PNP_H
2#define DEVICE_PNP_H
3
Eric Biederman5cd81732004-03-11 15:01:31 +00004#include <stdint.h>
5#include <device/device.h>
Elyes HAOUAS4b683b82020-09-15 07:45:17 +02006/* When <device/pnp.h> is needed, it supposed to provide <device/pnp_{def,type}.h> */
Eric Biederman5cd81732004-03-11 15:01:31 +00007#include <device/pnp_def.h>
Kyösti Mälkki0f639752019-09-27 12:01:15 +03008#include <device/pnp_type.h>
Dave Frodin2d3964e2015-05-12 06:53:11 -06009#include <arch/io.h>
Eric Biederman9b4336c2003-07-19 04:28:22 +000010
Kyösti Mälkki0f639752019-09-27 12:01:15 +030011#if !ENV_PNP_SIMPLE_DEVICE
Kyösti Mälkkief844012013-06-25 23:17:43 +030012
Uwe Hermannd453dd02010-10-18 00:00:57 +000013/* Primitive PNP resource manipulation */
Elyes HAOUAS3d0af852018-09-19 14:42:02 +020014void pnp_write_config(struct device *dev, u8 reg, u8 value);
15u8 pnp_read_config(struct device *dev, u8 reg);
Angel Ponsbb8d00d2021-06-06 19:20:48 +020016void pnp_unset_and_set_config(struct device *dev, u8 reg, u8 unset, u8 set);
Elyes HAOUAS3d0af852018-09-19 14:42:02 +020017void pnp_set_logical_device(struct device *dev);
18void pnp_set_enable(struct device *dev, int enable);
19int pnp_read_enable(struct device *dev);
20void pnp_set_iobase(struct device *dev, u8 index, u16 iobase);
21void pnp_set_irq(struct device *dev, u8 index, u8 irq);
22void pnp_set_drq(struct device *dev, u8 index, u8 drq);
Eric Biederman9b4336c2003-07-19 04:28:22 +000023
Kyösti Mälkki0f639752019-09-27 12:01:15 +030024#endif
Kyösti Mälkki7d640e22019-08-17 18:29:02 +030025
Eric Biederman5cd81732004-03-11 15:01:31 +000026/* PNP device operations */
Elyes HAOUAS3d0af852018-09-19 14:42:02 +020027void pnp_read_resources(struct device *dev);
28void pnp_set_resources(struct device *dev);
29void pnp_enable_resources(struct device *dev);
30void pnp_enable(struct device *dev);
31void pnp_alt_enable(struct device *dev);
Eric Biederman9b4336c2003-07-19 04:28:22 +000032
Stefan Reinauerbe7f7982009-03-13 15:42:27 +000033extern struct device_operations pnp_ops;
Eric Biederman9b4336c2003-07-19 04:28:22 +000034
Eric Biederman5cd81732004-03-11 15:01:31 +000035/* PNP helper operations */
Eric Biederman9b4336c2003-07-19 04:28:22 +000036
Eric Biederman5cd81732004-03-11 15:01:31 +000037struct pnp_info {
Felix Held745e58a2018-07-06 19:38:24 +020038 struct device_operations *ops; /* LDN-specific ops override */
Felix Held7b7bc592019-12-15 13:53:48 +010039#define PNP_SKIP_FUNCTION 0xffff
Felix Held9c6e9c62019-12-15 13:51:19 +010040 u16 function; /* Must be at least 16 bits (virtual LDNs)! */
Uwe Hermannd453dd02010-10-18 00:00:57 +000041 unsigned int flags;
Michael Niewöhner6e016f02020-12-26 22:20:49 +010042#define PNP_IO0 0x0000001
43#define PNP_IO1 0x0000002
44#define PNP_IO2 0x0000004
45#define PNP_IO3 0x0000008
46#define PNP_IO4 0x0000010
47#define PNP_IRQ0 0x0000020
48#define PNP_IRQ1 0x0000040
49#define PNP_DRQ0 0x0000080
50#define PNP_DRQ1 0x0000100
51#define PNP_EN 0x0000200
52#define PNP_MSC0 0x0000400
53#define PNP_MSC1 0x0000800
54#define PNP_MSC2 0x0001000
55#define PNP_MSC3 0x0002000
56#define PNP_MSC4 0x0004000
57#define PNP_MSC5 0x0008000
58#define PNP_MSC6 0x0010000
59#define PNP_MSC7 0x0020000
60#define PNP_MSC8 0x0040000
61#define PNP_MSC9 0x0080000
62#define PNP_MSCA 0x0100000
63#define PNP_MSCB 0x0200000
64#define PNP_MSCC 0x0400000
65#define PNP_MSCD 0x0800000
66#define PNP_MSCE 0x1000000
67 u16 io0, io1, io2, io3, io4;
Eric Biederman5cd81732004-03-11 15:01:31 +000068};
Elyes HAOUAS3d0af852018-09-19 14:42:02 +020069struct resource *pnp_get_resource(struct device *dev, unsigned int index);
Eric Biederman7003ba42004-10-16 06:20:29 +000070void pnp_enable_devices(struct device *dev, struct device_operations *ops,
Uwe Hermannd453dd02010-10-18 00:00:57 +000071 unsigned int functions, struct pnp_info *info);
Eric Biederman9b4336c2003-07-19 04:28:22 +000072
Nico Huberdd4715b2013-06-10 22:08:35 +020073struct pnp_mode_ops {
Elyes HAOUAS3d0af852018-09-19 14:42:02 +020074 void (*enter_conf_mode)(struct device *dev);
75 void (*exit_conf_mode)(struct device *dev);
Patrick Rudolph7db16dd2019-12-10 13:15:42 +010076#if CONFIG(HAVE_ACPI_TABLES)
77 /*
78 * Generates ASL code to enter/exit config mode.
79 *
80 * @param idx The ACPI name of the SuperIO index port register. eg. 'INDX'.
81 * @param data The ACPI name of the SuperIO data port register. eg. 'DATA'.
82 */
83 void (*ssdt_enter_conf_mode)(struct device *dev, const char *idx, const char *data);
84 void (*ssdt_exit_conf_mode)(struct device *dev, const char *idx, const char *data);
85#endif
Nico Huberdd4715b2013-06-10 22:08:35 +020086};
Elyes HAOUAS3d0af852018-09-19 14:42:02 +020087void pnp_enter_conf_mode(struct device *dev);
88void pnp_exit_conf_mode(struct device *dev);
Patrick Rudolph7db16dd2019-12-10 13:15:42 +010089#if CONFIG(HAVE_ACPI_TABLES)
90/*
91 * Generates ASL code to enter/exit config mode if supported.
92 * The calling code has to place this within an ASL MethodOP.
93 *
94 * @param idx The ACPI name of the SuperIO index port register. eg. 'INDX'.
95 * @param data The ACPI name of the SuperIO data port register. eg. 'DATA'.
96 */
97void pnp_ssdt_enter_conf_mode(struct device *dev, const char *idx, const char *data);
98void pnp_ssdt_exit_conf_mode(struct device *dev, const char *idx, const char *data);
99#endif
Dave Frodin2d3964e2015-05-12 06:53:11 -0600100/* PNP indexed I/O operations */
101
102/*
103 * u8 pnp_read_index(u16 port, u8 reg)
104 * Description:
105 * This routine reads indexed I/O registers. The reg byte is written
106 * to the index register at I/O address = port. The result is then
107 * read from the data register at I/O address = port + 1.
108 *
109 * Parameters:
110 * @param[in] u16 port = The I/O address of the port index register.
111 * @param[in] u8 reg = The offset within the indexed space.
112 * @param[out] u8 result = The value read back from the data register.
113 */
114static inline u8 pnp_read_index(u16 port, u8 reg)
115{
116 outb(reg, port);
117 return inb(port + 1);
118}
119
120/*
121 * void pnp_write_index(u16 port, u8 reg, u8 value)
122 * Description:
123 * This routine writes indexed I/O registers. The reg byte is written
124 * to the index register at I/O address = port. The value byte is then
125 * written to the data register at I/O address = port + 1.
126 *
127 * Parameters:
128 * @param[in] u16 port = The address of the port index register.
129 * @param[in] u8 reg = The offset within the indexed space.
130 * @param[in] u8 value = The value to be written to the data register.
131 */
132static inline void pnp_write_index(u16 port, u8 reg, u8 value)
133{
134 outb(reg, port);
135 outb(value, port + 1);
136}
137
Angel Pons64a6b6c2020-06-05 19:10:03 +0200138/*
139 * void pnp_unset_and_set_index(u16 port, u8 reg, u8 unset, u8 set)
140 * Description:
141 * This routine unsets and sets bits from indexed I/O registers. The
142 * reg byte is written to the index register at I/O address = port.
143 * The value byte to update is data register at I/O address = port + 1.
144 *
145 * Unlike and-then-or style operations, no bitwise negation is necessary
146 * to specify the bits to unset. Because the bitwise negation implicitly
147 * promotes operands to int before operating, one may have to explicitly
148 * downcast the result if the data width is smaller than that of an int.
149 * Since warnings are errors in coreboot, explicit casting is necessary.
150 *
151 * Performing said negation inside this routine alleviates this problem,
152 * while allowing the compiler to warn if the input parameters overflow.
153 * Casting outside this function would silence valid compiler warnings.
154 *
155 * Parameters:
156 * @param[in] u16 port = The address of the port index register.
157 * @param[in] u8 reg = The offset within the indexed space.
158 * @param[in] u8 unset = Bitmask with ones to the bits to unset from the data register.
159 * @param[in] u8 set = Bitmask with ones to the bits to set from the data register.
160 */
161static inline void pnp_unset_and_set_index(u16 port, u8 reg, u8 unset, u8 set)
162{
163 outb(reg, port);
164
165 u8 value = inb(port + 1);
166 value &= (u8)~unset;
167 value |= set;
168 outb(value, port + 1);
169}
170
Eric Biederman9b4336c2003-07-19 04:28:22 +0000171#endif /* DEVICE_PNP_H */