/* SPDX-License-Identifier: GPL-2.0-only */ #include #include #include #include #include #include "sch5545.h" #include "sch5545_emi.h" static uint16_t emi_bar; #ifdef __SIMPLE_DEVICE__ static void sch5545_enter_conf_state(pnp_devfn_t dev) { unsigned int port = dev >> 8; outb(0x55, port); } static void sch5545_exit_conf_state(pnp_devfn_t dev) { unsigned int port = dev >> 8; outb(0xaa, port); } #endif uint16_t sch5545_read_emi_bar(uint8_t sio_port) { uint16_t bar; #ifdef __SIMPLE_DEVICE__ pnp_devfn_t lpcif = PNP_DEV(sio_port, SCH5545_LDN_LPC); sch5545_enter_conf_state(lpcif); #else struct device *lpcif = dev_find_slot_pnp(sio_port, SCH5545_LDN_LPC); if (!lpcif) return 0; pnp_enter_conf_mode_55(lpcif); #endif pnp_set_logical_device(lpcif); bar = pnp_read_config(lpcif, SCH5545_BAR_EM_IF + 2); bar |= pnp_read_config(lpcif, SCH5545_BAR_EM_IF + 3) << 8; #ifdef __SIMPLE_DEVICE__ sch5545_exit_conf_state(lpcif); #else pnp_exit_conf_mode_aa(lpcif); #endif return bar; } void sch5545_emi_init(uint8_t sio_port) { emi_bar = sch5545_read_emi_bar(sio_port); assert(emi_bar != 0); } void sch5545_emi_ec2h_mailbox_clear(void) { sch5545_emi_ec2h_mbox_write(sch5545_emi_ec2h_mbox_read()); } void sch5545_emi_disable_interrupts(void) { sch5545_emi_set_int_mask(0); } void sch5545_emi_h2ec_mbox_write(uint8_t mbox_message) { outb(mbox_message, emi_bar + SCH5545_EMI_HOST_TO_EC_MAILBOX); } uint8_t sch5545_emi_h2ec_mbox_read(void) { return inb(emi_bar + SCH5545_EMI_HOST_TO_EC_MAILBOX); } void sch5545_emi_ec2h_mbox_write(uint8_t mbox_message) { outb(mbox_message, emi_bar + SCH5545_EMI_EC_TO_HOST_MAILBOX); } uint8_t sch5545_emi_ec2h_mbox_read(void) { return inb(emi_bar + SCH5545_EMI_EC_TO_HOST_MAILBOX); } void sch5545_emi_set_int_mask(uint16_t mask) { outw(mask, emi_bar + SCH5545_EMI_INT_MASK); } void sch5545_emi_set_int_mask_low(uint8_t mask) { outb(mask, emi_bar + SCH5545_EMI_INT_MASK); } void sch5545_emi_set_int_mask_high(uint8_t mask) { outb(mask, emi_bar + SCH5545_EMI_INT_MASK + 1); } uint8_t sch5545_emi_get_int_mask_low(void) { return inb(emi_bar + SCH5545_EMI_INT_MASK); } uint8_t sch5545_emi_get_int_mask_high(void) { return inb(emi_bar + SCH5545_EMI_INT_MASK + 1); } uint16_t sch5545_emi_get_int_mask(void) { return inw(emi_bar + SCH5545_EMI_INT_MASK); } void sch5545_emi_set_int_src_low(uint8_t int_src) { outb(int_src, emi_bar + SCH5545_EMI_INT_SOURCE); } void sch5545_emi_set_int_src_high(uint8_t int_src) { outb(int_src, emi_bar + SCH5545_EMI_INT_SOURCE + 1); } uint8_t sch5545_emi_get_int_src_low(void) { return inb(emi_bar + SCH5545_EMI_INT_SOURCE); } uint8_t sch5545_emi_get_int_src_high(void) { return inb(emi_bar + SCH5545_EMI_INT_SOURCE + 1); } uint16_t sch5545_emi_get_int_src(void) { return inw(emi_bar + SCH5545_EMI_INT_SOURCE); } void sch5545_emi_set_int_src(uint16_t int_src) { outw(int_src, emi_bar + SCH5545_EMI_INT_SOURCE); } void sch5545_emi_set_ec_addr(uint16_t addr) { outw(addr, emi_bar + SCH5545_EMI_EC_ADDR); } uint16_t sch5545_emi_read_ec_addr(void) { return inw(emi_bar + SCH5545_EMI_EC_ADDR); } void sch5545_emi_ec_write8(uint16_t addr, uint8_t data) { sch5545_emi_set_ec_addr((addr & 0xfffc) | EMI_EC_8BIT_ACCESS); outb(data, emi_bar + SCH5545_EMI_EC_DATA + (addr & 3)); } void sch5545_emi_ec_write16(uint16_t addr, uint16_t data) { sch5545_emi_set_ec_addr((addr & 0xfffc) | EMI_EC_16BIT_ACCESS); outw(data, emi_bar + SCH5545_EMI_EC_DATA + (addr & 2)); } void sch5545_emi_ec_write32(uint16_t addr, uint32_t data) { sch5545_emi_set_ec_addr((addr & 0xfffc) | EMI_EC_32BIT_ACCESS); outl(data, emi_bar + SCH5545_EMI_EC_DATA); } void sch5545_emi_ec_write32_bulk(uint16_t addr, const uint32_t *buffer, size_t len) { sch5545_emi_set_ec_addr((addr & 0xfffc) | EMI_EC_32BIT_AUTO_ACCESS); while (len > 0) { outl(*(buffer++), emi_bar + SCH5545_EMI_EC_DATA); len--; } } uint8_t sch5545_emi_ec_read8(uint16_t addr) { sch5545_emi_set_ec_addr((addr & 0xfffc) | EMI_EC_8BIT_ACCESS); return inb(emi_bar + SCH5545_EMI_EC_DATA + (addr & 3)); } uint16_t sch5545_emi_ec_read16(uint16_t addr) { sch5545_emi_set_ec_addr((addr & 0xfffc) | EMI_EC_16BIT_ACCESS); return inw(emi_bar + SCH5545_EMI_EC_DATA + (addr & 2)); } uint32_t sch5545_emi_ec_read32(uint16_t addr) { sch5545_emi_set_ec_addr((addr & 0xfffc) | EMI_EC_32BIT_ACCESS); return inb(emi_bar + SCH5545_EMI_EC_DATA); } void sch5545_emi_ec_read32_bulk(uint16_t addr, uint32_t *buffer, size_t len) { sch5545_emi_set_ec_addr((addr & 0xfffc) | EMI_EC_32BIT_AUTO_ACCESS); while (len > 0) { *(buffer++) = inl(emi_bar + SCH5545_EMI_EC_DATA); len--; } }