]>
Commit | Line | Data |
---|---|---|
cf4ece53 | 1 | /* |
7f2732c8 | 2 | * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd. |
cf4ece53 MO |
3 | * |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; version 2 of the License. | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, | |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | * GNU General Public License for more details. | |
12 | * | |
13 | * You should have received a copy of the GNU General Public License | |
14 | * along with this program; if not, write to the Free Software | |
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. | |
16 | */ | |
17 | ||
18 | #include <linux/module.h> | |
19 | #include <linux/kernel.h> | |
20 | #include <linux/types.h> | |
21 | #include <linux/fs.h> | |
22 | #include <linux/uaccess.h> | |
23 | #include <linux/string.h> | |
24 | #include <linux/pci.h> | |
25 | #include <linux/io.h> | |
26 | #include <linux/delay.h> | |
27 | #include <linux/mutex.h> | |
28 | #include <linux/if_ether.h> | |
29 | #include <linux/ctype.h> | |
6ae705b2 | 30 | #include <linux/dmi.h> |
549ce8f1 | 31 | #include <linux/of.h> |
cf4ece53 MO |
32 | |
33 | #define PHUB_STATUS 0x00 /* Status Register offset */ | |
34 | #define PHUB_CONTROL 0x04 /* Control Register offset */ | |
35 | #define PHUB_TIMEOUT 0x05 /* Time out value for Status Register */ | |
36 | #define PCH_PHUB_ROM_WRITE_ENABLE 0x01 /* Enabling for writing ROM */ | |
37 | #define PCH_PHUB_ROM_WRITE_DISABLE 0x00 /* Disabling for writing ROM */ | |
275640b0 TM |
38 | #define PCH_PHUB_MAC_START_ADDR_EG20T 0x14 /* MAC data area start address |
39 | offset */ | |
40 | #define PCH_PHUB_MAC_START_ADDR_ML7223 0x20C /* MAC data area start address | |
41 | offset */ | |
42 | #define PCH_PHUB_ROM_START_ADDR_EG20T 0x80 /* ROM data area start address offset | |
c47dda7d TM |
43 | (Intel EG20T PCH)*/ |
44 | #define PCH_PHUB_ROM_START_ADDR_ML7213 0x400 /* ROM data area start address | |
7f2732c8 | 45 | offset(LAPIS Semicon ML7213) |
c47dda7d | 46 | */ |
275640b0 | 47 | #define PCH_PHUB_ROM_START_ADDR_ML7223 0x400 /* ROM data area start address |
7f2732c8 | 48 | offset(LAPIS Semicon ML7223) |
275640b0 | 49 | */ |
cf4ece53 MO |
50 | |
51 | /* MAX number of INT_REDUCE_CONTROL registers */ | |
52 | #define MAX_NUM_INT_REDUCE_CONTROL_REG 128 | |
53 | #define PCI_DEVICE_ID_PCH1_PHUB 0x8801 | |
54 | #define PCH_MINOR_NOS 1 | |
55 | #define CLKCFG_CAN_50MHZ 0x12000000 | |
56 | #define CLKCFG_CANCLK_MASK 0xFF000000 | |
6ae705b2 DT |
57 | #define CLKCFG_UART_MASK 0xFFFFFF |
58 | ||
59 | /* CM-iTC */ | |
60 | #define CLKCFG_UART_48MHZ (1 << 16) | |
bed3d7ba | 61 | #define CLKCFG_UART_25MHZ (2 << 16) |
6ae705b2 DT |
62 | #define CLKCFG_BAUDDIV (2 << 20) |
63 | #define CLKCFG_PLL2VCO (8 << 9) | |
64 | #define CLKCFG_UARTCLKSEL (1 << 18) | |
cf4ece53 | 65 | |
1a738dcf TM |
66 | /* Macros for ML7213 */ |
67 | #define PCI_VENDOR_ID_ROHM 0x10db | |
68 | #define PCI_DEVICE_ID_ROHM_ML7213_PHUB 0x801A | |
cf4ece53 | 69 | |
275640b0 TM |
70 | /* Macros for ML7223 */ |
71 | #define PCI_DEVICE_ID_ROHM_ML7223_mPHUB 0x8012 /* for Bus-m */ | |
72 | #define PCI_DEVICE_ID_ROHM_ML7223_nPHUB 0x8002 /* for Bus-n */ | |
73 | ||
584ad00c TM |
74 | /* Macros for ML7831 */ |
75 | #define PCI_DEVICE_ID_ROHM_ML7831_PHUB 0x8801 | |
76 | ||
cf4ece53 MO |
77 | /* SROM ACCESS Macro */ |
78 | #define PCH_WORD_ADDR_MASK (~((1 << 2) - 1)) | |
79 | ||
80 | /* Registers address offset */ | |
81 | #define PCH_PHUB_ID_REG 0x0000 | |
82 | #define PCH_PHUB_QUEUE_PRI_VAL_REG 0x0004 | |
83 | #define PCH_PHUB_RC_QUEUE_MAXSIZE_REG 0x0008 | |
84 | #define PCH_PHUB_BRI_QUEUE_MAXSIZE_REG 0x000C | |
85 | #define PCH_PHUB_COMP_RESP_TIMEOUT_REG 0x0010 | |
86 | #define PCH_PHUB_BUS_SLAVE_CONTROL_REG 0x0014 | |
87 | #define PCH_PHUB_DEADLOCK_AVOID_TYPE_REG 0x0018 | |
88 | #define PCH_PHUB_INTPIN_REG_WPERMIT_REG0 0x0020 | |
89 | #define PCH_PHUB_INTPIN_REG_WPERMIT_REG1 0x0024 | |
90 | #define PCH_PHUB_INTPIN_REG_WPERMIT_REG2 0x0028 | |
91 | #define PCH_PHUB_INTPIN_REG_WPERMIT_REG3 0x002C | |
92 | #define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE 0x0040 | |
93 | #define CLKCFG_REG_OFFSET 0x500 | |
dd7d7fea | 94 | #define FUNCSEL_REG_OFFSET 0x508 |
cf4ece53 MO |
95 | |
96 | #define PCH_PHUB_OROM_SIZE 15360 | |
97 | ||
98 | /** | |
99 | * struct pch_phub_reg - PHUB register structure | |
100 | * @phub_id_reg: PHUB_ID register val | |
101 | * @q_pri_val_reg: QUEUE_PRI_VAL register val | |
102 | * @rc_q_maxsize_reg: RC_QUEUE_MAXSIZE register val | |
103 | * @bri_q_maxsize_reg: BRI_QUEUE_MAXSIZE register val | |
104 | * @comp_resp_timeout_reg: COMP_RESP_TIMEOUT register val | |
105 | * @bus_slave_control_reg: BUS_SLAVE_CONTROL_REG register val | |
106 | * @deadlock_avoid_type_reg: DEADLOCK_AVOID_TYPE register val | |
107 | * @intpin_reg_wpermit_reg0: INTPIN_REG_WPERMIT register 0 val | |
108 | * @intpin_reg_wpermit_reg1: INTPIN_REG_WPERMIT register 1 val | |
109 | * @intpin_reg_wpermit_reg2: INTPIN_REG_WPERMIT register 2 val | |
110 | * @intpin_reg_wpermit_reg3: INTPIN_REG_WPERMIT register 3 val | |
111 | * @int_reduce_control_reg: INT_REDUCE_CONTROL registers val | |
112 | * @clkcfg_reg: CLK CFG register val | |
dd7d7fea | 113 | * @funcsel_reg: Function select register value |
cf4ece53 MO |
114 | * @pch_phub_base_address: Register base address |
115 | * @pch_phub_extrom_base_address: external rom base address | |
275640b0 TM |
116 | * @pch_mac_start_address: MAC address area start address |
117 | * @pch_opt_rom_start_address: Option ROM start address | |
118 | * @ioh_type: Save IOH type | |
9914a0de | 119 | * @pdev: pointer to pci device struct |
cf4ece53 MO |
120 | */ |
121 | struct pch_phub_reg { | |
122 | u32 phub_id_reg; | |
123 | u32 q_pri_val_reg; | |
124 | u32 rc_q_maxsize_reg; | |
125 | u32 bri_q_maxsize_reg; | |
126 | u32 comp_resp_timeout_reg; | |
127 | u32 bus_slave_control_reg; | |
128 | u32 deadlock_avoid_type_reg; | |
129 | u32 intpin_reg_wpermit_reg0; | |
130 | u32 intpin_reg_wpermit_reg1; | |
131 | u32 intpin_reg_wpermit_reg2; | |
132 | u32 intpin_reg_wpermit_reg3; | |
133 | u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG]; | |
134 | u32 clkcfg_reg; | |
dd7d7fea | 135 | u32 funcsel_reg; |
cf4ece53 MO |
136 | void __iomem *pch_phub_base_address; |
137 | void __iomem *pch_phub_extrom_base_address; | |
275640b0 TM |
138 | u32 pch_mac_start_address; |
139 | u32 pch_opt_rom_start_address; | |
140 | int ioh_type; | |
9914a0de | 141 | struct pci_dev *pdev; |
cf4ece53 MO |
142 | }; |
143 | ||
144 | /* SROM SPEC for MAC address assignment offset */ | |
145 | static const int pch_phub_mac_offset[ETH_ALEN] = {0x3, 0x2, 0x1, 0x0, 0xb, 0xa}; | |
146 | ||
147 | static DEFINE_MUTEX(pch_phub_mutex); | |
148 | ||
149 | /** | |
150 | * pch_phub_read_modify_write_reg() - Reading modifying and writing register | |
151 | * @reg_addr_offset: Register offset address value. | |
152 | * @data: Writing value. | |
153 | * @mask: Mask value. | |
154 | */ | |
155 | static void pch_phub_read_modify_write_reg(struct pch_phub_reg *chip, | |
156 | unsigned int reg_addr_offset, | |
157 | unsigned int data, unsigned int mask) | |
158 | { | |
159 | void __iomem *reg_addr = chip->pch_phub_base_address + reg_addr_offset; | |
160 | iowrite32(((ioread32(reg_addr) & ~mask)) | data, reg_addr); | |
161 | } | |
162 | ||
7750efd5 | 163 | #ifdef CONFIG_PM |
cf4ece53 MO |
164 | /* pch_phub_save_reg_conf - saves register configuration */ |
165 | static void pch_phub_save_reg_conf(struct pci_dev *pdev) | |
166 | { | |
167 | unsigned int i; | |
168 | struct pch_phub_reg *chip = pci_get_drvdata(pdev); | |
169 | ||
170 | void __iomem *p = chip->pch_phub_base_address; | |
171 | ||
172 | chip->phub_id_reg = ioread32(p + PCH_PHUB_ID_REG); | |
173 | chip->q_pri_val_reg = ioread32(p + PCH_PHUB_QUEUE_PRI_VAL_REG); | |
174 | chip->rc_q_maxsize_reg = ioread32(p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG); | |
175 | chip->bri_q_maxsize_reg = ioread32(p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG); | |
176 | chip->comp_resp_timeout_reg = | |
177 | ioread32(p + PCH_PHUB_COMP_RESP_TIMEOUT_REG); | |
178 | chip->bus_slave_control_reg = | |
179 | ioread32(p + PCH_PHUB_BUS_SLAVE_CONTROL_REG); | |
180 | chip->deadlock_avoid_type_reg = | |
181 | ioread32(p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG); | |
182 | chip->intpin_reg_wpermit_reg0 = | |
183 | ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0); | |
184 | chip->intpin_reg_wpermit_reg1 = | |
185 | ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1); | |
186 | chip->intpin_reg_wpermit_reg2 = | |
187 | ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2); | |
188 | chip->intpin_reg_wpermit_reg3 = | |
189 | ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3); | |
190 | dev_dbg(&pdev->dev, "%s : " | |
191 | "chip->phub_id_reg=%x, " | |
192 | "chip->q_pri_val_reg=%x, " | |
193 | "chip->rc_q_maxsize_reg=%x, " | |
194 | "chip->bri_q_maxsize_reg=%x, " | |
195 | "chip->comp_resp_timeout_reg=%x, " | |
196 | "chip->bus_slave_control_reg=%x, " | |
197 | "chip->deadlock_avoid_type_reg=%x, " | |
198 | "chip->intpin_reg_wpermit_reg0=%x, " | |
199 | "chip->intpin_reg_wpermit_reg1=%x, " | |
200 | "chip->intpin_reg_wpermit_reg2=%x, " | |
201 | "chip->intpin_reg_wpermit_reg3=%x\n", __func__, | |
202 | chip->phub_id_reg, | |
203 | chip->q_pri_val_reg, | |
204 | chip->rc_q_maxsize_reg, | |
205 | chip->bri_q_maxsize_reg, | |
206 | chip->comp_resp_timeout_reg, | |
207 | chip->bus_slave_control_reg, | |
208 | chip->deadlock_avoid_type_reg, | |
209 | chip->intpin_reg_wpermit_reg0, | |
210 | chip->intpin_reg_wpermit_reg1, | |
211 | chip->intpin_reg_wpermit_reg2, | |
212 | chip->intpin_reg_wpermit_reg3); | |
213 | for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) { | |
214 | chip->int_reduce_control_reg[i] = | |
215 | ioread32(p + PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i); | |
216 | dev_dbg(&pdev->dev, "%s : " | |
217 | "chip->int_reduce_control_reg[%d]=%x\n", | |
218 | __func__, i, chip->int_reduce_control_reg[i]); | |
219 | } | |
220 | chip->clkcfg_reg = ioread32(p + CLKCFG_REG_OFFSET); | |
dd7d7fea TM |
221 | if ((chip->ioh_type == 2) || (chip->ioh_type == 4)) |
222 | chip->funcsel_reg = ioread32(p + FUNCSEL_REG_OFFSET); | |
cf4ece53 MO |
223 | } |
224 | ||
225 | /* pch_phub_restore_reg_conf - restore register configuration */ | |
226 | static void pch_phub_restore_reg_conf(struct pci_dev *pdev) | |
227 | { | |
228 | unsigned int i; | |
229 | struct pch_phub_reg *chip = pci_get_drvdata(pdev); | |
230 | void __iomem *p; | |
231 | p = chip->pch_phub_base_address; | |
232 | ||
233 | iowrite32(chip->phub_id_reg, p + PCH_PHUB_ID_REG); | |
234 | iowrite32(chip->q_pri_val_reg, p + PCH_PHUB_QUEUE_PRI_VAL_REG); | |
235 | iowrite32(chip->rc_q_maxsize_reg, p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG); | |
236 | iowrite32(chip->bri_q_maxsize_reg, p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG); | |
237 | iowrite32(chip->comp_resp_timeout_reg, | |
238 | p + PCH_PHUB_COMP_RESP_TIMEOUT_REG); | |
239 | iowrite32(chip->bus_slave_control_reg, | |
240 | p + PCH_PHUB_BUS_SLAVE_CONTROL_REG); | |
241 | iowrite32(chip->deadlock_avoid_type_reg, | |
242 | p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG); | |
243 | iowrite32(chip->intpin_reg_wpermit_reg0, | |
244 | p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0); | |
245 | iowrite32(chip->intpin_reg_wpermit_reg1, | |
246 | p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1); | |
247 | iowrite32(chip->intpin_reg_wpermit_reg2, | |
248 | p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2); | |
249 | iowrite32(chip->intpin_reg_wpermit_reg3, | |
250 | p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3); | |
251 | dev_dbg(&pdev->dev, "%s : " | |
252 | "chip->phub_id_reg=%x, " | |
253 | "chip->q_pri_val_reg=%x, " | |
254 | "chip->rc_q_maxsize_reg=%x, " | |
255 | "chip->bri_q_maxsize_reg=%x, " | |
256 | "chip->comp_resp_timeout_reg=%x, " | |
257 | "chip->bus_slave_control_reg=%x, " | |
258 | "chip->deadlock_avoid_type_reg=%x, " | |
259 | "chip->intpin_reg_wpermit_reg0=%x, " | |
260 | "chip->intpin_reg_wpermit_reg1=%x, " | |
261 | "chip->intpin_reg_wpermit_reg2=%x, " | |
262 | "chip->intpin_reg_wpermit_reg3=%x\n", __func__, | |
263 | chip->phub_id_reg, | |
264 | chip->q_pri_val_reg, | |
265 | chip->rc_q_maxsize_reg, | |
266 | chip->bri_q_maxsize_reg, | |
267 | chip->comp_resp_timeout_reg, | |
268 | chip->bus_slave_control_reg, | |
269 | chip->deadlock_avoid_type_reg, | |
270 | chip->intpin_reg_wpermit_reg0, | |
271 | chip->intpin_reg_wpermit_reg1, | |
272 | chip->intpin_reg_wpermit_reg2, | |
273 | chip->intpin_reg_wpermit_reg3); | |
274 | for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) { | |
275 | iowrite32(chip->int_reduce_control_reg[i], | |
276 | p + PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i); | |
277 | dev_dbg(&pdev->dev, "%s : " | |
278 | "chip->int_reduce_control_reg[%d]=%x\n", | |
279 | __func__, i, chip->int_reduce_control_reg[i]); | |
280 | } | |
281 | ||
282 | iowrite32(chip->clkcfg_reg, p + CLKCFG_REG_OFFSET); | |
dd7d7fea TM |
283 | if ((chip->ioh_type == 2) || (chip->ioh_type == 4)) |
284 | iowrite32(chip->funcsel_reg, p + FUNCSEL_REG_OFFSET); | |
cf4ece53 | 285 | } |
7750efd5 | 286 | #endif |
cf4ece53 MO |
287 | |
288 | /** | |
289 | * pch_phub_read_serial_rom() - Reading Serial ROM | |
290 | * @offset_address: Serial ROM offset address to read. | |
291 | * @data: Read buffer for specified Serial ROM value. | |
292 | */ | |
293 | static void pch_phub_read_serial_rom(struct pch_phub_reg *chip, | |
294 | unsigned int offset_address, u8 *data) | |
295 | { | |
296 | void __iomem *mem_addr = chip->pch_phub_extrom_base_address + | |
297 | offset_address; | |
298 | ||
299 | *data = ioread8(mem_addr); | |
300 | } | |
301 | ||
302 | /** | |
303 | * pch_phub_write_serial_rom() - Writing Serial ROM | |
304 | * @offset_address: Serial ROM offset address. | |
305 | * @data: Serial ROM value to write. | |
306 | */ | |
307 | static int pch_phub_write_serial_rom(struct pch_phub_reg *chip, | |
308 | unsigned int offset_address, u8 data) | |
309 | { | |
310 | void __iomem *mem_addr = chip->pch_phub_extrom_base_address + | |
311 | (offset_address & PCH_WORD_ADDR_MASK); | |
312 | int i; | |
313 | unsigned int word_data; | |
314 | unsigned int pos; | |
315 | unsigned int mask; | |
316 | pos = (offset_address % 4) * 8; | |
317 | mask = ~(0xFF << pos); | |
318 | ||
319 | iowrite32(PCH_PHUB_ROM_WRITE_ENABLE, | |
320 | chip->pch_phub_extrom_base_address + PHUB_CONTROL); | |
321 | ||
322 | word_data = ioread32(mem_addr); | |
323 | iowrite32((word_data & mask) | (u32)data << pos, mem_addr); | |
324 | ||
325 | i = 0; | |
326 | while (ioread8(chip->pch_phub_extrom_base_address + | |
327 | PHUB_STATUS) != 0x00) { | |
328 | msleep(1); | |
329 | if (i == PHUB_TIMEOUT) | |
330 | return -ETIMEDOUT; | |
331 | i++; | |
332 | } | |
333 | ||
334 | iowrite32(PCH_PHUB_ROM_WRITE_DISABLE, | |
335 | chip->pch_phub_extrom_base_address + PHUB_CONTROL); | |
336 | ||
337 | return 0; | |
338 | } | |
339 | ||
340 | /** | |
341 | * pch_phub_read_serial_rom_val() - Read Serial ROM value | |
342 | * @offset_address: Serial ROM address offset value. | |
343 | * @data: Serial ROM value to read. | |
344 | */ | |
345 | static void pch_phub_read_serial_rom_val(struct pch_phub_reg *chip, | |
346 | unsigned int offset_address, u8 *data) | |
347 | { | |
348 | unsigned int mem_addr; | |
349 | ||
275640b0 | 350 | mem_addr = chip->pch_mac_start_address + |
cf4ece53 MO |
351 | pch_phub_mac_offset[offset_address]; |
352 | ||
353 | pch_phub_read_serial_rom(chip, mem_addr, data); | |
354 | } | |
355 | ||
356 | /** | |
357 | * pch_phub_write_serial_rom_val() - writing Serial ROM value | |
358 | * @offset_address: Serial ROM address offset value. | |
359 | * @data: Serial ROM value. | |
360 | */ | |
361 | static int pch_phub_write_serial_rom_val(struct pch_phub_reg *chip, | |
362 | unsigned int offset_address, u8 data) | |
363 | { | |
364 | int retval; | |
365 | unsigned int mem_addr; | |
366 | ||
275640b0 | 367 | mem_addr = chip->pch_mac_start_address + |
cf4ece53 MO |
368 | pch_phub_mac_offset[offset_address]; |
369 | ||
370 | retval = pch_phub_write_serial_rom(chip, mem_addr, data); | |
371 | ||
372 | return retval; | |
373 | } | |
374 | ||
375 | /* pch_phub_gbe_serial_rom_conf - makes Serial ROM header format configuration | |
376 | * for Gigabit Ethernet MAC address | |
377 | */ | |
378 | static int pch_phub_gbe_serial_rom_conf(struct pch_phub_reg *chip) | |
379 | { | |
380 | int retval; | |
381 | ||
382 | retval = pch_phub_write_serial_rom(chip, 0x0b, 0xbc); | |
383 | retval |= pch_phub_write_serial_rom(chip, 0x0a, 0x10); | |
384 | retval |= pch_phub_write_serial_rom(chip, 0x09, 0x01); | |
385 | retval |= pch_phub_write_serial_rom(chip, 0x08, 0x02); | |
386 | ||
387 | retval |= pch_phub_write_serial_rom(chip, 0x0f, 0x00); | |
388 | retval |= pch_phub_write_serial_rom(chip, 0x0e, 0x00); | |
389 | retval |= pch_phub_write_serial_rom(chip, 0x0d, 0x00); | |
390 | retval |= pch_phub_write_serial_rom(chip, 0x0c, 0x80); | |
391 | ||
392 | retval |= pch_phub_write_serial_rom(chip, 0x13, 0xbc); | |
393 | retval |= pch_phub_write_serial_rom(chip, 0x12, 0x10); | |
394 | retval |= pch_phub_write_serial_rom(chip, 0x11, 0x01); | |
395 | retval |= pch_phub_write_serial_rom(chip, 0x10, 0x18); | |
396 | ||
397 | retval |= pch_phub_write_serial_rom(chip, 0x1b, 0xbc); | |
398 | retval |= pch_phub_write_serial_rom(chip, 0x1a, 0x10); | |
399 | retval |= pch_phub_write_serial_rom(chip, 0x19, 0x01); | |
400 | retval |= pch_phub_write_serial_rom(chip, 0x18, 0x19); | |
401 | ||
402 | retval |= pch_phub_write_serial_rom(chip, 0x23, 0xbc); | |
403 | retval |= pch_phub_write_serial_rom(chip, 0x22, 0x10); | |
404 | retval |= pch_phub_write_serial_rom(chip, 0x21, 0x01); | |
405 | retval |= pch_phub_write_serial_rom(chip, 0x20, 0x3a); | |
406 | ||
407 | retval |= pch_phub_write_serial_rom(chip, 0x27, 0x01); | |
408 | retval |= pch_phub_write_serial_rom(chip, 0x26, 0x00); | |
409 | retval |= pch_phub_write_serial_rom(chip, 0x25, 0x00); | |
410 | retval |= pch_phub_write_serial_rom(chip, 0x24, 0x00); | |
411 | ||
412 | return retval; | |
413 | } | |
414 | ||
275640b0 TM |
415 | /* pch_phub_gbe_serial_rom_conf_mp - makes SerialROM header format configuration |
416 | * for Gigabit Ethernet MAC address | |
417 | */ | |
418 | static int pch_phub_gbe_serial_rom_conf_mp(struct pch_phub_reg *chip) | |
419 | { | |
420 | int retval; | |
421 | u32 offset_addr; | |
422 | ||
423 | offset_addr = 0x200; | |
424 | retval = pch_phub_write_serial_rom(chip, 0x03 + offset_addr, 0xbc); | |
425 | retval |= pch_phub_write_serial_rom(chip, 0x02 + offset_addr, 0x00); | |
426 | retval |= pch_phub_write_serial_rom(chip, 0x01 + offset_addr, 0x40); | |
427 | retval |= pch_phub_write_serial_rom(chip, 0x00 + offset_addr, 0x02); | |
428 | ||
429 | retval |= pch_phub_write_serial_rom(chip, 0x07 + offset_addr, 0x00); | |
430 | retval |= pch_phub_write_serial_rom(chip, 0x06 + offset_addr, 0x00); | |
431 | retval |= pch_phub_write_serial_rom(chip, 0x05 + offset_addr, 0x00); | |
432 | retval |= pch_phub_write_serial_rom(chip, 0x04 + offset_addr, 0x80); | |
433 | ||
434 | retval |= pch_phub_write_serial_rom(chip, 0x0b + offset_addr, 0xbc); | |
435 | retval |= pch_phub_write_serial_rom(chip, 0x0a + offset_addr, 0x00); | |
436 | retval |= pch_phub_write_serial_rom(chip, 0x09 + offset_addr, 0x40); | |
437 | retval |= pch_phub_write_serial_rom(chip, 0x08 + offset_addr, 0x18); | |
438 | ||
439 | retval |= pch_phub_write_serial_rom(chip, 0x13 + offset_addr, 0xbc); | |
440 | retval |= pch_phub_write_serial_rom(chip, 0x12 + offset_addr, 0x00); | |
441 | retval |= pch_phub_write_serial_rom(chip, 0x11 + offset_addr, 0x40); | |
442 | retval |= pch_phub_write_serial_rom(chip, 0x10 + offset_addr, 0x19); | |
443 | ||
444 | retval |= pch_phub_write_serial_rom(chip, 0x1b + offset_addr, 0xbc); | |
445 | retval |= pch_phub_write_serial_rom(chip, 0x1a + offset_addr, 0x00); | |
446 | retval |= pch_phub_write_serial_rom(chip, 0x19 + offset_addr, 0x40); | |
447 | retval |= pch_phub_write_serial_rom(chip, 0x18 + offset_addr, 0x3a); | |
448 | ||
449 | retval |= pch_phub_write_serial_rom(chip, 0x1f + offset_addr, 0x01); | |
450 | retval |= pch_phub_write_serial_rom(chip, 0x1e + offset_addr, 0x00); | |
451 | retval |= pch_phub_write_serial_rom(chip, 0x1d + offset_addr, 0x00); | |
452 | retval |= pch_phub_write_serial_rom(chip, 0x1c + offset_addr, 0x00); | |
453 | ||
454 | return retval; | |
455 | } | |
456 | ||
cf4ece53 MO |
457 | /** |
458 | * pch_phub_read_gbe_mac_addr() - Read Gigabit Ethernet MAC address | |
459 | * @offset_address: Gigabit Ethernet MAC address offset value. | |
460 | * @data: Buffer of the Gigabit Ethernet MAC address value. | |
461 | */ | |
462 | static void pch_phub_read_gbe_mac_addr(struct pch_phub_reg *chip, u8 *data) | |
463 | { | |
464 | int i; | |
465 | for (i = 0; i < ETH_ALEN; i++) | |
466 | pch_phub_read_serial_rom_val(chip, i, &data[i]); | |
467 | } | |
468 | ||
469 | /** | |
470 | * pch_phub_write_gbe_mac_addr() - Write MAC address | |
471 | * @offset_address: Gigabit Ethernet MAC address offset value. | |
472 | * @data: Gigabit Ethernet MAC address value. | |
473 | */ | |
474 | static int pch_phub_write_gbe_mac_addr(struct pch_phub_reg *chip, u8 *data) | |
475 | { | |
476 | int retval; | |
477 | int i; | |
478 | ||
2a988791 | 479 | if ((chip->ioh_type == 1) || (chip->ioh_type == 5)) /* EG20T or ML7831*/ |
275640b0 TM |
480 | retval = pch_phub_gbe_serial_rom_conf(chip); |
481 | else /* ML7223 */ | |
482 | retval = pch_phub_gbe_serial_rom_conf_mp(chip); | |
cf4ece53 MO |
483 | if (retval) |
484 | return retval; | |
485 | ||
486 | for (i = 0; i < ETH_ALEN; i++) { | |
487 | retval = pch_phub_write_serial_rom_val(chip, i, data[i]); | |
488 | if (retval) | |
489 | return retval; | |
490 | } | |
491 | ||
492 | return retval; | |
493 | } | |
494 | ||
495 | static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj, | |
496 | struct bin_attribute *attr, char *buf, | |
497 | loff_t off, size_t count) | |
498 | { | |
499 | unsigned int rom_signature; | |
500 | unsigned char rom_length; | |
501 | unsigned int tmp; | |
502 | unsigned int addr_offset; | |
503 | unsigned int orom_size; | |
504 | int ret; | |
505 | int err; | |
9914a0de | 506 | ssize_t rom_size; |
cf4ece53 | 507 | |
85f4f39c | 508 | struct pch_phub_reg *chip = dev_get_drvdata(kobj_to_dev(kobj)); |
cf4ece53 MO |
509 | |
510 | ret = mutex_lock_interruptible(&pch_phub_mutex); | |
511 | if (ret) { | |
512 | err = -ERESTARTSYS; | |
513 | goto return_err_nomutex; | |
514 | } | |
515 | ||
516 | /* Get Rom signature */ | |
9914a0de | 517 | chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size); |
a75fa128 CIK |
518 | if (!chip->pch_phub_extrom_base_address) { |
519 | err = -ENODATA; | |
9914a0de | 520 | goto exrom_map_err; |
a75fa128 | 521 | } |
9914a0de | 522 | |
275640b0 TM |
523 | pch_phub_read_serial_rom(chip, chip->pch_opt_rom_start_address, |
524 | (unsigned char *)&rom_signature); | |
cf4ece53 | 525 | rom_signature &= 0xff; |
275640b0 TM |
526 | pch_phub_read_serial_rom(chip, chip->pch_opt_rom_start_address + 1, |
527 | (unsigned char *)&tmp); | |
cf4ece53 MO |
528 | rom_signature |= (tmp & 0xff) << 8; |
529 | if (rom_signature == 0xAA55) { | |
275640b0 TM |
530 | pch_phub_read_serial_rom(chip, |
531 | chip->pch_opt_rom_start_address + 2, | |
532 | &rom_length); | |
cf4ece53 MO |
533 | orom_size = rom_length * 512; |
534 | if (orom_size < off) { | |
535 | addr_offset = 0; | |
536 | goto return_ok; | |
537 | } | |
538 | if (orom_size < count) { | |
539 | addr_offset = 0; | |
540 | goto return_ok; | |
541 | } | |
542 | ||
543 | for (addr_offset = 0; addr_offset < count; addr_offset++) { | |
275640b0 TM |
544 | pch_phub_read_serial_rom(chip, |
545 | chip->pch_opt_rom_start_address + addr_offset + off, | |
546 | &buf[addr_offset]); | |
cf4ece53 MO |
547 | } |
548 | } else { | |
549 | err = -ENODATA; | |
550 | goto return_err; | |
551 | } | |
552 | return_ok: | |
9914a0de | 553 | pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address); |
cf4ece53 MO |
554 | mutex_unlock(&pch_phub_mutex); |
555 | return addr_offset; | |
556 | ||
557 | return_err: | |
9914a0de TM |
558 | pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address); |
559 | exrom_map_err: | |
cf4ece53 MO |
560 | mutex_unlock(&pch_phub_mutex); |
561 | return_err_nomutex: | |
562 | return err; | |
563 | } | |
564 | ||
565 | static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj, | |
566 | struct bin_attribute *attr, | |
567 | char *buf, loff_t off, size_t count) | |
568 | { | |
569 | int err; | |
570 | unsigned int addr_offset; | |
571 | int ret; | |
9914a0de | 572 | ssize_t rom_size; |
85f4f39c | 573 | struct pch_phub_reg *chip = dev_get_drvdata(kobj_to_dev(kobj)); |
cf4ece53 MO |
574 | |
575 | ret = mutex_lock_interruptible(&pch_phub_mutex); | |
576 | if (ret) | |
577 | return -ERESTARTSYS; | |
578 | ||
579 | if (off > PCH_PHUB_OROM_SIZE) { | |
580 | addr_offset = 0; | |
581 | goto return_ok; | |
582 | } | |
583 | if (count > PCH_PHUB_OROM_SIZE) { | |
584 | addr_offset = 0; | |
585 | goto return_ok; | |
586 | } | |
587 | ||
9914a0de TM |
588 | chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size); |
589 | if (!chip->pch_phub_extrom_base_address) { | |
590 | err = -ENOMEM; | |
591 | goto exrom_map_err; | |
592 | } | |
593 | ||
cf4ece53 MO |
594 | for (addr_offset = 0; addr_offset < count; addr_offset++) { |
595 | if (PCH_PHUB_OROM_SIZE < off + addr_offset) | |
596 | goto return_ok; | |
597 | ||
275640b0 TM |
598 | ret = pch_phub_write_serial_rom(chip, |
599 | chip->pch_opt_rom_start_address + addr_offset + off, | |
600 | buf[addr_offset]); | |
cf4ece53 MO |
601 | if (ret) { |
602 | err = ret; | |
603 | goto return_err; | |
604 | } | |
605 | } | |
606 | ||
607 | return_ok: | |
9914a0de | 608 | pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address); |
cf4ece53 MO |
609 | mutex_unlock(&pch_phub_mutex); |
610 | return addr_offset; | |
611 | ||
612 | return_err: | |
9914a0de TM |
613 | pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address); |
614 | ||
615 | exrom_map_err: | |
cf4ece53 MO |
616 | mutex_unlock(&pch_phub_mutex); |
617 | return err; | |
618 | } | |
619 | ||
620 | static ssize_t show_pch_mac(struct device *dev, struct device_attribute *attr, | |
621 | char *buf) | |
622 | { | |
623 | u8 mac[8]; | |
624 | struct pch_phub_reg *chip = dev_get_drvdata(dev); | |
9914a0de TM |
625 | ssize_t rom_size; |
626 | ||
627 | chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size); | |
628 | if (!chip->pch_phub_extrom_base_address) | |
629 | return -ENOMEM; | |
cf4ece53 MO |
630 | |
631 | pch_phub_read_gbe_mac_addr(chip, mac); | |
9914a0de | 632 | pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address); |
cf4ece53 | 633 | |
25b8a88c | 634 | return sprintf(buf, "%pM\n", mac); |
cf4ece53 MO |
635 | } |
636 | ||
637 | static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr, | |
638 | const char *buf, size_t count) | |
639 | { | |
143e9c76 | 640 | u8 mac[ETH_ALEN]; |
9914a0de | 641 | ssize_t rom_size; |
cf4ece53 | 642 | struct pch_phub_reg *chip = dev_get_drvdata(dev); |
a246b973 | 643 | int ret; |
cf4ece53 | 644 | |
143e9c76 | 645 | if (!mac_pton(buf, mac)) |
cf4ece53 MO |
646 | return -EINVAL; |
647 | ||
9914a0de TM |
648 | chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size); |
649 | if (!chip->pch_phub_extrom_base_address) | |
650 | return -ENOMEM; | |
651 | ||
a246b973 | 652 | ret = pch_phub_write_gbe_mac_addr(chip, mac); |
9914a0de | 653 | pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address); |
a246b973 AS |
654 | if (ret) |
655 | return ret; | |
cf4ece53 MO |
656 | |
657 | return count; | |
658 | } | |
659 | ||
660 | static DEVICE_ATTR(pch_mac, S_IRUGO | S_IWUSR, show_pch_mac, store_pch_mac); | |
661 | ||
57daedf8 | 662 | static const struct bin_attribute pch_bin_attr = { |
cf4ece53 MO |
663 | .attr = { |
664 | .name = "pch_firmware", | |
665 | .mode = S_IRUGO | S_IWUSR, | |
666 | }, | |
667 | .size = PCH_PHUB_OROM_SIZE + 1, | |
668 | .read = pch_phub_bin_read, | |
669 | .write = pch_phub_bin_write, | |
670 | }; | |
671 | ||
80c8ae28 | 672 | static int pch_phub_probe(struct pci_dev *pdev, |
cf4ece53 MO |
673 | const struct pci_device_id *id) |
674 | { | |
cf4ece53 | 675 | int ret; |
cf4ece53 MO |
676 | struct pch_phub_reg *chip; |
677 | ||
678 | chip = kzalloc(sizeof(struct pch_phub_reg), GFP_KERNEL); | |
679 | if (chip == NULL) | |
680 | return -ENOMEM; | |
681 | ||
682 | ret = pci_enable_device(pdev); | |
683 | if (ret) { | |
684 | dev_err(&pdev->dev, | |
685 | "%s : pci_enable_device FAILED(ret=%d)", __func__, ret); | |
686 | goto err_pci_enable_dev; | |
687 | } | |
688 | dev_dbg(&pdev->dev, "%s : pci_enable_device returns %d\n", __func__, | |
689 | ret); | |
690 | ||
691 | ret = pci_request_regions(pdev, KBUILD_MODNAME); | |
692 | if (ret) { | |
693 | dev_err(&pdev->dev, | |
694 | "%s : pci_request_regions FAILED(ret=%d)", __func__, ret); | |
695 | goto err_req_regions; | |
696 | } | |
697 | dev_dbg(&pdev->dev, "%s : " | |
698 | "pci_request_regions returns %d\n", __func__, ret); | |
699 | ||
700 | chip->pch_phub_base_address = pci_iomap(pdev, 1, 0); | |
701 | ||
702 | ||
73ac0e9e | 703 | if (chip->pch_phub_base_address == NULL) { |
cf4ece53 MO |
704 | dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__); |
705 | ret = -ENOMEM; | |
706 | goto err_pci_iomap; | |
707 | } | |
708 | dev_dbg(&pdev->dev, "%s : pci_iomap SUCCESS and value " | |
da0d7f98 GKH |
709 | "in pch_phub_base_address variable is %p\n", __func__, |
710 | chip->pch_phub_base_address); | |
cf4ece53 | 711 | |
9914a0de | 712 | chip->pdev = pdev; /* Save pci device struct */ |
cf4ece53 | 713 | |
275640b0 | 714 | if (id->driver_data == 1) { /* EG20T PCH */ |
2b934c62 | 715 | const char *board_name; |
549ce8f1 ZLK |
716 | unsigned int prefetch = 0x000affaa; |
717 | ||
718 | if (pdev->dev.of_node) | |
719 | of_property_read_u32(pdev->dev.of_node, | |
720 | "intel,eg20t-prefetch", | |
721 | &prefetch); | |
2b934c62 | 722 | |
29ddae2a WY |
723 | ret = sysfs_create_file(&pdev->dev.kobj, |
724 | &dev_attr_pch_mac.attr); | |
725 | if (ret) | |
c47dda7d | 726 | goto err_sysfs_create; |
cf4ece53 | 727 | |
29ddae2a WY |
728 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); |
729 | if (ret) | |
c47dda7d TM |
730 | goto exit_bin_attr; |
731 | ||
732 | pch_phub_read_modify_write_reg(chip, | |
733 | (unsigned int)CLKCFG_REG_OFFSET, | |
734 | CLKCFG_CAN_50MHZ, | |
735 | CLKCFG_CANCLK_MASK); | |
736 | ||
6ae705b2 | 737 | /* quirk for CM-iTC board */ |
2b934c62 AS |
738 | board_name = dmi_get_system_info(DMI_BOARD_NAME); |
739 | if (board_name && strstr(board_name, "CM-iTC")) | |
6ae705b2 DT |
740 | pch_phub_read_modify_write_reg(chip, |
741 | (unsigned int)CLKCFG_REG_OFFSET, | |
742 | CLKCFG_UART_48MHZ | CLKCFG_BAUDDIV | | |
743 | CLKCFG_PLL2VCO | CLKCFG_UARTCLKSEL, | |
744 | CLKCFG_UART_MASK); | |
745 | ||
c47dda7d | 746 | /* set the prefech value */ |
549ce8f1 | 747 | iowrite32(prefetch, chip->pch_phub_base_address + 0x14); |
c47dda7d TM |
748 | /* set the interrupt delay value */ |
749 | iowrite32(0x25, chip->pch_phub_base_address + 0x44); | |
275640b0 TM |
750 | chip->pch_opt_rom_start_address = PCH_PHUB_ROM_START_ADDR_EG20T; |
751 | chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_EG20T; | |
bed3d7ba ZLK |
752 | |
753 | /* quirk for MIPS Boston platform */ | |
754 | if (pdev->dev.of_node) { | |
755 | if (of_machine_is_compatible("img,boston")) { | |
756 | pch_phub_read_modify_write_reg(chip, | |
757 | (unsigned int)CLKCFG_REG_OFFSET, | |
758 | CLKCFG_UART_25MHZ, | |
759 | CLKCFG_UART_MASK); | |
760 | } | |
761 | } | |
275640b0 | 762 | } else if (id->driver_data == 2) { /* ML7213 IOH */ |
29ddae2a WY |
763 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); |
764 | if (ret) | |
c47dda7d TM |
765 | goto err_sysfs_create; |
766 | /* set the prefech value | |
767 | * Device2(USB OHCI #1/ USB EHCI #1/ USB Device):a | |
768 | * Device4(SDIO #0,1,2):f | |
769 | * Device6(SATA 2):f | |
770 | * Device8(USB OHCI #0/ USB EHCI #0):a | |
771 | */ | |
772 | iowrite32(0x000affa0, chip->pch_phub_base_address + 0x14); | |
275640b0 TM |
773 | chip->pch_opt_rom_start_address =\ |
774 | PCH_PHUB_ROM_START_ADDR_ML7213; | |
775 | } else if (id->driver_data == 3) { /* ML7223 IOH Bus-m*/ | |
776 | /* set the prefech value | |
777 | * Device8(GbE) | |
778 | */ | |
779 | iowrite32(0x000a0000, chip->pch_phub_base_address + 0x14); | |
20ae6d0b TM |
780 | /* set the interrupt delay value */ |
781 | iowrite32(0x25, chip->pch_phub_base_address + 0x140); | |
275640b0 TM |
782 | chip->pch_opt_rom_start_address =\ |
783 | PCH_PHUB_ROM_START_ADDR_ML7223; | |
784 | chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223; | |
785 | } else if (id->driver_data == 4) { /* ML7223 IOH Bus-n*/ | |
29ddae2a WY |
786 | ret = sysfs_create_file(&pdev->dev.kobj, |
787 | &dev_attr_pch_mac.attr); | |
788 | if (ret) | |
275640b0 | 789 | goto err_sysfs_create; |
29ddae2a WY |
790 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); |
791 | if (ret) | |
275640b0 TM |
792 | goto exit_bin_attr; |
793 | /* set the prefech value | |
794 | * Device2(USB OHCI #0,1,2,3/ USB EHCI #0):a | |
795 | * Device4(SDIO #0,1):f | |
796 | * Device6(SATA 2):f | |
797 | */ | |
798 | iowrite32(0x0000ffa0, chip->pch_phub_base_address + 0x14); | |
275640b0 TM |
799 | chip->pch_opt_rom_start_address =\ |
800 | PCH_PHUB_ROM_START_ADDR_ML7223; | |
801 | chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223; | |
584ad00c | 802 | } else if (id->driver_data == 5) { /* ML7831 */ |
29ddae2a WY |
803 | ret = sysfs_create_file(&pdev->dev.kobj, |
804 | &dev_attr_pch_mac.attr); | |
805 | if (ret) | |
584ad00c TM |
806 | goto err_sysfs_create; |
807 | ||
29ddae2a WY |
808 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); |
809 | if (ret) | |
584ad00c TM |
810 | goto exit_bin_attr; |
811 | ||
812 | /* set the prefech value */ | |
813 | iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14); | |
814 | /* set the interrupt delay value */ | |
815 | iowrite32(0x25, chip->pch_phub_base_address + 0x44); | |
816 | chip->pch_opt_rom_start_address = PCH_PHUB_ROM_START_ADDR_EG20T; | |
817 | chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_EG20T; | |
c47dda7d | 818 | } |
275640b0 TM |
819 | |
820 | chip->ioh_type = id->driver_data; | |
c47dda7d | 821 | pci_set_drvdata(pdev, chip); |
cf4ece53 MO |
822 | |
823 | return 0; | |
824 | exit_bin_attr: | |
825 | sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr); | |
826 | ||
827 | err_sysfs_create: | |
cf4ece53 MO |
828 | pci_iounmap(pdev, chip->pch_phub_base_address); |
829 | err_pci_iomap: | |
830 | pci_release_regions(pdev); | |
831 | err_req_regions: | |
832 | pci_disable_device(pdev); | |
833 | err_pci_enable_dev: | |
834 | kfree(chip); | |
835 | dev_err(&pdev->dev, "%s returns %d\n", __func__, ret); | |
836 | return ret; | |
837 | } | |
838 | ||
486a5c28 | 839 | static void pch_phub_remove(struct pci_dev *pdev) |
cf4ece53 MO |
840 | { |
841 | struct pch_phub_reg *chip = pci_get_drvdata(pdev); | |
842 | ||
843 | sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr); | |
844 | sysfs_remove_bin_file(&pdev->dev.kobj, &pch_bin_attr); | |
cf4ece53 MO |
845 | pci_iounmap(pdev, chip->pch_phub_base_address); |
846 | pci_release_regions(pdev); | |
847 | pci_disable_device(pdev); | |
848 | kfree(chip); | |
849 | } | |
850 | ||
851 | #ifdef CONFIG_PM | |
852 | ||
853 | static int pch_phub_suspend(struct pci_dev *pdev, pm_message_t state) | |
854 | { | |
855 | int ret; | |
856 | ||
857 | pch_phub_save_reg_conf(pdev); | |
858 | ret = pci_save_state(pdev); | |
859 | if (ret) { | |
860 | dev_err(&pdev->dev, | |
861 | " %s -pci_save_state returns %d\n", __func__, ret); | |
862 | return ret; | |
863 | } | |
864 | pci_enable_wake(pdev, PCI_D3hot, 0); | |
865 | pci_disable_device(pdev); | |
866 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | |
867 | ||
868 | return 0; | |
869 | } | |
870 | ||
871 | static int pch_phub_resume(struct pci_dev *pdev) | |
872 | { | |
873 | int ret; | |
874 | ||
875 | pci_set_power_state(pdev, PCI_D0); | |
876 | pci_restore_state(pdev); | |
877 | ret = pci_enable_device(pdev); | |
878 | if (ret) { | |
879 | dev_err(&pdev->dev, | |
880 | "%s-pci_enable_device failed(ret=%d) ", __func__, ret); | |
881 | return ret; | |
882 | } | |
883 | ||
884 | pci_enable_wake(pdev, PCI_D3hot, 0); | |
885 | pch_phub_restore_reg_conf(pdev); | |
886 | ||
887 | return 0; | |
888 | } | |
889 | #else | |
890 | #define pch_phub_suspend NULL | |
891 | #define pch_phub_resume NULL | |
892 | #endif /* CONFIG_PM */ | |
893 | ||
e3b9c5ce | 894 | static const struct pci_device_id pch_phub_pcidev_id[] = { |
c47dda7d TM |
895 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH1_PHUB), 1, }, |
896 | { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7213_PHUB), 2, }, | |
275640b0 TM |
897 | { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_mPHUB), 3, }, |
898 | { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_nPHUB), 4, }, | |
584ad00c | 899 | { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7831_PHUB), 5, }, |
c47dda7d | 900 | { } |
cf4ece53 | 901 | }; |
b2595142 | 902 | MODULE_DEVICE_TABLE(pci, pch_phub_pcidev_id); |
cf4ece53 MO |
903 | |
904 | static struct pci_driver pch_phub_driver = { | |
905 | .name = "pch_phub", | |
906 | .id_table = pch_phub_pcidev_id, | |
907 | .probe = pch_phub_probe, | |
2d6bed9c | 908 | .remove = pch_phub_remove, |
cf4ece53 MO |
909 | .suspend = pch_phub_suspend, |
910 | .resume = pch_phub_resume | |
911 | }; | |
912 | ||
cfeb2852 | 913 | module_pci_driver(pch_phub_driver); |
cf4ece53 | 914 | |
7f2732c8 | 915 | MODULE_DESCRIPTION("Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7223) PHUB"); |
cf4ece53 | 916 | MODULE_LICENSE("GPL"); |