blob: 66a9d42364075d6928af43c68989be5701a12f2b [file] [log] [blame]
Michał Żygowskifba08302020-04-13 20:51:32 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <assert.h>
4#include <arch/io.h>
5#include <device/pnp.h>
Michał Żygowskifba08302020-04-13 20:51:32 +02006#include <device/pnp_ops.h>
7#include <superio/conf_mode.h>
Elyes HAOUAS84477502021-02-12 08:21:07 +01008#include <types.h>
Michał Żygowskifba08302020-04-13 20:51:32 +02009
10#include "sch5545.h"
11#include "sch5545_emi.h"
12
13static uint16_t emi_bar;
14
15#ifdef __SIMPLE_DEVICE__
16static void sch5545_enter_conf_state(pnp_devfn_t dev)
17{
18 unsigned int port = dev >> 8;
19 outb(0x55, port);
20}
21
22static void sch5545_exit_conf_state(pnp_devfn_t dev)
23{
24 unsigned int port = dev >> 8;
25 outb(0xaa, port);
26}
27#endif
28
29uint16_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
55void sch5545_emi_init(uint8_t sio_port)
56{
57 emi_bar = sch5545_read_emi_bar(sio_port);
58 assert(emi_bar != 0);
59}
60
61void sch5545_emi_ec2h_mailbox_clear(void)
62{
63 sch5545_emi_ec2h_mbox_write(sch5545_emi_ec2h_mbox_read());
64}
65
66void sch5545_emi_disable_interrupts(void)
67{
68 sch5545_emi_set_int_mask(0);
69}
70
71void sch5545_emi_h2ec_mbox_write(uint8_t mbox_message)
72{
73 outb(mbox_message, emi_bar + SCH5545_EMI_HOST_TO_EC_MAILBOX);
74}
75
76uint8_t sch5545_emi_h2ec_mbox_read(void)
77{
78 return inb(emi_bar + SCH5545_EMI_HOST_TO_EC_MAILBOX);
79}
80
81void sch5545_emi_ec2h_mbox_write(uint8_t mbox_message)
82{
83 outb(mbox_message, emi_bar + SCH5545_EMI_EC_TO_HOST_MAILBOX);
84}
85
86uint8_t sch5545_emi_ec2h_mbox_read(void)
87{
88 return inb(emi_bar + SCH5545_EMI_EC_TO_HOST_MAILBOX);
89}
90
91void sch5545_emi_set_int_mask(uint16_t mask)
92{
93 outw(mask, emi_bar + SCH5545_EMI_INT_MASK);
94}
95
96void sch5545_emi_set_int_mask_low(uint8_t mask)
97{
98 outb(mask, emi_bar + SCH5545_EMI_INT_MASK);
99}
100
101void sch5545_emi_set_int_mask_high(uint8_t mask)
102{
103 outb(mask, emi_bar + SCH5545_EMI_INT_MASK + 1);
104}
105
106uint8_t sch5545_emi_get_int_mask_low(void)
107{
108 return inb(emi_bar + SCH5545_EMI_INT_MASK);
109}
110
111uint8_t sch5545_emi_get_int_mask_high(void)
112{
113 return inb(emi_bar + SCH5545_EMI_INT_MASK + 1);
114}
115
116uint16_t sch5545_emi_get_int_mask(void)
117{
118 return inw(emi_bar + SCH5545_EMI_INT_MASK);
119}
120
121void sch5545_emi_set_int_src_low(uint8_t int_src)
122{
123 outb(int_src, emi_bar + SCH5545_EMI_INT_SOURCE);
124}
125
126void sch5545_emi_set_int_src_high(uint8_t int_src)
127{
128 outb(int_src, emi_bar + SCH5545_EMI_INT_SOURCE + 1);
129}
130
131uint8_t sch5545_emi_get_int_src_low(void)
132{
133 return inb(emi_bar + SCH5545_EMI_INT_SOURCE);
134}
135
136uint8_t sch5545_emi_get_int_src_high(void)
137{
138 return inb(emi_bar + SCH5545_EMI_INT_SOURCE + 1);
139}
140uint16_t sch5545_emi_get_int_src(void)
141{
142 return inw(emi_bar + SCH5545_EMI_INT_SOURCE);
143}
144
145void sch5545_emi_set_int_src(uint16_t int_src)
146{
147 outw(int_src, emi_bar + SCH5545_EMI_INT_SOURCE);
148}
149
150void sch5545_emi_set_ec_addr(uint16_t addr)
151{
152 outw(addr, emi_bar + SCH5545_EMI_EC_ADDR);
153}
154
155uint16_t sch5545_emi_read_ec_addr(void)
156{
157 return inw(emi_bar + SCH5545_EMI_EC_ADDR);
158}
159
160void 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
166void 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
172void 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
178void 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
188uint8_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
194uint16_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
200uint32_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
206void 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}