Michał Żygowski | 72f06ca | 2020-04-13 21:42:24 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 2 | |
| 3 | #include <arch/io.h> |
| 4 | #include <superio/smsc/sch5545/sch5545.h> |
| 5 | #include <superio/smsc/sch5545/sch5545_emi.h> |
| 6 | |
Michał Żygowski | 7e8b597 | 2022-02-20 23:27:18 +0100 | [diff] [blame] | 7 | #include <baseboard/sch5545_ec.h> |
Michał Żygowski | 72f06ca | 2020-04-13 21:42:24 +0200 | [diff] [blame] | 8 | |
| 9 | static uint16_t emi_bar; |
| 10 | |
| 11 | static const struct ec_val_reg ec_gpio_init_table[] = { |
| 12 | /* |
| 13 | * Probably some early GPIO initialization, setting GPIO functions. |
| 14 | * The LSBs in third column match the GPIO config registers offsets for |
| 15 | * non-default GPIOs. |
| 16 | */ |
| 17 | { EC_GPIO_PP | EC_GPIO_FUNC1, 0x08cc }, /* GP063 (def) / KBDRST# */ |
| 18 | { EC_GPIO_PP | EC_GPIO_FUNC1, 0x08d0 }, /* GP064 (def) / A20M */ |
| 19 | { EC_GPIO_PP | EC_GPIO_FUNC1, 0x089c }, /* GP047 / TXD1 (def) */ |
| 20 | { EC_GPIO_PP | EC_GPIO_FUNC1, 0x0878 }, /* GP036 (def) / SMBCLK1 */ |
| 21 | { EC_GPIO_PP | EC_GPIO_FUNC1, 0x0880 }, /* GP040 (def) / SMBDAT1 */ |
| 22 | { EC_GPIO_OD | EC_GPIO_FUNC1, 0x0884 }, /* GP041 (def) / IO_PME# */ |
| 23 | { EC_GPIO_PP | EC_GPIO_FUNC1, 0x08e4 }, /* GP071 (def) / IO_SMI# */ |
| 24 | { EC_GPIO_PP | EC_GPIO_FUNC1, 0x08e0 }, /* GP070 (def) / SPEAKER */ |
| 25 | { EC_GPIO_PP | EC_GPIO_FUNC1, 0x0848 }, /* GP022 (def) / PWM1 */ |
| 26 | { EC_GPIO_PP | EC_GPIO_FUNC1, 0x084c }, /* GP023 (def) / PWM2 */ |
| 27 | { EC_GPIO_PP | EC_GPIO_FUNC1, 0x0850 }, /* GP024 (def) / PWM3 */ |
| 28 | { EC_GPIO_PP | EC_GPIO_FUNC1, 0x083c }, /* GP017 / TACH1 (def) */ |
| 29 | { EC_GPIO_PP | EC_GPIO_FUNC1, 0x0840 }, /* GP020 / TACH2 (def) */ |
| 30 | { EC_GPIO_PP | EC_GPIO_FUNC1, 0x0844 }, /* GP021 / TACH3 (def) */ |
| 31 | { EC_GPIO_PP | EC_GPIO_FUNC1, 0x0814 }, /* GP005 (def) / PECI_REQ# */ |
| 32 | }; |
| 33 | |
| 34 | static const struct ec_val_reg ec_hwm_early_init_table[] = { |
| 35 | /* Probably some early hardware monitor initialization */ |
| 36 | { 0xff, 0x0005 }, |
| 37 | { 0x30, 0x00f0 }, |
| 38 | { 0x10, 0x00f8 }, |
| 39 | { 0x00, 0x00f9 }, |
| 40 | { 0x00, 0x00fa }, |
| 41 | { 0x00, 0x00fb }, |
| 42 | { 0x00, 0x00ea }, |
| 43 | { 0x00, 0x00eb }, |
| 44 | { 0x7c, 0x00ef }, |
| 45 | { 0x03, 0x006e }, |
| 46 | { 0x51, 0x02d0 }, |
| 47 | { 0x01, 0x02d2 }, |
| 48 | { 0x12, 0x059a }, |
| 49 | { 0x11, 0x059e }, |
| 50 | { 0x14, 0x05a2 }, |
| 51 | { 0x55, 0x05a3 }, |
| 52 | { 0x01, 0x02db }, |
| 53 | { 0x01, 0x0040 }, |
| 54 | }; |
| 55 | |
| 56 | static void ec_read_write_reg_timeout(uint16_t ldn, uint8_t *val, uint16_t reg, |
| 57 | uint8_t rw_bit) |
| 58 | { |
| 59 | uint16_t timeout = 0; |
| 60 | rw_bit &= 1; |
| 61 | sch5545_emi_ec2h_mailbox_clear(); |
| 62 | sch5545_emi_ec_write16(0x8000, (ldn << 1) | 0x100 | rw_bit); |
| 63 | |
| 64 | sch5545_emi_set_ec_addr(0x8004); |
| 65 | |
| 66 | if (rw_bit) |
| 67 | outb(*val, emi_bar + SCH5545_EMI_EC_DATA); |
| 68 | |
| 69 | outb(reg & 0xff, emi_bar + SCH5545_EMI_EC_DATA + 2); |
| 70 | outb((reg >> 8) & 0xff, emi_bar + SCH5545_EMI_EC_DATA + 3); |
| 71 | sch5545_emi_h2ec_mbox_write(1); |
| 72 | |
| 73 | do { |
| 74 | timeout++; |
| 75 | if ((sch5545_emi_ec2h_mbox_read() & 1) != 0) |
| 76 | break; |
| 77 | } while (timeout < 0xfff); |
| 78 | |
| 79 | sch5545_emi_set_int_src(0x11); |
| 80 | sch5545_emi_h2ec_mbox_write(0xc0); |
| 81 | |
| 82 | if (!rw_bit) |
| 83 | *val = inb(emi_bar + SCH5545_EMI_EC_DATA); |
| 84 | } |
| 85 | |
| 86 | static void ec_init_gpios(void) |
| 87 | { |
| 88 | unsigned int i; |
| 89 | uint8_t val; |
| 90 | |
| 91 | for (i = 0; i < ARRAY_SIZE(ec_gpio_init_table); i++) { |
| 92 | val = ec_gpio_init_table[i].val; |
| 93 | ec_read_write_reg_timeout(EC_GPIO_LDN, &val, ec_gpio_init_table[i].reg, |
| 94 | WRITE_OP); |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | static void ec_early_hwm_init(void) |
| 99 | { |
| 100 | unsigned int i; |
| 101 | uint8_t val; |
| 102 | |
| 103 | for (i = 0; i < ARRAY_SIZE(ec_hwm_early_init_table); i++) { |
| 104 | val = ec_hwm_early_init_table[i].val; |
| 105 | ec_read_write_reg_timeout(EC_HWM_LDN, &val, ec_hwm_early_init_table[i].reg, |
| 106 | WRITE_OP); |
| 107 | } |
| 108 | } |
| 109 | |
| 110 | void sch5545_ec_early_init(void) |
| 111 | { |
| 112 | emi_bar = sch5545_read_emi_bar(0x2e); |
| 113 | |
| 114 | ec_init_gpios(); |
| 115 | ec_early_hwm_init(); |
| 116 | } |