diff options
Diffstat (limited to 'drivers/misc/pch_phub.c')
-rw-r--r-- | drivers/misc/pch_phub.c | 153 |
1 files changed, 129 insertions, 24 deletions
diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c index a19cb710a246..5fe79df44838 100644 --- a/drivers/misc/pch_phub.c +++ b/drivers/misc/pch_phub.c | |||
@@ -34,12 +34,18 @@ | |||
34 | #define PHUB_TIMEOUT 0x05 /* Time out value for Status Register */ | 34 | #define PHUB_TIMEOUT 0x05 /* Time out value for Status Register */ |
35 | #define PCH_PHUB_ROM_WRITE_ENABLE 0x01 /* Enabling for writing ROM */ | 35 | #define PCH_PHUB_ROM_WRITE_ENABLE 0x01 /* Enabling for writing ROM */ |
36 | #define PCH_PHUB_ROM_WRITE_DISABLE 0x00 /* Disabling for writing ROM */ | 36 | #define PCH_PHUB_ROM_WRITE_DISABLE 0x00 /* Disabling for writing ROM */ |
37 | #define PCH_PHUB_MAC_START_ADDR 0x20C /* MAC data area start address offset */ | 37 | #define PCH_PHUB_MAC_START_ADDR_EG20T 0x14 /* MAC data area start address |
38 | #define PCH_PHUB_ROM_START_ADDR_EG20T 0x14 /* ROM data area start address offset | 38 | offset */ |
39 | #define PCH_PHUB_MAC_START_ADDR_ML7223 0x20C /* MAC data area start address | ||
40 | offset */ | ||
41 | #define PCH_PHUB_ROM_START_ADDR_EG20T 0x80 /* ROM data area start address offset | ||
39 | (Intel EG20T PCH)*/ | 42 | (Intel EG20T PCH)*/ |
40 | #define PCH_PHUB_ROM_START_ADDR_ML7213 0x400 /* ROM data area start address | 43 | #define PCH_PHUB_ROM_START_ADDR_ML7213 0x400 /* ROM data area start address |
41 | offset(OKI SEMICONDUCTOR ML7213) | 44 | offset(OKI SEMICONDUCTOR ML7213) |
42 | */ | 45 | */ |
46 | #define PCH_PHUB_ROM_START_ADDR_ML7223 0x400 /* ROM data area start address | ||
47 | offset(OKI SEMICONDUCTOR ML7223) | ||
48 | */ | ||
43 | 49 | ||
44 | /* MAX number of INT_REDUCE_CONTROL registers */ | 50 | /* MAX number of INT_REDUCE_CONTROL registers */ |
45 | #define MAX_NUM_INT_REDUCE_CONTROL_REG 128 | 51 | #define MAX_NUM_INT_REDUCE_CONTROL_REG 128 |
@@ -63,6 +69,10 @@ | |||
63 | #define PCI_VENDOR_ID_ROHM 0x10db | 69 | #define PCI_VENDOR_ID_ROHM 0x10db |
64 | #define PCI_DEVICE_ID_ROHM_ML7213_PHUB 0x801A | 70 | #define PCI_DEVICE_ID_ROHM_ML7213_PHUB 0x801A |
65 | 71 | ||
72 | /* Macros for ML7223 */ | ||
73 | #define PCI_DEVICE_ID_ROHM_ML7223_mPHUB 0x8012 /* for Bus-m */ | ||
74 | #define PCI_DEVICE_ID_ROHM_ML7223_nPHUB 0x8002 /* for Bus-n */ | ||
75 | |||
66 | /* SROM ACCESS Macro */ | 76 | /* SROM ACCESS Macro */ |
67 | #define PCH_WORD_ADDR_MASK (~((1 << 2) - 1)) | 77 | #define PCH_WORD_ADDR_MASK (~((1 << 2) - 1)) |
68 | 78 | ||
@@ -100,6 +110,9 @@ | |||
100 | * @clkcfg_reg: CLK CFG register val | 110 | * @clkcfg_reg: CLK CFG register val |
101 | * @pch_phub_base_address: Register base address | 111 | * @pch_phub_base_address: Register base address |
102 | * @pch_phub_extrom_base_address: external rom base address | 112 | * @pch_phub_extrom_base_address: external rom base address |
113 | * @pch_mac_start_address: MAC address area start address | ||
114 | * @pch_opt_rom_start_address: Option ROM start address | ||
115 | * @ioh_type: Save IOH type | ||
103 | */ | 116 | */ |
104 | struct pch_phub_reg { | 117 | struct pch_phub_reg { |
105 | u32 phub_id_reg; | 118 | u32 phub_id_reg; |
@@ -117,6 +130,9 @@ struct pch_phub_reg { | |||
117 | u32 clkcfg_reg; | 130 | u32 clkcfg_reg; |
118 | void __iomem *pch_phub_base_address; | 131 | void __iomem *pch_phub_base_address; |
119 | void __iomem *pch_phub_extrom_base_address; | 132 | void __iomem *pch_phub_extrom_base_address; |
133 | u32 pch_mac_start_address; | ||
134 | u32 pch_opt_rom_start_address; | ||
135 | int ioh_type; | ||
120 | }; | 136 | }; |
121 | 137 | ||
122 | /* SROM SPEC for MAC address assignment offset */ | 138 | /* SROM SPEC for MAC address assignment offset */ |
@@ -319,7 +335,7 @@ static void pch_phub_read_serial_rom_val(struct pch_phub_reg *chip, | |||
319 | { | 335 | { |
320 | unsigned int mem_addr; | 336 | unsigned int mem_addr; |
321 | 337 | ||
322 | mem_addr = PCH_PHUB_ROM_START_ADDR_EG20T + | 338 | mem_addr = chip->pch_mac_start_address + |
323 | pch_phub_mac_offset[offset_address]; | 339 | pch_phub_mac_offset[offset_address]; |
324 | 340 | ||
325 | pch_phub_read_serial_rom(chip, mem_addr, data); | 341 | pch_phub_read_serial_rom(chip, mem_addr, data); |
@@ -336,7 +352,7 @@ static int pch_phub_write_serial_rom_val(struct pch_phub_reg *chip, | |||
336 | int retval; | 352 | int retval; |
337 | unsigned int mem_addr; | 353 | unsigned int mem_addr; |
338 | 354 | ||
339 | mem_addr = PCH_PHUB_ROM_START_ADDR_EG20T + | 355 | mem_addr = chip->pch_mac_start_address + |
340 | pch_phub_mac_offset[offset_address]; | 356 | pch_phub_mac_offset[offset_address]; |
341 | 357 | ||
342 | retval = pch_phub_write_serial_rom(chip, mem_addr, data); | 358 | retval = pch_phub_write_serial_rom(chip, mem_addr, data); |
@@ -384,6 +400,48 @@ static int pch_phub_gbe_serial_rom_conf(struct pch_phub_reg *chip) | |||
384 | return retval; | 400 | return retval; |
385 | } | 401 | } |
386 | 402 | ||
403 | /* pch_phub_gbe_serial_rom_conf_mp - makes SerialROM header format configuration | ||
404 | * for Gigabit Ethernet MAC address | ||
405 | */ | ||
406 | static int pch_phub_gbe_serial_rom_conf_mp(struct pch_phub_reg *chip) | ||
407 | { | ||
408 | int retval; | ||
409 | u32 offset_addr; | ||
410 | |||
411 | offset_addr = 0x200; | ||
412 | retval = pch_phub_write_serial_rom(chip, 0x03 + offset_addr, 0xbc); | ||
413 | retval |= pch_phub_write_serial_rom(chip, 0x02 + offset_addr, 0x00); | ||
414 | retval |= pch_phub_write_serial_rom(chip, 0x01 + offset_addr, 0x40); | ||
415 | retval |= pch_phub_write_serial_rom(chip, 0x00 + offset_addr, 0x02); | ||
416 | |||
417 | retval |= pch_phub_write_serial_rom(chip, 0x07 + offset_addr, 0x00); | ||
418 | retval |= pch_phub_write_serial_rom(chip, 0x06 + offset_addr, 0x00); | ||
419 | retval |= pch_phub_write_serial_rom(chip, 0x05 + offset_addr, 0x00); | ||
420 | retval |= pch_phub_write_serial_rom(chip, 0x04 + offset_addr, 0x80); | ||
421 | |||
422 | retval |= pch_phub_write_serial_rom(chip, 0x0b + offset_addr, 0xbc); | ||
423 | retval |= pch_phub_write_serial_rom(chip, 0x0a + offset_addr, 0x00); | ||
424 | retval |= pch_phub_write_serial_rom(chip, 0x09 + offset_addr, 0x40); | ||
425 | retval |= pch_phub_write_serial_rom(chip, 0x08 + offset_addr, 0x18); | ||
426 | |||
427 | retval |= pch_phub_write_serial_rom(chip, 0x13 + offset_addr, 0xbc); | ||
428 | retval |= pch_phub_write_serial_rom(chip, 0x12 + offset_addr, 0x00); | ||
429 | retval |= pch_phub_write_serial_rom(chip, 0x11 + offset_addr, 0x40); | ||
430 | retval |= pch_phub_write_serial_rom(chip, 0x10 + offset_addr, 0x19); | ||
431 | |||
432 | retval |= pch_phub_write_serial_rom(chip, 0x1b + offset_addr, 0xbc); | ||
433 | retval |= pch_phub_write_serial_rom(chip, 0x1a + offset_addr, 0x00); | ||
434 | retval |= pch_phub_write_serial_rom(chip, 0x19 + offset_addr, 0x40); | ||
435 | retval |= pch_phub_write_serial_rom(chip, 0x18 + offset_addr, 0x3a); | ||
436 | |||
437 | retval |= pch_phub_write_serial_rom(chip, 0x1f + offset_addr, 0x01); | ||
438 | retval |= pch_phub_write_serial_rom(chip, 0x1e + offset_addr, 0x00); | ||
439 | retval |= pch_phub_write_serial_rom(chip, 0x1d + offset_addr, 0x00); | ||
440 | retval |= pch_phub_write_serial_rom(chip, 0x1c + offset_addr, 0x00); | ||
441 | |||
442 | return retval; | ||
443 | } | ||
444 | |||
387 | /** | 445 | /** |
388 | * pch_phub_read_gbe_mac_addr() - Read Gigabit Ethernet MAC address | 446 | * pch_phub_read_gbe_mac_addr() - Read Gigabit Ethernet MAC address |
389 | * @offset_address: Gigabit Ethernet MAC address offset value. | 447 | * @offset_address: Gigabit Ethernet MAC address offset value. |
@@ -406,7 +464,10 @@ static int pch_phub_write_gbe_mac_addr(struct pch_phub_reg *chip, u8 *data) | |||
406 | int retval; | 464 | int retval; |
407 | int i; | 465 | int i; |
408 | 466 | ||
409 | retval = pch_phub_gbe_serial_rom_conf(chip); | 467 | if (chip->ioh_type == 1) /* EG20T */ |
468 | retval = pch_phub_gbe_serial_rom_conf(chip); | ||
469 | else /* ML7223 */ | ||
470 | retval = pch_phub_gbe_serial_rom_conf_mp(chip); | ||
410 | if (retval) | 471 | if (retval) |
411 | return retval; | 472 | return retval; |
412 | 473 | ||
@@ -441,12 +502,16 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj, | |||
441 | } | 502 | } |
442 | 503 | ||
443 | /* Get Rom signature */ | 504 | /* Get Rom signature */ |
444 | pch_phub_read_serial_rom(chip, 0x80, (unsigned char *)&rom_signature); | 505 | pch_phub_read_serial_rom(chip, chip->pch_opt_rom_start_address, |
506 | (unsigned char *)&rom_signature); | ||
445 | rom_signature &= 0xff; | 507 | rom_signature &= 0xff; |
446 | pch_phub_read_serial_rom(chip, 0x81, (unsigned char *)&tmp); | 508 | pch_phub_read_serial_rom(chip, chip->pch_opt_rom_start_address + 1, |
509 | (unsigned char *)&tmp); | ||
447 | rom_signature |= (tmp & 0xff) << 8; | 510 | rom_signature |= (tmp & 0xff) << 8; |
448 | if (rom_signature == 0xAA55) { | 511 | if (rom_signature == 0xAA55) { |
449 | pch_phub_read_serial_rom(chip, 0x82, &rom_length); | 512 | pch_phub_read_serial_rom(chip, |
513 | chip->pch_opt_rom_start_address + 2, | ||
514 | &rom_length); | ||
450 | orom_size = rom_length * 512; | 515 | orom_size = rom_length * 512; |
451 | if (orom_size < off) { | 516 | if (orom_size < off) { |
452 | addr_offset = 0; | 517 | addr_offset = 0; |
@@ -458,8 +523,9 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj, | |||
458 | } | 523 | } |
459 | 524 | ||
460 | for (addr_offset = 0; addr_offset < count; addr_offset++) { | 525 | for (addr_offset = 0; addr_offset < count; addr_offset++) { |
461 | pch_phub_read_serial_rom(chip, 0x80 + addr_offset + off, | 526 | pch_phub_read_serial_rom(chip, |
462 | &buf[addr_offset]); | 527 | chip->pch_opt_rom_start_address + addr_offset + off, |
528 | &buf[addr_offset]); | ||
463 | } | 529 | } |
464 | } else { | 530 | } else { |
465 | err = -ENODATA; | 531 | err = -ENODATA; |
@@ -502,8 +568,9 @@ static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj, | |||
502 | if (PCH_PHUB_OROM_SIZE < off + addr_offset) | 568 | if (PCH_PHUB_OROM_SIZE < off + addr_offset) |
503 | goto return_ok; | 569 | goto return_ok; |
504 | 570 | ||
505 | ret = pch_phub_write_serial_rom(chip, 0x80 + addr_offset + off, | 571 | ret = pch_phub_write_serial_rom(chip, |
506 | buf[addr_offset]); | 572 | chip->pch_opt_rom_start_address + addr_offset + off, |
573 | buf[addr_offset]); | ||
507 | if (ret) { | 574 | if (ret) { |
508 | err = ret; | 575 | err = ret; |
509 | goto return_err; | 576 | goto return_err; |
@@ -603,19 +670,22 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev, | |||
603 | dev_dbg(&pdev->dev, "%s : pci_iomap SUCCESS and value " | 670 | dev_dbg(&pdev->dev, "%s : pci_iomap SUCCESS and value " |
604 | "in pch_phub_base_address variable is %p\n", __func__, | 671 | "in pch_phub_base_address variable is %p\n", __func__, |
605 | chip->pch_phub_base_address); | 672 | chip->pch_phub_base_address); |
606 | chip->pch_phub_extrom_base_address = pci_map_rom(pdev, &rom_size); | ||
607 | 673 | ||
608 | if (chip->pch_phub_extrom_base_address == 0) { | 674 | if (id->driver_data != 3) { |
609 | dev_err(&pdev->dev, "%s : pci_map_rom FAILED", __func__); | 675 | chip->pch_phub_extrom_base_address =\ |
610 | ret = -ENOMEM; | 676 | pci_map_rom(pdev, &rom_size); |
611 | goto err_pci_map; | 677 | if (chip->pch_phub_extrom_base_address == 0) { |
678 | dev_err(&pdev->dev, "%s: pci_map_rom FAILED", __func__); | ||
679 | ret = -ENOMEM; | ||
680 | goto err_pci_map; | ||
681 | } | ||
682 | dev_dbg(&pdev->dev, "%s : " | ||
683 | "pci_map_rom SUCCESS and value in " | ||
684 | "pch_phub_extrom_base_address variable is %p\n", | ||
685 | __func__, chip->pch_phub_extrom_base_address); | ||
612 | } | 686 | } |
613 | dev_dbg(&pdev->dev, "%s : " | ||
614 | "pci_map_rom SUCCESS and value in " | ||
615 | "pch_phub_extrom_base_address variable is %p\n", __func__, | ||
616 | chip->pch_phub_extrom_base_address); | ||
617 | 687 | ||
618 | if (id->driver_data == 1) { | 688 | if (id->driver_data == 1) { /* EG20T PCH */ |
619 | retval = sysfs_create_file(&pdev->dev.kobj, | 689 | retval = sysfs_create_file(&pdev->dev.kobj, |
620 | &dev_attr_pch_mac.attr); | 690 | &dev_attr_pch_mac.attr); |
621 | if (retval) | 691 | if (retval) |
@@ -642,7 +712,9 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev, | |||
642 | iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14); | 712 | iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14); |
643 | /* set the interrupt delay value */ | 713 | /* set the interrupt delay value */ |
644 | iowrite32(0x25, chip->pch_phub_base_address + 0x44); | 714 | iowrite32(0x25, chip->pch_phub_base_address + 0x44); |
645 | } else if (id->driver_data == 2) { | 715 | chip->pch_opt_rom_start_address = PCH_PHUB_ROM_START_ADDR_EG20T; |
716 | chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_EG20T; | ||
717 | } else if (id->driver_data == 2) { /* ML7213 IOH */ | ||
646 | retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); | 718 | retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); |
647 | if (retval) | 719 | if (retval) |
648 | goto err_sysfs_create; | 720 | goto err_sysfs_create; |
@@ -653,7 +725,38 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev, | |||
653 | * Device8(USB OHCI #0/ USB EHCI #0):a | 725 | * Device8(USB OHCI #0/ USB EHCI #0):a |
654 | */ | 726 | */ |
655 | iowrite32(0x000affa0, chip->pch_phub_base_address + 0x14); | 727 | iowrite32(0x000affa0, chip->pch_phub_base_address + 0x14); |
728 | chip->pch_opt_rom_start_address =\ | ||
729 | PCH_PHUB_ROM_START_ADDR_ML7213; | ||
730 | } else if (id->driver_data == 3) { /* ML7223 IOH Bus-m*/ | ||
731 | /* set the prefech value | ||
732 | * Device8(GbE) | ||
733 | */ | ||
734 | iowrite32(0x000a0000, chip->pch_phub_base_address + 0x14); | ||
735 | chip->pch_opt_rom_start_address =\ | ||
736 | PCH_PHUB_ROM_START_ADDR_ML7223; | ||
737 | chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223; | ||
738 | } else if (id->driver_data == 4) { /* ML7223 IOH Bus-n*/ | ||
739 | retval = sysfs_create_file(&pdev->dev.kobj, | ||
740 | &dev_attr_pch_mac.attr); | ||
741 | if (retval) | ||
742 | goto err_sysfs_create; | ||
743 | retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); | ||
744 | if (retval) | ||
745 | goto exit_bin_attr; | ||
746 | /* set the prefech value | ||
747 | * Device2(USB OHCI #0,1,2,3/ USB EHCI #0):a | ||
748 | * Device4(SDIO #0,1):f | ||
749 | * Device6(SATA 2):f | ||
750 | */ | ||
751 | iowrite32(0x0000ffa0, chip->pch_phub_base_address + 0x14); | ||
752 | /* set the interrupt delay value */ | ||
753 | iowrite32(0x25, chip->pch_phub_base_address + 0x140); | ||
754 | chip->pch_opt_rom_start_address =\ | ||
755 | PCH_PHUB_ROM_START_ADDR_ML7223; | ||
756 | chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223; | ||
656 | } | 757 | } |
758 | |||
759 | chip->ioh_type = id->driver_data; | ||
657 | pci_set_drvdata(pdev, chip); | 760 | pci_set_drvdata(pdev, chip); |
658 | 761 | ||
659 | return 0; | 762 | return 0; |
@@ -733,6 +836,8 @@ static int pch_phub_resume(struct pci_dev *pdev) | |||
733 | static struct pci_device_id pch_phub_pcidev_id[] = { | 836 | static struct pci_device_id pch_phub_pcidev_id[] = { |
734 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH1_PHUB), 1, }, | 837 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH1_PHUB), 1, }, |
735 | { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7213_PHUB), 2, }, | 838 | { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7213_PHUB), 2, }, |
839 | { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_mPHUB), 3, }, | ||
840 | { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_nPHUB), 4, }, | ||
736 | { } | 841 | { } |
737 | }; | 842 | }; |
738 | MODULE_DEVICE_TABLE(pci, pch_phub_pcidev_id); | 843 | MODULE_DEVICE_TABLE(pci, pch_phub_pcidev_id); |
@@ -759,5 +864,5 @@ static void __exit pch_phub_pci_exit(void) | |||
759 | module_init(pch_phub_pci_init); | 864 | module_init(pch_phub_pci_init); |
760 | module_exit(pch_phub_pci_exit); | 865 | module_exit(pch_phub_pci_exit); |
761 | 866 | ||
762 | MODULE_DESCRIPTION("PCH Packet Hub PCI Driver"); | 867 | MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR IOH(ML7213/ML7223) PHUB"); |
763 | MODULE_LICENSE("GPL"); | 868 | MODULE_LICENSE("GPL"); |