From: Masayuki Ohtake on
Hi Yong Wang

Thank you for your comment.

> Why is 50MHz so special, btw?
This code is work around for previous HW bug.
(CAN worked only 50MHz with previous HW)

Since the HW bug has been already fixed for the latest HW,
this code is unnecessary for the latest HW.

> Note that 'a' is supposed to be surrounded by brackets, too.
>
> #define PCH_WRITE_REG(a, b) iowrite32((a), pcb_phub_base_address + (b))
Thank you for your indication. We have updated.

Best Regards,
----- Original Message -----
From: "Yong Wang" <yong.y.wang(a)linux.intel.com>
To: "Masayuki Ohtak" <masa-korg(a)dsn.okisemi.com>
Cc: "Alan Cox" <alan(a)lxorguk.ukuu.org.uk>; "LKML" <linux-kernel(a)vger.kernel.org>; "Andrew"
<andrew.chih.howe.khor(a)intel.com>; "Intel OTC" <joel.clark(a)intel.com>; "Wang, Qi" <qi.wang(a)intel.com>; "Wang, Yong Y"
<yong.y.wang(a)intel.com>
Sent: Tuesday, June 08, 2010 4:20 PM
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver


> On Tue, Jun 08, 2010 at 02:00:55PM +0900, Masayuki Ohtak wrote:
> > Hi Alan
> >
> > We are now updating our Phub driver.
> >
> > I have a questions for your comment.
> >
> > (1)
> > >> +#ifdef PCH_CAN_PCLK_50MHZ
> > >> + /* save clk cfg register */
> > >> + g_pch_phub_reg.clkcfg_reg = PCH_READ_REG(CLKCFG_REG_OFFSET);
> > >> +#endif
> > >
> > > This makes it hard to build one kernel for everything
> > We couldn't understand your intention.
> > Does the above mean we must not use "#ifdef PCH_CAN_PCLK_50MHZ" in source code ?
> >
>
> I think what Alan means is that you will have to build two kernel images
> for two possible configurations of how your hardware is going to be used
> if you write code this way. One is the case when CAN clock runs at 50MHz
> and you will build a kernel image with PCH_CAN_PCLK_50MHZ defined. The
> other is when CAN clock runs at other speed and you need to build
> another kernel image with PCH_CAN_PCLK_50MHZ undefined. It would be much
> better if one kernel image could run on all configurations.
>
> Why is 50MHz so special, btw? Don't you need to save and restore the
> clock config register when CAN clock runs at other speed?
>
> >
> > >> +#define PCH_READ_REG(a) ioread32((pch_phub_base_address + a))
> >
> > >> +
> >
> > >> +#define PCH_WRITE_REG(a, b) iowrite32(a, (pch_phub_base_address + b))
> >
> > >
> >
> > > These on the other hand do - but not where they are now
> >
> > >
> >
> > > iowrite32((a), pcb_phub_base_address + (b))
> >
> > >
> >
> > > (so that if a or b are expressions they are evaluated first)
> >
> > Modify like below.
> >
> > #define PCH_READ_REG(a) ioread32(pch_phub_base_address + (a))
> >
> > #define PCH_WRITE_REG(a, b) iowrite32(a, pch_phub_base_address + (b))
> >
>
> Note that 'a' is supposed to be surrounded by brackets, too.
>
> #define PCH_WRITE_REG(a, b) iowrite32((a), pcb_phub_base_address + (b))
>
> Thanks
> -Yong
>


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
From: Masayuki Ohtake on
Hi Arnd

We are studying your indication.
> My feeling is that this ioctl interface is too
> low-level in general. You only export access to specific
> registers, not to functionality exposed by them.
> The best kernel interfaces are defined in a way that
> is independent of the underlying hardware and
> convert generic commands into device specific commands.

I have a question.
We don't know 'generic commands' concretely.
Let me know 'generic commands' in detail.

Thanks. Ohtake.

----- Original Message -----
From: "Arnd Bergmann" <arnd(a)arndb.de>
To: "Masayuki Ohtake" <masa-korg(a)dsn.okisemi.com>
Cc: "LKML" <linux-kernel(a)vger.kernel.org>; "Andrew" <andrew.chih.howe.khor(a)intel.com>; "Intel OTC"
<joel.clark(a)intel.com>; "Wang, Qi" <qi.wang(a)intel.com>; "Wang, Yong Y" <yong.y.wang(a)intel.com>
Sent: Monday, June 07, 2010 10:37 PM
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver


> On Friday 04 June 2010, Masayuki Ohtake wrote:
> > From: Masayuki Ohtake <masa-korg(a)dsn.okisemi.com>
> >
> > This patch adds the Packet Hub driver for Topcliff.
> > Patch created against 2.6.33.1
> >
> > Signed-off-by: Masayuki Ohtake <masa-korg(a)dsn.okisemi.com>
>
> Most of the comments from my first review still apply to
> this version, please have another look at what I wrote
> back in april, see http://article.gmane.org/gmane.linux.network/158879
>
> Note also that patch submissions should be against the latest
> development kernel, in this case 2.6.35-rc2, not against stable
> kernel releases like 2.6.33.1.
>
> Arnd
>


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
From: Arnd Bergmann on
On Tuesday 08 June 2010, Masayuki Ohtake wrote:
> We are studying your indication.
> > My feeling is that this ioctl interface is too
> > low-level in general. You only export access to specific
> > registers, not to functionality exposed by them.
> > The best kernel interfaces are defined in a way that
> > is independent of the underlying hardware and
> > convert generic commands into device specific commands.
>
> I have a question.
> We don't know 'generic commands' concretely.
> Let me know 'generic commands' in detail.

I have not seen the application using the driver, but
a better abstraction IMHO would be to take an abstraction
you have in your application and move it into the kernel.

I can be more specific if you tell me where to find the
source of the application. Generally speaking, you'd
transform a function like

/* the function that knows how to do 'this' */
int phub_do_this(int phub_fd, unsigned long arg)
{
struct pch_phub_req req = {
.addr_offset = SOME_ADDR_OFF,
};
ioctl(fd, IOCTL_PHUB_READ_REG, &req);

if (req.data & SOME_BITS)
return ERROR;

req.addr_offset = ANOTHER_ADDR_OFF;
req.data = arg | REALLY_DO_IT_BITMASK;

ioctl(fd, IOCTL_PHUB_WRITE_REG, &req);

return 0;
}

into another function that does the same thing but
without knowing anything about the registers:

/* the same function on the abstract interface */
int phub_do_this_new(int phub_fd, unsigned long arg)
{
return ioctl(phub_fd, IOCTL_PHUB_DO_THIS, &arg);
}

Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
From: Wang, Qi on
Ohtake-san,

Let me explain what Arnd means.

Writing the all the registers with ioctl is discouraged. For this case, what you need is writing/updating or reading some registers, not all the registers of Topcliff. It's better that you implement as the following example.

For example, you want to update MAC register with 'aaaa'.
It's not a better way to pass the register of mac address and aaaa via the ioctl routine. It's better only pass the aaaa with the 'update mac address command' (update aaaa to mac register). Actually it's discouraged to pass the address information with ioctl routine, because it'll bring the security issue even if you check the address-range.

