Martin Roth | f18034c | 2022-08-07 15:06:28 -0600 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 2 | |
Eric Biederman | 9b4336c | 2003-07-19 04:28:22 +0000 | [diff] [blame] | 3 | #ifndef DEVICE_PNP_H |
| 4 | #define DEVICE_PNP_H |
| 5 | |
Eric Biederman | 5cd8173 | 2004-03-11 15:01:31 +0000 | [diff] [blame] | 6 | #include <stdint.h> |
| 7 | #include <device/device.h> |
Elyes HAOUAS | 4b683b8 | 2020-09-15 07:45:17 +0200 | [diff] [blame] | 8 | /* When <device/pnp.h> is needed, it supposed to provide <device/pnp_{def,type}.h> */ |
Elyes Haouas | 35c3ae3b | 2022-10-27 12:25:12 +0200 | [diff] [blame] | 9 | #include <device/pnp_def.h> /* IWYU pragma: export */ |
| 10 | #include <device/pnp_type.h> /* IWYU pragma: export */ |
Dave Frodin | 2d3964e | 2015-05-12 06:53:11 -0600 | [diff] [blame] | 11 | #include <arch/io.h> |
Eric Biederman | 9b4336c | 2003-07-19 04:28:22 +0000 | [diff] [blame] | 12 | |
Kyösti Mälkki | 0f63975 | 2019-09-27 12:01:15 +0300 | [diff] [blame] | 13 | #if !ENV_PNP_SIMPLE_DEVICE |
Kyösti Mälkki | ef84401 | 2013-06-25 23:17:43 +0300 | [diff] [blame] | 14 | |
Uwe Hermann | d453dd0 | 2010-10-18 00:00:57 +0000 | [diff] [blame] | 15 | /* Primitive PNP resource manipulation */ |
Elyes HAOUAS | 3d0af85 | 2018-09-19 14:42:02 +0200 | [diff] [blame] | 16 | void pnp_write_config(struct device *dev, u8 reg, u8 value); |
| 17 | u8 pnp_read_config(struct device *dev, u8 reg); |
Angel Pons | bb8d00d | 2021-06-06 19:20:48 +0200 | [diff] [blame] | 18 | void pnp_unset_and_set_config(struct device *dev, u8 reg, u8 unset, u8 set); |
Elyes HAOUAS | 3d0af85 | 2018-09-19 14:42:02 +0200 | [diff] [blame] | 19 | void pnp_set_logical_device(struct device *dev); |
| 20 | void pnp_set_enable(struct device *dev, int enable); |
| 21 | int pnp_read_enable(struct device *dev); |
| 22 | void pnp_set_iobase(struct device *dev, u8 index, u16 iobase); |
| 23 | void pnp_set_irq(struct device *dev, u8 index, u8 irq); |
| 24 | void pnp_set_drq(struct device *dev, u8 index, u8 drq); |
Eric Biederman | 9b4336c | 2003-07-19 04:28:22 +0000 | [diff] [blame] | 25 | |
Kyösti Mälkki | 0f63975 | 2019-09-27 12:01:15 +0300 | [diff] [blame] | 26 | #endif |
Kyösti Mälkki | 7d640e2 | 2019-08-17 18:29:02 +0300 | [diff] [blame] | 27 | |
Eric Biederman | 5cd8173 | 2004-03-11 15:01:31 +0000 | [diff] [blame] | 28 | /* PNP device operations */ |
Elyes HAOUAS | 3d0af85 | 2018-09-19 14:42:02 +0200 | [diff] [blame] | 29 | void pnp_read_resources(struct device *dev); |
| 30 | void pnp_set_resources(struct device *dev); |
| 31 | void pnp_enable_resources(struct device *dev); |
| 32 | void pnp_enable(struct device *dev); |
| 33 | void pnp_alt_enable(struct device *dev); |
Eric Biederman | 9b4336c | 2003-07-19 04:28:22 +0000 | [diff] [blame] | 34 | |
Stefan Reinauer | be7f798 | 2009-03-13 15:42:27 +0000 | [diff] [blame] | 35 | extern struct device_operations pnp_ops; |
Eric Biederman | 9b4336c | 2003-07-19 04:28:22 +0000 | [diff] [blame] | 36 | |
Eric Biederman | 5cd8173 | 2004-03-11 15:01:31 +0000 | [diff] [blame] | 37 | /* PNP helper operations */ |
Eric Biederman | 9b4336c | 2003-07-19 04:28:22 +0000 | [diff] [blame] | 38 | |
Eric Biederman | 5cd8173 | 2004-03-11 15:01:31 +0000 | [diff] [blame] | 39 | struct pnp_info { |
Felix Held | 745e58a | 2018-07-06 19:38:24 +0200 | [diff] [blame] | 40 | struct device_operations *ops; /* LDN-specific ops override */ |
Felix Held | 7b7bc59 | 2019-12-15 13:53:48 +0100 | [diff] [blame] | 41 | #define PNP_SKIP_FUNCTION 0xffff |
Felix Held | 9c6e9c6 | 2019-12-15 13:51:19 +0100 | [diff] [blame] | 42 | u16 function; /* Must be at least 16 bits (virtual LDNs)! */ |
Uwe Hermann | d453dd0 | 2010-10-18 00:00:57 +0000 | [diff] [blame] | 43 | unsigned int flags; |
Michael Niewöhner | 6e016f0 | 2020-12-26 22:20:49 +0100 | [diff] [blame] | 44 | #define PNP_IO0 0x0000001 |
| 45 | #define PNP_IO1 0x0000002 |
| 46 | #define PNP_IO2 0x0000004 |
| 47 | #define PNP_IO3 0x0000008 |
| 48 | #define PNP_IO4 0x0000010 |
| 49 | #define PNP_IRQ0 0x0000020 |
| 50 | #define PNP_IRQ1 0x0000040 |
| 51 | #define PNP_DRQ0 0x0000080 |
| 52 | #define PNP_DRQ1 0x0000100 |
| 53 | #define PNP_EN 0x0000200 |
| 54 | #define PNP_MSC0 0x0000400 |
| 55 | #define PNP_MSC1 0x0000800 |
| 56 | #define PNP_MSC2 0x0001000 |
| 57 | #define PNP_MSC3 0x0002000 |
| 58 | #define PNP_MSC4 0x0004000 |
| 59 | #define PNP_MSC5 0x0008000 |
| 60 | #define PNP_MSC6 0x0010000 |
| 61 | #define PNP_MSC7 0x0020000 |
| 62 | #define PNP_MSC8 0x0040000 |
| 63 | #define PNP_MSC9 0x0080000 |
| 64 | #define PNP_MSCA 0x0100000 |
| 65 | #define PNP_MSCB 0x0200000 |
| 66 | #define PNP_MSCC 0x0400000 |
| 67 | #define PNP_MSCD 0x0800000 |
| 68 | #define PNP_MSCE 0x1000000 |
| 69 | u16 io0, io1, io2, io3, io4; |
Eric Biederman | 5cd8173 | 2004-03-11 15:01:31 +0000 | [diff] [blame] | 70 | }; |
Elyes HAOUAS | 3d0af85 | 2018-09-19 14:42:02 +0200 | [diff] [blame] | 71 | struct resource *pnp_get_resource(struct device *dev, unsigned int index); |
Eric Biederman | 7003ba4 | 2004-10-16 06:20:29 +0000 | [diff] [blame] | 72 | void pnp_enable_devices(struct device *dev, struct device_operations *ops, |
Uwe Hermann | d453dd0 | 2010-10-18 00:00:57 +0000 | [diff] [blame] | 73 | unsigned int functions, struct pnp_info *info); |
Eric Biederman | 9b4336c | 2003-07-19 04:28:22 +0000 | [diff] [blame] | 74 | |
Nico Huber | dd4715b | 2013-06-10 22:08:35 +0200 | [diff] [blame] | 75 | struct pnp_mode_ops { |
Elyes HAOUAS | 3d0af85 | 2018-09-19 14:42:02 +0200 | [diff] [blame] | 76 | void (*enter_conf_mode)(struct device *dev); |
| 77 | void (*exit_conf_mode)(struct device *dev); |
Patrick Rudolph | 7db16dd | 2019-12-10 13:15:42 +0100 | [diff] [blame] | 78 | #if CONFIG(HAVE_ACPI_TABLES) |
| 79 | /* |
| 80 | * Generates ASL code to enter/exit config mode. |
| 81 | * |
| 82 | * @param idx The ACPI name of the SuperIO index port register. eg. 'INDX'. |
| 83 | * @param data The ACPI name of the SuperIO data port register. eg. 'DATA'. |
| 84 | */ |
| 85 | void (*ssdt_enter_conf_mode)(struct device *dev, const char *idx, const char *data); |
| 86 | void (*ssdt_exit_conf_mode)(struct device *dev, const char *idx, const char *data); |
| 87 | #endif |
Nico Huber | dd4715b | 2013-06-10 22:08:35 +0200 | [diff] [blame] | 88 | }; |
Elyes HAOUAS | 3d0af85 | 2018-09-19 14:42:02 +0200 | [diff] [blame] | 89 | void pnp_enter_conf_mode(struct device *dev); |
| 90 | void pnp_exit_conf_mode(struct device *dev); |
Patrick Rudolph | 7db16dd | 2019-12-10 13:15:42 +0100 | [diff] [blame] | 91 | #if CONFIG(HAVE_ACPI_TABLES) |
| 92 | /* |
| 93 | * Generates ASL code to enter/exit config mode if supported. |
| 94 | * The calling code has to place this within an ASL MethodOP. |
| 95 | * |
| 96 | * @param idx The ACPI name of the SuperIO index port register. eg. 'INDX'. |
| 97 | * @param data The ACPI name of the SuperIO data port register. eg. 'DATA'. |
| 98 | */ |
| 99 | void pnp_ssdt_enter_conf_mode(struct device *dev, const char *idx, const char *data); |
| 100 | void pnp_ssdt_exit_conf_mode(struct device *dev, const char *idx, const char *data); |
| 101 | #endif |
Dave Frodin | 2d3964e | 2015-05-12 06:53:11 -0600 | [diff] [blame] | 102 | /* PNP indexed I/O operations */ |
| 103 | |
| 104 | /* |
| 105 | * u8 pnp_read_index(u16 port, u8 reg) |
| 106 | * Description: |
| 107 | * This routine reads indexed I/O registers. The reg byte is written |
| 108 | * to the index register at I/O address = port. The result is then |
| 109 | * read from the data register at I/O address = port + 1. |
| 110 | * |
| 111 | * Parameters: |
| 112 | * @param[in] u16 port = The I/O address of the port index register. |
| 113 | * @param[in] u8 reg = The offset within the indexed space. |
| 114 | * @param[out] u8 result = The value read back from the data register. |
| 115 | */ |
| 116 | static inline u8 pnp_read_index(u16 port, u8 reg) |
| 117 | { |
| 118 | outb(reg, port); |
| 119 | return inb(port + 1); |
| 120 | } |
| 121 | |
| 122 | /* |
| 123 | * void pnp_write_index(u16 port, u8 reg, u8 value) |
| 124 | * Description: |
| 125 | * This routine writes indexed I/O registers. The reg byte is written |
| 126 | * to the index register at I/O address = port. The value byte is then |
| 127 | * written to the data register at I/O address = port + 1. |
| 128 | * |
| 129 | * Parameters: |
| 130 | * @param[in] u16 port = The address of the port index register. |
| 131 | * @param[in] u8 reg = The offset within the indexed space. |
| 132 | * @param[in] u8 value = The value to be written to the data register. |
| 133 | */ |
| 134 | static inline void pnp_write_index(u16 port, u8 reg, u8 value) |
| 135 | { |
| 136 | outb(reg, port); |
| 137 | outb(value, port + 1); |
| 138 | } |
| 139 | |
Angel Pons | 64a6b6c | 2020-06-05 19:10:03 +0200 | [diff] [blame] | 140 | /* |
| 141 | * void pnp_unset_and_set_index(u16 port, u8 reg, u8 unset, u8 set) |
| 142 | * Description: |
| 143 | * This routine unsets and sets bits from indexed I/O registers. The |
| 144 | * reg byte is written to the index register at I/O address = port. |
| 145 | * The value byte to update is data register at I/O address = port + 1. |
| 146 | * |
| 147 | * Unlike and-then-or style operations, no bitwise negation is necessary |
| 148 | * to specify the bits to unset. Because the bitwise negation implicitly |
| 149 | * promotes operands to int before operating, one may have to explicitly |
| 150 | * downcast the result if the data width is smaller than that of an int. |
| 151 | * Since warnings are errors in coreboot, explicit casting is necessary. |
| 152 | * |
| 153 | * Performing said negation inside this routine alleviates this problem, |
| 154 | * while allowing the compiler to warn if the input parameters overflow. |
| 155 | * Casting outside this function would silence valid compiler warnings. |
| 156 | * |
| 157 | * Parameters: |
| 158 | * @param[in] u16 port = The address of the port index register. |
| 159 | * @param[in] u8 reg = The offset within the indexed space. |
| 160 | * @param[in] u8 unset = Bitmask with ones to the bits to unset from the data register. |
| 161 | * @param[in] u8 set = Bitmask with ones to the bits to set from the data register. |
| 162 | */ |
| 163 | static inline void pnp_unset_and_set_index(u16 port, u8 reg, u8 unset, u8 set) |
| 164 | { |
| 165 | outb(reg, port); |
| 166 | |
| 167 | u8 value = inb(port + 1); |
| 168 | value &= (u8)~unset; |
| 169 | value |= set; |
| 170 | outb(value, port + 1); |
| 171 | } |
| 172 | |
Eric Biederman | 9b4336c | 2003-07-19 04:28:22 +0000 | [diff] [blame] | 173 | #endif /* DEVICE_PNP_H */ |