x86: apl: Add pinctrl driver
[oweals/u-boot.git] / drivers / pinctrl / intel / pinctrl_apl.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2017 Intel Corp.
4  * Copyright 2019 Google LLC
5  *
6  * Taken partly from coreboot gpio.c
7  */
8
9 #define LOG_CATEGORY UCLASS_GPIO
10
11 #include <common.h>
12 #include <dm.h>
13 #include <dt-structs.h>
14 #include <p2sb.h>
15 #include <asm/intel_pinctrl.h>
16 #include <asm-generic/gpio.h>
17 #include <asm/intel_pinctrl_defs.h>
18
19 /**
20  * struct apl_gpio_platdata - platform data for each device
21  *
22  * @dtplat: of-platdata data from C struct
23  */
24 struct apl_gpio_platdata {
25 #if CONFIG_IS_ENABLED(OF_PLATDATA)
26         /* Put this first since driver model will copy the data here */
27         struct dtd_intel_apl_pinctrl dtplat;
28 #endif
29 };
30
31 static const struct reset_mapping rst_map[] = {
32         { .logical = PAD_CFG0_LOGICAL_RESET_PWROK, .chipset = 0U << 30 },
33         { .logical = PAD_CFG0_LOGICAL_RESET_DEEP, .chipset = 1U << 30 },
34         { .logical = PAD_CFG0_LOGICAL_RESET_PLTRST, .chipset = 2U << 30 },
35 };
36
37 /* Groups for each community */
38 static const struct pad_group apl_community_n_groups[] = {
39         INTEL_GPP(N_OFFSET, N_OFFSET, GPIO_31),         /* NORTH 0 */
40         INTEL_GPP(N_OFFSET, GPIO_32, JTAG_TRST_B),      /* NORTH 1 */
41         INTEL_GPP(N_OFFSET, JTAG_TMS, SVID0_CLK),       /* NORTH 2 */
42 };
43
44 static const struct pad_group apl_community_w_groups[] = {
45         INTEL_GPP(W_OFFSET, W_OFFSET, OSC_CLK_OUT_1),   /* WEST 0 */
46         INTEL_GPP(W_OFFSET, OSC_CLK_OUT_2, SUSPWRDNACK),/* WEST 1 */
47 };
48
49 static const struct pad_group apl_community_sw_groups[] = {
50         INTEL_GPP(SW_OFFSET, SW_OFFSET, SMB_ALERTB),    /* SOUTHWEST 0 */
51         INTEL_GPP(SW_OFFSET, SMB_CLK, LPC_FRAMEB),      /* SOUTHWEST 1 */
52 };
53
54 static const struct pad_group apl_community_nw_groups[] = {
55         INTEL_GPP(NW_OFFSET, NW_OFFSET, PROCHOT_B),     /* NORTHWEST 0 */
56         INTEL_GPP(NW_OFFSET, PMIC_I2C_SCL, GPIO_106),   /* NORTHWEST 1 */
57         INTEL_GPP(NW_OFFSET, GPIO_109, GPIO_123),       /* NORTHWEST 2 */
58 };
59
60 /* TODO(sjg@chromium.org): Consider moving this to device tree */
61 static const struct pad_community apl_gpio_communities[] = {
62         {
63                 .port = PID_GPIO_N,
64                 .first_pad = N_OFFSET,
65                 .last_pad = SVID0_CLK,
66                 .num_gpi_regs = NUM_N_GPI_REGS,
67                 .gpi_status_offset = NUM_NW_GPI_REGS + NUM_W_GPI_REGS
68                         + NUM_SW_GPI_REGS,
69                 .pad_cfg_base = PAD_CFG_BASE,
70                 .host_own_reg_0 = HOSTSW_OWN_REG_0,
71                 .gpi_int_sts_reg_0 = GPI_INT_STS_0,
72                 .gpi_int_en_reg_0 = GPI_INT_EN_0,
73                 .gpi_smi_sts_reg_0 = GPI_SMI_STS_0,
74                 .gpi_smi_en_reg_0 = GPI_SMI_EN_0,
75                 .max_pads_per_group = GPIO_MAX_NUM_PER_GROUP,
76                 .name = "GPIO_GPE_N",
77                 .acpi_path = "\\_SB.GPO0",
78                 .reset_map = rst_map,
79                 .num_reset_vals = ARRAY_SIZE(rst_map),
80                 .groups = apl_community_n_groups,
81                 .num_groups = ARRAY_SIZE(apl_community_n_groups),
82         }, {
83                 .port = PID_GPIO_NW,
84                 .first_pad = NW_OFFSET,
85                 .last_pad = GPIO_123,
86                 .num_gpi_regs = NUM_NW_GPI_REGS,
87                 .gpi_status_offset = NUM_W_GPI_REGS + NUM_SW_GPI_REGS,
88                 .pad_cfg_base = PAD_CFG_BASE,
89                 .host_own_reg_0 = HOSTSW_OWN_REG_0,
90                 .gpi_int_sts_reg_0 = GPI_INT_STS_0,
91                 .gpi_int_en_reg_0 = GPI_INT_EN_0,
92                 .gpi_smi_sts_reg_0 = GPI_SMI_STS_0,
93                 .gpi_smi_en_reg_0 = GPI_SMI_EN_0,
94                 .max_pads_per_group = GPIO_MAX_NUM_PER_GROUP,
95                 .name = "GPIO_GPE_NW",
96                 .acpi_path = "\\_SB.GPO1",
97                 .reset_map = rst_map,
98                 .num_reset_vals = ARRAY_SIZE(rst_map),
99                 .groups = apl_community_nw_groups,
100                 .num_groups = ARRAY_SIZE(apl_community_nw_groups),
101         }, {
102                 .port = PID_GPIO_W,
103                 .first_pad = W_OFFSET,
104                 .last_pad = SUSPWRDNACK,
105                 .num_gpi_regs = NUM_W_GPI_REGS,
106                 .gpi_status_offset = NUM_SW_GPI_REGS,
107                 .pad_cfg_base = PAD_CFG_BASE,
108                 .host_own_reg_0 = HOSTSW_OWN_REG_0,
109                 .gpi_int_sts_reg_0 = GPI_INT_STS_0,
110                 .gpi_int_en_reg_0 = GPI_INT_EN_0,
111                 .gpi_smi_sts_reg_0 = GPI_SMI_STS_0,
112                 .gpi_smi_en_reg_0 = GPI_SMI_EN_0,
113                 .max_pads_per_group = GPIO_MAX_NUM_PER_GROUP,
114                 .name = "GPIO_GPE_W",
115                 .acpi_path = "\\_SB.GPO2",
116                 .reset_map = rst_map,
117                 .num_reset_vals = ARRAY_SIZE(rst_map),
118                 .groups = apl_community_w_groups,
119                 .num_groups = ARRAY_SIZE(apl_community_w_groups),
120         }, {
121                 .port = PID_GPIO_SW,
122                 .first_pad = SW_OFFSET,
123                 .last_pad = LPC_FRAMEB,
124                 .num_gpi_regs = NUM_SW_GPI_REGS,
125                 .gpi_status_offset = 0,
126                 .pad_cfg_base = PAD_CFG_BASE,
127                 .host_own_reg_0 = HOSTSW_OWN_REG_0,
128                 .gpi_int_sts_reg_0 = GPI_INT_STS_0,
129                 .gpi_int_en_reg_0 = GPI_INT_EN_0,
130                 .gpi_smi_sts_reg_0 = GPI_SMI_STS_0,
131                 .gpi_smi_en_reg_0 = GPI_SMI_EN_0,
132                 .max_pads_per_group = GPIO_MAX_NUM_PER_GROUP,
133                 .name = "GPIO_GPE_SW",
134                 .acpi_path = "\\_SB.GPO3",
135                 .reset_map = rst_map,
136                 .num_reset_vals = ARRAY_SIZE(rst_map),
137                 .groups = apl_community_sw_groups,
138                 .num_groups = ARRAY_SIZE(apl_community_sw_groups),
139         },
140 };
141
142 static int apl_pinctrl_ofdata_to_platdata(struct udevice *dev)
143 {
144         struct p2sb_child_platdata *pplat;
145         const struct pad_community *comm = NULL;
146         int i;
147
148 #if CONFIG_IS_ENABLED(OF_PLATDATA)
149         struct apl_gpio_platdata *plat = dev_get_platdata(dev);
150         int ret;
151
152         /*
153          * It would be nice to do this in the bind() method, but with
154          * of-platdata binding happens in the order that DM finds things in the
155          * linker list (i.e. alphabetical order by driver name). So the GPIO
156          * device may well be bound before its parent (p2sb), and this call
157          * will fail if p2sb is not bound yet.
158          *
159          * TODO(sjg@chromium.org): Add a parent pointer to child devices in dtoc
160          */
161         ret = p2sb_set_port_id(dev, plat->dtplat.intel_p2sb_port_id);
162         if (ret)
163                 return log_msg_ret("Could not set port id", ret);
164 #endif
165         /* Attach this device to its community structure */
166         pplat = dev_get_parent_platdata(dev);
167         for (i = 0; i < ARRAY_SIZE(apl_gpio_communities); i++) {
168                 if (apl_gpio_communities[i].port == pplat->pid)
169                         comm = &apl_gpio_communities[i];
170         }
171
172         return intel_pinctrl_ofdata_to_platdata(dev, comm, 2);
173 }
174
175 static const struct udevice_id apl_gpio_ids[] = {
176         { .compatible = "intel,apl-pinctrl"},
177         { }
178 };
179
180 U_BOOT_DRIVER(apl_pinctrl_drv) = {
181         .name           = "intel_apl_pinctrl",
182         .id             = UCLASS_PINCTRL,
183         .of_match       = apl_gpio_ids,
184         .probe          = intel_pinctrl_probe,
185         .ops            = &intel_pinctrl_ops,
186 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
187         .bind           = dm_scan_fdt_dev,
188 #endif
189         .ofdata_to_platdata = apl_pinctrl_ofdata_to_platdata,
190         .priv_auto_alloc_size = sizeof(struct intel_pinctrl_priv),
191         .platdata_auto_alloc_size = sizeof(struct apl_gpio_platdata),
192 };