diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-22 22:36:42 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-22 22:36:42 -0400 |
commit | b9da0571050c09863e59f94d0b8594a290d61b88 (patch) | |
tree | 3632c4fee768db9a27a5c872bd42133692e2f3d0 /drivers/misc | |
parent | f8cae0f03f75adb54b1d48ddbc90f84a1f5de186 (diff) | |
parent | 5abd935661e01289ba143c3b2c1ba300c65bcc5f (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6: (31 commits)
driver core: Display error codes when class suspend fails
Driver core: Add section count to memory_block struct
Driver core: Add mutex for adding/removing memory blocks
Driver core: Move find_memory_block routine
hpilo: Despecificate driver from iLO generation
driver core: Convert link_mem_sections to use find_memory_block_hinted.
driver core: Introduce find_memory_block_hinted which utilizes kset_find_obj_hinted.
kobject: Introduce kset_find_obj_hinted.
driver core: fix build for CONFIG_BLOCK not enabled
driver-core: base: change to new flag variable
sysfs: only access bin file vm_ops with the active lock
sysfs: Fail bin file mmap if vma close is implemented.
FW_LOADER: fix kconfig dependency warning on HOTPLUG
uio: Statically allocate uio_class and use class .dev_attrs.
uio: Support 2^MINOR_BITS minors
uio: Cleanup irq handling.
uio: Don't clear driver data
uio: Fix lack of locking in init_uio_class
SYSFS: Allow boot time switching between deprecated and modern sysfs layout
driver core: remove CONFIG_SYSFS_DEPRECATED_V2 but keep it for block devices
...
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/Kconfig | 22 | ||||
-rw-r--r-- | drivers/misc/Makefile | 1 | ||||
-rw-r--r-- | drivers/misc/hpilo.c | 2 | ||||
-rw-r--r-- | drivers/misc/pch_phub.c | 717 |
4 files changed, 736 insertions, 6 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index b74331260744..db2fbe2d4146 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
@@ -248,15 +248,15 @@ config CS5535_CLOCK_EVENT_SRC | |||
248 | generic PIT, and are suitable for use as high-res timers. | 248 | generic PIT, and are suitable for use as high-res timers. |
249 | 249 | ||
250 | config HP_ILO | 250 | config HP_ILO |
251 | tristate "Channel interface driver for HP iLO/iLO2 processor" | 251 | tristate "Channel interface driver for the HP iLO processor" |
252 | depends on PCI | 252 | depends on PCI |
253 | default n | 253 | default n |
254 | help | 254 | help |
255 | The channel interface driver allows applications to communicate | 255 | The channel interface driver allows applications to communicate |
256 | with iLO/iLO2 management processors present on HP ProLiant | 256 | with iLO management processors present on HP ProLiant servers. |
257 | servers. Upon loading, the driver creates /dev/hpilo/dXccbN files, | 257 | Upon loading, the driver creates /dev/hpilo/dXccbN files, which |
258 | which can be used to gather data from the management processor, | 258 | can be used to gather data from the management processor, via |
259 | via read and write system calls. | 259 | read and write system calls. |
260 | 260 | ||
261 | To compile this driver as a module, choose M here: the | 261 | To compile this driver as a module, choose M here: the |
262 | module will be called hpilo. | 262 | module will be called hpilo. |
@@ -390,6 +390,18 @@ config BMP085 | |||
390 | To compile this driver as a module, choose M here: the | 390 | To compile this driver as a module, choose M here: the |
391 | module will be called bmp085. | 391 | module will be called bmp085. |
392 | 392 | ||
393 | config PCH_PHUB | ||
394 | tristate "PCH Packet Hub of Intel Topcliff" | ||
395 | depends on PCI | ||
396 | help | ||
397 | This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of | ||
398 | Intel Topcliff which is an IOH(Input/Output Hub) for x86 embedded | ||
399 | processor. The Topcliff has MAC address and Option ROM data in SROM. | ||
400 | This driver can access MAC address and Option ROM data in SROM. | ||
401 | |||
402 | To compile this driver as a module, choose M here: the module will | ||
403 | be called pch_phub. | ||
404 | |||
393 | source "drivers/misc/c2port/Kconfig" | 405 | source "drivers/misc/c2port/Kconfig" |
394 | source "drivers/misc/eeprom/Kconfig" | 406 | source "drivers/misc/eeprom/Kconfig" |
395 | source "drivers/misc/cb710/Kconfig" | 407 | source "drivers/misc/cb710/Kconfig" |
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 42eab95cde2a..9f2986b4da2f 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile | |||
@@ -35,3 +35,4 @@ obj-y += eeprom/ | |||
35 | obj-y += cb710/ | 35 | obj-y += cb710/ |
36 | obj-$(CONFIG_VMWARE_BALLOON) += vmw_balloon.o | 36 | obj-$(CONFIG_VMWARE_BALLOON) += vmw_balloon.o |
37 | obj-$(CONFIG_ARM_CHARLCD) += arm-charlcd.o | 37 | obj-$(CONFIG_ARM_CHARLCD) += arm-charlcd.o |
38 | obj-$(CONFIG_PCH_PHUB) += pch_phub.o | ||
diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c index 69c1f2fca141..fffc227181b0 100644 --- a/drivers/misc/hpilo.c +++ b/drivers/misc/hpilo.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for HP iLO/iLO2 management processor. | 2 | * Driver for the HP iLO management processor. |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Hewlett-Packard Development Company, L.P. | 4 | * Copyright (C) 2008 Hewlett-Packard Development Company, L.P. |
5 | * David Altobelli <david.altobelli@hp.com> | 5 | * David Altobelli <david.altobelli@hp.com> |
diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c new file mode 100644 index 000000000000..744b804aca15 --- /dev/null +++ b/drivers/misc/pch_phub.c | |||
@@ -0,0 +1,717 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD. | ||
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> | ||
30 | |||
31 | #define PHUB_STATUS 0x00 /* Status Register offset */ | ||
32 | #define PHUB_CONTROL 0x04 /* Control Register offset */ | ||
33 | #define PHUB_TIMEOUT 0x05 /* Time out value for Status Register */ | ||
34 | #define PCH_PHUB_ROM_WRITE_ENABLE 0x01 /* Enabling for writing ROM */ | ||
35 | #define PCH_PHUB_ROM_WRITE_DISABLE 0x00 /* Disabling for writing ROM */ | ||
36 | #define PCH_PHUB_ROM_START_ADDR 0x14 /* ROM data area start address offset */ | ||
37 | |||
38 | /* MAX number of INT_REDUCE_CONTROL registers */ | ||
39 | #define MAX_NUM_INT_REDUCE_CONTROL_REG 128 | ||
40 | #define PCI_DEVICE_ID_PCH1_PHUB 0x8801 | ||
41 | #define PCH_MINOR_NOS 1 | ||
42 | #define CLKCFG_CAN_50MHZ 0x12000000 | ||
43 | #define CLKCFG_CANCLK_MASK 0xFF000000 | ||
44 | |||
45 | /* SROM ACCESS Macro */ | ||
46 | #define PCH_WORD_ADDR_MASK (~((1 << 2) - 1)) | ||
47 | |||
48 | /* Registers address offset */ | ||
49 | #define PCH_PHUB_ID_REG 0x0000 | ||
50 | #define PCH_PHUB_QUEUE_PRI_VAL_REG 0x0004 | ||
51 | #define PCH_PHUB_RC_QUEUE_MAXSIZE_REG 0x0008 | ||
52 | #define PCH_PHUB_BRI_QUEUE_MAXSIZE_REG 0x000C | ||
53 | #define PCH_PHUB_COMP_RESP_TIMEOUT_REG 0x0010 | ||
54 | #define PCH_PHUB_BUS_SLAVE_CONTROL_REG 0x0014 | ||
55 | #define PCH_PHUB_DEADLOCK_AVOID_TYPE_REG 0x0018 | ||
56 | #define PCH_PHUB_INTPIN_REG_WPERMIT_REG0 0x0020 | ||
57 | #define PCH_PHUB_INTPIN_REG_WPERMIT_REG1 0x0024 | ||
58 | #define PCH_PHUB_INTPIN_REG_WPERMIT_REG2 0x0028 | ||
59 | #define PCH_PHUB_INTPIN_REG_WPERMIT_REG3 0x002C | ||
60 | #define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE 0x0040 | ||
61 | #define CLKCFG_REG_OFFSET 0x500 | ||
62 | |||
63 | #define PCH_PHUB_OROM_SIZE 15360 | ||
64 | |||
65 | /** | ||
66 | * struct pch_phub_reg - PHUB register structure | ||
67 | * @phub_id_reg: PHUB_ID register val | ||
68 | * @q_pri_val_reg: QUEUE_PRI_VAL register val | ||
69 | * @rc_q_maxsize_reg: RC_QUEUE_MAXSIZE register val | ||
70 | * @bri_q_maxsize_reg: BRI_QUEUE_MAXSIZE register val | ||
71 | * @comp_resp_timeout_reg: COMP_RESP_TIMEOUT register val | ||
72 | * @bus_slave_control_reg: BUS_SLAVE_CONTROL_REG register val | ||
73 | * @deadlock_avoid_type_reg: DEADLOCK_AVOID_TYPE register val | ||
74 | * @intpin_reg_wpermit_reg0: INTPIN_REG_WPERMIT register 0 val | ||
75 | * @intpin_reg_wpermit_reg1: INTPIN_REG_WPERMIT register 1 val | ||
76 | * @intpin_reg_wpermit_reg2: INTPIN_REG_WPERMIT register 2 val | ||
77 | * @intpin_reg_wpermit_reg3: INTPIN_REG_WPERMIT register 3 val | ||
78 | * @int_reduce_control_reg: INT_REDUCE_CONTROL registers val | ||
79 | * @clkcfg_reg: CLK CFG register val | ||
80 | * @pch_phub_base_address: Register base address | ||
81 | * @pch_phub_extrom_base_address: external rom base address | ||
82 | */ | ||
83 | struct pch_phub_reg { | ||
84 | u32 phub_id_reg; | ||
85 | u32 q_pri_val_reg; | ||
86 | u32 rc_q_maxsize_reg; | ||
87 | u32 bri_q_maxsize_reg; | ||
88 | u32 comp_resp_timeout_reg; | ||
89 | u32 bus_slave_control_reg; | ||
90 | u32 deadlock_avoid_type_reg; | ||
91 | u32 intpin_reg_wpermit_reg0; | ||
92 | u32 intpin_reg_wpermit_reg1; | ||
93 | u32 intpin_reg_wpermit_reg2; | ||
94 | u32 intpin_reg_wpermit_reg3; | ||
95 | u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG]; | ||
96 | u32 clkcfg_reg; | ||
97 | void __iomem *pch_phub_base_address; | ||
98 | void __iomem *pch_phub_extrom_base_address; | ||
99 | }; | ||
100 | |||
101 | /* SROM SPEC for MAC address assignment offset */ | ||
102 | static const int pch_phub_mac_offset[ETH_ALEN] = {0x3, 0x2, 0x1, 0x0, 0xb, 0xa}; | ||
103 | |||
104 | static DEFINE_MUTEX(pch_phub_mutex); | ||
105 | |||
106 | /** | ||
107 | * pch_phub_read_modify_write_reg() - Reading modifying and writing register | ||
108 | * @reg_addr_offset: Register offset address value. | ||
109 | * @data: Writing value. | ||
110 | * @mask: Mask value. | ||
111 | */ | ||
112 | static void pch_phub_read_modify_write_reg(struct pch_phub_reg *chip, | ||
113 | unsigned int reg_addr_offset, | ||
114 | unsigned int data, unsigned int mask) | ||
115 | { | ||
116 | void __iomem *reg_addr = chip->pch_phub_base_address + reg_addr_offset; | ||
117 | iowrite32(((ioread32(reg_addr) & ~mask)) | data, reg_addr); | ||
118 | } | ||
119 | |||
120 | /* pch_phub_save_reg_conf - saves register configuration */ | ||
121 | static void pch_phub_save_reg_conf(struct pci_dev *pdev) | ||
122 | { | ||
123 | unsigned int i; | ||
124 | struct pch_phub_reg *chip = pci_get_drvdata(pdev); | ||
125 | |||
126 | void __iomem *p = chip->pch_phub_base_address; | ||
127 | |||
128 | chip->phub_id_reg = ioread32(p + PCH_PHUB_ID_REG); | ||
129 | chip->q_pri_val_reg = ioread32(p + PCH_PHUB_QUEUE_PRI_VAL_REG); | ||
130 | chip->rc_q_maxsize_reg = ioread32(p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG); | ||
131 | chip->bri_q_maxsize_reg = ioread32(p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG); | ||
132 | chip->comp_resp_timeout_reg = | ||
133 | ioread32(p + PCH_PHUB_COMP_RESP_TIMEOUT_REG); | ||
134 | chip->bus_slave_control_reg = | ||
135 | ioread32(p + PCH_PHUB_BUS_SLAVE_CONTROL_REG); | ||
136 | chip->deadlock_avoid_type_reg = | ||
137 | ioread32(p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG); | ||
138 | chip->intpin_reg_wpermit_reg0 = | ||
139 | ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0); | ||
140 | chip->intpin_reg_wpermit_reg1 = | ||
141 | ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1); | ||
142 | chip->intpin_reg_wpermit_reg2 = | ||
143 | ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2); | ||
144 | chip->intpin_reg_wpermit_reg3 = | ||
145 | ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3); | ||
146 | dev_dbg(&pdev->dev, "%s : " | ||
147 | "chip->phub_id_reg=%x, " | ||
148 | "chip->q_pri_val_reg=%x, " | ||
149 | "chip->rc_q_maxsize_reg=%x, " | ||
150 | "chip->bri_q_maxsize_reg=%x, " | ||
151 | "chip->comp_resp_timeout_reg=%x, " | ||
152 | "chip->bus_slave_control_reg=%x, " | ||
153 | "chip->deadlock_avoid_type_reg=%x, " | ||
154 | "chip->intpin_reg_wpermit_reg0=%x, " | ||
155 | "chip->intpin_reg_wpermit_reg1=%x, " | ||
156 | "chip->intpin_reg_wpermit_reg2=%x, " | ||
157 | "chip->intpin_reg_wpermit_reg3=%x\n", __func__, | ||
158 | chip->phub_id_reg, | ||
159 | chip->q_pri_val_reg, | ||
160 | chip->rc_q_maxsize_reg, | ||
161 | chip->bri_q_maxsize_reg, | ||
162 | chip->comp_resp_timeout_reg, | ||
163 | chip->bus_slave_control_reg, | ||
164 | chip->deadlock_avoid_type_reg, | ||
165 | chip->intpin_reg_wpermit_reg0, | ||
166 | chip->intpin_reg_wpermit_reg1, | ||
167 | chip->intpin_reg_wpermit_reg2, | ||
168 | chip->intpin_reg_wpermit_reg3); | ||
169 | for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) { | ||
170 | chip->int_reduce_control_reg[i] = | ||
171 | ioread32(p + PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i); | ||
172 | dev_dbg(&pdev->dev, "%s : " | ||
173 | "chip->int_reduce_control_reg[%d]=%x\n", | ||
174 | __func__, i, chip->int_reduce_control_reg[i]); | ||
175 | } | ||
176 | chip->clkcfg_reg = ioread32(p + CLKCFG_REG_OFFSET); | ||
177 | } | ||
178 | |||
179 | /* pch_phub_restore_reg_conf - restore register configuration */ | ||
180 | static void pch_phub_restore_reg_conf(struct pci_dev *pdev) | ||
181 | { | ||
182 | unsigned int i; | ||
183 | struct pch_phub_reg *chip = pci_get_drvdata(pdev); | ||
184 | void __iomem *p; | ||
185 | p = chip->pch_phub_base_address; | ||
186 | |||
187 | iowrite32(chip->phub_id_reg, p + PCH_PHUB_ID_REG); | ||
188 | iowrite32(chip->q_pri_val_reg, p + PCH_PHUB_QUEUE_PRI_VAL_REG); | ||
189 | iowrite32(chip->rc_q_maxsize_reg, p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG); | ||
190 | iowrite32(chip->bri_q_maxsize_reg, p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG); | ||
191 | iowrite32(chip->comp_resp_timeout_reg, | ||
192 | p + PCH_PHUB_COMP_RESP_TIMEOUT_REG); | ||
193 | iowrite32(chip->bus_slave_control_reg, | ||
194 | p + PCH_PHUB_BUS_SLAVE_CONTROL_REG); | ||
195 | iowrite32(chip->deadlock_avoid_type_reg, | ||
196 | p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG); | ||
197 | iowrite32(chip->intpin_reg_wpermit_reg0, | ||
198 | p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0); | ||
199 | iowrite32(chip->intpin_reg_wpermit_reg1, | ||
200 | p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1); | ||
201 | iowrite32(chip->intpin_reg_wpermit_reg2, | ||
202 | p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2); | ||
203 | iowrite32(chip->intpin_reg_wpermit_reg3, | ||
204 | p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3); | ||
205 | dev_dbg(&pdev->dev, "%s : " | ||
206 | "chip->phub_id_reg=%x, " | ||
207 | "chip->q_pri_val_reg=%x, " | ||
208 | "chip->rc_q_maxsize_reg=%x, " | ||
209 | "chip->bri_q_maxsize_reg=%x, " | ||
210 | "chip->comp_resp_timeout_reg=%x, " | ||
211 | "chip->bus_slave_control_reg=%x, " | ||
212 | "chip->deadlock_avoid_type_reg=%x, " | ||
213 | "chip->intpin_reg_wpermit_reg0=%x, " | ||
214 | "chip->intpin_reg_wpermit_reg1=%x, " | ||
215 | "chip->intpin_reg_wpermit_reg2=%x, " | ||
216 | "chip->intpin_reg_wpermit_reg3=%x\n", __func__, | ||
217 | chip->phub_id_reg, | ||
218 | chip->q_pri_val_reg, | ||
219 | chip->rc_q_maxsize_reg, | ||
220 | chip->bri_q_maxsize_reg, | ||
221 | chip->comp_resp_timeout_reg, | ||
222 | chip->bus_slave_control_reg, | ||
223 | chip->deadlock_avoid_type_reg, | ||
224 | chip->intpin_reg_wpermit_reg0, | ||
225 | chip->intpin_reg_wpermit_reg1, | ||
226 | chip->intpin_reg_wpermit_reg2, | ||
227 | chip->intpin_reg_wpermit_reg3); | ||
228 | for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) { | ||
229 | iowrite32(chip->int_reduce_control_reg[i], | ||
230 | p + PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i); | ||
231 | dev_dbg(&pdev->dev, "%s : " | ||
232 | "chip->int_reduce_control_reg[%d]=%x\n", | ||
233 | __func__, i, chip->int_reduce_control_reg[i]); | ||
234 | } | ||
235 | |||
236 | iowrite32(chip->clkcfg_reg, p + CLKCFG_REG_OFFSET); | ||
237 | } | ||
238 | |||
239 | /** | ||
240 | * pch_phub_read_serial_rom() - Reading Serial ROM | ||
241 | * @offset_address: Serial ROM offset address to read. | ||
242 | * @data: Read buffer for specified Serial ROM value. | ||
243 | */ | ||
244 | static void pch_phub_read_serial_rom(struct pch_phub_reg *chip, | ||
245 | unsigned int offset_address, u8 *data) | ||
246 | { | ||
247 | void __iomem *mem_addr = chip->pch_phub_extrom_base_address + | ||
248 | offset_address; | ||
249 | |||
250 | *data = ioread8(mem_addr); | ||
251 | } | ||
252 | |||
253 | /** | ||
254 | * pch_phub_write_serial_rom() - Writing Serial ROM | ||
255 | * @offset_address: Serial ROM offset address. | ||
256 | * @data: Serial ROM value to write. | ||
257 | */ | ||
258 | static int pch_phub_write_serial_rom(struct pch_phub_reg *chip, | ||
259 | unsigned int offset_address, u8 data) | ||
260 | { | ||
261 | void __iomem *mem_addr = chip->pch_phub_extrom_base_address + | ||
262 | (offset_address & PCH_WORD_ADDR_MASK); | ||
263 | int i; | ||
264 | unsigned int word_data; | ||
265 | unsigned int pos; | ||
266 | unsigned int mask; | ||
267 | pos = (offset_address % 4) * 8; | ||
268 | mask = ~(0xFF << pos); | ||
269 | |||
270 | iowrite32(PCH_PHUB_ROM_WRITE_ENABLE, | ||
271 | chip->pch_phub_extrom_base_address + PHUB_CONTROL); | ||
272 | |||
273 | word_data = ioread32(mem_addr); | ||
274 | iowrite32((word_data & mask) | (u32)data << pos, mem_addr); | ||
275 | |||
276 | i = 0; | ||
277 | while (ioread8(chip->pch_phub_extrom_base_address + | ||
278 | PHUB_STATUS) != 0x00) { | ||
279 | msleep(1); | ||
280 | if (i == PHUB_TIMEOUT) | ||
281 | return -ETIMEDOUT; | ||
282 | i++; | ||
283 | } | ||
284 | |||
285 | iowrite32(PCH_PHUB_ROM_WRITE_DISABLE, | ||
286 | chip->pch_phub_extrom_base_address + PHUB_CONTROL); | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | /** | ||
292 | * pch_phub_read_serial_rom_val() - Read Serial ROM value | ||
293 | * @offset_address: Serial ROM address offset value. | ||
294 | * @data: Serial ROM value to read. | ||
295 | */ | ||
296 | static void pch_phub_read_serial_rom_val(struct pch_phub_reg *chip, | ||
297 | unsigned int offset_address, u8 *data) | ||
298 | { | ||
299 | unsigned int mem_addr; | ||
300 | |||
301 | mem_addr = PCH_PHUB_ROM_START_ADDR + | ||
302 | pch_phub_mac_offset[offset_address]; | ||
303 | |||
304 | pch_phub_read_serial_rom(chip, mem_addr, data); | ||
305 | } | ||
306 | |||
307 | /** | ||
308 | * pch_phub_write_serial_rom_val() - writing Serial ROM value | ||
309 | * @offset_address: Serial ROM address offset value. | ||
310 | * @data: Serial ROM value. | ||
311 | */ | ||
312 | static int pch_phub_write_serial_rom_val(struct pch_phub_reg *chip, | ||
313 | unsigned int offset_address, u8 data) | ||
314 | { | ||
315 | int retval; | ||
316 | unsigned int mem_addr; | ||
317 | |||
318 | mem_addr = PCH_PHUB_ROM_START_ADDR + | ||
319 | pch_phub_mac_offset[offset_address]; | ||
320 | |||
321 | retval = pch_phub_write_serial_rom(chip, mem_addr, data); | ||
322 | |||
323 | return retval; | ||
324 | } | ||
325 | |||
326 | /* pch_phub_gbe_serial_rom_conf - makes Serial ROM header format configuration | ||
327 | * for Gigabit Ethernet MAC address | ||
328 | */ | ||
329 | static int pch_phub_gbe_serial_rom_conf(struct pch_phub_reg *chip) | ||
330 | { | ||
331 | int retval; | ||
332 | |||
333 | retval = pch_phub_write_serial_rom(chip, 0x0b, 0xbc); | ||
334 | retval |= pch_phub_write_serial_rom(chip, 0x0a, 0x10); | ||
335 | retval |= pch_phub_write_serial_rom(chip, 0x09, 0x01); | ||
336 | retval |= pch_phub_write_serial_rom(chip, 0x08, 0x02); | ||
337 | |||
338 | retval |= pch_phub_write_serial_rom(chip, 0x0f, 0x00); | ||
339 | retval |= pch_phub_write_serial_rom(chip, 0x0e, 0x00); | ||
340 | retval |= pch_phub_write_serial_rom(chip, 0x0d, 0x00); | ||
341 | retval |= pch_phub_write_serial_rom(chip, 0x0c, 0x80); | ||
342 | |||
343 | retval |= pch_phub_write_serial_rom(chip, 0x13, 0xbc); | ||
344 | retval |= pch_phub_write_serial_rom(chip, 0x12, 0x10); | ||
345 | retval |= pch_phub_write_serial_rom(chip, 0x11, 0x01); | ||
346 | retval |= pch_phub_write_serial_rom(chip, 0x10, 0x18); | ||
347 | |||
348 | retval |= pch_phub_write_serial_rom(chip, 0x1b, 0xbc); | ||
349 | retval |= pch_phub_write_serial_rom(chip, 0x1a, 0x10); | ||
350 | retval |= pch_phub_write_serial_rom(chip, 0x19, 0x01); | ||
351 | retval |= pch_phub_write_serial_rom(chip, 0x18, 0x19); | ||
352 | |||
353 | retval |= pch_phub_write_serial_rom(chip, 0x23, 0xbc); | ||
354 | retval |= pch_phub_write_serial_rom(chip, 0x22, 0x10); | ||
355 | retval |= pch_phub_write_serial_rom(chip, 0x21, 0x01); | ||
356 | retval |= pch_phub_write_serial_rom(chip, 0x20, 0x3a); | ||
357 | |||
358 | retval |= pch_phub_write_serial_rom(chip, 0x27, 0x01); | ||
359 | retval |= pch_phub_write_serial_rom(chip, 0x26, 0x00); | ||
360 | retval |= pch_phub_write_serial_rom(chip, 0x25, 0x00); | ||
361 | retval |= pch_phub_write_serial_rom(chip, 0x24, 0x00); | ||
362 | |||
363 | return retval; | ||
364 | } | ||
365 | |||
366 | /** | ||
367 | * pch_phub_read_gbe_mac_addr() - Read Gigabit Ethernet MAC address | ||
368 | * @offset_address: Gigabit Ethernet MAC address offset value. | ||
369 | * @data: Buffer of the Gigabit Ethernet MAC address value. | ||
370 | */ | ||
371 | static void pch_phub_read_gbe_mac_addr(struct pch_phub_reg *chip, u8 *data) | ||
372 | { | ||
373 | int i; | ||
374 | for (i = 0; i < ETH_ALEN; i++) | ||
375 | pch_phub_read_serial_rom_val(chip, i, &data[i]); | ||
376 | } | ||
377 | |||
378 | /** | ||
379 | * pch_phub_write_gbe_mac_addr() - Write MAC address | ||
380 | * @offset_address: Gigabit Ethernet MAC address offset value. | ||
381 | * @data: Gigabit Ethernet MAC address value. | ||
382 | */ | ||
383 | static int pch_phub_write_gbe_mac_addr(struct pch_phub_reg *chip, u8 *data) | ||
384 | { | ||
385 | int retval; | ||
386 | int i; | ||
387 | |||
388 | retval = pch_phub_gbe_serial_rom_conf(chip); | ||
389 | if (retval) | ||
390 | return retval; | ||
391 | |||
392 | for (i = 0; i < ETH_ALEN; i++) { | ||
393 | retval = pch_phub_write_serial_rom_val(chip, i, data[i]); | ||
394 | if (retval) | ||
395 | return retval; | ||
396 | } | ||
397 | |||
398 | return retval; | ||
399 | } | ||
400 | |||
401 | static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj, | ||
402 | struct bin_attribute *attr, char *buf, | ||
403 | loff_t off, size_t count) | ||
404 | { | ||
405 | unsigned int rom_signature; | ||
406 | unsigned char rom_length; | ||
407 | unsigned int tmp; | ||
408 | unsigned int addr_offset; | ||
409 | unsigned int orom_size; | ||
410 | int ret; | ||
411 | int err; | ||
412 | |||
413 | struct pch_phub_reg *chip = | ||
414 | dev_get_drvdata(container_of(kobj, struct device, kobj)); | ||
415 | |||
416 | ret = mutex_lock_interruptible(&pch_phub_mutex); | ||
417 | if (ret) { | ||
418 | err = -ERESTARTSYS; | ||
419 | goto return_err_nomutex; | ||
420 | } | ||
421 | |||
422 | /* Get Rom signature */ | ||
423 | pch_phub_read_serial_rom(chip, 0x80, (unsigned char *)&rom_signature); | ||
424 | rom_signature &= 0xff; | ||
425 | pch_phub_read_serial_rom(chip, 0x81, (unsigned char *)&tmp); | ||
426 | rom_signature |= (tmp & 0xff) << 8; | ||
427 | if (rom_signature == 0xAA55) { | ||
428 | pch_phub_read_serial_rom(chip, 0x82, &rom_length); | ||
429 | orom_size = rom_length * 512; | ||
430 | if (orom_size < off) { | ||
431 | addr_offset = 0; | ||
432 | goto return_ok; | ||
433 | } | ||
434 | if (orom_size < count) { | ||
435 | addr_offset = 0; | ||
436 | goto return_ok; | ||
437 | } | ||
438 | |||
439 | for (addr_offset = 0; addr_offset < count; addr_offset++) { | ||
440 | pch_phub_read_serial_rom(chip, 0x80 + addr_offset + off, | ||
441 | &buf[addr_offset]); | ||
442 | } | ||
443 | } else { | ||
444 | err = -ENODATA; | ||
445 | goto return_err; | ||
446 | } | ||
447 | return_ok: | ||
448 | mutex_unlock(&pch_phub_mutex); | ||
449 | return addr_offset; | ||
450 | |||
451 | return_err: | ||
452 | mutex_unlock(&pch_phub_mutex); | ||
453 | return_err_nomutex: | ||
454 | return err; | ||
455 | } | ||
456 | |||
457 | static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj, | ||
458 | struct bin_attribute *attr, | ||
459 | char *buf, loff_t off, size_t count) | ||
460 | { | ||
461 | int err; | ||
462 | unsigned int addr_offset; | ||
463 | int ret; | ||
464 | struct pch_phub_reg *chip = | ||
465 | dev_get_drvdata(container_of(kobj, struct device, kobj)); | ||
466 | |||
467 | ret = mutex_lock_interruptible(&pch_phub_mutex); | ||
468 | if (ret) | ||
469 | return -ERESTARTSYS; | ||
470 | |||
471 | if (off > PCH_PHUB_OROM_SIZE) { | ||
472 | addr_offset = 0; | ||
473 | goto return_ok; | ||
474 | } | ||
475 | if (count > PCH_PHUB_OROM_SIZE) { | ||
476 | addr_offset = 0; | ||
477 | goto return_ok; | ||
478 | } | ||
479 | |||
480 | for (addr_offset = 0; addr_offset < count; addr_offset++) { | ||
481 | if (PCH_PHUB_OROM_SIZE < off + addr_offset) | ||
482 | goto return_ok; | ||
483 | |||
484 | ret = pch_phub_write_serial_rom(chip, 0x80 + addr_offset + off, | ||
485 | buf[addr_offset]); | ||
486 | if (ret) { | ||
487 | err = ret; | ||
488 | goto return_err; | ||
489 | } | ||
490 | } | ||
491 | |||
492 | return_ok: | ||
493 | mutex_unlock(&pch_phub_mutex); | ||
494 | return addr_offset; | ||
495 | |||
496 | return_err: | ||
497 | mutex_unlock(&pch_phub_mutex); | ||
498 | return err; | ||
499 | } | ||
500 | |||
501 | static ssize_t show_pch_mac(struct device *dev, struct device_attribute *attr, | ||
502 | char *buf) | ||
503 | { | ||
504 | u8 mac[8]; | ||
505 | struct pch_phub_reg *chip = dev_get_drvdata(dev); | ||
506 | |||
507 | pch_phub_read_gbe_mac_addr(chip, mac); | ||
508 | |||
509 | return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
510 | mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); | ||
511 | } | ||
512 | |||
513 | static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr, | ||
514 | const char *buf, size_t count) | ||
515 | { | ||
516 | u8 mac[6]; | ||
517 | struct pch_phub_reg *chip = dev_get_drvdata(dev); | ||
518 | |||
519 | if (count != 18) | ||
520 | return -EINVAL; | ||
521 | |||
522 | sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", | ||
523 | (u32 *)&mac[0], (u32 *)&mac[1], (u32 *)&mac[2], (u32 *)&mac[3], | ||
524 | (u32 *)&mac[4], (u32 *)&mac[5]); | ||
525 | |||
526 | pch_phub_write_gbe_mac_addr(chip, mac); | ||
527 | |||
528 | return count; | ||
529 | } | ||
530 | |||
531 | static DEVICE_ATTR(pch_mac, S_IRUGO | S_IWUSR, show_pch_mac, store_pch_mac); | ||
532 | |||
533 | static struct bin_attribute pch_bin_attr = { | ||
534 | .attr = { | ||
535 | .name = "pch_firmware", | ||
536 | .mode = S_IRUGO | S_IWUSR, | ||
537 | }, | ||
538 | .size = PCH_PHUB_OROM_SIZE + 1, | ||
539 | .read = pch_phub_bin_read, | ||
540 | .write = pch_phub_bin_write, | ||
541 | }; | ||
542 | |||
543 | static int __devinit pch_phub_probe(struct pci_dev *pdev, | ||
544 | const struct pci_device_id *id) | ||
545 | { | ||
546 | int retval; | ||
547 | |||
548 | int ret; | ||
549 | ssize_t rom_size; | ||
550 | struct pch_phub_reg *chip; | ||
551 | |||
552 | chip = kzalloc(sizeof(struct pch_phub_reg), GFP_KERNEL); | ||
553 | if (chip == NULL) | ||
554 | return -ENOMEM; | ||
555 | |||
556 | ret = pci_enable_device(pdev); | ||
557 | if (ret) { | ||
558 | dev_err(&pdev->dev, | ||
559 | "%s : pci_enable_device FAILED(ret=%d)", __func__, ret); | ||
560 | goto err_pci_enable_dev; | ||
561 | } | ||
562 | dev_dbg(&pdev->dev, "%s : pci_enable_device returns %d\n", __func__, | ||
563 | ret); | ||
564 | |||
565 | ret = pci_request_regions(pdev, KBUILD_MODNAME); | ||
566 | if (ret) { | ||
567 | dev_err(&pdev->dev, | ||
568 | "%s : pci_request_regions FAILED(ret=%d)", __func__, ret); | ||
569 | goto err_req_regions; | ||
570 | } | ||
571 | dev_dbg(&pdev->dev, "%s : " | ||
572 | "pci_request_regions returns %d\n", __func__, ret); | ||
573 | |||
574 | chip->pch_phub_base_address = pci_iomap(pdev, 1, 0); | ||
575 | |||
576 | |||
577 | if (chip->pch_phub_base_address == 0) { | ||
578 | dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__); | ||
579 | ret = -ENOMEM; | ||
580 | goto err_pci_iomap; | ||
581 | } | ||
582 | dev_dbg(&pdev->dev, "%s : pci_iomap SUCCESS and value " | ||
583 | "in pch_phub_base_address variable is %p\n", __func__, | ||
584 | chip->pch_phub_base_address); | ||
585 | chip->pch_phub_extrom_base_address = pci_map_rom(pdev, &rom_size); | ||
586 | |||
587 | if (chip->pch_phub_extrom_base_address == 0) { | ||
588 | dev_err(&pdev->dev, "%s : pci_map_rom FAILED", __func__); | ||
589 | ret = -ENOMEM; | ||
590 | goto err_pci_map; | ||
591 | } | ||
592 | dev_dbg(&pdev->dev, "%s : " | ||
593 | "pci_map_rom SUCCESS and value in " | ||
594 | "pch_phub_extrom_base_address variable is %p\n", __func__, | ||
595 | chip->pch_phub_extrom_base_address); | ||
596 | |||
597 | pci_set_drvdata(pdev, chip); | ||
598 | |||
599 | retval = sysfs_create_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr); | ||
600 | if (retval) | ||
601 | goto err_sysfs_create; | ||
602 | |||
603 | retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); | ||
604 | if (retval) | ||
605 | goto exit_bin_attr; | ||
606 | |||
607 | pch_phub_read_modify_write_reg(chip, (unsigned int)CLKCFG_REG_OFFSET, | ||
608 | CLKCFG_CAN_50MHZ, CLKCFG_CANCLK_MASK); | ||
609 | |||
610 | /* set the prefech value */ | ||
611 | iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14); | ||
612 | /* set the interrupt delay value */ | ||
613 | iowrite32(0x25, chip->pch_phub_base_address + 0x44); | ||
614 | |||
615 | return 0; | ||
616 | exit_bin_attr: | ||
617 | sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr); | ||
618 | |||
619 | err_sysfs_create: | ||
620 | pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address); | ||
621 | err_pci_map: | ||
622 | pci_iounmap(pdev, chip->pch_phub_base_address); | ||
623 | err_pci_iomap: | ||
624 | pci_release_regions(pdev); | ||
625 | err_req_regions: | ||
626 | pci_disable_device(pdev); | ||
627 | err_pci_enable_dev: | ||
628 | kfree(chip); | ||
629 | dev_err(&pdev->dev, "%s returns %d\n", __func__, ret); | ||
630 | return ret; | ||
631 | } | ||
632 | |||
633 | static void __devexit pch_phub_remove(struct pci_dev *pdev) | ||
634 | { | ||
635 | struct pch_phub_reg *chip = pci_get_drvdata(pdev); | ||
636 | |||
637 | sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr); | ||
638 | sysfs_remove_bin_file(&pdev->dev.kobj, &pch_bin_attr); | ||
639 | pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address); | ||
640 | pci_iounmap(pdev, chip->pch_phub_base_address); | ||
641 | pci_release_regions(pdev); | ||
642 | pci_disable_device(pdev); | ||
643 | kfree(chip); | ||
644 | } | ||
645 | |||
646 | #ifdef CONFIG_PM | ||
647 | |||
648 | static int pch_phub_suspend(struct pci_dev *pdev, pm_message_t state) | ||
649 | { | ||
650 | int ret; | ||
651 | |||
652 | pch_phub_save_reg_conf(pdev); | ||
653 | ret = pci_save_state(pdev); | ||
654 | if (ret) { | ||
655 | dev_err(&pdev->dev, | ||
656 | " %s -pci_save_state returns %d\n", __func__, ret); | ||
657 | return ret; | ||
658 | } | ||
659 | pci_enable_wake(pdev, PCI_D3hot, 0); | ||
660 | pci_disable_device(pdev); | ||
661 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
662 | |||
663 | return 0; | ||
664 | } | ||
665 | |||
666 | static int pch_phub_resume(struct pci_dev *pdev) | ||
667 | { | ||
668 | int ret; | ||
669 | |||
670 | pci_set_power_state(pdev, PCI_D0); | ||
671 | pci_restore_state(pdev); | ||
672 | ret = pci_enable_device(pdev); | ||
673 | if (ret) { | ||
674 | dev_err(&pdev->dev, | ||
675 | "%s-pci_enable_device failed(ret=%d) ", __func__, ret); | ||
676 | return ret; | ||
677 | } | ||
678 | |||
679 | pci_enable_wake(pdev, PCI_D3hot, 0); | ||
680 | pch_phub_restore_reg_conf(pdev); | ||
681 | |||
682 | return 0; | ||
683 | } | ||
684 | #else | ||
685 | #define pch_phub_suspend NULL | ||
686 | #define pch_phub_resume NULL | ||
687 | #endif /* CONFIG_PM */ | ||
688 | |||
689 | static struct pci_device_id pch_phub_pcidev_id[] = { | ||
690 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH1_PHUB)}, | ||
691 | {0,} | ||
692 | }; | ||
693 | |||
694 | static struct pci_driver pch_phub_driver = { | ||
695 | .name = "pch_phub", | ||
696 | .id_table = pch_phub_pcidev_id, | ||
697 | .probe = pch_phub_probe, | ||
698 | .remove = __devexit_p(pch_phub_remove), | ||
699 | .suspend = pch_phub_suspend, | ||
700 | .resume = pch_phub_resume | ||
701 | }; | ||
702 | |||
703 | static int __init pch_phub_pci_init(void) | ||
704 | { | ||
705 | return pci_register_driver(&pch_phub_driver); | ||
706 | } | ||
707 | |||
708 | static void __exit pch_phub_pci_exit(void) | ||
709 | { | ||
710 | pci_unregister_driver(&pch_phub_driver); | ||
711 | } | ||
712 | |||
713 | module_init(pch_phub_pci_init); | ||
714 | module_exit(pch_phub_pci_exit); | ||
715 | |||
716 | MODULE_DESCRIPTION("PCH Packet Hub PCI Driver"); | ||
717 | MODULE_LICENSE("GPL"); | ||