blob: 0a3e26f2788cd3bd02d1eb02f3b6f8d9532eec18 [file] [log] [blame]
Angel Pons182dbde2020-04-02 23:49:05 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Arthur Heymans7b9c1392017-04-09 20:40:39 +02002
3#include <console/console.h>
4#include <device/device.h>
5#include <device/pci.h>
6#include <device/pci_ids.h>
Kyösti Mälkkicbf95712020-01-05 08:05:45 +02007#include <option.h>
Arthur Heymans7b9c1392017-04-09 20:40:39 +02008#include <pc80/mc146818rtc.h>
9#include <pc80/isa-dma.h>
10#include <pc80/i8259.h>
11#include <arch/io.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020012#include <device/pci_ops.h>
Arthur Heymans7b9c1392017-04-09 20:40:39 +020013#include <arch/ioapic.h>
Furquan Shaikh76cedd22020-05-02 10:24:23 -070014#include <acpi/acpi.h>
Arthur Heymans7b9c1392017-04-09 20:40:39 +020015#include <cpu/x86/smm.h>
Arthur Heymans98c92572022-11-07 11:39:58 +010016#include <cpu/intel/speedstep.h>
Furquan Shaikh76cedd22020-05-02 10:24:23 -070017#include <acpi/acpigen.h>
Arthur Heymansad501492017-04-12 00:15:39 +020018#include <arch/smp/mpspec.h>
Kyösti Mälkki12b121c2019-08-18 16:33:39 +030019#include "chip.h"
Arthur Heymans349e0852017-04-09 20:48:37 +020020#include "i82801jx.h"
Arthur Heymans7b9c1392017-04-09 20:40:39 +020021#include <southbridge/intel/common/pciehp.h>
Angel Pons490473e2020-06-21 17:10:28 +020022#include <southbridge/intel/common/pmutil.h>
Arthur Heymansa8a9f342017-12-24 08:11:13 +010023#include <southbridge/intel/common/acpi_pirq_gen.h>
Tim Wawrzynczakf62c4942021-02-26 10:30:52 -070024#include <southbridge/intel/common/rcba_pirq.h>
Arthur Heymans7b9c1392017-04-09 20:40:39 +020025
26#define NMI_OFF 0
27
Arthur Heymans349e0852017-04-09 20:48:37 +020028typedef struct southbridge_intel_i82801jx_config config_t;
Arthur Heymans7b9c1392017-04-09 20:40:39 +020029
Arthur Heymans349e0852017-04-09 20:48:37 +020030static void i82801jx_enable_apic(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +020031{
Arthur Heymans7b9c1392017-04-09 20:40:39 +020032 /* Enable IOAPIC. Keep APIC Range Select at zero. */
33 RCBA8(0x31ff) = 0x03;
34 /* We have to read 0x31ff back if bit0 changed. */
35 RCBA8(0x31ff);
36
37 /* Lock maximum redirection entries (MRE), R/WO register. */
Felix Held0d192892024-02-06 16:55:29 +010038 ioapic_lock_max_vectors(IO_APIC_ADDR);
Arthur Heymans7b9c1392017-04-09 20:40:39 +020039
Felix Held0d192892024-02-06 16:55:29 +010040 register_new_ioapic_gsi0(IO_APIC_ADDR);
Arthur Heymans7b9c1392017-04-09 20:40:39 +020041}
42
Arthur Heymans349e0852017-04-09 20:48:37 +020043static void i82801jx_enable_serial_irqs(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +020044{
45 /* Set packet length and toggle silent mode bit for one frame. */
46 pci_write_config8(dev, D31F0_SERIRQ_CNTL,
47 (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
48}
49
50/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
51 * 0x00 - 0000 = Reserved
52 * 0x01 - 0001 = Reserved
53 * 0x02 - 0010 = Reserved
54 * 0x03 - 0011 = IRQ3
55 * 0x04 - 0100 = IRQ4
56 * 0x05 - 0101 = IRQ5
57 * 0x06 - 0110 = IRQ6
58 * 0x07 - 0111 = IRQ7
59 * 0x08 - 1000 = Reserved
60 * 0x09 - 1001 = IRQ9
61 * 0x0A - 1010 = IRQ10
62 * 0x0B - 1011 = IRQ11
63 * 0x0C - 1100 = IRQ12
64 * 0x0D - 1101 = Reserved
65 * 0x0E - 1110 = IRQ14
66 * 0x0F - 1111 = IRQ15
67 * PIRQ[n]_ROUT[7] - PIRQ Routing Control
68 * 0x80 - The PIRQ is not routed.
69 */
70
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +020071static void i82801jx_pirq_init(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +020072{
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +020073 struct device *irq_dev;
Arthur Heymans7b9c1392017-04-09 20:40:39 +020074
Arthur Heymans87af36a2017-04-12 10:53:30 +020075 /* Interrupt 11 is not used by legacy devices and so can always be used
76 * for PCI interrupts. Full legacy IRQ routing is complicated and hard
77 * to get right. Fortunately all modern OS use MSI and so it's not that
78 * big of an issue anyway. Still we have to provide a reasonable
79 * default. Using interrupt 11 for it everywhere is a working default.
80 * ACPI-aware OS can move it to any interrupt and others will just leave
81 * them at default.
82 */
83 const u8 pirq_routing = 11;
Arthur Heymans7b9c1392017-04-09 20:40:39 +020084
Arthur Heymans87af36a2017-04-12 10:53:30 +020085 pci_write_config8(dev, D31F0_PIRQA_ROUT, pirq_routing);
86 pci_write_config8(dev, D31F0_PIRQB_ROUT, pirq_routing);
87 pci_write_config8(dev, D31F0_PIRQC_ROUT, pirq_routing);
88 pci_write_config8(dev, D31F0_PIRQD_ROUT, pirq_routing);
89
90 pci_write_config8(dev, D31F0_PIRQE_ROUT, pirq_routing);
91 pci_write_config8(dev, D31F0_PIRQF_ROUT, pirq_routing);
92 pci_write_config8(dev, D31F0_PIRQG_ROUT, pirq_routing);
93 pci_write_config8(dev, D31F0_PIRQH_ROUT, pirq_routing);
Arthur Heymans7b9c1392017-04-09 20:40:39 +020094
95 /* Eric Biederman once said we should let the OS do this.
96 * I am not so sure anymore he was right.
97 */
98
99 for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
Arthur Heymans87af36a2017-04-12 10:53:30 +0200100 u8 int_pin = 0;
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200101
Fabio Aiutod835da92022-09-30 11:25:28 +0200102 if (!is_enabled_pci(irq_dev))
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200103 continue;
104
105 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
106
Arthur Heymans87af36a2017-04-12 10:53:30 +0200107 if (int_pin == 0)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200108 continue;
109
Arthur Heymans87af36a2017-04-12 10:53:30 +0200110 pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, pirq_routing);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200111 }
112}
113
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200114static void i82801jx_gpi_routing(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200115{
116 /* Get the chip configuration */
117 config_t *config = dev->chip_info;
118 u32 reg32 = 0;
119
120 /* An array would be much nicer here, or some
121 * other method of doing this.
122 */
123 reg32 |= (config->gpi0_routing & 0x03) << 0;
124 reg32 |= (config->gpi1_routing & 0x03) << 2;
125 reg32 |= (config->gpi2_routing & 0x03) << 4;
126 reg32 |= (config->gpi3_routing & 0x03) << 6;
127 reg32 |= (config->gpi4_routing & 0x03) << 8;
128 reg32 |= (config->gpi5_routing & 0x03) << 10;
129 reg32 |= (config->gpi6_routing & 0x03) << 12;
130 reg32 |= (config->gpi7_routing & 0x03) << 14;
131 reg32 |= (config->gpi8_routing & 0x03) << 16;
132 reg32 |= (config->gpi9_routing & 0x03) << 18;
133 reg32 |= (config->gpi10_routing & 0x03) << 20;
134 reg32 |= (config->gpi11_routing & 0x03) << 22;
135 reg32 |= (config->gpi12_routing & 0x03) << 24;
136 reg32 |= (config->gpi13_routing & 0x03) << 26;
137 reg32 |= (config->gpi14_routing & 0x03) << 28;
138 reg32 |= (config->gpi15_routing & 0x03) << 30;
139
140 pci_write_config32(dev, D31F0_GPIO_ROUT, reg32);
141}
142
Arthur Heymans98c92572022-11-07 11:39:58 +0100143bool southbridge_support_c5(void)
144{
145 struct device *lpc_dev = __pci_0_1f_0;
146 struct southbridge_intel_i82801jx_config *config = lpc_dev->chip_info;
Elyes Haouasa7f55af2023-09-09 10:18:03 +0200147 return config->c5_enable;
Arthur Heymans98c92572022-11-07 11:39:58 +0100148}
149
150bool southbridge_support_c6(void)
151{
152 struct device *lpc_dev = __pci_0_1f_0;
153 struct southbridge_intel_i82801jx_config *config = lpc_dev->chip_info;
Elyes Haouasa7f55af2023-09-09 10:18:03 +0200154 return config->c6_enable;
Arthur Heymans98c92572022-11-07 11:39:58 +0100155}
156
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200157static void i82801jx_power_options(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200158{
159 u8 reg8;
160 u16 reg16, pmbase;
161 u32 reg32;
162 const char *state;
163 /* Get the chip configuration */
164 config_t *config = dev->chip_info;
165
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200166 /* BIOS must program... */
Angel Pons2048cb42020-06-08 02:09:33 +0200167 pci_or_config32(dev, 0xac, (1 << 30) | (3 << 8));
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200168
169 /* Which state do we want to goto after g3 (power restored)?
170 * 0 == S0 Full On
171 * 1 == S5 Soft Off
172 *
173 * If the option is not existent (Laptops), use MAINBOARD_POWER_ON.
174 */
Angel Pons88dcb312021-04-26 17:10:28 +0200175 const unsigned int pwr_on = get_uint_option("power_on_after_fail", MAINBOARD_POWER_ON);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200176
177 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
178 reg8 &= 0xfe;
179 switch (pwr_on) {
180 case MAINBOARD_POWER_OFF:
181 reg8 |= 1;
182 state = "off";
183 break;
184 case MAINBOARD_POWER_ON:
185 reg8 &= ~1;
186 state = "on";
187 break;
188 case MAINBOARD_POWER_KEEP:
189 reg8 &= ~1;
190 state = "state keep";
191 break;
192 default:
193 state = "undefined";
194 }
195
196 reg8 |= (3 << 4); /* avoid #S4 assertions */
Elyes HAOUASdc413712021-02-07 20:54:53 +0100197 reg8 &= ~(1 << 3); /* minimum assertion is 1 to 2 RTCCLK */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200198
199 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
200 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
201
202 /* Set up NMI on errors. */
203 reg8 = inb(0x61);
204 reg8 &= 0x0f; /* Higher Nibble must be 0 */
205 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
206 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
207 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
208 outb(reg8, 0x61);
209
210 reg8 = inb(0x74); /* Read from 0x74 as 0x70 is write only. */
Angel Pons88dcb312021-04-26 17:10:28 +0200211 const unsigned int nmi_option = get_uint_option("nmi", NMI_OFF);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200212 if (nmi_option) {
213 printk(BIOS_INFO, "NMI sources enabled.\n");
214 reg8 &= ~(1 << 7); /* Set NMI. */
215 } else {
216 printk(BIOS_INFO, "NMI sources disabled.\n");
Elyes HAOUAS9c5d4632018-04-26 22:21:21 +0200217 reg8 |= (1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200218 }
219 outb(reg8, 0x70);
220
221 /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
222 reg16 = pci_read_config16(dev, D31F0_GEN_PMCON_1);
223 reg16 &= ~(3 << 0); // SMI# rate 1 minute
224 reg16 |= (1 << 2); // CLKRUN_EN - Mobile/Ultra only
225 reg16 |= (1 << 3); // Speedstep Enable - Mobile/Ultra only
226 reg16 |= (1 << 5); // CPUSLP_EN Desktop only
227
228 if (config->c4onc3_enable)
229 reg16 |= (1 << 7);
230
231 // another laptop wants this?
232 // reg16 &= ~(1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
233 reg16 |= (1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
Kyösti Mälkki94464472020-06-13 13:45:42 +0300234 if (CONFIG(DEBUG_PERIODIC_SMI))
235 reg16 |= (3 << 0); // Periodic SMI every 8s
Arthur Heymans98c92572022-11-07 11:39:58 +0100236 if (southbridge_support_c5())
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200237 reg16 |= (1 << 11); /* Enable C5, C6 and PMSYNC# */
238 pci_write_config16(dev, D31F0_GEN_PMCON_1, reg16);
239
240 /* Set exit timings for C5/C6. */
Arthur Heymans98c92572022-11-07 11:39:58 +0100241 if (southbridge_support_c5()) {
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200242 reg8 = pci_read_config8(dev, D31F0_C5_EXIT_TIMING);
243 reg8 &= ~((7 << 3) | (7 << 0));
Arthur Heymans98c92572022-11-07 11:39:58 +0100244 if (southbridge_support_c6())
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200245 reg8 |= (5 << 3) | (3 << 0); /* 38-44us PMSYNC# to STPCLK#,
246 95-102us DPRSTP# to STP_CPU# */
247 else
248 reg8 |= (0 << 3) | (1 << 0); /* 16-17us PMSYNC# to STPCLK#,
249 34-40us DPRSTP# to STP_CPU# */
250 pci_write_config8(dev, D31F0_C5_EXIT_TIMING, reg8);
251 }
252
253 // Set the board's GPI routing.
Arthur Heymans349e0852017-04-09 20:48:37 +0200254 i82801jx_gpi_routing(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200255
256 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
257
258 outl(config->gpe0_en, pmbase + 0x28);
259 outw(config->alt_gp_smi_en, pmbase + 0x38);
260
261 /* Set up power management block and determine sleep mode */
262 reg16 = inw(pmbase + 0x00); /* PM1_STS */
263 outw(reg16, pmbase + 0x00); /* Clear status bits. At least bit11 (power
264 button override) must be cleared or SCI
265 will be constantly fired and OSPM must
266 not know about it (ACPI spec says to
267 ignore the bit). */
268 reg32 = inl(pmbase + 0x04); // PM1_CNT
269 reg32 &= ~(7 << 10); // SLP_TYP
270 outl(reg32, pmbase + 0x04);
271
272 /* Set duty cycle for hardware throttling (defaults to 0x0: 50%). */
273 reg32 = inl(pmbase + 0x10);
274 reg32 &= ~(7 << 5);
275 reg32 |= (config->throttle_duty & 7) << 5;
276 outl(reg32, pmbase + 0x10);
277}
278
Arthur Heymans349e0852017-04-09 20:48:37 +0200279static void i82801jx_rtc_init(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200280{
281 u8 reg8;
282 int rtc_failed;
283
284 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
285 rtc_failed = reg8 & RTC_BATTERY_DEAD;
286 if (rtc_failed) {
287 reg8 &= ~RTC_BATTERY_DEAD;
288 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
289 }
290 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
291
292 cmos_init(rtc_failed);
293}
294
295static void enable_hpet(void)
296{
297 u32 reg32;
298
299 /* Move HPET to default address 0xfed00000 and enable it */
300 reg32 = RCBA32(RCBA_HPTC);
301 reg32 |= (1 << 7); // HPET Address Enable
302 reg32 &= ~(3 << 0);
303 RCBA32(RCBA_HPTC) = reg32;
304}
305
306static void enable_clock_gating(void)
307{
308 u32 reg32;
309
310 /* Enable DMI dynamic clock gating. */
311 RCBA32(RCBA_DMIC) |= 3;
312
313 /* Enable Clock Gating for most devices. */
314 reg32 = RCBA32(RCBA_CG);
315 reg32 |= (1 << 31); /* LPC dynamic clock gating */
316 /* USB UHCI dynamic clock gating: */
317 reg32 |= (1 << 29) | (1 << 28);
318 /* SATA dynamic clock gating [0-3]: */
319 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
320 reg32 |= (1 << 23); /* LAN static clock gating (if LAN disabled) */
321 reg32 |= (1 << 22); /* HD audio dynamic clock gating */
322 reg32 &= ~(1 << 21); /* No HD audio static clock gating */
323 reg32 &= ~(1 << 20); /* No USB EHCI static clock gating */
324 reg32 |= (1 << 19); /* USB EHCI dynamic clock gating */
325 /* More SATA dynamic clock gating [4-5]: */
326 reg32 |= (1 << 18) | (1 << 17);
327 reg32 |= (1 << 16); /* PCI dynamic clock gating */
328 /* PCIe, DMI dynamic clock gating: */
329 reg32 |= (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1);
330 reg32 |= (1 << 0); /* PCIe root port static clock gating */
331 RCBA32(RCBA_CG) = reg32;
332
333 /* Enable SPI dynamic clock gating. */
334 RCBA32(0x38c0) |= 7;
335}
336
Kyösti Mälkki83d6a8a2019-07-12 08:16:53 +0300337static void i82801jx_set_acpi_mode(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200338{
Kyösti Mälkkiad882c32020-06-02 05:05:30 +0300339 if (!acpi_is_wakeup_s3()) {
340 apm_control(APM_CNT_ACPI_DISABLE);
341 } else {
342 apm_control(APM_CNT_ACPI_ENABLE);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200343 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200344}
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200345
346static void lpc_init(struct device *dev)
347{
Elyes HAOUASbfc255a2020-03-07 13:05:14 +0100348 printk(BIOS_DEBUG, "i82801jx: %s\n", __func__);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200349
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200350 /* IO APIC initialization. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200351 i82801jx_enable_apic(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200352
Arthur Heymans349e0852017-04-09 20:48:37 +0200353 i82801jx_enable_serial_irqs(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200354
355 /* Setup the PIRQ. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200356 i82801jx_pirq_init(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200357
358 /* Setup power options. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200359 i82801jx_power_options(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200360
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200361 /* Initialize the real time clock. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200362 i82801jx_rtc_init(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200363
364 /* Initialize ISA DMA. */
365 isa_dma_init();
366
367 /* Initialize the High Precision Event Timers, if present. */
368 enable_hpet();
369
370 /* Initialize Clock Gating */
371 enable_clock_gating();
372
373 setup_i8259();
374
375 /* The OS should do this? */
376 /* Interrupt 9 should be level triggered (SCI) */
377 i8259_configure_irq_trigger(9, 1);
378
Kyösti Mälkki44da9e72019-10-09 12:32:16 +0300379 i82801jx_set_acpi_mode(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200380}
381
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200382static void i82801jx_lpc_read_resources(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200383{
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200384 int i, io_index = 0;
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200385 /*
386 * I/O Resources
387 *
388 * 0x0000 - 0x000f....ISA DMA
389 * 0x0010 - 0x001f....ISA DMA aliases
390 * 0x0020 ~ 0x003d....PIC
391 * 0x002e - 0x002f....Maybe Super I/O
392 * 0x0040 - 0x0043....Timer
393 * 0x004e - 0x004f....Maybe Super I/O
394 * 0x0050 - 0x0053....Timer aliases
395 * 0x0061.............NMI_SC
396 * 0x0070.............NMI_EN (readable in alternative access mode)
397 * 0x0070 - 0x0077....RTC
398 * 0x0080 - 0x008f....ISA DMA
399 * 0x0090 ~ 0x009f....ISA DMA aliases
400 * 0x0092.............Fast A20 and Init
401 * 0x00a0 ~ 0x00bd....PIC
402 * 0x00b2 - 0x00b3....APM
403 * 0x00c0 ~ 0x00de....ISA DMA
404 * 0x00c1 ~ 0x00df....ISA DMA aliases
405 * 0x00f0.............Coprocessor Error
Angel Ponsb21bffa2020-07-03 01:02:28 +0200406 * (0x0400-0x041f)....SMBus (CONFIG_FIXED_SMBUS_IO_BASE, during raminit)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200407 * 0x04d0 - 0x04d1....PIC
408 * 0x0500 - 0x057f....PM (DEFAULT_PMBASE)
409 * 0x0580 - 0x05bf....SB GPIO (DEFAULT_GPIOBASE)
410 * 0x05c0 - 0x05ff....SB GPIO cont. (mobile only)
411 * 0x0cf8 - 0x0cff....PCI
412 * 0x0cf9.............Reset Control
413 */
414
415 struct resource *res;
416
417 /* Get the normal PCI resources of this device. */
418 pci_dev_read_resources(dev);
419
420 /* Add an extra subtractive resource for both memory and I/O. */
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200421 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200422 res->base = 0;
423 res->size = 0x1000;
424 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
425 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
426
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200427 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
428 res->base = 0xff000000;
429 res->size = 0x01000000; /* 16 MB for flash */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200430 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
431 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
432
433 res = new_resource(dev, 3); /* IOAPIC */
434 res->base = IO_APIC_ADDR;
435 res->size = 0x00001000;
436 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200437
438 /* Set IO decode ranges if required.*/
439 for (i = 0; i < 4; i++) {
440 u32 gen_dec;
441 gen_dec = pci_read_config32(dev, 0x84 + 4 * i);
442
443 if ((gen_dec & 0xFFFC) > 0x1000) {
444 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
445 res->base = gen_dec & 0xFFFC;
446 res->size = (gen_dec >> 16) & 0xFC;
447 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
448 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
449 }
450 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200451}
452
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100453static const char *lpc_acpi_name(const struct device *dev)
454{
455 return "LPCB";
456}
457
Furquan Shaikh7536a392020-04-24 21:59:21 -0700458static void southbridge_fill_ssdt(const struct device *device)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200459{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300460 struct device *dev = pcidev_on_root(0x1f, 0);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200461 config_t *chip = dev->chip_info;
462
463 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100464 intel_acpi_gen_def_acpi_pirq(device);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200465}
466
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200467static struct device_operations device_ops = {
Arthur Heymans349e0852017-04-09 20:48:37 +0200468 .read_resources = i82801jx_lpc_read_resources,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200469 .set_resources = pci_dev_set_resources,
470 .enable_resources = pci_dev_enable_resources,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200471 .write_acpi_tables = acpi_write_hpet,
Nico Huber68680dd2020-03-31 17:34:52 +0200472 .acpi_fill_ssdt = southbridge_fill_ssdt,
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100473 .acpi_name = lpc_acpi_name,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200474 .init = lpc_init,
Nico Huber51b75ae2019-03-14 16:02:05 +0100475 .scan_bus = scan_static_bus,
Angel Pons1fc0edd2020-05-31 00:03:28 +0200476 .ops_pci = &pci_dev_ops_pci,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200477};
478
479static const unsigned short pci_device_ids[] = {
Arthur Heymans349e0852017-04-09 20:48:37 +0200480 0x3a10, /* ICH10R Eng. Sample */
481 0x3a14, /* ICH10DO */
482 0x3a16, /* ICH10R */
483 0x3a18, /* ICH10 */
484 0x3a1a, /* ICH10D */
485 0x3a1e, /* ICH10 Eng. Sample */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200486 0
487};
488
Arthur Heymans349e0852017-04-09 20:48:37 +0200489static const struct pci_driver ich10_lpc __pci_driver = {
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200490 .ops = &device_ops,
Felix Singer43b7f412022-03-07 04:34:52 +0100491 .vendor = PCI_VID_INTEL,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200492 .devices = pci_device_ids,
493};