1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2006-2007 PA Semi, Inc 4 * 5 * SMBus host driver for PA Semi PWRficient 6 */ 7 8 #include <linux/module.h> 9 #include <linux/pci.h> 10 #include <linux/kernel.h> 11 #include <linux/stddef.h> 12 #include <linux/sched.h> 13 #include <linux/i2c.h> 14 #include <linux/delay.h> 15 #include <linux/slab.h> 16 #include <linux/io.h> 17 18 #include "i2c-pasemi-core.h" 19 20 #define CLK_100K_DIV 84 21 #define CLK_400K_DIV 21 22 23 static struct pci_driver pasemi_smb_pci_driver; 24 25 static int pasemi_smb_pci_probe(struct pci_dev *dev, 26 const struct pci_device_id *id) 27 { 28 struct pasemi_smbus *smbus; 29 unsigned long base; 30 int size; 31 int error; 32 33 if (!(pci_resource_flags(dev, 0) & IORESOURCE_IO)) 34 return -ENODEV; 35 36 smbus = devm_kzalloc(&dev->dev, sizeof(*smbus), GFP_KERNEL); 37 if (!smbus) 38 return -ENOMEM; 39 40 smbus->dev = &dev->dev; 41 base = pci_resource_start(dev, 0); 42 size = pci_resource_len(dev, 0); 43 smbus->clk_div = CLK_100K_DIV; 44 45 /* 46 * The original PASemi PCI controllers don't have a register for 47 * their HW revision. 48 */ 49 smbus->hw_rev = PASEMI_HW_REV_PCI; 50 51 if (!devm_request_region(&dev->dev, base, size, 52 pasemi_smb_pci_driver.name)) 53 return -EBUSY; 54 55 smbus->ioaddr = pcim_iomap(dev, 0, 0); 56 if (!smbus->ioaddr) 57 return -EBUSY; 58 59 error = pasemi_i2c_common_probe(smbus); 60 if (error) 61 return error; 62 63 pci_set_drvdata(dev, smbus); 64 65 return 0; 66 } 67 68 static const struct pci_device_id pasemi_smb_pci_ids[] = { 69 { PCI_DEVICE(0x1959, 0xa003) }, 70 { 0, } 71 }; 72 73 MODULE_DEVICE_TABLE(pci, pasemi_smb_pci_ids); 74 75 static struct pci_driver pasemi_smb_pci_driver = { 76 .name = "i2c-pasemi", 77 .id_table = pasemi_smb_pci_ids, 78 .probe = pasemi_smb_pci_probe, 79 }; 80 81 module_pci_driver(pasemi_smb_pci_driver); 82 83 MODULE_LICENSE("GPL"); 84 MODULE_AUTHOR("Olof Johansson <olof@lixom.net>"); 85 MODULE_DESCRIPTION("PA Semi PWRficient SMBus driver"); 86