]>
Commit | Line | Data |
---|---|---|
0a6f333e SG |
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 | ||
d678a59d | 11 | #include <common.h> |
0a6f333e SG |
12 | #include <dm.h> |
13 | #include <dt-structs.h> | |
f7ae49fc | 14 | #include <log.h> |
0a6f333e SG |
15 | #include <p2sb.h> |
16 | #include <asm/intel_pinctrl.h> | |
17 | #include <asm-generic/gpio.h> | |
18 | #include <asm/intel_pinctrl_defs.h> | |
19 | ||
0a6f333e SG |
20 | static const struct reset_mapping rst_map[] = { |
21 | { .logical = PAD_CFG0_LOGICAL_RESET_PWROK, .chipset = 0U << 30 }, | |
22 | { .logical = PAD_CFG0_LOGICAL_RESET_DEEP, .chipset = 1U << 30 }, | |
23 | { .logical = PAD_CFG0_LOGICAL_RESET_PLTRST, .chipset = 2U << 30 }, | |
24 | }; | |
25 | ||
26 | /* Groups for each community */ | |
27 | static const struct pad_group apl_community_n_groups[] = { | |
28 | INTEL_GPP(N_OFFSET, N_OFFSET, GPIO_31), /* NORTH 0 */ | |
29 | INTEL_GPP(N_OFFSET, GPIO_32, JTAG_TRST_B), /* NORTH 1 */ | |
30 | INTEL_GPP(N_OFFSET, JTAG_TMS, SVID0_CLK), /* NORTH 2 */ | |
31 | }; | |
32 | ||
33 | static const struct pad_group apl_community_w_groups[] = { | |
34 | INTEL_GPP(W_OFFSET, W_OFFSET, OSC_CLK_OUT_1), /* WEST 0 */ | |
35 | INTEL_GPP(W_OFFSET, OSC_CLK_OUT_2, SUSPWRDNACK),/* WEST 1 */ | |
36 | }; | |
37 | ||
38 | static const struct pad_group apl_community_sw_groups[] = { | |
39 | INTEL_GPP(SW_OFFSET, SW_OFFSET, SMB_ALERTB), /* SOUTHWEST 0 */ | |
40 | INTEL_GPP(SW_OFFSET, SMB_CLK, LPC_FRAMEB), /* SOUTHWEST 1 */ | |
41 | }; | |
42 | ||
43 | static const struct pad_group apl_community_nw_groups[] = { | |
44 | INTEL_GPP(NW_OFFSET, NW_OFFSET, PROCHOT_B), /* NORTHWEST 0 */ | |
45 | INTEL_GPP(NW_OFFSET, PMIC_I2C_SCL, GPIO_106), /* NORTHWEST 1 */ | |
46 | INTEL_GPP(NW_OFFSET, GPIO_109, GPIO_123), /* NORTHWEST 2 */ | |
47 | }; | |
48 | ||
49 | /* TODO(sjg@chromium.org): Consider moving this to device tree */ | |
50 | static const struct pad_community apl_gpio_communities[] = { | |
51 | { | |
52 | .port = PID_GPIO_N, | |
53 | .first_pad = N_OFFSET, | |
54 | .last_pad = SVID0_CLK, | |
55 | .num_gpi_regs = NUM_N_GPI_REGS, | |
56 | .gpi_status_offset = NUM_NW_GPI_REGS + NUM_W_GPI_REGS | |
57 | + NUM_SW_GPI_REGS, | |
58 | .pad_cfg_base = PAD_CFG_BASE, | |
59 | .host_own_reg_0 = HOSTSW_OWN_REG_0, | |
60 | .gpi_int_sts_reg_0 = GPI_INT_STS_0, | |
61 | .gpi_int_en_reg_0 = GPI_INT_EN_0, | |
62 | .gpi_smi_sts_reg_0 = GPI_SMI_STS_0, | |
63 | .gpi_smi_en_reg_0 = GPI_SMI_EN_0, | |
64 | .max_pads_per_group = GPIO_MAX_NUM_PER_GROUP, | |
65 | .name = "GPIO_GPE_N", | |
0a6f333e SG |
66 | .reset_map = rst_map, |
67 | .num_reset_vals = ARRAY_SIZE(rst_map), | |
68 | .groups = apl_community_n_groups, | |
69 | .num_groups = ARRAY_SIZE(apl_community_n_groups), | |
70 | }, { | |
71 | .port = PID_GPIO_NW, | |
72 | .first_pad = NW_OFFSET, | |
73 | .last_pad = GPIO_123, | |
74 | .num_gpi_regs = NUM_NW_GPI_REGS, | |
75 | .gpi_status_offset = NUM_W_GPI_REGS + NUM_SW_GPI_REGS, | |
76 | .pad_cfg_base = PAD_CFG_BASE, | |
77 | .host_own_reg_0 = HOSTSW_OWN_REG_0, | |
78 | .gpi_int_sts_reg_0 = GPI_INT_STS_0, | |
79 | .gpi_int_en_reg_0 = GPI_INT_EN_0, | |
80 | .gpi_smi_sts_reg_0 = GPI_SMI_STS_0, | |
81 | .gpi_smi_en_reg_0 = GPI_SMI_EN_0, | |
82 | .max_pads_per_group = GPIO_MAX_NUM_PER_GROUP, | |
83 | .name = "GPIO_GPE_NW", | |
0a6f333e SG |
84 | .reset_map = rst_map, |
85 | .num_reset_vals = ARRAY_SIZE(rst_map), | |
86 | .groups = apl_community_nw_groups, | |
87 | .num_groups = ARRAY_SIZE(apl_community_nw_groups), | |
88 | }, { | |
89 | .port = PID_GPIO_W, | |
90 | .first_pad = W_OFFSET, | |
91 | .last_pad = SUSPWRDNACK, | |
92 | .num_gpi_regs = NUM_W_GPI_REGS, | |
93 | .gpi_status_offset = NUM_SW_GPI_REGS, | |
94 | .pad_cfg_base = PAD_CFG_BASE, | |
95 | .host_own_reg_0 = HOSTSW_OWN_REG_0, | |
96 | .gpi_int_sts_reg_0 = GPI_INT_STS_0, | |
97 | .gpi_int_en_reg_0 = GPI_INT_EN_0, | |
98 | .gpi_smi_sts_reg_0 = GPI_SMI_STS_0, | |
99 | .gpi_smi_en_reg_0 = GPI_SMI_EN_0, | |
100 | .max_pads_per_group = GPIO_MAX_NUM_PER_GROUP, | |
101 | .name = "GPIO_GPE_W", | |
0a6f333e SG |
102 | .reset_map = rst_map, |
103 | .num_reset_vals = ARRAY_SIZE(rst_map), | |
104 | .groups = apl_community_w_groups, | |
105 | .num_groups = ARRAY_SIZE(apl_community_w_groups), | |
106 | }, { | |
107 | .port = PID_GPIO_SW, | |
108 | .first_pad = SW_OFFSET, | |
109 | .last_pad = LPC_FRAMEB, | |
110 | .num_gpi_regs = NUM_SW_GPI_REGS, | |
111 | .gpi_status_offset = 0, | |
112 | .pad_cfg_base = PAD_CFG_BASE, | |
113 | .host_own_reg_0 = HOSTSW_OWN_REG_0, | |
114 | .gpi_int_sts_reg_0 = GPI_INT_STS_0, | |
115 | .gpi_int_en_reg_0 = GPI_INT_EN_0, | |
116 | .gpi_smi_sts_reg_0 = GPI_SMI_STS_0, | |
117 | .gpi_smi_en_reg_0 = GPI_SMI_EN_0, | |
118 | .max_pads_per_group = GPIO_MAX_NUM_PER_GROUP, | |
119 | .name = "GPIO_GPE_SW", | |
0a6f333e SG |
120 | .reset_map = rst_map, |
121 | .num_reset_vals = ARRAY_SIZE(rst_map), | |
122 | .groups = apl_community_sw_groups, | |
123 | .num_groups = ARRAY_SIZE(apl_community_sw_groups), | |
124 | }, | |
125 | }; | |
126 | ||
d1998a9f | 127 | static int apl_pinctrl_of_to_plat(struct udevice *dev) |
0a6f333e | 128 | { |
8a8d24bd | 129 | struct p2sb_child_plat *pplat; |
0a6f333e SG |
130 | const struct pad_community *comm = NULL; |
131 | int i; | |
132 | ||
133 | #if CONFIG_IS_ENABLED(OF_PLATDATA) | |
8a8d24bd | 134 | struct apl_gpio_plat *plat = dev_get_plat(dev); |
0a6f333e SG |
135 | int ret; |
136 | ||
137 | /* | |
138 | * It would be nice to do this in the bind() method, but with | |
139 | * of-platdata binding happens in the order that DM finds things in the | |
140 | * linker list (i.e. alphabetical order by driver name). So the GPIO | |
141 | * device may well be bound before its parent (p2sb), and this call | |
142 | * will fail if p2sb is not bound yet. | |
0a6f333e SG |
143 | */ |
144 | ret = p2sb_set_port_id(dev, plat->dtplat.intel_p2sb_port_id); | |
145 | if (ret) | |
146 | return log_msg_ret("Could not set port id", ret); | |
147 | #endif | |
148 | /* Attach this device to its community structure */ | |
caa4daa2 | 149 | pplat = dev_get_parent_plat(dev); |
0a6f333e SG |
150 | for (i = 0; i < ARRAY_SIZE(apl_gpio_communities); i++) { |
151 | if (apl_gpio_communities[i].port == pplat->pid) | |
152 | comm = &apl_gpio_communities[i]; | |
153 | } | |
154 | ||
d1998a9f | 155 | return intel_pinctrl_of_to_plat(dev, comm, 2); |
0a6f333e SG |
156 | } |
157 | ||
95397385 | 158 | #if CONFIG_IS_ENABLED(OF_REAL) |
0a6f333e SG |
159 | static const struct udevice_id apl_gpio_ids[] = { |
160 | { .compatible = "intel,apl-pinctrl"}, | |
161 | { } | |
162 | }; | |
8b842be1 | 163 | #endif |
0a6f333e | 164 | |
9d20db04 | 165 | U_BOOT_DRIVER(intel_apl_pinctrl) = { |
0a6f333e SG |
166 | .name = "intel_apl_pinctrl", |
167 | .id = UCLASS_PINCTRL, | |
8b842be1 | 168 | .of_match = of_match_ptr(apl_gpio_ids), |
0a6f333e SG |
169 | .probe = intel_pinctrl_probe, |
170 | .ops = &intel_pinctrl_ops, | |
95397385 | 171 | #if CONFIG_IS_ENABLED(OF_REAL) |
0a6f333e SG |
172 | .bind = dm_scan_fdt_dev, |
173 | #endif | |
d1998a9f | 174 | .of_to_plat = apl_pinctrl_of_to_plat, |
41575d8e | 175 | .priv_auto = sizeof(struct intel_pinctrl_priv), |
8a8d24bd | 176 | .plat_auto = sizeof(struct apl_gpio_plat), |
0a6f333e | 177 | }; |