/ src / superio / common / conf_mode.c
conf_mode.c
  1  /* SPDX-License-Identifier: GPL-2.0-only */
  2  
  3  #include <arch/io.h>
  4  #include <device/device.h>
  5  #include <superio/conf_mode.h>
  6  #include <acpi/acpigen.h>
  7  
  8  /* Common enter/exit implementations */
  9  
 10  void pnp_enter_conf_mode_55(struct device *dev)
 11  {
 12  	outb(0x55, dev->path.pnp.port);
 13  }
 14  
 15  void pnp_enter_conf_mode_6767(struct device *dev)
 16  {
 17  	outb(0x67, dev->path.pnp.port);
 18  	outb(0x67, dev->path.pnp.port);
 19  }
 20  
 21  void pnp_enter_conf_mode_7777(struct device *dev)
 22  {
 23  	outb(0x77, dev->path.pnp.port);
 24  	outb(0x77, dev->path.pnp.port);
 25  }
 26  
 27  void pnp_enter_conf_mode_8787(struct device *dev)
 28  {
 29  	outb(0x87, dev->path.pnp.port);
 30  	outb(0x87, dev->path.pnp.port);
 31  }
 32  
 33  void pnp_enter_conf_mode_a0a0(struct device *dev)
 34  {
 35  	outb(0xa0, dev->path.pnp.port);
 36  	outb(0xa0, dev->path.pnp.port);
 37  }
 38  
 39  void pnp_enter_conf_mode_a5a5(struct device *dev)
 40  {
 41  	outb(0xa5, dev->path.pnp.port);
 42  	outb(0xa5, dev->path.pnp.port);
 43  }
 44  
 45  void pnp_exit_conf_mode_aa(struct device *dev)
 46  {
 47  	outb(0xaa, dev->path.pnp.port);
 48  }
 49  
 50  void pnp_enter_conf_mode_870155aa(struct device *dev)
 51  {
 52  	outb(0x87, dev->path.pnp.port);
 53  	outb(0x01, dev->path.pnp.port);
 54  	outb(0x55, dev->path.pnp.port);
 55  
 56  	if (dev->path.pnp.port == 0x4e)
 57  		outb(0xaa, dev->path.pnp.port);
 58  	else
 59  		outb(0x55, dev->path.pnp.port);
 60  }
 61  
 62  void pnp_exit_conf_mode_0202(struct device *dev)
 63  {
 64  	pnp_write_config(dev, 0x02, (1 << 1));
 65  }
 66  
 67  /* Functions for ACPI */
 68  #if CONFIG(HAVE_ACPI_TABLES)
 69  static void pnp_ssdt_enter_conf_mode_55(struct device *dev, const char *idx, const char *data)
 70  {
 71  	acpigen_write_store();
 72  	acpigen_write_byte(0x55);
 73  	acpigen_emit_namestring(idx);
 74  }
 75  
 76  static void pnp_ssdt_enter_conf_mode_6767(struct device *dev, const char *idx, const char *data)
 77  {
 78  	acpigen_write_store();
 79  	acpigen_write_byte(0x67);
 80  	acpigen_emit_namestring(idx);
 81  
 82  	acpigen_write_store();
 83  	acpigen_write_byte(0x67);
 84  	acpigen_emit_namestring(idx);
 85  }
 86  
 87  static void pnp_ssdt_enter_conf_mode_7777(struct device *dev, const char *idx, const char *data)
 88  {
 89  	acpigen_write_store();
 90  	acpigen_write_byte(0x77);
 91  	acpigen_emit_namestring(idx);
 92  
 93  	acpigen_write_store();
 94  	acpigen_write_byte(0x77);
 95  	acpigen_emit_namestring(idx);
 96  }
 97  
 98  static void pnp_ssdt_enter_conf_mode_8787(struct device *dev, const char *idx, const char *data)
 99  {
100  	acpigen_write_store();
101  	acpigen_write_byte(0x87);
102  	acpigen_emit_namestring(idx);
103  
104  	acpigen_write_store();
105  	acpigen_write_byte(0x87);
106  	acpigen_emit_namestring(idx);
107  }
108  
109  static void pnp_ssdt_enter_conf_mode_a0a0(struct device *dev, const char *idx, const char *data)
110  {
111  	acpigen_write_store();
112  	acpigen_write_byte(0xa0);
113  	acpigen_emit_namestring(idx);
114  
115  	acpigen_write_store();
116  	acpigen_write_byte(0xa0);
117  	acpigen_emit_namestring(idx);
118  }
119  
120  static void pnp_ssdt_enter_conf_mode_a5a5(struct device *dev, const char *idx, const char *data)
121  {
122  	acpigen_write_store();
123  	acpigen_write_byte(0xa5);
124  	acpigen_emit_namestring(idx);
125  
126  	acpigen_write_store();
127  	acpigen_write_byte(0xa5);
128  	acpigen_emit_namestring(idx);
129  }
130  
131  static void pnp_ssdt_enter_conf_mode_870155aa(struct device *dev,
132  					      const char *idx, const char *data)
133  {
134  	acpigen_write_store();
135  	acpigen_write_byte(0x87);
136  	acpigen_emit_namestring(idx);
137  
138  	acpigen_write_store();
139  	acpigen_write_byte(0x01);
140  	acpigen_emit_namestring(idx);
141  
142  	acpigen_write_store();
143  	acpigen_write_byte(0x55);
144  	acpigen_emit_namestring(idx);
145  
146  	acpigen_write_store();
147  	if (dev->path.pnp.port == 0x4e)
148  		acpigen_write_byte(0xaa);
149  	else
150  		acpigen_write_byte(0x55);
151  	acpigen_emit_namestring(idx);
152  }
153  
154  static void pnp_ssdt_exit_conf_mode_aa(struct device *dev, const char *idx, const char *data)
155  {
156  	acpigen_write_store();
157  	acpigen_write_byte(0xaa);
158  	acpigen_emit_namestring(idx);
159  }
160  
161  static void pnp_ssdt_exit_conf_mode_0202(struct device *dev, const char *idx, const char *data)
162  {
163  	acpigen_write_store();
164  	acpigen_write_byte(0x02);
165  	acpigen_emit_namestring(idx);
166  
167  	acpigen_write_store();
168  	acpigen_write_byte(0x02);
169  	acpigen_emit_namestring(data);
170  }
171  #endif
172  
173  const struct pnp_mode_ops pnp_conf_mode_55_aa = {
174  	.enter_conf_mode = pnp_enter_conf_mode_55,
175  	.exit_conf_mode  = pnp_exit_conf_mode_aa,
176  #if CONFIG(HAVE_ACPI_TABLES)
177  	.ssdt_enter_conf_mode = pnp_ssdt_enter_conf_mode_55,
178  	.ssdt_exit_conf_mode = pnp_ssdt_exit_conf_mode_aa,
179  #endif
180  };
181  
182  const struct pnp_mode_ops pnp_conf_mode_6767_aa = {
183  	.enter_conf_mode = pnp_enter_conf_mode_6767,
184  	.exit_conf_mode  = pnp_exit_conf_mode_aa,
185  #if CONFIG(HAVE_ACPI_TABLES)
186  	.ssdt_enter_conf_mode = pnp_ssdt_enter_conf_mode_6767,
187  	.ssdt_exit_conf_mode = pnp_ssdt_exit_conf_mode_aa,
188  #endif
189  };
190  
191  const struct pnp_mode_ops pnp_conf_mode_7777_aa = {
192  	.enter_conf_mode = pnp_enter_conf_mode_7777,
193  	.exit_conf_mode  = pnp_exit_conf_mode_aa,
194  #if CONFIG(HAVE_ACPI_TABLES)
195  	.ssdt_enter_conf_mode = pnp_ssdt_enter_conf_mode_7777,
196  	.ssdt_exit_conf_mode = pnp_ssdt_exit_conf_mode_aa,
197  #endif
198  };
199  
200  const struct pnp_mode_ops pnp_conf_mode_8787_aa = {
201  	.enter_conf_mode = pnp_enter_conf_mode_8787,
202  	.exit_conf_mode  = pnp_exit_conf_mode_aa,
203  #if CONFIG(HAVE_ACPI_TABLES)
204  	.ssdt_enter_conf_mode = pnp_ssdt_enter_conf_mode_8787,
205  	.ssdt_exit_conf_mode = pnp_ssdt_exit_conf_mode_aa,
206  #endif
207  };
208  
209  const struct pnp_mode_ops pnp_conf_mode_a0a0_aa = {
210  	.enter_conf_mode = pnp_enter_conf_mode_a0a0,
211  	.exit_conf_mode  = pnp_exit_conf_mode_aa,
212  #if CONFIG(HAVE_ACPI_TABLES)
213  	.ssdt_enter_conf_mode = pnp_ssdt_enter_conf_mode_a0a0,
214  	.ssdt_exit_conf_mode = pnp_ssdt_exit_conf_mode_aa,
215  #endif
216  };
217  
218  const struct pnp_mode_ops pnp_conf_mode_a5a5_aa = {
219  	.enter_conf_mode = pnp_enter_conf_mode_a5a5,
220  	.exit_conf_mode  = pnp_exit_conf_mode_aa,
221  #if CONFIG(HAVE_ACPI_TABLES)
222  	.ssdt_enter_conf_mode = pnp_ssdt_enter_conf_mode_a5a5,
223  	.ssdt_exit_conf_mode = pnp_ssdt_exit_conf_mode_aa,
224  #endif
225  };
226  
227  const struct pnp_mode_ops pnp_conf_mode_870155_aa = {
228  	.enter_conf_mode = pnp_enter_conf_mode_870155aa,
229  	.exit_conf_mode  = pnp_exit_conf_mode_0202,
230  #if CONFIG(HAVE_ACPI_TABLES)
231  	.ssdt_enter_conf_mode = pnp_ssdt_enter_conf_mode_870155aa,
232  	.ssdt_exit_conf_mode = pnp_ssdt_exit_conf_mode_0202,
233  #endif
234  };