1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Host interface (LPC or eSPI) configuration on Nuvoton BMC 4 * Copyright (c) 2022 Nuvoton Technology Corp. 5 */ 6 7#include <dm.h> 8#include <regmap.h> 9#include <syscon.h> 10#include <asm/io.h> 11#include <dm/device_compat.h> 12#include <linux/bitfield.h> 13 14#define SMC_CTL_REG_ADDR 0xc0001001 15#define SMC_CTL_HOSTWAIT 0x80 16 17/* GCR Register Offsets */ 18#define HIFCR 0x50 19#define MFSEL1 0x260 20#define MFSEL4 0x26c 21 22/* ESPI Register offsets */ 23#define ESPICFG 0x4 24#define ESPIHINDP 0x80 25 26/* MFSEL bit fileds */ 27#define MFSEL1_LPCSEL BIT(26) 28#define MFSEL4_ESPISEL BIT(8) 29 30/* ESPICFG bit fileds */ 31#define CHSUPP_MASK GENMASK(27, 24) 32#define IOMODE_MASK GENMASK(9, 8) 33#define IOMODE_SDQ FIELD_PREP(IOMODE_MASK, 3) 34#define MAXFREQ_MASK GENMASK(12, 10) 35#define MAXFREQ_33MHZ FIELD_PREP(MAXFREQ_MASK, 2) 36 37/* ESPIHINDP bit fileds */ 38#define AUTO_SBLD BIT(4) 39#define AUTO_HS1 BIT(8) 40#define AUTO_HS2 BIT(12) 41#define AUTO_HS3 BIT(16) 42 43static int npcm_host_intf_bind(struct udevice *dev) 44{ 45 struct regmap *syscon; 46 void __iomem *base; 47 u32 ch_supp, val; 48 u32 ioaddr; 49 const char *type; 50 int ret; 51 52 syscon = syscon_regmap_lookup_by_phandle(dev, "syscon"); 53 if (IS_ERR(syscon)) { 54 dev_err(dev, "%s: unable to get syscon, dev %s\n", __func__, dev->name); 55 return PTR_ERR(syscon); 56 } 57 58 ioaddr = dev_read_u32_default(dev, "ioaddr", 0); 59 if (ioaddr) 60 regmap_write(syscon, HIFCR, ioaddr); 61 62 type = dev_read_string(dev, "type"); 63 if (!type) 64 return -EINVAL; 65 66 if (!strcmp(type, "espi")) { 67 base = dev_read_addr_ptr(dev); 68 if (!base) 69 return -EINVAL; 70 71 ret = dev_read_u32(dev, "channel-support", &ch_supp); 72 if (ret) 73 return ret; 74 75 /* Select eSPI pins function */ 76 regmap_update_bits(syscon, MFSEL1, MFSEL1_LPCSEL, 0); 77 regmap_update_bits(syscon, MFSEL4, MFSEL4_ESPISEL, MFSEL4_ESPISEL); 78 79 val = AUTO_SBLD | AUTO_HS1 | AUTO_HS2 | AUTO_HS3 | ch_supp; 80 writel(val, base + ESPIHINDP); 81 82 val = readl(base + ESPICFG); 83 val &= ~(CHSUPP_MASK | IOMODE_MASK | MAXFREQ_MASK); 84 val |= IOMODE_SDQ | MAXFREQ_33MHZ | FIELD_PREP(CHSUPP_MASK, ch_supp); 85 writel(val, base + ESPICFG); 86 } else if (!strcmp(type, "lpc")) { 87 /* Select LPC pin function */ 88 regmap_update_bits(syscon, MFSEL4, MFSEL4_ESPISEL, 0); 89 regmap_update_bits(syscon, MFSEL1, MFSEL1_LPCSEL, MFSEL1_LPCSEL); 90 } 91 92 /* Release host wait */ 93 setbits_8(SMC_CTL_REG_ADDR, SMC_CTL_HOSTWAIT); 94 95 return 0; 96} 97 98static const struct udevice_id npcm_hostintf_ids[] = { 99 { .compatible = "nuvoton,npcm750-host-intf" }, 100 { .compatible = "nuvoton,npcm845-host-intf" }, 101 { } 102}; 103 104U_BOOT_DRIVER(npcm_host_intf) = { 105 .name = "npcm_host_intf", 106 .id = UCLASS_MISC, 107 .of_match = npcm_hostintf_ids, 108 .bind = npcm_host_intf_bind, 109}; 110