xref: /aosp_15_r20/external/flashrom/amd_imc.c (revision 0d6140be3aa665ecc836e8907834fcd3e3b018fc)
1*0d6140beSAndroid Build Coastguard Worker /*
2*0d6140beSAndroid Build Coastguard Worker  * This file is part of the flashrom project.
3*0d6140beSAndroid Build Coastguard Worker  *
4*0d6140beSAndroid Build Coastguard Worker  * Copyright (C) 2013 Rudolf Marek <[email protected]>
5*0d6140beSAndroid Build Coastguard Worker  * Copyright (C) 2013 Stefan Tauner
6*0d6140beSAndroid Build Coastguard Worker  *
7*0d6140beSAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or modify
8*0d6140beSAndroid Build Coastguard Worker  * it under the terms of the GNU General Public License as published by
9*0d6140beSAndroid Build Coastguard Worker  * the Free Software Foundation; either version 2 of the License, or
10*0d6140beSAndroid Build Coastguard Worker  * (at your option) any later version.
11*0d6140beSAndroid Build Coastguard Worker  *
12*0d6140beSAndroid Build Coastguard Worker  * This program is distributed in the hope that it will be useful,
13*0d6140beSAndroid Build Coastguard Worker  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14*0d6140beSAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*0d6140beSAndroid Build Coastguard Worker  * GNU General Public License for more details.
16*0d6140beSAndroid Build Coastguard Worker  */
17*0d6140beSAndroid Build Coastguard Worker 
18*0d6140beSAndroid Build Coastguard Worker #include "flash.h"
19*0d6140beSAndroid Build Coastguard Worker #include "programmer.h"
20*0d6140beSAndroid Build Coastguard Worker #include "hwaccess_x86_io.h"
21*0d6140beSAndroid Build Coastguard Worker #include "spi.h"
22*0d6140beSAndroid Build Coastguard Worker #include "platform/pci.h"
23*0d6140beSAndroid Build Coastguard Worker 
24*0d6140beSAndroid Build Coastguard Worker /* same as serverengines */
enter_conf_mode_ec(uint16_t port)25*0d6140beSAndroid Build Coastguard Worker static void enter_conf_mode_ec(uint16_t port)
26*0d6140beSAndroid Build Coastguard Worker {
27*0d6140beSAndroid Build Coastguard Worker 	OUTB(0x5a, port);
28*0d6140beSAndroid Build Coastguard Worker }
29*0d6140beSAndroid Build Coastguard Worker 
exit_conf_mode_ec(uint16_t port)30*0d6140beSAndroid Build Coastguard Worker static void exit_conf_mode_ec(uint16_t port)
31*0d6140beSAndroid Build Coastguard Worker {
32*0d6140beSAndroid Build Coastguard Worker 	OUTB(0xa5, port);
33*0d6140beSAndroid Build Coastguard Worker }
34*0d6140beSAndroid Build Coastguard Worker 
get_sio_port(struct pci_dev * dev)35*0d6140beSAndroid Build Coastguard Worker static uint16_t get_sio_port(struct pci_dev *dev)
36*0d6140beSAndroid Build Coastguard Worker {
37*0d6140beSAndroid Build Coastguard Worker 	uint16_t ec_port;
38*0d6140beSAndroid Build Coastguard Worker 
39*0d6140beSAndroid Build Coastguard Worker 	if (!dev) {
40*0d6140beSAndroid Build Coastguard Worker 		return 0;
41*0d6140beSAndroid Build Coastguard Worker 	}
42*0d6140beSAndroid Build Coastguard Worker 
43*0d6140beSAndroid Build Coastguard Worker 	ec_port = pci_read_word(dev, 0xa4);
44*0d6140beSAndroid Build Coastguard Worker 
45*0d6140beSAndroid Build Coastguard Worker 	/* EcPortActive? */
46*0d6140beSAndroid Build Coastguard Worker 	if (!(ec_port & 0x1))
47*0d6140beSAndroid Build Coastguard Worker 		return 0;
48*0d6140beSAndroid Build Coastguard Worker 
49*0d6140beSAndroid Build Coastguard Worker 	ec_port &= ~0x1;
50*0d6140beSAndroid Build Coastguard Worker 
51*0d6140beSAndroid Build Coastguard Worker 	return ec_port;
52*0d6140beSAndroid Build Coastguard Worker }
53*0d6140beSAndroid Build Coastguard Worker 
54*0d6140beSAndroid Build Coastguard Worker /* Wait for up to 10 ms for a response. */
mbox_wait_ack(uint16_t mbox_port)55*0d6140beSAndroid Build Coastguard Worker static int mbox_wait_ack(uint16_t mbox_port)
56*0d6140beSAndroid Build Coastguard Worker {
57*0d6140beSAndroid Build Coastguard Worker 	int i = 10;
58*0d6140beSAndroid Build Coastguard Worker 	while (sio_read(mbox_port, 0x82) != 0xfa) {
59*0d6140beSAndroid Build Coastguard Worker 		if (--i == 0) {
60*0d6140beSAndroid Build Coastguard Worker 			msg_pwarn("IMC MBOX: Timeout!\n");
61*0d6140beSAndroid Build Coastguard Worker 			return 1;
62*0d6140beSAndroid Build Coastguard Worker 		}
63*0d6140beSAndroid Build Coastguard Worker 		default_delay(1000);
64*0d6140beSAndroid Build Coastguard Worker 	}
65*0d6140beSAndroid Build Coastguard Worker 	return 0;
66*0d6140beSAndroid Build Coastguard Worker }
67*0d6140beSAndroid Build Coastguard Worker 
mbox_get_port(uint16_t sio_port)68*0d6140beSAndroid Build Coastguard Worker static uint16_t mbox_get_port(uint16_t sio_port)
69*0d6140beSAndroid Build Coastguard Worker {
70*0d6140beSAndroid Build Coastguard Worker 	uint16_t mbox_port;
71*0d6140beSAndroid Build Coastguard Worker 
72*0d6140beSAndroid Build Coastguard Worker 	enter_conf_mode_ec(sio_port);
73*0d6140beSAndroid Build Coastguard Worker 
74*0d6140beSAndroid Build Coastguard Worker 	/* Go to LDN 9, mailbox */
75*0d6140beSAndroid Build Coastguard Worker 	sio_write(sio_port, 7, 9);
76*0d6140beSAndroid Build Coastguard Worker 
77*0d6140beSAndroid Build Coastguard Worker 	/* MBOX inactive? */
78*0d6140beSAndroid Build Coastguard Worker 	if ((sio_read(sio_port, 0x30) & 1) == 0) {
79*0d6140beSAndroid Build Coastguard Worker 		exit_conf_mode_ec(sio_port);
80*0d6140beSAndroid Build Coastguard Worker 		return 0;
81*0d6140beSAndroid Build Coastguard Worker 	}
82*0d6140beSAndroid Build Coastguard Worker 
83*0d6140beSAndroid Build Coastguard Worker 	mbox_port = sio_read(sio_port, 0x60) << 8;
84*0d6140beSAndroid Build Coastguard Worker 	mbox_port |= sio_read(sio_port, 0x61);
85*0d6140beSAndroid Build Coastguard Worker 
86*0d6140beSAndroid Build Coastguard Worker 	exit_conf_mode_ec(sio_port);
87*0d6140beSAndroid Build Coastguard Worker 	return mbox_port;
88*0d6140beSAndroid Build Coastguard Worker }
89*0d6140beSAndroid Build Coastguard Worker 
90*0d6140beSAndroid Build Coastguard Worker /* Returns negative values when IMC is inactive, positive values on errors */
imc_send_cmd(struct pci_dev * dev,uint8_t cmd)91*0d6140beSAndroid Build Coastguard Worker static int imc_send_cmd(struct pci_dev *dev, uint8_t cmd)
92*0d6140beSAndroid Build Coastguard Worker {
93*0d6140beSAndroid Build Coastguard Worker 	uint16_t sio_port;
94*0d6140beSAndroid Build Coastguard Worker 	uint16_t mbox_port;
95*0d6140beSAndroid Build Coastguard Worker 
96*0d6140beSAndroid Build Coastguard Worker 	/* IntegratedEcPresent? */
97*0d6140beSAndroid Build Coastguard Worker 	if (!(pci_read_byte(dev, 0x40) & (1 << 7)))
98*0d6140beSAndroid Build Coastguard Worker 		return -1;
99*0d6140beSAndroid Build Coastguard Worker 
100*0d6140beSAndroid Build Coastguard Worker 	sio_port = get_sio_port(dev);
101*0d6140beSAndroid Build Coastguard Worker 	if (!sio_port)
102*0d6140beSAndroid Build Coastguard Worker 		return -1;
103*0d6140beSAndroid Build Coastguard Worker 
104*0d6140beSAndroid Build Coastguard Worker 	msg_pdbg2("IMC SIO is at 0x%x.\n", sio_port);
105*0d6140beSAndroid Build Coastguard Worker 	mbox_port = mbox_get_port(sio_port);
106*0d6140beSAndroid Build Coastguard Worker 	if (!mbox_port)
107*0d6140beSAndroid Build Coastguard Worker 		return -1;
108*0d6140beSAndroid Build Coastguard Worker 	msg_pdbg2("IMC MBOX is at 0x%x.\n", mbox_port);
109*0d6140beSAndroid Build Coastguard Worker 
110*0d6140beSAndroid Build Coastguard Worker 	sio_write(mbox_port, 0x82, 0x0);
111*0d6140beSAndroid Build Coastguard Worker 	sio_write(mbox_port, 0x83, cmd);
112*0d6140beSAndroid Build Coastguard Worker 	sio_write(mbox_port, 0x84, 0x0);
113*0d6140beSAndroid Build Coastguard Worker 	/* trigger transfer 0x96 with subcommand cmd */
114*0d6140beSAndroid Build Coastguard Worker 	sio_write(mbox_port, 0x80, 0x96);
115*0d6140beSAndroid Build Coastguard Worker 
116*0d6140beSAndroid Build Coastguard Worker 	return mbox_wait_ack(mbox_port);
117*0d6140beSAndroid Build Coastguard Worker }
118*0d6140beSAndroid Build Coastguard Worker 
imc_resume(void * data)119*0d6140beSAndroid Build Coastguard Worker static int imc_resume(void *data)
120*0d6140beSAndroid Build Coastguard Worker {
121*0d6140beSAndroid Build Coastguard Worker 	struct pci_dev *dev = data;
122*0d6140beSAndroid Build Coastguard Worker 	int ret = imc_send_cmd(dev, 0xb5);
123*0d6140beSAndroid Build Coastguard Worker 
124*0d6140beSAndroid Build Coastguard Worker 	if (ret != 0)
125*0d6140beSAndroid Build Coastguard Worker 		msg_pinfo("Resuming IMC failed.\n");
126*0d6140beSAndroid Build Coastguard Worker 	else
127*0d6140beSAndroid Build Coastguard Worker 		msg_pdbg2("IMC resumed.\n");
128*0d6140beSAndroid Build Coastguard Worker 	return ret;
129*0d6140beSAndroid Build Coastguard Worker }
130*0d6140beSAndroid Build Coastguard Worker 
amd_imc_shutdown(struct pci_dev * dev)131*0d6140beSAndroid Build Coastguard Worker int amd_imc_shutdown(struct pci_dev *dev)
132*0d6140beSAndroid Build Coastguard Worker {
133*0d6140beSAndroid Build Coastguard Worker 	/* Try to put IMC to sleep */
134*0d6140beSAndroid Build Coastguard Worker 	int ret = imc_send_cmd(dev, 0xb4);
135*0d6140beSAndroid Build Coastguard Worker 
136*0d6140beSAndroid Build Coastguard Worker 	/* No IMC activity detectable, assume we are fine */
137*0d6140beSAndroid Build Coastguard Worker 	if (ret < 0) {
138*0d6140beSAndroid Build Coastguard Worker 		msg_pdbg2("No IMC found.\n");
139*0d6140beSAndroid Build Coastguard Worker 		return 0;
140*0d6140beSAndroid Build Coastguard Worker 	}
141*0d6140beSAndroid Build Coastguard Worker 
142*0d6140beSAndroid Build Coastguard Worker 	if (ret != 0) {
143*0d6140beSAndroid Build Coastguard Worker 		msg_perr("Shutting down IMC failed.\n");
144*0d6140beSAndroid Build Coastguard Worker 		return ret;
145*0d6140beSAndroid Build Coastguard Worker 	}
146*0d6140beSAndroid Build Coastguard Worker 	msg_pdbg2("Shutting down IMC successful.\n");
147*0d6140beSAndroid Build Coastguard Worker 
148*0d6140beSAndroid Build Coastguard Worker 	if (register_shutdown(imc_resume, dev))
149*0d6140beSAndroid Build Coastguard Worker 		return 1;
150*0d6140beSAndroid Build Coastguard Worker 
151*0d6140beSAndroid Build Coastguard Worker 	return ret;
152*0d6140beSAndroid Build Coastguard Worker }
153