It's better to pass the command and relative argument to implement something, not 'the address', 'read/write register command' and 'the value to read/write'.

Any question, please let me know.

Best Regards,
Qi.

-----Original Message-----
From: Masayuki Ohtake [mailto:masa-korg(a)dsn.okisemi.com]
Sent: Tuesday, June 08, 2010 4:49 PM
To: Arnd Bergmann
Cc: LKML; Khor, Andrew Chih Howe; Clark, Joel; Wang, Qi; Wang, Yong Y
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver

Hi Arnd

We are studying your indication.
> My feeling is that this ioctl interface is too
> low-level in general. You only export access to specific
> registers, not to functionality exposed by them.
> The best kernel interfaces are defined in a way that
> is independent of the underlying hardware and
> convert generic commands into device specific commands.

I have a question.
We don't know 'generic commands' concretely.
Let me know 'generic commands' in detail.

Thanks. Ohtake.

----- Original Message -----
From: "Arnd Bergmann" <arnd(a)arndb.de>
To: "Masayuki Ohtake" <masa-korg(a)dsn.okisemi.com>
Cc: "LKML" <linux-kernel(a)vger.kernel.org>; "Andrew" <andrew.chih.howe.khor(a)intel.com>; "Intel OTC"
<joel.clark(a)intel.com>; "Wang, Qi" <qi.wang(a)intel.com>; "Wang, Yong Y" <yong.y.wang(a)intel.com>
Sent: Monday, June 07, 2010 10:37 PM
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver


> On Friday 04 June 2010, Masayuki Ohtake wrote:
> > From: Masayuki Ohtake <masa-korg(a)dsn.okisemi.com>
> >
> > This patch adds the Packet Hub driver for Topcliff.
> > Patch created against 2.6.33.1
> >
> > Signed-off-by: Masayuki Ohtake <masa-korg(a)dsn.okisemi.com>
>
> Most of the comments from my first review still apply to
> this version, please have another look at what I wrote
> back in april, see http://article.gmane.org/gmane.linux.network/158879
>
> Note also that patch submissions should be against the latest
> development kernel, in this case 2.6.35-rc2, not against stable
> kernel releases like 2.6.33.1.
>
> Arnd
>


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
From: Masayuki Ohtak on
Hi we have modified for your comments.
Please Confirm below.

Thanks.
Ohtake.


Signed-off-by: Masayuki Ohtake <masa-korg(a)dsn.okisemi.com>
---
linux-2.6.33.1/drivers/char/Kconfig | 25 +
linux-2.6.33.1/drivers/char/Makefile | 4 +
linux-2.6.33.1/drivers/char/pch_phub/Makefile | 11 +
linux-2.6.33.1/drivers/char/pch_phub/pch_phub.c | 1000 +++++++++++++++++++++++
linux-2.6.33.1/drivers/char/pch_phub/pch_phub.h | 87 ++
5 files changed, 1127 insertions(+), 0 deletions(-)
create mode 100644 linux-2.6.33.1/drivers/char/pch_phub/Makefile
create mode 100755 linux-2.6.33.1/drivers/char/pch_phub/pch_phub.c
create mode 100755 linux-2.6.33.1/drivers/char/pch_phub/pch_phub.h

diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index e023682..285ce78 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -4,6 +4,31 @@

menu "Character devices"

+config PCH_IEEE1588
+ tristate "PCH IEEE1588"
+ depends on PCI
+ help
+ If you say yes to this option, support will be included for the
+ PCH IEEE1588 Host controller.
+
+config PCH_PHUB
+ tristate "PCH PHUB"
+ depends on PCI
+ help
+ If you say yes to this option, support will be included for the
+ PCH Packet Hub Host controller.
+ This driver is for PCH Packet hub driver for Topcliff.
+ This driver is integrated as built-in.
+ This driver can access GbE MAC address.
+ This driver can access HW register.
+ You can also be integrated as module.
+
+config PCH_CAN_PCLK_50MHZ
+ bool "CAN PCLK 50MHz"
+ depends on PCH_PHUB
+ help
+ If you say yes to this option, clock is set to 50MHz.(For CAN control)
+
config VT
bool "Virtual terminal" if EMBEDDED
depends on !S390
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index f957edf..dc092d0 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -111,6 +111,10 @@ obj-$(CONFIG_PS3_FLASH) += ps3flash.o
obj-$(CONFIG_JS_RTC) += js-rtc.o
js-rtc-y = rtc.o

+obj-$(CONFIG_PCH_IEEE1588) += pch_ieee1588/
+
+obj-$(CONFIG_PCH_PHUB) += pch_phub/
+
# Files generated that shall be removed upon make clean
clean-files := consolemap_deftbl.c defkeymap.c

