From: Masayuki Ohtake Subject: OKI Semiconductor PCH PCIEQOS driver This driver implements PCH PCIEQOS controls for PCH. Signed-off-by: Masayuki Ohtake Acked-by: Wang Qi --- drivers/char/Kconfig | 7++ drivers/char/Makefile | 1 drivers/char/pch_pcieqos/Makefile | 9 drivers/char/pch_pcieqos/pch_common.h | 146 driers/char/pch_pcieqos/pch_debug.h | 60 drivers/char/pch_pcieqos/pch_pcieqos.c | 392 drivers/char/pch_pcieqos/pch_pcieqos.h | 196 drivers/char/pch_pcieqos/pch_pcieqos_hal.c | 550 drivers/char/pch_pcieqos/pch_pcieqos_hal.h | 125 drivers/char/pch_pcieqos/pch_pcieqos_pci.c | 523 +++++++++++++++++++++++++++++++ 10 files changed, 2009 insertions(+) diff -urN linux-2.6.33-rc3/drivers/char/Kconfig topcliff-2.6.33-rc3/drivers/char/Kconfig --- linux-2.6.33-rc3/drivers/char/Kconfig 2010-03-12 14:46:34.000000000 +0900 +++ topcliff-2.6.33-rc3/drivers/char/Kconfig 2010-03-09 10:14:52.000000000 +0900 @@ -11,6 +11,13 @@ If you say yes to this option, support will be included for the PCH IEEE1588 Host controller. +config PCH_PCIEQOS + tristate "PCH PCIEQOS" + depends on PCI + help + If you say yes to this option, support will be included for the + PCH PCIEQOS Host controller. + config VT bool "Virtual terminal" if EMBEDDED depends on !S390 diff -urN linux-2.6.33-rc3/drivers/char/Makefile topcliff-2.6.33-rc3/drivers/char/Makefile --- linux-2.6.33-rc3/drivers/char/Makefile 2010-03-12 14:46:34.000000000 +0900 +++ topcliff-2.6.33-rc3/drivers/char/Makefile 2010-03-05 22:57:39.000000000 +0900 @@ -112,6 +112,7 @@ js-rtc-y = rtc.o obj-$(CONFIG_PCH_IEEE1588) += pch_ieee1588/ +obj-$(CONFIG_PCH_PCIEQOS) += pch_pcieqos/ # Files generated that shall be removed upon make clean clean-files := consolemap_deftbl.c defkeymap.c diff -urN linux-2.6.33-rc3/drivers/char/pch_pcieqos/Makefile topcliff-2.6.33-rc3/drivers/char/pch_pcieqos/Makefile --- linux-2.6.33-rc3/drivers/char/pch_pcieqos/Makefile 1970-01-01 09:00:00.000000000 +0900 +++ topcliff-2.6.33-rc3/drivers/char/pch_pcieqos/Makefile 2010-03-09 09:15:41.000000000 +0900 @@ -0,0 +1,9 @@ +ifeq ($(CONFIG_PCIEQOS_DEBUG),y) +EXTRA_CFLAGS += -DDEBUG +endif + +obj-$(CONFIG_PCH_PCIEQOS) += pch_pcieqos_drv.o +#to set CAN clock to 50Mhz +EXTRA_CFLAGS+=-DIOH_CAN_PCLK_50MHZ + +pch_pcieqos_drv-objs := pch_pcieqos.o pch_pcieqos_pci.o pch_pcieqos_hal.o diff -urN linux-2.6.33-rc3/drivers/char/pch_pcieqos/pch_common.h topcliff-2.6.33-rc3/drivers/char/pch_pcieqos/pch_common.h --- linux-2.6.33-rc3/drivers/char/pch_pcieqos/pch_common.h 1970-01-01 09:00:00.000000000 +0900 +++ topcliff-2.6.33-rc3/drivers/char/pch_pcieqos/pch_common.h 2010-03-09 05:56:11.000000000 +0900 @@ -0,0 +1,146 @@ +/*! + * @file ioh_common.h + * @brief Provides the macro definitions used by all files. + * @version 1.0.0.0 + * @section + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * History: + * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. + * All rights reserved. + * + * created: + * WIPRO 03/07/2009 + * modified: + * WIPRO 05/08/2009 + * + */ + +#ifndef __IOH_COMMON_H__ +#define __IOH_COMMON_H__ + +/*! @ingroup Global +@def IOH_WRITE8 +@brief Macro for writing 8 bit data to an io/mem address +*/ +#define IOH_WRITE8(val, addr) iowrite8((val), (void __iomem *)(addr)) +/*! @ingroup Global +@def IOH_LOG +@brief Macro for writing 16 bit data to an io/mem address +*/ +#define IOH_WRITE16(val, addr) iowrite16((val), (void __iomem *)(addr)) +/*! @ingroup Global +@def IOH_LOG +@brief Macro for writing 32 bit data to an io/mem address +*/ +#define IOH_WRITE32(val, addr) iowrite32((val), (void __iomem *)(addr)) + +/*! @ingroup Global +@def IOH_READ8 +@brief Macro for reading 8 bit data from an io/mem address +*/ +#define IOH_READ8(addr) ioread8((void __iomem *)(addr)) +/*! @ingroup Global +@def IOH_READ16 +@brief Macro for reading 16 bit data from an io/mem address +*/ +#define IOH_READ16(addr) ioread16((void __iomem *)(addr)) +/*! @ingroup Global +@def IOH_READ32 +@brief Macro for reading 32 bit data from an io/mem address +*/ +#define IOH_READ32(addr) ioread32((void __iomem *)(addr)) +/*! @ingroup Global +@def IOH_WRITE32_F +@brief Macro for writing 32 bit data to an io/mem address +*/ +#define IOH_WRITE32_F(val, addr) do \ + { IOH_WRITE32((val), (addr)); (void)IOH_READ32((addr)); } while (0); + +/*! @ingroup Global +@def IOH_WRITE_BYTE +@brief Macro for writing 1 byte data to an io/mem address +*/ +#define IOH_WRITE_BYTE IOH_WRITE8 +/*! @ingroup Global +@def IOH_WRITE_WORD +@brief Macro for writing 1 word data to an io/mem address +*/ +#define IOH_WRITE_WORD IOH_WRITE16 +/*! @ingroup Global +@def IOH_WRITE_LONG +@brief Macro for writing long data to an io/mem address +*/ +#define IOH_WRITE_LONG IOH_WRITE32 + +/*! @ingroup Global +@def IOH_READ_BYTE +@brief Macro for reading 1 byte data from an io/mem address +*/ +#define IOH_READ_BYTE IOH_READ8 +/*! @ingroup Global +@def IOH_READ_WORD +@brief Macro for reading 1 word data from an io/mem address +*/ +#define IOH_READ_WORD IOH_READ16 +/*! @ingroup Global +@def IOH_READ_LONG +@brief Macro for reading long data from an io/mem address +*/ +#define IOH_READ_LONG IOH_READ32 + +/* Bit Manipulation Macros */ + +/*! @ingroup Global +@def IOH_READ_LONG +@brief macro to set a specified bit(mask) at the + specified address +*/ +#define IOH_SET_ADDR_BIT(addr, bitmask) IOH_WRITE_LONG((IOH_READ_LONG(addr) |\ + (bitmask)), (addr)) + +/*! @ingroup Global +@def IOH_READ_LONG +@brief macro to clear a specified bit(mask) at the specified address +*/ +#define IOH_CLR_ADDR_BIT(addr, bitmask) IOH_WRITE_LONG((IOH_READ_LONG(addr) &\ + ~(bitmask)), (addr)) + +/*! @ingroup Global +@def IOH_READ_LONG +@brief macro to set a specified bitmask for a variable +*/ +#define IOH_SET_BITMSK(var, bitmask) ((var) |= (bitmask)) + +/*! @ingroup Global +@def IOH_READ_LONG +@brief macro to clear a specified bitmask for a variable +*/ +#define IOH_CLR_BITMSK(var, bitmask) ((var) &= (~(bitmask))) + +/*! @ingroup Global +@def IOH_READ_LONG +@brief macro to set a specified bit for a variable +*/ +#define IOH_SET_BIT(var, bit) ((var) |= (1<<(bit))) + +/*! @ingroup Global +@def IOH_READ_LONG +@brief macro to clear a specified bit for a variable +*/ +#define IOH_CLR_BIT(var, bit) ((var) &= ~(1<<(bit))) + +#endif diff -urN linux-2.6.33-rc3/drivers/char/pch_pcieqos/pch_debug.h topcliff-2.6.33-rc3/drivers/char/pch_pcieqos/pch_debug.h --- linux-2.6.33-rc3/drivers/char/pch_pcieqos/pch_debug.h 1970-01-01 09:00:00.000000000 +0900 +++ topcliff-2.6.33-rc3/drivers/char/pch_pcieqos/pch_debug.h 2010-03-09 05:37:47.000000000 +0900 @@ -0,0 +1,60 @@ +/*! + * @file ioh_debug.h + * @brief Provides the macro definitions used for debugging. + * @version 1.0.0.0 + * @section + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * History: + * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. + * All rights reserved. + * + * created: + * WIPRO 03/07/2009 + * modified: + * WIPRO 05/08/2009 + * + */ + +#ifndef __IOH_DEBUG_H__ +#define __IOH_DEBUG_H__ + +#ifdef MODULE +#define IOH_LOG(level, fmt, args...) printk(level "%s:" fmt "\n",\ + THIS_MODULE->name, ##args) +#else +#define IOH_LOG(level, fmt, args...) printk(level "%s:" fmt "\n" ,\ + __FILE__, ##args) +#endif + + +#ifdef DEBUG + #define IOH_DEBUG(fmt, args...) IOH_LOG(KERN_DEBUG, fmt, ##args) +#else + #define IOH_DEBUG(fmt, args...) +#endif + +#ifdef IOH_TRACE_ENABLED + #define IOH_TRACE IOH_DEBUG +#else + #define IOH_TRACE(fmt, args...) +#endif + +#define IOH_TRACE_ENTER IOH_TRACE("Enter %s", __func__) +#define IOH_TRACE_EXIT IOH_TRACE("Exit %s", __func__) + + +#endif diff -urN linux-2.6.33-rc3/drivers/char/pch_pcieqos/pch_pcieqos.c topcliff-2.6.33-rc3/drivers/char/pch_pcieqos/pch_pcieqos.c --- linux-2.6.33-rc3/drivers/char/pch_pcieqos/pch_pcieqos.c 1970-01-01 09:00:00.000000000 +0900 +++ topcliff-2.6.33-rc3/drivers/char/pch_pcieqos/pch_pcieqos.c 2010-03-12 14:16:44.000000000 +0900 @@ -0,0 +1,392 @@ +/*! + * @file ioh_pcieqos.c + * @brief Provides all the implementation of the interfaces pertaining to the PCIEQOS module. + * @version 1.0.0.0 + * @section + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * History: + * Copyright (C) 2009 OKI SEMICONDUCTOR Co., LTD. + * All rights reserved. + * + * created: + * OKI SEMICONDUCTOR 06/20/2009 + * modified: + * + */ + +/* includes */ + +#include +#include +#include +#include +#include +#include + +#include "pch_common.h" +#include "pch_debug.h" +#include "pch_pcieqos.h" +#include "pch_pcieqos_hal.h" + +#define MODULE_NAME "pch_pcieqos" + +/* global variables */ +s32 ioh_pcieqos_opencount; /* check whether opened or not */ + +DEFINE_SPINLOCK(ioh_pcieqos_lock); /* for spin lock */ + +/** + * file_operations structure initialization + */ +const struct file_operations ioh_pcieqos_fops = { + .owner = THIS_MODULE, + .open = ioh_pcieqos_open, + .release = ioh_pcieqos_release, + .ioctl = ioh_pcieqos_ioctl, +}; + +/*function implementations*/ + +/*! @ingroup PCIEQOS_InterfaceLayerAPI + @fn int ioh_pcieqos_open( struct inode *inode,struct file *file) + @remarks Implements the Initializing and opening of the pcieqos module. + @param inode [@ref INOUT] Contains the reference of the inode + structure + @param file [@ref INOUT] Contains the reference of the file structure + @retval returnvalue [@ref OUT] contains the result for the concerned + attempt. + The result would generally comprise of success code + or failure code. The failure code will indicate reason for + failure. + @see + EBUSY + */ +int ioh_pcieqos_open(struct inode *inode, struct file *file) +{ + int ret; + + spin_lock(&ioh_pcieqos_lock); + IOH_DEBUG("ioh_pcieqos_open : open count value = %d", + ioh_pcieqos_opencount); + if (ioh_pcieqos_opencount) { + IOH_LOG(KERN_ERR, + "ioh_pcieqos_open : device already opened\n"); + ret = -EBUSY; + } else { + ioh_pcieqos_opencount++; + ret = IOH_PCIEQOS_SUCCESS; + } + spin_unlock(&ioh_pcieqos_lock); + + IOH_DEBUG("ioh_pcieqos_open returns=%d\n", ret); + return ret; +} + +/*! @ingroup PCIEQOS_InterfaceLayerAPI + @fn int ioh_pcieqos_release(struct inode *inode,struct file *file) + @remarks Implements the release functionality of the pcieqos module. + @param inode [@ref INOUT] Contains the reference of the inode + structure + @param file [@ref INOUT] Contains the reference of the file structure + @retval returnvalue [@ref OUT] contains the result for the concerned + attempt. + The result would generally comprise of success code + or failure code. The failure code will indicate reason for + failure. + @see + SUCCESS + */ +int ioh_pcieqos_release(struct inode *inode, struct file *file) +{ + spin_lock(&ioh_pcieqos_lock); + + if (ioh_pcieqos_opencount > 0) + ioh_pcieqos_opencount--; + spin_unlock(&ioh_pcieqos_lock); + + IOH_DEBUG("ioh_pcieqos_release : ioh_pcieqos_opencount =%d\n", + ioh_pcieqos_opencount); + + IOH_DEBUG("ioh_pcieqos_release returning=%d\n", IOH_PCIEQOS_SUCCESS); + return IOH_PCIEQOS_SUCCESS; +} + +/*! @ingroup PCIEQOS_InterfaceLayerAPI + @fn int ioh_pcieqos_ioctl(struct inode * inode,struct file * file, + unsigned int cmd,unsigned long arg) + @remarks Implements the various ioctl functionalities of the pcieqos module. + @param inode [@ref INOUT] Contains the reference of the inode + structure + @param file [@ref INOUT] Contains the reference of the file structure + @param cmd [@ref IN] Contains the command value + @param arg [@ref IN] Contains the command argument value + @retval returnvalue [@ref OUT] contains the result for the concerned + attempt. + The result would generally comprise of success code + or failure code. The failure code will indicate reason for + failure. + @see + EINVAL + EFAULT + */ +int ioh_pcieqos_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + + int ret_value = IOH_PCIEQOS_SUCCESS; + struct ioh_pcieqos_reqt *p_ioh_pcieqos_reqt; + unsigned long addr_offset; + unsigned long data; + unsigned long mask; + + do { + if (ioh_pcieqos_suspended == true) { + IOH_LOG(KERN_ERR, + "ioh_pcieqos_ioctl : suspend initiated\ + returning =%d\n", + IOH_PCIEQOS_FAIL); + ret_value = IOH_PCIEQOS_FAIL; + break; + } + + p_ioh_pcieqos_reqt = (struct ioh_pcieqos_reqt *)arg; + ret_value = + copy_from_user((void *)&addr_offset, + (void *)&p_ioh_pcieqos_reqt->addr_offset, + sizeof(addr_offset)); + if (ret_value) { + IOH_LOG(KERN_ERR, + "ioh_pcieqos_ioctl : copy_from_user fail\ + returning =%d\n", + -EFAULT); + ret_value = -EFAULT; + break; + } + IOH_DEBUG("ioh_pcieqos_ioctl : copy_from_user returns =%d\n", + ret_value); + + switch (cmd) { + case IOCTL_PCIEQOS_READ_REG: + { + + ioh_pcieqos_read_reg(addr_offset, &data); + IOH_DEBUG + ("ioh_pcieqos_ioctl : Invoked\ + ioh_pcieqos_read_reg successfully\n"); + + ret_value = + copy_to_user((void *)&p_ioh_pcieqos_reqt-> + data, (void *)&data, + sizeof(data)); + if (ret_value) { + IOH_LOG(KERN_ERR, + "ioh_pcieqos_ioctl :\ + copy_to_user fail returning =%d\n", + -EFAULT); + ret_value = -EFAULT; + break; + } + break; + } + + case IOCTL_PCIEQOS_WRITE_REG: + { + + ret_value = + copy_from_user((void *)&data, + (void *)&p_ioh_pcieqos_reqt-> + data, sizeof(data)); + if (ret_value) { + IOH_LOG(KERN_ERR, + "ioh_pcieqos_ioctl :\ + copy_from_user fail returning =%d\n", + -EFAULT); + ret_value = -EFAULT; + break; + } + ioh_pcieqos_write_reg(addr_offset, data); + IOH_DEBUG + ("ioh_pcieqos_ioctl : Invoked\ + ioh_pcieqos_write_reg successfully\n"); + break; + } + + case IOCTL_PCIEQOS_READ_MODIFY_WRITE_REG: + { + + ret_value = + copy_from_user((void *)&data, + (void *)&p_ioh_pcieqos_reqt-> + data, sizeof(data)); + if (ret_value) { + IOH_LOG(KERN_ERR, + "ioh_pcieqos_ioctl :\ + copy_from_user fail returning =%d\n", + -EFAULT); + ret_value = -EFAULT; + break; + } + ret_value = + copy_from_user((void *)&mask, + (void *)&p_ioh_pcieqos_reqt-> + mask, sizeof(mask)); + if (ret_value) { + IOH_LOG(KERN_ERR, + "ioh_pcieqos_ioctl :\ + copy_from_user fail returning =%d\n", + -EFAULT); + ret_value = -EFAULT; + break; + } + ioh_pcieqos_read_modify_write_reg(addr_offset, + data, mask); + IOH_DEBUG + ("ioh_pcieqos_ioctl : Invoked\ + ioh_pcieqos_read_modify_write_reg successfully\n"); + break; + } + + case IOCTL_PCIEQOS_READ_OROM: + { + + ret_value = + ioh_pcieqos_read_serial_rom(addr_offset, + (unsigned char *)&data); + if (ret_value) { + IOH_LOG(KERN_ERR, + "ioh_pcieqos_ioctl :\ + Invoked ioh_pcieqos_read_serial_rom =%d\n", + -EFAULT); + ret_value = -EFAULT; + break; + } else { + IOH_DEBUG + ("ioh_pcieqos_ioctl :\ + Invoked ioh_pcieqos_read_serial_rom successfully\n"); + } + + ret_value = + copy_to_user((void *)&p_ioh_pcieqos_reqt-> + data, (void *)&data, + sizeof(data)); + if (ret_value) { + IOH_LOG(KERN_ERR, + "ioh_pcieqos_ioctl :\ + copy_to_user fail returning =%d\n", + -EFAULT); + ret_value = -EFAULT; + break; + } + break; + } + + case IOCTL_PCIEQOS_WRITE_OROM: + { + + ret_value = + copy_from_user((void *)&data, + (void *)&p_ioh_pcieqos_reqt-> + data, sizeof(data)); + if (ret_value) { + IOH_LOG(KERN_ERR, + "ioh_pcieqos_ioctl :\ + copy_from_user fail returning =%d\n", + -EFAULT); + ret_value = -EFAULT; + break; + } + ret_value = + ioh_pcieqos_write_serial_rom(addr_offset, + data); + if (ret_value) { + IOH_LOG(KERN_ERR, + "ioh_pcieqos_ioctl :\ + Invoked ioh_pcieqos_write_serial_rom =%d\n", + -EFAULT); + ret_value = -EFAULT; + break; + } else { + IOH_DEBUG + ("ioh_pcieqos_ioctl :\ + Invoked ioh_pcieqos_write_serial_rom successfully\n"); + } + break; + } + + case IOCTL_PCIEQOS_READ_MAC_ADDR: + { + + ioh_pcieqos_read_gbe_mac_addr(addr_offset, + (unsigned char *)&data); + IOH_DEBUG + ("ioh_pcieqos_ioctl : Invoked\ + ioh_pcieqos_read_gbe_mac_addr successfully\n"); + + ret_value = + copy_to_user((void *)&p_ioh_pcieqos_reqt-> + data, (void *)&data, + sizeof(data)); + if (ret_value) { + IOH_LOG(KERN_ERR, + "ioh_pcieqos_ioctl :\ + copy_to_user fail returning =%d\n", + -EFAULT); + ret_value = -EFAULT; + break; + } + break; + } + + case IOCTL_PCIEQOS_WRITE_MAC_ADDR: + { + + ret_value = + copy_from_user((void *)&data, + (void *)&p_ioh_pcieqos_reqt-> + data, sizeof(data)); + if (ret_value) { + IOH_LOG(KERN_ERR, + "ioh_pcieqos_ioctl :\ + copy_from_user fail returning =%d\n", + -EFAULT); + ret_value = -EFAULT; + break; + } + ioh_pcieqos_write_gbe_mac_addr(addr_offset, + data); + IOH_DEBUG + ("ioh_pcieqos_ioctl : Invoked\ + ioh_pcieqos_write_gbe_mac_addr successfully\n"); + break; + } + + default: + { + IOH_LOG(KERN_ERR, + "ioh_write_ioctl invalid command\ + returning=%d\n", + -EINVAL); + ret_value = -EINVAL; + break; + } + } + break; + + } while (0); + IOH_LOG(KERN_ERR, "ioh_write_ioctl returns=%d\n", ret_value); + return ret_value; +} diff -urN linux-2.6.33-rc3/drivers/char/pch_pcieqos/pch_pcieqos.h topcliff-2.6.33-rc3/drivers/char/pch_pcieqos/pch_pcieqos.h --- linux-2.6.33-rc3/drivers/char/pch_pcieqos/pch_pcieqos.h 1970-01-01 09:00:00.000000000 +0900 +++ topcliff-2.6.33-rc3/drivers/char/pch_pcieqos/pch_pcieqos.h 2010-03-08 12:14:32.000000000 +0900 @@ -0,0 +1,196 @@ +#ifndef __IOH_PCIEQOS_H__ +#define __IOH_PCIEQOS_H__ +/*! + * @file ioh_pcieqos.h + * @brief Provides all the interfaces pertaining to the PCIEQOS module. + * @version 1.0.0.0 + * @section + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * History: + * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. + * All rights reserved. + * + * created: + * OKI SEMICONDUCTOR 06/20/2009 + * modified: + * + */ + +/*! @defgroup PCIEQOS */ +/*! @defgroup PCIEQOS_Global Global + @ingroup PCIEQOS */ +/*! @defgroup PCIEQOS_GlobalGeneral General + @ingroup PCIEQOS_Global */ +/*! @defgroup PCIEQOS_GlobalResultCodes StatusCodes + @ingroup PCIEQOS_Global */ +/*! @defgroup PCIEQOS_InterfaceLayer InterfaceLayer + @ingroup PCIEQOS */ +/*! @defgroup PCIEQOS_InterfaceLayerAPI Providers + @ingroup PCIEQOS_InterfaceLayer + */ +/*! @defgroup PCIEQOS_InterfaceLayerNotifyRoutines Notifiers + @ingroup PCIEQOS_InterfaceLayer + */ +/*! @defgroup PCIEQOS_PCILayer PCILayer + @ingroup PCIEQOS */ +/*! @defgroup PCIEQOS_PCILayerAPI Providers + @ingroup PCIEQOS_PCILayer + */ +/*! @defgroup PCIEQOS_PCILayerFacilitators Facilitators + @ingroup PCIEQOS_PCILayer + */ +/*! @defgroup PCIEQOS_HALLayer HALLayer + @ingroup PCIEQOS */ +/*! @defgroup PCIEQOS_HALLayerAPI Providers + @ingroup PCIEQOS_HALLayer + */ +/*! @defgroup PCIEQOS_HALLayerFacilitators Facilitators + @ingroup PCIEQOS_HALLayer + */ +/*! @defgroup PCIEQOS_Utilities Utilities + @ingroup PCIEQOS */ +/*! @defgroup PCIEQOS_UtilitiesAPI Providers + @ingroup PCIEQOS_Utilities + */ + +/*! @ingroup PCIEQOS_InterfaceLayer + @def PCIEQOS_IOCTL_MAGIC + @brief Outlines the ioctl magic. + */ +#define PCIEQOS_IOCTL_MAGIC (0xf7) + +/*! @ingroup PCIEQOS_InterfaceLayer + @def IOCTL_PCIEQOS_READ_REG + @brief Outlines the read register function signature. + */ +#define IOCTL_PCIEQOS_READ_REG (_IOW(PCIEQOS_IOCTL_MAGIC, 1, unsigned long)) + +/*! @ingroup PCIEQOS_InterfaceLayer + @def IOCTL_PCIEQOS_WRITE_REG + @brief Outlines the write register function signature. + */ +#define IOCTL_PCIEQOS_WRITE_REG (_IOW(PCIEQOS_IOCTL_MAGIC, 2, unsigned long)) + +/*! @ingroup PCIEQOS_InterfaceLayer + @def IOCTL_PCIEQOS_READ_MODIFY_WRITE_REG + @brief Outlines the read, modify and write register function signature. + */ +#define IOCTL_PCIEQOS_READ_MODIFY_WRITE_REG (_IOW(PCIEQOS_IOCTL_MAGIC, 3,\ + unsigned long)) + +/*! @ingroup PCIEQOS_InterfaceLayer + @def IOCTL_PCIEQOS_READ_OROM + @brief Outlines the read option rom function signature. + */ +#define IOCTL_PCIEQOS_READ_OROM (_IOW(PCIEQOS_IOCTL_MAGIC, 4, unsigned long)) + +/*! @ingroup PCIEQOS_InterfaceLayer + @def IOCTL_PCIEQOS_WRITE_OROM + @brief Outlines the write option rom function signature. + */ +#define IOCTL_PCIEQOS_WRITE_OROM (_IOW(PCIEQOS_IOCTL_MAGIC, 5, unsigned long)) + +/*! @ingroup PCIEQOS_InterfaceLayer + @def IOCTL_PCIEQOS_READ_MAC_ADDR + @brief Outlines the read mac address function signature. + */ +#define IOCTL_PCIEQOS_READ_MAC_ADDR (_IOW(PCIEQOS_IOCTL_MAGIC, 6,\ + unsigned long)) + +/*! @ingroup PCIEQOS_InterfaceLayer + @def IOCTL_PCIEQOS_WRITE_MAC_ADDR + @brief Outlines the write mac address function signature. + */ +#define IOCTL_PCIEQOS_WRITE_MAC_ADDR (_IOW(PCIEQOS_IOCTL_MAGIC, 7,\ + unsigned long)) + +/*! @ingroup PCIEQOS_InterfaceLayer + @def PCIEQOS STATUS CODE + @brief Outlines PCIEQOS SUCCESS STATUS CODE + */ +#define IOH_PCIEQOS_SUCCESS (0) + +/*! @ingroup PCIEQOS_InterfaceLayer + @def PCIEQOS STATUS CODE + @brief Outlines PCIEQOS ERROR STATUS CODE + */ +#define IOH_PCIEQOS_FAIL (-1) + +/* Registers address offset */ +#define IOH_PCIEQOS_PHUB_ID_REG (0x0000) +#define IOH_PCIEQOS_QUEUE_PRI_VAL_REG (0x0004) +#define IOH_PCIEQOS_RC_QUEUE_MAXSIZE_REG (0x0008) +#define IOH_PCIEQOS_BRI_QUEUE_MAXSIZE_REG (0x000C) +#define IOH_PCIEQOS_COMP_RESP_TIMEOUT_REG (0x0010) +#define IOH_PCIEQOS_BUS_SLAVE_CONTROL_REG (0x0014) +#define IOH_PCIEQOS_DEADLOCK_AVOID_TYPE_REG (0x0018) +#define IOH_PCIEQOS_INTPIN_REG_WPERMIT_REG0 (0x0020) +#define IOH_PCIEQOS_INTPIN_REG_WPERMIT_REG1 (0x0024) +#define IOH_PCIEQOS_INTPIN_REG_WPERMIT_REG2 (0x0028) +#define IOH_PCIEQOS_INTPIN_REG_WPERMIT_REG3 (0x002C) +#define IOH_PCIEQOS_INT_REDUCE_CONTROL_REG_BASE (0x0040) +#define CLKCFG_REG_OFFSET (0x500) + +/*structures*/ +/*! @ingroup PCIEQOS_InterfaceLayer + @struct ioh_pcieqos_reqt + @brief It is a structure used for perserving information related to the + pcieqos request. + @note + The concerned details should be provided during the read register, + write register and read / modify / write register. + @see + ioh_pcieqos_ioctl + */ +struct ioh_pcieqos_reqt { + unsigned long addr_offset; /*specifies the register address + offset */ + unsigned long data; /*specifies the data */ + unsigned long mask; /*specifies the mask */ +}; + +/* exported function prototypes */ +/*! @ingroup PCIEQOS_InterfaceLayerAPI + @fn nt ioh_pcieqos_open( struct inode *inode,struct file *file ) + @brief Provides the functionality of initialization of the module + */ +int ioh_pcieqos_open(struct inode *inode, struct file *file); + +/*! @ingroup PCIEQOS_InterfaceLayerAPI + @fn int ioh_pcieqos_release(struct inode *inode,struct file *file) + @brief Provides the functionality of releasing the module + */ +int ioh_pcieqos_release(struct inode *inode, struct file *file); + +/*! @ingroup PCIEQOS_InterfaceLayerAPI + @fn int ioh_pcieqos_ioctl(struct inode * inode,struct file * file, + unsigned int cmd, + unsigned long arg) + @brief Provides the functionality of invoking various functionalities of + the PCIEQOS. + */ +int ioh_pcieqos_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg); + +/**global variables*/ +extern u32 ioh_pcieqos_base_address; /* base address */ +extern s32 ioh_pcieqos_suspended; /* suspend status */ + +extern s32 ioh_pcieqos_opencount; +extern spinlock_t ioh_pcieqos_lock; +extern const struct file_operations ioh_pcieqos_fops; +#endif diff -urN linux-2.6.33-rc3/drivers/char/pch_pcieqos/pch_pcieqos_hal.c topcliff-2.6.33-rc3/drivers/char/pch_pcieqos/pch_pcieqos_hal.c --- linux-2.6.33-rc3/drivers/char/pch_pcieqos/pch_pcieqos_hal.c 1970-01-01 09:00:00.000000000 +0900 +++ topcliff-2.6.33-rc3/drivers/char/pch_pcieqos/pch_pcieqos_hal.c 2010-03-08 17:51:33.000000000 +0900 @@ -0,0 +1,550 @@ +/*! + * @file ioh_pcieqos_hal.c + * @brief Provides all the implementation of the interfaces pertaining to the + * HAL. + * @version 1.0.0.0 + * @section + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * History: + * Copyright (C) 2009 OKI SEMICONDUCTOR Co., LTD. + * All rights reserved. + * + * created: + * OKI SEMICONDUCTOR 06/20/2009 + * modified: + * + */ + +/*includes*/ +#include +#include +#include +#include +#include +#include "pch_common.h" +#include "pch_debug.h" +#include "pch_pcieqos.h" +#include "pch_pcieqos_hal.h" + +/* Status Register offset */ +#define PCIEQOS_STATUS (0x00) + +/* Control Register offset */ +#define PCIEQOS_CONTROL (0x04) + +/* Time out value for Status Register */ +#define PCIEQOS_TIMEOUT (0x05) + +/* Enabling for writing ROM */ +#define IOH_PCIEQOS_ROM_WRITE_ENABLE (0x01) + +/* Disabling for writing ROM */ +#define IOH_PCIEQOS_ROM_WRITE_DISABLE (0x00) + +/* ROM data area start address offset */ +#define IOH_PCIEQOS_ROM_START_ADDR (0x14) + +/* MAX number of INT_REDUCE_CONTROL registers */ +#define MAX_NUM_INT_REDUCE_CONTROL_REG (128) + +/* global variables */ +struct ioh_pcieqos_reg { + u32 phub_id_reg; /* PHUB_ID register val */ + u32 q_pri_val_reg; /* QUEUE_PRI_VAL register val */ + u32 rc_q_maxsize_reg; /* RC_QUEUE_MAXSIZE register val */ + u32 bri_q_maxsize_reg; /* BRI_QUEUE_MAXSIZE register val */ + u32 comp_resp_timeout_reg; /* COMP_RESP_TIMEOUT register val */ + u32 bus_slave_control_reg; /* BUS_SLAVE_CONTROL_REG register val */ + u32 deadlock_avoid_type_reg; /* DEADLOCK_AVOID_TYPE register val */ + u32 intpin_reg_wpermit_reg0; /* INTPIN_REG_WPERMIT register 0 val */ + u32 intpin_reg_wpermit_reg1; /* INTPIN_REG_WPERMIT register 1 val */ + u32 intpin_reg_wpermit_reg2; /* INTPIN_REG_WPERMIT register 2 val */ + u32 intpin_reg_wpermit_reg3; /* INTPIN_REG_WPERMIT register 3 val */ + /* INT_REDUCE_CONTROL registers val */ + u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG]; +#ifdef IOH_CAN_PCLK_50MHZ + u32 clkcfg_reg; /* CLK CFG register val */ +#endif +} g_ioh_pcieqos_reg; + +/*functions implementations*/ +/*! @ingroup PCIEQOS_HALLayerAPI + @fn void ioh_pcieqos_read_reg(unsigned long reg_addr_offset, + unsigned long *data) + @remarks Implements the functionality of reading register. + @param reg_addr_offset [@ref IN] Contains the register offset address value + @param *data [@ref INOUT] Contains the register value + @retval NONE + @see + */ +void ioh_pcieqos_read_reg(unsigned long reg_addr_offset, unsigned long *data) +{ + unsigned long reg_addr = ioh_pcieqos_base_address + reg_addr_offset; + *data = IOH_READ32(reg_addr); + + return; +} + +/*! @ingroup PCIEQOS_HALLayerAPI + @fn void ioh_pcieqos_write_reg(unsigned long reg_addr_offset, + unsigned long data) + @remarks Implements the functionality of writing register. + @param reg_addr_offset [@ref IN] Contains the register offset address value + @param data [@ref IN] Contains the writing value + @retval NONE + @see + */ +void ioh_pcieqos_write_reg(unsigned long reg_addr_offset, unsigned long data) +{ + unsigned long reg_addr = ioh_pcieqos_base_address + reg_addr_offset; + IOH_WRITE32(data, reg_addr); + + return; +} + +/*! @ingroup PCIEQOS_HALLayerAPI + @fn void ioh_pcieqos_read_modify_write_reg(unsigned long reg_addr_offset, + unsigned long data, unsigned long mask) + @remarks Implements the functionality of reading, modifying and writing + register. + @param reg_addr_offset [@ref IN] Contains the register offset address value + @param data [@ref IN] Contains the writing value + @param mask [@ref IN] Contains the mask value + @retval NONE + @see + */ +void ioh_pcieqos_read_modify_write_reg(unsigned long reg_addr_offset, + unsigned long data, unsigned long mask) +{ + unsigned long reg_addr = ioh_pcieqos_base_address + reg_addr_offset; + IOH_WRITE32(((IOH_READ32(reg_addr) & ~mask)) | data, reg_addr); + + return; +} + +/*! @ingroup PCIEQOS_HALLayerAPI + @fn int ioh_pcieqos_read_gbe_mac_addr(unsigned long offset_address, + unsigned char *data) + @param unsigned long offset_address [@ref IN] Contains the Gigabit + Ethernet MAC address offset value + @param *data [@ref INOUT] Contains the Gigabit + Ethernet MAC address value + @retval return value [@ref OUT] contains the result + for the reading Gigabit Ethernet MAC address attempt + @see + */ +int ioh_pcieqos_read_gbe_mac_addr(unsigned long offset_address, + unsigned char *data) +{ + int retval = IOH_PCIEQOS_SUCCESS; + + retval = ioh_pcieqos_read_serial_rom_val(offset_address, data); + + return retval; +} +EXPORT_SYMBOL(ioh_pcieqos_read_gbe_mac_addr); + +/*! @ingroup PCIEQOS_HALLayerAPI + @fn int ioh_pcieqos_write_gbe_mac_addr(unsigned long offset_address, + unsigned char data) + @param unsigned long offset_address [@ref IN] Contains the Gigabit + Ethernet MAC address offset value + @param data [@ref IN] Contains the Gigabit Ethernet + MAC address value + @retval return value [@ref OUT] contains the result for the + writing Gigabit Ethernet MAC address attempt + @see + */ +int ioh_pcieqos_write_gbe_mac_addr(unsigned long offset_address, + unsigned char data) +{ + int retval = IOH_PCIEQOS_SUCCESS; + + retval = ioh_pcieqos_gbe_serial_rom_conf(); + retval |= ioh_pcieqos_write_serial_rom_val(offset_address, data); + + return retval; +} +EXPORT_SYMBOL(ioh_pcieqos_write_gbe_mac_addr); + +/*! @ingroup PCIEQOS_HALLayerAPI + @fn void ioh_pcieqos_save_reg_conf(void) + @remarks saves register configuration + @param NONE + @retval NONE + @see + ioh_pcieqos_suspend + */ +void ioh_pcieqos_save_reg_conf(void) +{ + u32 base_addr = ioh_pcieqos_base_address; + u32 i = 0; + + IOH_DEBUG("ioh_pcieqos_save_reg_conf ENTRY\n"); + /* to store contents of PHUB_ID register */ + g_ioh_pcieqos_reg.phub_id_reg = + IOH_READ32(base_addr + IOH_PCIEQOS_PHUB_ID_REG); + /* to store contents of QUEUE_PRI_VAL register */ + g_ioh_pcieqos_reg.q_pri_val_reg = + IOH_READ32(base_addr + IOH_PCIEQOS_QUEUE_PRI_VAL_REG); + /* to store contents of RC_QUEUE_MAXSIZE register */ + g_ioh_pcieqos_reg.rc_q_maxsize_reg = + IOH_READ32(base_addr + IOH_PCIEQOS_RC_QUEUE_MAXSIZE_REG); + /* to store contents of BRI_QUEUE_MAXSIZE register */ + g_ioh_pcieqos_reg.bri_q_maxsize_reg = + IOH_READ32(base_addr + IOH_PCIEQOS_BRI_QUEUE_MAXSIZE_REG); + /* to store contents of COMP_RESP_TIMEOUT register */ + g_ioh_pcieqos_reg.comp_resp_timeout_reg = + IOH_READ32(base_addr + IOH_PCIEQOS_COMP_RESP_TIMEOUT_REG); + /* to store contents of BUS_SLAVE_CONTROL_REG register */ + g_ioh_pcieqos_reg.bus_slave_control_reg = + IOH_READ32(base_addr + IOH_PCIEQOS_BUS_SLAVE_CONTROL_REG); + /* to store contents of DEADLOCK_AVOID_TYPE register */ + g_ioh_pcieqos_reg.deadlock_avoid_type_reg = + IOH_READ32(base_addr + IOH_PCIEQOS_DEADLOCK_AVOID_TYPE_REG); + /* to store contents of INTPIN_REG_WPERMIT register 0 */ + g_ioh_pcieqos_reg.intpin_reg_wpermit_reg0 = + IOH_READ32(base_addr + IOH_PCIEQOS_INTPIN_REG_WPERMIT_REG0); + /* to store contents of INTPIN_REG_WPERMIT register 1 */ + g_ioh_pcieqos_reg.intpin_reg_wpermit_reg1 = + IOH_READ32(base_addr + IOH_PCIEQOS_INTPIN_REG_WPERMIT_REG1); + /* to store contents of INTPIN_REG_WPERMIT register 2 */ + g_ioh_pcieqos_reg.intpin_reg_wpermit_reg2 = + IOH_READ32(base_addr + IOH_PCIEQOS_INTPIN_REG_WPERMIT_REG2); + /* to store contents of INTPIN_REG_WPERMIT register 3 */ + g_ioh_pcieqos_reg.intpin_reg_wpermit_reg3 = + IOH_READ32(base_addr + IOH_PCIEQOS_INTPIN_REG_WPERMIT_REG3); + IOH_DEBUG + ("ioh_pcieqos_save_reg_conf : g_ioh_pcieqos_reg.phub_id_reg=%x, \ + g_ioh_pcieqos_reg.q_pri_val_reg=%x, \ + g_ioh_pcieqos_reg.rc_q_maxsize_reg=%x, \ + g_ioh_pcieqos_reg.bri_q_maxsize_reg=%x, \ + g_ioh_pcieqos_reg.comp_resp_timeout_reg=%x, \ + g_ioh_pcieqos_reg.bus_slave_control_reg=%x, \ + g_ioh_pcieqos_reg.deadlock_avoid_type_reg=%x, \ + g_ioh_pcieqos_reg.intpin_reg_wpermit_reg0=%x, \ + g_ioh_pcieqos_reg.intpin_reg_wpermit_reg1=%x, \ + g_ioh_pcieqos_reg.intpin_reg_wpermit_reg2=%x, \ + g_ioh_pcieqos_reg.intpin_reg_wpermit_reg3=%x\n", + g_ioh_pcieqos_reg.phub_id_reg, + g_ioh_pcieqos_reg.q_pri_val_reg, + g_ioh_pcieqos_reg.rc_q_maxsize_reg, + g_ioh_pcieqos_reg.bri_q_maxsize_reg, + g_ioh_pcieqos_reg.comp_resp_timeout_reg, + g_ioh_pcieqos_reg.bus_slave_control_reg, + g_ioh_pcieqos_reg.deadlock_avoid_type_reg, + g_ioh_pcieqos_reg.intpin_reg_wpermit_reg0, + g_ioh_pcieqos_reg.intpin_reg_wpermit_reg1, + g_ioh_pcieqos_reg.intpin_reg_wpermit_reg2, + g_ioh_pcieqos_reg.intpin_reg_wpermit_reg3); + /* to store contents of INT_REDUCE_CONTROL registers */ + for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) { + g_ioh_pcieqos_reg.int_reduce_control_reg[i] = + IOH_READ32(base_addr + + IOH_PCIEQOS_INT_REDUCE_CONTROL_REG_BASE + 4 * i); + IOH_DEBUG + ("ioh_pcieqos_save_reg_conf : \ + g_ioh_pcieqos_reg.int_reduce_control_reg[%d]=%x\n", + i, g_ioh_pcieqos_reg.int_reduce_control_reg[i]); + } +#ifdef IOH_CAN_PCLK_50MHZ + /* save clk cfg register */ + g_ioh_pcieqos_reg.clkcfg_reg = + IOH_READ32(base_addr + CLKCFG_REG_OFFSET); +#endif + return; +} + +/*! @ingroup PCIEQOS_HALLayerAPI + @fn void ioh_pcieqos_restore_reg_conf(void) + @remarks restore register configuration + @param NONE + @retval NONE + @see + ioh_pcieqos_resume + */ +void ioh_pcieqos_restore_reg_conf(void) +{ + u32 base_addr = ioh_pcieqos_base_address; + u32 i = 0; + + IOH_DEBUG("ioh_pcieqos_restore_reg_conf ENTRY\n"); + /* to store contents of PHUB_ID register */ + IOH_WRITE32(g_ioh_pcieqos_reg.phub_id_reg, + base_addr + IOH_PCIEQOS_PHUB_ID_REG); + /* to store contents of QUEUE_PRI_VAL register */ + IOH_WRITE32(g_ioh_pcieqos_reg.q_pri_val_reg, + base_addr + IOH_PCIEQOS_QUEUE_PRI_VAL_REG); + /* to store contents of RC_QUEUE_MAXSIZE register */ + IOH_WRITE32(g_ioh_pcieqos_reg.rc_q_maxsize_reg, + base_addr + IOH_PCIEQOS_RC_QUEUE_MAXSIZE_REG); + /* to store contents of BRI_QUEUE_MAXSIZE register */ + IOH_WRITE32(g_ioh_pcieqos_reg.bri_q_maxsize_reg, + base_addr + IOH_PCIEQOS_BRI_QUEUE_MAXSIZE_REG); + /* to store contents of COMP_RESP_TIMEOUT register */ + IOH_WRITE32(g_ioh_pcieqos_reg.comp_resp_timeout_reg, + base_addr + IOH_PCIEQOS_COMP_RESP_TIMEOUT_REG); + /* to store contents of BUS_SLAVE_CONTROL_REG register */ + IOH_WRITE32(g_ioh_pcieqos_reg.bus_slave_control_reg, + base_addr + IOH_PCIEQOS_BUS_SLAVE_CONTROL_REG); + /* to store contents of DEADLOCK_AVOID_TYPE register */ + IOH_WRITE32(g_ioh_pcieqos_reg.deadlock_avoid_type_reg, + base_addr + IOH_PCIEQOS_DEADLOCK_AVOID_TYPE_REG); + /* to store contents of INTPIN_REG_WPERMIT register 0 */ + IOH_WRITE32(g_ioh_pcieqos_reg.intpin_reg_wpermit_reg0, + base_addr + IOH_PCIEQOS_INTPIN_REG_WPERMIT_REG0); + /* to store contents of INTPIN_REG_WPERMIT register 1 */ + IOH_WRITE32(g_ioh_pcieqos_reg.intpin_reg_wpermit_reg1, + base_addr + IOH_PCIEQOS_INTPIN_REG_WPERMIT_REG1); + /* to store contents of INTPIN_REG_WPERMIT register 2 */ + IOH_WRITE32(g_ioh_pcieqos_reg.intpin_reg_wpermit_reg2, + base_addr + IOH_PCIEQOS_INTPIN_REG_WPERMIT_REG2); + /* to store contents of INTPIN_REG_WPERMIT register 3 */ + IOH_WRITE32(g_ioh_pcieqos_reg.intpin_reg_wpermit_reg3, + base_addr + IOH_PCIEQOS_INTPIN_REG_WPERMIT_REG3); + IOH_DEBUG + ("ioh_pcieqos_save_reg_conf : g_ioh_pcieqos_reg.phub_id_reg=%x, \ + g_ioh_pcieqos_reg.q_pri_val_reg=%x, \ + g_ioh_pcieqos_reg.rc_q_maxsize_reg=%x, \ + g_ioh_pcieqos_reg.bri_q_maxsize_reg=%x, \ + g_ioh_pcieqos_reg.comp_resp_timeout_reg=%x, \ + g_ioh_pcieqos_reg.bus_slave_control_reg=%x, \ + g_ioh_pcieqos_reg.deadlock_avoid_type_reg=%x, \ + g_ioh_pcieqos_reg.intpin_reg_wpermit_reg0=%x, \ + g_ioh_pcieqos_reg.intpin_reg_wpermit_reg1=%x, \ + g_ioh_pcieqos_reg.intpin_reg_wpermit_reg2=%x, \ + g_ioh_pcieqos_reg.intpin_reg_wpermit_reg3=%x\n", + g_ioh_pcieqos_reg.phub_id_reg, g_ioh_pcieqos_reg.q_pri_val_reg, + g_ioh_pcieqos_reg.rc_q_maxsize_reg, + g_ioh_pcieqos_reg.bri_q_maxsize_reg, + g_ioh_pcieqos_reg.comp_resp_timeout_reg, + g_ioh_pcieqos_reg.bus_slave_control_reg, + g_ioh_pcieqos_reg.deadlock_avoid_type_reg, + g_ioh_pcieqos_reg.intpin_reg_wpermit_reg0, + g_ioh_pcieqos_reg.intpin_reg_wpermit_reg1, + g_ioh_pcieqos_reg.intpin_reg_wpermit_reg2, + g_ioh_pcieqos_reg.intpin_reg_wpermit_reg3); + /* to store contents of INT_REDUCE_CONTROL register */ + for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) { + IOH_WRITE32(g_ioh_pcieqos_reg.int_reduce_control_reg[i], + base_addr + + IOH_PCIEQOS_INT_REDUCE_CONTROL_REG_BASE + 4 * i); + IOH_DEBUG + ("ioh_pcieqos_save_reg_conf : \ + g_ioh_pcieqos_reg.int_reduce_control_reg[%d]=%x\n", + i, g_ioh_pcieqos_reg.int_reduce_control_reg[i]); + } + +#ifdef IOH_CAN_PCLK_50MHZ + /*restore the clock config reg */ + IOH_WRITE32(g_ioh_pcieqos_reg.clkcfg_reg, + base_addr + CLKCFG_REG_OFFSET); +#endif + + return; +} + +/*! @ingroup PCIEQOS_HALLayerAPI + @fn void ioh_pcieqos_read_serial_rom(unsigned long offset_address, + unsigned char *data) + @remarks Implements the functionality of reading Serial ROM. + @param unsigned long offset_address [@ref IN] Contains the Serial ROM + address offset value + @param *data [@ref INOUT] Contains the Serial + ROM value + @retval returnvalue [@ref OUT] contains the result for the reading Serial + ROM attempt + @see + */ +int ioh_pcieqos_read_serial_rom(unsigned long offset_address, + unsigned char *data) +{ + unsigned long mem_addr = + ioh_pcieqos_extrom_base_address + offset_address; + + IOH_DEBUG("ioh_pcieqos_read_serial_rom:mem_addr=0x%08x\n", mem_addr); + *data = IOH_READ8(mem_addr); + + return IOH_PCIEQOS_SUCCESS; +} + +/*! @ingroup PCIEQOS_HALLayerAPI + @fn void ioh_pcieqos_write_serial_rom(unsigned long offset_address, + unsigned char data) + @remarks Implements the functionality of writing Serial ROM. + @param unsigned long offset_address [@ref IN] Contains the Serial ROM + address offset value + @param data [@ref IN] Contains the Serial ROM value + @retval returnvalue [@ref OUT] contains the result for the writing Serial + ROM attempt + @see + */ +int ioh_pcieqos_write_serial_rom(unsigned long offset_address, + unsigned char data) +{ + int retval = IOH_PCIEQOS_SUCCESS; + unsigned long mem_addr = + ioh_pcieqos_extrom_base_address + offset_address; + int i = 0; + unsigned long word_data = 0; + + IOH_DEBUG("ioh_pcieqos_write_serial_rom:mem_addr=0x%08x\n", mem_addr); + IOH_WRITE32(IOH_PCIEQOS_ROM_WRITE_ENABLE, + ioh_pcieqos_extrom_base_address + PCIEQOS_CONTROL); + + word_data = IOH_READ32((mem_addr & 0xFFFFFFFC)); + IOH_DEBUG("word_data=0x%08x\n", word_data); + IOH_DEBUG("data=0x%02x\n", data); + switch (mem_addr % 4) { + case 0: + { + word_data &= 0xFFFFFF00; + IOH_WRITE32((word_data | (unsigned long)data), + (mem_addr & 0xFFFFFFFC)); + } + case 1: + { + word_data &= 0xFFFF00FF; + IOH_WRITE32((word_data | ((unsigned long)data << 8)), + (mem_addr & 0xFFFFFFFC)); + } + case 2: + { + word_data &= 0xFF00FFFF; + IOH_WRITE32((word_data | ((unsigned long)data << 16)), + (mem_addr & 0xFFFFFFFC)); + } + case 3: + { + word_data &= 0x00FFFFFF; + IOH_WRITE32((word_data | ((unsigned long)data << 24)), + (mem_addr & 0xFFFFFFFC)); + } + } + while (0x00 != + IOH_READ8(ioh_pcieqos_extrom_base_address + PCIEQOS_STATUS)) { + msleep(1); + if (PCIEQOS_TIMEOUT == i) { + retval = IOH_PCIEQOS_FAIL; + break; + } + i++; + } + + IOH_WRITE32(IOH_PCIEQOS_ROM_WRITE_DISABLE, + ioh_pcieqos_extrom_base_address + PCIEQOS_CONTROL); + + return retval; +} + +/*! @ingroup PCIEQOS_HALLayerAPI + @fn void ioh_pcieqos_read_serial_rom_val(unsigned long offset_address, + unsigned char *data) + @remarks Implements the functionality of reading Serial ROM value. + @param unsigned long offset_address [@ref IN] Contains the Serial ROM + address offset value + @param *data [@ref INOUT] Contains the Serial + ROM value + @retval returnvalue [@ref OUT] contains the result for the reading Serial + ROM attempt + @see + */ +int ioh_pcieqos_read_serial_rom_val(unsigned long offset_address, + unsigned char *data) +{ + int retval = IOH_PCIEQOS_SUCCESS; + unsigned long mem_addr; + + mem_addr = + (offset_address / 4 * 8) + 3 - (offset_address % 4) + + IOH_PCIEQOS_ROM_START_ADDR; + retval = ioh_pcieqos_read_serial_rom(mem_addr, data); + + return retval; +} + +/*! @ingroup PCIEQOS_HALLayerAPI + @fn void ioh_pcieqos_write_serial_rom_val(unsigned long offset_address, + unsigned char data) + @remarks Implements the functionality of writing Serial ROM value. + @param unsigned long offset_address [@ref IN] Contains the Serial ROM + address offset value + @param data [@ref IN] Contains the Serial ROM value + @retval returnvalue [@ref OUT] contains the result for the writing Serial + ROM attempt + @see + */ +int ioh_pcieqos_write_serial_rom_val(unsigned long offset_address, + unsigned char data) +{ + int retval = IOH_PCIEQOS_SUCCESS; + unsigned long mem_addr; + + mem_addr = + (offset_address / 4 * 8) + 3 - (offset_address % 4) + + IOH_PCIEQOS_ROM_START_ADDR; + retval = ioh_pcieqos_write_serial_rom(mem_addr, data); + + return retval; +} + +/*! @ingroup PCIEQOS_HALLayerAPI + @fn int ioh_pcieqos_gbe_serial_rom_conf(void) + @remarks makes Serial ROM header format configuration for Gigabit Ethernet + MAC address + @param NONE + @retval returnvalue [@ref OUT] contains the result for the writing Serial + ROM attempt + @see + */ +int ioh_pcieqos_gbe_serial_rom_conf(void) +{ + int retval = IOH_PCIEQOS_SUCCESS; + + retval |= ioh_pcieqos_write_serial_rom(0x0b, 0xbc); + retval |= ioh_pcieqos_write_serial_rom(0x0a, 0x10); + retval |= ioh_pcieqos_write_serial_rom(0x09, 0x01); + retval |= ioh_pcieqos_write_serial_rom(0x08, 0x02); + + retval |= ioh_pcieqos_write_serial_rom(0x0f, 0x00); + retval |= ioh_pcieqos_write_serial_rom(0x0e, 0x00); + retval |= ioh_pcieqos_write_serial_rom(0x0d, 0x00); + retval |= ioh_pcieqos_write_serial_rom(0x0c, 0x80); + + retval |= ioh_pcieqos_write_serial_rom(0x13, 0xbc); + retval |= ioh_pcieqos_write_serial_rom(0x12, 0x10); + retval |= ioh_pcieqos_write_serial_rom(0x11, 0x01); + retval |= ioh_pcieqos_write_serial_rom(0x10, 0x18); + + retval |= ioh_pcieqos_write_serial_rom(0x1b, 0xbc); + retval |= ioh_pcieqos_write_serial_rom(0x1a, 0x10); + retval |= ioh_pcieqos_write_serial_rom(0x19, 0x01); + retval |= ioh_pcieqos_write_serial_rom(0x18, 0x19); + + retval |= ioh_pcieqos_write_serial_rom(0x23, 0xbc); + retval |= ioh_pcieqos_write_serial_rom(0x22, 0x10); + retval |= ioh_pcieqos_write_serial_rom(0x21, 0x01); + retval |= ioh_pcieqos_write_serial_rom(0x20, 0x3a); + + retval |= ioh_pcieqos_write_serial_rom(0x27, 0x01); + retval |= ioh_pcieqos_write_serial_rom(0x26, 0x00); + retval |= ioh_pcieqos_write_serial_rom(0x25, 0x00); + retval |= ioh_pcieqos_write_serial_rom(0x24, 0x00); + + return retval; +} + diff -urN linux-2.6.33-rc3/drivers/char/pch_pcieqos/pch_pcieqos_hal.h topcliff-2.6.33-rc3/drivers/char/pch_pcieqos/pch_pcieqos_hal.h --- linux-2.6.33-rc3/drivers/char/pch_pcieqos/pch_pcieqos_hal.h 1970-01-01 09:00:00.000000000 +0900 +++ topcliff-2.6.33-rc3/drivers/char/pch_pcieqos/pch_pcieqos_hal.h 2010-03-08 12:02:57.000000000 +0900 @@ -0,0 +1,125 @@ +#ifndef __IOH_PCIEQOS_HAL_H__ +#define __IOH_PCIEQOS_HAL_H__ +/*! + * @file ioh_pcieqos_hal.h + * @brief Provides all the interfaces pertaining to the HAL. + * @version 1.0.0.0 + * @section + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * History: + * Copyright (C) 2009 OKI SEMICONDUCTOR Co., LTD. + * All rights reserved. + * + * created: + * OKI SEMICONDUCTOR 06/20/2009 + * modified: + * + */ + +/* exported function prototypes */ +/*! @ingroup PCIEQOS_HALLayerAPI + @fn void ioh_pcieqos_read_reg(unsigned long reg_addr_offset, + unsigned long *data) + @brief Provides the functionality of reading register + */ +void ioh_pcieqos_read_reg(unsigned long reg_addr_offset, unsigned long *data); + +/*! @ingroup PCIEQOS_HALLayerAPI + @fn ioh_pcieqos_write_reg(unsigned long reg_addr_offset, unsigned long data) + @brief Provides the functionality of writing register + */ +void ioh_pcieqos_write_reg(unsigned long reg_addr_offset, unsigned long data); + +/*! @ingroup PCIEQOS_HALLayerAPI + @fn ioh_pcieqos_read_modify_write_reg(unsigned long reg_addr_offset, + unsigned long data, unsigned long mask) + @brief Provides the functionality of reading, modifying and writing register + */ +void ioh_pcieqos_read_modify_write_reg(unsigned long reg_addr_offset, + unsigned long data, unsigned long mask); + +/*! @ingroup PCIEQOS_HALLayerAPI + @fn int ioh_pcieqos_read_gbe_mac_addr(unsigned long offset_address, + unsigned char *data) + @brief Provides the functionality of reading Gigabit Ethernet MAC address + */ +int ioh_pcieqos_read_gbe_mac_addr(unsigned long offset_address, + unsigned char *data); + +/*! @ingroup PCIEQOS_HALLayerAPI + @fn int ioh_pcieqos_write_gbe_mac_addr(unsigned long offset_address, + unsigned char data) + @brief Provides the functionality of writing Gigabit Ethernet MAC address + */ +int ioh_pcieqos_write_gbe_mac_addr(unsigned long offset_address, + unsigned char data); + +/*! @ingroup PCIEQOS_HALLayerAPI + @fn void ioh_pcieqos_save_reg_conf(void) + @brief saves register configuration + */ +void ioh_pcieqos_save_reg_conf(void); + +/*! @ingroup PCIEQOS_HALLayerAPI + @fn void ioh_pcieqos_restore_reg_conf(void) + @brief restores register configuration + */ +void ioh_pcieqos_restore_reg_conf(void); + +/*! @ingroup PCIEQOS_HALLayerAPI + @fn int ioh_pcieqos_read_serial_rom(unsigned long offset_address, + unsigned char *data) + @brief Provides the functionality of reading Serial ROM + */ +int ioh_pcieqos_read_serial_rom(unsigned long offset_address, + unsigned char *data); + +/*! @ingroup PCIEQOS_HALLayerAPI + @fn int ioh_pcieqos_write_serial_rom(unsigned long offset_address, + unsigned char data) + @brief Provides the functionality of writing Serial ROM + */ +int ioh_pcieqos_write_serial_rom(unsigned long offset_address, + unsigned char data); + +/*! @ingroup PCIEQOS_HALLayerAPI + @fn int ioh_pcieqos_read_serial_rom_val(unsigned long offset_address, + unsigned char *data) + @brief Provides the functionality of reading Serial ROM value + */ +int ioh_pcieqos_read_serial_rom_val(unsigned long offset_address, + unsigned char *data); + +/*! @ingroup PCIEQOS_HALLayerAPI + @fn int ioh_pcieqos_write_serial_rom_val(unsigned long offset_address, + unsigned char data) + @brief Provides the functionality of writing Serial ROM value + */ +int ioh_pcieqos_write_serial_rom_val(unsigned long offset_address, + unsigned char data); + +/*! @ingroup PCIEQOS_HALLayerAPI + @fn int ioh_pcieqos_gbe_serial_rom_conf(void) + @brief makes Serial ROM data format configuration for Gigabit Ethernet + MAC address + */ +int ioh_pcieqos_gbe_serial_rom_conf(void); + +/* global variables */ +extern u32 ioh_pcieqos_base_address; +extern u32 ioh_pcieqos_extrom_base_address; +#endif diff -urN linux-2.6.33-rc3/drivers/char/pch_pcieqos/pch_pcieqos_pci.c topcliff-2.6.33-rc3/drivers/char/pch_pcieqos/pch_pcieqos_pci.c --- linux-2.6.33-rc3/drivers/char/pch_pcieqos/pch_pcieqos_pci.c 1970-01-01 09:00:00.000000000 +0900 +++ topcliff-2.6.33-rc3/drivers/char/pch_pcieqos/pch_pcieqos_pci.c 2010-03-08 17:51:26.000000000 +0900 @@ -0,0 +1,523 @@ +/*! + * @file ioh_pcieqos_pci.c + * @brief Provides all the implementation of the interfaces pertaining to the + * pci and gpic registrations. + * @version 1.0.0.0 + * @section + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * History: + * Copyright (C) 2009 OKI SEMICONDUCTOR Co., LTD. + * All rights reserved. + * + * created: + * OKI SEMICONDUCTOR 06/20/2009 + * modified: + * + */ +/*includes*/ +#include +#include +#include +#include +#include +#include + +#include "pch_common.h" +#include "pch_debug.h" +#include "pch_pcieqos.h" +#include "pch_pcieqos_hal.h" + +/*macros*/ + +/*! @ingroup PCIEQOS_PCILayer + @def PCI_DEVICE_ID_IOH1_PCIEQOS + @brief Outlines the PCI Device ID. + */ +#define PCI_DEVICE_ID_IOH1_PCIEQOS (0x8801) + +/*! @ingroup PCIEQOS_PCILayer + @def IOH_MINOR_NOS + @brief Outlines the PCIEQOS minor numbers limit. + */ +#define IOH_MINOR_NOS (1) + +/*values for configuring CLKCFG reg + * for CAN clock of 50Mhz*/ + +/*! @ingroup PCIEQOS_PCILayer + @def CLKCFG_CAN_50MHZ + @brief CLKCFG register setting for CAN clock of 50Mhz. + */ +#define CLKCFG_CAN_50MHZ (0x12000000) + +/*! @ingroup PCIEQOS_PCILayer + @def CLKCFG_CANCLK_MASK + @brief Bit mask for bit fields in CLKCFG register + to set CAN clock to 50Mhz. + */ +#define CLKCFG_CANCLK_MASK (0xFF000000) + +/**global variables*/ +u32 ioh_pcieqos_base_address; +u32 ioh_pcieqos_extrom_base_address; +s32 ioh_pcieqos_suspended; + +/* ToDo: major number allocation via module parameter */ +static dev_t ioh_pcieqos_dev_no; +static int ioh_pcieqos_major_no; + +static struct cdev ioh_pcieqos_dev; + +/*! @ingroup PCIEQOS_PCILayerAPI + @fn static int __devinit ioh_pcieqos_probe(struct pci_dev* ioh_pci_dev, + const struct pci_device_id* pci_id) + @brief Provides the functionality of probing the module + */ +static int __devinit ioh_pcieqos_probe(struct pci_dev *pdev, const + struct pci_device_id *id); + +/*! @ingroup PCIEQOS_PCILayerAPI + @fn static void __devexit ioh_pcieqos_remove(struct pci_dev * ioh_pci_dev) + @brief Provides the functionality of removing the module + */ +static void __devexit ioh_pcieqos_remove(struct pci_dev *pdev); + +/*! @ingroup PCIEQOS_PCILayerAPI + @fn static int ioh_pcieqos_suspend(struct pci_dev* pDev,pm_message_t state) + @brief Provides the functionality of suspending the module + */ +static int ioh_pcieqos_suspend(struct pci_dev *pdev, pm_message_t state); + +/*! @ingroup PCIEQOS_PCILayerAPI + @fn static int ioh_pcieqos_resume(struct pci_dev* pDev) + @brief Provides the functionality of resuming the module + */ +static int ioh_pcieqos_resume(struct pci_dev *pdev); + +/*structures*/ +/*! @ingroup PCIEQOS_PCILayerFacilitators + @static struct pci_device_id + @brief It is a structure used for perserving information related to the + device id. + @note + The concerned details should be provided as a reference in the pci driver + structure. + */ +static struct pci_device_id ioh_pcieqos_pcidev_id[] = { + + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_IOH1_PCIEQOS)}, + {0,} +}; + +/*! @ingroup PCIEQOS_PCILayerFacilitators + @static struct ioh_pcieqos_driver + @brief It is a structure used for perserving information related to the + pcieqos device and preserves function signatures to manipulate the device. + @note + The structure contains the various interfaces aspects + provided to the pci layer. + @see + ioh_pcieqos_probe + ioh_pcieqos_suspend + ioh_pcieqos_resume + ioh_pcieqos_remove + */ +static struct pci_driver ioh_pcieqos_driver = { + .name = "ioh_pcieqos", + .id_table = ioh_pcieqos_pcidev_id, + .probe = ioh_pcieqos_probe, + .remove = __devexit_p(ioh_pcieqos_remove), +#ifdef CONFIG_PM + .suspend = ioh_pcieqos_suspend, + .resume = ioh_pcieqos_resume +#endif +}; + +/*! @ingroup PCIEQOS_PCILayerAPI + * @fn static int __init ioh_pcieqos_pci_init(void) + * @brief Provides the functionality of initializing the module + * */ +static int __init ioh_pcieqos_pci_init(void); +/*! @ingroup PCIEQOS_PCILayerAPI + * @fn static void __exit ioh_pcieqos_pci_exit(void) + * @brief Provides the functionality of exiting the module + * */ +static void __exit ioh_pcieqos_pci_exit(void); + +MODULE_DESCRIPTION("IOH PCIEQOS PCI Driver"); +MODULE_LICENSE("GPL"); +module_init(ioh_pcieqos_pci_init); +module_exit(ioh_pcieqos_pci_exit); +module_param(ioh_pcieqos_major_no, int, S_IRUSR | S_IWUSR); + +/*function implementations*/ + +/*! @ingroup PCIEQOS_PCILayerAPI + @fn static int __init ioh_pcieqos_pci_init(void) + @remarks Implements the initialization functionality of the module. + @param NONE + @retval returnvalue [@ref OUT] contains the result for the concerned + attempt. + The result would generally comprise of success code + or failure code. The failure code will indicate reason for + failure. + @see + ioh_pcieqos_pci_exit + */ +static int __init ioh_pcieqos_pci_init(void) +{ + s32 ret; + ret = pci_register_driver(&ioh_pcieqos_driver); + IOH_DEBUG + ("ioh_pcieqos_pci_init : Invoked pci_register_driver\ + successfully\n"); + IOH_DEBUG("ioh_pcieqos_pci_init returns %d\n", ret); + return ret; +} + +/*! @ingroup PCIEQOS_PCILayerAPI + @fn static void __exit ioh_pcieqos_pci_exit(void) + @remarks Implements the exit functionality of the module. + @param NONE + @retval returnvalue [@ref OUT] contains the result for the concerned + attempt. + The result would generally comprise of success code + or failure code. The failure code will indicate reason for + failure. + @see + ioh_pcieqos_pci_init + */ +static void __exit ioh_pcieqos_pci_exit(void) +{ + pci_unregister_driver(&ioh_pcieqos_driver); + IOH_DEBUG + ("ioh_pcieqos_pci_exit : Invoked pci_unregister_driver\ + successfully\n"); +} + +/*! @ingroup PCIEQOS_PCILayerAPI + @fn static int __devinit ioh_pcieqos_probe(struct pci_dev* pdev, + const struct pci_device_id* id) + @remarks Implements the probe functionality of the module. + @param pdev [@ref INOUT] Contains the reference of the pci_dev structure + @param id [@ref INOUT] Contains the reference of the pci_device_id structure + @retval returnvalue [@ref OUT] contains the result for the concerned + attempt. + The result would generally comprise of success code + or failure code. The failure code will indicate reason for + failure. + @see + ioh_pcieqos_pci_init + */ +static int __devinit ioh_pcieqos_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + + char *DRIVER_NAME = "ioh_pcieqos"; + int ret; + unsigned int rom_size; + + ioh_pcieqos_major_no = (ioh_pcieqos_major_no < 0 + || ioh_pcieqos_major_no > + 254) ? 0 : ioh_pcieqos_major_no; + + do { + + ret = pci_enable_device(pdev); + if (ret) { + IOH_LOG(KERN_ERR, + "\nioh_pcieqos_probe : pci_enable_device\ + FAILED"); + break; + } + IOH_DEBUG("ioh_pcieqos_probe : pci_enable_device returns %d\n", + ret); + + ret = pci_request_regions(pdev, DRIVER_NAME); + if (ret) { + IOH_LOG(KERN_ERR, + "ioh_pcieqos_probe : pci_request_regions\ + FAILED"); + pci_disable_device(pdev); + break; + } + IOH_DEBUG + ("ioh_pcieqos_probe : pci_request_regions returns %d\n", + ret); + + ioh_pcieqos_base_address = (unsigned long)pci_iomap(pdev, 1, 0); + + if (ioh_pcieqos_base_address == 0) { + IOH_LOG(KERN_ERR, + "ioh_pcieqos_probe : pci_iomap FAILED"); + pci_release_regions(pdev); + pci_disable_device(pdev); + ret = -ENOMEM; + break; + } + IOH_DEBUG + ("ioh_pcieqos_probe : pci_iomap SUCCESS and value in\ + ioh_pcieqos_base_address variable is 0x%08x\n", + ioh_pcieqos_base_address); + + ioh_pcieqos_extrom_base_address = + (unsigned long)pci_map_rom(pdev, &rom_size); + if (ioh_pcieqos_extrom_base_address == 0) { + IOH_LOG(KERN_ERR, + "ioh_pcieqos_probe : pci_map_rom FAILED"); + pci_iounmap(pdev, (void *)ioh_pcieqos_base_address); + pci_release_regions(pdev); + pci_disable_device(pdev); + ret = -ENOMEM; + break; + } + IOH_DEBUG + ("ioh_pcieqos_probe : pci_map_rom SUCCESS and value in\ + ioh_pcieqos_extrom_base_address variable is 0x%08x\n", + ioh_pcieqos_extrom_base_address); + + if (ioh_pcieqos_major_no) { + ioh_pcieqos_dev_no = MKDEV(ioh_pcieqos_major_no, 0); + ret = + register_chrdev_region(ioh_pcieqos_dev_no, + IOH_MINOR_NOS, DRIVER_NAME); + if (ret) { + IOH_LOG(KERN_ERR, + "ioh_pcieqos_probe :\ + register_chrdev_region FAILED"); + pci_unmap_rom(pdev, + (void *) + ioh_pcieqos_extrom_base_address); + pci_iounmap(pdev, + (void *)ioh_pcieqos_base_address); + pci_release_regions(pdev); + pci_disable_device(pdev); + break; + } + IOH_DEBUG + ("ioh_pcieqos_probe :\ + register_chrdev_region returns %d\n", + ret); + } else { + ret = + alloc_chrdev_region(&ioh_pcieqos_dev_no, 0, + IOH_MINOR_NOS, DRIVER_NAME); + if (ret) { + IOH_LOG(KERN_ERR, + "ioh_pcieqos_probe :\ + alloc_chrdev_region FAILED"); + pci_unmap_rom(pdev, + (void *) + ioh_pcieqos_extrom_base_address); + pci_iounmap(pdev, + (void *)ioh_pcieqos_base_address); + pci_release_regions(pdev); + pci_disable_device(pdev); + break; + } + IOH_DEBUG + ("ioh_pcieqos_probe :\ + alloc_chrdev_region returns %d\n", + ret); + } + + cdev_init(&ioh_pcieqos_dev, &ioh_pcieqos_fops); + IOH_DEBUG + ("ioh_pcieqos_probe : cdev_init invoked successfully\n"); + + ioh_pcieqos_dev.owner = THIS_MODULE; + ioh_pcieqos_dev.ops = &ioh_pcieqos_fops; + + ret = + cdev_add(&ioh_pcieqos_dev, ioh_pcieqos_dev_no, + IOH_MINOR_NOS); + if (ret) { + IOH_LOG(KERN_ERR, + "ioh_pcieqos_probe : cdev_add FAILED"); + unregister_chrdev_region(ioh_pcieqos_dev_no, + IOH_MINOR_NOS); + pci_unmap_rom(pdev, + (void *)ioh_pcieqos_extrom_base_address); + pci_iounmap(pdev, (void *)ioh_pcieqos_base_address); + pci_release_regions(pdev); + pci_disable_device(pdev); + break; + } + IOH_DEBUG("ioh_pcieqos_probe : cdev_add returns %d\n", ret); + +#ifdef IOH_CAN_PCLK_50MHZ + /*set the clock config reg if CAN clock is 50Mhz */ + IOH_DEBUG + ("ioh_pcieqos_probe : invoking\ + ioh_pcieqos_read_modify_write_reg to set CLKCFG reg\ + for CAN clk 50Mhz\n"); + ioh_pcieqos_read_modify_write_reg(CLKCFG_REG_OFFSET, + CLKCFG_CAN_50MHZ, + CLKCFG_CANCLK_MASK); +#endif + return IOH_PCIEQOS_SUCCESS; + } while (0); + IOH_DEBUG("ioh_pcieqos_probe returns %d\n", ret); + return ret; +} + +/*! @ingroup PCIEQOS_PCILayerAPI + @fn static void __devexit ioh_pcieqos_remove(struct pci_dev * pdev) + @remarks Implements the remove functionality of the module. + @param pdev [@ref INOUT] Contains the reference of the pci_dev structure + @retval returnvalue [@ref OUT] contains the result for the concerned + attempt. + The result would generally comprise of success code + or failure code. The failure code will indicate reason for + failure. + @see + ioh_pcieqos_pci_init + */ +static void __devexit ioh_pcieqos_remove(struct pci_dev *pdev) +{ + + cdev_del(&ioh_pcieqos_dev); + IOH_DEBUG("ioh_pcieqos_remove - cdev_del Invoked successfully\n"); + + unregister_chrdev_region(ioh_pcieqos_dev_no, IOH_MINOR_NOS); + IOH_DEBUG + ("ioh_pcieqos_remove - unregister_chrdev_region Invoked\ + successfully\n"); + + pci_unmap_rom(pdev, (void *)ioh_pcieqos_extrom_base_address); + + pci_iounmap(pdev, (void *)ioh_pcieqos_base_address); + + IOH_DEBUG("ioh_pcieqos_remove - pci_iounmap Invoked successfully\n"); + + pci_release_regions(pdev); + IOH_DEBUG + ("ioh_pcieqos_remove - pci_release_regions Invoked successfully\n"); + + pci_disable_device(pdev); + IOH_DEBUG + ("ioh_pcieqos_remove - pci_disable_device Invoked successfully\n"); + +} + +#ifdef CONFIG_PM + +/*! @ingroup PCIEQOS_PCILayerAPI + @fn static int ioh_pcieqos_suspend(struct pci_dev* pdev,pm_message_t state) + @remarks Implements the suspend functionality of the module. + @param pdev [@ref INOUT] Contains the reference of the pci_dev structure + @param state [@ref INOUT] Contains the reference of the pm_message_t + structure + @retval returnvalue [@ref OUT] contains the result for the concerned + attempt. + The result would generally comprise of success code + or failure code. The failure code will indicate reason for + failure. + @see + ioh_pcieqos_pci_init + ioh_pcieqos_resume + */ +static int ioh_pcieqos_suspend(struct pci_dev *pdev, pm_message_t state) +{ + int ret; + + ioh_pcieqos_suspended = true; /* For blocking further IOCTLs */ + + ioh_pcieqos_save_reg_conf(); + IOH_DEBUG + ("ioh_pcieqos_suspend - ioh_pcieqos_save_reg_conf Invoked\ + successfully\n"); + + ret = pci_save_state(pdev); + if (ret) { + IOH_LOG(KERN_ERR, + " ioh_pcieqos_suspend -pci_save_state returns-%d\n", + ret); + return ret; + } + + pci_enable_wake(pdev, PCI_D3hot, 0); + IOH_DEBUG + ("ioh_pcieqos_suspend - pci_enable_wake Invoked successfully\n"); + + IOH_DEBUG("ioh_pcieqos_suspend - pci_save_state returns %d\n", ret); + + pci_disable_device(pdev); + IOH_DEBUG + ("ioh_pcieqos_suspend - pci_disable_device Invoked successfully\n"); + + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + IOH_DEBUG + ("ioh_pcieqos_suspend - pci_set_power_state Invoked\ + successfully\n"); + + IOH_DEBUG("ioh_pcieqos_suspend - return %d\n", IOH_PCIEQOS_SUCCESS); + + return IOH_PCIEQOS_SUCCESS; +} + +/*! @ingroup PCIEQOS_PCILayerAPI + @fn static int ioh_pcieqos_resume(struct pci_dev* pdev) + @remarks Implements the resume functionality of the module. + @param pdev [@ref INOUT] Contains the reference of the pci_dev structure + @retval returnvalue [@ref OUT] contains the result for the concerned\ + attempt. + The result would generally comprise of success code + or failure code. The failure code will indicate reason for + failure. + @see + ioh_pcieqos_pci_init + ioh_pcieqos_suspend + */ +static int ioh_pcieqos_resume(struct pci_dev *pdev) +{ + + int ret; + + pci_set_power_state(pdev, PCI_D0); + IOH_DEBUG + ("ioh_pcieqos_resume - pci_set_power_state Invoked successfully\n"); + + pci_restore_state(pdev); + IOH_DEBUG + ("ioh_pcieqos_resume - pci_restore_state Invoked successfully\n"); + + ret = pci_enable_device(pdev); + if (ret) { + IOH_LOG(KERN_ERR, + "ioh_pcieqos_resume-pci_enable_device failed "); + return ret; + } + + IOH_DEBUG("ioh_pcieqos_resume - pci_enable_device returns -%d\n", ret); + + pci_enable_wake(pdev, PCI_D3hot, 0); + IOH_DEBUG + ("ioh_pcieqos_resume - pci_enable_wake Invoked successfully\n"); + + ioh_pcieqos_restore_reg_conf(); + IOH_DEBUG + ("ioh_pcieqos_resume - ioh_pcieqos_restore_reg_conf Invoked\ + successfully\n"); + + ioh_pcieqos_suspended = false; + + IOH_DEBUG("ioh_pcieqos_resume returns- %d\n", IOH_PCIEQOS_SUCCESS); + return IOH_PCIEQOS_SUCCESS; +} + +#endif