blob: f4c757a0609ba76430aa5219a44dec2e1a2df89e [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>
8#include <device/pci_def.h>
9#include <device/pci_ids.h>
10#include <device/pci_ops.h>
11#include <stdint.h>
12
13#include "pch.h"
14
15int pch_silicon_revision(void)
16{
17 static int pch_revision_id = -1;
18
19 if (pch_revision_id < 0)
20 pch_revision_id = pci_read_config8(PCH_LPC_DEV, PCI_REVISION_ID);
21
22 return pch_revision_id;
23}
24
25int pch_silicon_type(void)
26{
27 static int pch_type = -1;
28
29 if (pch_type < 0)
30 pch_type = pci_read_config8(PCH_LPC_DEV, PCI_DEVICE_ID + 1);
31
32 return pch_type;
33}
34
35int pch_silicon_supported(int type, int rev)
36{
37 int cur_type = pch_silicon_type();
38 int cur_rev = pch_silicon_revision();
39
40 switch (type) {
41 case PCH_TYPE_CPT:
42 /* CougarPoint minimum revision */
43 if (cur_type == PCH_TYPE_CPT && cur_rev >= rev)
44 return 1;
45 /* PantherPoint any revision */
46 if (cur_type == PCH_TYPE_PPT)
47 return 1;
48 break;
49
50 case PCH_TYPE_PPT:
51 /* PantherPoint minimum revision */
52 if (cur_type == PCH_TYPE_PPT && cur_rev >= rev)
53 return 1;
54 break;
55 }
56
57 return 0;
58}
59
60#define IOBP_RETRY 1000
61static inline int iobp_poll(void)
62{
63 unsigned int try = IOBP_RETRY;
64 u32 data;
65
66 while (try--) {
67 data = RCBA32(IOBPS);
68 if ((data & 1) == 0)
69 return 1;
70 udelay(10);
71 }
72
73 printk(BIOS_ERR, "IOBP timeout\n");
74 return 0;
75}
76
77void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue)
78{
79 u32 data;
80
81 /* Set the address */
82 RCBA32(IOBPIRI) = address;
83
84 /* READ OPCODE */
85 if (pch_silicon_supported(PCH_TYPE_CPT, PCH_STEP_B0))
86 RCBA32(IOBPS) = IOBPS_RW_BX;
87 else
88 RCBA32(IOBPS) = IOBPS_READ_AX;
89 if (!iobp_poll())
90 return;
91
92 /* Read IOBP data */
93 data = RCBA32(IOBPD);
94 if (!iobp_poll())
95 return;
96
97 /* Check for successful transaction */
98 if ((RCBA32(IOBPS) & 0x6) != 0) {
99 printk(BIOS_ERR, "IOBP read 0x%08x failed\n", address);
100 return;
101 }
102
103 /* Update the data */
104 data &= andvalue;
105 data |= orvalue;
106
107 /* WRITE OPCODE */
108 if (pch_silicon_supported(PCH_TYPE_CPT, PCH_STEP_B0))
109 RCBA32(IOBPS) = IOBPS_RW_BX;
110 else
111 RCBA32(IOBPS) = IOBPS_WRITE_AX;
112 if (!iobp_poll())
113 return;
114
115 /* Write IOBP data */
116 RCBA32(IOBPD) = data;
117 if (!iobp_poll())
118 return;
119}