diff --git a/drivers/char/pch_phub/Makefile b/drivers/char/pch_phub/Makefile
new file mode 100644
index 0000000..bfe2a2b
--- /dev/null
+++ b/drivers/char/pch_phub/Makefile
@@ -0,0 +1,11 @@
+ifeq ($(CONFIG_PHUB_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+obj-$(CONFIG_PCH_PHUB) += pch_phub_drv.o
+#to set CAN clock to 50Mhz
+ifdef CONFIG_PCH_CAN_PCLK_50MHZ
+EXTRA_CFLAGS +=-DPCH_CAN_PCLK_50MHZ
+endif
+
+pch_phub_drv-objs := pch_phub.o
diff --git a/drivers/char/pch_phub/pch_phub.c b/drivers/char/pch_phub/pch_phub.c
new file mode 100755
index 0000000..e9f5d4c
--- /dev/null
+++ b/drivers/char/pch_phub/pch_phub.c
@@ -0,0 +1,1000 @@
+/*!
+ * @file pch_phub.c
+ * @brief Provides all the implementation of the interfaces pertaining to
+ * the Packet Hub 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) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * created:
+ * OKI SEMICONDUCTOR 04/14/2010
+ * modified:
+ *
+ */
+
+/* includes */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+
+#include "pch_phub.h"
+
+/*--------------------------------------------
+ macros
+--------------------------------------------*/
+/* Status Register offset */
+#define PHUB_STATUS 0x00
+/* Control Register offset */
+#define PHUB_CONTROL 0x04
+/* Time out value for Status Register */
+#define PHUB_TIMEOUT 0x05
+/* Enabling for writing ROM */
+#define PCH_PHUB_ROM_WRITE_ENABLE 0x01
+/* Disabling for writing ROM */
+#define PCH_PHUB_ROM_WRITE_DISABLE 0x00
+/* ROM data area start address offset */
+#define PCH_PHUB_ROM_START_ADDR 0x14
+/* MAX number of INT_REDUCE_CONTROL registers */
+#define MAX_NUM_INT_REDUCE_CONTROL_REG 128
+
+#define PCI_DEVICE_ID_PCH1_PHUB 0x8801
+
+#define PCH_MINOR_NOS 1
+#define CLKCFG_CAN_50MHZ 0x12000000
+#define CLKCFG_CANCLK_MASK 0xFF000000
+
+#define MODULE_NAME "pch_phub"
+
+#define PCH_READ_REG(a) ioread32(pch_phub_reg.pch_phub_base_address + (a))
+
+#define PCH_WRITE_REG(a, b) iowrite32((a), pch_phub_reg.pch_phub_base_address +\
+ (b))
+/*--------------------------------------------
+ global variables
+--------------------------------------------*/
+/**
+ * struct pch_phub_reg_t - PHUB register structure
+ * @phub_id_reg: PHUB_ID register val
+ * @q_pri_val_reg: QUEUE_PRI_VAL register val
+ * @rc_q_maxsize_reg: RC_QUEUE_MAXSIZE register val
+ * @bri_q_maxsize_reg: BRI_QUEUE_MAXSIZE register val
+ * @comp_resp_timeout_reg: COMP_RESP_TIMEOUT register val
+ * @bus_slave_control_reg: BUS_SLAVE_CONTROL_REG register val
+ * @deadlock_avoid_type_reg: DEADLOCK_AVOID_TYPE register val
+ * @intpin_reg_wpermit_reg0: INTPIN_REG_WPERMIT register 0 val
+ * @intpin_reg_wpermit_reg1: INTPIN_REG_WPERMIT register 1 val
+ * @intpin_reg_wpermit_reg2: INTPIN_REG_WPERMIT register 2 val
+ * @intpin_reg_wpermit_reg3: INTPIN_REG_WPERMIT register 3 val
+ * @int_reduce_control_reg: INT_REDUCE_CONTROL registers val
+ * @clkcfg_reg: CLK CFG register val
+ * @pch_phub_opencount: check whether opened or not
+ * @pch_phub_base_address: register base address
+ * @pch_phub_extrom_base_address: external rom base address
+ * @pch_phub_suspended: PHUB status val
+ */
+struct pch_phub_reg_t {
+ __u32 phub_id_reg;
+ __u32 q_pri_val_reg;
+ __u32 rc_q_maxsize_reg;
+ __u32 bri_q_maxsize_reg;
+ __u32 comp_resp_timeout_reg;
+ __u32 bus_slave_control_reg;
+ __u32 deadlock_avoid_type_reg;
+ __u32 intpin_reg_wpermit_reg0;
+ __u32 intpin_reg_wpermit_reg1;
+ __u32 intpin_reg_wpermit_reg2;
+ __u32 intpin_reg_wpermit_reg3;
+ __u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG];
+#ifdef PCH_CAN_PCLK_50MHZ
+ __u32 clkcfg_reg;
+#endif
+ __s32 pch_phub_opencount;
+ void __iomem *pch_phub_base_address;
+ void __iomem *pch_phub_extrom_base_address;
+ __s32 pch_phub_suspended;
+} pch_phub_reg;
+
+DEFINE_MUTEX(pch_phub_ioctl_mutex);
+
+static DEFINE_SPINLOCK(pch_phub_lock); /* for spin lock */
+
+/* ToDo: major number allocation via module parameter */
+static dev_t pch_phub_dev_no;
+static __s32 pch_phub_major_no;
+static struct cdev pch_phub_dev;
+
+
+/*--------------------------------------------
+ internal function prototypes
+--------------------------------------------*/
+static __s32 __devinit pch_phub_probe(struct pci_dev *pdev, const
+ struct pci_device_id *id);
+static void __devexit pch_phub_remove(struct pci_dev *pdev);
+static __s32 pch_phub_suspend(struct pci_dev *pdev, pm_message_t state);
+static __s32 pch_phub_resume(struct pci_dev *pdev);
+static __s32 pch_phub_open(struct inode *inode, struct file *file);
+static __s32 pch_phub_release(struct inode *inode, struct file *file);
+static long pch_phub_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg);
+static ssize_t pch_phub_read(struct file *, char __user *, size_t, loff_t *);
+static ssize_t pch_phub_write(struct file *, const char __user *,
+ size_t, loff_t *);
+
+/**
+ * file_operations structure initialization
+ */
+static const struct file_operations pch_phub_fops = {
+ .owner = THIS_MODULE,
+ .open = pch_phub_open,
+ .read = pch_phub_read,
+ .write = pch_phub_write,
+ .release = pch_phub_release,
+ .unlocked_ioctl = pch_phub_ioctl,
+};
+
+/*--------------------------------------------
+ functions implementations
+--------------------------------------------*/
+/** pch_phub_read_modify_write_reg - Implements the functionality of reading,
+ * modifying and writing register.
+ * @reg_addr_offset: Contains the register offset address value
+ * @data: Contains the writing value
+ * @mask: Contains the mask value
+ */
+static void pch_phub_read_modify_write_reg(__u32 reg_addr_offset,
+ __u32 data, __u32 mask)
+{
+ void __iomem *reg_addr = pch_phub_reg.pch_phub_base_address +\
+ reg_addr_offset;
+ iowrite32(((ioread32(reg_addr) & ~mask)) | data, reg_addr);
+ return;
+}
+
+
+/** pch_phub_save_reg_conf - saves register configuration
+ */
+static void pch_phub_save_reg_conf(struct pci_dev *pdev)
+{
+ __u32 i = 0;
+
+ dev_dbg(&pdev->dev, "pch_phub_save_reg_conf ENTRY\n");
+ /* to store contents of PHUB_ID register */
+ pch_phub_reg.phub_id_reg = PCH_READ_REG(PCH_PHUB_PHUB_ID_REG);
+ /* to store contents of QUEUE_PRI_VAL register */
+ pch_phub_reg.q_pri_val_reg = PCH_READ_REG(PCH_PHUB_QUEUE_PRI_VAL_REG);
+ /* to store contents of RC_QUEUE_MAXSIZE register */
+ pch_phub_reg.rc_q_maxsize_reg =
+ PCH_READ_REG(PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
+ /* to store contents of BRI_QUEUE_MAXSIZE register */
+ pch_phub_reg.bri_q_maxsize_reg =
+ PCH_READ_REG(PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
+ /* to store contents of COMP_RESP_TIMEOUT register */
+ pch_phub_reg.comp_resp_timeout_reg =
+ PCH_READ_REG(PCH_PHUB_COMP_RESP_TIMEOUT_REG);
+ /* to store contents of BUS_SLAVE_CONTROL_REG register */
+ pch_phub_reg.bus_slave_control_reg =
+ PCH_READ_REG(PCH_PHUB_BUS_SLAVE_CONTROL_REG);
+ /* to store contents of DEADLOCK_AVOID_TYPE register */
+ pch_phub_reg.deadlock_avoid_type_reg =
+ PCH_READ_REG(PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
+ /* to store contents of INTPIN_REG_WPERMIT register 0 */
+ pch_phub_reg.intpin_reg_wpermit_reg0 =
+ PCH_READ_REG(PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
+ /* to store contents of INTPIN_REG_WPERMIT register 1 */
+ pch_phub_reg.intpin_reg_wpermit_reg1 =
+ PCH_READ_REG(PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
+ /* to store contents of INTPIN_REG_WPERMIT register 2 */
+ pch_phub_reg.intpin_reg_wpermit_reg2 =
+ PCH_READ_REG(PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
+ /* to store contents of INTPIN_REG_WPERMIT register 3 */
+ pch_phub_reg.intpin_reg_wpermit_reg3 =
+ PCH_READ_REG(PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
+ dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
+ "pch_phub_reg.phub_id_reg=%x, "
+ "pch_phub_reg.q_pri_val_reg=%x, "
+ "pch_phub_reg.rc_q_maxsize_reg=%x, "
+ "pch_phub_reg.bri_q_maxsize_reg=%x, "
+ "pch_phub_reg.comp_resp_timeout_reg=%x, "
+ "pch_phub_reg.bus_slave_control_reg=%x, "
+ "pch_phub_reg.deadlock_avoid_type_reg=%x, "
+ "pch_phub_reg.intpin_reg_wpermit_reg0=%x, "
+ "pch_phub_reg.intpin_reg_wpermit_reg1=%x, "
+ "pch_phub_reg.intpin_reg_wpermit_reg2=%x, "
+ "pch_phub_reg.intpin_reg_wpermit_reg3=%x\n",
+ pch_phub_reg.phub_id_reg,
+ pch_phub_reg.q_pri_val_reg,
+ pch_phub_reg.rc_q_maxsize_reg,
+ pch_phub_reg.bri_q_maxsize_reg,
+ pch_phub_reg.comp_resp_timeout_reg,
+ pch_phub_reg.bus_slave_control_reg,
+ pch_phub_reg.deadlock_avoid_type_reg,
+ pch_phub_reg.intpin_reg_wpermit_reg0,
+ pch_phub_reg.intpin_reg_wpermit_reg1,
+ pch_phub_reg.intpin_reg_wpermit_reg2,
+ pch_phub_reg.intpin_reg_wpermit_reg3);
+ /* to store contents of INT_REDUCE_CONTROL registers */
+ for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
+ pch_phub_reg.int_reduce_control_reg[i] =
+ PCH_READ_REG(
+ PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
+ dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
+ "pch_phub_reg.int_reduce_control_reg[%d]=%x\n",
+ i, pch_phub_reg.int_reduce_control_reg[i]);
+ }
+#ifdef PCH_CAN_PCLK_50MHZ
+ /* save clk cfg register */
+ pch_phub_reg.clkcfg_reg = PCH_READ_REG(CLKCFG_REG_OFFSET);
+#endif
+ return;
+}
+
+/** pch_phub_restore_reg_conf - restore register configuration
+ */
+
+static void pch_phub_restore_reg_conf(struct pci_dev *pdev)
+{
+ __u32 i;
+
+ dev_dbg(&pdev->dev, "pch_phub_restore_reg_conf ENTRY\n");
+ /* to store contents of PHUB_ID register */
+ PCH_WRITE_REG(pch_phub_reg.phub_id_reg, PCH_PHUB_PHUB_ID_REG);
+ /* to store contents of QUEUE_PRI_VAL register */
+ PCH_WRITE_REG(pch_phub_reg.q_pri_val_reg, PCH_PHUB_QUEUE_PRI_VAL_REG);
+ /* to store contents of RC_QUEUE_MAXSIZE register */
+ PCH_WRITE_REG(pch_phub_reg.rc_q_maxsize_reg,
+ PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
+ /* to store contents of BRI_QUEUE_MAXSIZE register */
+ PCH_WRITE_REG(pch_phub_reg.bri_q_maxsize_reg,
+ PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
+ /* to store contents of COMP_RESP_TIMEOUT register */
+ PCH_WRITE_REG(pch_phub_reg.comp_resp_timeout_reg,
+ PCH_PHUB_COMP_RESP_TIMEOUT_REG);
+ /* to store contents of BUS_SLAVE_CONTROL_REG register */
+ PCH_WRITE_REG(pch_phub_reg.bus_slave_control_reg,
+ PCH_PHUB_BUS_SLAVE_CONTROL_REG);
+ /* to store contents of DEADLOCK_AVOID_TYPE register */
+ PCH_WRITE_REG(pch_phub_reg.deadlock_avoid_type_reg,
+ PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
+ /* to store contents of INTPIN_REG_WPERMIT register 0 */
+ PCH_WRITE_REG(pch_phub_reg.intpin_reg_wpermit_reg0,
+ PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
+ /* to store contents of INTPIN_REG_WPERMIT register 1 */
+ PCH_WRITE_REG(pch_phub_reg.intpin_reg_wpermit_reg1,
+ PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
+ /* to store contents of INTPIN_REG_WPERMIT register 2 */
+ PCH_WRITE_REG(pch_phub_reg.intpin_reg_wpermit_reg2,
+ PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
+ /* to store contents of INTPIN_REG_WPERMIT register 3 */
+ PCH_WRITE_REG(pch_phub_reg.intpin_reg_wpermit_reg3,
+ PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
+ dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
+ "pch_phub_reg.phub_id_reg=%x, "
+ "pch_phub_reg.q_pri_val_reg=%x, "
+ "pch_phub_reg.rc_q_maxsize_reg=%x, "
+ "pch_phub_reg.bri_q_maxsize_reg=%x, "
+ "pch_phub_reg.comp_resp_timeout_reg=%x, "
+ "pch_phub_reg.bus_slave_control_reg=%x, "
+ "pch_phub_reg.deadlock_avoid_type_reg=%x, "
+ "pch_phub_reg.intpin_reg_wpermit_reg0=%x, "
+ "pch_phub_reg.intpin_reg_wpermit_reg1=%x, "
+ "pch_phub_reg.intpin_reg_wpermit_reg2=%x, "
+ "pch_phub_reg.intpin_reg_wpermit_reg3=%x\n",
+ pch_phub_reg.phub_id_reg,
+ pch_phub_reg.q_pri_val_reg,
+ pch_phub_reg.rc_q_maxsize_reg,
+ pch_phub_reg.bri_q_maxsize_reg,
+ pch_phub_reg.comp_resp_timeout_reg,
+ pch_phub_reg.bus_slave_control_reg,
+ pch_phub_reg.deadlock_avoid_type_reg,
+ pch_phub_reg.intpin_reg_wpermit_reg0,
+ pch_phub_reg.intpin_reg_wpermit_reg1,
+ pch_phub_reg.intpin_reg_wpermit_reg2,
+ pch_phub_reg.intpin_reg_wpermit_reg3);
+ /* to store contents of INT_REDUCE_CONTROL register */
+ for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
+ PCH_WRITE_REG(pch_phub_reg.int_reduce_control_reg[i],
+ PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
+ dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
+ "pch_phub_reg.int_reduce_control_reg[%d]=%x\n",
+ i, pch_phub_reg.int_reduce_control_reg[i]);
+ }
+
+#ifdef PCH_CAN_PCLK_50MHZ
+ /*restore the clock config reg */
+ PCH_WRITE_REG(pch_phub_reg.clkcfg_reg, CLKCFG_REG_OFFSET);
+#endif
+
+ return;
+}
+
+/** pch_phub_read_serial_rom - Implements the functionality of reading Serial
+ * ROM.
+ * @offset_address: Contains the Serial ROM address offset value
+ * @data: Contains the Serial ROM value
+ */
+static __s32 pch_phub_read_serial_rom(__u32 offset_address, __u8 *data)
+{
+ void __iomem *mem_addr = pch_phub_reg.pch_phub_extrom_base_address +\
+ offset_address;
+
+ *data = ioread8(mem_addr);
+
+ return 0;
+}
+
+/** pch_phub_write_serial_rom - Implements the functionality of writing Serial
+ * ROM.
+ * @offset_address: Contains the Serial ROM address offset value
+ * @data: Contains the Serial ROM value
+ */
+static __s32 pch_phub_write_serial_rom(__u32 offset_address,
+ __u8 data)
+{
+ __s32 retval = 0;
+ void __iomem *mem_addr = pch_phub_reg.pch_phub_extrom_base_address +\
+ (offset_address & 0xFFFFFFFC);
+ __s32 i = 0;
+ __u32 word_data = 0;
+
+ iowrite32(PCH_PHUB_ROM_WRITE_ENABLE,
+ pch_phub_reg.pch_phub_extrom_base_address +\
+ PHUB_CONTROL);
+
+ word_data = ioread32(mem_addr);
+
+ switch (offset_address % 4) {
+ case 0:
+ word_data &= 0xFFFFFF00;
+ iowrite32((word_data | (__u32)data),
+ mem_addr);
+ break;
+ case 1:
+ word_data &= 0xFFFF00FF;
+ iowrite32((word_data | ((__u32)data << 8)),
+ mem_addr);
+ break;
+ case 2:
+ word_data &= 0xFF00FFFF;
+ iowrite32((word_data | ((__u32)data << 16)),
+ mem_addr);
+ break;
+ case 3:
+ word_data &= 0x00FFFFFF;
+ iowrite32((word_data | ((__u32)data << 24)),
+ mem_addr);
+ break;
+ }
+ while (0x00 !=
+ ioread8(pch_phub_reg.pch_phub_extrom_base_address +\
+ PHUB_STATUS)) {
+ msleep(1);
+ if (PHUB_TIMEOUT == i) {
+ retval = -EPERM;
+ break;
+ }
+ i++;
+ }
+
+ iowrite32(PCH_PHUB_ROM_WRITE_DISABLE,
+ pch_phub_reg.pch_phub_extrom_base_address +\
+ PHUB_CONTROL);
+
+ return retval;
+}
+
+/** pch_phub_read_serial_rom_val - Implements the functionality of reading
+ * Serial ROM value.
+ * @offset_address: Contains the Serial ROM address offset value
+ * @data: Contains the Serial ROM value
+ */
+static __s32 pch_phub_read_serial_rom_val(__u32 offset_address, __u8 *data)
+{
+ __s32 retval = 0;
+ __u32 mem_addr;
+
+ mem_addr = (offset_address / 4 * 8) + 3 -
+ (offset_address % 4) + PCH_PHUB_ROM_START_ADDR;
+ retval = pch_phub_read_serial_rom(mem_addr, data);
+
+ return retval;
+}
+
+/** pch_phub_write_serial_rom_val - Implements the functionality of writing
+ * Serial ROM value.
+ * @offset_address: Contains the Serial ROM address offset value
+ * @data: Contains the Serial ROM value
+ */
+static __s32 pch_phub_write_serial_rom_val(__u32 offset_address,
+ __u8 data)
+{
+ __s32 retval = 0;
+ __u32 mem_addr;
+
+ mem_addr =
+ (offset_address / 4 * 8) + 3 - (offset_address % 4) +
+ PCH_PHUB_ROM_START_ADDR;
+ retval = pch_phub_write_serial_rom(mem_addr, data);
+
+ return retval;
+}
+
+/** pch_phub_gbe_serial_rom_conf - makes Serial ROM header format configuration
+ * for Gigabit Ethernet MAC address
+ */
+static __s32 pch_phub_gbe_serial_rom_conf(void)
+{
+ __s32 retval = 0;
+
+ retval |= pch_phub_write_serial_rom(0x0b, 0xbc);
+ retval |= pch_phub_write_serial_rom(0x0a, 0x10);
+ retval |= pch_phub_write_serial_rom(0x09, 0x01);
+ retval |= pch_phub_write_serial_rom(0x08, 0x02);
+
+ retval |= pch_phub_write_serial_rom(0x0f, 0x00);
+ retval |= pch_phub_write_serial_rom(0x0e, 0x00);
+ retval |= pch_phub_write_serial_rom(0x0d, 0x00);
+ retval |= pch_phub_write_serial_rom(0x0c, 0x80);
+
+ retval |= pch_phub_write_serial_rom(0x13, 0xbc);
+ retval |= pch_phub_write_serial_rom(0x12, 0x10);
+ retval |= pch_phub_write_serial_rom(0x11, 0x01);
+ retval |= pch_phub_write_serial_rom(0x10, 0x18);
+
+ retval |= pch_phub_write_serial_rom(0x1b, 0xbc);
+ retval |= pch_phub_write_serial_rom(0x1a, 0x10);
+ retval |= pch_phub_write_serial_rom(0x19, 0x01);
+ retval |= pch_phub_write_serial_rom(0x18, 0x19);
+
+ retval |= pch_phub_write_serial_rom(0x23, 0xbc);
+ retval |= pch_phub_write_serial_rom(0x22, 0x10);
+ retval |= pch_phub_write_serial_rom(0x21, 0x01);
+ retval |= pch_phub_write_serial_rom(0x20, 0x3a);
+
+ retval |= pch_phub_write_serial_rom(0x27, 0x01);
+ retval |= pch_phub_write_serial_rom(0x26, 0x00);
+ retval |= pch_phub_write_serial_rom(0x25, 0x00);
+ retval |= pch_phub_write_serial_rom(0x24, 0x00);
+
+ return retval;
+}
+
+/** pch_phub_read_gbe_mac_addr - Contains the Gigabit Ethernet MAC address
+ * offset value
+ * @offset_address: Gigabit Ethernet MAC address offset value
+ * @data: Contains the Gigabit Ethernet MAC address value
+ */
+static __s32 pch_phub_read_gbe_mac_addr(__u32 offset_address, __u8 *data)
+{
+ __s32 retval = 0;
+
+ retval = pch_phub_read_serial_rom_val(offset_address, data);
+
+ return retval;
+}
+
+/** pch_phub_write_gbe_mac_addr - Write MAC address
+ * @offset_address: Contains the Gigabit Ethernet MAC address offset value
+ * @data: Contains the Gigabit Ethernet MAC address value
+ */
+static __s32 pch_phub_write_gbe_mac_addr(__u32 offset_address,
+ __u8 data)
+{
+ __s32 retval = 0;
+
+ retval = pch_phub_gbe_serial_rom_conf();
+ retval |= pch_phub_write_serial_rom_val(offset_address, data);
+
+ return retval;
+}
+
+/** pch_phub_open - Implements the Initializing and opening of the Packet Hub
+ module.
+ * @inode: Contains the reference of the inode structure
+ * @file: Contains the reference of the file structure
+ */
+static __s32 pch_phub_open(struct inode *inode, struct file *file)
+{
+ __s32 ret;
+
+ spin_lock(&pch_phub_lock);
+ if (pch_phub_reg.pch_phub_opencount) {
+ ret = -EBUSY;
+ } else {
+ pch_phub_reg.pch_phub_opencount++;
+ ret = 0;
+ }
+ spin_unlock(&pch_phub_lock);
+
+ return ret;
+}
+/** pch_phub_read - Implements the read functionality of the Packet Hub module.
+ * @file: Contains the reference of the file structure
+ * @buf: Usermode buffer pointer
+ * @size: Usermode buffer size
+ * @pos: Contains the reference of the file structure
+ */
+
+static ssize_t pch_phub_read(struct file *file, char __user *buf, size_t size,
+ loff_t *pos)
+{
+ __u32 rom_signature = 0;
+ __u8 rom_length;
+ __s32 ret_value;
+ __u32 tmp;
+ __u8 data;
+ __u32 addr_offset = 0;
+
+ /*Get Rom signature*/
+ pch_phub_read_serial_rom(0x80, (__u8 *)&rom_signature);
+ pch_phub_read_serial_rom(0x81, (__u8 *)&tmp);
+ rom_signature |= (tmp & 0xff) << 8;
+ if (rom_signature == 0xAA55) {
+ pch_phub_read_serial_rom(0x82, &rom_length);
+ if (size > (rom_length * 512)+1)
+ return -ENOMEM;
+
+ for (addr_offset = 0;
+ addr_offset <= ((__u32)rom_length * 512);
+ addr_offset++) {
+ pch_phub_read_serial_rom(0x80 + addr_offset, &data);
+ ret_value = copy_to_user((void *)&buf[addr_offset],
+ (void *)&data, 1);
+ if (ret_value)
+ return -EFAULT;
+ }
+ } else {
+ return -ENOEXEC;
+ }
+
+ return rom_length * 512 + 1;
+}
+
+/** pch_phub_write - Implements the write functionality of the Packet Hub
+ * module.
+ * @file: Contains the reference of the file structure
+ * @buf: Usermode buffer pointer
+ * @size: Usermode buffer size
+ * @pos: Contains the reference of the file structure
+ */
+static ssize_t pch_phub_write(struct file *file, const char __user *buf,
+ size_t size, loff_t *pos)
+{
+ static __u8 data[PCH_PHUB_OROM_SIZE];
+ __s32 ret_value;
+ __u32 addr_offset = 0;
+
+ if (size > PCH_PHUB_OROM_SIZE)
+ size = PCH_PHUB_OROM_SIZE;
+
+ ret_value = copy_from_user(data, buf, size);
+ if (ret_value)
+ return -EFAULT;
+
+ for (addr_offset = 0; addr_offset < size; addr_offset++) {
+ ret_value = pch_phub_write_serial_rom(0x80 + addr_offset,
+ data[addr_offset]);
+ }
+
+ return size;
+}
+
+
+/** pch_phub_release - Implements the release functionality of the Packet Hub
+ * module.
+ * @inode: Contains the reference of the inode structure
+ * @file: Contains the reference of the file structure
+ */
+static __s32 pch_phub_release(struct inode *inode, struct file *file)
+{
+ spin_lock(&pch_phub_lock);
+
+ if (pch_phub_reg.pch_phub_opencount > 0)
+ pch_phub_reg.pch_phub_opencount--;
+ spin_unlock(&pch_phub_lock);
+
+ return 0;
+}
+
+/** pch_phub_ioctl - Implements the various ioctl functionalities of the Packet
+ * Hub module.
+ * @inode: Contains the reference of the inode structure
+ * @file: Contains the reference of the file structure
+ * @cmd: Contains the command value
+ * @arg: Contains the command argument value
+ */
+
+
+static long pch_phub_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ __s32 ret_value = 0;
+ struct pch_phub_reqt __user *p_pch_phub_reqt;
+ __u32 data;
+ __u32 mac_addr[2];
+ __s32 ret;
+ __u32 i;
+ void __user *varg = (void __user *)arg;
+
+ ret = mutex_trylock(&pch_phub_ioctl_mutex);
+ if (ret == 0)
+ goto return_ioctrl;/*Can't get mutex lock*/
+
+ if (pch_phub_reg.pch_phub_suspended == true) {
+ ret_value = -EPERM;
+ goto return_ioctrl;
+ }
+
+ p_pch_phub_reqt = (struct pch_phub_reqt *)varg;
+
+ if (ret_value)
+ goto return_ioctrl;
+
+ /* End of Access area check */
+
+
+ switch (cmd) {
+
+ case IOCTL_PHUB_READ_MAC_ADDR:
+ mac_addr[0] = 0;
+ mac_addr[1] = 0;
+ for (i = 0; i < 4; i++) {
+ pch_phub_read_gbe_mac_addr(i, (__u8 *)&data);
+ mac_addr[0] |= data << i*8;
+ }
+ for (; i < 6; i++) {
+ pch_phub_read_gbe_mac_addr(i, (__u8 *)&data);
+ mac_addr[1] |= data << (i-4)*8;
+ }
+
+ ret_value = copy_to_user((void *)&p_pch_phub_reqt->data,
+ (void *)mac_addr, sizeof(mac_addr));
+ if (ret_value) {
+ ret_value = -EFAULT;
+ break;
+ }
+ break;
+ case IOCTL_PHUB_WRITE_MAC_ADDR:
+ ret_value = get_user(mac_addr[0], &p_pch_phub_reqt->data[0]);
+ ret_value += get_user(mac_addr[1], &p_pch_phub_reqt->data[1]);
+ if (ret_value) {
+ ret_value = -EFAULT;
+ break;
+ }
+ for (i = 0; i < 4; i++) {
+ data = (mac_addr[0] & (0xff << 8*i))>>(8*i);
+ pch_phub_write_gbe_mac_addr(i, data);
+ }
+ for (; i < 6; i++) {
+ data = (mac_addr[1] & (0xff << 8*(i-4)))>>(8*(i-4));
+ pch_phub_write_gbe_mac_addr(i, data);
+ }
+ break;
+ default:
+ ret_value = -EINVAL;
+ break;
+ }
+return_ioctrl:
+ mutex_unlock(&pch_phub_ioctl_mutex);
+ return ret_value;
+}
+
+
+/** pch_phub_probe - Implements the probe functionality of the module.
+ * @pdev: Contains the reference of the pci_dev structure
+ * @id: Contains the reference of the pci_device_id structure
+ */
+static __s32 __devinit pch_phub_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+
+ char *DRIVER_NAME = "pch_phub";
+ __s32 ret;
+ __u32 rom_size;
+
+ pch_phub_major_no = (pch_phub_major_no < 0 || pch_phub_major_no > 254) ?
+ 0 : pch_phub_major_no;
+
+ ret = pci_enable_device(pdev);
+ if (ret) {
+ dev_dbg(&pdev->dev,
+ "\npch_phub_probe : pci_enable_device FAILED");
+ goto err_probe;
+ }
+ dev_dbg(&pdev->dev, "pch_phub_probe : "
+ "pci_enable_device returns %d\n", ret);
+
+ ret = pci_request_regions(pdev, DRIVER_NAME);
+ if (ret) {
+ dev_dbg(&pdev->dev,
+ "pch_phub_probe : pci_request_regions FAILED");
+ pci_disable_device(pdev);
+ goto err_probe;
+ }
+ dev_dbg(&pdev->dev, "pch_phub_probe : "
+ "pci_request_regions returns %d\n", ret);
+
+ pch_phub_reg.pch_phub_base_address = \
+ (void __iomem *)pci_iomap(pdev, 1, 0);
+
+ if (pch_phub_reg.pch_phub_base_address == 0) {
+ dev_dbg(&pdev->dev, "pch_phub_probe : pci_iomap FAILED");
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ ret = -ENOMEM;
+ goto err_probe;
+ }
+ dev_dbg(&pdev->dev, "pch_phub_probe : pci_iomap SUCCESS and value "
+ "in pch_phub_base_address variable is 0x%08x\n",
+ (__u32)pch_phub_reg.pch_phub_base_address);
+
+ pch_phub_reg.pch_phub_extrom_base_address =
+ (void __iomem *)pci_map_rom(pdev, &rom_size);
+ if (pch_phub_reg.pch_phub_extrom_base_address == 0) {
+ dev_dbg(&pdev->dev, "pch_phub_probe : pci_map_rom FAILED");
+ pci_iounmap(pdev, (void *)pch_phub_reg.pch_phub_base_address);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ ret = -ENOMEM;
+ goto err_probe;
+ }
+ dev_dbg(&pdev->dev, "pch_phub_probe : "
+ "pci_map_rom SUCCESS and value in "
+ "pch_phub_extrom_base_address variable is 0x%08x\n",
+ (__u32)pch_phub_reg.pch_phub_extrom_base_address);
+
+ if (pch_phub_major_no) {
+ pch_phub_dev_no = MKDEV(pch_phub_major_no, 0);
+ ret = register_chrdev_region(pch_phub_dev_no,
+ PCH_MINOR_NOS, DRIVER_NAME);
+ if (ret) {
+ dev_dbg(&pdev->dev, "pch_phub_probe : "
+ "register_chrdev_region FAILED");
+ pci_unmap_rom(pdev,
+ (void *)pch_phub_reg.pch_phub_extrom_base_address);
+ pci_iounmap(pdev,
+ (void *)pch_phub_reg.pch_phub_base_address);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ goto err_probe;
+ }
+ dev_dbg(&pdev->dev, "pch_phub_probe : "
+ "register_chrdev_region returns %d\n", ret);
+ } else {
+ ret = alloc_chrdev_region(&pch_phub_dev_no, 0,
+ PCH_MINOR_NOS, DRIVER_NAME);
+ if (ret) {
+ dev_dbg(&pdev->dev, "pch_phub_probe : "
+ "alloc_chrdev_region FAILED");
+ pci_unmap_rom(pdev,
+ (void *)pch_phub_reg.pch_phub_extrom_base_address);
+ pci_iounmap(pdev,
+ (void *)pch_phub_reg.pch_phub_base_address);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ goto err_probe;
+ }
+ dev_dbg(&pdev->dev, "pch_phub_probe : "
+ "alloc_chrdev_region returns %d\n", ret);
+ }
+
+ cdev_init(&pch_phub_dev, &pch_phub_fops);
+ dev_dbg(&pdev->dev,
+ "pch_phub_probe : cdev_init invoked successfully\n");
+
+ pch_phub_dev.owner = THIS_MODULE;
+ pch_phub_dev.ops = &pch_phub_fops;
+
+ ret = cdev_add(&pch_phub_dev, pch_phub_dev_no, PCH_MINOR_NOS);
+ if (ret) {
+ dev_dbg(&pdev->dev, "pch_phub_probe : cdev_add FAILED");
+ unregister_chrdev_region(pch_phub_dev_no, PCH_MINOR_NOS);
+ pci_unmap_rom(pdev,
+ (void *)pch_phub_reg.pch_phub_extrom_base_address);
+ pci_iounmap(pdev, (void *)pch_phub_reg.pch_phub_base_address);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ goto err_probe;
+ }
+ dev_dbg(&pdev->dev, "pch_phub_probe : cdev_add returns %d\n", ret);
+
+#ifdef PCH_CAN_PCLK_50MHZ
+ /*set the clock config reg if CAN clock is 50Mhz */
+ dev_dbg(&pdev->dev, "pch_phub_probe : invoking "
+ "pch_phub_read_modify_write_reg "
+ "to set CLKCFG reg for CAN clk 50Mhz\n");
+ pch_phub_read_modify_write_reg((__u32)CLKCFG_REG_OFFSET,
+ CLKCFG_CAN_50MHZ, CLKCFG_CANCLK_MASK);
+#endif
+ /* set the prefech value */
+ PCH_WRITE_REG(0x000ffffa, 0x14);
+ /* set the interrupt delay value */
+ PCH_WRITE_REG(0x25, 0x44);
+ return 0;
+
+err_probe:
+ dev_dbg(&pdev->dev, "pch_phub_probe returns %d\n", ret);
+ return ret;
+}
+
+/** pch_phub_remove - Implements the remove functionality of the module.
+ * @pdev: Contains the reference of the pci_dev structure
+ */
+static void __devexit pch_phub_remove(struct pci_dev *pdev)
+{
+
+ cdev_del(&pch_phub_dev);
+ dev_dbg(&pdev->dev,
+ "pch_phub_remove - cdev_del Invoked successfully\n");
+
+ unregister_chrdev_region(pch_phub_dev_no, PCH_MINOR_NOS);
+ dev_dbg(&pdev->dev, "pch_phub_remove - "
+ "unregister_chrdev_region Invoked successfully\n");
+
+ pci_unmap_rom(pdev, (void *)pch_phub_reg.pch_phub_extrom_base_address);
+
+ pci_iounmap(pdev, (void *)pch_phub_reg.pch_phub_base_address);
+
+ dev_dbg(&pdev->dev, "pch_phub_remove - "
+ "pci_iounmap Invoked successfully\n");
+
+ pci_release_regions(pdev);
+ dev_dbg(&pdev->dev, "pch_phub_remove - "
+ "pci_release_regions Invoked successfully\n");
+
+ pci_disable_device(pdev);
+ dev_dbg(&pdev->dev, "pch_phub_remove - "
+ "pci_disable_device Invoked successfully\n");
+
+}
+
+#ifdef CONFIG_PM
+
+/** pch_phub_suspend - Implements the suspend functionality of the module.
+ * @pdev: Contains the reference of the pci_dev structure
+ * @state: Contains the reference of the pm_message_t structure
+ */
+static __s32 pch_phub_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ __s32 ret;
+
+ pch_phub_reg.pch_phub_suspended = true;/* For blocking further IOCTLs */
+
+ pch_phub_save_reg_conf(pdev);
+ dev_dbg(&pdev->dev, "pch_phub_suspend - "
+ "pch_phub_save_reg_conf Invoked successfully\n");
+
+ ret = pci_save_state(pdev);
+ if (ret) {
+ dev_dbg(&pdev->dev,
+ " pch_phub_suspend -pci_save_state returns-%d\n", ret);
+ return ret;
+ }
+ dev_dbg(&pdev->dev,
+ "pch_phub_suspend - pci_save_state returns %d\n", ret);
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ dev_dbg(&pdev->dev, "pch_phub_suspend - "
+ "pci_enable_wake Invoked successfully\n");
+
+ pci_disable_device(pdev);
+ dev_dbg(&pdev->dev, "pch_phub_suspend - "
+ "pci_disable_device Invoked successfully\n");
+
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ dev_dbg(&pdev->dev, "pch_phub_suspend - "
+ "pci_set_power_state Invoked successfully "
+ "return = %d\n", 0);
+
+ return 0;
+}
+
+/** pch_phub_resume - Implements the resume functionality of the module.
+ * @pdev: Contains the reference of the pci_dev structure
+ */
+static __s32 pch_phub_resume(struct pci_dev *pdev)
+{
+
+ __s32 ret;
+
+ pci_set_power_state(pdev, PCI_D0);
+ dev_dbg(&pdev->dev, "pch_phub_resume - "
+ "pci_set_power_state Invoked successfully\n");
+
+ pci_restore_state(pdev);
+ dev_dbg(&pdev->dev, "pch_phub_resume - "
+ "pci_restore_state Invoked successfully\n");
+
+ ret = pci_enable_device(pdev);
+ if (ret) {
+ dev_dbg(&pdev->dev,
+ "pch_phub_resume-pci_enable_device failed ");
+ return ret;
+ }
+
+ dev_dbg(&pdev->dev, "pch_phub_resume - "
+ "pci_enable_device returns -%d\n", ret);
+
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ dev_dbg(&pdev->dev, "pch_phub_resume - "
+ "pci_enable_wake Invoked successfully\n");
+
+ pch_phub_restore_reg_conf(pdev);
+ dev_dbg(&pdev->dev, "pch_phub_resume - "
+ "pch_phub_restore_reg_conf Invoked successfully\n");
+
+ pch_phub_reg.pch_phub_suspended = false;
+
+ dev_dbg(&pdev->dev, "pch_phub_resume returns- %d\n", 0);
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+static struct pci_device_id pch_phub_pcidev_id[] = {
+
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH1_PHUB)},
+ {0,}
+};
+
+
+static struct pci_driver pch_phub_driver = {
+ .name = "pch_phub",
+ .id_table = pch_phub_pcidev_id,
+ .probe = pch_phub_probe,
+ .remove = __devexit_p(pch_phub_remove),
+#ifdef CONFIG_PM
+ .suspend = pch_phub_suspend,
+ .resume = pch_phub_resume
+#endif
+};
+
+/** pch_phub_pci_init - Implements the initialization functionality of
+ * the module.
+ */
+static __s32 __init pch_phub_pci_init(void)
+{
+ __s32 ret;
+ ret = pci_register_driver(&pch_phub_driver);
+
+ return ret;
+}
+
+/** pch_phub_pci_exit - Implements the exit functionality of the module.
+ */
+static void __exit pch_phub_pci_exit(void)
+{
+ pci_unregister_driver(&pch_phub_driver);
+
+}
+
+module_init(pch_phub_pci_init);
+module_exit(pch_phub_pci_exit);
+module_param(pch_phub_major_no, int, S_IRUSR | S_IWUSR);
+
+MODULE_DESCRIPTION("PCH PACKET HUB PCI Driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/char/pch_phub/pch_phub.h b/drivers/char/pch_phub/pch_phub.h
new file mode 100755
index 0000000..4859e2f
--- /dev/null
+++ b/drivers/char/pch_phub/pch_phub.h
@@ -0,0 +1,87 @@
+#ifndef __PCH_PHUB_H__
+#define __PCH_PHUB_H__
+/*!
+ * @file pch_phub.h
+ * @brief Provides all the interfaces pertaining to the Packet Hub 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) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * created:
+ * OKI SEMICONDUCTOR 04/14/2010
+ * modified:
+ *
+ */
+
+#define PHUB_IOCTL_MAGIC (0xf7)
+
+/*Outlines the read register function signature. */
+#define IOCTL_PHUB_READ_REG (_IOW(PHUB_IOCTL_MAGIC, 1, __u32))
+
+/*Outlines the write register function signature. */
+#define IOCTL_PHUB_WRITE_REG (_IOW(PHUB_IOCTL_MAGIC, 2, __u32))
+
+/*Outlines the read, modify and write register function signature. */
+#define IOCTL_PHUB_READ_MODIFY_WRITE_REG (_IOW(PHUB_IOCTL_MAGIC, 3,\
+ __u32))
+
+/*Outlines the read option rom function signature. */
+#define IOCTL_PHUB_READ_OROM (_IOW(PHUB_IOCTL_MAGIC, 4, __u32))
+
+/*Outlines the write option rom function signature. */
+#define IOCTL_PHUB_WRITE_OROM (_IOW(PHUB_IOCTL_MAGIC, 5, __u32))
+
+/*Outlines the read mac address function signature. */
+#define IOCTL_PHUB_READ_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 6, __u32))
+
+/*brief Outlines the write mac address function signature. */
+#define IOCTL_PHUB_WRITE_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 7, __u32))
+
+
+/* Registers address offset */
+#define PCH_PHUB_PHUB_ID_REG 0x0000
+#define PCH_PHUB_QUEUE_PRI_VAL_REG 0x0004
+#define PCH_PHUB_RC_QUEUE_MAXSIZE_REG 0x0008
+#define PCH_PHUB_BRI_QUEUE_MAXSIZE_REG 0x000C
+#define PCH_PHUB_COMP_RESP_TIMEOUT_REG 0x0010
+#define PCH_PHUB_BUS_SLAVE_CONTROL_REG 0x0014
+#define PCH_PHUB_DEADLOCK_AVOID_TYPE_REG 0x0018
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG0 0x0020
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG1 0x0024
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG2 0x0028
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG3 0x002C
+#define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE 0x0040
+#define CLKCFG_REG_OFFSET 0x500
+
+#define PCH_PHUB_OROM_SIZE 15361
+/**
+ * struct pch_phub_reqt - It is a structure used for perserving information
+ * related to the Packet Hub request.
+ * @addr_offset: specifies the register address offset
+ * @data: specifies the data
+ * @mask: specifies the mask
+ *
+ */
+struct pch_phub_reqt {
+ __u32 dev_id;
+ __u32 func_id;
+ __u32 data[2];
+};
+
+#endif
--
1.6.0.6

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/