提交 275640b0 编写于 作者: T Tomoya MORINAGA 提交者: Greg Kroah-Hartman

pch_phub: Support new device ML7223

Support new device OKI SEMICONDUCTOR ML7223 IOH(Input/Output Hub).
The ML7223 IOH is for MP(Media Phone) use.
The ML7223 is companion chip for Intel Atom E6xx series.
The ML7223 is completely compatible for Intel EG20T PCH.
Signed-off-by: NTomoya MORINAGA <tomoya-linux@dsn.okisemi.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
上级 aa273ae5
...@@ -459,7 +459,7 @@ config BMP085 ...@@ -459,7 +459,7 @@ config BMP085
module will be called bmp085. module will be called bmp085.
config PCH_PHUB config PCH_PHUB
tristate "PCH Packet Hub of Intel Topcliff / OKI SEMICONDUCTOR ML7213" tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223) PHUB"
depends on PCI depends on PCI
help help
This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of
...@@ -467,10 +467,12 @@ config PCH_PHUB ...@@ -467,10 +467,12 @@ config PCH_PHUB
processor. The Topcliff has MAC address and Option ROM data in SROM. processor. The Topcliff has MAC address and Option ROM data in SROM.
This driver can access MAC address and Option ROM data in SROM. This driver can access MAC address and Option ROM data in SROM.
This driver also can be used for OKI SEMICONDUCTOR's ML7213 which is This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
for IVI(In-Vehicle Infotainment) use. Output Hub), ML7213 and ML7223.
ML7213 is companion chip for Intel Atom E6xx series. ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is
ML7213 is completely compatible for Intel EG20T PCH. for MP(Media Phone) use.
ML7213/ML7223 is companion chip for Intel Atom E6xx series.
ML7213/ML7223 is completely compatible for Intel EG20T PCH.
To compile this driver as a module, choose M here: the module will To compile this driver as a module, choose M here: the module will
be called pch_phub. be called pch_phub.
......
...@@ -34,12 +34,18 @@ ...@@ -34,12 +34,18 @@
#define PHUB_TIMEOUT 0x05 /* Time out value for Status Register */ #define PHUB_TIMEOUT 0x05 /* Time out value for Status Register */
#define PCH_PHUB_ROM_WRITE_ENABLE 0x01 /* Enabling for writing ROM */ #define PCH_PHUB_ROM_WRITE_ENABLE 0x01 /* Enabling for writing ROM */
#define PCH_PHUB_ROM_WRITE_DISABLE 0x00 /* Disabling for writing ROM */ #define PCH_PHUB_ROM_WRITE_DISABLE 0x00 /* Disabling for writing ROM */
#define PCH_PHUB_MAC_START_ADDR 0x20C /* MAC data area start address offset */ #define PCH_PHUB_MAC_START_ADDR_EG20T 0x14 /* MAC data area start address
#define PCH_PHUB_ROM_START_ADDR_EG20T 0x14 /* ROM data area start address offset offset */
#define PCH_PHUB_MAC_START_ADDR_ML7223 0x20C /* MAC data area start address
offset */
#define PCH_PHUB_ROM_START_ADDR_EG20T 0x80 /* ROM data area start address offset
(Intel EG20T PCH)*/ (Intel EG20T PCH)*/
#define PCH_PHUB_ROM_START_ADDR_ML7213 0x400 /* ROM data area start address #define PCH_PHUB_ROM_START_ADDR_ML7213 0x400 /* ROM data area start address
offset(OKI SEMICONDUCTOR ML7213) offset(OKI SEMICONDUCTOR ML7213)
*/ */
#define PCH_PHUB_ROM_START_ADDR_ML7223 0x400 /* ROM data area start address
offset(OKI SEMICONDUCTOR ML7223)
*/
/* MAX number of INT_REDUCE_CONTROL registers */ /* MAX number of INT_REDUCE_CONTROL registers */
#define MAX_NUM_INT_REDUCE_CONTROL_REG 128 #define MAX_NUM_INT_REDUCE_CONTROL_REG 128
...@@ -63,6 +69,10 @@ ...@@ -63,6 +69,10 @@
#define PCI_VENDOR_ID_ROHM 0x10db #define PCI_VENDOR_ID_ROHM 0x10db
#define PCI_DEVICE_ID_ROHM_ML7213_PHUB 0x801A #define PCI_DEVICE_ID_ROHM_ML7213_PHUB 0x801A
/* Macros for ML7223 */
#define PCI_DEVICE_ID_ROHM_ML7223_mPHUB 0x8012 /* for Bus-m */
#define PCI_DEVICE_ID_ROHM_ML7223_nPHUB 0x8002 /* for Bus-n */
/* SROM ACCESS Macro */ /* SROM ACCESS Macro */
#define PCH_WORD_ADDR_MASK (~((1 << 2) - 1)) #define PCH_WORD_ADDR_MASK (~((1 << 2) - 1))
...@@ -100,6 +110,9 @@ ...@@ -100,6 +110,9 @@
* @clkcfg_reg: CLK CFG register val * @clkcfg_reg: CLK CFG register val
* @pch_phub_base_address: Register base address * @pch_phub_base_address: Register base address
* @pch_phub_extrom_base_address: external rom base address * @pch_phub_extrom_base_address: external rom base address
* @pch_mac_start_address: MAC address area start address
* @pch_opt_rom_start_address: Option ROM start address
* @ioh_type: Save IOH type
*/ */
struct pch_phub_reg { struct pch_phub_reg {
u32 phub_id_reg; u32 phub_id_reg;
...@@ -117,6 +130,9 @@ struct pch_phub_reg { ...@@ -117,6 +130,9 @@ struct pch_phub_reg {
u32 clkcfg_reg; u32 clkcfg_reg;
void __iomem *pch_phub_base_address; void __iomem *pch_phub_base_address;
void __iomem *pch_phub_extrom_base_address; void __iomem *pch_phub_extrom_base_address;
u32 pch_mac_start_address;
u32 pch_opt_rom_start_address;
int ioh_type;
}; };
/* SROM SPEC for MAC address assignment offset */ /* 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,7 +335,7 @@ static void pch_phub_read_serial_rom_val(struct pch_phub_reg *chip,
{ {
unsigned int mem_addr; unsigned int mem_addr;
mem_addr = PCH_PHUB_ROM_START_ADDR_EG20T + mem_addr = chip->pch_mac_start_address +
pch_phub_mac_offset[offset_address]; pch_phub_mac_offset[offset_address];
pch_phub_read_serial_rom(chip, mem_addr, data); 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,7 +352,7 @@ static int pch_phub_write_serial_rom_val(struct pch_phub_reg *chip,
int retval; int retval;
unsigned int mem_addr; unsigned int mem_addr;
mem_addr = PCH_PHUB_ROM_START_ADDR_EG20T + mem_addr = chip->pch_mac_start_address +
pch_phub_mac_offset[offset_address]; pch_phub_mac_offset[offset_address];
retval = pch_phub_write_serial_rom(chip, mem_addr, data); 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,6 +400,48 @@ static int pch_phub_gbe_serial_rom_conf(struct pch_phub_reg *chip)
return retval; return retval;
} }
/* pch_phub_gbe_serial_rom_conf_mp - makes SerialROM header format configuration
* for Gigabit Ethernet MAC address
*/
static int pch_phub_gbe_serial_rom_conf_mp(struct pch_phub_reg *chip)
{
int retval;
u32 offset_addr;
offset_addr = 0x200;
retval = pch_phub_write_serial_rom(chip, 0x03 + offset_addr, 0xbc);
retval |= pch_phub_write_serial_rom(chip, 0x02 + offset_addr, 0x00);
retval |= pch_phub_write_serial_rom(chip, 0x01 + offset_addr, 0x40);
retval |= pch_phub_write_serial_rom(chip, 0x00 + offset_addr, 0x02);
retval |= pch_phub_write_serial_rom(chip, 0x07 + offset_addr, 0x00);
retval |= pch_phub_write_serial_rom(chip, 0x06 + offset_addr, 0x00);
retval |= pch_phub_write_serial_rom(chip, 0x05 + offset_addr, 0x00);
retval |= pch_phub_write_serial_rom(chip, 0x04 + offset_addr, 0x80);
retval |= pch_phub_write_serial_rom(chip, 0x0b + offset_addr, 0xbc);
retval |= pch_phub_write_serial_rom(chip, 0x0a + offset_addr, 0x00);
retval |= pch_phub_write_serial_rom(chip, 0x09 + offset_addr, 0x40);
retval |= pch_phub_write_serial_rom(chip, 0x08 + offset_addr, 0x18);
retval |= pch_phub_write_serial_rom(chip, 0x13 + offset_addr, 0xbc);
retval |= pch_phub_write_serial_rom(chip, 0x12 + offset_addr, 0x00);
retval |= pch_phub_write_serial_rom(chip, 0x11 + offset_addr, 0x40);
retval |= pch_phub_write_serial_rom(chip, 0x10 + offset_addr, 0x19);
retval |= pch_phub_write_serial_rom(chip, 0x1b + offset_addr, 0xbc);
retval |= pch_phub_write_serial_rom(chip, 0x1a + offset_addr, 0x00);
retval |= pch_phub_write_serial_rom(chip, 0x19 + offset_addr, 0x40);
retval |= pch_phub_write_serial_rom(chip, 0x18 + offset_addr, 0x3a);
retval |= pch_phub_write_serial_rom(chip, 0x1f + offset_addr, 0x01);
retval |= pch_phub_write_serial_rom(chip, 0x1e + offset_addr, 0x00);
retval |= pch_phub_write_serial_rom(chip, 0x1d + offset_addr, 0x00);
retval |= pch_phub_write_serial_rom(chip, 0x1c + offset_addr, 0x00);
return retval;
}
/** /**
* pch_phub_read_gbe_mac_addr() - Read Gigabit Ethernet MAC address * pch_phub_read_gbe_mac_addr() - Read Gigabit Ethernet MAC address
* @offset_address: Gigabit Ethernet MAC address offset value. * @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,7 +464,10 @@ static int pch_phub_write_gbe_mac_addr(struct pch_phub_reg *chip, u8 *data)
int retval; int retval;
int i; int i;
retval = pch_phub_gbe_serial_rom_conf(chip); if (chip->ioh_type == 1) /* EG20T */
retval = pch_phub_gbe_serial_rom_conf(chip);
else /* ML7223 */
retval = pch_phub_gbe_serial_rom_conf_mp(chip);
if (retval) if (retval)
return retval; return retval;
...@@ -441,12 +502,16 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj, ...@@ -441,12 +502,16 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj,
} }
/* Get Rom signature */ /* Get Rom signature */
pch_phub_read_serial_rom(chip, 0x80, (unsigned char *)&rom_signature); pch_phub_read_serial_rom(chip, chip->pch_opt_rom_start_address,
(unsigned char *)&rom_signature);
rom_signature &= 0xff; rom_signature &= 0xff;
pch_phub_read_serial_rom(chip, 0x81, (unsigned char *)&tmp); pch_phub_read_serial_rom(chip, chip->pch_opt_rom_start_address + 1,
(unsigned char *)&tmp);
rom_signature |= (tmp & 0xff) << 8; rom_signature |= (tmp & 0xff) << 8;
if (rom_signature == 0xAA55) { if (rom_signature == 0xAA55) {
pch_phub_read_serial_rom(chip, 0x82, &rom_length); pch_phub_read_serial_rom(chip,
chip->pch_opt_rom_start_address + 2,
&rom_length);
orom_size = rom_length * 512; orom_size = rom_length * 512;
if (orom_size < off) { if (orom_size < off) {
addr_offset = 0; addr_offset = 0;
...@@ -458,8 +523,9 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj, ...@@ -458,8 +523,9 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj,
} }
for (addr_offset = 0; addr_offset < count; addr_offset++) { for (addr_offset = 0; addr_offset < count; addr_offset++) {
pch_phub_read_serial_rom(chip, 0x80 + addr_offset + off, pch_phub_read_serial_rom(chip,
&buf[addr_offset]); chip->pch_opt_rom_start_address + addr_offset + off,
&buf[addr_offset]);
} }
} else { } else {
err = -ENODATA; err = -ENODATA;
...@@ -502,8 +568,9 @@ static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj, ...@@ -502,8 +568,9 @@ static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj,
if (PCH_PHUB_OROM_SIZE < off + addr_offset) if (PCH_PHUB_OROM_SIZE < off + addr_offset)
goto return_ok; goto return_ok;
ret = pch_phub_write_serial_rom(chip, 0x80 + addr_offset + off, ret = pch_phub_write_serial_rom(chip,
buf[addr_offset]); chip->pch_opt_rom_start_address + addr_offset + off,
buf[addr_offset]);
if (ret) { if (ret) {
err = ret; err = ret;
goto return_err; goto return_err;
...@@ -603,19 +670,22 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev, ...@@ -603,19 +670,22 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
dev_dbg(&pdev->dev, "%s : pci_iomap SUCCESS and value " dev_dbg(&pdev->dev, "%s : pci_iomap SUCCESS and value "
"in pch_phub_base_address variable is %p\n", __func__, "in pch_phub_base_address variable is %p\n", __func__,
chip->pch_phub_base_address); chip->pch_phub_base_address);
chip->pch_phub_extrom_base_address = pci_map_rom(pdev, &rom_size);
if (chip->pch_phub_extrom_base_address == 0) { if (id->driver_data != 3) {
dev_err(&pdev->dev, "%s : pci_map_rom FAILED", __func__); chip->pch_phub_extrom_base_address =\
ret = -ENOMEM; pci_map_rom(pdev, &rom_size);
goto err_pci_map; if (chip->pch_phub_extrom_base_address == 0) {
dev_err(&pdev->dev, "%s: pci_map_rom FAILED", __func__);
ret = -ENOMEM;
goto err_pci_map;
}
dev_dbg(&pdev->dev, "%s : "
"pci_map_rom SUCCESS and value in "
"pch_phub_extrom_base_address variable is %p\n",
__func__, chip->pch_phub_extrom_base_address);
} }
dev_dbg(&pdev->dev, "%s : "
"pci_map_rom SUCCESS and value in "
"pch_phub_extrom_base_address variable is %p\n", __func__,
chip->pch_phub_extrom_base_address);
if (id->driver_data == 1) { if (id->driver_data == 1) { /* EG20T PCH */
retval = sysfs_create_file(&pdev->dev.kobj, retval = sysfs_create_file(&pdev->dev.kobj,
&dev_attr_pch_mac.attr); &dev_attr_pch_mac.attr);
if (retval) if (retval)
...@@ -642,7 +712,9 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev, ...@@ -642,7 +712,9 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14); iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14);
/* set the interrupt delay value */ /* set the interrupt delay value */
iowrite32(0x25, chip->pch_phub_base_address + 0x44); iowrite32(0x25, chip->pch_phub_base_address + 0x44);
} else if (id->driver_data == 2) { chip->pch_opt_rom_start_address = PCH_PHUB_ROM_START_ADDR_EG20T;
chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_EG20T;
} else if (id->driver_data == 2) { /* ML7213 IOH */
retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
if (retval) if (retval)
goto err_sysfs_create; goto err_sysfs_create;
...@@ -653,7 +725,38 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev, ...@@ -653,7 +725,38 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
* Device8(USB OHCI #0/ USB EHCI #0):a * Device8(USB OHCI #0/ USB EHCI #0):a
*/ */
iowrite32(0x000affa0, chip->pch_phub_base_address + 0x14); iowrite32(0x000affa0, chip->pch_phub_base_address + 0x14);
chip->pch_opt_rom_start_address =\
PCH_PHUB_ROM_START_ADDR_ML7213;
} else if (id->driver_data == 3) { /* ML7223 IOH Bus-m*/
/* set the prefech value
* Device8(GbE)
*/
iowrite32(0x000a0000, chip->pch_phub_base_address + 0x14);
chip->pch_opt_rom_start_address =\
PCH_PHUB_ROM_START_ADDR_ML7223;
chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223;
} else if (id->driver_data == 4) { /* ML7223 IOH Bus-n*/
retval = sysfs_create_file(&pdev->dev.kobj,
&dev_attr_pch_mac.attr);
if (retval)
goto err_sysfs_create;
retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
if (retval)
goto exit_bin_attr;
/* set the prefech value
* Device2(USB OHCI #0,1,2,3/ USB EHCI #0):a
* Device4(SDIO #0,1):f
* Device6(SATA 2):f
*/
iowrite32(0x0000ffa0, chip->pch_phub_base_address + 0x14);
/* set the interrupt delay value */
iowrite32(0x25, chip->pch_phub_base_address + 0x140);
chip->pch_opt_rom_start_address =\
PCH_PHUB_ROM_START_ADDR_ML7223;
chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223;
} }
chip->ioh_type = id->driver_data;
pci_set_drvdata(pdev, chip); pci_set_drvdata(pdev, chip);
return 0; return 0;
...@@ -733,6 +836,8 @@ static int pch_phub_resume(struct pci_dev *pdev) ...@@ -733,6 +836,8 @@ static int pch_phub_resume(struct pci_dev *pdev)
static struct pci_device_id pch_phub_pcidev_id[] = { static struct pci_device_id pch_phub_pcidev_id[] = {
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH1_PHUB), 1, }, { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH1_PHUB), 1, },
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7213_PHUB), 2, }, { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7213_PHUB), 2, },
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_mPHUB), 3, },
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_nPHUB), 4, },
{ } { }
}; };
MODULE_DEVICE_TABLE(pci, pch_phub_pcidev_id); MODULE_DEVICE_TABLE(pci, pch_phub_pcidev_id);
...@@ -759,5 +864,5 @@ static void __exit pch_phub_pci_exit(void) ...@@ -759,5 +864,5 @@ static void __exit pch_phub_pci_exit(void)
module_init(pch_phub_pci_init); module_init(pch_phub_pci_init);
module_exit(pch_phub_pci_exit); module_exit(pch_phub_pci_exit);
MODULE_DESCRIPTION("PCH Packet Hub PCI Driver"); MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR IOH(ML7213/ML7223) PHUB");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册