aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorMasayuki Ohtak <masa-korg@dsn.okisemi.com>2010-09-01 08:16:30 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-10-22 13:16:42 -0400
commitcf4ece53460c64a04a643ef13f6b6cb4bf3a8342 (patch)
tree832441822810fddd690f150044d9b18ce32e758f /drivers/misc
parentc64a0926710153b9d44c979d2942f4a8648fd74e (diff)
add Packet hub driver for Topcliff Platform controller hub
Packet hub driver of Topcliff PCH Topcliff PCH is the platform controller hub that is going to be used in Intel's upcoming general embedded platform. All IO peripherals in Topcliff PCH are actually devices sitting on AMBA bus. Packet hub is a special converter device in Topcliff PCH that translate AMBA transactions to PCI Express transactions and vice versa. Thus packet hub helps present all IO peripherals in Topcliff PCH as PCIE devices to IA system. Topcliff PCH has MAC address and Option ROM data. These data are in SROM which is connected to PCIE bus. Packet hub driver of Topcliff PCH can access MAC address and Option ROM data in SROM via sysfs interface. Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/Kconfig12
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/pch_phub.c717
3 files changed, 730 insertions, 0 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index b74331260744..6f46e27ed682 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -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
393config 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
393source "drivers/misc/c2port/Kconfig" 405source "drivers/misc/c2port/Kconfig"
394source "drivers/misc/eeprom/Kconfig" 406source "drivers/misc/eeprom/Kconfig"
395source "drivers/misc/cb710/Kconfig" 407source "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/
35obj-y += cb710/ 35obj-y += cb710/
36obj-$(CONFIG_VMWARE_BALLOON) += vmw_balloon.o 36obj-$(CONFIG_VMWARE_BALLOON) += vmw_balloon.o
37obj-$(CONFIG_ARM_CHARLCD) += arm-charlcd.o 37obj-$(CONFIG_ARM_CHARLCD) += arm-charlcd.o
38obj-$(CONFIG_PCH_PHUB) += pch_phub.o
diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c
new file mode 100644
index 000000000000..ed56e4f91fa0
--- /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 */
83struct 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 */
102static const int pch_phub_mac_offset[ETH_ALEN] = {0x3, 0x2, 0x1, 0x0, 0xb, 0xa};
103
104static 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 */
112static 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 */
121static 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 */
180static 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 */
244static 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 */
258static 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 */
296static 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 */
312static 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 */
329static 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 */
371static 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 */
383static 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
401static 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 }
447return_ok:
448 mutex_unlock(&pch_phub_mutex);
449 return addr_offset;
450
451return_err:
452 mutex_unlock(&pch_phub_mutex);
453return_err_nomutex:
454 return err;
455}
456
457static 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
492return_ok:
493 mutex_unlock(&pch_phub_mutex);
494 return addr_offset;
495
496return_err:
497 mutex_unlock(&pch_phub_mutex);
498 return err;
499}
500
501static 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
513static 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
531static DEVICE_ATTR(pch_mac, S_IRUGO | S_IWUSR, show_pch_mac, store_pch_mac);
532
533static 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
543static 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 unsigned int 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 0x%08x\n", __func__,
584 (unsigned int)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 0x%08x\n", __func__,
595 (unsigned int)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;
616exit_bin_attr:
617 sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
618
619err_sysfs_create:
620 pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);
621err_pci_map:
622 pci_iounmap(pdev, chip->pch_phub_base_address);
623err_pci_iomap:
624 pci_release_regions(pdev);
625err_req_regions:
626 pci_disable_device(pdev);
627err_pci_enable_dev:
628 kfree(chip);
629 dev_err(&pdev->dev, "%s returns %d\n", __func__, ret);
630 return ret;
631}
632
633static 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
648static 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
666static 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
689static struct pci_device_id pch_phub_pcidev_id[] = {
690 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH1_PHUB)},
691 {0,}
692};
693
694static 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
703static int __init pch_phub_pci_init(void)
704{
705 return pci_register_driver(&pch_phub_driver);
706}
707
708static void __exit pch_phub_pci_exit(void)
709{
710 pci_unregister_driver(&pch_phub_driver);
711}
712
713module_init(pch_phub_pci_init);
714module_exit(pch_phub_pci_exit);
715
716MODULE_DESCRIPTION("PCH Packet Hub PCI Driver");
717MODULE_LICENSE("GPL");