xref: /aosp_15_r20/external/coreboot/src/superio/smsc/sch5545/sch5545_emi.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <assert.h>
4 #include <arch/io.h>
5 #include <device/pnp.h>
6 #include <device/pnp_ops.h>
7 #include <superio/conf_mode.h>
8 #include <types.h>
9 
10 #include "sch5545.h"
11 #include "sch5545_emi.h"
12 
13 static uint16_t emi_bar;
14 
15 #ifdef __SIMPLE_DEVICE__
sch5545_enter_conf_state(pnp_devfn_t dev)16 static void sch5545_enter_conf_state(pnp_devfn_t dev)
17 {
18 	unsigned int port = dev >> 8;
19 	outb(0x55, port);
20 }
21 
sch5545_exit_conf_state(pnp_devfn_t dev)22 static void sch5545_exit_conf_state(pnp_devfn_t dev)
23 {
24 	unsigned int port = dev >> 8;
25 	outb(0xaa, port);
26 }
27 #endif
28 
sch5545_read_emi_bar(uint8_t sio_port)29 uint16_t sch5545_read_emi_bar(uint8_t sio_port)
30 {
31 	uint16_t bar;
32 
33 #ifdef __SIMPLE_DEVICE__
34 	pnp_devfn_t lpcif = PNP_DEV(sio_port, SCH5545_LDN_LPC);
35 	sch5545_enter_conf_state(lpcif);
36 #else
37 	struct device *lpcif = dev_find_slot_pnp(sio_port, SCH5545_LDN_LPC);
38 	if (!lpcif)
39 		return 0;
40 	pnp_enter_conf_mode_55(lpcif);
41 #endif
42 	pnp_set_logical_device(lpcif);
43 
44 	bar = pnp_read_config(lpcif, SCH5545_BAR_EM_IF + 2);
45 	bar |= pnp_read_config(lpcif, SCH5545_BAR_EM_IF + 3) << 8;
46 
47 #ifdef __SIMPLE_DEVICE__
48 	sch5545_exit_conf_state(lpcif);
49 #else
50 	pnp_exit_conf_mode_aa(lpcif);
51 #endif
52 	return bar;
53 }
54 
sch5545_emi_init(uint8_t sio_port)55 void sch5545_emi_init(uint8_t sio_port)
56 {
57 	emi_bar = sch5545_read_emi_bar(sio_port);
58 	assert(emi_bar != 0);
59 }
60 
sch5545_emi_ec2h_mailbox_clear(void)61 void sch5545_emi_ec2h_mailbox_clear(void)
62 {
63 	sch5545_emi_ec2h_mbox_write(sch5545_emi_ec2h_mbox_read());
64 }
65 
sch5545_emi_disable_interrupts(void)66 void sch5545_emi_disable_interrupts(void)
67 {
68 	sch5545_emi_set_int_mask(0);
69 }
70 
sch5545_emi_h2ec_mbox_write(uint8_t mbox_message)71 void sch5545_emi_h2ec_mbox_write(uint8_t mbox_message)
72 {
73 	outb(mbox_message, emi_bar + SCH5545_EMI_HOST_TO_EC_MAILBOX);
74 }
75 
sch5545_emi_h2ec_mbox_read(void)76 uint8_t sch5545_emi_h2ec_mbox_read(void)
77 {
78 	return inb(emi_bar + SCH5545_EMI_HOST_TO_EC_MAILBOX);
79 }
80 
sch5545_emi_ec2h_mbox_write(uint8_t mbox_message)81 void sch5545_emi_ec2h_mbox_write(uint8_t mbox_message)
82 {
83 	outb(mbox_message, emi_bar + SCH5545_EMI_EC_TO_HOST_MAILBOX);
84 }
85 
sch5545_emi_ec2h_mbox_read(void)86 uint8_t sch5545_emi_ec2h_mbox_read(void)
87 {
88 	return inb(emi_bar + SCH5545_EMI_EC_TO_HOST_MAILBOX);
89 }
90 
sch5545_emi_set_int_mask(uint16_t mask)91 void sch5545_emi_set_int_mask(uint16_t mask)
92 {
93 	outw(mask, emi_bar + SCH5545_EMI_INT_MASK);
94 }
95 
sch5545_emi_set_int_mask_low(uint8_t mask)96 void sch5545_emi_set_int_mask_low(uint8_t mask)
97 {
98 	outb(mask, emi_bar + SCH5545_EMI_INT_MASK);
99 }
100 
sch5545_emi_set_int_mask_high(uint8_t mask)101 void sch5545_emi_set_int_mask_high(uint8_t mask)
102 {
103 	outb(mask, emi_bar + SCH5545_EMI_INT_MASK + 1);
104 }
105 
sch5545_emi_get_int_mask_low(void)106 uint8_t sch5545_emi_get_int_mask_low(void)
107 {
108 	return inb(emi_bar + SCH5545_EMI_INT_MASK);
109 }
110 
sch5545_emi_get_int_mask_high(void)111 uint8_t sch5545_emi_get_int_mask_high(void)
112 {
113 	return inb(emi_bar + SCH5545_EMI_INT_MASK + 1);
114 }
115 
sch5545_emi_get_int_mask(void)116 uint16_t sch5545_emi_get_int_mask(void)
117 {
118 	return inw(emi_bar + SCH5545_EMI_INT_MASK);
119 }
120 
sch5545_emi_set_int_src_low(uint8_t int_src)121 void sch5545_emi_set_int_src_low(uint8_t int_src)
122 {
123 	outb(int_src, emi_bar + SCH5545_EMI_INT_SOURCE);
124 }
125 
sch5545_emi_set_int_src_high(uint8_t int_src)126 void sch5545_emi_set_int_src_high(uint8_t int_src)
127 {
128 	outb(int_src, emi_bar + SCH5545_EMI_INT_SOURCE + 1);
129 }
130 
sch5545_emi_get_int_src_low(void)131 uint8_t sch5545_emi_get_int_src_low(void)
132 {
133 	return inb(emi_bar + SCH5545_EMI_INT_SOURCE);
134 }
135 
sch5545_emi_get_int_src_high(void)136 uint8_t sch5545_emi_get_int_src_high(void)
137 {
138 	return inb(emi_bar + SCH5545_EMI_INT_SOURCE + 1);
139 }
sch5545_emi_get_int_src(void)140 uint16_t sch5545_emi_get_int_src(void)
141 {
142 	return inw(emi_bar + SCH5545_EMI_INT_SOURCE);
143 }
144 
sch5545_emi_set_int_src(uint16_t int_src)145 void sch5545_emi_set_int_src(uint16_t int_src)
146 {
147 	outw(int_src, emi_bar + SCH5545_EMI_INT_SOURCE);
148 }
149 
sch5545_emi_set_ec_addr(uint16_t addr)150 void sch5545_emi_set_ec_addr(uint16_t addr)
151 {
152 	outw(addr, emi_bar + SCH5545_EMI_EC_ADDR);
153 }
154 
sch5545_emi_read_ec_addr(void)155 uint16_t sch5545_emi_read_ec_addr(void)
156 {
157 	return inw(emi_bar + SCH5545_EMI_EC_ADDR);
158 }
159 
sch5545_emi_ec_write8(uint16_t addr,uint8_t data)160 void sch5545_emi_ec_write8(uint16_t addr, uint8_t data)
161 {
162 	sch5545_emi_set_ec_addr((addr & 0xfffc) | EMI_EC_8BIT_ACCESS);
163 	outb(data, emi_bar + SCH5545_EMI_EC_DATA + (addr & 3));
164 }
165 
sch5545_emi_ec_write16(uint16_t addr,uint16_t data)166 void sch5545_emi_ec_write16(uint16_t addr, uint16_t data)
167 {
168 	sch5545_emi_set_ec_addr((addr & 0xfffc) | EMI_EC_16BIT_ACCESS);
169 	outw(data, emi_bar + SCH5545_EMI_EC_DATA + (addr & 2));
170 }
171 
sch5545_emi_ec_write32(uint16_t addr,uint32_t data)172 void sch5545_emi_ec_write32(uint16_t addr, uint32_t data)
173 {
174 	sch5545_emi_set_ec_addr((addr & 0xfffc) | EMI_EC_32BIT_ACCESS);
175 	outl(data, emi_bar + SCH5545_EMI_EC_DATA);
176 }
177 
sch5545_emi_ec_write32_bulk(uint16_t addr,const uint32_t * buffer,size_t len)178 void sch5545_emi_ec_write32_bulk(uint16_t addr, const uint32_t *buffer, size_t len)
179 {
180 	sch5545_emi_set_ec_addr((addr & 0xfffc) | EMI_EC_32BIT_AUTO_ACCESS);
181 
182 	while (len > 0) {
183 		outl(*(buffer++), emi_bar + SCH5545_EMI_EC_DATA);
184 		len--;
185 	}
186 }
187 
sch5545_emi_ec_read8(uint16_t addr)188 uint8_t sch5545_emi_ec_read8(uint16_t addr)
189 {
190 	sch5545_emi_set_ec_addr((addr & 0xfffc) | EMI_EC_8BIT_ACCESS);
191 	return inb(emi_bar + SCH5545_EMI_EC_DATA + (addr & 3));
192 }
193 
sch5545_emi_ec_read16(uint16_t addr)194 uint16_t sch5545_emi_ec_read16(uint16_t addr)
195 {
196 	sch5545_emi_set_ec_addr((addr & 0xfffc) | EMI_EC_16BIT_ACCESS);
197 	return inw(emi_bar + SCH5545_EMI_EC_DATA + (addr & 2));
198 }
199 
sch5545_emi_ec_read32(uint16_t addr)200 uint32_t sch5545_emi_ec_read32(uint16_t addr)
201 {
202 	sch5545_emi_set_ec_addr((addr & 0xfffc) | EMI_EC_32BIT_ACCESS);
203 	return inb(emi_bar + SCH5545_EMI_EC_DATA);
204 }
205 
sch5545_emi_ec_read32_bulk(uint16_t addr,uint32_t * buffer,size_t len)206 void sch5545_emi_ec_read32_bulk(uint16_t addr, uint32_t *buffer, size_t len)
207 {
208 	sch5545_emi_set_ec_addr((addr & 0xfffc) | EMI_EC_32BIT_AUTO_ACCESS);
209 
210 	while (len > 0) {
211 		*(buffer++) = inl(emi_bar + SCH5545_EMI_EC_DATA);
212 		len--;
213 	}
214 }
215