blob: 7952eb85a7587d086a2caeccabed6255d8e20890 [file] [log] [blame]
Michał Żygowskifba08302020-04-13 20:51:32 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <arch/io.h>
4#include <device/device.h>
5#include <device/pnp.h>
6#include <superio/conf_mode.h>
7#include <console/console.h>
8#include <pc80/keyboard.h>
Michał Żygowskifba08302020-04-13 20:51:32 +02009
10#include "sch5545.h"
11
12int sch5545_get_gpio(uint8_t sio_port, uint8_t gpio)
13{
14 struct device *dev;
15 uint16_t runtime_reg_base;
16 uint8_t gpio_bank, gpio_num;
17
18 gpio_bank = gpio / 10;
19 gpio_num = gpio % 10;
20 /*
21 * GPIOs are divided into banks of 8 GPIOs (kind of). Each group starts
22 * at decimal base, i.e. 8 GPIOs from GPIO000, 8 GPIOs from GPIO010,
23 * etc., up to GPIO071 and GPIO072 which are an exception (only two
24 * gpios in the bank 7).
25 */
26 if (gpio_num > 7)
27 return -1;
28 else if (gpio_bank == 7 && gpio_num > 1)
29 return -1;
30 else if (gpio_bank > 7)
31 return -1;
32
33 dev = dev_find_slot_pnp(sio_port, SCH5545_LDN_LPC);
34
35 if (!dev) {
36 printk(BIOS_ERR, "%s: ERROR: LPC interface LDN not present."
37 "Check the devicetree!\n", __func__);
38 return -1;
39 }
40
41 pnp_enter_conf_mode(dev);
42 pnp_set_logical_device(dev);
43
44 runtime_reg_base = pnp_read_config(dev, SCH5545_BAR_RUNTIME_REG + 2);
45 runtime_reg_base |= pnp_read_config(dev, SCH5545_BAR_RUNTIME_REG + 3) << 8;
46
47 pnp_exit_conf_mode(dev);
48
49 if (runtime_reg_base == 0)
50 return -1;
51
52 outb(gpio_bank * 8 + gpio_num, runtime_reg_base + SCH5545_RR_GPIO_SEL);
53
54 return inb(runtime_reg_base + SCH5545_RR_GPIO_READ) & 1;
55}
56
57static void sch5545_init(struct device *dev)
58{
59 if (!dev->enabled)
60 return;
61
62 switch (dev->path.pnp.device) {
63 case SCH5545_LDN_KBC:
Michał Żygowski5aba2ae2021-11-25 21:49:28 +010064 pnp_enter_conf_mode(dev);
65 pnp_set_logical_device(dev);
66 /* Disable PS/2 clock and data isolation */
67 pnp_unset_and_set_config(dev, 0xf0,
68 SCH5545_KBD_ISOLATION | SCH5545_MOUSE_ISOLATION, 0);
69 pnp_exit_conf_mode(dev);
Michał Żygowskifba08302020-04-13 20:51:32 +020070 pc_keyboard_init(NO_AUX_DEVICE);
71 break;
72 case SCH5545_LDN_LPC:
73 pnp_enter_conf_mode(dev);
74 pnp_set_logical_device(dev);
75 /* Enable SERIRQ */
76 pnp_write_config(dev, 0x24, pnp_read_config(dev, 0x24) | 0x04);
77 pnp_exit_conf_mode(dev);
78 break;
79 }
80}
81
82static void sch5545_set_iobase(struct device *dev, u8 index, u16 iobase)
83{
84 u8 val;
85 struct device *lpc_if;
86 u8 iobase_reg = 0;
87
88 lpc_if = dev_find_slot_pnp(dev->path.pnp.port, SCH5545_LDN_LPC);
89
90 if (!lpc_if) {
91 printk(BIOS_ERR, "ERROR: %s LPC interface LDN not present."
92 "Check the devicetree!\n", dev_path(dev));
93 return;
94 }
95
96 switch (dev->path.pnp.device) {
97 case SCH5545_LDN_EMI:
98 iobase_reg = SCH5545_BAR_EM_IF;
99 break;
100 case SCH5545_LDN_KBC:
101 iobase_reg = SCH5545_BAR_KBC;
102 break;
103 case SCH5545_LDN_UART1:
104 iobase_reg = SCH5545_BAR_UART1;
105 break;
106 case SCH5545_LDN_UART2:
107 iobase_reg = SCH5545_BAR_UART2;
108 break;
109 case SCH5545_LDN_RR:
110 iobase_reg = SCH5545_BAR_RUNTIME_REG;
111 break;
112 case SCH5545_LDN_FDC:
113 iobase_reg = SCH5545_BAR_FLOPPY;
114 break;
115 case SCH5545_LDN_LPC:
116 iobase_reg = SCH5545_BAR_LPC_IF;
117 break;
118 case SCH5545_LDN_PP:
119 iobase_reg = SCH5545_BAR_PARPORT;
120 break;
121 default:
122 return;
123 }
124
125 pnp_set_logical_device(lpc_if);
126
127 /* Flip the bytes in IO base, LSB goes first */
128 pnp_write_config(lpc_if, iobase_reg + 2, iobase & 0xff);
129 pnp_write_config(lpc_if, iobase_reg + 3, (iobase >> 8) & 0xff);
130
131 /* Set valid bit */
132 val = pnp_read_config(lpc_if, iobase_reg + 1);
133 val |= 0x80;
134 pnp_write_config(lpc_if, iobase_reg + 1, val);
135
136 pnp_set_logical_device(dev);
137}
138
139static void sch5545_set_irq(struct device *dev, u8 index, u8 irq)
140{
141 u8 select_bit = 0;
142 struct device *lpc_if;
143
144 /* In case it is not the IRQ, write misc register directly */
145 if (index >= PNP_IDX_MSC0) {
146 pnp_write_config(dev, index, irq);
147 return;
148 }
149
150 lpc_if = dev_find_slot_pnp(dev->path.pnp.port, SCH5545_LDN_LPC);
151
152 if (!lpc_if) {
153 printk(BIOS_ERR, "ERROR: %s LPC interface LDN not present."
154 "Check the devicetree!\n", dev_path(dev));
155 return;
156 }
157
158 pnp_set_logical_device(lpc_if);
159
160 /*
161 * Some LDNs can generate IRQs from two sources, i.e.
162 * - EMI may generate interrupts for Mailbox and INT source register
163 * - KBC may generate separate IRQ for mouse and keyboard,
164 * - RR LDN may generate IRQ for PME and SMI etc.
165 * SELECT bit allows to distinguish IRQ source for single LDN.
166 * Use the standard IRQs for devices.
167 */
168 switch (dev->path.pnp.device) {
169 case SCH5545_LDN_EMI:
170 case SCH5545_LDN_KBC:
171 case SCH5545_LDN_RR:
172 if (index == 0x72)
173 select_bit = 0x80;
174 break;
175 default:
176 break;
177 }
178
179 /*
180 * IRQs are set in a little different manner. Each IRQ number has its
181 * own register which is programmed with LDN number which should use
182 * the IRQ. Ignore the index offset and choose register based on IRQ
183 * number counting from IRQ base.
184 */
185 pnp_write_config(lpc_if, SCH5545_IRQ_BASE + irq, dev->path.pnp.device | select_bit);
186 pnp_set_logical_device(dev);
187}
188
189static void sch5545_set_drq(struct device *dev, u8 index, u8 drq)
190{
191 struct device *lpc_if;
192
193 if (drq == 4) {
194 printk(BIOS_ERR, "ERROR: %s %02x: Trying to set reserved DMA channel 4!\n",
195 dev_path(dev), index);
196 printk(BIOS_ERR, "This configuration is untested. Trying to continue.\n");
197 }
198
199 /* DMA channel is programmed via LPC LDN */
200 lpc_if = dev_find_slot_pnp(dev->path.pnp.port, SCH5545_LDN_LPC);
201
202 if (!lpc_if) {
203 printk(BIOS_ERR, "ERROR: %s LPC interface LDN not present."
204 "Check the devicetree!\n", dev_path(dev));
205 return;
206 }
207
208 pnp_set_logical_device(lpc_if);
209
210 /*
211 * There are 8 configurable DMA channels. DRQs are set in a little
212 * different manner. Each DMA channel has its own 16-bit register which
213 * is programmed with LDN number (in higher byte) which should use the
214 * IRQ. Ignore the index offset and choose register based on IRQ number
215 * counting from IRQ base. Set valid bit (bit 7) additionally.
216 */
217 pnp_write_config(dev, SCH5545_DRQ_BASE + (drq * 2) + 1, dev->path.pnp.device | 0x80);
218
219 pnp_set_logical_device(dev);
220}
221
222static void sch5545_set_resource(struct device *dev, struct resource *resource)
223{
224 if (!(resource->flags & IORESOURCE_ASSIGNED)) {
225 /*
226 * The PNP_MSC super IO registers have the IRQ flag set. If no
227 * value is assigned in the devicetree, the corresponding
228 * PNP_MSC register doesn't get written, which should be printed
229 * as warning and not as error.
230 */
231 if (resource->flags & IORESOURCE_IRQ &&
232 (resource->index != PNP_IDX_IRQ0) &&
233 (resource->index != PNP_IDX_IRQ1))
234 printk(BIOS_WARNING, "WARNING: %s %02lx %s size: "
235 "0x%010llx not assigned\n", dev_path(dev),
236 resource->index, resource_type(resource),
237 resource->size);
238 else
239 printk(BIOS_ERR, "ERROR: %s %02lx %s size: 0x%010llx "
240 "not assigned\n", dev_path(dev), resource->index,
241 resource_type(resource), resource->size);
242 return;
243 }
244
245 /* Now store the resource. */
246 if (resource->flags & IORESOURCE_IO) {
247 sch5545_set_iobase(dev, resource->index, resource->base);
248 } else if (resource->flags & IORESOURCE_DRQ) {
249 sch5545_set_drq(dev, resource->index, resource->base);
250 } else if (resource->flags & IORESOURCE_IRQ) {
251 sch5545_set_irq(dev, resource->index, resource->base);
252 } else {
253 printk(BIOS_ERR, "ERROR: %s %02lx unknown resource type\n",
254 dev_path(dev), resource->index);
255 return;
256 }
257 resource->flags |= IORESOURCE_STORED;
258
259 report_resource_stored(dev, resource, "");
260}
261
262static void sch5545_set_resources(struct device *dev)
263{
264 struct resource *res;
265
266 pnp_enter_conf_mode(dev);
267
268 /* Select the logical device (LDN). */
269 pnp_set_logical_device(dev);
270
271 for (res = dev->resource_list; res; res = res->next)
272 sch5545_set_resource(dev, res);
273
274 pnp_exit_conf_mode(dev);
275}
276
277static struct device_operations ops = {
278 .read_resources = pnp_read_resources,
279 .set_resources = sch5545_set_resources,
280 .enable_resources = pnp_enable_resources,
281 .enable = pnp_alt_enable,
282 .init = sch5545_init,
283 .ops_pnp_mode = &pnp_conf_mode_55_aa,
284};
285
286static struct pnp_info pnp_dev_info[] = {
287 { NULL, SCH5545_LDN_EMI, PNP_IO0 | PNP_IRQ0 | PNP_IRQ1, 0x0ff0 },
288 { NULL, SCH5545_LDN_KBC, PNP_IO0 | PNP_IRQ0 | PNP_IRQ1 | PNP_MSC0 | PNP_MSC1, 0x0fff },
289 { NULL, SCH5545_LDN_UART1, PNP_IO0 | PNP_IRQ0 | PNP_MSC0, 0x0ff8 },
290 { NULL, SCH5545_LDN_UART2, PNP_IO0 | PNP_IRQ0 | PNP_MSC0, 0x0ff8 },
291 { NULL, SCH5545_LDN_RR, PNP_IO0 | PNP_IRQ0 | PNP_IRQ1 | PNP_MSC0, 0x0fc0 },
292 { NULL, SCH5545_LDN_FDC, PNP_IO0 | PNP_IRQ0 | PNP_DRQ0 | PNP_MSC0 | PNP_MSC1 |
293 PNP_MSC2 | PNP_MSC3 | PNP_MSC4 | PNP_MSC5, 0x0ff8, },
294 { NULL, SCH5545_LDN_LPC, PNP_IO0, 0x0ffe },
295 { NULL, SCH5545_LDN_PP, PNP_IO0 | PNP_IRQ0 | PNP_DRQ0 | PNP_MSC0 | PNP_MSC1, 0x0ff8 },
296};
297
298static void enable_dev(struct device *dev)
299{
300 pnp_enable_devices(dev, &ops, ARRAY_SIZE(pnp_dev_info), pnp_dev_info);
301}
302
303struct chip_operations superio_smsc_sch5545_ops = {
304 CHIP_NAME("SMSC SCH5545 Super I/O")
305 .enable_dev = enable_dev,
306};