/* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * Copyright(c) 2012 Intel Corporation. All rights reserved. * * GPL LICENSE SUMMARY * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * BSD LICENSE * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Supports the SMBus Message Transport (SMT) in the Intel Atom Processor * S12xx Product Family. * * Features supported by this driver: * Hardware PEC yes * Block buffer yes * Block process call transaction yes * Slave mode no */ #include <linux/module.h> #include <linux/pci.h> #include <linux/kernel.h> #include <linux/stddef.h> #include <linux/completion.h> #include <linux/dma-mapping.h> #include <linux/i2c.h> #include <linux/acpi.h> #include <linux/interrupt.h> #include <linux/io-64-nonatomic-lo-hi.h> /* PCI Address Constants */ #define SMBBAR … /* PCI DIDs for the Intel SMBus Message Transport (SMT) Devices */ #define PCI_DEVICE_ID_INTEL_S1200_SMT0 … #define PCI_DEVICE_ID_INTEL_S1200_SMT1 … #define PCI_DEVICE_ID_INTEL_CDF_SMT … #define PCI_DEVICE_ID_INTEL_DNV_SMT … #define PCI_DEVICE_ID_INTEL_EBG_SMT … #define PCI_DEVICE_ID_INTEL_AVOTON_SMT … #define ISMT_DESC_ENTRIES … #define ISMT_MAX_RETRIES … #define ISMT_LOG_ENTRIES … /* Hardware Descriptor Constants - Control Field */ #define ISMT_DESC_CWRL … #define ISMT_DESC_BLK … #define ISMT_DESC_FAIR … #define ISMT_DESC_PEC … #define ISMT_DESC_I2C … #define ISMT_DESC_INT … #define ISMT_DESC_SOE … /* Hardware Descriptor Constants - Status Field */ #define ISMT_DESC_SCS … #define ISMT_DESC_DLTO … #define ISMT_DESC_NAK … #define ISMT_DESC_CRC … #define ISMT_DESC_CLTO … #define ISMT_DESC_COL … #define ISMT_DESC_LPR … /* Macros */ #define ISMT_DESC_ADDR_RW(addr, rw) … /* iSMT General Register address offsets (SMBBAR + <addr>) */ #define ISMT_GR_GCTRL … #define ISMT_GR_SMTICL … #define ISMT_GR_ERRINTMSK … #define ISMT_GR_ERRAERMSK … #define ISMT_GR_ERRSTS … #define ISMT_GR_ERRINFO … /* iSMT Master Registers */ #define ISMT_MSTR_MDBA … #define ISMT_MSTR_MCTRL … #define ISMT_MSTR_MSTS … #define ISMT_MSTR_MDS … #define ISMT_MSTR_RPOLICY … /* iSMT Miscellaneous Registers */ #define ISMT_SPGT … /* General Control Register (GCTRL) bit definitions */ #define ISMT_GCTRL_TRST … #define ISMT_GCTRL_KILL … #define ISMT_GCTRL_SRST … /* Master Control Register (MCTRL) bit definitions */ #define ISMT_MCTRL_SS … #define ISMT_MCTRL_MEIE … #define ISMT_MCTRL_FMHP … /* Master Status Register (MSTS) bit definitions */ #define ISMT_MSTS_HMTP … #define ISMT_MSTS_MIS … #define ISMT_MSTS_MEIS … #define ISMT_MSTS_IP … /* Master Descriptor Size (MDS) bit definitions */ #define ISMT_MDS_MASK … /* SMBus PHY Global Timing Register (SPGT) bit definitions */ #define ISMT_SPGT_SPD_MASK … #define ISMT_SPGT_SPD_80K … #define ISMT_SPGT_SPD_100K … #define ISMT_SPGT_SPD_400K … #define ISMT_SPGT_SPD_1M … /* MSI Control Register (MSICTL) bit definitions */ #define ISMT_MSICTL_MSIE … /* iSMT Hardware Descriptor */ struct ismt_desc { … } __packed; struct ismt_priv { … }; static const struct pci_device_id ismt_ids[] = …; MODULE_DEVICE_TABLE(pci, ismt_ids); /* Bus speed control bits for slow debuggers - refer to the docs for usage */ static unsigned int bus_speed; module_param(bus_speed, uint, S_IRUGO); MODULE_PARM_DESC(…) …; /** * __ismt_desc_dump() - dump the contents of a specific descriptor * @dev: the iSMT device * @desc: the iSMT hardware descriptor */ static void __ismt_desc_dump(struct device *dev, const struct ismt_desc *desc) { … } /** * ismt_desc_dump() - dump the contents of a descriptor for debug purposes * @priv: iSMT private data */ static void ismt_desc_dump(struct ismt_priv *priv) { … } /** * ismt_gen_reg_dump() - dump the iSMT General Registers * @priv: iSMT private data */ static void ismt_gen_reg_dump(struct ismt_priv *priv) { … } /** * ismt_mstr_reg_dump() - dump the iSMT Master Registers * @priv: iSMT private data */ static void ismt_mstr_reg_dump(struct ismt_priv *priv) { … } /** * ismt_submit_desc() - add a descriptor to the ring * @priv: iSMT private data */ static void ismt_submit_desc(struct ismt_priv *priv) { … } /** * ismt_process_desc() - handle the completion of the descriptor * @desc: the iSMT hardware descriptor * @data: data buffer from the upper layer * @priv: ismt_priv struct holding our dma buffer * @size: SMBus transaction type * @read_write: flag to indicate if this is a read or write */ static int ismt_process_desc(const struct ismt_desc *desc, union i2c_smbus_data *data, struct ismt_priv *priv, int size, char read_write) { … } /** * ismt_access() - process an SMBus command * @adap: the i2c host adapter * @addr: address of the i2c/SMBus target * @flags: command options * @read_write: read from or write to device * @command: the i2c/SMBus command to issue * @size: SMBus transaction type * @data: read/write data buffer */ static int ismt_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data) { … } /** * ismt_func() - report which i2c commands are supported by this adapter * @adap: the i2c host adapter */ static u32 ismt_func(struct i2c_adapter *adap) { … } static const struct i2c_algorithm smbus_algorithm = …; /** * ismt_handle_isr() - interrupt handler bottom half * @priv: iSMT private data */ static irqreturn_t ismt_handle_isr(struct ismt_priv *priv) { … } /** * ismt_do_interrupt() - IRQ interrupt handler * @vec: interrupt vector * @data: iSMT private data */ static irqreturn_t ismt_do_interrupt(int vec, void *data) { … } /** * ismt_do_msi_interrupt() - MSI interrupt handler * @vec: interrupt vector * @data: iSMT private data */ static irqreturn_t ismt_do_msi_interrupt(int vec, void *data) { … } /** * ismt_hw_init() - initialize the iSMT hardware * @priv: iSMT private data */ static void ismt_hw_init(struct ismt_priv *priv) { … } /** * ismt_dev_init() - initialize the iSMT data structures * @priv: iSMT private data */ static int ismt_dev_init(struct ismt_priv *priv) { … } /** * ismt_int_init() - initialize interrupts * @priv: iSMT private data */ static int ismt_int_init(struct ismt_priv *priv) { … } static struct pci_driver ismt_driver; /** * ismt_probe() - probe for iSMT devices * @pdev: PCI-Express device * @id: PCI-Express device ID */ static int ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id) { … } /** * ismt_remove() - release driver resources * @pdev: PCI-Express device */ static void ismt_remove(struct pci_dev *pdev) { … } static struct pci_driver ismt_driver = …; module_pci_driver(…) …; MODULE_LICENSE(…) …; MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …;