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