/* * intel-ce2700.c * * GPL LICENSE SUMMARY * * Copyright(c) 2015-2019 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * 2200 Mission College Blvd. * Santa Clara, CA 97052 * */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include #include #include #include #include #include #define CE2700_SOC_DEVICE_ID 0x2B80 #define CE2700_PCU_DEVFN PCI_DEVFN(31, 0) #define CE2700_PCU_SPI_BAR_BASE 0x54 #define CE2700_PCU_SPI_BAR_SIZE 0x200 #define IO_CTRL_ENABLE_VAL2STR(_enable) ((_enable) ? "enable" : "disable") static struct intel_spi_boardinfo ce2700_pcu_spi_plat_data = { .type = INTEL_SPI_BYT, }; static struct resource ce2700_pcu_spi_resources[] = { { .flags = IORESOURCE_MEM, }, }; static struct platform_device_info ce2700_pcu_spi = { .name = "intel-spi", .id = -1, .res = ce2700_pcu_spi_resources, .num_res = ARRAY_SIZE(ce2700_pcu_spi_resources), .data = &ce2700_pcu_spi_plat_data, .size_data = sizeof(ce2700_pcu_spi_plat_data), }; static int __init ce2700_register_spi(struct pci_bus *root_bus) { u32 spi_base; struct platform_device *ret; /* Get SPI BAR from PCU PCI device & update resource */ pci_bus_read_config_dword(root_bus, CE2700_PCU_DEVFN, CE2700_PCU_SPI_BAR_BASE, &spi_base); spi_base &= 0xfffffff0; ce2700_pcu_spi_resources[0].start = spi_base; ce2700_pcu_spi_resources[0].end = spi_base + CE2700_PCU_SPI_BAR_SIZE; ret = platform_device_register_full(&ce2700_pcu_spi); if(IS_ERR(ret)) { pr_err("Could not register platform device\n"); return PTR_ERR(ret); } return 0; } static int __init intel_ce_platform_init(void) { struct pci_bus *root_bus; u16 device_id; // Get SOC Device ID from PCI device B0:D0:F0 root_bus = pci_find_bus(0, 0); if (root_bus == NULL) { pr_err("Cannot find PCI root bridge\n"); return -ENODEV; } pci_bus_read_config_word(root_bus, PCI_DEVFN(0,0), PCI_DEVICE_ID, &device_id); switch (device_id) { case CE2700_SOC_DEVICE_ID: return ce2700_register_spi(root_bus); default: pr_err("Unknown SOC DEVID 0x%04x\n", device_id); return -1; } } int intel_ce2700_config_atom_uartctrl(int enable) { IO_CFG0_t io_pad_cnfg0; pr_info("Request controlAtomUart enable=%d\n", enable); /*configure cnfg0 according to input parameter*/ if (enable == 0) { /*Disable UART*/ io_pad_cnfg0.field.GPIOEn = 1; io_pad_cnfg0.field.GPIOCfg = 3; } else { /*Enable UART*/ io_pad_cnfg0.field.GPIOEn = 0; io_pad_cnfg0.field.GPIOCfg = 0; } /*Config Tx*/ if (iosf_mbi_modify(IOSF_GPIONW_PORT, INTEL_CE2700_MEM_WRITE_OPCODE, GPIO_NORTHWEST_REGISTERS_ATOM_UART_TXD_PAD_MSGREGADDR, io_pad_cnfg0.val, PCR0_GPIOEN_MASK | PCR0_GPIOCFG_MASK) < 0) { pr_err("fail to %s Atom (Tm) UART Tx\n", IO_CTRL_ENABLE_VAL2STR(enable)); return IOCNFG_FAIL; } /*Config Rx*/ if (iosf_mbi_modify(IOSF_GPIONW_PORT, INTEL_CE2700_MEM_WRITE_OPCODE, GPIO_NORTHWEST_REGISTERS_ATOM_UART_RXD_PAD_MSGREGADDR, io_pad_cnfg0.val, PCR0_GPIOEN_MASK | PCR0_GPIOCFG_MASK) < 0) { pr_err("fail to %s Atom (Tm) UART Rx\n", IO_CTRL_ENABLE_VAL2STR(enable)); return IOCNFG_FAIL; } return IOCNFG_OK; } #ifdef CONFIG_INTEL_UART_ENABLE_CONTROL int intel_ce2700_read_atom_uartctrl(int *enable) { IO_CFG0_t io_pad_cnfg0; if (enable == NULL) return IOCNFG_FAIL; *enable = 0; if (iosf_mbi_read(IOSF_GPIONW_PORT, INTEL_CE2700_MEM_READ_OPCODE, GPIO_NORTHWEST_REGISTERS_ATOM_UART_TXD_PAD_MSGREGADDR, &io_pad_cnfg0.val)) { pr_err("fail to read Atom (Tm) UART Tx control status\n"); return IOCNFG_FAIL; } if (!((io_pad_cnfg0.field.GPIOEn == 1) && (io_pad_cnfg0.field.GPIOCfg == 3))) { /* Tx is enabled */ *enable |= 1; } if (iosf_mbi_read(IOSF_GPIONW_PORT, INTEL_CE2700_MEM_READ_OPCODE, GPIO_NORTHWEST_REGISTERS_ATOM_UART_RXD_PAD_MSGREGADDR, &io_pad_cnfg0.val)) { pr_err("fail to read Atom (Tm) UART Rx control status\n"); return IOCNFG_FAIL; } if (!((io_pad_cnfg0.field.GPIOEn == 1) && (io_pad_cnfg0.field.GPIOCfg == 3))) { /* Rx is enabled */ *enable |= 1; } return IOCNFG_OK; } #endif device_initcall(intel_ce_platform_init);