|
8 | 8 | * Configuration Registers.
|
9 | 9 | *
|
10 | 10 | * This driver is derived from lpc_sch.
|
11 |
| -
|
| 11 | + * |
| 12 | + * Copyright (c) 2017, 2021-2022 Intel Corporation |
12 | 13 | * Copyright (c) 2011 Extreme Engineering Solution, Inc.
|
13 | 14 | * Author: Aaron Sierra <[email protected]>
|
14 | 15 | *
|
|
42 | 43 | #include <linux/errno.h>
|
43 | 44 | #include <linux/acpi.h>
|
44 | 45 | #include <linux/pci.h>
|
| 46 | +#include <linux/pinctrl/pinctrl.h> |
45 | 47 | #include <linux/mfd/core.h>
|
46 | 48 | #include <linux/mfd/lpc_ich.h>
|
47 | 49 | #include <linux/platform_data/itco_wdt.h>
|
@@ -142,6 +144,73 @@ static struct mfd_cell lpc_ich_gpio_cell = {
|
142 | 144 | .ignore_resource_conflicts = true,
|
143 | 145 | };
|
144 | 146 |
|
| 147 | +#define APL_GPIO_NORTH 0 |
| 148 | +#define APL_GPIO_NORTHWEST 1 |
| 149 | +#define APL_GPIO_WEST 2 |
| 150 | +#define APL_GPIO_SOUTHWEST 3 |
| 151 | +#define APL_GPIO_NR_DEVICES 4 |
| 152 | + |
| 153 | +/* Offset data for Apollo Lake GPIO controllers */ |
| 154 | +static resource_size_t apl_gpio_offsets[APL_GPIO_NR_DEVICES] = { |
| 155 | + [APL_GPIO_NORTH] = 0xc50000, |
| 156 | + [APL_GPIO_NORTHWEST] = 0xc40000, |
| 157 | + [APL_GPIO_WEST] = 0xc70000, |
| 158 | + [APL_GPIO_SOUTHWEST] = 0xc00000, |
| 159 | +}; |
| 160 | + |
| 161 | +#define APL_GPIO_RESOURCE_SIZE 0x1000 |
| 162 | + |
| 163 | +#define APL_GPIO_IRQ 14 |
| 164 | + |
| 165 | +static struct resource apl_gpio_resources[APL_GPIO_NR_DEVICES][2] = { |
| 166 | + [APL_GPIO_NORTH] = { |
| 167 | + DEFINE_RES_MEM(0, 0), |
| 168 | + DEFINE_RES_IRQ(APL_GPIO_IRQ), |
| 169 | + }, |
| 170 | + [APL_GPIO_NORTHWEST] = { |
| 171 | + DEFINE_RES_MEM(0, 0), |
| 172 | + DEFINE_RES_IRQ(APL_GPIO_IRQ), |
| 173 | + }, |
| 174 | + [APL_GPIO_WEST] = { |
| 175 | + DEFINE_RES_MEM(0, 0), |
| 176 | + DEFINE_RES_IRQ(APL_GPIO_IRQ), |
| 177 | + }, |
| 178 | + [APL_GPIO_SOUTHWEST] = { |
| 179 | + DEFINE_RES_MEM(0, 0), |
| 180 | + DEFINE_RES_IRQ(APL_GPIO_IRQ), |
| 181 | + }, |
| 182 | +}; |
| 183 | + |
| 184 | +static const struct mfd_cell apl_gpio_devices[APL_GPIO_NR_DEVICES] = { |
| 185 | + [APL_GPIO_NORTH] = { |
| 186 | + .name = "apollolake-pinctrl", |
| 187 | + .id = APL_GPIO_NORTH, |
| 188 | + .num_resources = ARRAY_SIZE(apl_gpio_resources[APL_GPIO_NORTH]), |
| 189 | + .resources = apl_gpio_resources[APL_GPIO_NORTH], |
| 190 | + .ignore_resource_conflicts = true, |
| 191 | + }, |
| 192 | + [APL_GPIO_NORTHWEST] = { |
| 193 | + .name = "apollolake-pinctrl", |
| 194 | + .id = APL_GPIO_NORTHWEST, |
| 195 | + .num_resources = ARRAY_SIZE(apl_gpio_resources[APL_GPIO_NORTHWEST]), |
| 196 | + .resources = apl_gpio_resources[APL_GPIO_NORTHWEST], |
| 197 | + .ignore_resource_conflicts = true, |
| 198 | + }, |
| 199 | + [APL_GPIO_WEST] = { |
| 200 | + .name = "apollolake-pinctrl", |
| 201 | + .id = APL_GPIO_WEST, |
| 202 | + .num_resources = ARRAY_SIZE(apl_gpio_resources[APL_GPIO_WEST]), |
| 203 | + .resources = apl_gpio_resources[APL_GPIO_WEST], |
| 204 | + .ignore_resource_conflicts = true, |
| 205 | + }, |
| 206 | + [APL_GPIO_SOUTHWEST] = { |
| 207 | + .name = "apollolake-pinctrl", |
| 208 | + .id = APL_GPIO_SOUTHWEST, |
| 209 | + .num_resources = ARRAY_SIZE(apl_gpio_resources[APL_GPIO_SOUTHWEST]), |
| 210 | + .resources = apl_gpio_resources[APL_GPIO_SOUTHWEST], |
| 211 | + .ignore_resource_conflicts = true, |
| 212 | + }, |
| 213 | +}; |
145 | 214 |
|
146 | 215 | static struct mfd_cell lpc_ich_spi_cell = {
|
147 | 216 | .name = "intel-spi",
|
@@ -1085,6 +1154,34 @@ static int lpc_ich_init_wdt(struct pci_dev *dev)
|
1085 | 1154 | return ret;
|
1086 | 1155 | }
|
1087 | 1156 |
|
| 1157 | +static int lpc_ich_init_pinctrl(struct pci_dev *dev) |
| 1158 | +{ |
| 1159 | + struct resource base; |
| 1160 | + unsigned int i; |
| 1161 | + int ret; |
| 1162 | + |
| 1163 | + /* Check, if GPIO has been exported as an ACPI device */ |
| 1164 | + if (acpi_dev_present("INT3452", NULL, -1)) |
| 1165 | + return -EEXIST; |
| 1166 | + |
| 1167 | + ret = p2sb_bar(dev->bus, 0, &base); |
| 1168 | + if (ret) |
| 1169 | + return ret; |
| 1170 | + |
| 1171 | + for (i = 0; i < ARRAY_SIZE(apl_gpio_devices); i++) { |
| 1172 | + struct resource *mem = &apl_gpio_resources[i][0]; |
| 1173 | + resource_size_t offset = apl_gpio_offsets[i]; |
| 1174 | + |
| 1175 | + /* Fill MEM resource */ |
| 1176 | + mem->start = base.start + offset; |
| 1177 | + mem->end = base.start + offset + APL_GPIO_RESOURCE_SIZE - 1; |
| 1178 | + mem->flags = base.flags; |
| 1179 | + } |
| 1180 | + |
| 1181 | + return mfd_add_devices(&dev->dev, 0, apl_gpio_devices, |
| 1182 | + ARRAY_SIZE(apl_gpio_devices), NULL, 0, NULL); |
| 1183 | +} |
| 1184 | + |
1088 | 1185 | static bool lpc_ich_byt_set_writeable(void __iomem *base, void *data)
|
1089 | 1186 | {
|
1090 | 1187 | u32 val;
|
@@ -1235,6 +1332,12 @@ static int lpc_ich_probe(struct pci_dev *dev,
|
1235 | 1332 | cell_added = true;
|
1236 | 1333 | }
|
1237 | 1334 |
|
| 1335 | + if (priv->chipset == LPC_APL) { |
| 1336 | + ret = lpc_ich_init_pinctrl(dev); |
| 1337 | + if (!ret) |
| 1338 | + cell_added = true; |
| 1339 | + } |
| 1340 | + |
1238 | 1341 | if (lpc_chipset_info[priv->chipset].spi_type) {
|
1239 | 1342 | ret = lpc_ich_init_spi(dev);
|
1240 | 1343 | if (!ret)
|
|
0 commit comments