blob: c7ce408253d4fe836259e0800671e95779d92fa4 [file] [log] [blame]
Simon Glassf3077082014-11-14 18:18:34 -07001/*
2 * From Coreboot
3 * Copyright (C) 2008-2009 coresystems GmbH
4 * Copyright (C) 2012 The Chromium OS Authors.
5 *
6 * SPDX-License-Identifier: GPL-2.0
7 */
8
9#include <common.h>
10#include <asm/io.h>
11#include <asm/pci.h>
12#include <asm/arch/pch.h>
13
14static int pch_revision_id = -1;
15static int pch_type = -1;
16
Simon Glassb3a9e512016-01-17 16:11:52 -070017int pch_silicon_revision(struct udevice *dev)
Simon Glassf3077082014-11-14 18:18:34 -070018{
Simon Glassb3a9e512016-01-17 16:11:52 -070019 u8 val;
Simon Glassf3077082014-11-14 18:18:34 -070020
Simon Glassb3a9e512016-01-17 16:11:52 -070021 if (pch_revision_id < 0) {
22 dm_pci_read_config8(dev, PCI_REVISION_ID, &val);
23 pch_revision_id = val;
24 }
Simon Glassf3077082014-11-14 18:18:34 -070025
Simon Glassf3077082014-11-14 18:18:34 -070026 return pch_revision_id;
27}
28
Simon Glassb3a9e512016-01-17 16:11:52 -070029int pch_silicon_type(struct udevice *dev)
Simon Glassf3077082014-11-14 18:18:34 -070030{
Simon Glassb3a9e512016-01-17 16:11:52 -070031 u8 val;
Simon Glassf3077082014-11-14 18:18:34 -070032
Simon Glassb3a9e512016-01-17 16:11:52 -070033 if (pch_type < 0) {
34 dm_pci_read_config8(dev, PCI_DEVICE_ID + 1, &val);
35 pch_type = val;
36 }
Simon Glassf3077082014-11-14 18:18:34 -070037
Simon Glassf3077082014-11-14 18:18:34 -070038 return pch_type;
39}
40
Simon Glassb3a9e512016-01-17 16:11:52 -070041int pch_silicon_supported(struct udevice *dev, int type, int rev)
Simon Glassf3077082014-11-14 18:18:34 -070042{
Simon Glassb3a9e512016-01-17 16:11:52 -070043 int cur_type = pch_silicon_type(dev);
44 int cur_rev = pch_silicon_revision(dev);
Simon Glassf3077082014-11-14 18:18:34 -070045
46 switch (type) {
47 case PCH_TYPE_CPT:
48 /* CougarPoint minimum revision */
49 if (cur_type == PCH_TYPE_CPT && cur_rev >= rev)
50 return 1;
51 /* PantherPoint any revision */
52 if (cur_type == PCH_TYPE_PPT)
53 return 1;
54 break;
55
56 case PCH_TYPE_PPT:
57 /* PantherPoint minimum revision */
58 if (cur_type == PCH_TYPE_PPT && cur_rev >= rev)
59 return 1;
60 break;
61 }
62
63 return 0;
64}
65
66#define IOBP_RETRY 1000
67static inline int iobp_poll(void)
68{
69 unsigned try = IOBP_RETRY;
70 u32 data;
71
72 while (try--) {
73 data = readl(RCB_REG(IOBPS));
74 if ((data & 1) == 0)
75 return 1;
76 udelay(10);
77 }
78
79 printf("IOBP timeout\n");
80 return 0;
81}
82
Simon Glassb3a9e512016-01-17 16:11:52 -070083void pch_iobp_update(struct udevice *dev, u32 address, u32 andvalue,
84 u32 orvalue)
Simon Glassf3077082014-11-14 18:18:34 -070085{
86 u32 data;
87
88 /* Set the address */
89 writel(address, RCB_REG(IOBPIRI));
90
91 /* READ OPCODE */
Simon Glassb3a9e512016-01-17 16:11:52 -070092 if (pch_silicon_supported(dev, PCH_TYPE_CPT, PCH_STEP_B0))
Simon Glassf3077082014-11-14 18:18:34 -070093 writel(IOBPS_RW_BX, RCB_REG(IOBPS));
94 else
95 writel(IOBPS_READ_AX, RCB_REG(IOBPS));
96 if (!iobp_poll())
97 return;
98
99 /* Read IOBP data */
100 data = readl(RCB_REG(IOBPD));
101 if (!iobp_poll())
102 return;
103
104 /* Check for successful transaction */
105 if ((readl(RCB_REG(IOBPS)) & 0x6) != 0) {
106 printf("IOBP read 0x%08x failed\n", address);
107 return;
108 }
109
110 /* Update the data */
111 data &= andvalue;
112 data |= orvalue;
113
114 /* WRITE OPCODE */
Simon Glassb3a9e512016-01-17 16:11:52 -0700115 if (pch_silicon_supported(dev, PCH_TYPE_CPT, PCH_STEP_B0))
Simon Glassf3077082014-11-14 18:18:34 -0700116 writel(IOBPS_RW_BX, RCB_REG(IOBPS));
117 else
118 writel(IOBPS_WRITE_AX, RCB_REG(IOBPS));
119 if (!iobp_poll())
120 return;
121
122 /* Write IOBP data */
123 writel(data, RCB_REG(IOBPD));
124 if (!iobp_poll())
125 return;
126}