.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * lpc_ich.c - LPC interface for Intel ICH |
---|
3 | 4 | * |
---|
.. | .. |
---|
10 | 11 | |
---|
11 | 12 | * Copyright (c) 2011 Extreme Engineering Solution, Inc. |
---|
12 | 13 | * Author: Aaron Sierra <asierra@xes-inc.com> |
---|
13 | | - * |
---|
14 | | - * This program is free software; you can redistribute it and/or modify |
---|
15 | | - * it under the terms of the GNU General Public License 2 as published |
---|
16 | | - * by the Free Software Foundation. |
---|
17 | | - * |
---|
18 | | - * This program is distributed in the hope that it will be useful, |
---|
19 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
20 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
21 | | - * GNU General Public License for more details. |
---|
22 | 14 | * |
---|
23 | 15 | * This driver supports the following I/O Controller hubs: |
---|
24 | 16 | * (See the intel documentation on http://developer.intel.com.) |
---|
.. | .. |
---|
71 | 63 | #define SPIBASE_BYT 0x54 |
---|
72 | 64 | #define SPIBASE_BYT_SZ 512 |
---|
73 | 65 | #define SPIBASE_BYT_EN BIT(1) |
---|
| 66 | +#define BYT_BCR 0xfc |
---|
| 67 | +#define BYT_BCR_WPD BIT(0) |
---|
74 | 68 | |
---|
75 | 69 | #define SPIBASE_LPT 0x3800 |
---|
76 | 70 | #define SPIBASE_LPT_SZ 512 |
---|
.. | .. |
---|
1091 | 1085 | return ret; |
---|
1092 | 1086 | } |
---|
1093 | 1087 | |
---|
| 1088 | +static bool lpc_ich_byt_set_writeable(void __iomem *base, void *data) |
---|
| 1089 | +{ |
---|
| 1090 | + u32 val; |
---|
| 1091 | + |
---|
| 1092 | + val = readl(base + BYT_BCR); |
---|
| 1093 | + if (!(val & BYT_BCR_WPD)) { |
---|
| 1094 | + val |= BYT_BCR_WPD; |
---|
| 1095 | + writel(val, base + BYT_BCR); |
---|
| 1096 | + val = readl(base + BYT_BCR); |
---|
| 1097 | + } |
---|
| 1098 | + |
---|
| 1099 | + return val & BYT_BCR_WPD; |
---|
| 1100 | +} |
---|
| 1101 | + |
---|
| 1102 | +static bool lpc_ich_lpt_set_writeable(void __iomem *base, void *data) |
---|
| 1103 | +{ |
---|
| 1104 | + struct pci_dev *pdev = data; |
---|
| 1105 | + u32 bcr; |
---|
| 1106 | + |
---|
| 1107 | + pci_read_config_dword(pdev, BCR, &bcr); |
---|
| 1108 | + if (!(bcr & BCR_WPD)) { |
---|
| 1109 | + bcr |= BCR_WPD; |
---|
| 1110 | + pci_write_config_dword(pdev, BCR, bcr); |
---|
| 1111 | + pci_read_config_dword(pdev, BCR, &bcr); |
---|
| 1112 | + } |
---|
| 1113 | + |
---|
| 1114 | + return bcr & BCR_WPD; |
---|
| 1115 | +} |
---|
| 1116 | + |
---|
| 1117 | +static bool lpc_ich_bxt_set_writeable(void __iomem *base, void *data) |
---|
| 1118 | +{ |
---|
| 1119 | + unsigned int spi = PCI_DEVFN(13, 2); |
---|
| 1120 | + struct pci_bus *bus = data; |
---|
| 1121 | + u32 bcr; |
---|
| 1122 | + |
---|
| 1123 | + pci_bus_read_config_dword(bus, spi, BCR, &bcr); |
---|
| 1124 | + if (!(bcr & BCR_WPD)) { |
---|
| 1125 | + bcr |= BCR_WPD; |
---|
| 1126 | + pci_bus_write_config_dword(bus, spi, BCR, bcr); |
---|
| 1127 | + pci_bus_read_config_dword(bus, spi, BCR, &bcr); |
---|
| 1128 | + } |
---|
| 1129 | + |
---|
| 1130 | + return bcr & BCR_WPD; |
---|
| 1131 | +} |
---|
| 1132 | + |
---|
1094 | 1133 | static int lpc_ich_init_spi(struct pci_dev *dev) |
---|
1095 | 1134 | { |
---|
1096 | 1135 | struct lpc_ich_priv *priv = pci_get_drvdata(dev); |
---|
1097 | 1136 | struct resource *res = &intel_spi_res[0]; |
---|
1098 | 1137 | struct intel_spi_boardinfo *info; |
---|
1099 | | - u32 spi_base, rcba, bcr; |
---|
| 1138 | + u32 spi_base, rcba; |
---|
1100 | 1139 | |
---|
1101 | 1140 | info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL); |
---|
1102 | 1141 | if (!info) |
---|
.. | .. |
---|
1110 | 1149 | if (spi_base & SPIBASE_BYT_EN) { |
---|
1111 | 1150 | res->start = spi_base & ~(SPIBASE_BYT_SZ - 1); |
---|
1112 | 1151 | res->end = res->start + SPIBASE_BYT_SZ - 1; |
---|
| 1152 | + |
---|
| 1153 | + info->set_writeable = lpc_ich_byt_set_writeable; |
---|
1113 | 1154 | } |
---|
1114 | 1155 | break; |
---|
1115 | 1156 | |
---|
.. | .. |
---|
1120 | 1161 | res->start = spi_base + SPIBASE_LPT; |
---|
1121 | 1162 | res->end = res->start + SPIBASE_LPT_SZ - 1; |
---|
1122 | 1163 | |
---|
1123 | | - pci_read_config_dword(dev, BCR, &bcr); |
---|
1124 | | - info->writeable = !!(bcr & BCR_WPD); |
---|
| 1164 | + info->set_writeable = lpc_ich_lpt_set_writeable; |
---|
| 1165 | + info->data = dev; |
---|
1125 | 1166 | } |
---|
1126 | 1167 | break; |
---|
1127 | 1168 | |
---|
.. | .. |
---|
1142 | 1183 | res->start = spi_base & 0xfffffff0; |
---|
1143 | 1184 | res->end = res->start + SPIBASE_APL_SZ - 1; |
---|
1144 | 1185 | |
---|
1145 | | - pci_bus_read_config_dword(bus, spi, BCR, &bcr); |
---|
1146 | | - info->writeable = !!(bcr & BCR_WPD); |
---|
| 1186 | + info->set_writeable = lpc_ich_bxt_set_writeable; |
---|
| 1187 | + info->data = bus; |
---|
1147 | 1188 | } |
---|
1148 | 1189 | |
---|
1149 | 1190 | pci_bus_write_config_byte(bus, p2sb, 0xe1, 0x1); |
---|