blob: 401be7609f6c74f41989cf008d545f24ed9c0242 [file] [log] [blame]
Angel Ponsb4492392021-01-06 01:56:14 +01001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#define __SIMPLE_DEVICE__
4
5#include <console/console.h>
6#include <delay.h>
7#include <device/pci.h>
Angel Ponsb4492392021-01-06 01:56:14 +01008#include <device/pci_ids.h>
9#include <device/pci_ops.h>
10#include <stdint.h>
11
12#include "pch.h"
13
14int pch_silicon_revision(void)
15{
Angel Pons20a95332021-01-06 14:30:19 +010016 static int pch_revision_id = 0;
Angel Ponsb4492392021-01-06 01:56:14 +010017
Angel Pons20a95332021-01-06 14:30:19 +010018 if (!pch_revision_id)
Angel Ponsb4492392021-01-06 01:56:14 +010019 pch_revision_id = pci_read_config8(PCH_LPC_DEV, PCI_REVISION_ID);
20
21 return pch_revision_id;
22}
23
24int pch_silicon_type(void)
25{
Angel Pons20a95332021-01-06 14:30:19 +010026 static int pch_type = 0;
Angel Ponsb4492392021-01-06 01:56:14 +010027
Angel Pons20a95332021-01-06 14:30:19 +010028 if (!pch_type)
Angel Ponsb4492392021-01-06 01:56:14 +010029 pch_type = pci_read_config8(PCH_LPC_DEV, PCI_DEVICE_ID + 1);
30
31 return pch_type;
32}
33
Patrick Rudolphb95ef282023-11-04 11:08:25 +010034bool pch_is_mobile(void)
35{
36 const u16 devids[] = {
37 PCI_DID_INTEL_6_SERIES_MOBILE_SFF, PCI_DID_INTEL_6_SERIES_MOBILE,
38 PCI_DID_INTEL_6_SERIES_UM67, PCI_DID_INTEL_6_SERIES_HM65,
39 PCI_DID_INTEL_6_SERIES_HM67, PCI_DID_INTEL_6_SERIES_QS67,
40 PCI_DID_INTEL_6_SERIES_QM67,
41 PCI_DID_INTEL_7_SERIES_MOBILE, PCI_DID_INTEL_7_SERIES_MOBILE_SFF,
42 PCI_DID_INTEL_7_SERIES_QM77, PCI_DID_INTEL_7_SERIES_QS77,
43 PCI_DID_INTEL_7_SERIES_HM77, PCI_DID_INTEL_7_SERIES_UM77,
44 PCI_DID_INTEL_7_SERIES_HM76, PCI_DID_INTEL_7_SERIES_HM75,
45 PCI_DID_INTEL_7_SERIES_HM70, PCI_DID_INTEL_7_SERIES_NM70
46 };
47 u16 devid = pci_s_read_config16(PCH_LPC_DEV, PCI_DEVICE_ID);
48
49 for (size_t i = 0; i < ARRAY_SIZE(devids); i++)
50 if (devid == devids[i])
51 return true;
52 return false;
53}
54
Angel Ponsb4492392021-01-06 01:56:14 +010055int pch_silicon_supported(int type, int rev)
56{
57 int cur_type = pch_silicon_type();
58 int cur_rev = pch_silicon_revision();
59
60 switch (type) {
61 case PCH_TYPE_CPT:
62 /* CougarPoint minimum revision */
63 if (cur_type == PCH_TYPE_CPT && cur_rev >= rev)
64 return 1;
65 /* PantherPoint any revision */
66 if (cur_type == PCH_TYPE_PPT)
67 return 1;
68 break;
69
70 case PCH_TYPE_PPT:
71 /* PantherPoint minimum revision */
72 if (cur_type == PCH_TYPE_PPT && cur_rev >= rev)
73 return 1;
74 break;
75 }
76
77 return 0;
78}
79
80#define IOBP_RETRY 1000
81static inline int iobp_poll(void)
82{
83 unsigned int try = IOBP_RETRY;
84 u32 data;
85
86 while (try--) {
87 data = RCBA32(IOBPS);
88 if ((data & 1) == 0)
89 return 1;
90 udelay(10);
91 }
92
93 printk(BIOS_ERR, "IOBP timeout\n");
94 return 0;
95}
96
97void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue)
98{
99 u32 data;
100
101 /* Set the address */
102 RCBA32(IOBPIRI) = address;
103
104 /* READ OPCODE */
105 if (pch_silicon_supported(PCH_TYPE_CPT, PCH_STEP_B0))
106 RCBA32(IOBPS) = IOBPS_RW_BX;
107 else
108 RCBA32(IOBPS) = IOBPS_READ_AX;
109 if (!iobp_poll())
110 return;
111
112 /* Read IOBP data */
113 data = RCBA32(IOBPD);
114 if (!iobp_poll())
115 return;
116
117 /* Check for successful transaction */
118 if ((RCBA32(IOBPS) & 0x6) != 0) {
119 printk(BIOS_ERR, "IOBP read 0x%08x failed\n", address);
120 return;
121 }
122
123 /* Update the data */
124 data &= andvalue;
125 data |= orvalue;
126
127 /* WRITE OPCODE */
128 if (pch_silicon_supported(PCH_TYPE_CPT, PCH_STEP_B0))
129 RCBA32(IOBPS) = IOBPS_RW_BX;
130 else
131 RCBA32(IOBPS) = IOBPS_WRITE_AX;
132 if (!iobp_poll())
133 return;
134
135 /* Write IOBP data */
136 RCBA32(IOBPD) = data;
137 if (!iobp_poll())
138 return;
139}